From 3d80fc16c442daf3f9907444d57e9ab07f7072de Mon Sep 17 00:00:00 2001 From: Lord-McSweeney Date: Thu, 4 Jul 2024 13:00:19 +0300 Subject: [PATCH] avm2: Use `Gc` instead of `GcCell` in `QNameObject` and `ErrorObject` --- core/src/avm2/object.rs | 4 +- core/src/avm2/object/error_object.rs | 38 +++++++++-------- core/src/avm2/object/qname_object.rs | 63 +++++++++++++++------------- 3 files changed, 56 insertions(+), 49 deletions(-) diff --git a/core/src/avm2/object.rs b/core/src/avm2/object.rs index 30da03cdc..97d52aa75 100644 --- a/core/src/avm2/object.rs +++ b/core/src/avm2/object.rs @@ -1397,10 +1397,10 @@ impl<'gc> Object<'gc> { Self::BitmapDataObject(o) => WeakObject::BitmapDataObject(BitmapDataObjectWeak(Gc::downgrade(o.0))), Self::DateObject(o) => WeakObject::DateObject(DateObjectWeak(Gc::downgrade(o.0))), Self::DictionaryObject(o) => WeakObject::DictionaryObject(DictionaryObjectWeak(Gc::downgrade(o.0))), - Self::QNameObject(o) => WeakObject::QNameObject(QNameObjectWeak(GcCell::downgrade(o.0))), + Self::QNameObject(o) => WeakObject::QNameObject(QNameObjectWeak(Gc::downgrade(o.0))), Self::TextFormatObject(o) => WeakObject::TextFormatObject(TextFormatObjectWeak(Gc::downgrade(o.0))), Self::ProxyObject(o) => WeakObject::ProxyObject(ProxyObjectWeak(Gc::downgrade(o.0))), - Self::ErrorObject(o) => WeakObject::ErrorObject(ErrorObjectWeak(GcCell::downgrade(o.0))), + Self::ErrorObject(o) => WeakObject::ErrorObject(ErrorObjectWeak(Gc::downgrade(o.0))), Self::Stage3DObject(o) => WeakObject::Stage3DObject(Stage3DObjectWeak(Gc::downgrade(o.0))), Self::Context3DObject(o) => WeakObject::Context3DObject(Context3DObjectWeak(Gc::downgrade(o.0))), Self::IndexBuffer3DObject(o) => WeakObject::IndexBuffer3DObject(IndexBuffer3DObjectWeak(Gc::downgrade(o.0))), diff --git a/core/src/avm2/object/error_object.rs b/core/src/avm2/object/error_object.rs index f49e78242..bbd1e02d5 100644 --- a/core/src/avm2/object/error_object.rs +++ b/core/src/avm2/object/error_object.rs @@ -8,7 +8,8 @@ use crate::avm2::value::Value; use crate::avm2::Error; use crate::string::WString; 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::fmt::Debug; use tracing::{enabled, Level}; @@ -18,15 +19,17 @@ pub fn error_allocator<'gc>( class: ClassObject<'gc>, activation: &mut Activation<'_, 'gc>, ) -> Result, Error<'gc>> { - let base = ScriptObjectData::new(class); + let base = ScriptObjectData::new(class).into(); - Ok(ErrorObject(GcCell::new( + let call_stack = (enabled!(Level::INFO) || cfg!(feature = "avm_debug")) + .then(|| activation.avm2().call_stack().read().clone()) + .unwrap_or_default(); + + Ok(ErrorObject(Gc::new( activation.context.gc_context, ErrorObjectData { base, - call_stack: (enabled!(Level::INFO) || cfg!(feature = "avm_debug")) - .then(|| activation.avm2().call_stack().read().clone()) - .unwrap_or_default(), + call_stack: RefLock::new(call_stack), }, )) .into()) @@ -34,17 +37,17 @@ pub fn error_allocator<'gc>( #[derive(Clone, Collect, Copy)] #[collect(no_drop)] -pub struct ErrorObject<'gc>(pub GcCell<'gc, ErrorObjectData<'gc>>); +pub struct ErrorObject<'gc>(pub Gc<'gc, ErrorObjectData<'gc>>); #[derive(Clone, Collect, Copy, Debug)] #[collect(no_drop)] -pub struct ErrorObjectWeak<'gc>(pub GcWeakCell<'gc, ErrorObjectData<'gc>>); +pub struct ErrorObjectWeak<'gc>(pub GcWeak<'gc, ErrorObjectData<'gc>>); impl fmt::Debug for ErrorObject<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("ErrorObject") .field("class", &self.debug_class_name()) - .field("ptr", &self.0.as_ptr()) + .field("ptr", &Gc::as_ptr(self.0)) .finish() } } @@ -53,9 +56,9 @@ impl fmt::Debug for ErrorObject<'_> { #[collect(no_drop)] pub struct ErrorObjectData<'gc> { /// Base script object - base: ScriptObjectData<'gc>, + base: RefLock>, - call_stack: CallStack<'gc>, + call_stack: RefLock>, } impl<'gc> ErrorObject<'gc> { @@ -105,28 +108,29 @@ impl<'gc> ErrorObject<'gc> { } pub fn call_stack(&self) -> Ref> { - Ref::map(self.0.read(), |r| &r.call_stack) + self.0.call_stack.borrow() } fn debug_class_name(&self) -> Box { self.0 - .try_read() - .map(|obj| obj.base.instance_class().debug_name()) + .base + .try_borrow() + .map(|base| base.instance_class().debug_name()) .unwrap_or_else(|err| Box::new(err)) } } impl<'gc> TObject<'gc> for ErrorObject<'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), ErrorObjectData, 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 value_of(&self, _mc: &Mutation<'gc>) -> Result, Error<'gc>> { diff --git a/core/src/avm2/object/qname_object.rs b/core/src/avm2/object/qname_object.rs index 2648928df..b9737c5d0 100644 --- a/core/src/avm2/object/qname_object.rs +++ b/core/src/avm2/object/qname_object.rs @@ -9,7 +9,8 @@ use crate::avm2::Error; use crate::avm2::Multiname; use crate::avm2::Namespace; 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}; /// A class instance allocator that allocates QName objects. @@ -17,13 +18,13 @@ pub fn q_name_allocator<'gc>( class: ClassObject<'gc>, activation: &mut Activation<'_, 'gc>, ) -> Result, Error<'gc>> { - let base = ScriptObjectData::new(class); + let base = ScriptObjectData::new(class).into(); - Ok(QNameObject(GcCell::new( + Ok(QNameObject(Gc::new( activation.context.gc_context, QNameObjectData { base, - name: Multiname::any(activation.context.gc_context), + name: RefLock::new(Multiname::any(activation.context.gc_context)), }, )) .into()) @@ -32,16 +33,16 @@ pub fn q_name_allocator<'gc>( /// An Object which represents a boxed QName. #[derive(Collect, Clone, Copy)] #[collect(no_drop)] -pub struct QNameObject<'gc>(pub GcCell<'gc, QNameObjectData<'gc>>); +pub struct QNameObject<'gc>(pub Gc<'gc, QNameObjectData<'gc>>); #[derive(Collect, Clone, Copy, Debug)] #[collect(no_drop)] -pub struct QNameObjectWeak<'gc>(pub GcWeakCell<'gc, QNameObjectData<'gc>>); +pub struct QNameObjectWeak<'gc>(pub GcWeak<'gc, QNameObjectData<'gc>>); impl fmt::Debug for QNameObject<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("QNameObject") - .field("ptr", &self.0.as_ptr()) + .field("ptr", &Gc::as_ptr(self.0)) .finish() } } @@ -50,10 +51,10 @@ impl fmt::Debug for QNameObject<'_> { #[collect(no_drop)] pub struct QNameObjectData<'gc> { /// All normal script data. - base: ScriptObjectData<'gc>, + base: RefLock>, /// The Multiname this object is associated with. - name: Multiname<'gc>, + name: RefLock>, } impl<'gc> QNameObject<'gc> { @@ -63,11 +64,14 @@ impl<'gc> QNameObject<'gc> { name: Multiname<'gc>, ) -> Result, Error<'gc>> { let class = activation.avm2().classes().qname; - let base = ScriptObjectData::new(class); + let base = ScriptObjectData::new(class).into(); - let this: Object<'gc> = QNameObject(GcCell::new( + let this: Object<'gc> = QNameObject(Gc::new( activation.context.gc_context, - QNameObjectData { base, name }, + QNameObjectData { + base, + name: RefLock::new(name), + }, )) .into(); this.install_instance_slots(activation.context.gc_context); @@ -76,21 +80,19 @@ impl<'gc> QNameObject<'gc> { } pub fn name(&self) -> Ref> { - let read = self.0.read(); - - Ref::map(read, |r| &r.name) + self.0.name.borrow() } pub fn set_namespace(&self, mc: &Mutation<'gc>, namespace: Namespace<'gc>) { - let mut write = self.0.write(mc); + let mut write_name = unlock!(Gc::write(mc, self.0), QNameObjectData, name).borrow_mut(); - write.name.set_single_namespace(namespace); + write_name.set_single_namespace(namespace); } pub fn set_local_name(&self, mc: &Mutation<'gc>, local: AvmString<'gc>) { - let mut write = self.0.write(mc); + let mut write_name = unlock!(Gc::write(mc, self.0), QNameObjectData, name).borrow_mut(); - write.name.set_local_name(local); + write_name.set_local_name(local); } pub fn local_name(&self) -> AvmString<'gc> { @@ -100,22 +102,21 @@ impl<'gc> QNameObject<'gc> { } pub fn set_is_qname(&self, mc: &Mutation<'gc>, is_qname: bool) { - let mut write = self.0.write(mc); + let mut write_name = unlock!(Gc::write(mc, self.0), QNameObjectData, name).borrow_mut(); - write.name.set_is_qname(is_qname); + write_name.set_is_qname(is_qname); } pub fn uri(&self) -> Option> { - let read = self.0.read(); + let name = self.0.name.borrow(); - if read.name.is_any_namespace() { + if name.is_any_namespace() { None - } else if read.name.namespace_set().len() > 1 { + } else if name.namespace_set().len() > 1 { Some("".into()) } else { Some( - read.name - .namespace_set() + name.namespace_set() .first() .expect("Malformed multiname") .as_uri(), @@ -124,21 +125,23 @@ impl<'gc> QNameObject<'gc> { } pub fn init_name(self, mc: &Mutation<'gc>, name: Multiname<'gc>) { - self.0.write(mc).name = name; + let mut write_name = unlock!(Gc::write(mc, self.0), QNameObjectData, name).borrow_mut(); + + *write_name = name; } } impl<'gc> TObject<'gc> for QNameObject<'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), QNameObjectData, 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 value_of(&self, _mc: &Mutation<'gc>) -> Result, Error<'gc>> {