public void restoreException(IRScope s, IRLoop currLoop) { if (currLoop == innermostLoop) s.addInstr(new PutGlobalVarInstr("$!", savedExceptionVariable)); } }
public void restoreException(IRScope s, IRLoop currLoop) { if (currLoop == innermostLoop) s.addInstr(new PutGlobalVarInstr("$!", savedExceptionVariable)); } }
public static PutGlobalVarInstr decode(IRReaderDecoder d) { return new PutGlobalVarInstr((GlobalVariable) d.decodeOperand(), d.decodeOperand()); }
public static PutGlobalVarInstr decode(IRReaderDecoder d) { return new PutGlobalVarInstr((GlobalVariable) d.decodeOperand(), d.decodeOperand()); }
@Override public Instr cloneForInlining(InlinerInfo ii) { return new PutGlobalVarInstr(((GlobalVariable) operands[TARGET]).getName(), operands[VALUE].cloneForInlining(ii)); }
@Override public Instr cloneForInlining(InlinerInfo ii) { return new PutGlobalVarInstr(((GlobalVariable) operands[TARGET]).getName(), operands[VALUE].cloneForInlining(ii)); }
public Operand buildGlobalAsgn(GlobalAsgnNode globalAsgnNode) { Operand value = build(globalAsgnNode.getValueNode()); addInstr(new PutGlobalVarInstr(globalAsgnNode.getName(), value)); return value; }
public Operand buildGlobalAsgn(GlobalAsgnNode globalAsgnNode, IRScope s) { Operand value = build(globalAsgnNode.getValueNode(), s); s.addInstr(new PutGlobalVarInstr(globalAsgnNode.getName(), value)); return value; }
public Operand buildGlobalAsgn(GlobalAsgnNode globalAsgnNode) { Operand value = build(globalAsgnNode.getValueNode()); addInstr(new PutGlobalVarInstr(globalAsgnNode.getName(), value)); return value; }
public Operand buildGlobalAsgn(GlobalAsgnNode globalAsgnNode, IRScope s) { Operand value = build(globalAsgnNode.getValueNode(), s); s.addInstr(new PutGlobalVarInstr(globalAsgnNode.getName(), value)); return value; }
@Override public Instr clone(CloneInfo ii) { return new PutGlobalVarInstr(getTarget().getName(), getValue().cloneForInlining(ii)); }
@Override public Instr clone(CloneInfo ii) { return new PutGlobalVarInstr(getTarget().getName(), getValue().cloneForInlining(ii)); }
public Operand buildRetry(Node node, IRScope s) { // JRuby only supports retry when present in rescue blocks! // 1.9 doesn't support retry anywhere else. // Jump back to the innermost rescue block // We either find it, or we add code to throw a runtime exception if (_rescueBlockStack.empty()) { s.addInstr(new ThrowExceptionInstr(IRException.RETRY_LocalJumpError)); } else { s.addInstr(new ThreadPollInstr(true)); // Restore $! and jump back to the entry of the rescue block RescueBlockInfo rbi = _rescueBlockStack.peek(); s.addInstr(new PutGlobalVarInstr("$!", rbi.savedExceptionVariable)); s.addInstr(new JumpInstr(rbi.entryLabel)); // Retries effectively create a loop s.setHasLoopsFlag(true); } return manager.getNil(); }
public Operand buildRetry(Node node, IRScope s) { // JRuby only supports retry when present in rescue blocks! // 1.9 doesn't support retry anywhere else. // Jump back to the innermost rescue block // We either find it, or we add code to throw a runtime exception if (_rescueBlockStack.empty()) { s.addInstr(new ThrowExceptionInstr(IRException.RETRY_LocalJumpError)); } else { s.addInstr(new ThreadPollInstr(true)); // Restore $! and jump back to the entry of the rescue block RescueBlockInfo rbi = _rescueBlockStack.peek(); s.addInstr(new PutGlobalVarInstr("$!", rbi.savedExceptionVariable)); s.addInstr(new JumpInstr(rbi.entryLabel)); // Retries effectively create a loop s.setHasLoopsFlag(true); } return manager.getNil(); }
public Operand buildRetry() { // JRuby only supports retry when present in rescue blocks! // 1.9 doesn't support retry anywhere else. // SSS FIXME: We should be able to use activeEnsureBlockStack for this // But, see the code in buildRescueInternal that pushes/pops these and // the documentation for retries. There is a small ordering issue // which is preventing me from getting rid of activeRescueBlockStack // altogether! // // Jump back to the innermost rescue block // We either find it, or we add code to throw a runtime exception if (activeRescueBlockStack.empty()) { addInstr(new ThrowExceptionInstr(IRException.RETRY_LocalJumpError)); } else { addInstr(new ThreadPollInstr(true)); // Restore $! and jump back to the entry of the rescue block RescueBlockInfo rbi = activeRescueBlockStack.peek(); addInstr(new PutGlobalVarInstr(symbol("$!"), rbi.savedExceptionVariable)); addInstr(new JumpInstr(rbi.entryLabel)); // Retries effectively create a loop scope.setHasLoopsFlag(); } return manager.getNil(); }
public Operand buildRetry() { // JRuby only supports retry when present in rescue blocks! // 1.9 doesn't support retry anywhere else. // SSS FIXME: We should be able to use activeEnsureBlockStack for this // But, see the code in buildRescueInternal that pushes/pops these and // the documentation for retries. There is a small ordering issue // which is preventing me from getting rid of activeRescueBlockStack // altogether! // // Jump back to the innermost rescue block // We either find it, or we add code to throw a runtime exception if (activeRescueBlockStack.empty()) { addInstr(new ThrowExceptionInstr(IRException.RETRY_LocalJumpError)); } else { addInstr(new ThreadPollInstr(true)); // Restore $! and jump back to the entry of the rescue block RescueBlockInfo rbi = activeRescueBlockStack.peek(); addInstr(new PutGlobalVarInstr(symbol("$!"), rbi.savedExceptionVariable)); addInstr(new JumpInstr(rbi.entryLabel)); // Retries effectively create a loop scope.setHasLoopsFlag(); } return manager.getNil(); }
public static void emitJumpChain(IRScope s, Stack<EnsureBlockInfo> ebStack, IRLoop loop) { // SSS: There are 2 ways of encoding this: // 1. Jump to ensure block 1, return back here, jump ensure block 2, return back here, ... // Generates 3*n instrs. where n is the # of ensure blocks to execute // 2. Jump to ensure block 1, then to block 2, then to 3, ... // Generates n+1 instrs. where n is the # of ensure blocks to execute // Doesn't really matter all that much since we shouldn't have deep nesting of ensure blocks often // but is there a reason to go with technique 1 at all?? int n = ebStack.size(); EnsureBlockInfo[] ebArray = ebStack.toArray(new EnsureBlockInfo[n]); for (int i = n-1; i >= 0; i--) { EnsureBlockInfo ebi = ebArray[i]; // if (ebi.innermostLoop != loop) break; Label retLabel = s.getNewLabel(); if (ebi.savedGlobalException != null) { s.addInstr(new PutGlobalVarInstr("$!", ebi.savedGlobalException)); } s.addInstr(new SetReturnAddressInstr(ebi.returnAddr, retLabel)); s.addInstr(new JumpInstr(ebi.start)); s.addInstr(new LabelInstr(retLabel)); } } }
public static void emitJumpChain(IRScope s, Stack<EnsureBlockInfo> ebStack, IRLoop loop) { // SSS: There are 2 ways of encoding this: // 1. Jump to ensure block 1, return back here, jump ensure block 2, return back here, ... // Generates 3*n instrs. where n is the # of ensure blocks to execute // 2. Jump to ensure block 1, then to block 2, then to 3, ... // Generates n+1 instrs. where n is the # of ensure blocks to execute // Doesn't really matter all that much since we shouldn't have deep nesting of ensure blocks often // but is there a reason to go with technique 1 at all?? int n = ebStack.size(); EnsureBlockInfo[] ebArray = ebStack.toArray(new EnsureBlockInfo[n]); for (int i = n-1; i >= 0; i--) { EnsureBlockInfo ebi = ebArray[i]; // if (ebi.innermostLoop != loop) break; Label retLabel = s.getNewLabel(); if (ebi.savedGlobalException != null) { s.addInstr(new PutGlobalVarInstr("$!", ebi.savedGlobalException)); } s.addInstr(new SetReturnAddressInstr(ebi.returnAddr, retLabel)); s.addInstr(new JumpInstr(ebi.start)); s.addInstr(new LabelInstr(retLabel)); } } }
public Operand buildReturn(ReturnNode returnNode, IRScope s) { Operand retVal = (returnNode.getValueNode() == null) ? manager.getNil() : build(returnNode.getValueNode(), s); // Before we return, // - have to go execute all the ensure blocks if there are any. // this code also takes care of resetting "$!" // - if we dont have any ensure blocks, we have to clear "$!" if (!_ensureBlockStack.empty()) EnsureBlockInfo.emitJumpChain(s, _ensureBlockStack, null); else if (!_rescueBlockStack.empty()) s.addInstr(new PutGlobalVarInstr("$!", manager.getNil())); if (s instanceof IRClosure) { // If 'm' is a block scope, a return returns from the closest enclosing method. // If this happens to be a module body, the runtime throws a local jump error if // the closure is a proc. If the closure is a lambda, then this is just a normal // return and the static methodToReturnFrom value is ignored s.addInstr(new NonlocalReturnInstr(retVal, s.getNearestMethod())); } else if (s.isModuleBody()) { IRMethod sm = s.getNearestMethod(); // Cannot return from top-level module bodies! if (sm == null) s.addInstr(new ThrowExceptionInstr(IRException.RETURN_LocalJumpError)); else s.addInstr(new NonlocalReturnInstr(retVal, sm)); } else { s.addInstr(new ReturnInstr(retVal)); } // The value of the return itself in the containing expression can never be used because of control-flow reasons. // The expression that uses this result can never be executed beyond the return and hence the value itself is just // a placeholder operand. return UnexecutableNil.U_NIL; }
public Operand buildReturn(ReturnNode returnNode, IRScope s) { Operand retVal = (returnNode.getValueNode() == null) ? manager.getNil() : build(returnNode.getValueNode(), s); // Before we return, // - have to go execute all the ensure blocks if there are any. // this code also takes care of resetting "$!" // - if we dont have any ensure blocks, we have to clear "$!" if (!_ensureBlockStack.empty()) EnsureBlockInfo.emitJumpChain(s, _ensureBlockStack, null); else if (!_rescueBlockStack.empty()) s.addInstr(new PutGlobalVarInstr("$!", manager.getNil())); if (s instanceof IRClosure) { // If 'm' is a block scope, a return returns from the closest enclosing method. // If this happens to be a module body, the runtime throws a local jump error if // the closure is a proc. If the closure is a lambda, then this is just a normal // return and the static methodToReturnFrom value is ignored s.addInstr(new NonlocalReturnInstr(retVal, s.getNearestMethod())); } else if (s.isModuleBody()) { IRMethod sm = s.getNearestMethod(); // Cannot return from top-level module bodies! if (sm == null) s.addInstr(new ThrowExceptionInstr(IRException.RETURN_LocalJumpError)); else s.addInstr(new NonlocalReturnInstr(retVal, sm)); } else { s.addInstr(new ReturnInstr(retVal)); } // The value of the return itself in the containing expression can never be used because of control-flow reasons. // The expression that uses this result can never be executed beyond the return and hence the value itself is just // a placeholder operand. return UnexecutableNil.U_NIL; }