1111import org .jruby .ir .passes .CompilerPass ;
1212import org .jruby .ir .passes .CompilerPassScheduler ;
1313import org .jruby .ir .passes .DeadCodeElimination ;
14+ import org .jruby .ir .passes .OptimizeDynScopesPass ;
1415import org .jruby .ir .dataflow .analyses .StoreLocalVarPlacementProblem ;
1516import org .jruby .ir .dataflow .analyses .LiveVariablesProblem ;
1617import org .jruby .ir .passes .UnboxingPass ;
@@ -105,6 +106,9 @@ public abstract class IRScope implements ParseResult {
105106 /** Map of name -> dataflow problem */
106107 private Map <String , DataFlowProblem > dfProbs ;
107108
109+ /** What passes have been run on this scope? */
110+ private List <CompilerPass > executedPasses ;
111+
108112 private Instr [] linearizedInstrArray ;
109113 private List <BasicBlock > linearizedBBList ;
110114 private Map <Integer , Integer > rescueMap ;
@@ -163,6 +167,8 @@ protected IRScope(IRScope s, IRScope lexicalParent) {
163167 this .scopeId = globalScopeCount .getAndIncrement ();
164168 this .relinearizeCFG = false ;
165169
170+ this .executedPasses = new ArrayList <CompilerPass >();
171+
166172 setupLexicalContainment ();
167173 }
168174
@@ -208,6 +214,8 @@ public IRScope(IRManager manager, IRScope lexicalParent, String name,
208214 this .scopeId = globalScopeCount .getAndIncrement ();
209215 this .relinearizeCFG = false ;
210216
217+ this .executedPasses = new ArrayList <CompilerPass >();
218+
211219 setupLexicalContainment ();
212220 }
213221
@@ -400,14 +408,6 @@ public boolean isNestedInClosure(IRClosure closure) {
400408 return false ;
401409 }
402410
403- public boolean hasHasOptimizedTemporaryVariables () {
404- return flags .contains (HAS_OPTIMIZED_TEMPORARY_VARIABLES );
405- }
406-
407- public void setHasOptimizedTemporaryVariables () {
408- flags .add (HAS_OPTIMIZED_TEMPORARY_VARIABLES );
409- }
410-
411411 public void setHasLoopsFlag () {
412412 flags .add (HAS_LOOPS );
413413 }
@@ -546,6 +546,10 @@ private boolean isUnsafeScope() {
546546 return unsafeScope ;
547547 }
548548
549+ public List <CompilerPass > getExecutedPasses () {
550+ return executedPasses ;
551+ }
552+
549553 private void runCompilerPasses (List <CompilerPass > passes ) {
550554 // SSS FIXME: Why is this again? Document this weirdness!
551555 // Forcibly clear out the shared eval-scope variable allocator each time this method executes
@@ -569,40 +573,28 @@ private void runCompilerPasses(List<CompilerPass> passes) {
569573
570574 CompilerPassScheduler scheduler = getManager ().schedulePasses (passes );
571575 for (CompilerPass pass : scheduler ) {
572- if (pass .previouslyRun (this ) == null ) {
573- pass .run (this );
574- }
576+ pass .run (this );
575577 }
576578
577579 if (RubyInstanceConfig .IR_UNBOXING ) {
578580 (new UnboxingPass ()).run (this );
579581 }
580582 }
581583
582- private void runDeadCodeAndVarLoadStorePasses () {
583- // For scopes that don't require a dynamic scope,
584- // inline-add lvar loads/store to tmp-var loads/stores.
584+ private void optimizeSimpleScopes () {
585+ // For safe scopes that don't require a dynamic scope,
586+ // run DCE since the analysis is less likely to be
587+ // stymied by escaped bindings.
585588 if (!isUnsafeScope () && !flags .contains (REQUIRES_DYNSCOPE )) {
586- CompilerPass pass ;
587- pass = new DeadCodeElimination ();
588- if (pass .previouslyRun (this ) == null ) {
589- pass .run (this );
590- }
591-
592- // This will run the simplified version of the pass
593- // that doesn't require dataflow analysis and hence
594- // can run on closures independent of enclosing scopes.
595- pass = new AddLocalVarLoadStoreInstructions ();
596- if (pass .previouslyRun (this ) == null ) {
597- ((AddLocalVarLoadStoreInstructions )pass ).eliminateLocalVars (this );
598- setDataFlowSolution (StoreLocalVarPlacementProblem .NAME , new StoreLocalVarPlacementProblem ());
599- setDataFlowSolution (LiveVariablesProblem .NAME , null );
600- }
589+ (new DeadCodeElimination ()).run (this );
590+ (new OptimizeDynScopesPass ()).run (this );
601591 }
602592 }
603593
604- /** Run any necessary passes to get the IR ready for interpretation */
605- public synchronized Instr [] prepareForInterpretation (boolean isLambda ) {
594+ public void initScope (boolean isLambda ) {
595+ // Reset linearization, if any exists
596+ resetLinearizationData ();
597+
606598 // Build CFG and run compiler passes, if necessary
607599 if (getCFG () == null ) {
608600 buildCFG ();
@@ -623,22 +615,35 @@ public synchronized Instr[] prepareForInterpretation(boolean isLambda) {
623615 // Run DCE and var load/store passes where applicable
624616 // But, if we have been passed in a list of passes to run
625617 // on the commandline, skip this opt.
626- runDeadCodeAndVarLoadStorePasses ();
618+ optimizeSimpleScopes ();
627619 }
620+ }
621+
622+ /** Run any necessary passes to get the IR ready for interpretation */
623+ public synchronized Instr [] prepareForInterpretation (boolean isLambda ) {
624+ initScope (isLambda );
628625
629626 checkRelinearization ();
630627
631628 if (linearizedInstrArray != null ) return linearizedInstrArray ;
632629
630+ // System.out.println("-- passes run for: " + this + " = " + java.util.Arrays.toString(executedPasses.toArray()));
631+
633632 // Linearize CFG, etc.
634633 return prepareInstructions ();
635634 }
636635
637636 /* SSS FIXME: Do we need to synchronize on this? Cache this info in a scope field? */
638637 /** Run any necessary passes to get the IR ready for compilation */
639638 public synchronized List <BasicBlock > prepareForCompilation () {
640- // Reset linearization, since we will add JIT-specific flow and instrs
641- resetLinearizationData ();
639+ // For lambdas, we need to add a global ensure block to catch
640+ // uncaught breaks and throw a LocalJumpError.
641+ //
642+ // Since we dont re-JIT a previously JIT-ted closure,
643+ // mark all closures lambdas always. But, check if there are
644+ // other smarts available to us and eliminate adding
645+ // this code to every closure there is.
646+ initScope (this instanceof IRClosure );
642647
643648 runCompilerPasses (getManager ().getJITPasses (this ));
644649
@@ -1136,10 +1141,6 @@ public void inlineMethod(IRScope method, RubyModule implClass, int classToken, B
11361141 }
11371142 }
11381143
1139- public void resetCFG () {
1140- cfg = null ;
1141- }
1142-
11431144 /* Record a begin block -- not all scope implementations can handle them */
11441145 public void recordBeginBlock (IRClosure beginBlockClosure ) {
11451146 throw new RuntimeException ("BEGIN blocks cannot be added to: " + this .getClass ().getName ());
0 commit comments