avm2: Make optimizer lookup callee return type

This provides us with more optimization opportunities.
Since we optimize methods one at a time, we need to look up
the return type in the domain rather than relying on the
resolved return type in the target `BytecodeMethod`
This commit is contained in:
Aaron Hill 2024-08-12 20:35:18 -04:00
parent 953c6732cc
commit 88e537bf48
No known key found for this signature in database
GPG Key ID: B4087E510E98B164
2 changed files with 41 additions and 0 deletions

View File

@ -8,6 +8,7 @@ use crate::avm2::value::{abc_default_value, Value};
use crate::avm2::verify::{resolve_param_config, VerifiedMethodInfo}; use crate::avm2::verify::{resolve_param_config, VerifiedMethodInfo};
use crate::avm2::Error; use crate::avm2::Error;
use crate::avm2::Multiname; use crate::avm2::Multiname;
use crate::context::UpdateContext;
use crate::string::AvmString; use crate::string::AvmString;
use crate::tag_utils::SwfMovie; use crate::tag_utils::SwfMovie;
use gc_arena::barrier::unlock; use gc_arena::barrier::unlock;
@ -23,6 +24,8 @@ use swf::avm2::types::{
MethodFlags as AbcMethodFlags, MethodParam as AbcMethodParam, MethodFlags as AbcMethodFlags, MethodParam as AbcMethodParam,
}; };
use super::Domain;
/// Represents a function defined in Ruffle's code. /// Represents a function defined in Ruffle's code.
/// ///
/// Parameters are as follows: /// Parameters are as follows:
@ -472,4 +475,11 @@ impl<'gc> Method<'gc> {
Method::Bytecode(bm) => bm.method().flags.contains(AbcMethodFlags::NEED_ARGUMENTS), Method::Bytecode(bm) => bm.method().flags.contains(AbcMethodFlags::NEED_ARGUMENTS),
} }
} }
pub fn domain(&self, context: &mut UpdateContext<'gc>) -> Domain<'gc> {
match self {
Method::Native(_) => context.avm2.playerglobals_domain(),
Method::Bytecode(bm) => bm.translation_unit().domain(),
}
}
} }

View File

@ -305,6 +305,25 @@ fn has_simple_scope_structure(
true true
} }
fn try_resolve_method_return_type<'gc>(
vtable: &VTable<'gc>,
disp_id: u32,
activation: &mut Activation<'_, 'gc>,
) -> Option<Class<'gc>> {
if let Some(target_method) = vtable.get_method(disp_id) {
let target_return_type = &target_method.return_type();
if !target_return_type.has_lazy_component() && !target_return_type.is_any_name() {
if let Some(target_ret_class) = target_method
.domain(activation.context)
.get_class(activation.context, target_return_type)
{
return Some(target_ret_class);
}
}
}
None
}
pub fn optimize<'gc>( pub fn optimize<'gc>(
activation: &mut Activation<'_, 'gc>, activation: &mut Activation<'_, 'gc>,
method: &BytecodeMethod<'gc>, method: &BytecodeMethod<'gc>,
@ -1097,6 +1116,12 @@ pub fn optimize<'gc>(
index: disp_id, index: disp_id,
push_return_value: true, push_return_value: true,
}; };
if let Some(ret_type) =
try_resolve_method_return_type(&vtable, disp_id, activation)
{
stack_push_done = true;
stack.push_class(ret_type);
}
} }
_ => {} _ => {}
} }
@ -1318,6 +1343,12 @@ pub fn optimize<'gc>(
index: disp_id, index: disp_id,
push_return_value: true, push_return_value: true,
}; };
if let Some(ret_type) =
try_resolve_method_return_type(&vtable, disp_id, activation)
{
stack_push_done = true;
stack.push_class(ret_type);
}
} }
Some(Property::Slot { slot_id }) Some(Property::Slot { slot_id })
| Some(Property::ConstSlot { slot_id }) => { | Some(Property::ConstSlot { slot_id }) => {