@Override public void encode(IRWriterEncoder e) { super.encode(e); e.encode(getReturnValue()); e.encode(methodName); }
@Override public void encode(IRWriterEncoder e) { super.encode(e); e.encode(getReturnValue()); e.encode(methodName); }
@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."); } }
@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(); } }
@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(); } }
@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(); }
@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(); }
protected static IRubyObject processReturnOp(ThreadContext context, Block block, Instr instr, Operation operation, DynamicScope currDynScope, Object[] temp, IRubyObject self, StaticScope currScope) { switch(operation) { // --------- Return flavored instructions -------- case RETURN: { return (IRubyObject)retrieveOp(((ReturnBase)instr).getReturnValue(), context, self, currDynScope, currScope, temp); } case BREAK: { BreakInstr bi = (BreakInstr)instr; IRubyObject rv = (IRubyObject)bi.getReturnValue().retrieve(context, self, currScope, currDynScope, temp); // This also handles breaks in lambdas -- by converting them to a return // // This assumes that scopes with break instr. have a frame / dynamic scope // pushed so that we can get to its static scope. For-loops now always have // a dyn-scope pushed onto stack which makes this work in all scenarios. return IRRuntimeHelpers.initiateBreak(context, currDynScope, rv, block); } case NONLOCAL_RETURN: { NonlocalReturnInstr ri = (NonlocalReturnInstr)instr; IRubyObject rv = (IRubyObject)retrieveOp(ri.getReturnValue(), context, self, currDynScope, currScope, temp); return IRRuntimeHelpers.initiateNonLocalReturn(context, currDynScope, block, rv); } case RETURN_OR_RETHROW_SAVED_EXC: { IRubyObject retVal = (IRubyObject) retrieveOp(((ReturnBase) instr).getReturnValue(), context, self, currDynScope, currScope, temp); return IRRuntimeHelpers.returnOrRethrowSavedException(context, retVal); } } return null; }
protected static IRubyObject processReturnOp(ThreadContext context, Block block, Instr instr, Operation operation, DynamicScope currDynScope, Object[] temp, IRubyObject self, StaticScope currScope) { switch(operation) { // --------- Return flavored instructions -------- case RETURN: { return (IRubyObject)retrieveOp(((ReturnBase)instr).getReturnValue(), context, self, currDynScope, currScope, temp); } case BREAK: { BreakInstr bi = (BreakInstr)instr; IRubyObject rv = (IRubyObject)bi.getReturnValue().retrieve(context, self, currScope, currDynScope, temp); // This also handles breaks in lambdas -- by converting them to a return // // This assumes that scopes with break instr. have a frame / dynamic scope // pushed so that we can get to its static scope. For-loops now always have // a dyn-scope pushed onto stack which makes this work in all scenarios. return IRRuntimeHelpers.initiateBreak(context, currDynScope, rv, block); } case NONLOCAL_RETURN: { NonlocalReturnInstr ri = (NonlocalReturnInstr)instr; IRubyObject rv = (IRubyObject)retrieveOp(ri.getReturnValue(), context, self, currDynScope, currScope, temp); return IRRuntimeHelpers.initiateNonLocalReturn(context, currDynScope, block, rv); } case RETURN_OR_RETHROW_SAVED_EXC: { IRubyObject retVal = (IRubyObject) retrieveOp(((ReturnBase) instr).getReturnValue(), context, self, currDynScope, currScope, temp); return IRRuntimeHelpers.returnOrRethrowSavedException(context, retVal); } } return null; }
IRubyObject rv = (IRubyObject)retrieveOp(ri.getReturnValue(), context, self, currDynScope, temp); ipc = n;
IRubyObject rv = (IRubyObject)retrieveOp(ri.getReturnValue(), context, self, currDynScope, temp); ipc = n;