@@ -646,42 +646,34 @@ pub fn optimize<'gc>(
646
646
} ;
647
647
648
648
// 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( ) ] ;
650
650
651
651
// Block #0 is the entry block
652
652
let mut worklist = Vec :: new ( ) ;
653
653
worklist. push ( ( 0 , entry_state. clone ( ) ) ) ;
654
654
while let Some ( ( block_idx, provided_abstract_state) ) = worklist. pop ( ) {
655
655
let block = & block_list[ block_idx] ;
656
656
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] ;
672
658
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
+ } ;
676
672
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 ( ) ) ;
682
674
683
675
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 ) ?;
685
677
686
678
for exit in & block. exits {
687
679
match exit {
@@ -710,18 +702,12 @@ pub fn optimize<'gc>(
710
702
711
703
// At this point we know the guaranteed state at every block start
712
704
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 ( ) {
714
706
let start_index = block_list[ i] . start_index ;
715
707
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" ) ;
723
709
724
- replacement_states. insert ( start_index, all_merged_state ) ;
710
+ replacement_states. insert ( start_index, abstract_state ) ;
725
711
}
726
712
727
713
if activation. avm2 ( ) . optimizer_enabled ( ) {
0 commit comments