Skip to content

Commit 2e1baa2

Browse files
Lord-McSweeneyLord-McSweeney
authored andcommitted
avm2: Change worklist/block handling algorithm to improve optimizer performance on complex methods
1 parent 5ff5bf0 commit 2e1baa2

File tree

1 file changed

+20
-34
lines changed

1 file changed

+20
-34
lines changed

core/src/avm2/optimizer/optimize.rs

Lines changed: 20 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -646,42 +646,34 @@ pub fn optimize<'gc>(
646646
};
647647

648648
// A Vec holding lists of possible abstract states, indexed by block index
649-
let mut abstract_states: Vec<Vec<AbstractState<'gc>>> = vec![Vec::new(); block_list.len()];
649+
let mut abstract_states: Vec<Option<AbstractState<'gc>>> = vec![None; block_list.len()];
650650

651651
// Block #0 is the entry block
652652
let mut worklist = Vec::new();
653653
worklist.push((0, entry_state.clone()));
654654
while let Some((block_idx, provided_abstract_state)) = worklist.pop() {
655655
let block = &block_list[block_idx];
656656

657-
let known_abstract_states = &mut abstract_states[block_idx];
658-
if !known_abstract_states
659-
.iter()
660-
.any(|s| s.eq(&provided_abstract_state))
661-
{
662-
// If a predecessor of this block left us off with a different abstract
663-
// state than any we've encountered so far, we'll re-verify the block
664-
// with the new state. Push `provided_abstract_state` to
665-
// `known_abstract_states` to mark that we've checked it.
666-
known_abstract_states.push(provided_abstract_state);
667-
} else {
668-
// If we encountered a state we've already verified, no need to
669-
// verify again; move on to the next worklist entry
670-
continue;
671-
}
657+
let known_abstract_state = &mut abstract_states[block_idx];
672658

673-
// We know every abstract state that could possibly end up here, but
674-
// when running the abstract optimizer, we need to give it a state
675-
// that is all of the abstract states that could be here merged into one
659+
let used_entry_state = if let Some(known_abstract_state) = known_abstract_state {
660+
let merged_state =
661+
provided_abstract_state.merged_with(activation, known_abstract_state)?;
662+
if merged_state.eq(known_abstract_state) {
663+
// We've already verified that this state works, no need to run it again
664+
continue;
665+
} else {
666+
merged_state
667+
}
668+
} else {
669+
// We don't have any state in the state list yet, so we use the provided one
670+
provided_abstract_state
671+
};
676672

677-
// This is guaranteed to have at least one entry because we just pushed to it
678-
let mut all_merged_state = known_abstract_states[0].clone();
679-
for abstract_state in known_abstract_states.iter().skip(1) {
680-
all_merged_state = all_merged_state.merged_with(activation, abstract_state)?;
681-
}
673+
*known_abstract_state = Some(used_entry_state.clone());
682674

683675
let resulting_state =
684-
abstract_interpret_ops(activation, block.ops, all_merged_state, None, &types, false)?;
676+
abstract_interpret_ops(activation, block.ops, used_entry_state, None, &types, false)?;
685677

686678
for exit in &block.exits {
687679
match exit {
@@ -710,18 +702,12 @@ pub fn optimize<'gc>(
710702

711703
// At this point we know the guaranteed state at every block start
712704
let mut replacement_states = HashMap::with_capacity(block_list.len());
713-
for (i, abstract_states) in abstract_states.into_iter().enumerate() {
705+
for (i, abstract_state) in abstract_states.into_iter().enumerate() {
714706
let start_index = block_list[i].start_index;
715707

716-
let mut all_merged_state = abstract_states
717-
.get(0)
718-
.expect("Abstract optimizer should have visited every block")
719-
.clone();
720-
for abstract_state in abstract_states.iter().skip(1) {
721-
all_merged_state = all_merged_state.merged_with(activation, abstract_state)?;
722-
}
708+
let abstract_state = abstract_state.expect("Every block should be visited");
723709

724-
replacement_states.insert(start_index, all_merged_state);
710+
replacement_states.insert(start_index, abstract_state);
725711
}
726712

727713
if activation.avm2().optimizer_enabled() {

0 commit comments

Comments
 (0)