@Override public Instr cloneForInlining(InlinerInfo ii) { return new NonlocalReturnInstr(returnValue.cloneForInlining(ii), methodToReturnFrom); }
@Override public void encode(IRWriterEncoder e) { super.encode(e); e.encode(getReturnValue()); e.encode(methodName); }
@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 String toString() { return getOperation() + "(" + returnValue + ", <" + (methodToReturnFrom == null ? "-NULL-" : methodToReturnFrom.getName()) + ">" + ")"; }
case MASGN_REST: return RestArgMultipleAsgnInstr.decode(this); case MATCH: return MatchInstr.decode(this); case NONLOCAL_RETURN: return NonlocalReturnInstr.decode(this); case NOP: return NopInstr.NOP; case NORESULT_CALL:
@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 String toString() { return getOperation() + "(" + returnValue + ", <" + (methodToReturnFrom == null ? "-NULL-" : methodToReturnFrom.getName()) + ">" + ")"; }
case MASGN_REST: return RestArgMultipleAsgnInstr.decode(this); case MATCH: return MatchInstr.decode(this); case NONLOCAL_RETURN: return NonlocalReturnInstr.decode(this); case NOP: return NopInstr.NOP; case NORESULT_CALL:
@Override public void encode(IRWriterEncoder e) { super.encode(e); e.encode(getReturnValue()); e.encode(methodName); }
@Override public Instr cloneForInlining(InlinerInfo ii) { return new NonlocalReturnInstr(returnValue.cloneForInlining(ii), methodToReturnFrom); }
@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 void NonlocalReturnInstr(NonlocalReturnInstr returninstr) { if (this.currentScope instanceof IRClosure) { /* generate run-time call to check non-local-return, errors, etc */ SkinnyMethodAdapter a = jvm.method().adapter; a.aload(0); // 1. ThreadContext a.aload(1); // 2. current scope // 3. ref. to returnInstr.methodToReturnFrom visit(returninstr.getReturnValue()); // 4. return value // boolean about whether we are in a closure or not // call to handle non-local return } else if (returninstr.methodToReturnFrom != null) { // methodtoReturnFrom will not be null for explicit returns from class/module/sclass bodies /* throw IR-return-jump */ } else { visit(returninstr.getReturnValue()); jvm.method().returnValue(); } }
public static NonlocalReturnInstr decode(IRReaderDecoder d) { return new NonlocalReturnInstr(d.decodeOperand(), d.decodeSymbol()); }
@Override public void NonlocalReturnInstr(NonlocalReturnInstr returninstr) { if (this.currentScope instanceof IRClosure) { /* generate run-time call to check non-local-return, errors, etc */ SkinnyMethodAdapter a = jvm.method().adapter; a.aload(0); // 1. ThreadContext a.aload(1); // 2. current scope // 3. ref. to returnInstr.methodToReturnFrom visit(returninstr.getReturnValue()); // 4. return value // boolean about whether we are in a closure or not // call to handle non-local return } else if (returninstr.methodToReturnFrom != null) { // methodtoReturnFrom will not be null for explicit returns from class/module/sclass bodies /* throw IR-return-jump */ } else { visit(returninstr.getReturnValue()); jvm.method().returnValue(); } }
public static NonlocalReturnInstr decode(IRReaderDecoder d) { return new NonlocalReturnInstr(d.decodeOperand(), d.decodeSymbol()); }
@Override public void NonlocalReturnInstr(NonlocalReturnInstr returninstr) { jvmMethod().loadContext(); jvmLoadLocal(DYNAMIC_SCOPE); jvmMethod().loadSelfBlock(); visit(returninstr.getReturnValue()); jvmMethod().invokeIRHelper("initiateNonLocalReturn", sig(IRubyObject.class, ThreadContext.class, DynamicScope.class, Block.class, IRubyObject.class)); jvmMethod().returnValue(); }
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; }
@Override public void NonlocalReturnInstr(NonlocalReturnInstr returninstr) { jvmMethod().loadContext(); jvmLoadLocal(DYNAMIC_SCOPE); jvmMethod().loadSelfBlock(); visit(returninstr.getReturnValue()); jvmMethod().invokeIRHelper("initiateNonLocalReturn", sig(IRubyObject.class, ThreadContext.class, DynamicScope.class, Block.class, IRubyObject.class)); jvmMethod().returnValue(); }
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; }