avm2: Use `Gc` instead of `GcCell` in `VectorObject`

This commit is contained in:
Lord-McSweeney 2024-07-04 16:43:58 +03:00 committed by Lord-McSweeney
parent b1acb17806
commit 562be06fb1
2 changed files with 50 additions and 49 deletions

View File

@ -1391,7 +1391,7 @@ impl<'gc> Object<'gc> {
Self::ByteArrayObject(o) => WeakObject::ByteArrayObject(ByteArrayObjectWeak(Gc::downgrade(o.0))), Self::ByteArrayObject(o) => WeakObject::ByteArrayObject(ByteArrayObjectWeak(Gc::downgrade(o.0))),
Self::LoaderInfoObject(o) => WeakObject::LoaderInfoObject(LoaderInfoObjectWeak(GcCell::downgrade(o.0))), Self::LoaderInfoObject(o) => WeakObject::LoaderInfoObject(LoaderInfoObjectWeak(GcCell::downgrade(o.0))),
Self::ClassObject(o) => WeakObject::ClassObject(ClassObjectWeak(GcCell::downgrade(o.0))), Self::ClassObject(o) => WeakObject::ClassObject(ClassObjectWeak(GcCell::downgrade(o.0))),
Self::VectorObject(o) => WeakObject::VectorObject(VectorObjectWeak(GcCell::downgrade(o.0))), Self::VectorObject(o) => WeakObject::VectorObject(VectorObjectWeak(Gc::downgrade(o.0))),
Self::SoundObject(o) => WeakObject::SoundObject(SoundObjectWeak(GcCell::downgrade(o.0))), Self::SoundObject(o) => WeakObject::SoundObject(SoundObjectWeak(GcCell::downgrade(o.0))),
Self::SoundChannelObject(o) => WeakObject::SoundChannelObject(SoundChannelObjectWeak(GcCell::downgrade(o.0))), Self::SoundChannelObject(o) => WeakObject::SoundChannelObject(SoundChannelObjectWeak(GcCell::downgrade(o.0))),
Self::BitmapDataObject(o) => WeakObject::BitmapDataObject(BitmapDataObjectWeak(Gc::downgrade(o.0))), Self::BitmapDataObject(o) => WeakObject::BitmapDataObject(BitmapDataObjectWeak(Gc::downgrade(o.0))),

View File

@ -8,7 +8,8 @@ use crate::avm2::vector::VectorStorage;
use crate::avm2::Error; use crate::avm2::Error;
use crate::avm2::Multiname; use crate::avm2::Multiname;
use core::fmt; use core::fmt;
use gc_arena::{Collect, GcCell, GcWeakCell, Mutation}; use gc_arena::barrier::unlock;
use gc_arena::{lock::RefLock, Collect, Gc, GcWeak, Mutation};
use std::cell::{Ref, RefMut}; use std::cell::{Ref, RefMut};
/// A class instance allocator that allocates Vector objects. /// A class instance allocator that allocates Vector objects.
@ -16,18 +17,18 @@ pub fn vector_allocator<'gc>(
class: ClassObject<'gc>, class: ClassObject<'gc>,
activation: &mut Activation<'_, 'gc>, activation: &mut Activation<'_, 'gc>,
) -> Result<Object<'gc>, Error<'gc>> { ) -> Result<Object<'gc>, Error<'gc>> {
let base = ScriptObjectData::new(class); let base = ScriptObjectData::new(class).into();
let param_type = class let param_type = class
.inner_class_definition() .inner_class_definition()
.param() .param()
.ok_or("Cannot convert to unparametrized Vector")?; .ok_or("Cannot convert to unparametrized Vector")?;
Ok(VectorObject(GcCell::new( Ok(VectorObject(Gc::new(
activation.context.gc_context, activation.context.gc_context,
VectorObjectData { VectorObjectData {
base, base,
vector: VectorStorage::new(0, false, param_type, activation), vector: RefLock::new(VectorStorage::new(0, false, param_type, activation)),
}, },
)) ))
.into()) .into())
@ -36,16 +37,16 @@ pub fn vector_allocator<'gc>(
/// An Object which stores typed properties in vector storage /// An Object which stores typed properties in vector storage
#[derive(Collect, Clone, Copy)] #[derive(Collect, Clone, Copy)]
#[collect(no_drop)] #[collect(no_drop)]
pub struct VectorObject<'gc>(pub GcCell<'gc, VectorObjectData<'gc>>); pub struct VectorObject<'gc>(pub Gc<'gc, VectorObjectData<'gc>>);
#[derive(Collect, Clone, Copy, Debug)] #[derive(Collect, Clone, Copy, Debug)]
#[collect(no_drop)] #[collect(no_drop)]
pub struct VectorObjectWeak<'gc>(pub GcWeakCell<'gc, VectorObjectData<'gc>>); pub struct VectorObjectWeak<'gc>(pub GcWeak<'gc, VectorObjectData<'gc>>);
impl fmt::Debug for VectorObject<'_> { impl fmt::Debug for VectorObject<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("VectorObject") f.debug_struct("VectorObject")
.field("ptr", &self.0.as_ptr()) .field("ptr", &Gc::as_ptr(self.0))
.finish() .finish()
} }
} }
@ -54,10 +55,10 @@ impl fmt::Debug for VectorObject<'_> {
#[collect(no_drop)] #[collect(no_drop)]
pub struct VectorObjectData<'gc> { pub struct VectorObjectData<'gc> {
/// Base script object /// Base script object
base: ScriptObjectData<'gc>, base: RefLock<ScriptObjectData<'gc>>,
/// Vector-structured properties /// Vector-structured properties
vector: VectorStorage<'gc>, vector: RefLock<VectorStorage<'gc>>,
} }
impl<'gc> VectorObject<'gc> { impl<'gc> VectorObject<'gc> {
@ -71,11 +72,11 @@ impl<'gc> VectorObject<'gc> {
let applied_class = vector_class.parametrize(activation, value_type)?; let applied_class = vector_class.parametrize(activation, value_type)?;
let object: Object<'gc> = VectorObject(GcCell::new( let object: Object<'gc> = VectorObject(Gc::new(
activation.context.gc_context, activation.context.gc_context,
VectorObjectData { VectorObjectData {
base: ScriptObjectData::new(applied_class), base: ScriptObjectData::new(applied_class).into(),
vector, vector: RefLock::new(vector),
}, },
)) ))
.into(); .into();
@ -88,15 +89,15 @@ impl<'gc> VectorObject<'gc> {
impl<'gc> TObject<'gc> for VectorObject<'gc> { impl<'gc> TObject<'gc> for VectorObject<'gc> {
fn base(&self) -> Ref<ScriptObjectData<'gc>> { fn base(&self) -> Ref<ScriptObjectData<'gc>> {
Ref::map(self.0.read(), |read| &read.base) self.0.base.borrow()
} }
fn base_mut(&self, mc: &Mutation<'gc>) -> RefMut<ScriptObjectData<'gc>> { fn base_mut(&self, mc: &Mutation<'gc>) -> RefMut<ScriptObjectData<'gc>> {
RefMut::map(self.0.write(mc), |write| &mut write.base) unlock!(Gc::write(mc, self.0), VectorObjectData, base).borrow_mut()
} }
fn as_ptr(&self) -> *const ObjectPtr { fn as_ptr(&self) -> *const ObjectPtr {
self.0.as_ptr() as *const ObjectPtr Gc::as_ptr(self.0) as *const ObjectPtr
} }
fn get_property_local( fn get_property_local(
@ -104,21 +105,19 @@ impl<'gc> TObject<'gc> for VectorObject<'gc> {
name: &Multiname<'gc>, name: &Multiname<'gc>,
activation: &mut Activation<'_, 'gc>, activation: &mut Activation<'_, 'gc>,
) -> Result<Value<'gc>, Error<'gc>> { ) -> Result<Value<'gc>, Error<'gc>> {
let read = self.0.read();
if name.contains_public_namespace() { if name.contains_public_namespace() {
if let Some(name) = name.local_name() { if let Some(name) = name.local_name() {
if let Ok(index) = name.parse::<usize>() { if let Ok(index) = name.parse::<usize>() {
return read.vector.get(index, activation); return self.0.vector.borrow().get(index, activation);
} }
} }
} }
read.base.get_property_local(name, activation) self.0.base.borrow().get_property_local(name, activation)
} }
fn get_index_property(self, index: usize) -> Option<Value<'gc>> { fn get_index_property(self, index: usize) -> Option<Value<'gc>> {
self.0.read().vector.get_optional(index) self.0.vector.borrow().get_optional(index)
} }
fn set_property_local( fn set_property_local(
@ -127,19 +126,20 @@ impl<'gc> TObject<'gc> for VectorObject<'gc> {
value: Value<'gc>, value: Value<'gc>,
activation: &mut Activation<'_, 'gc>, activation: &mut Activation<'_, 'gc>,
) -> Result<(), Error<'gc>> { ) -> Result<(), Error<'gc>> {
let mc = activation.context.gc_context;
if name.contains_public_namespace() { if name.contains_public_namespace() {
if let Some(name) = name.local_name() { if let Some(name) = name.local_name() {
if let Ok(index) = name.parse::<usize>() { if let Ok(index) = name.parse::<usize>() {
let type_of = self.0.read().vector.value_type_for_coercion(activation); let type_of = self.0.vector.borrow().value_type_for_coercion(activation);
let value = match value.coerce_to_type(activation, type_of)? { let value = match value.coerce_to_type(activation, type_of)? {
Value::Undefined => self.0.read().vector.default(activation), Value::Undefined => self.0.vector.borrow().default(activation),
Value::Null => self.0.read().vector.default(activation), Value::Null => self.0.vector.borrow().default(activation),
v => v, v => v,
}; };
self.0 unlock!(Gc::write(mc, self.0), VectorObjectData, vector)
.write(activation.context.gc_context) .borrow_mut()
.vector
.set(index, value, activation)?; .set(index, value, activation)?;
return Ok(()); return Ok(());
@ -147,9 +147,9 @@ impl<'gc> TObject<'gc> for VectorObject<'gc> {
} }
} }
let mut write = self.0.write(activation.context.gc_context); unlock!(Gc::write(mc, self.0), VectorObjectData, base)
.borrow_mut()
write.base.set_property_local(name, value, activation) .set_property_local(name, value, activation)
} }
fn init_property_local( fn init_property_local(
@ -158,19 +158,20 @@ impl<'gc> TObject<'gc> for VectorObject<'gc> {
value: Value<'gc>, value: Value<'gc>,
activation: &mut Activation<'_, 'gc>, activation: &mut Activation<'_, 'gc>,
) -> Result<(), Error<'gc>> { ) -> Result<(), Error<'gc>> {
let mc = activation.context.gc_context;
if name.contains_public_namespace() { if name.contains_public_namespace() {
if let Some(name) = name.local_name() { if let Some(name) = name.local_name() {
if let Ok(index) = name.parse::<usize>() { if let Ok(index) = name.parse::<usize>() {
let type_of = self.0.read().vector.value_type_for_coercion(activation); let type_of = self.0.vector.borrow().value_type_for_coercion(activation);
let value = match value.coerce_to_type(activation, type_of)? { let value = match value.coerce_to_type(activation, type_of)? {
Value::Undefined => self.0.read().vector.default(activation), Value::Undefined => self.0.vector.borrow().default(activation),
Value::Null => self.0.read().vector.default(activation), Value::Null => self.0.vector.borrow().default(activation),
v => v, v => v,
}; };
self.0 unlock!(Gc::write(mc, self.0), VectorObjectData, vector)
.write(activation.context.gc_context) .borrow_mut()
.vector
.set(index, value, activation)?; .set(index, value, activation)?;
return Ok(()); return Ok(());
@ -178,9 +179,9 @@ impl<'gc> TObject<'gc> for VectorObject<'gc> {
} }
} }
let mut write = self.0.write(activation.context.gc_context); unlock!(Gc::write(mc, self.0), VectorObjectData, base)
.borrow_mut()
write.base.init_property_local(name, value, activation) .init_property_local(name, value, activation)
} }
fn delete_property_local( fn delete_property_local(
@ -188,6 +189,8 @@ impl<'gc> TObject<'gc> for VectorObject<'gc> {
activation: &mut Activation<'_, 'gc>, activation: &mut Activation<'_, 'gc>,
name: &Multiname<'gc>, name: &Multiname<'gc>,
) -> Result<bool, Error<'gc>> { ) -> Result<bool, Error<'gc>> {
let mc = activation.context.gc_context;
if name.contains_public_namespace() if name.contains_public_namespace()
&& name.local_name().is_some() && name.local_name().is_some()
&& name.local_name().unwrap().parse::<usize>().is_ok() && name.local_name().unwrap().parse::<usize>().is_ok()
@ -195,10 +198,8 @@ impl<'gc> TObject<'gc> for VectorObject<'gc> {
return Ok(true); return Ok(true);
} }
Ok(self Ok(unlock!(Gc::write(mc, self.0), VectorObjectData, base)
.0 .borrow_mut()
.write(activation.context.gc_context)
.base
.delete_property_local(name)) .delete_property_local(name))
} }
@ -206,12 +207,12 @@ impl<'gc> TObject<'gc> for VectorObject<'gc> {
if name.contains_public_namespace() { if name.contains_public_namespace() {
if let Some(name) = name.local_name() { if let Some(name) = name.local_name() {
if let Ok(index) = name.parse::<usize>() { if let Ok(index) = name.parse::<usize>() {
return self.0.read().vector.is_in_range(index); return self.0.vector.borrow().is_in_range(index);
} }
} }
} }
self.0.read().base.has_own_property(name) self.0.base.borrow().has_own_property(name)
} }
fn get_next_enumerant( fn get_next_enumerant(
@ -219,7 +220,7 @@ impl<'gc> TObject<'gc> for VectorObject<'gc> {
last_index: u32, last_index: u32,
_activation: &mut Activation<'_, 'gc>, _activation: &mut Activation<'_, 'gc>,
) -> Result<Option<u32>, Error<'gc>> { ) -> Result<Option<u32>, Error<'gc>> {
if last_index < self.0.read().vector.length() as u32 { if last_index < self.0.vector.borrow().length() as u32 {
Ok(Some(last_index.saturating_add(1))) Ok(Some(last_index.saturating_add(1)))
} else { } else {
Ok(None) Ok(None)
@ -231,7 +232,7 @@ impl<'gc> TObject<'gc> for VectorObject<'gc> {
index: u32, index: u32,
_activation: &mut Activation<'_, 'gc>, _activation: &mut Activation<'_, 'gc>,
) -> Result<Value<'gc>, Error<'gc>> { ) -> Result<Value<'gc>, Error<'gc>> {
if self.0.read().vector.length() as u32 >= index { if self.0.vector.borrow().length() as u32 >= index {
Ok(index Ok(index
.checked_sub(1) .checked_sub(1)
.map(|index| index.into()) .map(|index| index.into())
@ -246,10 +247,10 @@ impl<'gc> TObject<'gc> for VectorObject<'gc> {
} }
fn as_vector_storage(&self) -> Option<Ref<VectorStorage<'gc>>> { fn as_vector_storage(&self) -> Option<Ref<VectorStorage<'gc>>> {
Some(Ref::map(self.0.read(), |vod| &vod.vector)) Some(self.0.vector.borrow())
} }
fn as_vector_storage_mut(&self, mc: &Mutation<'gc>) -> Option<RefMut<VectorStorage<'gc>>> { fn as_vector_storage_mut(&self, mc: &Mutation<'gc>) -> Option<RefMut<VectorStorage<'gc>>> {
Some(RefMut::map(self.0.write(mc), |vod| &mut vod.vector)) Some(unlock!(Gc::write(mc, self.0), VectorObjectData, vector).borrow_mut())
} }
} }