private static Object interpretLoop()

in rhino/src/main/java/org/mozilla/javascript/Interpreter.java [1256:2804]


    private static Object interpretLoop(Context cx, CallFrame frame, Object throwable) {
        // throwable holds exception object to rethrow or catch
        // It is also used for continuation restart in which case
        // it holds ContinuationJump

        final Object DBL_MRK = DOUBLE_MARK;

        final boolean instructionCounting = cx.instructionThreshold != 0;

        String stringReg = null;
        BigInteger bigIntReg = null;
        int indexReg = -1;

        if (cx.lastInterpreterFrame != null) {
            // save the top frame from the previous interpretLoop
            // invocation on the stack
            if (cx.previousInterpreterInvocations == null) {
                cx.previousInterpreterInvocations = new ArrayDeque<>();
            }
            cx.previousInterpreterInvocations.push(cx.lastInterpreterFrame);
        }

        // When restarting continuation throwable is not null and to jump
        // to the code that rewind continuation state indexReg should be set
        // to -1.
        // With the normal call throwable == null and indexReg == -1 allows to
        // catch bugs with using indeReg to access array elements before
        // initializing indexReg.

        GeneratorState generatorState = null;
        if (throwable != null) {
            if (throwable instanceof GeneratorState) {
                generatorState = (GeneratorState) throwable;

                // reestablish this call frame
                enterFrame(cx, frame, ScriptRuntime.emptyArgs, true);
                throwable = null;
            } else if (!(throwable instanceof ContinuationJump)) {
                // It should be continuation
                Kit.codeBug();
            }
        }

        Object interpreterResult = null;
        double interpreterResultDbl = 0.0;

        StateLoop:
        for (; ; ) {
            withoutExceptions:
            try {

                if (throwable != null) {
                    // Need to return both 'frame' and 'throwable' from
                    // 'processThrowable', so just added a 'throwable'
                    // member in 'frame'.
                    frame = processThrowable(cx, throwable, frame, indexReg, instructionCounting);
                    throwable = frame.throwable;
                    frame.throwable = null;
                } else {
                    if (generatorState == null && frame.frozen) Kit.codeBug();
                }

                // Use local variables for constant values in frame
                // for faster access
                Object[] stack = frame.stack;
                double[] sDbl = frame.sDbl;
                Object[] vars = frame.varSource.stack;
                double[] varDbls = frame.varSource.sDbl;
                int[] varAttributes = frame.varSource.stackAttributes;
                byte[] iCode = frame.idata.itsICode;
                String[] strings = frame.idata.itsStringTable;
                BigInteger[] bigInts = frame.idata.itsBigIntTable;

                // Use local for stackTop as well. Since execption handlers
                // can only exist at statement level where stack is empty,
                // it is necessary to save/restore stackTop only across
                // function calls and normal returns.
                int stackTop = frame.savedStackTop;

                // Store new frame in cx which is used for error reporting etc.
                cx.lastInterpreterFrame = frame;

                Loop:
                for (; ; ) {

                    // Exception handler assumes that PC is already incremented
                    // pass the instruction start when it searches the
                    // exception handler
                    int op = iCode[frame.pc++];
                    jumplessRun:
                    {

                        // Back indent to ease implementation reading
                        switch (op) {
                            case Icode_GENERATOR:
                                {
                                    if (!frame.frozen) {
                                        // First time encountering this opcode: create new generator
                                        // object and return
                                        frame.pc--; // we want to come back here when we resume
                                        CallFrame generatorFrame = captureFrameForGenerator(frame);
                                        generatorFrame.frozen = true;
                                        if (cx.getLanguageVersion() >= Context.VERSION_ES6) {
                                            frame.result =
                                                    new ES6Generator(
                                                            frame.scope,
                                                            generatorFrame.fnOrScript,
                                                            generatorFrame);
                                        } else {
                                            frame.result =
                                                    new NativeGenerator(
                                                            frame.scope,
                                                            generatorFrame.fnOrScript,
                                                            generatorFrame);
                                        }
                                        break Loop;
                                    }
                                    // We are now resuming execution. Fall through to YIELD case.
                                }
                            // fall through...
                            case Token.YIELD:
                            case Icode_YIELD_STAR:
                                {
                                    if (!frame.frozen) {
                                        return freezeGenerator(
                                                cx,
                                                frame,
                                                stackTop,
                                                generatorState,
                                                op == Icode_YIELD_STAR);
                                    }
                                    Object obj = thawGenerator(frame, stackTop, generatorState, op);
                                    if (obj != Scriptable.NOT_FOUND) {
                                        throwable = obj;
                                        break withoutExceptions;
                                    }
                                    continue Loop;
                                }
                            case Icode_GENERATOR_END:
                                {
                                    // throw StopIteration
                                    frame.frozen = true;
                                    int sourceLine = getIndex(iCode, frame.pc);
                                    generatorState.returnedException =
                                            new JavaScriptException(
                                                    NativeIterator.getStopIterationObject(
                                                            frame.scope),
                                                    frame.idata.itsSourceFile,
                                                    sourceLine);
                                    break Loop;
                                }
                            case Icode_GENERATOR_RETURN:
                                {
                                    // throw StopIteration with the value of "return"
                                    frame.frozen = true;
                                    frame.result = stack[stackTop];
                                    frame.resultDbl = sDbl[stackTop];
                                    --stackTop;

                                    NativeIterator.StopIteration si =
                                            new NativeIterator.StopIteration(
                                                    (frame.result == DOUBLE_MARK)
                                                            ? Double.valueOf(frame.resultDbl)
                                                            : frame.result);

                                    int sourceLine = getIndex(iCode, frame.pc);
                                    generatorState.returnedException =
                                            new JavaScriptException(
                                                    si, frame.idata.itsSourceFile, sourceLine);
                                    break Loop;
                                }
                            case Token.THROW:
                                {
                                    Object value = stack[stackTop];
                                    if (value == DBL_MRK)
                                        value = ScriptRuntime.wrapNumber(sDbl[stackTop]);
                                    --stackTop;

                                    int sourceLine = getIndex(iCode, frame.pc);
                                    throwable =
                                            new JavaScriptException(
                                                    value, frame.idata.itsSourceFile, sourceLine);
                                    break withoutExceptions;
                                }
                            case Token.RETHROW:
                                {
                                    indexReg += frame.localShift;
                                    throwable = stack[indexReg];
                                    break withoutExceptions;
                                }
                            case Token.GE:
                            case Token.LE:
                            case Token.GT:
                            case Token.LT:
                                {
                                    stackTop = doCompare(frame, op, stack, sDbl, stackTop);
                                    continue Loop;
                                }
                            case Token.IN:
                            case Token.INSTANCEOF:
                                {
                                    stackTop = doInOrInstanceof(cx, op, stack, sDbl, stackTop);
                                    continue Loop;
                                }
                            case Token.EQ:
                            case Token.NE:
                                {
                                    --stackTop;
                                    boolean valBln = doEquals(stack, sDbl, stackTop);
                                    valBln ^= (op == Token.NE);
                                    stack[stackTop] = ScriptRuntime.wrapBoolean(valBln);
                                    continue Loop;
                                }
                            case Token.SHEQ:
                            case Token.SHNE:
                                {
                                    --stackTop;
                                    boolean valBln = doShallowEquals(stack, sDbl, stackTop);
                                    valBln ^= (op == Token.SHNE);
                                    stack[stackTop] = ScriptRuntime.wrapBoolean(valBln);
                                    continue Loop;
                                }
                            case Token.IFNE:
                                if (stack_boolean(frame, stackTop--)) {
                                    frame.pc += 2;
                                    continue Loop;
                                }
                                break jumplessRun;
                            case Token.IFEQ:
                                if (!stack_boolean(frame, stackTop--)) {
                                    frame.pc += 2;
                                    continue Loop;
                                }
                                break jumplessRun;
                            case Icode_IFEQ_POP:
                                if (!stack_boolean(frame, stackTop--)) {
                                    frame.pc += 2;
                                    continue Loop;
                                }
                                stack[stackTop--] = null;
                                break jumplessRun;
                            case Icode_IF_NULL_UNDEF:
                                {
                                    Object val = frame.stack[stackTop];
                                    --stackTop;
                                    if (val != null && !Undefined.isUndefined(val)) {
                                        frame.pc += 2;
                                        continue Loop;
                                    }
                                    break jumplessRun;
                                }
                            case Icode_IF_NOT_NULL_UNDEF:
                                {
                                    Object val = frame.stack[stackTop];
                                    --stackTop;
                                    if (val == null || Undefined.isUndefined(val)) {
                                        frame.pc += 2;
                                        continue Loop;
                                    }
                                    break jumplessRun;
                                }
                            case Token.GOTO:
                                break jumplessRun;
                            case Icode_GOSUB:
                                ++stackTop;
                                stack[stackTop] = DBL_MRK;
                                sDbl[stackTop] = frame.pc + 2;
                                break jumplessRun;
                            case Icode_STARTSUB:
                                if (stackTop == frame.emptyStackTop + 1) {
                                    // Call from Icode_GOSUB: store return PC address in the local
                                    indexReg += frame.localShift;
                                    stack[indexReg] = stack[stackTop];
                                    sDbl[indexReg] = sDbl[stackTop];
                                    --stackTop;
                                } else {
                                    // Call from exception handler: exception object is already
                                    // stored
                                    // in the local
                                    if (stackTop != frame.emptyStackTop) Kit.codeBug();
                                }
                                continue Loop;
                            case Icode_RETSUB:
                                {
                                    // indexReg: local to store return address
                                    if (instructionCounting) {
                                        addInstructionCount(cx, frame, 0);
                                    }
                                    indexReg += frame.localShift;
                                    Object value = stack[indexReg];
                                    if (value != DBL_MRK) {
                                        // Invocation from exception handler, restore object to
                                        // rethrow
                                        throwable = value;
                                        break withoutExceptions;
                                    }
                                    // Normal return from GOSUB
                                    frame.pc = (int) sDbl[indexReg];
                                    if (instructionCounting) {
                                        frame.pcPrevBranch = frame.pc;
                                    }
                                    continue Loop;
                                }
                            case Icode_POP:
                                stack[stackTop] = null;
                                stackTop--;
                                continue Loop;
                            case Icode_POP_RESULT:
                                frame.result = stack[stackTop];
                                frame.resultDbl = sDbl[stackTop];
                                stack[stackTop] = null;
                                --stackTop;
                                continue Loop;
                            case Icode_DUP:
                                stack[stackTop + 1] = stack[stackTop];
                                sDbl[stackTop + 1] = sDbl[stackTop];
                                stackTop++;
                                continue Loop;
                            case Icode_DUP2:
                                stack[stackTop + 1] = stack[stackTop - 1];
                                sDbl[stackTop + 1] = sDbl[stackTop - 1];
                                stack[stackTop + 2] = stack[stackTop];
                                sDbl[stackTop + 2] = sDbl[stackTop];
                                stackTop += 2;
                                continue Loop;
                            case Icode_SWAP:
                                {
                                    Object o = stack[stackTop];
                                    stack[stackTop] = stack[stackTop - 1];
                                    stack[stackTop - 1] = o;
                                    double d = sDbl[stackTop];
                                    sDbl[stackTop] = sDbl[stackTop - 1];
                                    sDbl[stackTop - 1] = d;
                                    continue Loop;
                                }
                            case Token.RETURN:
                                frame.result = stack[stackTop];
                                frame.resultDbl = sDbl[stackTop];
                                --stackTop;
                                break Loop;
                            case Token.RETURN_RESULT:
                                break Loop;
                            case Icode_RETUNDEF:
                                frame.result = undefined;
                                break Loop;
                            case Token.BITNOT:
                                {
                                    stackTop = doBitNOT(frame, stack, sDbl, stackTop);
                                    continue Loop;
                                }
                            case Token.BITAND:
                            case Token.BITOR:
                            case Token.BITXOR:
                            case Token.LSH:
                            case Token.RSH:
                                {
                                    stackTop = doBitOp(frame, op, stack, sDbl, stackTop);
                                    continue Loop;
                                }
                            case Token.URSH:
                                {
                                    double lDbl = stack_double(frame, stackTop - 1);
                                    int rIntValue = stack_int32(frame, stackTop) & 0x1F;
                                    stack[--stackTop] = DBL_MRK;
                                    sDbl[stackTop] = ScriptRuntime.toUint32(lDbl) >>> rIntValue;
                                    continue Loop;
                                }
                            case Token.POS:
                                {
                                    double rDbl = stack_double(frame, stackTop);
                                    stack[stackTop] = DBL_MRK;
                                    sDbl[stackTop] = rDbl;
                                    continue Loop;
                                }
                            case Token.NEG:
                                {
                                    Number rNum = stack_numeric(frame, stackTop);
                                    Number rNegNum = ScriptRuntime.negate(rNum);
                                    if (rNegNum instanceof BigInteger) {
                                        stack[stackTop] = rNegNum;
                                    } else {
                                        stack[stackTop] = DBL_MRK;
                                        sDbl[stackTop] = rNegNum.doubleValue();
                                    }
                                    continue Loop;
                                }
                            case Token.ADD:
                                --stackTop;
                                doAdd(stack, sDbl, stackTop, cx);
                                continue Loop;
                            case Token.SUB:
                            case Token.MUL:
                            case Token.DIV:
                            case Token.MOD:
                            case Token.EXP:
                                {
                                    stackTop = doArithmetic(frame, op, stack, sDbl, stackTop);
                                    continue Loop;
                                }
                            case Token.NOT:
                                stack[stackTop] =
                                        ScriptRuntime.wrapBoolean(!stack_boolean(frame, stackTop));
                                continue Loop;
                            case Token.BINDNAME:
                                stack[++stackTop] = ScriptRuntime.bind(cx, frame.scope, stringReg);
                                continue Loop;
                            case Token.STRICT_SETNAME:
                            case Token.SETNAME:
                                {
                                    Object rhs = stack[stackTop];
                                    if (rhs == DBL_MRK)
                                        rhs = ScriptRuntime.wrapNumber(sDbl[stackTop]);
                                    --stackTop;
                                    Scriptable lhs = (Scriptable) stack[stackTop];
                                    stack[stackTop] =
                                            op == Token.SETNAME
                                                    ? ScriptRuntime.setName(
                                                            lhs, rhs, cx, frame.scope, stringReg)
                                                    : ScriptRuntime.strictSetName(
                                                            lhs, rhs, cx, frame.scope, stringReg);
                                    continue Loop;
                                }
                            case Icode_SETCONST:
                                {
                                    Object rhs = stack[stackTop];
                                    if (rhs == DBL_MRK)
                                        rhs = ScriptRuntime.wrapNumber(sDbl[stackTop]);
                                    --stackTop;
                                    Scriptable lhs = (Scriptable) stack[stackTop];
                                    stack[stackTop] =
                                            ScriptRuntime.setConst(lhs, rhs, cx, stringReg);
                                    continue Loop;
                                }
                            case Token.DELPROP:
                            case Icode_DELNAME:
                                {
                                    stackTop = doDelName(cx, frame, op, stack, sDbl, stackTop);
                                    continue Loop;
                                }
                            case Icode_DELPROP_SUPER:
                                stackTop -= 1;
                                stack[stackTop] = Boolean.FALSE;
                                ScriptRuntime.throwDeleteOnSuperPropertyNotAllowed();
                                continue Loop;
                            case Token.GETPROPNOWARN:
                                {
                                    Object lhs = stack[stackTop];
                                    if (lhs == DBL_MRK)
                                        lhs = ScriptRuntime.wrapNumber(sDbl[stackTop]);
                                    stack[stackTop] =
                                            ScriptRuntime.getObjectPropNoWarn(
                                                    lhs, stringReg, cx, frame.scope);
                                    continue Loop;
                                }
                            case Token.GETPROP:
                                {
                                    Object lhs = stack[stackTop];
                                    if (lhs == DBL_MRK)
                                        lhs = ScriptRuntime.wrapNumber(sDbl[stackTop]);
                                    stack[stackTop] =
                                            ScriptRuntime.getObjectProp(
                                                    lhs, stringReg, cx, frame.scope);
                                    continue Loop;
                                }
                            case Token.GETPROP_SUPER:
                            case Token.GETPROPNOWARN_SUPER:
                                {
                                    Object superObject = stack[stackTop];
                                    if (superObject == DBL_MRK) Kit.codeBug();
                                    stack[stackTop] =
                                            ScriptRuntime.getSuperProp(
                                                    superObject,
                                                    stringReg,
                                                    cx,
                                                    frame.scope,
                                                    frame.thisObj,
                                                    op == Token.GETPROPNOWARN_SUPER);
                                    continue Loop;
                                }
                            case Token.SETPROP:
                                {
                                    Object rhs = stack[stackTop];
                                    if (rhs == DBL_MRK)
                                        rhs = ScriptRuntime.wrapNumber(sDbl[stackTop]);
                                    --stackTop;
                                    Object lhs = stack[stackTop];
                                    if (lhs == DBL_MRK)
                                        lhs = ScriptRuntime.wrapNumber(sDbl[stackTop]);
                                    stack[stackTop] =
                                            ScriptRuntime.setObjectProp(
                                                    lhs, stringReg, rhs, cx, frame.scope);
                                    continue Loop;
                                }
                            case Token.SETPROP_SUPER:
                                {
                                    Object rhs = stack[stackTop];
                                    if (rhs == DBL_MRK)
                                        rhs = ScriptRuntime.wrapNumber(sDbl[stackTop]);
                                    --stackTop;
                                    Object superObject = stack[stackTop];
                                    if (superObject == DBL_MRK) Kit.codeBug();
                                    stack[stackTop] =
                                            ScriptRuntime.setSuperProp(
                                                    superObject,
                                                    stringReg,
                                                    rhs,
                                                    cx,
                                                    frame.scope,
                                                    frame.thisObj);
                                    continue Loop;
                                }
                            case Icode_PROP_INC_DEC:
                                {
                                    Object lhs = stack[stackTop];
                                    if (lhs == DBL_MRK)
                                        lhs = ScriptRuntime.wrapNumber(sDbl[stackTop]);
                                    stack[stackTop] =
                                            ScriptRuntime.propIncrDecr(
                                                    lhs,
                                                    stringReg,
                                                    cx,
                                                    frame.scope,
                                                    iCode[frame.pc]);
                                    ++frame.pc;
                                    continue Loop;
                                }
                            case Token.GETELEM:
                                {
                                    stackTop = doGetElem(cx, frame, stack, sDbl, stackTop);
                                    continue Loop;
                                }
                            case Token.GETELEM_SUPER:
                                {
                                    stackTop = doGetElemSuper(cx, frame, stack, sDbl, stackTop);
                                    continue Loop;
                                }
                            case Token.SETELEM:
                                {
                                    stackTop = doSetElem(cx, frame, stack, sDbl, stackTop);
                                    continue Loop;
                                }
                            case Token.SETELEM_SUPER:
                                {
                                    stackTop = doSetElemSuper(cx, frame, stack, sDbl, stackTop);
                                    continue Loop;
                                }
                            case Icode_ELEM_INC_DEC:
                                {
                                    stackTop =
                                            doElemIncDec(cx, frame, iCode, stack, sDbl, stackTop);
                                    continue Loop;
                                }
                            case Token.GET_REF:
                                {
                                    Ref ref = (Ref) stack[stackTop];
                                    stack[stackTop] = ScriptRuntime.refGet(ref, cx);
                                    continue Loop;
                                }
                            case Token.SET_REF:
                                {
                                    Object value = stack[stackTop];
                                    if (value == DBL_MRK)
                                        value = ScriptRuntime.wrapNumber(sDbl[stackTop]);
                                    --stackTop;
                                    Ref ref = (Ref) stack[stackTop];
                                    stack[stackTop] =
                                            ScriptRuntime.refSet(ref, value, cx, frame.scope);
                                    continue Loop;
                                }
                            case Token.DEL_REF:
                                {
                                    Ref ref = (Ref) stack[stackTop];
                                    stack[stackTop] = ScriptRuntime.refDel(ref, cx);
                                    continue Loop;
                                }
                            case Icode_REF_INC_DEC:
                                {
                                    Ref ref = (Ref) stack[stackTop];
                                    stack[stackTop] =
                                            ScriptRuntime.refIncrDecr(
                                                    ref, cx, frame.scope, iCode[frame.pc]);
                                    ++frame.pc;
                                    continue Loop;
                                }
                            case Token.LOCAL_LOAD:
                                ++stackTop;
                                indexReg += frame.localShift;
                                stack[stackTop] = stack[indexReg];
                                sDbl[stackTop] = sDbl[indexReg];
                                continue Loop;
                            case Icode_LOCAL_CLEAR:
                                indexReg += frame.localShift;
                                stack[indexReg] = null;
                                continue Loop;
                            case Icode_NAME_AND_THIS:
                                // stringReg: name
                                ++stackTop;
                                stack[stackTop] =
                                        ScriptRuntime.getNameFunctionAndThis(
                                                stringReg, cx, frame.scope);
                                ++stackTop;
                                stack[stackTop] = ScriptRuntime.lastStoredScriptable(cx);
                                continue Loop;
                            case Icode_NAME_AND_THIS_OPTIONAL:
                                // stringReg: name
                                ++stackTop;
                                stack[stackTop] =
                                        ScriptRuntime.getNameFunctionAndThisOptional(
                                                stringReg, cx, frame.scope);
                                ++stackTop;
                                stack[stackTop] = ScriptRuntime.lastStoredScriptable(cx);
                                continue Loop;
                            case Icode_PROP_AND_THIS:
                                {
                                    Object obj = stack[stackTop];
                                    if (obj == DBL_MRK)
                                        obj = ScriptRuntime.wrapNumber(sDbl[stackTop]);
                                    // stringReg: property
                                    stack[stackTop] =
                                            ScriptRuntime.getPropFunctionAndThis(
                                                    obj, stringReg, cx, frame.scope);
                                    ++stackTop;
                                    stack[stackTop] = ScriptRuntime.lastStoredScriptable(cx);
                                    continue Loop;
                                }
                            case Icode_PROP_AND_THIS_OPTIONAL:
                                {
                                    Object obj = stack[stackTop];
                                    if (obj == DBL_MRK)
                                        obj = ScriptRuntime.wrapNumber(sDbl[stackTop]);
                                    // stringReg: property
                                    stack[stackTop] =
                                            ScriptRuntime.getPropFunctionAndThisOptional(
                                                    obj, stringReg, cx, frame.scope);
                                    ++stackTop;
                                    stack[stackTop] = ScriptRuntime.lastStoredScriptable(cx);
                                    continue Loop;
                                }
                            case Icode_ELEM_AND_THIS:
                                {
                                    Object obj = stack[stackTop - 1];
                                    if (obj == DBL_MRK)
                                        obj = ScriptRuntime.wrapNumber(sDbl[stackTop - 1]);
                                    Object id = stack[stackTop];
                                    if (id == DBL_MRK)
                                        id = ScriptRuntime.wrapNumber(sDbl[stackTop]);
                                    stack[stackTop - 1] =
                                            ScriptRuntime.getElemFunctionAndThis(
                                                    obj, id, cx, frame.scope);
                                    stack[stackTop] = ScriptRuntime.lastStoredScriptable(cx);
                                    continue Loop;
                                }
                            case Icode_ELEM_AND_THIS_OPTIONAL:
                                {
                                    Object obj = stack[stackTop - 1];
                                    if (obj == DBL_MRK)
                                        obj = ScriptRuntime.wrapNumber(sDbl[stackTop - 1]);
                                    Object id = stack[stackTop];
                                    if (id == DBL_MRK)
                                        id = ScriptRuntime.wrapNumber(sDbl[stackTop]);
                                    stack[stackTop - 1] =
                                            ScriptRuntime.getElemFunctionAndThisOptional(
                                                    obj, id, cx, frame.scope);
                                    stack[stackTop] = ScriptRuntime.lastStoredScriptable(cx);
                                    continue Loop;
                                }
                            case Icode_VALUE_AND_THIS:
                                {
                                    Object value = stack[stackTop];
                                    if (value == DBL_MRK)
                                        value = ScriptRuntime.wrapNumber(sDbl[stackTop]);
                                    stack[stackTop] =
                                            ScriptRuntime.getValueFunctionAndThis(value, cx);
                                    ++stackTop;
                                    stack[stackTop] = ScriptRuntime.lastStoredScriptable(cx);
                                    continue Loop;
                                }
                            case Icode_VALUE_AND_THIS_OPTIONAL:
                                {
                                    Object value = stack[stackTop];
                                    if (value == DBL_MRK)
                                        value = ScriptRuntime.wrapNumber(sDbl[stackTop]);
                                    stack[stackTop] =
                                            ScriptRuntime.getValueFunctionAndThisOptional(
                                                    value, cx);
                                    ++stackTop;
                                    stack[stackTop] = ScriptRuntime.lastStoredScriptable(cx);
                                    continue Loop;
                                }
                            case Icode_CALLSPECIAL:
                                {
                                    if (instructionCounting) {
                                        cx.instructionCount += INVOCATION_COST;
                                    }
                                    stackTop =
                                            doCallSpecial(
                                                    cx, frame, stack, sDbl, stackTop, iCode,
                                                    indexReg, false);
                                    continue Loop;
                                }
                            case Icode_CALLSPECIAL_OPTIONAL:
                                {
                                    if (instructionCounting) {
                                        cx.instructionCount += INVOCATION_COST;
                                    }
                                    stackTop =
                                            doCallSpecial(
                                                    cx, frame, stack, sDbl, stackTop, iCode,
                                                    indexReg, true);
                                    continue Loop;
                                }
                            case Token.CALL:
                            case Icode_CALL_ON_SUPER:
                            case Icode_TAIL_CALL:
                            case Token.REF_CALL:
                                {
                                    var callState =
                                            doCallByteCode(
                                                    cx,
                                                    frame,
                                                    instructionCounting,
                                                    op,
                                                    stackTop,
                                                    indexReg);
                                    if (callState instanceof ContinueLoop) {
                                        var contLoop = (ContinueLoop) callState;
                                        frame = contLoop.frame;
                                        stack = frame.stack;
                                        sDbl = frame.sDbl;
                                        stackTop = contLoop.stackTop;
                                        indexReg = contLoop.indexReg;
                                        continue Loop;
                                    } else if (callState instanceof StateContinue) {
                                        frame = ((StateContinue) callState).frame;
                                        continue StateLoop;
                                    } else if (callState instanceof NewThrowable) {
                                        throwable = ((NewThrowable) callState).throwable;
                                        break withoutExceptions;
                                    } else {
                                        Kit.codeBug();
                                        break;
                                    }
                                }
                            case Token.NEW:
                                {
                                    if (instructionCounting) {
                                        cx.instructionCount += INVOCATION_COST;
                                    }
                                    // stack change: function arg0 .. argN -> newResult
                                    // indexReg: number of arguments
                                    stackTop -= indexReg;

                                    Object lhs = stack[stackTop];
                                    if (lhs instanceof InterpretedFunction) {
                                        InterpretedFunction f = (InterpretedFunction) lhs;
                                        if (frame.fnOrScript.securityDomain == f.securityDomain) {
                                            if (cx.getLanguageVersion() >= Context.VERSION_ES6
                                                    && f.getHomeObject() != null) {
                                                // Only methods have home objects associated with
                                                // them
                                                throw ScriptRuntime.typeErrorById(
                                                        "msg.not.ctor", f.getFunctionName());
                                            }

                                            Scriptable newInstance =
                                                    f.createObject(cx, frame.scope);
                                            CallFrame calleeFrame =
                                                    initFrame(
                                                            cx,
                                                            frame.scope,
                                                            newInstance,
                                                            newInstance,
                                                            stack,
                                                            sDbl,
                                                            stackTop + 1,
                                                            indexReg,
                                                            f,
                                                            frame);

                                            stack[stackTop] = newInstance;
                                            frame.savedStackTop = stackTop;
                                            frame.savedCallOp = op;
                                            frame = calleeFrame;
                                            continue StateLoop;
                                        }
                                    }
                                    if (!(lhs instanceof Constructable)) {
                                        if (lhs == DBL_MRK)
                                            lhs = ScriptRuntime.wrapNumber(sDbl[stackTop]);
                                        throw ScriptRuntime.notFunctionError(lhs);
                                    }
                                    Constructable ctor = (Constructable) lhs;

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

                                    Object[] outArgs =
                                            getArgsArray(stack, sDbl, stackTop + 1, indexReg);
                                    stack[stackTop] = ctor.construct(cx, frame.scope, outArgs);
                                    continue Loop;
                                }
                            case Token.TYPEOF:
                                {
                                    Object lhs = stack[stackTop];
                                    if (lhs == DBL_MRK)
                                        lhs = ScriptRuntime.wrapNumber(sDbl[stackTop]);
                                    stack[stackTop] = ScriptRuntime.typeof(lhs);
                                    continue Loop;
                                }
                            case Icode_TYPEOFNAME:
                                stack[++stackTop] =
                                        ScriptRuntime.typeofName(frame.scope, stringReg);
                                continue Loop;
                            case Token.STRING:
                                stack[++stackTop] = stringReg;
                                continue Loop;
                            case Icode_SHORTNUMBER:
                                ++stackTop;
                                stack[stackTop] = DBL_MRK;
                                sDbl[stackTop] = getShort(iCode, frame.pc);
                                frame.pc += 2;
                                continue Loop;
                            case Icode_INTNUMBER:
                                ++stackTop;
                                stack[stackTop] = DBL_MRK;
                                sDbl[stackTop] = getInt(iCode, frame.pc);
                                frame.pc += 4;
                                continue Loop;
                            case Token.NUMBER:
                                ++stackTop;
                                stack[stackTop] = DBL_MRK;
                                sDbl[stackTop] = frame.idata.itsDoubleTable[indexReg];
                                continue Loop;
                            case Token.BIGINT:
                                stack[++stackTop] = bigIntReg;
                                continue Loop;
                            case Token.NAME:
                                stack[++stackTop] = ScriptRuntime.name(cx, frame.scope, stringReg);
                                continue Loop;
                            case Icode_NAME_INC_DEC:
                                stack[++stackTop] =
                                        ScriptRuntime.nameIncrDecr(
                                                frame.scope, stringReg, cx, iCode[frame.pc]);
                                ++frame.pc;
                                continue Loop;
                            case Icode_SETCONSTVAR1:
                                indexReg = iCode[frame.pc++];
                            // fallthrough
                            case Token.SETCONSTVAR:
                                stackTop =
                                        doSetConstVar(
                                                frame,
                                                stack,
                                                sDbl,
                                                stackTop,
                                                vars,
                                                varDbls,
                                                varAttributes,
                                                indexReg);
                                continue Loop;
                            case Icode_SETVAR1:
                                indexReg = iCode[frame.pc++];
                            // fallthrough
                            case Token.SETVAR:
                                stackTop =
                                        doSetVar(
                                                frame,
                                                stack,
                                                sDbl,
                                                stackTop,
                                                vars,
                                                varDbls,
                                                varAttributes,
                                                indexReg);
                                continue Loop;
                            case Icode_GETVAR1:
                                indexReg = iCode[frame.pc++];
                            // fallthrough
                            case Token.GETVAR:
                                stackTop =
                                        doGetVar(
                                                frame, stack, sDbl, stackTop, vars, varDbls,
                                                indexReg);
                                continue Loop;
                            case Icode_VAR_INC_DEC:
                                {
                                    stackTop =
                                            doVarIncDec(
                                                    cx,
                                                    frame,
                                                    stack,
                                                    sDbl,
                                                    stackTop,
                                                    vars,
                                                    varDbls,
                                                    varAttributes,
                                                    indexReg);
                                    continue Loop;
                                }
                            case Icode_ZERO:
                                ++stackTop;
                                stack[stackTop] = Integer.valueOf(0);
                                continue Loop;
                            case Icode_ONE:
                                ++stackTop;
                                stack[stackTop] = Integer.valueOf(1);
                                continue Loop;
                            case Token.NULL:
                                stack[++stackTop] = null;
                                continue Loop;
                            case Token.THIS:
                                stack[++stackTop] = frame.thisObj;
                                continue Loop;
                            case Token.SUPER:
                                {
                                    // See 9.1.1.3.5 GetSuperBase

                                    // If we are referring to "super", then we always have an
                                    // activation
                                    // (this is done in IrFactory). The home object is stored as
                                    // part of the
                                    // activation frame to propagate it correctly for nested
                                    // functions.
                                    Scriptable homeObject = getCurrentFrameHomeObject(frame);
                                    if (homeObject == null) {
                                        // This if is specified in the spec, but I cannot imagine
                                        // how the home object will ever be null since `super` is
                                        // legal _only_ in method definitions, where we do have a
                                        // home object!
                                        stack[++stackTop] = Undefined.instance;
                                    } else {
                                        stack[++stackTop] = homeObject.getPrototype();
                                    }
                                    continue Loop;
                                }
                            case Token.THISFN:
                                stack[++stackTop] = frame.fnOrScript;
                                continue Loop;
                            case Token.FALSE:
                                stack[++stackTop] = Boolean.FALSE;
                                continue Loop;
                            case Token.TRUE:
                                stack[++stackTop] = Boolean.TRUE;
                                continue Loop;
                            case Icode_UNDEF:
                                stack[++stackTop] = undefined;
                                continue Loop;
                            case Token.ENTERWITH:
                                {
                                    Object lhs = stack[stackTop];
                                    if (lhs == DBL_MRK)
                                        lhs = ScriptRuntime.wrapNumber(sDbl[stackTop]);
                                    --stackTop;
                                    frame.scope = ScriptRuntime.enterWith(lhs, cx, frame.scope);
                                    continue Loop;
                                }
                            case Token.LEAVEWITH:
                                frame.scope = ScriptRuntime.leaveWith(frame.scope);
                                continue Loop;
                            case Token.CATCH_SCOPE:
                                {
                                    // stack top: exception object
                                    // stringReg: name of exception variable
                                    // indexReg: local for exception scope
                                    --stackTop;
                                    indexReg += frame.localShift;

                                    boolean afterFirstScope = (frame.idata.itsICode[frame.pc] != 0);
                                    Throwable caughtException = (Throwable) stack[stackTop + 1];
                                    Scriptable lastCatchScope;
                                    if (!afterFirstScope) {
                                        lastCatchScope = null;
                                    } else {
                                        lastCatchScope = (Scriptable) stack[indexReg];
                                    }
                                    stack[indexReg] =
                                            ScriptRuntime.newCatchScope(
                                                    caughtException,
                                                    lastCatchScope,
                                                    stringReg,
                                                    cx,
                                                    frame.scope);
                                    ++frame.pc;
                                    continue Loop;
                                }
                            case Token.ENUM_INIT_KEYS:
                            case Token.ENUM_INIT_VALUES:
                            case Token.ENUM_INIT_ARRAY:
                            case Token.ENUM_INIT_VALUES_IN_ORDER:
                                {
                                    Object lhs = stack[stackTop];
                                    if (lhs == DBL_MRK)
                                        lhs = ScriptRuntime.wrapNumber(sDbl[stackTop]);
                                    --stackTop;
                                    indexReg += frame.localShift;
                                    int enumType =
                                            op == Token.ENUM_INIT_KEYS
                                                    ? ScriptRuntime.ENUMERATE_KEYS
                                                    : op == Token.ENUM_INIT_VALUES
                                                            ? ScriptRuntime.ENUMERATE_VALUES
                                                            : op == Token.ENUM_INIT_VALUES_IN_ORDER
                                                                    ? ScriptRuntime
                                                                            .ENUMERATE_VALUES_IN_ORDER
                                                                    : ScriptRuntime.ENUMERATE_ARRAY;
                                    stack[indexReg] =
                                            ScriptRuntime.enumInit(lhs, cx, frame.scope, enumType);
                                    continue Loop;
                                }
                            case Token.ENUM_NEXT:
                            case Token.ENUM_ID:
                                {
                                    indexReg += frame.localShift;
                                    Object val = stack[indexReg];
                                    ++stackTop;
                                    stack[stackTop] =
                                            (op == Token.ENUM_NEXT)
                                                    ? ScriptRuntime.enumNext(val, cx)
                                                    : ScriptRuntime.enumId(val, cx);
                                    continue Loop;
                                }
                            case Token.REF_SPECIAL:
                                {
                                    // stringReg: name of special property
                                    Object obj = stack[stackTop];
                                    if (obj == DBL_MRK)
                                        obj = ScriptRuntime.wrapNumber(sDbl[stackTop]);
                                    stack[stackTop] =
                                            ScriptRuntime.specialRef(
                                                    obj, stringReg, cx, frame.scope);
                                    continue Loop;
                                }
                            case Token.REF_MEMBER:
                                {
                                    // indexReg: flags
                                    stackTop = doRefMember(cx, stack, sDbl, stackTop, indexReg);
                                    continue Loop;
                                }
                            case Token.REF_NS_MEMBER:
                                {
                                    // indexReg: flags
                                    stackTop = doRefNsMember(cx, stack, sDbl, stackTop, indexReg);
                                    continue Loop;
                                }
                            case Token.REF_NAME:
                                {
                                    // indexReg: flags
                                    Object name = stack[stackTop];
                                    if (name == DBL_MRK)
                                        name = ScriptRuntime.wrapNumber(sDbl[stackTop]);
                                    stack[stackTop] =
                                            ScriptRuntime.nameRef(name, cx, frame.scope, indexReg);
                                    continue Loop;
                                }
                            case Token.REF_NS_NAME:
                                {
                                    // indexReg: flags
                                    stackTop =
                                            doRefNsName(cx, frame, stack, sDbl, stackTop, indexReg);
                                    continue Loop;
                                }
                            case Icode_SCOPE_LOAD:
                                indexReg += frame.localShift;
                                frame.scope = (Scriptable) stack[indexReg];
                                continue Loop;
                            case Icode_SCOPE_SAVE:
                                indexReg += frame.localShift;
                                stack[indexReg] = frame.scope;
                                continue Loop;
                            case Icode_CLOSURE_EXPR:
                                InterpretedFunction fn =
                                        InterpretedFunction.createFunction(
                                                cx, frame.scope, frame.fnOrScript, indexReg);
                                if (fn.idata.itsFunctionType == FunctionNode.ARROW_FUNCTION) {
                                    Scriptable homeObject = getCurrentFrameHomeObject(frame);
                                    if (fn.idata.itsNeedsActivation) {
                                        fn.setHomeObject(homeObject);
                                    }

                                    stack[++stackTop] =
                                            new ArrowFunction(
                                                    cx, frame.scope, fn, frame.thisObj, homeObject);
                                } else {
                                    stack[++stackTop] = fn;
                                }
                                continue Loop;
                            case ICode_FN_STORE_HOME_OBJECT:
                                {
                                    // Stack contains: [object, keysArray, flagsArray, valuesArray,
                                    // function]
                                    InterpretedFunction fun = (InterpretedFunction) stack[stackTop];
                                    Scriptable homeObject = (Scriptable) stack[stackTop - 4];
                                    fun.setHomeObject(homeObject);
                                    continue Loop;
                                }
                            case Icode_CLOSURE_STMT:
                                initFunction(cx, frame.scope, frame.fnOrScript, indexReg);
                                continue Loop;
                            case Token.REGEXP:
                                Object re = frame.idata.itsRegExpLiterals[indexReg];
                                stack[++stackTop] = ScriptRuntime.wrapRegExp(cx, frame.scope, re);
                                continue Loop;
                            case Icode_TEMPLATE_LITERAL_CALLSITE:
                                Object[] templateLiterals = frame.idata.itsTemplateLiterals;
                                stack[++stackTop] =
                                        ScriptRuntime.getTemplateLiteralCallSite(
                                                cx, frame.scope, templateLiterals, indexReg);
                                continue Loop;
                            case Icode_LITERAL_NEW_OBJECT:
                                {
                                    // indexReg: index of constant with the keys
                                    Object[] ids = (Object[]) frame.idata.literalIds[indexReg];
                                    boolean copyArray = iCode[frame.pc] != 0;
                                    ++frame.pc;
                                    ++stackTop;
                                    stack[stackTop] = cx.newObject(frame.scope);
                                    ++stackTop;
                                    stack[stackTop] =
                                            copyArray ? Arrays.copyOf(ids, ids.length) : ids;
                                    ++stackTop;
                                    stack[stackTop] = new int[ids.length];
                                    ++stackTop;
                                    stack[stackTop] = new Object[ids.length];
                                    sDbl[stackTop] = 0;
                                    continue Loop;
                                }
                            case Icode_LITERAL_NEW_ARRAY:
                                // indexReg: number of values in the literal
                                ++stackTop;
                                stack[stackTop] = new int[indexReg];
                                ++stackTop;
                                stack[stackTop] = new Object[indexReg];
                                sDbl[stackTop] = 0;
                                continue Loop;
                            case Icode_LITERAL_SET:
                                {
                                    Object value = stack[stackTop];
                                    if (value == DBL_MRK)
                                        value = ScriptRuntime.wrapNumber(sDbl[stackTop]);
                                    --stackTop;
                                    int i = (int) sDbl[stackTop];
                                    ((Object[]) stack[stackTop])[i] = value;
                                    sDbl[stackTop] = i + 1;
                                    continue Loop;
                                }
                            case Icode_LITERAL_GETTER:
                                {
                                    Object value = stack[stackTop];
                                    --stackTop;
                                    int i = (int) sDbl[stackTop];
                                    ((Object[]) stack[stackTop])[i] = value;
                                    ((int[]) stack[stackTop - 1])[i] = -1;
                                    sDbl[stackTop] = i + 1;
                                    continue Loop;
                                }
                            case Icode_LITERAL_SETTER:
                                {
                                    Object value = stack[stackTop];
                                    --stackTop;
                                    int i = (int) sDbl[stackTop];
                                    ((Object[]) stack[stackTop])[i] = value;
                                    ((int[]) stack[stackTop - 1])[i] = 1;
                                    sDbl[stackTop] = i + 1;
                                    continue Loop;
                                }

                            case Icode_LITERAL_KEY_SET:
                                {
                                    Object key = stack[stackTop];
                                    if (key == DBL_MRK)
                                        key = ScriptRuntime.wrapNumber(sDbl[stackTop]);
                                    --stackTop;
                                    Object[] ids = (Object[]) stack[stackTop - 2];
                                    int i = (int) sDbl[stackTop];
                                    ids[i] = key;
                                    continue Loop;
                                }
                            case Token.OBJECTLIT:
                                {
                                    Object[] values = (Object[]) stack[stackTop];
                                    --stackTop;
                                    int[] getterSetters = (int[]) stack[stackTop];
                                    --stackTop;
                                    Object[] keys = (Object[]) stack[stackTop];
                                    --stackTop;
                                    Scriptable object = (Scriptable) stack[stackTop];
                                    ScriptRuntime.fillObjectLiteral(
                                            object, keys, values, getterSetters, cx, frame.scope);
                                    continue Loop;
                                }
                            case Token.ARRAYLIT:
                            case Icode_SPARE_ARRAYLIT:
                                {
                                    Object[] data = (Object[]) stack[stackTop];
                                    --stackTop;
                                    int[] getterSetters = (int[]) stack[stackTop];
                                    Object val;

                                    int[] skipIndexces = null;
                                    if (op == Icode_SPARE_ARRAYLIT) {
                                        skipIndexces = (int[]) frame.idata.literalIds[indexReg];
                                    }
                                    val =
                                            ScriptRuntime.newArrayLiteral(
                                                    data, skipIndexces, cx, frame.scope);

                                    stack[stackTop] = val;
                                    continue Loop;
                                }
                            case Icode_ENTERDQ:
                                {
                                    Object lhs = stack[stackTop];
                                    if (lhs == DBL_MRK)
                                        lhs = ScriptRuntime.wrapNumber(sDbl[stackTop]);
                                    --stackTop;
                                    frame.scope = ScriptRuntime.enterDotQuery(lhs, frame.scope);
                                    continue Loop;
                                }
                            case Icode_LEAVEDQ:
                                {
                                    boolean valBln = stack_boolean(frame, stackTop);
                                    Object x = ScriptRuntime.updateDotQuery(valBln, frame.scope);
                                    if (x != null) {
                                        stack[stackTop] = x;
                                        frame.scope = ScriptRuntime.leaveDotQuery(frame.scope);
                                        frame.pc += 2;
                                        continue Loop;
                                    }
                                    // reset stack and PC to code after ENTERDQ
                                    --stackTop;
                                    break jumplessRun;
                                }
                            case Token.DEFAULTNAMESPACE:
                                {
                                    Object value = stack[stackTop];
                                    if (value == DBL_MRK)
                                        value = ScriptRuntime.wrapNumber(sDbl[stackTop]);
                                    stack[stackTop] = ScriptRuntime.setDefaultNamespace(value, cx);
                                    continue Loop;
                                }
                            case Token.ESCXMLATTR:
                                {
                                    Object value = stack[stackTop];
                                    if (value != DBL_MRK) {
                                        stack[stackTop] =
                                                ScriptRuntime.escapeAttributeValue(value, cx);
                                    }
                                    continue Loop;
                                }
                            case Token.ESCXMLTEXT:
                                {
                                    Object value = stack[stackTop];
                                    if (value != DBL_MRK) {
                                        stack[stackTop] = ScriptRuntime.escapeTextValue(value, cx);
                                    }
                                    continue Loop;
                                }
                            case Icode_DEBUGGER:
                                if (frame.debuggerFrame != null) {
                                    frame.debuggerFrame.onDebuggerStatement(cx);
                                }
                                continue Loop;
                            case Icode_LINE:
                                frame.pcSourceLineStart = frame.pc;
                                if (frame.debuggerFrame != null) {
                                    int line = getIndex(iCode, frame.pc);
                                    frame.debuggerFrame.onLineChange(cx, line);
                                }
                                frame.pc += 2;
                                continue Loop;
                            case Icode_REG_IND_C0:
                                indexReg = 0;
                                continue Loop;
                            case Icode_REG_IND_C1:
                                indexReg = 1;
                                continue Loop;
                            case Icode_REG_IND_C2:
                                indexReg = 2;
                                continue Loop;
                            case Icode_REG_IND_C3:
                                indexReg = 3;
                                continue Loop;
                            case Icode_REG_IND_C4:
                                indexReg = 4;
                                continue Loop;
                            case Icode_REG_IND_C5:
                                indexReg = 5;
                                continue Loop;
                            case Icode_REG_IND1:
                                indexReg = 0xFF & iCode[frame.pc];
                                ++frame.pc;
                                continue Loop;
                            case Icode_REG_IND2:
                                indexReg = getIndex(iCode, frame.pc);
                                frame.pc += 2;
                                continue Loop;
                            case Icode_REG_IND4:
                                indexReg = getInt(iCode, frame.pc);
                                frame.pc += 4;
                                continue Loop;
                            case Icode_REG_STR_C0:
                                stringReg = strings[0];
                                continue Loop;
                            case Icode_REG_STR_C1:
                                stringReg = strings[1];
                                continue Loop;
                            case Icode_REG_STR_C2:
                                stringReg = strings[2];
                                continue Loop;
                            case Icode_REG_STR_C3:
                                stringReg = strings[3];
                                continue Loop;
                            case Icode_REG_STR1:
                                stringReg = strings[0xFF & iCode[frame.pc]];
                                ++frame.pc;
                                continue Loop;
                            case Icode_REG_STR2:
                                stringReg = strings[getIndex(iCode, frame.pc)];
                                frame.pc += 2;
                                continue Loop;
                            case Icode_REG_STR4:
                                stringReg = strings[getInt(iCode, frame.pc)];
                                frame.pc += 4;
                                continue Loop;
                            case Icode_REG_BIGINT_C0:
                                bigIntReg = bigInts[0];
                                continue Loop;
                            case Icode_REG_BIGINT_C1:
                                bigIntReg = bigInts[1];
                                continue Loop;
                            case Icode_REG_BIGINT_C2:
                                bigIntReg = bigInts[2];
                                continue Loop;
                            case Icode_REG_BIGINT_C3:
                                bigIntReg = bigInts[3];
                                continue Loop;
                            case Icode_REG_BIGINT1:
                                bigIntReg = bigInts[0xFF & iCode[frame.pc]];
                                ++frame.pc;
                                continue Loop;
                            case Icode_REG_BIGINT2:
                                bigIntReg = bigInts[getIndex(iCode, frame.pc)];
                                frame.pc += 2;
                                continue Loop;
                            case Icode_REG_BIGINT4:
                                bigIntReg = bigInts[getInt(iCode, frame.pc)];
                                frame.pc += 4;
                                continue Loop;
                            default:
                                dumpICode(frame.idata);
                                throw new RuntimeException(
                                        "Unknown icode : " + op + " @ pc : " + (frame.pc - 1));
                        } // end of interpreter switch
                    } // end of jumplessRun label block

                    // This should be reachable only for jump implementation
                    // when pc points to encoded target offset
                    if (instructionCounting) {
                        addInstructionCount(cx, frame, 2);
                    }
                    int offset = getShort(iCode, frame.pc);
                    if (offset != 0) {
                        // -1 accounts for pc pointing to jump opcode + 1
                        frame.pc += offset - 1;
                    } else {
                        frame.pc = frame.idata.longJumps.get(frame.pc);
                    }
                    if (instructionCounting) {
                        frame.pcPrevBranch = frame.pc;
                    }
                    continue Loop;
                } // end of Loop: for

                exitFrame(cx, frame, null);
                interpreterResult = frame.result;
                interpreterResultDbl = frame.resultDbl;
                if (frame.parentFrame != null) {
                    frame = frame.parentFrame;
                    if (frame.frozen) {
                        frame = frame.cloneFrozen();
                    }
                    setCallResult(frame, interpreterResult, interpreterResultDbl);
                    interpreterResult = null; // Help GC
                    continue StateLoop;
                }
                break StateLoop;

            } // end of interpreter withoutExceptions: try
            catch (Throwable ex) {
                if (throwable != null) {
                    // This is serious bug and it is better to track it ASAP
                    ex.printStackTrace(System.err);
                    throw new IllegalStateException();
                }
                throwable = ex;
            }

            // This should be reachable only after above catch or from
            // finally when it needs to propagate exception or from
            // explicit throw
            if (throwable == null) Kit.codeBug();

            // Exception type
            final int EX_CATCH_STATE = 2; // Can execute JS catch
            final int EX_FINALLY_STATE = 1; // Can execute JS finally
            final int EX_NO_JS_STATE = 0; // Terminate JS execution

            int exState;
            ContinuationJump cjump = null;

            if (generatorState != null
                    && generatorState.operation == NativeGenerator.GENERATOR_CLOSE
                    && throwable == generatorState.value) {
                exState = EX_FINALLY_STATE;
            } else if (throwable instanceof JavaScriptException) {
                exState = EX_CATCH_STATE;
            } else if (throwable instanceof EcmaError) {
                // an offical ECMA error object,
                exState = EX_CATCH_STATE;
            } else if (throwable instanceof EvaluatorException) {
                exState = EX_CATCH_STATE;
            } else if (throwable instanceof ContinuationPending) {
                exState = EX_NO_JS_STATE;
            } else if (throwable instanceof RuntimeException) {
                exState =
                        cx.hasFeature(Context.FEATURE_ENHANCED_JAVA_ACCESS)
                                ? EX_CATCH_STATE
                                : EX_FINALLY_STATE;
            } else if (throwable instanceof Error) {
                exState =
                        cx.hasFeature(Context.FEATURE_ENHANCED_JAVA_ACCESS)
                                ? EX_CATCH_STATE
                                : EX_NO_JS_STATE;
            } else if (throwable instanceof ContinuationJump) {
                // It must be ContinuationJump
                exState = EX_FINALLY_STATE;
                cjump = (ContinuationJump) throwable;
            } else {
                exState =
                        cx.hasFeature(Context.FEATURE_ENHANCED_JAVA_ACCESS)
                                ? EX_CATCH_STATE
                                : EX_FINALLY_STATE;
            }

            if (instructionCounting) {
                try {
                    addInstructionCount(cx, frame, EXCEPTION_COST);
                } catch (RuntimeException ex) {
                    throwable = ex;
                    exState = EX_FINALLY_STATE;
                } catch (Error ex) {
                    // Error from instruction counting
                    //     => unconditionally terminate JS
                    throwable = ex;
                    cjump = null;
                    exState = EX_NO_JS_STATE;
                }
            }
            if (frame.debuggerFrame != null && throwable instanceof RuntimeException) {
                // Call debugger only for RuntimeException
                RuntimeException rex = (RuntimeException) throwable;
                try {
                    frame.debuggerFrame.onExceptionThrown(cx, rex);
                } catch (Throwable ex) {
                    // Any exception from debugger
                    //     => unconditionally terminate JS
                    throwable = ex;
                    cjump = null;
                    exState = EX_NO_JS_STATE;
                }
            }

            for (; ; ) {
                if (exState != EX_NO_JS_STATE) {
                    boolean onlyFinally = (exState != EX_CATCH_STATE);
                    indexReg = getExceptionHandler(frame, onlyFinally);
                    if (indexReg >= 0) {
                        // We caught an exception, restart the loop
                        // with exception pending the processing at the loop
                        // start
                        continue StateLoop;
                    }
                }
                // No allowed exception handlers in this frame, unwind
                // to parent and try to look there

                exitFrame(cx, frame, throwable);

                frame = frame.parentFrame;
                if (frame == null) {
                    break;
                }
                if (cjump != null && Objects.equals(cjump.branchFrame, frame)) {
                    // Continuation branch point was hit,
                    // restart the state loop to reenter continuation
                    indexReg = -1;
                    continue StateLoop;
                }
            }

            // No more frames, rethrow the exception or deal with continuation
            if (cjump != null) {
                if (cjump.branchFrame != null) {
                    // The above loop should locate the top frame
                    Kit.codeBug();
                }
                if (cjump.capturedFrame != null) {
                    // Restarting detached continuation
                    indexReg = -1;
                    continue StateLoop;
                }
                // Return continuation result to the caller
                interpreterResult = cjump.result;
                interpreterResultDbl = cjump.resultDbl;
                throwable = null;
            }
            break StateLoop;
        } // end of StateLoop: for(;;)

        // Do cleanups/restorations before the final return or throw

        if (cx.previousInterpreterInvocations != null
                && cx.previousInterpreterInvocations.size() != 0) {
            cx.lastInterpreterFrame = cx.previousInterpreterInvocations.pop();
        } else {
            // It was the last interpreter frame on the stack
            cx.lastInterpreterFrame = null;
            // Force GC of the value cx.previousInterpreterInvocations
            cx.previousInterpreterInvocations = null;
        }

        if (throwable != null) {
            if (throwable instanceof RuntimeException) {
                throw (RuntimeException) throwable;
            }
            // Must be instance of Error or code bug
            throw (Error) throwable;
        }

        return (interpreterResult != DBL_MRK)
                ? interpreterResult
                : ScriptRuntime.wrapNumber(interpreterResultDbl);
    }