📄 interpreter.java
字号:
Node.Jump tryNode = (Node.Jump)node; int exceptionObjectLocal = getLocalBlockRef(tryNode); int scopeLocal = allocLocal(); addIndexOp(Icode_SCOPE_SAVE, scopeLocal); int tryStart = itsICodeTop; while (child != null) { visitStatement(child); child = child.getNext(); } Node catchTarget = tryNode.target; if (catchTarget != null) { int catchStartPC = itsLabelTable[getTargetLabel(catchTarget)]; addExceptionHandler( tryStart, catchStartPC, catchStartPC, false, exceptionObjectLocal, scopeLocal); } Node finallyTarget = tryNode.getFinally(); if (finallyTarget != null) { int finallyStartPC = itsLabelTable[getTargetLabel(finallyTarget)]; addExceptionHandler( tryStart, finallyStartPC, finallyStartPC, true, exceptionObjectLocal, scopeLocal); } addIndexOp(Icode_LOCAL_CLEAR, scopeLocal); releaseLocal(scopeLocal); } break; case Token.CATCH_SCOPE: { int localIndex = getLocalBlockRef(node); int scopeIndex = node.getExistingIntProp(Node.CATCH_SCOPE_PROP); String name = child.getString(); child = child.getNext(); visitExpression(child, 0); // load expression object addStringPrefix(name); addIndexPrefix(localIndex); addToken(Token.CATCH_SCOPE); addUint8(scopeIndex != 0 ? 1 : 0); stackChange(-1); } break; case Token.THROW: updateLineNumber(node); visitExpression(child, 0); addToken(Token.THROW); addUint16(itsLineNumber & 0xFFFF); stackChange(-1); break; case Token.RETHROW: updateLineNumber(node); addIndexOp(Token.RETHROW, getLocalBlockRef(node)); break; case Token.RETURN: updateLineNumber(node); if (child != null) { visitExpression(child, ECF_TAIL); addToken(Token.RETURN); stackChange(-1); } else { addIcode(Icode_RETUNDEF); } break; case Token.RETURN_RESULT: updateLineNumber(node); addToken(Token.RETURN_RESULT); break; case Token.ENUM_INIT_KEYS: case Token.ENUM_INIT_VALUES : visitExpression(child, 0); addIndexOp(type, getLocalBlockRef(node)); stackChange(-1); break; default: throw badTree(node); } if (itsStackDepth != 0) { throw Kit.codeBug(); } } private void visitExpression(Node node, int contextFlags) { int type = node.getType(); Node child = node.getFirstChild(); int savedStackDepth = itsStackDepth; switch (type) { case Token.FUNCTION: { int fnIndex = node.getExistingIntProp(Node.FUNCTION_PROP); FunctionNode fn = scriptOrFn.getFunctionNode(fnIndex); // See comments in visitStatement for Token.FUNCTION case if (fn.getFunctionType() != FunctionNode.FUNCTION_EXPRESSION) { throw Kit.codeBug(); } addIndexOp(Icode_CLOSURE_EXPR, fnIndex); stackChange(1); } break; case Token.LOCAL_LOAD: { int localIndex = getLocalBlockRef(node); addIndexOp(Token.LOCAL_LOAD, localIndex); stackChange(1); } break; case Token.COMMA: { Node lastChild = node.getLastChild(); while (child != lastChild) { visitExpression(child, 0); addIcode(Icode_POP); stackChange(-1); child = child.getNext(); } // Preserve tail context flag if any visitExpression(child, contextFlags & ECF_TAIL); } break; case Token.USE_STACK: // Indicates that stack was modified externally, // like placed catch object stackChange(1); break; case Token.REF_CALL: case Token.CALL: case Token.NEW: { if (type == Token.NEW) { visitExpression(child, 0); } else { generateCallFunAndThis(child); } int argCount = 0; while ((child = child.getNext()) != null) { visitExpression(child, 0); ++argCount; } int callType = node.getIntProp(Node.SPECIALCALL_PROP, Node.NON_SPECIALCALL); if (callType != Node.NON_SPECIALCALL) { // embed line number and source filename addIndexOp(Icode_CALLSPECIAL, argCount); addUint8(callType); addUint8(type == Token.NEW ? 1 : 0); addUint16(itsLineNumber & 0xFFFF); } else { if (type == Token.CALL) { if ((contextFlags & ECF_TAIL) != 0) { type = Icode_TAIL_CALL; } } addIndexOp(type, argCount); } // adjust stack if (type == Token.NEW) { // new: f, args -> result stackChange(-argCount); } else { // call: f, thisObj, args -> result // ref_call: f, thisObj, args -> ref stackChange(-1 - argCount); } if (argCount > itsData.itsMaxCalleeArgs) { itsData.itsMaxCalleeArgs = argCount; } } break; case Token.AND: case Token.OR: { visitExpression(child, 0); addIcode(Icode_DUP); stackChange(1); int afterSecondJumpStart = itsICodeTop; int jump = (type == Token.AND) ? Token.IFNE : Token.IFEQ; addGotoOp(jump); stackChange(-1); addIcode(Icode_POP); stackChange(-1); child = child.getNext(); // Preserve tail context flag if any visitExpression(child, contextFlags & ECF_TAIL); resolveForwardGoto(afterSecondJumpStart); } break; case Token.HOOK: { Node ifThen = child.getNext(); Node ifElse = ifThen.getNext(); visitExpression(child, 0); int elseJumpStart = itsICodeTop; addGotoOp(Token.IFNE); stackChange(-1); // Preserve tail context flag if any visitExpression(ifThen, contextFlags & ECF_TAIL); int afterElseJumpStart = itsICodeTop; addGotoOp(Token.GOTO); resolveForwardGoto(elseJumpStart); itsStackDepth = savedStackDepth; // Preserve tail context flag if any visitExpression(ifElse, contextFlags & ECF_TAIL); resolveForwardGoto(afterElseJumpStart); } break; case Token.GETPROP: visitExpression(child, 0); child = child.getNext(); addStringOp(Token.GETPROP, child.getString()); break; case Token.GETELEM: case Token.DELPROP: case Token.BITAND: case Token.BITOR: case Token.BITXOR: case Token.LSH: case Token.RSH: case Token.URSH: case Token.ADD: case Token.SUB: case Token.MOD: case Token.DIV: case Token.MUL: case Token.EQ: case Token.NE: case Token.SHEQ: case Token.SHNE: case Token.IN: case Token.INSTANCEOF: case Token.LE: case Token.LT: case Token.GE: case Token.GT: visitExpression(child, 0); child = child.getNext(); visitExpression(child, 0); addToken(type); stackChange(-1); break; case Token.POS: case Token.NEG: case Token.NOT: case Token.BITNOT: case Token.TYPEOF: case Token.VOID: visitExpression(child, 0); if (type == Token.VOID) { addIcode(Icode_POP); addIcode(Icode_UNDEF); } else { addToken(type); } break; case Token.GET_REF: case Token.DEL_REF: visitExpression(child, 0); addToken(type); break; case Token.SETPROP: case Token.SETPROP_OP: { visitExpression(child, 0); child = child.getNext(); String property = child.getString(); child = child.getNext(); if (type == Token.SETPROP_OP) { addIcode(Icode_DUP); stackChange(1); addStringOp(Token.GETPROP, property); // Compensate for the following USE_STACK stackChange(-1); } visitExpression(child, 0); addStringOp(Token.SETPROP, property); stackChange(-1); } break; case Token.SETELEM: case Token.SETELEM_OP: visitExpression(child, 0); child = child.getNext(); visitExpression(child, 0); child = child.getNext(); if (type == Token.SETELEM_OP) { addIcode(Icode_DUP2); stackChange(2); addToken(Token.GETELEM); stackChange(-1); // Compensate for the following USE_STACK stackChange(-1); } visitExpression(child, 0); addToken(Token.SETELEM); stackChange(-2); break; case Token.SET_REF: case Token.SET_REF_OP: visitExpression(child, 0); child = child.getNext(); if (type == Token.SET_REF_OP) { addIcode(Icode_DUP); stackChange(1); addToken(Token.GET_REF); // Compensate for the following USE_STACK stackChange(-1); } visitExpression(child, 0); addToken(Token.SET_REF); stackChange(-1); break; case Token.SETNAME: { String name = child.getString(); visitExpression(child, 0); child = child.getNext(); visitExpression(child, 0); addStringOp(Token.SETNAME, name); stackChange(-1); } break; case Token.TYPEOFNAME: { String name = node.getString(); int index = -1; // use typeofname if an activation frame exists // since the vars all exist there instead of in jregs if (itsInFunctionFlag && !itsData.itsNeedsActivation) index = scriptOrFn.getParamOrVarIndex(name); if (index == -1) { addStringOp(Icode_TYPEOFNAME, name); stackChange(1); } else { addVarOp(Token.GETVAR, index); stackChange(1); addToken(Token.TYPEOF); } } break; case Token.BINDNAME: case Token.NAME: case Token.STRING: addStringOp(type, node.getString()); stackChange(1); break; case Token.INC: case Token.DEC: visitIncDec(node, child); break; case Token.NUMBER: { double num = node.getDouble(); int inum = (int)num;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -