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::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))),
Self::VectorObject(o) => WeakObject::VectorObject(VectorObjectWeak(Gc::downgrade(o.0))),
Self::SoundObject(o) => WeakObject::SoundObject(SoundObjectWeak(GcCell::downgrade(o.0))),
Self::SoundChannelObject(o) => WeakObject::SoundChannelObject(SoundChannelObjectWeak(GcCell::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::Multiname;
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 Vector objects.
@ -16,18 +17,18 @@ pub fn vector_allocator<'gc>(
class: ClassObject<'gc>,
activation: &mut Activation<'_, 'gc>,
) -> Result<Object<'gc>, Error<'gc>> {
let base = ScriptObjectData::new(class);
let base = ScriptObjectData::new(class).into();
let param_type = class
.inner_class_definition()
.param()
.ok_or("Cannot convert to unparametrized Vector")?;
Ok(VectorObject(GcCell::new(
Ok(VectorObject(Gc::new(
activation.context.gc_context,
VectorObjectData {
base,
vector: VectorStorage::new(0, false, param_type, activation),
vector: RefLock::new(VectorStorage::new(0, false, param_type, activation)),
},
))
.into())
@ -36,16 +37,16 @@ pub fn vector_allocator<'gc>(
/// An Object which stores typed properties in vector storage
#[derive(Collect, Clone, Copy)]
#[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)]
#[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<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("VectorObject")
.field("ptr", &self.0.as_ptr())
.field("ptr", &Gc::as_ptr(self.0))
.finish()
}
}
@ -54,10 +55,10 @@ impl fmt::Debug for VectorObject<'_> {
#[collect(no_drop)]
pub struct VectorObjectData<'gc> {
/// Base script object
base: ScriptObjectData<'gc>,
base: RefLock<ScriptObjectData<'gc>>,
/// Vector-structured properties
vector: VectorStorage<'gc>,
vector: RefLock<VectorStorage<'gc>>,
}
impl<'gc> VectorObject<'gc> {
@ -71,11 +72,11 @@ impl<'gc> VectorObject<'gc> {
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,
VectorObjectData {
base: ScriptObjectData::new(applied_class),
vector,
base: ScriptObjectData::new(applied_class).into(),
vector: RefLock::new(vector),
},
))
.into();
@ -88,15 +89,15 @@ impl<'gc> VectorObject<'gc> {
impl<'gc> TObject<'gc> for VectorObject<'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>> {
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 {
self.0.as_ptr() as *const ObjectPtr
Gc::as_ptr(self.0) as *const ObjectPtr
}
fn get_property_local(
@ -104,21 +105,19 @@ impl<'gc> TObject<'gc> for VectorObject<'gc> {
name: &Multiname<'gc>,
activation: &mut Activation<'_, 'gc>,
) -> Result<Value<'gc>, 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::<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>> {
self.0.read().vector.get_optional(index)
self.0.vector.borrow().get_optional(index)
}
fn set_property_local(
@ -127,19 +126,20 @@ impl<'gc> TObject<'gc> for VectorObject<'gc> {
value: Value<'gc>,
activation: &mut Activation<'_, 'gc>,
) -> Result<(), Error<'gc>> {
let mc = activation.context.gc_context;
if name.contains_public_namespace() {
if let Some(name) = name.local_name() {
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)? {
Value::Undefined => self.0.read().vector.default(activation),
Value::Null => self.0.read().vector.default(activation),
Value::Undefined => self.0.vector.borrow().default(activation),
Value::Null => self.0.vector.borrow().default(activation),
v => v,
};
self.0
.write(activation.context.gc_context)
.vector
unlock!(Gc::write(mc, self.0), VectorObjectData, vector)
.borrow_mut()
.set(index, value, activation)?;
return Ok(());
@ -147,9 +147,9 @@ impl<'gc> TObject<'gc> for VectorObject<'gc> {
}
}
let mut write = self.0.write(activation.context.gc_context);
write.base.set_property_local(name, value, activation)
unlock!(Gc::write(mc, self.0), VectorObjectData, base)
.borrow_mut()
.set_property_local(name, value, activation)
}
fn init_property_local(
@ -158,19 +158,20 @@ impl<'gc> TObject<'gc> for VectorObject<'gc> {
value: Value<'gc>,
activation: &mut Activation<'_, 'gc>,
) -> Result<(), Error<'gc>> {
let mc = activation.context.gc_context;
if name.contains_public_namespace() {
if let Some(name) = name.local_name() {
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)? {
Value::Undefined => self.0.read().vector.default(activation),
Value::Null => self.0.read().vector.default(activation),
Value::Undefined => self.0.vector.borrow().default(activation),
Value::Null => self.0.vector.borrow().default(activation),
v => v,
};
self.0
.write(activation.context.gc_context)
.vector
unlock!(Gc::write(mc, self.0), VectorObjectData, vector)
.borrow_mut()
.set(index, value, activation)?;
return Ok(());
@ -178,9 +179,9 @@ impl<'gc> TObject<'gc> for VectorObject<'gc> {
}
}
let mut write = self.0.write(activation.context.gc_context);
write.base.init_property_local(name, value, activation)
unlock!(Gc::write(mc, self.0), VectorObjectData, base)
.borrow_mut()
.init_property_local(name, value, activation)
}
fn delete_property_local(
@ -188,6 +189,8 @@ impl<'gc> TObject<'gc> for VectorObject<'gc> {
activation: &mut Activation<'_, 'gc>,
name: &Multiname<'gc>,
) -> Result<bool, Error<'gc>> {
let mc = activation.context.gc_context;
if name.contains_public_namespace()
&& name.local_name().is_some()
&& name.local_name().unwrap().parse::<usize>().is_ok()
@ -195,10 +198,8 @@ impl<'gc> TObject<'gc> for VectorObject<'gc> {
return Ok(true);
}
Ok(self
.0
.write(activation.context.gc_context)
.base
Ok(unlock!(Gc::write(mc, self.0), VectorObjectData, base)
.borrow_mut()
.delete_property_local(name))
}
@ -206,12 +207,12 @@ impl<'gc> TObject<'gc> for VectorObject<'gc> {
if name.contains_public_namespace() {
if let Some(name) = name.local_name() {
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(
@ -219,7 +220,7 @@ impl<'gc> TObject<'gc> for VectorObject<'gc> {
last_index: u32,
_activation: &mut Activation<'_, '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)))
} else {
Ok(None)
@ -231,7 +232,7 @@ impl<'gc> TObject<'gc> for VectorObject<'gc> {
index: u32,
_activation: &mut Activation<'_, '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
.checked_sub(1)
.map(|index| index.into())
@ -246,10 +247,10 @@ impl<'gc> TObject<'gc> for VectorObject<'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>>> {
Some(RefMut::map(self.0.write(mc), |vod| &mut vod.vector))
Some(unlock!(Gc::write(mc, self.0), VectorObjectData, vector).borrow_mut())
}
}