From cf5420e2e140c2bac6157601de4dec753aecc774 Mon Sep 17 00:00:00 2001 From: David Wendt Date: Sun, 29 Sep 2019 09:31:33 -0400 Subject: [PATCH] Implement register preloading, for variables we already have implemented. --- core/src/avm1.rs | 16 ++++++++--- core/src/avm1/function.rs | 56 ++++++++++++++++++++++++++++++++++----- 2 files changed, 63 insertions(+), 9 deletions(-) diff --git a/core/src/avm1.rs b/core/src/avm1.rs index 5814feecc..26b3fea30 100644 --- a/core/src/avm1.rs +++ b/core/src/avm1.rs @@ -687,6 +687,7 @@ impl<'gc> Avm1<'gc> { action_func.preload_arguments, action_func.suppress_this, action_func.preload_this, + action_func.preload_global, &action_func.params, scope ); @@ -877,20 +878,29 @@ impl<'gc> Avm1<'gc> { Ok(()) } + /// Obtain the value of `_root`. + pub fn root_object(&self, context: &mut ActionContext<'_, 'gc, '_>) -> Value<'gc> { + context.start_clip.read().object() + } + + /// Obtain the value of `_global`. + pub fn global_object(&self, _context: &mut ActionContext<'_, 'gc, '_>) -> Value<'gc> { + Value::Object(self.globals) + } + fn action_get_variable( &mut self, context: &mut ActionContext<'_, 'gc, '_>, ) -> Result<(), Error> { let var_path = self.pop()?; let path = var_path.as_string()?; - let globals = self.globals; // Special hardcoded variables if path == "_root" { - self.push(context.start_clip.read().object()); + self.push(self.root_object(context)); return Ok(()); } else if path == "_global" { - self.push(Value::Object(globals)); + self.push(self.global_object(context)); return Ok(()); } diff --git a/core/src/avm1/function.rs b/core/src/avm1/function.rs index 85214cd6f..6a44fe438 100644 --- a/core/src/avm1/function.rs +++ b/core/src/avm1/function.rs @@ -94,6 +94,7 @@ pub struct Avm1Function2<'gc> { preload_arguments: bool, supress_this: bool, preload_this: bool, + preload_global: bool, /// The names of the function parameters and their register mappings. /// r0 indicates that no register shall be written and the parameter stored @@ -117,6 +118,7 @@ impl<'gc> Avm1Function2<'gc> { preload_arguments: bool, supress_this: bool, preload_this: bool, + preload_global: bool, params: &Vec, scope: GcCell<'gc, Scope<'gc>>) -> Self { @@ -143,6 +145,7 @@ impl<'gc> Avm1Function2<'gc> { preload_arguments: preload_arguments, supress_this: supress_this, preload_this: preload_this, + preload_global: preload_global, params: owned_params, scope: scope } @@ -212,20 +215,61 @@ impl<'gc> Executable<'gc> { let mut arguments = Object::object(ac.gc_context); if !af.supress_arguments { for i in 0..args.len() { - arguments.set(&format!("{}", i), args.get(i).unwrap().clone()) + arguments.force_set(&format!("{}", i), args.get(i).unwrap().clone()) } - arguments.set("length", Value::Number(args.len() as f64)); + arguments.force_set("length", Value::Number(args.len() as f64)); + } + let argcell = GcCell::allocate(ac.gc_context, arguments); + + avm.insert_stack_frame_for_function2(af, this, argcell, ac); + + let mut preload_r = 1; + + if af.preload_this { + //TODO: What happens if you specify both suppress and + //preload for this? + avm.set_current_register(preload_r, Value::Object(this), ac); + preload_r += 1; } - avm.insert_stack_frame_for_function2(af, this, GcCell::allocate(ac.gc_context, arguments), ac); + if af.preload_arguments { + //TODO: What happens if you specify both suppress and + //preload for arguments? + avm.set_current_register(preload_r, Value::Object(argcell), ac); + preload_r += 1; + } + if af.preload_super { + //TODO: super not implemented + log::warn!("Cannot preload super into register because it's not implemented"); + //TODO: What happens if you specify both suppress and + //preload for super? + preload_r += 1; + } + + if af.preload_root { + avm.set_current_register(preload_r, avm.root_object(ac), ac); + preload_r += 1; + } + + if af.preload_parent { + //TODO: _parent not implemented + log::warn!("Cannot preload parent into register because it's not implemented"); + preload_r += 1; + } + + if af.preload_global { + avm.set_current_register(preload_r, avm.global_object(ac), ac); + } + + //TODO: What happens if the argument registers clash with the + //preloaded registers? What gets done last? for i in 0..args.len() { match (args.get(i), af.params.get(i)) { - (Some(arg), Some((Some(argreg), argname))) => avm.set_current_register(*argreg, arg.clone(), ac), + (Some(arg), Some((Some(argreg), _argname))) => avm.set_current_register(*argreg, arg.clone(), ac), (Some(arg), Some((None, argname))) => avm.current_stack_frame_mut().unwrap().define(argname, arg.clone(), ac.gc_context), - (Some(arg), _) => {}, - _ => panic!("Missing argument value") + _ => {} } }