Skip to content

Commit

Permalink
Use a one-object pool and encapculate fields
Browse files Browse the repository at this point in the history
This allows multiple IRReturnJump to be in flight at once without
stepping on each other, and cleans up some direct accesses of the
jump fields.
  • Loading branch information
headius committed Dec 5, 2023
1 parent c4c331b commit cff4a23
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 11 deletions.
2 changes: 1 addition & 1 deletion core/src/main/java/org/jruby/Ruby.java
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
31 changes: 23 additions & 8 deletions core/src/main/java/org/jruby/ir/runtime/IRReturnJump.java
Original file line number Diff line number Diff line change
Expand Up @@ -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<IRReturnJump> 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() + ">";
}
}
4 changes: 2 additions & 2 deletions core/src/main/java/org/jruby/ir/runtime/IRRuntimeHelpers.java
Original file line number Diff line number Diff line change
Expand Up @@ -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<ropagating.
if (rj.isReturnToScope(currentScope)) {
if (isDebug()) System.out.println("---> Non-local Return reached target in scope: " + currentScope);
return (IRubyObject) rj.returnValue;
return (IRubyObject) rj.returnAndReset();
}

// If not, Just pass it along!
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit cff4a23

Please sign in to comment.