diff --git a/core/src/main/java/org/jruby/Ruby.java b/core/src/main/java/org/jruby/Ruby.java index 43a8910d1cf4..7893d4de918d 100644 --- a/core/src/main/java/org/jruby/Ruby.java +++ b/core/src/main/java/org/jruby/Ruby.java @@ -1303,7 +1303,7 @@ public IRubyObject runInterpreter(ThreadContext context, ParseResult parseResult * exit point. We still raise when jump off point is anything else since that is a bug. */ if (!ex.methodToReturnFrom.getStaticScope().getIRScope().isScriptScope()) { - System.err.println("Unexpected 'return' escaped the runtime from " + ex.returnScope.getIRScope() + " to " + ex.methodToReturnFrom.getStaticScope().getIRScope()); + System.err.println("Unexpected 'return' escaped the runtime: " + ex.toString()); System.err.println(ThreadContext.createRawBacktraceStringFromThrowable(ex, false)); Throwable t = ex; while ((t = t.getCause()) != null) { diff --git a/core/src/main/java/org/jruby/ir/runtime/IRReturnJump.java b/core/src/main/java/org/jruby/ir/runtime/IRReturnJump.java index 50ef12c0552c..455700994d93 100644 --- a/core/src/main/java/org/jruby/ir/runtime/IRReturnJump.java +++ b/core/src/main/java/org/jruby/ir/runtime/IRReturnJump.java @@ -6,39 +6,54 @@ import org.jruby.runtime.DynamicScope; public class IRReturnJump extends IRJump implements Unrescuable { - public StaticScope returnScope; - public DynamicScope methodToReturnFrom; - public Object returnValue; + private StaticScope returnScope; + private DynamicScope methodToReturnFrom; + private Object returnValue; + private boolean inUse = false; private static final ThreadLocal RETURN_JUMP = new ThreadLocal<>(); private IRReturnJump(StaticScope returnScope, DynamicScope scopeToReturnFrom, Object rv) { - reset(returnScope, scopeToReturnFrom, rv); + update(returnScope, scopeToReturnFrom, rv); } public static IRReturnJump create(StaticScope returnScope, DynamicScope scopeToReturnFrom, Object rv) { IRReturnJump jump = RETURN_JUMP.get(); - if (jump == null) { + if (jump == null || jump.inUse) { RETURN_JUMP.set(jump = new IRReturnJump(returnScope, scopeToReturnFrom, rv)); } else { - jump.reset(returnScope, scopeToReturnFrom, rv); + jump.update(returnScope, scopeToReturnFrom, rv); } return jump; } - private void reset(StaticScope returnScope, DynamicScope scopeToReturnFrom, Object rv) { + private void update(StaticScope returnScope, DynamicScope scopeToReturnFrom, Object rv) { this.methodToReturnFrom = scopeToReturnFrom; this.returnScope = returnScope; this.returnValue = rv; + this.inUse = true; + } + + public void reset() { + methodToReturnFrom = null; + returnScope = null; + returnValue = null; + inUse = false; } public boolean isReturnToScope(DynamicScope scope) { return methodToReturnFrom == scope; } + public Object returnAndReset() { + Object returnValue = this.returnValue; + reset(); + return returnValue; + } + @Override public String toString() { - return "IRReturnJump:<" + methodToReturnFrom + ":" + returnValue + ">"; + return "IRReturnJump:<" + returnScope.getIRScope() + ":" + methodToReturnFrom.getStaticScope().getIRScope() + ">"; } } diff --git a/core/src/main/java/org/jruby/ir/runtime/IRRuntimeHelpers.java b/core/src/main/java/org/jruby/ir/runtime/IRRuntimeHelpers.java index 917672419760..8b4a336dcf08 100644 --- a/core/src/main/java/org/jruby/ir/runtime/IRRuntimeHelpers.java +++ b/core/src/main/java/org/jruby/ir/runtime/IRRuntimeHelpers.java @@ -193,7 +193,7 @@ public static IRubyObject handleNonlocalReturn(DynamicScope currentScope, Object // If we are in the method scope we are supposed to return from, stop p Non-local Return reached target in scope: " + currentScope); - return (IRubyObject) rj.returnValue; + return (IRubyObject) rj.returnAndReset(); } // If not, Just pass it along! @@ -243,7 +243,7 @@ public static IRubyObject handleBreakAndReturnsInLambdas(ThreadContext context, return ((IRWrappedLambdaReturnValue) exc).returnValue; } else if (exc instanceof IRReturnJump && dynScope != null && inReturnToScope(block.type, (IRReturnJump) exc, dynScope)) { if (isDebug()) System.out.println("---> Non-local Return reached target in scope: " + dynScope); - return (IRubyObject) ((IRReturnJump) exc).returnValue; + return (IRubyObject) ((IRReturnJump) exc).returnAndReset(); } else { // Propagate the exception context.setSavedExceptionInLambda((Throwable) exc);