Implement register preloading, for variables we already have implemented.
This commit is contained in:
parent
8734c036a7
commit
cf5420e2e1
|
@ -687,6 +687,7 @@ impl<'gc> Avm1<'gc> {
|
||||||
action_func.preload_arguments,
|
action_func.preload_arguments,
|
||||||
action_func.suppress_this,
|
action_func.suppress_this,
|
||||||
action_func.preload_this,
|
action_func.preload_this,
|
||||||
|
action_func.preload_global,
|
||||||
&action_func.params,
|
&action_func.params,
|
||||||
scope
|
scope
|
||||||
);
|
);
|
||||||
|
@ -877,20 +878,29 @@ impl<'gc> Avm1<'gc> {
|
||||||
Ok(())
|
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(
|
fn action_get_variable(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut ActionContext<'_, 'gc, '_>,
|
context: &mut ActionContext<'_, 'gc, '_>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
let var_path = self.pop()?;
|
let var_path = self.pop()?;
|
||||||
let path = var_path.as_string()?;
|
let path = var_path.as_string()?;
|
||||||
let globals = self.globals;
|
|
||||||
|
|
||||||
// Special hardcoded variables
|
// Special hardcoded variables
|
||||||
if path == "_root" {
|
if path == "_root" {
|
||||||
self.push(context.start_clip.read().object());
|
self.push(self.root_object(context));
|
||||||
return Ok(());
|
return Ok(());
|
||||||
} else if path == "_global" {
|
} else if path == "_global" {
|
||||||
self.push(Value::Object(globals));
|
self.push(self.global_object(context));
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -94,6 +94,7 @@ pub struct Avm1Function2<'gc> {
|
||||||
preload_arguments: bool,
|
preload_arguments: bool,
|
||||||
supress_this: bool,
|
supress_this: bool,
|
||||||
preload_this: bool,
|
preload_this: bool,
|
||||||
|
preload_global: bool,
|
||||||
|
|
||||||
/// The names of the function parameters and their register mappings.
|
/// The names of the function parameters and their register mappings.
|
||||||
/// r0 indicates that no register shall be written and the parameter stored
|
/// r0 indicates that no register shall be written and the parameter stored
|
||||||
|
@ -117,6 +118,7 @@ impl<'gc> Avm1Function2<'gc> {
|
||||||
preload_arguments: bool,
|
preload_arguments: bool,
|
||||||
supress_this: bool,
|
supress_this: bool,
|
||||||
preload_this: bool,
|
preload_this: bool,
|
||||||
|
preload_global: bool,
|
||||||
params: &Vec<FunctionParam>,
|
params: &Vec<FunctionParam>,
|
||||||
scope: GcCell<'gc, Scope<'gc>>) -> Self {
|
scope: GcCell<'gc, Scope<'gc>>) -> Self {
|
||||||
|
|
||||||
|
@ -143,6 +145,7 @@ impl<'gc> Avm1Function2<'gc> {
|
||||||
preload_arguments: preload_arguments,
|
preload_arguments: preload_arguments,
|
||||||
supress_this: supress_this,
|
supress_this: supress_this,
|
||||||
preload_this: preload_this,
|
preload_this: preload_this,
|
||||||
|
preload_global: preload_global,
|
||||||
params: owned_params,
|
params: owned_params,
|
||||||
scope: scope
|
scope: scope
|
||||||
}
|
}
|
||||||
|
@ -212,20 +215,61 @@ impl<'gc> Executable<'gc> {
|
||||||
let mut arguments = Object::object(ac.gc_context);
|
let mut arguments = Object::object(ac.gc_context);
|
||||||
if !af.supress_arguments {
|
if !af.supress_arguments {
|
||||||
for i in 0..args.len() {
|
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() {
|
for i in 0..args.len() {
|
||||||
match (args.get(i), af.params.get(i)) {
|
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), Some((None, argname))) => avm.current_stack_frame_mut().unwrap().define(argname, arg.clone(), ac.gc_context),
|
||||||
(Some(arg), _) => {},
|
_ => {}
|
||||||
_ => panic!("Missing argument value")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue