@@ -186,31 +186,19 @@ protected int currentLine() {
186186 */
187187 protected Operand buildEnsureInternal (U body , U elseNode , U [] exceptions , U rescueBody , X optRescue , boolean isModifier ,
188188 U ensureNode , boolean isRescue , U reference ) {
189- // Save $!
190- final Variable savedGlobalException = temp ();
191- addInstr (new GetGlobalVariableInstr (savedGlobalException , symbol ("$!" )));
189+ var savedGlobalException = addResultInstr (new GetGlobalVariableInstr (temp (), symbol ("$!" )));
192190
193- // ------------ Build the body of the ensure block ------------
194- //
195191 // The ensure code is built first so that when the protected body is being built,
196192 // the ensure code can be cloned at break/next/return sites in the protected body.
197-
198- // Push a new ensure block node onto the stack of ensure bodies being built
199- // The body's instructions are stashed and emitted later.
200193 EnsureBlockInfo ebi = new EnsureBlockInfo (scope , getCurrentLoop (), activeRescuers .peek (), currentLine () + 1 );
201194
202- // Record $! save var if we had a non-empty rescue node.
203- // $! will be restored from it where required.
195+ /// // ENEBO: If this is ensure it won't save $! if it is empty ensure what does it need to do? It needs a
196+ // path to catch and rethrow
197+ // Rescue will change $! but we need to restore $! later.
204198 if (isRescue ) ebi .savedGlobalException = savedGlobalException ;
205199
206- Operand ensureRetVal ;
207- if (ensureNode != null ) {
208- ensureBodyBuildStack .push (ebi );
209- ensureRetVal = build (ensureNode );
210- ensureBodyBuildStack .pop ();
211- } else {
212- ensureRetVal = nil ();
213- }
200+ // Record body of ensure and push to ensure body stack if there is an actual ensure body.
201+ Operand ensureRetVal = processEnsureBody (ensureNode , ebi );
214202
215203 // ------------ Build the protected region ------------
216204 activeEnsureBlockStack .push (ebi );
@@ -221,7 +209,6 @@ protected Operand buildEnsureInternal(U body, U elseNode, U[] exceptions, U resc
221209 activeRescuers .push (ebi .ensureRescue );
222210
223211 // Generate IR for code being protected
224- Variable ensureExprValue = temp ();
225212 Operand rv ;
226213 if (isRescue ) {
227214 rv = buildRescueInternal (body , elseNode , exceptions , rescueBody , optRescue , isModifier , ebi , reference );
@@ -237,6 +224,7 @@ protected Operand buildEnsureInternal(U body, U elseNode, U[] exceptions, U resc
237224 // (vs. returning from protected body)
238225 boolean isEnsureExpr = ensureNode != null && rv != U_NIL && !isRescue ;
239226
227+ Variable ensureExprValue = temp ();
240228 // Clone the ensure body and jump to the end
241229 if (isEnsureExpr ) {
242230 addInstr (new CopyInstr (ensureExprValue , rv ));
@@ -271,6 +259,18 @@ protected Operand buildEnsureInternal(U body, U elseNode, U[] exceptions, U resc
271259 return isEnsureExpr ? ensureExprValue : rv ;
272260 }
273261
262+ private Operand processEnsureBody (U ensureNode , EnsureBlockInfo ebi ) {
263+ Operand ensureRetVal ;
264+ if (ensureNode != null ) {
265+ ensureBodyBuildStack .push (ebi );
266+ ensureRetVal = build (ensureNode );
267+ ensureBodyBuildStack .pop ();
268+ } else {
269+ ensureRetVal = nil ();
270+ }
271+ return ensureRetVal ;
272+ }
273+
274274 public InterpreterContext buildEvalRoot (ParseResult rootNode ) {
275275 executesOnce = false ;
276276 coverageMode = rootNode .getCoverageMode ();
@@ -2519,7 +2519,6 @@ protected Operand buildRedo(int line) {
25192519 protected void buildRescueBodyInternal (U [] exceptions , U body , X consequent , Variable rv , Variable exc , Label endLabel ,
25202520 U reference ) {
25212521 // Compare and branch as necessary!
2522- Label uncaughtLabel = getNewLabel ("MISSED" );
25232522 Label caughtLabel = getNewLabel ("RESCUE" );
25242523 if (exceptions == null || exceptions .length == 0 ) {
25252524 outputExceptionCheck (getManager ().getStandardError (), exc , caughtLabel );
@@ -2530,7 +2529,6 @@ protected void buildRescueBodyInternal(U[] exceptions, U body, X consequent, Var
25302529 }
25312530
25322531 // Uncaught exception -- build other rescue nodes or rethrow!
2533- addInstr (new LabelInstr (uncaughtLabel ));
25342532 if (consequent != null ) {
25352533 buildRescueBodyInternal (exceptionNodesFor (consequent ), bodyFor (consequent ), optRescueFor (consequent ), rv ,
25362534 exc , endLabel , referenceFor (consequent ));
@@ -2615,16 +2613,17 @@ protected Operand buildRescueInternal(U bodyNode, U elseNode, U[] exceptions, U
26152613 boolean needsBacktrace = !canBacktraceBeRemoved (exceptions , rescueBody , optRescue , elseNode , isModifier );
26162614
26172615 // Labels marking start, else, end of the begin-rescue(-ensure)-end block
2618- Label rBeginLabel = getNewLabel ();
2619- Label rEndLabel = ensure .end ;
2620- Label rescueLabel = getNewLabel ("RESC_TEST" ); // Label marking start of the first rescue code.
2616+ int line = currentLine () + 1 ;
2617+ Label beginLabel = getNewLabel ("BEGIN_@" + line );
2618+ Label endLabel = ensure .end ;
2619+ Label rescueTestLabel = getNewLabel ("RESCUE_TEST_@" + line ); // Label marking start of the first rescue code.
26212620 ensure .needsBacktrace = needsBacktrace ;
26222621
2623- addInstr (new LabelInstr (rBeginLabel ));
2622+ addInstr (new LabelInstr (beginLabel ));
26242623
26252624 // Placeholder rescue instruction that tells rest of the compiler passes the boundaries of the rescue block.
2626- addInstr (new ExceptionRegionStartMarkerInstr (rescueLabel ));
2627- activeRescuers .push (rescueLabel );
2625+ addInstr (new ExceptionRegionStartMarkerInstr (rescueTestLabel ));
2626+ activeRescuers .push (rescueTestLabel );
26282627 addInstr (getManager ().needsBacktrace (needsBacktrace ));
26292628
26302629 // Body
@@ -2659,7 +2658,7 @@ protected Operand buildRescueInternal(U bodyNode, U elseNode, U[] exceptions, U
26592658 //
26602659 // The retry should jump to 1, not 2.
26612660 // If we push the rescue block before building the body, we will jump to 2.
2662- RescueBlockInfo rbi = new RescueBlockInfo (rBeginLabel , ensure .savedGlobalException );
2661+ RescueBlockInfo rbi = new RescueBlockInfo (beginLabel , ensure .savedGlobalException );
26632662 activeRescueBlockStack .push (rbi );
26642663
26652664 if (tmp != U_NIL ) {
@@ -2669,7 +2668,7 @@ protected Operand buildRescueInternal(U bodyNode, U elseNode, U[] exceptions, U
26692668 // - If we dont have any ensure blocks, simply jump to the end of the rescue block
26702669 // - If we do, execute the ensure code.
26712670 ensure .cloneIntoHostScope (this );
2672- addInstr (new JumpInstr (rEndLabel ));
2671+ addInstr (new JumpInstr (endLabel ));
26732672 } //else {
26742673 // If the body had an explicit return, the return instruction IR build takes care of setting
26752674 // up execution of all necessary ensure blocks. So, nothing to do here!
@@ -2681,7 +2680,7 @@ protected Operand buildRescueInternal(U bodyNode, U elseNode, U[] exceptions, U
26812680 //}
26822681
26832682 // Start of rescue logic
2684- addInstr (new LabelInstr (rescueLabel ));
2683+ addInstr (new LabelInstr (rescueTestLabel ));
26852684
26862685 // This is optimized no backtrace path so we need to reenable backtraces since we are
26872686 // exiting that region.
@@ -2691,7 +2690,7 @@ protected Operand buildRescueInternal(U bodyNode, U elseNode, U[] exceptions, U
26912690 Variable exc = addResultInstr (new ReceiveRubyExceptionInstr (temp ()));
26922691
26932692 // Build the actual rescue block(s)
2694- buildRescueBodyInternal (exceptions , rescueBody , optRescue , rv , exc , rEndLabel , reference );
2693+ buildRescueBodyInternal (exceptions , rescueBody , optRescue , rv , exc , endLabel , reference );
26952694
26962695 activeRescueBlockStack .pop ();
26972696 return rv ;
0 commit comments