Skip to content

Commit

Permalink
avm2: Handle lazy multinames in optimizer
Browse files Browse the repository at this point in the history
  • Loading branch information
Lord-McSweeney authored and Lord-McSweeney committed Feb 24, 2024
1 parent 9f25a3a commit d2971e8
Showing 1 changed file with 46 additions and 39 deletions.
85 changes: 46 additions & 39 deletions core/src/avm2/optimize.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
use crate::avm2::activation::Activation;
use crate::avm2::class::Class;
use crate::avm2::method::BytecodeMethod;
use crate::avm2::multiname::Multiname;
use crate::avm2::object::ClassObject;
use crate::avm2::op::Op;
use crate::avm2::property::Property;

use gc_arena::GcCell;
use gc_arena::{Gc, GcCell};
use std::collections::HashSet;
use swf::avm2::types::Index;

Expand Down Expand Up @@ -116,6 +117,15 @@ impl<'gc> Stack<'gc> {
self.0.pop()
}

pub fn pop_for_multiname(&mut self, multiname: Gc<'gc, Multiname<'gc>>) {
if multiname.has_lazy_name() {
self.0.pop();
}
if multiname.has_lazy_ns() {
self.0.pop();
}
}

fn popn(&mut self, count: u32) {
for _ in 0..count {
self.pop();
Expand Down Expand Up @@ -218,6 +228,23 @@ pub fn optimize<'gc>(
}

let mut stack = Stack::new();

macro_rules! stack_pop_multiname {
($index: expr) => {{
let multiname = method
.translation_unit()
// note: ideally this should be a VerifyError here or earlier
.pool_maybe_uninitialized_multiname(*$index, &mut activation.context);

if let Ok(multiname) = multiname {
stack.pop_for_multiname(multiname);
Some(multiname)
} else {
None
}
}};
}

let mut scope_stack = Stack::new();
let mut local_types = initial_local_types.clone();

Expand Down Expand Up @@ -632,12 +659,11 @@ pub fn optimize<'gc>(
}
Op::GetProperty { index: name_index } => {
let mut stack_push_done = false;

let multiname = stack_pop_multiname!(name_index);
let stack_value = stack.pop();

let multiname = method
.translation_unit()
.pool_maybe_uninitialized_multiname(*name_index, &mut activation.context);
if let Ok(multiname) = multiname {
if let Some(multiname) = multiname {
if !multiname.has_lazy_component() {
if let Some(ValueType::Class(class)) = stack_value {
if !class.inner_class_definition().read().is_interface() {
Expand Down Expand Up @@ -677,10 +703,8 @@ pub fn optimize<'gc>(
}
}
}
} else {
// Avoid handling lazy for now
stack.clear();
}
// `stack_pop_multiname` handled lazy
}

if !stack_push_done {
Expand All @@ -695,12 +719,11 @@ pub fn optimize<'gc>(
}
Op::InitProperty { index: name_index } => {
stack.pop();

let multiname = stack_pop_multiname!(name_index);
let stack_value = stack.pop();

let multiname = method
.translation_unit()
.pool_maybe_uninitialized_multiname(*name_index, &mut activation.context);
if let Ok(multiname) = multiname {
if let Some(multiname) = multiname {
if !multiname.has_lazy_component() {
if let Some(ValueType::Class(class)) = stack_value {
if !class.inner_class_definition().read().is_interface() {
Expand All @@ -713,20 +736,17 @@ pub fn optimize<'gc>(
}
}
}
} else {
// Avoid handling lazy for now
stack.clear();
}
// `stack_pop_multiname` handled lazy
}
}
Op::SetProperty { index: name_index } => {
stack.pop();

let multiname = stack_pop_multiname!(name_index);
let stack_value = stack.pop();

let multiname = method
.translation_unit()
.pool_maybe_uninitialized_multiname(*name_index, &mut activation.context);
if let Ok(multiname) = multiname {
if let Some(multiname) = multiname {
if !multiname.has_lazy_component() {
if let Some(ValueType::Class(class)) = stack_value {
if !class.inner_class_definition().read().is_interface() {
Expand All @@ -738,10 +758,8 @@ pub fn optimize<'gc>(
}
}
}
} else {
// Avoid handling lazy for now
stack.clear();
}
// `stack_pop_multiname` handled lazy
}
}
Op::Construct { num_args } => {
Expand All @@ -767,19 +785,11 @@ pub fn optimize<'gc>(
// Arguments
stack.popn(*num_args);

stack_pop_multiname!(name_index);

// Then receiver.
stack.pop();

let multiname = method
.translation_unit()
.pool_maybe_uninitialized_multiname(*name_index, &mut activation.context);
if let Ok(multiname) = multiname {
if multiname.has_lazy_component() {
// Avoid handling lazy for now
stack.clear();
}
}

// Avoid checking return value for now
stack.push_any();
}
Expand All @@ -790,13 +800,12 @@ pub fn optimize<'gc>(
// Arguments
stack.popn(*num_args);

let multiname = stack_pop_multiname!(name_index);

// Then receiver.
let stack_value = stack.pop();

let multiname = method
.translation_unit()
.pool_maybe_uninitialized_multiname(*name_index, &mut activation.context);
if let Ok(multiname) = multiname {
if let Some(multiname) = multiname {
if !multiname.has_lazy_component() {
if let Some(ValueType::Class(class)) = stack_value {
if !class.inner_class_definition().read().is_interface() {
Expand All @@ -811,10 +820,8 @@ pub fn optimize<'gc>(
}
}
}
} else {
// Avoid handling lazy for now
stack.clear();
}
// `stack_pop_multiname` handled lazy
}

// Avoid checking return value for now
Expand Down

0 comments on commit d2971e8

Please sign in to comment.