avm2: Avoid unnecessary Gc allocation for `PropertyClass::Name`
This commit is contained in:
parent
ed9b250d0a
commit
ae956eb10f
|
@ -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('*'),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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),
|
||||
|
|
Loading…
Reference in New Issue