Skip to content

Commit

Permalink
Move things out of the loop that don't necessarily belong there
Browse files Browse the repository at this point in the history
  • Loading branch information
szegedi committed Jul 4, 2024
1 parent e06b83b commit e76a43a
Showing 1 changed file with 66 additions and 58 deletions.
124 changes: 66 additions & 58 deletions rhino/src/main/java/org/mozilla/javascript/Interpreter.java
Original file line number Diff line number Diff line change
Expand Up @@ -1778,55 +1778,12 @@ private static Object interpretLoop(Context cx, CallFrame frame, Object throwabl
// arrows, lambdas, bound functions, call/apply, and
// no-such-method-handler in order to make a best-effort to keep
// them in this interpreter loop so continuations keep working.
for (; ; ) {
// When an interpreted function is encountered, install it
// as the current function.
if (fun instanceof InterpretedFunction) {
InterpretedFunction ifun = (InterpretedFunction) fun;
if (frame.fnOrScript.securityDomain
== ifun.securityDomain) {
CallFrame callParentFrame = frame;
if (op == Icode_TAIL_CALL) {
// In principle tail call can re-use the current
// frame and its stack arrays but it is hard to
// do properly. Any exceptions that can legally
// happen during frame re-initialization
// including StackOverflowException during
// innocent looking System.arraycopy may leave
// the current frame data corrupted leading to
// undefined behaviour in the catch code below
// that unwinds JS stack on exceptions. Then
// there is issue about frame release end
// exceptions there. To avoid frame allocation a
// released frame can be cached for re-use which
// would also benefit non-tail calls but it is
// not clear that this caching would gain in
// performance due to potentially bad
// interaction with GC.
callParentFrame = frame.parentFrame;
// Release the current frame. See Bug #344501 to
// see why it is being done here.
exitFrame(cx, frame, null);
}
CallFrame calleeFrame =
initFrame(
cx,
calleeScope,
funThisObj,
stack,
sDbl,
stackTop + 2,
indexReg,
ifun,
callParentFrame);
if (op != Icode_TAIL_CALL) {
frame.savedStackTop = stackTop;
frame.savedCallOp = op;
}
frame = calleeFrame;
continue StateLoop;
}
} else if (fun instanceof ArrowFunction) {
// The loop initializer and condition are formulated so that
// they short-circuit the loop if the function is already an
// interpreted function, which should be the majority of cases.
for (boolean notInt = !(fun instanceof InterpretedFunction);
notInt; ) {
if (fun instanceof ArrowFunction) {
ArrowFunction afun = (ArrowFunction) fun;
fun = afun.getTargetFunction();
funThisObj = afun.getCallThis(cx);
Expand Down Expand Up @@ -1864,13 +1821,6 @@ private static Object interpretLoop(Context cx, CallFrame frame, Object throwabl
continue;
} else if (fun instanceof IdFunctionObject) {
IdFunctionObject ifun = (IdFunctionObject) fun;
if (NativeContinuation.isContinuationConstructor(
ifun)) {
frame.stack[stackTop] =
captureContinuation(
cx, frame.parentFrame, false);
continue Loop;
}
// Bug 405654 -- make the best effort to keep
// Function.apply and Function.call within this
// interpreter loop invocation
Expand Down Expand Up @@ -1952,11 +1902,59 @@ private static Object interpretLoop(Context cx, CallFrame frame, Object throwabl

// We reached here without any of the continue statements
// triggering. Current function is something that we can't
// peel back further, just continue after the loop with an
// ordinary call.
// peel back further.
break;
}

if (fun instanceof InterpretedFunction) {
InterpretedFunction ifun = (InterpretedFunction) fun;
if (frame.fnOrScript.securityDomain
== ifun.securityDomain) {
CallFrame callParentFrame = frame;
if (op == Icode_TAIL_CALL) {
// In principle tail call can re-use the current
// frame and its stack arrays but it is hard to
// do properly. Any exceptions that can legally
// happen during frame re-initialization including
// StackOverflowException during innocent looking
// System.arraycopy may leave the current frame
// data corrupted leading to undefined behaviour
// in the catch code bellow that unwinds JS stack
// on exceptions. Then there is issue about frame
// release
// end exceptions there.
// To avoid frame allocation a released frame
// can be cached for re-use which would also benefit
// non-tail calls but it is not clear that this
// caching
// would gain in performance due to potentially
// bad interaction with GC.
callParentFrame = frame.parentFrame;
// Release the current frame. See Bug #344501 to see
// why
// it is being done here.
exitFrame(cx, frame, null);
}
CallFrame calleeFrame =
initFrame(
cx,
calleeScope,
funThisObj,
stack,
sDbl,
stackTop + 2,
indexReg,
ifun,
callParentFrame);
if (op != Icode_TAIL_CALL) {
frame.savedStackTop = stackTop;
frame.savedCallOp = op;
}
frame = calleeFrame;
continue StateLoop;
}
}

if (fun instanceof NativeContinuation) {
// Jump to the captured continuation
ContinuationJump cjump;
Expand All @@ -1978,6 +1976,16 @@ private static Object interpretLoop(Context cx, CallFrame frame, Object throwabl
break withoutExceptions;
}

if (fun instanceof IdFunctionObject) {
IdFunctionObject ifun = (IdFunctionObject) fun;
if (NativeContinuation.isContinuationConstructor(ifun)) {
frame.stack[stackTop] =
captureContinuation(
cx, frame.parentFrame, false);
continue Loop;
}
}

cx.lastInterpreterFrame = frame;
frame.savedCallOp = op;
frame.savedStackTop = stackTop;
Expand Down

0 comments on commit e76a43a

Please sign in to comment.