From eaebd3c63c3b515a9d279a10396275d669d1a3df Mon Sep 17 00:00:00 2001 From: David Wendt Date: Thu, 2 Jul 2020 19:02:54 -0400 Subject: [PATCH] Make `Avm2MethodEntry` hold it's `TranslationUnit` rather than an `AbcFile`. --- core/src/avm2.rs | 12 ++++++---- core/src/avm2/activation.rs | 6 ++--- core/src/avm2/function.rs | 46 +++++++++++++++++++++++++------------ core/src/avm2/script.rs | 2 +- 4 files changed, 43 insertions(+), 23 deletions(-) diff --git a/core/src/avm2.rs b/core/src/avm2.rs index 20e37b013..ca1dbab6a 100644 --- a/core/src/avm2.rs +++ b/core/src/avm2.rs @@ -233,7 +233,7 @@ impl<'gc> Avm2<'gc> { frame_ref.lock()?; let method = frame_ref.method(); - let abc = method.abc.as_ref().clone(); + let abc = method.abc(); let _method_index = method.abc_method; let method_body_index = method.abc_method_body as usize; @@ -367,7 +367,11 @@ impl<'gc> Avm2<'gc> { /// Retrieve the current constant pool for the currently executing function. fn current_abc(&self) -> Option> { self.current_stack_frame() - .map(|sf| sf.read().method().abc.clone()) + .map(|sf| sf.read().method().abc()) + } + + fn current_translation_unit(&self) -> Option> { + self.current_stack_frame().map(|sf| sf.read().method().translation_unit()) } /// Retrieve a int from the current constant pool. @@ -407,8 +411,8 @@ impl<'gc> Avm2<'gc> { } /// Retrieve a method entry from the current ABC file's method table. - fn table_method(&mut self, index: Index) -> Result { - Avm2MethodEntry::from_method_index(self.current_abc().unwrap(), index.clone()) + fn table_method(&mut self, index: Index) -> Result, Error> { + Avm2MethodEntry::from_method_index(self.current_translation_unit().unwrap(), index.clone()) .ok_or_else(|| format!("Method index {} does not exist", index.0).into()) } diff --git a/core/src/avm2/activation.rs b/core/src/avm2/activation.rs index dafc8c720..4e85097b4 100644 --- a/core/src/avm2/activation.rs +++ b/core/src/avm2/activation.rs @@ -50,7 +50,7 @@ impl<'gc> RegisterSet<'gc> { #[collect(no_drop)] pub struct Activation<'gc> { /// The AVM method entry we're executing code out of. - method: Avm2MethodEntry, + method: Avm2MethodEntry<'gc>, /// The current location of the instruction stream being executed. pc: usize, @@ -125,7 +125,7 @@ impl<'gc> Activation<'gc> { pub fn from_action( context: &mut UpdateContext<'_, 'gc, '_>, - method: Avm2MethodEntry, + method: Avm2MethodEntry<'gc>, scope: Option>>, this: Option>, arguments: &[Value<'gc>], @@ -184,7 +184,7 @@ impl<'gc> Activation<'gc> { } /// Obtain a reference to the method being executed. - pub fn method(&self) -> &Avm2MethodEntry { + pub fn method(&self) -> &Avm2MethodEntry<'gc> { &self.method } diff --git a/core/src/avm2/function.rs b/core/src/avm2/function.rs index 31b11ca1e..3cf03e663 100644 --- a/core/src/avm2/function.rs +++ b/core/src/avm2/function.rs @@ -7,6 +7,7 @@ use crate::avm2::object::{Object, ObjectPtr, TObject}; use crate::avm2::r#trait::Trait; use crate::avm2::return_value::ReturnValue; use crate::avm2::scope::Scope; +use crate::avm2::script::TranslationUnit; use crate::avm2::script_object::{ScriptObjectClass, ScriptObjectData}; use crate::avm2::value::Value; use crate::avm2::{Avm2, Error}; @@ -39,10 +40,10 @@ pub type NativeFunction<'gc> = fn( /// Represents a reference to an AVM2 method and body. #[derive(Collect, Clone, Debug)] -#[collect(require_static)] -pub struct Avm2MethodEntry { +#[collect(no_drop)] +pub struct Avm2MethodEntry<'gc> { /// The ABC file this function was defined in. - pub abc: Rc, + pub txunit: TranslationUnit<'gc>, /// The ABC method this function uses. pub abc_method: u32, @@ -51,17 +52,22 @@ pub struct Avm2MethodEntry { pub abc_method_body: u32, } -impl Avm2MethodEntry { +impl<'gc> Avm2MethodEntry<'gc> { /// Construct an `Avm2MethodEntry` from an `AbcFile` and method index. /// /// The method body index will be determined by searching through the ABC /// for a matching method. If none exists, this function returns `None`. - pub fn from_method_index(abc: Rc, abc_method: Index) -> Option { + pub fn from_method_index( + txunit: TranslationUnit<'gc>, + abc_method: Index, + ) -> 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 { - abc, + txunit, abc_method: abc_method.0, abc_method_body: index as u32, }); @@ -75,17 +81,27 @@ impl Avm2MethodEntry { /// Get the underlying ABC file. #[allow(dead_code)] pub fn abc(&self) -> Rc { - self.abc.clone() + self.txunit.abc().clone() + } + + /// Get the underlying translation unit this method was defined in. + pub fn translation_unit(&self) -> TranslationUnit<'gc> { + self.txunit } /// Get a reference to the ABC method entry this refers to. pub fn method(&self) -> &AbcMethod { - self.abc.methods.get(self.abc_method as usize).unwrap() + self.txunit + .abc() + .methods + .get(self.abc_method as usize) + .unwrap() } /// Get a reference to the ABC method body entry this refers to. pub fn body(&self) -> &AbcMethodBody { - self.abc + self.txunit + .abc() .method_bodies .get(self.abc_method_body as usize) .unwrap() @@ -100,7 +116,7 @@ pub enum Method<'gc> { Native(NativeFunction<'gc>), /// An ABC-provided method entry. - Entry(Avm2MethodEntry), + Entry(Avm2MethodEntry<'gc>), } unsafe impl<'gc> Collect for Method<'gc> { @@ -130,14 +146,14 @@ impl<'gc> From> for Method<'gc> { } } -impl<'gc> From for Method<'gc> { - fn from(a2me: Avm2MethodEntry) -> Self { +impl<'gc> From> for Method<'gc> { + fn from(a2me: Avm2MethodEntry<'gc>) -> Self { Self::Entry(a2me) } } impl<'gc> Method<'gc> { - pub fn as_entry(self) -> Result { + pub fn as_entry(self) -> Result, Error> { match self { Method::Native(_) => { Err("Attempted to unwrap a native method as a user-defined one".into()) @@ -152,7 +168,7 @@ impl<'gc> Method<'gc> { #[collect(no_drop)] pub struct Avm2Function<'gc> { /// The AVM method entry used to create this function. - pub method: Avm2MethodEntry, + pub method: Avm2MethodEntry<'gc>, /// Closure scope stack at time of creation pub scope: Option>>, @@ -175,7 +191,7 @@ pub enum Executable<'gc> { /// Code defined in a loaded ABC file. Action { /// The method code to execute from a given ABC file. - method: Avm2MethodEntry, + method: Avm2MethodEntry<'gc>, /// The scope stack to pull variables from. scope: Option>>, diff --git a/core/src/avm2/script.rs b/core/src/avm2/script.rs index c4e557570..3bb1a968e 100644 --- a/core/src/avm2/script.rs +++ b/core/src/avm2/script.rs @@ -80,7 +80,7 @@ impl<'gc> TranslationUnit<'gc> { drop(write); let method: Result = - Avm2MethodEntry::from_method_index(abc, Index::new(method_index)) + Avm2MethodEntry::from_method_index(self, Index::new(method_index)) .ok_or_else(|| "Method index does not exist".into()); let method = method?.into();