diff --git a/core/src/avm2/bytearray.rs b/core/src/avm2/bytearray.rs index 3f10a01c8..79045ab40 100644 --- a/core/src/avm2/bytearray.rs +++ b/core/src/avm2/bytearray.rs @@ -83,8 +83,7 @@ pub enum ObjectEncoding { Amf3 = 3, } -#[derive(Clone, Collect, Debug)] -#[collect(no_drop)] +#[derive(Clone, Debug)] pub struct ByteArrayStorage { /// Underlying ByteArray bytes: Vec, diff --git a/core/src/avm2/object.rs b/core/src/avm2/object.rs index 317143893..b0e9b3a67 100644 --- a/core/src/avm2/object.rs +++ b/core/src/avm2/object.rs @@ -1388,7 +1388,7 @@ impl<'gc> Object<'gc> { Self::XmlObject(o) => WeakObject::XmlObject(XmlObjectWeak(GcCell::downgrade(o.0))), Self::XmlListObject(o) => WeakObject::XmlListObject(XmlListObjectWeak(GcCell::downgrade(o.0))), Self::RegExpObject(o) => WeakObject::RegExpObject(RegExpObjectWeak(GcCell::downgrade(o.0))), - Self::ByteArrayObject(o) => WeakObject::ByteArrayObject(ByteArrayObjectWeak(GcCell::downgrade(o.0))), + Self::ByteArrayObject(o) => WeakObject::ByteArrayObject(ByteArrayObjectWeak(Gc::downgrade(o.0))), Self::LoaderInfoObject(o) => WeakObject::LoaderInfoObject(LoaderInfoObjectWeak(GcCell::downgrade(o.0))), Self::ClassObject(o) => WeakObject::ClassObject(ClassObjectWeak(GcCell::downgrade(o.0))), Self::VectorObject(o) => WeakObject::VectorObject(VectorObjectWeak(GcCell::downgrade(o.0))), diff --git a/core/src/avm2/object/bytearray_object.rs b/core/src/avm2/object/bytearray_object.rs index 0d4e0c766..faf412018 100644 --- a/core/src/avm2/object/bytearray_object.rs +++ b/core/src/avm2/object/bytearray_object.rs @@ -7,8 +7,9 @@ use crate::avm2::Error; use crate::avm2::Multiname; use crate::character::Character; use core::fmt; -use gc_arena::{Collect, GcCell, GcWeakCell, Mutation}; -use std::cell::{Ref, RefMut}; +use gc_arena::barrier::unlock; +use gc_arena::{lock::RefLock, Collect, Gc, GcWeak, Mutation}; +use std::cell::{Ref, RefCell, RefMut}; /// A class instance allocator that allocates ByteArray objects. pub fn byte_array_allocator<'gc>( @@ -38,27 +39,30 @@ pub fn byte_array_allocator<'gc>( unreachable!("A ByteArray subclass should have ByteArray in superclass chain") }); - let base = ScriptObjectData::new(class); + let base = ScriptObjectData::new(class).into(); - Ok(ByteArrayObject(GcCell::new( + Ok(ByteArrayObject(Gc::new( activation.context.gc_context, - ByteArrayObjectData { base, storage }, + ByteArrayObjectData { + base, + storage: RefCell::new(storage), + }, )) .into()) } #[derive(Clone, Collect, Copy)] #[collect(no_drop)] -pub struct ByteArrayObject<'gc>(pub GcCell<'gc, ByteArrayObjectData<'gc>>); +pub struct ByteArrayObject<'gc>(pub Gc<'gc, ByteArrayObjectData<'gc>>); #[derive(Clone, Collect, Copy, Debug)] #[collect(no_drop)] -pub struct ByteArrayObjectWeak<'gc>(pub GcWeakCell<'gc, ByteArrayObjectData<'gc>>); +pub struct ByteArrayObjectWeak<'gc>(pub GcWeak<'gc, ByteArrayObjectData<'gc>>); impl fmt::Debug for ByteArrayObject<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("ByteArrayObject") - .field("ptr", &self.0.as_ptr()) + .field("ptr", &Gc::as_ptr(self.0)) .finish() } } @@ -67,9 +71,9 @@ impl fmt::Debug for ByteArrayObject<'_> { #[collect(no_drop)] pub struct ByteArrayObjectData<'gc> { /// Base script object - base: ScriptObjectData<'gc>, + base: RefLock>, - storage: ByteArrayStorage, + storage: RefCell, } impl<'gc> ByteArrayObject<'gc> { @@ -78,13 +82,13 @@ impl<'gc> ByteArrayObject<'gc> { bytes: ByteArrayStorage, ) -> Result, Error<'gc>> { let class = activation.avm2().classes().bytearray; - let base = ScriptObjectData::new(class); + let base = ScriptObjectData::new(class).into(); - let instance: Object<'gc> = ByteArrayObject(GcCell::new( + let instance: Object<'gc> = ByteArrayObject(Gc::new( activation.context.gc_context, ByteArrayObjectData { base, - storage: bytes, + storage: RefCell::new(bytes), }, )) .into(); @@ -96,21 +100,21 @@ impl<'gc> ByteArrayObject<'gc> { } pub fn storage(&self) -> Ref { - Ref::map(self.0.read(), |d| &d.storage) + self.0.storage.borrow() } } impl<'gc> TObject<'gc> for ByteArrayObject<'gc> { fn base(&self) -> Ref> { - Ref::map(self.0.read(), |read| &read.base) + self.0.base.borrow() } fn base_mut(&self, mc: &Mutation<'gc>) -> RefMut> { - RefMut::map(self.0.write(mc), |write| &mut write.base) + unlock!(Gc::write(mc, self.0), ByteArrayObjectData, base).borrow_mut() } 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( @@ -118,8 +122,6 @@ impl<'gc> TObject<'gc> for ByteArrayObject<'gc> { name: &Multiname<'gc>, activation: &mut Activation<'_, 'gc>, ) -> Result, Error<'gc>> { - let read = self.0.read(); - if name.contains_public_namespace() { if let Some(name) = name.local_name() { if let Ok(index) = name.parse::() { @@ -128,15 +130,15 @@ impl<'gc> TObject<'gc> for ByteArrayObject<'gc> { } } - read.base.get_property_local(name, activation) + self.0.base.borrow().get_property_local(name, activation) } fn get_index_property(self, index: usize) -> Option> { - let read = self.0.read(); - // ByteArrays never forward to base even for out-of-bounds access. Some( - read.storage + self.0 + .storage + .borrow() .get(index) .map_or(Value::Undefined, |val| Value::Integer(val as i32)), ) @@ -148,13 +150,12 @@ impl<'gc> TObject<'gc> for ByteArrayObject<'gc> { value: Value<'gc>, activation: &mut Activation<'_, 'gc>, ) -> Result<(), Error<'gc>> { - let mut write = self.0.write(activation.context.gc_context); - if name.contains_public_namespace() { if let Some(name) = name.local_name() { if let Ok(index) = name.parse::() { - write + self.0 .storage + .borrow_mut() .set(index, value.coerce_to_u32(activation)? as u8); return Ok(()); @@ -162,7 +163,13 @@ impl<'gc> TObject<'gc> for ByteArrayObject<'gc> { } } - write.base.set_property_local(name, value, activation) + unlock!( + Gc::write(activation.context.gc_context, self.0), + ByteArrayObjectData, + base + ) + .borrow_mut() + .set_property_local(name, value, activation) } fn init_property_local( @@ -171,13 +178,12 @@ impl<'gc> TObject<'gc> for ByteArrayObject<'gc> { value: Value<'gc>, activation: &mut Activation<'_, 'gc>, ) -> Result<(), Error<'gc>> { - let mut write = self.0.write(activation.context.gc_context); - if name.contains_public_namespace() { if let Some(name) = name.local_name() { if let Ok(index) = name.parse::() { - write + self.0 .storage + .borrow_mut() .set(index, value.coerce_to_u32(activation)? as u8); return Ok(()); @@ -185,7 +191,13 @@ impl<'gc> TObject<'gc> for ByteArrayObject<'gc> { } } - write.base.init_property_local(name, value, activation) + unlock!( + Gc::write(activation.context.gc_context, self.0), + ByteArrayObjectData, + base + ) + .borrow_mut() + .init_property_local(name, value, activation) } fn delete_property_local( @@ -196,32 +208,31 @@ impl<'gc> TObject<'gc> for ByteArrayObject<'gc> { if name.contains_public_namespace() { if let Some(name) = name.local_name() { if let Ok(index) = name.parse::() { - self.0 - .write(activation.context.gc_context) - .storage - .delete(index); + self.0.storage.borrow_mut().delete(index); return Ok(true); } } } - Ok(self - .0 - .write(activation.context.gc_context) - .base - .delete_property_local(name)) + Ok(unlock!( + Gc::write(activation.context.gc_context, self.0), + ByteArrayObjectData, + base + ) + .borrow_mut() + .delete_property_local(name)) } fn has_own_property(self, name: &Multiname<'gc>) -> bool { if name.contains_public_namespace() { if let Some(name) = name.local_name() { if let Ok(index) = name.parse::() { - return self.0.read().storage.get(index).is_some(); + return self.0.storage.borrow().get(index).is_some(); } } } - self.0.read().base.has_own_property(name) + self.0.base.borrow().has_own_property(name) } fn value_of(&self, _mc: &Mutation<'gc>) -> Result, Error<'gc>> { @@ -229,11 +240,11 @@ impl<'gc> TObject<'gc> for ByteArrayObject<'gc> { } fn as_bytearray(&self) -> Option> { - Some(Ref::map(self.0.read(), |d| &d.storage)) + Some(self.0.storage.borrow()) } - fn as_bytearray_mut(&self, mc: &Mutation<'gc>) -> Option> { - Some(RefMut::map(self.0.write(mc), |d| &mut d.storage)) + fn as_bytearray_mut(&self, _mc: &Mutation<'gc>) -> Option> { + Some(self.0.storage.borrow_mut()) } fn as_bytearray_object(&self) -> Option> {