avm2: Use TU's method cache for callstatic, newfunction opcodes

This commit is contained in:
Adrian Wielgosik 2021-12-17 15:39:37 +01:00 committed by kmeisthax
parent 4b23f4dfb7
commit 22a0711d85
5 changed files with 23 additions and 22 deletions

View File

@ -727,8 +727,10 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
method: Gc<'gc, BytecodeMethod<'gc>>,
index: Index<AbcMethod>,
is_function: bool,
) -> Result<Gc<'gc, BytecodeMethod<'gc>>, Error> {
BytecodeMethod::from_method_index(method.translation_unit(), index, is_function, self)
) -> Result<Method<'gc>, Error> {
method
.translation_unit()
.load_method(index, is_function, self)
}
/// Retrieve a class entry from the current ABC file's method table.
@ -1209,7 +1211,7 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
let method = self.table_method(method, index, false)?;
// TODO: What scope should the function be executed with?
let scope = self.create_scopechain();
let function = FunctionObject::from_method(self, method.into(), scope, None, None);
let function = FunctionObject::from_method(self, method, scope, None, None);
let value = function.call(Some(receiver), &args, self)?;
self.context.avm2.push(value);
@ -1707,7 +1709,7 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
let method_entry = self.table_method(method, index, true)?;
let scope = self.create_scopechain();
let new_fn = FunctionObject::from_function(self, method_entry.into(), scope)?;
let new_fn = FunctionObject::from_function(self, method_entry, scope)?;
self.context.avm2.push(new_fn);

View File

@ -277,9 +277,9 @@ impl<'gc> Class<'gc> {
)?);
}
let instance_init = unit.load_method(abc_instance.init_method.0, false, activation)?;
let instance_init = unit.load_method(abc_instance.init_method, false, activation)?;
let native_instance_init = instance_init.clone();
let class_init = unit.load_method(abc_class.init_method.0, false, activation)?;
let class_init = unit.load_method(abc_class.init_method, false, activation)?;
let mut attributes = ClassAttributes::empty();
attributes.set(ClassAttributes::SEALED, abc_instance.is_sealed);

View File

@ -15,7 +15,7 @@ use gc_arena::{Collect, Gc, GcCell, MutationContext};
use std::cell::Ref;
use std::mem::drop;
use std::rc::Rc;
use swf::avm2::types::{AbcFile, Index, Script as AbcScript};
use swf::avm2::types::{AbcFile, Index, Method as AbcMethod, Script as AbcScript};
#[derive(Copy, Clone, Debug, Collect)]
#[collect(no_drop)]
@ -87,26 +87,22 @@ impl<'gc> TranslationUnit<'gc> {
/// Load a method from the ABC file and return its method definition.
pub fn load_method(
self,
method_index: u32,
method_index: Index<AbcMethod>,
is_function: bool,
activation: &mut Activation<'_, 'gc, '_>,
) -> Result<Method<'gc>, Error> {
let read = self.0.read();
if let Some(Some(method)) = read.methods.get(method_index as usize) {
if let Some(Some(method)) = read.methods.get(method_index.0 as usize) {
return Ok(method.clone());
}
drop(read);
let method: Result<Gc<'gc, BytecodeMethod<'gc>>, Error> = BytecodeMethod::from_method_index(
self,
Index::new(method_index),
is_function,
activation,
);
let method: Result<Gc<'gc, BytecodeMethod<'gc>>, Error> =
BytecodeMethod::from_method_index(self, method_index, is_function, activation);
let method: Method<'gc> = method?.into();
self.0.write(activation.context.gc_context).methods[method_index as usize] =
self.0.write(activation.context.gc_context).methods[method_index.0 as usize] =
Some(method.clone());
Ok(method)
@ -298,7 +294,7 @@ impl<'gc> Script<'gc> {
.ok_or_else(|| "LoadError: Script index not valid".into());
let script = script?;
let init = unit.load_method(script.init_method.0, false, activation)?;
let init = unit.load_method(script.init_method, false, activation)?;
Ok(Self(GcCell::allocate(
activation.context.gc_context,

View File

@ -214,7 +214,7 @@ impl<'gc> Trait<'gc> {
attributes: trait_attribs_from_abc_traits(abc_trait),
kind: TraitKind::Method {
disp_id: *disp_id,
method: unit.load_method(method.0, false, activation)?,
method: unit.load_method(*method, false, activation)?,
},
},
AbcTraitKind::Getter { disp_id, method } => Trait {
@ -222,7 +222,7 @@ impl<'gc> Trait<'gc> {
attributes: trait_attribs_from_abc_traits(abc_trait),
kind: TraitKind::Getter {
disp_id: *disp_id,
method: unit.load_method(method.0, false, activation)?,
method: unit.load_method(*method, false, activation)?,
},
},
AbcTraitKind::Setter { disp_id, method } => Trait {
@ -230,7 +230,7 @@ impl<'gc> Trait<'gc> {
attributes: trait_attribs_from_abc_traits(abc_trait),
kind: TraitKind::Setter {
disp_id: *disp_id,
method: unit.load_method(method.0, false, activation)?,
method: unit.load_method(*method, false, activation)?,
},
},
AbcTraitKind::Class { slot_id, class } => Trait {
@ -246,7 +246,7 @@ impl<'gc> Trait<'gc> {
attributes: trait_attribs_from_abc_traits(abc_trait),
kind: TraitKind::Function {
slot_id: *slot_id,
function: unit.load_method(function.0, true, activation)?,
function: unit.load_method(*function, true, activation)?,
},
},
AbcTraitKind::Const {

View File

@ -24,9 +24,12 @@ pub struct ConstantPool {
pub multinames: Vec<Multiname>,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Index<T>(pub u32, pub PhantomData<T>);
// see: https://github.com/rust-lang/rust/issues/26925
impl<T: Clone> Copy for Index<T> {}
impl<T> Index<T> {
pub fn new(i: u32) -> Index<T> {
Index(i, PhantomData)