@Override public Instr clone(CloneInfo ii) { if (ii instanceof SimpleCloneInfo) return new ThreadPollInstr(onBackEdge); // Get rid of non-back-edge thread-poll instructions when scopes are inlined return onBackEdge ? new ThreadPollInstr(onBackEdge) : null; }
@Override public Instr clone(CloneInfo ii) { if (ii instanceof SimpleCloneInfo) return new ThreadPollInstr(onBackEdge); // Get rid of non-back-edge thread-poll instructions when scopes are inlined return onBackEdge ? new ThreadPollInstr(onBackEdge) : null; }
public static ThreadPollInstr decode(IRReaderDecoder d) { return new ThreadPollInstr(d.decodeBoolean()); }
public static ThreadPollInstr decode(IRReaderDecoder d) { return new ThreadPollInstr(d.decodeBoolean()); }
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 Operand buildNext(final NextNode nextNode, IRScope s) { IRLoop currLoop = getCurrentLoop(); Operand rv = (nextNode.getValueNode() == null) ? manager.getNil() : build(nextNode.getValueNode(), s); // If we have ensure blocks, have to run those first! if (!_ensureBlockStack.empty()) EnsureBlockInfo.emitJumpChain(s, _ensureBlockStack, currLoop); else if (!_rescueBlockStack.empty()) _rescueBlockStack.peek().restoreException(s, currLoop); if (currLoop != null) { // If a regular loop, the next is simply a jump to the end of the iteration s.addInstr(new JumpInstr(currLoop.iterEndLabel)); } else { s.addInstr(new ThreadPollInstr(true)); // If a closure, the next is simply a return from the closure! if (s instanceof IRClosure) s.addInstr(new ReturnInstr(rv)); else s.addInstr(new ThrowExceptionInstr(IRException.NEXT_LocalJumpError)); } // Once the "next instruction" (closure-return) executes, control exits this scope return UnexecutableNil.U_NIL; }
public Operand buildNext(final NextNode nextNode, IRScope s) { IRLoop currLoop = getCurrentLoop(); Operand rv = (nextNode.getValueNode() == null) ? manager.getNil() : build(nextNode.getValueNode(), s); // If we have ensure blocks, have to run those first! if (!_ensureBlockStack.empty()) EnsureBlockInfo.emitJumpChain(s, _ensureBlockStack, currLoop); else if (!_rescueBlockStack.empty()) _rescueBlockStack.peek().restoreException(s, currLoop); if (currLoop != null) { // If a regular loop, the next is simply a jump to the end of the iteration s.addInstr(new JumpInstr(currLoop.iterEndLabel)); } else { s.addInstr(new ThreadPollInstr(true)); // If a closure, the next is simply a return from the closure! if (s instanceof IRClosure) s.addInstr(new ReturnInstr(rv)); else s.addInstr(new ThrowExceptionInstr(IRException.NEXT_LocalJumpError)); } // Once the "next instruction" (closure-return) executes, control exits this scope return UnexecutableNil.U_NIL; }
public Operand buildNext(final NextNode nextNode) { IRLoop currLoop = getCurrentLoop(); Operand rv = build(nextNode.getValueNode()); // If we have ensure blocks, have to run those first! if (!activeEnsureBlockStack.empty()) emitEnsureBlocks(currLoop); if (currLoop != null) { // If a regular loop, the next is simply a jump to the end of the iteration addInstr(new JumpInstr(currLoop.iterEndLabel)); } else { addInstr(new ThreadPollInstr(true)); // If a closure, the next is simply a return from the closure! if (scope instanceof IRClosure) { if (scope instanceof IREvalScript) { throwSyntaxError(nextNode, "Can't escape from eval with next"); } else { addInstr(new ReturnInstr(rv)); } } else { throwSyntaxError(nextNode, "Invalid next"); } } // Once the "next instruction" (closure-return) executes, control exits this scope return U_NIL; }
public Operand buildRedo(RedoNode redoNode) { // If we have ensure blocks, have to run those first! if (!activeEnsureBlockStack.empty()) { emitEnsureBlocks(getCurrentLoop()); } // If in a loop, a redo is a jump to the beginning of the loop. // If not, for closures, a redo is a jump to the beginning of the closure. // If not in a loop or a closure, it is a compile/syntax error IRLoop currLoop = getCurrentLoop(); if (currLoop != null) { addInstr(new JumpInstr(currLoop.iterStartLabel)); } else { if (scope instanceof IRClosure) { if (scope instanceof IREvalScript) { throwSyntaxError(redoNode, "Can't escape from eval with redo"); } else { addInstr(new ThreadPollInstr(true)); addInstr(new JumpInstr(((IRClosure) scope).startLabel)); } } else { throwSyntaxError(redoNode, "Invalid redo"); } } return manager.getNil(); }
public Operand buildRedo(Node node, IRScope s) { // If in a loop, a redo is a jump to the beginning of the loop. // If not, for closures, a redo is a jump to the beginning of the closure. // If not in a loop or a closure, it is a local jump error IRLoop currLoop = getCurrentLoop(); if (currLoop != null) { s.addInstr(new JumpInstr(currLoop.iterStartLabel)); } else { if (s instanceof IRClosure) { s.addInstr(new ThreadPollInstr(true)); s.addInstr(new JumpInstr(((IRClosure)s).startLabel)); } else { s.addInstr(new ThrowExceptionInstr(IRException.REDO_LocalJumpError)); } } return manager.getNil(); }
public Operand buildNext(final NextNode nextNode) { IRLoop currLoop = getCurrentLoop(); Operand rv = build(nextNode.getValueNode()); // If we have ensure blocks, have to run those first! if (!activeEnsureBlockStack.empty()) emitEnsureBlocks(currLoop); if (currLoop != null) { // If a regular loop, the next is simply a jump to the end of the iteration addInstr(new JumpInstr(currLoop.iterEndLabel)); } else { addInstr(new ThreadPollInstr(true)); // If a closure, the next is simply a return from the closure! if (scope instanceof IRClosure) { if (scope instanceof IREvalScript) { throwSyntaxError(nextNode, "Can't escape from eval with next"); } else { addInstr(new ReturnInstr(rv)); } } else { throwSyntaxError(nextNode, "Invalid next"); } } // Once the "next instruction" (closure-return) executes, control exits this scope return U_NIL; }
public Operand buildRedo(RedoNode redoNode) { // If we have ensure blocks, have to run those first! if (!activeEnsureBlockStack.empty()) { emitEnsureBlocks(getCurrentLoop()); } // If in a loop, a redo is a jump to the beginning of the loop. // If not, for closures, a redo is a jump to the beginning of the closure. // If not in a loop or a closure, it is a compile/syntax error IRLoop currLoop = getCurrentLoop(); if (currLoop != null) { addInstr(new JumpInstr(currLoop.iterStartLabel)); } else { if (scope instanceof IRClosure) { if (scope instanceof IREvalScript) { throwSyntaxError(redoNode, "Can't escape from eval with redo"); } else { addInstr(new ThreadPollInstr(true)); addInstr(new JumpInstr(((IRClosure) scope).startLabel)); } } else { throwSyntaxError(redoNode, "Invalid redo"); } } return manager.getNil(); }
public Operand buildRedo(Node node, IRScope s) { // If in a loop, a redo is a jump to the beginning of the loop. // If not, for closures, a redo is a jump to the beginning of the closure. // If not in a loop or a closure, it is a local jump error IRLoop currLoop = getCurrentLoop(); if (currLoop != null) { s.addInstr(new JumpInstr(currLoop.iterStartLabel)); } else { if (s instanceof IRClosure) { s.addInstr(new ThreadPollInstr(true)); s.addInstr(new JumpInstr(((IRClosure)s).startLabel)); } else { s.addInstr(new ThrowExceptionInstr(IRException.REDO_LocalJumpError)); } } return manager.getNil(); }
private IRMethod defineNewMethod(MethodDefNode defNode, IRScope s, boolean isInstanceMethod) { IRMethod method = new IRMethod(manager, s, defNode.getName(), isInstanceMethod, defNode.getPosition().getLine(), defNode.getScope()); method.addInstr(new ReceiveSelfInstr(getSelf(s))); // Set %current_scope = <current-scope> // Set %current_module = isInstanceMethod ? %self.metaclass : %self IRScope nearestScope = s.getNearestModuleReferencingScope(); method.addInstr(new CopyInstr(method.getCurrentScopeVariable(), new CurrentScope(nearestScope == null ? s : nearestScope))); method.addInstr(new CopyInstr(method.getCurrentModuleVariable(), new ScopeModule(nearestScope == null ? s : nearestScope))); // Build IR for arguments (including the block arg) receiveMethodArgs(defNode.getArgsNode(), method); // Thread poll on entry to method method.addInstr(new ThreadPollInstr()); // Build IR for body Node bodyNode = defNode.getBodyNode(); if (bodyNode != null) { // Create a new nested builder to ensure this gets its own IR builder state Operand rv = newIRBuilder(manager).build(bodyNode, method); if (rv != null) method.addInstr(new ReturnInstr(rv)); } else { method.addInstr(new ReturnInstr(manager.getNil())); } // If the method can receive non-local returns if (method.canReceiveNonlocalReturns()) { handleNonlocalReturnInMethod(method); } return method; }
private IRMethod defineNewMethod(MethodDefNode defNode, IRScope s, boolean isInstanceMethod) { IRMethod method = new IRMethod(manager, s, defNode.getName(), isInstanceMethod, defNode.getPosition().getLine(), defNode.getScope()); method.addInstr(new ReceiveSelfInstr(getSelf(s))); // Set %current_scope = <current-scope> // Set %current_module = isInstanceMethod ? %self.metaclass : %self IRScope nearestScope = s.getNearestModuleReferencingScope(); method.addInstr(new CopyInstr(method.getCurrentScopeVariable(), new CurrentScope(nearestScope == null ? s : nearestScope))); method.addInstr(new CopyInstr(method.getCurrentModuleVariable(), new ScopeModule(nearestScope == null ? s : nearestScope))); // Build IR for arguments (including the block arg) receiveMethodArgs(defNode.getArgsNode(), method); // Thread poll on entry to method method.addInstr(new ThreadPollInstr()); // Build IR for body Node bodyNode = defNode.getBodyNode(); if (bodyNode != null) { // Create a new nested builder to ensure this gets its own IR builder state Operand rv = newIRBuilder(manager).build(bodyNode, method); if (rv != null) method.addInstr(new ReturnInstr(rv)); } else { method.addInstr(new ReturnInstr(manager.getNil())); } // If the method can receive non-local returns if (method.canReceiveNonlocalReturns()) { handleNonlocalReturnInMethod(method); } return method; }
public Operand buildForIter(final ForNode forNode, IRScope s) { // Create a new closure context IRClosure closure = new IRClosure(manager, s, true, forNode.getPosition().getStartLine(), forNode.getScope(), Arity.procArityOf(forNode.getVarNode()), forNode.getArgumentType(), !is1_9() && !is2_0()); s.addClosure(closure); // Create a new nested builder to ensure this gets its own IR builder state // like the ensure block stack IRBuilder forBuilder = newIRBuilder(manager); // Receive self closure.addInstr(new ReceiveSelfInstr(getSelf(closure))); // Build args Node varNode = forNode.getVarNode(); if (varNode != null && varNode.getNodeType() != null) forBuilder.receiveBlockArgs(forNode, closure); // Set %current_scope = <current-scope> // Set %current_module = <current-module> closure.addInstr(new CopyInstr(closure.getCurrentScopeVariable(), new CurrentScope(closure))); closure.addInstr(new CopyInstr(closure.getCurrentModuleVariable(), new ScopeModule(closure))); // Thread poll on entry of closure closure.addInstr(new ThreadPollInstr()); // Start label -- used by redo! closure.addInstr(new LabelInstr(closure.startLabel)); // Build closure body and return the result of the closure Operand closureRetVal = forNode.getBodyNode() == null ? manager.getNil() : forBuilder.build(forNode.getBodyNode(), closure); if (closureRetVal != U_NIL) { // can be null if the node is an if node with returns in both branches. closure.addInstr(new ReturnInstr(closureRetVal)); } return new WrappedIRClosure(closure); }
public Operand buildIter(final IterNode iterNode, IRScope s) { IRClosure closure = new IRClosure(manager, s, false, iterNode.getPosition().getStartLine(), iterNode.getScope(), Arity.procArityOf(iterNode.getVarNode()), iterNode.getArgumentType(), !is1_9() && !is2_0()); s.addClosure(closure); // Create a new nested builder to ensure this gets its own IR builder state // like the ensure block stack IRBuilder closureBuilder = newIRBuilder(manager); // Receive self closure.addInstr(new ReceiveSelfInstr(getSelf(closure))); // Build args NodeType argsNodeId = BlockBody.getArgumentTypeWackyHack(iterNode); if ((iterNode.getVarNode() != null) && (argsNodeId != null)) closureBuilder.receiveBlockArgs(iterNode, closure); closureBuilder.receiveBlockClosureArg(iterNode.getBlockVarNode(), closure); // Set %current_scope = <current-scope> // Set %current_module = <current-module> closure.addInstr(new CopyInstr(closure.getCurrentScopeVariable(), new CurrentScope(closure))); closure.addInstr(new CopyInstr(closure.getCurrentModuleVariable(), new ScopeModule(closure))); // Thread poll on entry of closure closure.addInstr(new ThreadPollInstr()); // start label -- used by redo! closure.addInstr(new LabelInstr(closure.startLabel)); // Build closure body and return the result of the closure Operand closureRetVal = iterNode.getBodyNode() == null ? manager.getNil() : closureBuilder.build(iterNode.getBodyNode(), closure); if (closureRetVal != U_NIL) { // can be U_NIL if the node is an if node with returns in both branches. closure.addInstr(new ReturnInstr(closureRetVal)); } return new WrappedIRClosure(closure); }