avm2: Avoid unnecessary Gc allocation for `PropertyClass::Name`

This commit is contained in:
Lord-McSweeney 2024-09-12 23:28:36 -07:00 committed by Lord-McSweeney
parent ed9b250d0a
commit ae956eb10f
2 changed files with 11 additions and 20 deletions

View File

@ -7,7 +7,7 @@ use crate::avm2::TranslationUnit;
use crate::avm2::Value;
use crate::context::GcContext;
use crate::string::AvmString;
use gc_arena::{Collect, Gc, Mutation};
use gc_arena::{Collect, Gc};
use super::class::Class;
@ -36,22 +36,17 @@ pub enum Property {
#[derive(Collect, Clone, Copy)]
#[collect(no_drop)]
pub enum PropertyClass<'gc> {
/// The type `*` (Multiname::is_any()). This allows
/// `Value::Undefined`, so it needs to be distinguished
/// from the `Object` class
/// The type `*`. This allows `Value::Undefined`, so it needs to
/// be distinguished from the `Object` class
Any,
Class(Class<'gc>),
Name(Gc<'gc, (Gc<'gc, Multiname<'gc>>, Option<TranslationUnit<'gc>>)>),
Name(Gc<'gc, Multiname<'gc>>, Option<TranslationUnit<'gc>>),
}
impl<'gc> PropertyClass<'gc> {
pub fn name(
mc: &Mutation<'gc>,
name: Option<Gc<'gc, Multiname<'gc>>>,
unit: Option<TranslationUnit<'gc>>,
) -> Self {
pub fn name(name: Option<Gc<'gc, Multiname<'gc>>>, unit: Option<TranslationUnit<'gc>>) -> Self {
if let Some(name) = name {
PropertyClass::Name(Gc::new(mc, (name, unit)))
PropertyClass::Name(name, unit)
} else {
PropertyClass::Any
}
@ -67,9 +62,7 @@ impl<'gc> PropertyClass<'gc> {
) -> Result<(Value<'gc>, bool), Error<'gc>> {
let (class, changed) = match self {
PropertyClass::Class(class) => (Some(*class), false),
PropertyClass::Name(gc) => {
let (name, unit) = &**gc;
PropertyClass::Name(name, unit) => {
// Note - we look up the class in the domain by name, which allows us to look up private classes.
// This also has the advantage of letting us coerce to a class while the `ClassObject`
// is still being constructed (since the `Class` will already exist in the domain).
@ -104,9 +97,7 @@ impl<'gc> PropertyClass<'gc> {
) -> Result<Option<Class<'gc>>, Error<'gc>> {
match self {
PropertyClass::Class(class) => Ok(Some(*class)),
PropertyClass::Name(gc) => {
let (name, unit) = &**gc;
PropertyClass::Name(name, unit) => {
let domain = unit.map_or(activation.avm2().playerglobals_domain, |u| u.domain());
if let Some(class) = domain.get_class(activation.context, name) {
*self = PropertyClass::Class(class);
@ -125,7 +116,7 @@ impl<'gc> PropertyClass<'gc> {
pub fn get_name(&self, context: &mut GcContext<'_, 'gc>) -> AvmString<'gc> {
match self {
PropertyClass::Class(class) => class.name().to_qualified_name(context.gc_context),
PropertyClass::Name(gc) => gc.0.to_qualified_name_or_star(context),
PropertyClass::Name(name, _) => name.to_qualified_name_or_star(context),
PropertyClass::Any => context.interner.get_ascii_char('*'),
}
}

View File

@ -461,13 +461,13 @@ impl<'gc> VTable<'gc> {
type_name, unit, ..
} => (
Property::new_slot(new_slot_id),
PropertyClass::name(mc, *type_name, *unit),
PropertyClass::name(*type_name, *unit),
),
TraitKind::Const {
type_name, unit, ..
} => (
Property::new_const_slot(new_slot_id),
PropertyClass::name(mc, *type_name, *unit),
PropertyClass::name(*type_name, *unit),
),
TraitKind::Class { class, .. } => (
Property::new_const_slot(new_slot_id),