From 090fe56bd32cdf6696cfd468885030d1978c0858 Mon Sep 17 00:00:00 2001 From: David Wendt Date: Sat, 4 Jul 2020 17:56:27 -0400 Subject: [PATCH] Wrap `BytecodeMethod` (and the bytecode half of `Executable`) in a `Gc`. This is inspired by Dinnerbone's similar PR on the AVM1 side, where the Action half of that VM's `Executable` was reduced from 128 bytes to 16 by shoving it in a `Gc`. This won't be as dramatic but should still save some memory. In fact, it should save a *lot* of memory in bytecode execution, where thanks to the previous commit's rebase, we now need to clone the current method once *for each instruction executed*. That is terrible, but should stop now. --- core/src/avm2/activation.rs | 106 ++++++++++++++++++++---------------- core/src/avm2/function.rs | 101 +++++++++++++++++----------------- core/src/avm2/method.rs | 35 +++++++----- core/src/avm2/property.rs | 6 +- core/src/avm2/script.rs | 6 +- 5 files changed, 136 insertions(+), 118 deletions(-) diff --git a/core/src/avm2/activation.rs b/core/src/avm2/activation.rs index d6a362edc..e936a06c1 100644 --- a/core/src/avm2/activation.rs +++ b/core/src/avm2/activation.rs @@ -11,7 +11,7 @@ use crate::avm2::script_object::ScriptObject; use crate::avm2::value::Value; use crate::avm2::{value, Avm2, Error}; use crate::context::UpdateContext; -use gc_arena::{Collect, GcCell, MutationContext}; +use gc_arena::{Collect, Gc, GcCell, MutationContext}; use smallvec::SmallVec; use std::io::Cursor; use swf::avm2::read::Reader; @@ -137,7 +137,7 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> { script: GcCell<'gc, Script<'gc>>, global: Object<'gc>, ) -> Result { - let method = script.read().init().into_entry()?; + let method = script.read().init().into_bytecode()?; let scope = Some(Scope::push_scope(None, global, context.gc_context)); let num_locals = method.body().num_locals; let local_registers = @@ -166,7 +166,7 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> { pub fn from_method( avm2: &'a mut Avm2<'gc>, context: &mut UpdateContext<'_, 'gc, '_>, - method: BytecodeMethod<'gc>, + method: Gc<'gc, BytecodeMethod<'gc>>, scope: Option>>, this: Option>, arguments: &[Value<'gc>], @@ -210,7 +210,7 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> { context: &mut UpdateContext<'_, 'gc, '_>, script: GcCell<'gc, Script<'gc>>, ) -> Result<(), Error> { - let init = script.read().init().into_entry()?; + let init = script.read().init().into_bytecode()?; self.run_actions(init, context)?; @@ -289,24 +289,36 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> { } /// Retrieve a int from the current constant pool. - fn pool_int(&self, method: BytecodeMethod<'gc>, index: Index) -> Result { + fn pool_int( + &self, + method: Gc<'gc, BytecodeMethod<'gc>>, + index: Index, + ) -> Result { value::abc_int(&method.abc(), index) } /// Retrieve a int from the current constant pool. - fn pool_uint(&self, method: BytecodeMethod<'gc>, index: Index) -> Result { + fn pool_uint( + &self, + method: Gc<'gc, BytecodeMethod<'gc>>, + index: Index, + ) -> Result { value::abc_uint(&method.abc(), index) } /// Retrieve a double from the current constant pool. - fn pool_double(&self, method: BytecodeMethod<'gc>, index: Index) -> Result { + fn pool_double( + &self, + method: Gc<'gc, BytecodeMethod<'gc>>, + index: Index, + ) -> Result { value::abc_double(&method.abc(), index) } /// Retrieve a string from the current constant pool. fn pool_string( &self, - method: BytecodeMethod<'gc>, + method: Gc<'gc, BytecodeMethod<'gc>>, index: Index, ) -> Result { value::abc_string(&method.abc(), index) @@ -315,7 +327,7 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> { /// Retrieve a namespace from the current constant pool. fn pool_namespace( &self, - method: BytecodeMethod<'gc>, + method: Gc<'gc, BytecodeMethod<'gc>>, index: Index, ) -> Result { Namespace::from_abc_namespace(&method.abc(), index) @@ -324,7 +336,7 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> { /// Retrieve a multiname from the current constant pool. fn pool_multiname( &mut self, - method: BytecodeMethod<'gc>, + method: Gc<'gc, BytecodeMethod<'gc>>, index: Index, ) -> Result { Multiname::from_abc_multiname(&method.abc(), index, self.avm2) @@ -334,7 +346,7 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> { /// pool. fn pool_multiname_static( &mut self, - method: BytecodeMethod<'gc>, + method: Gc<'gc, BytecodeMethod<'gc>>, index: Index, ) -> Result { Multiname::from_abc_multiname_static(&method.abc(), index) @@ -343,17 +355,18 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> { /// Retrieve a method entry from the current ABC file's method table. fn table_method( &mut self, - method: BytecodeMethod<'gc>, + method: Gc<'gc, BytecodeMethod<'gc>>, index: Index, - ) -> Result, Error> { - BytecodeMethod::from_method_index(method.translation_unit(), index.clone()) + mc: MutationContext<'gc, '_>, + ) -> Result>, Error> { + BytecodeMethod::from_method_index(method.translation_unit(), index.clone(), mc) .ok_or_else(|| format!("Method index {} does not exist", index.0).into()) } /// Retrieve a class entry from the current ABC file's method table. fn table_class( &mut self, - method: BytecodeMethod<'gc>, + method: Gc<'gc, BytecodeMethod<'gc>>, index: Index, context: &mut UpdateContext<'_, 'gc, '_>, ) -> Result>, Error> { @@ -364,14 +377,13 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> { pub fn run_actions( &mut self, - method: BytecodeMethod<'gc>, + method: Gc<'gc, BytecodeMethod<'gc>>, context: &mut UpdateContext<'_, 'gc, '_>, ) -> Result, Error> { - let clone_method = method.clone(); - let mut read = Reader::new(Cursor::new(clone_method.body().code.as_ref())); + let mut read = Reader::new(Cursor::new(method.body().code.as_ref())); loop { - let result = self.do_next_opcode(method.clone(), context, &mut read); + let result = self.do_next_opcode(method, context, &mut read); match result { Ok(FrameControl::Return(value)) => break Ok(value), Ok(FrameControl::Continue) => {} @@ -383,7 +395,7 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> { /// Run a single action from a given action reader. fn do_next_opcode( &mut self, - method: BytecodeMethod<'gc>, + method: Gc<'gc, BytecodeMethod<'gc>>, context: &mut UpdateContext<'_, 'gc, '_>, reader: &mut Reader>, ) -> Result, Error> { @@ -511,7 +523,7 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> { fn op_push_double( &mut self, - method: BytecodeMethod<'gc>, + method: Gc<'gc, BytecodeMethod<'gc>>, value: Index, ) -> Result, Error> { self.avm2.push(self.pool_double(method, value)?); @@ -525,7 +537,7 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> { fn op_push_int( &mut self, - method: BytecodeMethod<'gc>, + method: Gc<'gc, BytecodeMethod<'gc>>, value: Index, ) -> Result, Error> { self.avm2.push(self.pool_int(method, value)?); @@ -534,7 +546,7 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> { fn op_push_namespace( &mut self, - method: BytecodeMethod<'gc>, + method: Gc<'gc, BytecodeMethod<'gc>>, value: Index, ) -> Result, Error> { self.avm2.push(self.pool_namespace(method, value)?); @@ -558,7 +570,7 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> { fn op_push_string( &mut self, - method: BytecodeMethod<'gc>, + method: Gc<'gc, BytecodeMethod<'gc>>, value: Index, ) -> Result, Error> { self.avm2.push(self.pool_string(method, value)?); @@ -572,7 +584,7 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> { fn op_push_uint( &mut self, - method: BytecodeMethod<'gc>, + method: Gc<'gc, BytecodeMethod<'gc>>, value: Index, ) -> Result, Error> { self.avm2.push(self.pool_uint(method, value)?); @@ -661,7 +673,7 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> { fn op_call_property( &mut self, - method: BytecodeMethod<'gc>, + method: Gc<'gc, BytecodeMethod<'gc>>, context: &mut UpdateContext<'_, 'gc, '_>, index: Index, arg_count: u32, @@ -686,7 +698,7 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> { fn op_call_prop_lex( &mut self, - method: BytecodeMethod<'gc>, + method: Gc<'gc, BytecodeMethod<'gc>>, context: &mut UpdateContext<'_, 'gc, '_>, index: Index, arg_count: u32, @@ -709,7 +721,7 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> { fn op_call_prop_void( &mut self, - method: BytecodeMethod<'gc>, + method: Gc<'gc, BytecodeMethod<'gc>>, context: &mut UpdateContext<'_, 'gc, '_>, index: Index, arg_count: u32, @@ -733,14 +745,14 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> { fn op_call_static( &mut self, - method: BytecodeMethod<'gc>, + method: Gc<'gc, BytecodeMethod<'gc>>, context: &mut UpdateContext<'_, 'gc, '_>, index: Index, arg_count: u32, ) -> Result, Error> { let args = self.avm2.pop_args(arg_count); let receiver = self.avm2.pop().as_object()?; - let method = self.table_method(method, index)?; + let method = self.table_method(method, index, context.gc_context)?; let scope = self.scope(); //TODO: Is this correct? let function = FunctionObject::from_method( context.gc_context, @@ -758,7 +770,7 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> { fn op_call_super( &mut self, - method: BytecodeMethod<'gc>, + method: Gc<'gc, BytecodeMethod<'gc>>, context: &mut UpdateContext<'_, 'gc, '_>, index: Index, arg_count: u32, @@ -791,7 +803,7 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> { fn op_call_super_void( &mut self, - method: BytecodeMethod<'gc>, + method: Gc<'gc, BytecodeMethod<'gc>>, context: &mut UpdateContext<'_, 'gc, '_>, index: Index, arg_count: u32, @@ -832,7 +844,7 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> { fn op_get_property( &mut self, - method: BytecodeMethod<'gc>, + method: Gc<'gc, BytecodeMethod<'gc>>, context: &mut UpdateContext<'_, 'gc, '_>, index: Index, ) -> Result, Error> { @@ -851,7 +863,7 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> { fn op_set_property( &mut self, - method: BytecodeMethod<'gc>, + method: Gc<'gc, BytecodeMethod<'gc>>, context: &mut UpdateContext<'_, 'gc, '_>, index: Index, ) -> Result, Error> { @@ -876,7 +888,7 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> { fn op_init_property( &mut self, - method: BytecodeMethod<'gc>, + method: Gc<'gc, BytecodeMethod<'gc>>, context: &mut UpdateContext<'_, 'gc, '_>, index: Index, ) -> Result, Error> { @@ -901,7 +913,7 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> { fn op_delete_property( &mut self, - method: BytecodeMethod<'gc>, + method: Gc<'gc, BytecodeMethod<'gc>>, context: &mut UpdateContext<'_, 'gc, '_>, index: Index, ) -> Result, Error> { @@ -920,7 +932,7 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> { fn op_get_super( &mut self, - method: BytecodeMethod<'gc>, + method: Gc<'gc, BytecodeMethod<'gc>>, context: &mut UpdateContext<'_, 'gc, '_>, index: Index, ) -> Result, Error> { @@ -950,7 +962,7 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> { fn op_set_super( &mut self, - method: BytecodeMethod<'gc>, + method: Gc<'gc, BytecodeMethod<'gc>>, context: &mut UpdateContext<'_, 'gc, '_>, index: Index, ) -> Result, Error> { @@ -1055,7 +1067,7 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> { fn op_find_property( &mut self, - method: BytecodeMethod<'gc>, + method: Gc<'gc, BytecodeMethod<'gc>>, context: &mut UpdateContext<'_, 'gc, '_>, index: Index, ) -> Result, Error> { @@ -1075,7 +1087,7 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> { fn op_find_prop_strict( &mut self, - method: BytecodeMethod<'gc>, + method: Gc<'gc, BytecodeMethod<'gc>>, context: &mut UpdateContext<'_, 'gc, '_>, index: Index, ) -> Result, Error> { @@ -1096,7 +1108,7 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> { fn op_get_lex( &mut self, - method: BytecodeMethod<'gc>, + method: Gc<'gc, BytecodeMethod<'gc>>, context: &mut UpdateContext<'_, 'gc, '_>, index: Index, ) -> Result, Error> { @@ -1188,7 +1200,7 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> { fn op_construct_prop( &mut self, - method: BytecodeMethod<'gc>, + method: Gc<'gc, BytecodeMethod<'gc>>, context: &mut UpdateContext<'_, 'gc, '_>, index: Index, arg_count: u32, @@ -1283,11 +1295,11 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> { fn op_new_function( &mut self, - method: BytecodeMethod<'gc>, + method: Gc<'gc, BytecodeMethod<'gc>>, context: &mut UpdateContext<'_, 'gc, '_>, index: Index, ) -> Result, Error> { - let method_entry = self.table_method(method, index)?; + let method_entry = self.table_method(method, index, context.gc_context)?; let scope = self.scope(); let mut new_fn = FunctionObject::from_method( @@ -1313,7 +1325,7 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> { fn op_new_class( &mut self, - method: BytecodeMethod<'gc>, + method: Gc<'gc, BytecodeMethod<'gc>>, context: &mut UpdateContext<'_, 'gc, '_>, index: Index, ) -> Result, Error> { @@ -1501,7 +1513,7 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> { #[allow(unused_variables)] fn op_debug( &mut self, - method: BytecodeMethod<'gc>, + method: Gc<'gc, BytecodeMethod<'gc>>, is_local_register: bool, register_name: Index, register: u8, @@ -1521,7 +1533,7 @@ impl<'a, 'gc: 'a> Activation<'a, 'gc> { #[allow(unused_variables)] fn op_debug_file( &mut self, - method: BytecodeMethod<'gc>, + method: Gc<'gc, BytecodeMethod<'gc>>, file_name: Index, ) -> Result, Error> { let file_name = self.pool_string(method, file_name)?; diff --git a/core/src/avm2/function.rs b/core/src/avm2/function.rs index 697924930..75e43efbc 100644 --- a/core/src/avm2/function.rs +++ b/core/src/avm2/function.rs @@ -11,11 +11,29 @@ use crate::avm2::script_object::{ScriptObjectClass, ScriptObjectData}; use crate::avm2::value::Value; use crate::avm2::Error; use crate::context::UpdateContext; -use gc_arena::{Collect, CollectionContext, GcCell, MutationContext}; +use gc_arena::{Collect, CollectionContext, Gc, GcCell, MutationContext}; use std::fmt; +/// Represents code written in AVM2 bytecode that can be executed by some +/// means. +#[derive(Clone, Collect)] +#[collect(no_drop)] +pub struct BytecodeExecutable<'gc> { + /// The method code to execute from a given ABC file. + method: Gc<'gc, BytecodeMethod<'gc>>, + + /// The scope stack to pull variables from. + scope: Option>>, + + /// The reciever that this function is always called with. + /// + /// If `None`, then the reciever provided by the caller is used. A + /// `Some` value indicates a bound executable. + reciever: Option>, +} + /// Represents code that can be executed by some means. -#[derive(Clone)] +#[derive(Copy, Clone)] pub enum Executable<'gc> { /// Code defined in Ruffle's binary. /// @@ -23,33 +41,13 @@ pub enum Executable<'gc> { Native(NativeMethod<'gc>, Option>), /// Code defined in a loaded ABC file. - Action { - /// The method code to execute from a given ABC file. - method: BytecodeMethod<'gc>, - - /// The scope stack to pull variables from. - scope: Option>>, - - /// The reciever that this function is always called with. - /// - /// If `None`, then the reciever provided by the caller is used. A - /// `Some` value indicates a bound executable. - reciever: Option>, - }, + Action(Gc<'gc, BytecodeExecutable<'gc>>), } unsafe impl<'gc> Collect for Executable<'gc> { fn trace(&self, cc: CollectionContext) { match self { - Self::Action { - method, - scope, - reciever, - } => { - method.trace(cc); - scope.trace(cc); - reciever.trace(cc); - } + Self::Action(be) => be.trace(cc), Self::Native(_nf, reciever) => reciever.trace(cc), } } @@ -61,14 +59,18 @@ impl<'gc> Executable<'gc> { method: Method<'gc>, scope: Option>>, reciever: Option>, + mc: MutationContext<'gc, '_>, ) -> Self { match method { Method::Native(nf) => Self::Native(nf, reciever), - Method::Entry(a2me) => Self::Action { - method: a2me, - scope, - reciever, - }, + Method::Entry(a2me) => Self::Action(Gc::allocate( + mc, + BytecodeExecutable { + method: a2me, + scope, + reciever, + }, + )), } } @@ -95,23 +97,19 @@ impl<'gc> Executable<'gc> { reciever.or(unbound_reciever), arguments, ), - Executable::Action { - method, - scope, - reciever, - } => { - let reciever = reciever.or(unbound_reciever); + Executable::Action(bm) => { + let reciever = bm.reciever.or(unbound_reciever); let mut activation = Activation::from_method( activation.avm2(), context, - method.clone(), - *scope, + bm.method, + bm.scope, reciever, arguments, base_proto, ); - activation.run_actions(method.clone(), context) + activation.run_actions(bm.method, context) } } } @@ -120,15 +118,11 @@ impl<'gc> Executable<'gc> { impl<'gc> fmt::Debug for Executable<'gc> { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - Self::Action { - method, - scope, - reciever, - } => fmt + Self::Action(be) => fmt .debug_struct("Executable::Action") - .field("method", method) - .field("scope", scope) - .field("reciever", reciever) + .field("method", &be.method) + .field("scope", &be.scope) + .field("reciever", &be.reciever) .finish(), Self::Native(nf, reciever) => fmt .debug_tuple("Executable::Native") @@ -200,7 +194,12 @@ impl<'gc> FunctionObject<'gc> { Some(fn_proto), ScriptObjectClass::ClassConstructor(class, scope), ), - exec: Some(Executable::from_method(initializer, scope, None)), + exec: Some(Executable::from_method( + initializer, + scope, + None, + context.gc_context, + )), }, )) .into(); @@ -239,7 +238,7 @@ impl<'gc> FunctionObject<'gc> { fn_proto: Object<'gc>, reciever: Option>, ) -> Object<'gc> { - let exec = Some(Executable::from_method(method, scope, reciever)); + let exec = Some(Executable::from_method(method, scope, reciever, mc)); FunctionObject(GcCell::allocate( mc, @@ -261,7 +260,7 @@ impl<'gc> FunctionObject<'gc> { mc, FunctionObjectData { base: ScriptObjectData::base_new(Some(fn_proto), ScriptObjectClass::NoClass), - exec: Some(Executable::from_method(nf.into(), None, None)), + exec: Some(Executable::from_method(nf.into(), None, None, mc)), }, )) .into() @@ -278,7 +277,7 @@ impl<'gc> FunctionObject<'gc> { mc, FunctionObjectData { base: ScriptObjectData::base_new(Some(fn_proto), ScriptObjectClass::NoClass), - exec: Some(Executable::from_method(constr.into(), None, None)), + exec: Some(Executable::from_method(constr.into(), None, None, mc)), }, )) .into(); @@ -465,7 +464,7 @@ impl<'gc> TObject<'gc> for FunctionObject<'gc> { } fn as_executable(&self) -> Option> { - self.0.read().exec.clone() + self.0.read().exec } fn call( diff --git a/core/src/avm2/method.rs b/core/src/avm2/method.rs index c2189143c..3d9e49d25 100644 --- a/core/src/avm2/method.rs +++ b/core/src/avm2/method.rs @@ -6,7 +6,7 @@ use crate::avm2::script::TranslationUnit; use crate::avm2::value::Value; use crate::avm2::Error; use crate::context::UpdateContext; -use gc_arena::{Collect, CollectionContext}; +use gc_arena::{Collect, CollectionContext, Gc, MutationContext}; use std::fmt; use std::rc::Rc; use swf::avm2::types::{AbcFile, Index, Method as AbcMethod, MethodBody as AbcMethodBody}; @@ -61,18 +61,22 @@ impl<'gc> BytecodeMethod<'gc> { pub fn from_method_index( txunit: TranslationUnit<'gc>, abc_method: Index, - ) -> Option { + mc: MutationContext<'gc, '_>, + ) -> Option> { let abc = txunit.abc(); if abc.methods.get(abc_method.0 as usize).is_some() { for (index, method_body) in abc.method_bodies.iter().enumerate() { if method_body.method.0 == abc_method.0 { - return Some(Self { - txunit, - abc: CollectWrapper(txunit.abc()), - abc_method: abc_method.0, - abc_method_body: index as u32, - }); + return Some(Gc::allocate( + mc, + Self { + txunit, + abc: CollectWrapper(txunit.abc()), + abc_method: abc_method.0, + abc_method_body: index as u32, + }, + )); } } } @@ -115,7 +119,7 @@ pub enum Method<'gc> { Native(NativeMethod<'gc>), /// An ABC-provided method entry. - Entry(BytecodeMethod<'gc>), + Entry(Gc<'gc, BytecodeMethod<'gc>>), } unsafe impl<'gc> Collect for Method<'gc> { @@ -145,19 +149,22 @@ impl<'gc> From> for Method<'gc> { } } -impl<'gc> From> for Method<'gc> { - fn from(a2me: BytecodeMethod<'gc>) -> Self { - Self::Entry(a2me) +impl<'gc> From>> for Method<'gc> { + fn from(bm: Gc<'gc, BytecodeMethod<'gc>>) -> Self { + Self::Entry(bm) } } impl<'gc> Method<'gc> { - pub fn into_entry(self) -> Result, Error> { + /// Access the bytecode of this method. + /// + /// This function returns `Err` if there is no bytecode for this method. + pub fn into_bytecode(self) -> Result>, Error> { match self { Method::Native(_) => { Err("Attempted to unwrap a native method as a user-defined one".into()) } - Method::Entry(a2me) => Ok(a2me), + Method::Entry(bm) => Ok(bm), } } } diff --git a/core/src/avm2/property.rs b/core/src/avm2/property.rs index 75e21dfe0..c9c12e550 100644 --- a/core/src/avm2/property.rs +++ b/core/src/avm2/property.rs @@ -140,7 +140,7 @@ impl<'gc> Property<'gc> { ) -> Result, Error> { match self { Property::Virtual { get: Some(get), .. } => Ok(ReturnValue::defer_execution( - get.clone(), + *get, Some(this), vec![], base_proto, @@ -168,7 +168,7 @@ impl<'gc> Property<'gc> { Property::Virtual { set, .. } => { if let Some(function) = set { return Ok(ReturnValue::defer_execution( - function.clone(), + *function, Some(this), vec![new_value.into()], base_proto, @@ -212,7 +212,7 @@ impl<'gc> Property<'gc> { Property::Virtual { set, .. } => { if let Some(function) = set { return Ok(ReturnValue::defer_execution( - function.clone(), + *function, Some(this), vec![new_value.into()], base_proto, diff --git a/core/src/avm2/script.rs b/core/src/avm2/script.rs index 684b5a939..c17dcc73c 100644 --- a/core/src/avm2/script.rs +++ b/core/src/avm2/script.rs @@ -4,7 +4,7 @@ use crate::avm2::class::Class; use crate::avm2::method::{BytecodeMethod, Method}; use crate::avm2::r#trait::Trait; use crate::avm2::Error; -use gc_arena::{Collect, GcCell, MutationContext}; +use gc_arena::{Collect, Gc, GcCell, MutationContext}; use std::collections::HashMap; use std::mem::drop; use std::rc::Rc; @@ -77,8 +77,8 @@ impl<'gc> TranslationUnit<'gc> { drop(write); - let method: Result, Error> = - BytecodeMethod::from_method_index(self, Index::new(method_index)) + let method: Result>, Error> = + BytecodeMethod::from_method_index(self, Index::new(method_index), mc) .ok_or_else(|| "Method index does not exist".into()); let method: Method<'gc> = method?.into();