@Override public Instr cloneForInlining(InlinerInfo ii) { return new NonlocalReturnInstr(returnValue.cloneForInlining(ii), methodToReturnFrom); }
@Override public Instr cloneForInlining(InlinerInfo ii) { return new NonlocalReturnInstr(returnValue.cloneForInlining(ii), methodToReturnFrom); }
public static NonlocalReturnInstr decode(IRReaderDecoder d) { return new NonlocalReturnInstr(d.decodeOperand(), d.decodeSymbol()); }
public static NonlocalReturnInstr decode(IRReaderDecoder d) { return new NonlocalReturnInstr(d.decodeOperand(), d.decodeSymbol()); }
@Override public Instr cloneForInlinedScope(InlinerInfo ii) { if (ii.getInlineHostScope() == methodToReturnFrom) { // Convert to a regular return instruction return new NonlocalReturnInstr(returnValue.cloneForInlining(ii)); } else { return cloneForInlining(ii); } }
@Override public Instr cloneForInlinedScope(InlinerInfo ii) { if (ii.getInlineHostScope() == methodToReturnFrom) { // Convert to a regular return instruction return new NonlocalReturnInstr(returnValue.cloneForInlining(ii)); } else { return cloneForInlining(ii); } }
@Override public Instr clone(CloneInfo info) { if (info instanceof SimpleCloneInfo) return new NonlocalReturnInstr(getReturnValue().cloneForInlining(info), methodName); InlineCloneInfo ii = (InlineCloneInfo) info; if (ii.isClosure()) { if (ii.getHostScope() instanceof IRMethod) { // Lexically contained non-local returns can return directly if the live in the method they are inlining to. if (((InlineCloneInfo) info).getScopeBeingInlined().isScopeContainedBy(ii.getHostScope())) { return new ReturnInstr(getReturnValue().cloneForInlining(ii)); } // Treat like inlining of a regular method-return (note: a jump is added to exit so this copy // actually ends up being the methods return value). Variable v = ii.getCallResultVariable(); return v == null ? null : new CopyInstr(v, getReturnValue().cloneForInlining(ii)); } return new NonlocalReturnInstr(getReturnValue().cloneForInlining(ii), methodName); } else { throw new UnsupportedOperationException("Nonlocal returns shouldn't show up outside closures."); } }
@Override public Instr clone(CloneInfo info) { if (info instanceof SimpleCloneInfo) return new NonlocalReturnInstr(getReturnValue().cloneForInlining(info), methodName); InlineCloneInfo ii = (InlineCloneInfo) info; if (ii.isClosure()) { if (ii.getHostScope() instanceof IRMethod) { // Lexically contained non-local returns can return directly if the live in the method they are inlining to. if (((InlineCloneInfo) info).getScopeBeingInlined().isScopeContainedBy(ii.getHostScope())) { return new ReturnInstr(getReturnValue().cloneForInlining(ii)); } // Treat like inlining of a regular method-return (note: a jump is added to exit so this copy // actually ends up being the methods return value). Variable v = ii.getCallResultVariable(); return v == null ? null : new CopyInstr(v, getReturnValue().cloneForInlining(ii)); } return new NonlocalReturnInstr(getReturnValue().cloneForInlining(ii), methodName); } else { throw new UnsupportedOperationException("Nonlocal returns shouldn't show up outside closures."); } }
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; }
public Operand buildReturn(ReturnNode returnNode) { Operand retVal = build(returnNode.getValueNode()); if (scope instanceof IRClosure) { // Closures return behavior has several cases (which depend on runtime state): // 1. closure in method (return). !method (error) except if in define_method (return) // 2. lambda (return) [dynamic] // FIXME: I believe ->() can be static and omit LJE check. // 3. migrated closure (LJE) [dynamic] // 4. eval/for (return) [static] boolean definedWithinMethod = scope.getNearestMethod() != null; if (!(scope instanceof IREvalScript) && !(scope instanceof IRFor)) addInstr(new CheckForLJEInstr(definedWithinMethod)); addInstr(new NonlocalReturnInstr(retVal, definedWithinMethod ? scope.getNearestMethod().getName() : manager.runtime.newSymbol("--none--"))); } else if (scope.isModuleBody()) { IRMethod sm = scope.getNearestMethod(); // Cannot return from top-level module bodies! if (sm == null) addInstr(new ThrowExceptionInstr(IRException.RETURN_LocalJumpError)); if (sm != null) addInstr(new NonlocalReturnInstr(retVal, sm.getName())); } else { retVal = processEnsureRescueBlocks(retVal); if (RubyInstanceConfig.FULL_TRACE_ENABLED) { addInstr(new TraceInstr(RubyEvent.RETURN, getName(), getFileName(), returnNode.getLine())); } 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 U_NIL; }
public Operand buildReturn(ReturnNode returnNode) { Operand retVal = build(returnNode.getValueNode()); if (scope instanceof IRClosure) { // Closures return behavior has several cases (which depend on runtime state): // 1. closure in method (return). !method (error) except if in define_method (return) // 2. lambda (return) [dynamic] // FIXME: I believe ->() can be static and omit LJE check. // 3. migrated closure (LJE) [dynamic] // 4. eval/for (return) [static] boolean definedWithinMethod = scope.getNearestMethod() != null; if (!(scope instanceof IREvalScript) && !(scope instanceof IRFor)) addInstr(new CheckForLJEInstr(definedWithinMethod)); addInstr(new NonlocalReturnInstr(retVal, definedWithinMethod ? scope.getNearestMethod().getName() : manager.runtime.newSymbol("--none--"))); } else if (scope.isModuleBody()) { IRMethod sm = scope.getNearestMethod(); // Cannot return from top-level module bodies! if (sm == null) addInstr(new ThrowExceptionInstr(IRException.RETURN_LocalJumpError)); if (sm != null) addInstr(new NonlocalReturnInstr(retVal, sm.getName())); } else { retVal = processEnsureRescueBlocks(retVal); if (RubyInstanceConfig.FULL_TRACE_ENABLED) { addInstr(new TraceInstr(RubyEvent.RETURN, getName(), getFileName(), returnNode.getLine())); } 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 U_NIL; }