From 12174b5219194e22f13c38e623e6f69c2b23799c Mon Sep 17 00:00:00 2001 From: Lord-McSweeney Date: Thu, 9 May 2024 19:36:34 -0700 Subject: [PATCH] avm2: Propagate types from getslot, getglobalscope, and getglobalslot in optimizer --- core/src/avm2/optimize.rs | 95 +++++++++++++++++++++++++++++++++++---- 1 file changed, 86 insertions(+), 9 deletions(-) diff --git a/core/src/avm2/optimize.rs b/core/src/avm2/optimize.rs index 6f6a51b95..7f0e4eb4a 100644 --- a/core/src/avm2/optimize.rs +++ b/core/src/avm2/optimize.rs @@ -850,11 +850,36 @@ pub fn optimize<'gc>( local_types.set_any(*index_register as usize); local_types.set_any(*object_register as usize); } - Op::GetSlot { .. } => { - stack.pop(); + Op::GetSlot { index: slot_id } => { + let mut stack_push_done = false; + let stack_value = stack.pop_or_any(); - // Avoid handling type for now - stack.push_any(); + 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(); + } + } + + 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 { .. } => { stack.pop(); @@ -1015,6 +1040,8 @@ pub fn optimize<'gc>( stack.pop_for_multiname(*multiname); stack.pop(); + + stack.push_class_object(types.boolean); } Op::Construct { num_args } => { // Arguments @@ -1188,12 +1215,62 @@ pub fn optimize<'gc>( stack.pop(); } Op::GetGlobalScope => { - // Avoid handling for now - stack.push_any(); + 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(); + } + } + } + + if !stack_push_done { + stack.push_any(); + } } - Op::GetGlobalSlot { .. } => { - // Avoid handling for now - 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 { .. } => { // Avoid handling for now