avm2: Propagate types from getslot, getglobalscope, and getglobalslot in optimizer

This commit is contained in:
Lord-McSweeney 2024-05-09 19:36:34 -07:00 committed by Lord-McSweeney
parent 92de618261
commit 12174b5219
1 changed files with 86 additions and 9 deletions

View File

@ -850,12 +850,37 @@ pub fn optimize<'gc>(
local_types.set_any(*index_register as usize); local_types.set_any(*index_register as usize);
local_types.set_any(*object_register as usize); local_types.set_any(*object_register as usize);
} }
Op::GetSlot { .. } => { Op::GetSlot { index: slot_id } => {
stack.pop(); let mut stack_push_done = false;
let stack_value = stack.pop_or_any();
// Avoid handling type for now if let Some(class) = stack_value.class {
if !class.inner_class_definition().is_interface() {
let mut value_class =
class.instance_vtable().slot_classes()[*slot_id as usize];
let resolved_value_class = value_class.get_class(activation);
if let Ok(class) = resolved_value_class {
stack_push_done = true;
if let Some(class) = class {
stack.push_class(class);
} else {
stack.push_any(); stack.push_any();
} }
}
class.instance_vtable().set_slot_class(
activation.context.gc_context,
*slot_id as usize,
value_class,
);
}
}
if !stack_push_done {
stack.push_any();
}
}
Op::SetSlot { .. } => { Op::SetSlot { .. } => {
stack.pop(); stack.pop();
stack.pop(); stack.pop();
@ -1015,6 +1040,8 @@ pub fn optimize<'gc>(
stack.pop_for_multiname(*multiname); stack.pop_for_multiname(*multiname);
stack.pop(); stack.pop();
stack.push_class_object(types.boolean);
} }
Op::Construct { num_args } => { Op::Construct { num_args } => {
// Arguments // Arguments
@ -1188,13 +1215,63 @@ pub fn optimize<'gc>(
stack.pop(); stack.pop();
} }
Op::GetGlobalScope => { Op::GetGlobalScope => {
// Avoid handling for now let mut stack_push_done = false;
if has_simple_scoping {
let outer_scope = activation.outer();
if !outer_scope.is_empty() {
let global_scope = outer_scope.get_unchecked(0);
stack_push_done = true;
if let Some(class) = global_scope.values().instance_of() {
stack.push_class_object(class);
} else {
stack.push_any(); stack.push_any();
} }
Op::GetGlobalSlot { .. } => { }
// Avoid handling for now }
if !stack_push_done {
stack.push_any(); stack.push_any();
} }
}
Op::GetGlobalSlot { index: slot_id } => {
let mut stack_push_done = false;
if has_simple_scoping {
let outer_scope = activation.outer();
if !outer_scope.is_empty() {
let global_scope = outer_scope.get_unchecked(0);
if let Some(class) = global_scope.values().instance_of() {
if !class.inner_class_definition().is_interface() {
let mut value_class =
class.instance_vtable().slot_classes()[*slot_id as usize];
let resolved_value_class = value_class.get_class(activation);
if let Ok(class) = resolved_value_class {
stack_push_done = true;
if let Some(class) = class {
stack.push_class(class);
} else {
stack.push_any();
}
}
class.instance_vtable().set_slot_class(
activation.context.gc_context,
*slot_id as usize,
value_class,
);
}
}
}
}
if !stack_push_done {
stack.push_any();
}
}
Op::SetGlobalSlot { .. } => { Op::SetGlobalSlot { .. } => {
// Avoid handling for now // Avoid handling for now
stack.pop(); stack.pop();