📄 interpreter.java
字号:
return String.valueOf(bytecode); } if (validTokenCode(bytecode)) { return Token.name(bytecode); } switch (bytecode) { case Icode_DUP: return "DUP"; case Icode_DUP2: return "DUP2"; case Icode_SWAP: return "SWAP"; case Icode_POP: return "POP"; case Icode_POP_RESULT: return "POP_RESULT"; case Icode_IFEQ_POP: return "IFEQ_POP"; case Icode_VAR_INC_DEC: return "VAR_INC_DEC"; case Icode_NAME_INC_DEC: return "NAME_INC_DEC"; case Icode_PROP_INC_DEC: return "PROP_INC_DEC"; case Icode_ELEM_INC_DEC: return "ELEM_INC_DEC"; case Icode_REF_INC_DEC: return "REF_INC_DEC"; case Icode_SCOPE_LOAD: return "SCOPE_LOAD"; case Icode_SCOPE_SAVE: return "SCOPE_SAVE"; case Icode_TYPEOFNAME: return "TYPEOFNAME"; case Icode_NAME_AND_THIS: return "NAME_AND_THIS"; case Icode_PROP_AND_THIS: return "PROP_AND_THIS"; case Icode_ELEM_AND_THIS: return "ELEM_AND_THIS"; case Icode_VALUE_AND_THIS: return "VALUE_AND_THIS"; case Icode_CLOSURE_EXPR: return "CLOSURE_EXPR"; case Icode_CLOSURE_STMT: return "CLOSURE_STMT"; case Icode_CALLSPECIAL: return "CALLSPECIAL"; case Icode_RETUNDEF: return "RETUNDEF"; case Icode_GOSUB: return "GOSUB"; case Icode_STARTSUB: return "STARTSUB"; case Icode_RETSUB: return "RETSUB"; case Icode_LINE: return "LINE"; case Icode_SHORTNUMBER: return "SHORTNUMBER"; case Icode_INTNUMBER: return "INTNUMBER"; case Icode_LITERAL_NEW: return "LITERAL_NEW"; case Icode_LITERAL_SET: return "LITERAL_SET"; case Icode_SPARE_ARRAYLIT: return "SPARE_ARRAYLIT"; case Icode_REG_IND_C0: return "REG_IND_C0"; case Icode_REG_IND_C1: return "REG_IND_C1"; case Icode_REG_IND_C2: return "REG_IND_C2"; case Icode_REG_IND_C3: return "REG_IND_C3"; case Icode_REG_IND_C4: return "REG_IND_C4"; case Icode_REG_IND_C5: return "REG_IND_C5"; case Icode_REG_IND1: return "LOAD_IND1"; case Icode_REG_IND2: return "LOAD_IND2"; case Icode_REG_IND4: return "LOAD_IND4"; case Icode_REG_STR_C0: return "REG_STR_C0"; case Icode_REG_STR_C1: return "REG_STR_C1"; case Icode_REG_STR_C2: return "REG_STR_C2"; case Icode_REG_STR_C3: return "REG_STR_C3"; case Icode_REG_STR1: return "LOAD_STR1"; case Icode_REG_STR2: return "LOAD_STR2"; case Icode_REG_STR4: return "LOAD_STR4"; case Icode_GETVAR1: return "GETVAR1"; case Icode_SETVAR1: return "SETVAR1"; case Icode_UNDEF: return "UNDEF"; case Icode_ZERO: return "ZERO"; case Icode_ONE: return "ONE"; case Icode_ENTERDQ: return "ENTERDQ"; case Icode_LEAVEDQ: return "LEAVEDQ"; case Icode_TAIL_CALL: return "TAIL_CALL"; case Icode_LOCAL_CLEAR: return "LOCAL_CLEAR"; case Icode_LITERAL_GETTER: return "LITERAL_GETTER"; case Icode_LITERAL_SETTER: return "LITERAL_SETTER"; case Icode_SETCONST: return "SETCONST"; case Icode_SETCONSTVAR: return "SETCONSTVAR"; case Icode_SETCONSTVAR1: return "SETCONSTVAR1"; case Icode_GENERATOR: return "GENERATOR"; case Icode_GENERATOR_END: return "GENERATOR_END"; case Icode_DEBUGGER: return "DEBUGGER"; } // icode without name throw new IllegalStateException(String.valueOf(bytecode)); } private static boolean validIcode(int icode) { return MIN_ICODE <= icode && icode <= -1; } private static boolean validTokenCode(int token) { return Token.FIRST_BYTECODE_TOKEN <= token && token <= Token.LAST_BYTECODE_TOKEN; } private static boolean validBytecode(int bytecode) { return validIcode(bytecode) || validTokenCode(bytecode); } public Object compile(CompilerEnvirons compilerEnv, ScriptOrFnNode tree, String encodedSource, boolean returnFunction) { this.compilerEnv = compilerEnv; new NodeTransformer().transform(tree); if (Token.printTrees) { System.out.println(tree.toStringTree(tree)); } if (returnFunction) { tree = tree.getFunctionNode(0); } scriptOrFn = tree; itsData = new InterpreterData(compilerEnv.getLanguageVersion(), scriptOrFn.getSourceName(), encodedSource); itsData.topLevel = true; if (returnFunction) { generateFunctionICode(); } else { generateICodeFromTree(scriptOrFn); } return itsData; } public Script createScriptObject(Object bytecode, Object staticSecurityDomain) { if(bytecode != itsData) { Kit.codeBug(); } return InterpretedFunction.createScript(itsData, staticSecurityDomain); } public void setEvalScriptFlag(Script script) { ((InterpretedFunction)script).idata.evalScriptFlag = true; } public Function createFunctionObject(Context cx, Scriptable scope, Object bytecode, Object staticSecurityDomain) { if(bytecode != itsData) { Kit.codeBug(); } return InterpretedFunction.createFunction(cx, scope, itsData, staticSecurityDomain); } private void generateFunctionICode() { itsInFunctionFlag = true; FunctionNode theFunction = (FunctionNode)scriptOrFn; itsData.itsFunctionType = theFunction.getFunctionType(); itsData.itsNeedsActivation = theFunction.requiresActivation(); itsData.itsName = theFunction.getFunctionName(); if (!theFunction.getIgnoreDynamicScope()) { if (compilerEnv.isUseDynamicScope()) { itsData.useDynamicScope = true; } } if (theFunction.isGenerator()) { addIcode(Icode_GENERATOR); addUint16(theFunction.getBaseLineno() & 0xFFFF); } generateICodeFromTree(theFunction.getLastChild()); } private void generateICodeFromTree(Node tree) { generateNestedFunctions(); generateRegExpLiterals(); visitStatement(tree, 0); fixLabelGotos(); // add RETURN_RESULT only to scripts as function always ends with RETURN if (itsData.itsFunctionType == 0) { addToken(Token.RETURN_RESULT); } if (itsData.itsICode.length != itsICodeTop) { // Make itsData.itsICode length exactly itsICodeTop to save memory // and catch bugs with jumps beyond icode as early as possible byte[] tmp = new byte[itsICodeTop]; System.arraycopy(itsData.itsICode, 0, tmp, 0, itsICodeTop); itsData.itsICode = tmp; } if (itsStrings.size() == 0) { itsData.itsStringTable = null; } else { itsData.itsStringTable = new String[itsStrings.size()]; ObjToIntMap.Iterator iter = itsStrings.newIterator(); for (iter.start(); !iter.done(); iter.next()) { String str = (String)iter.getKey(); int index = iter.getValue(); if (itsData.itsStringTable[index] != null) Kit.codeBug(); itsData.itsStringTable[index] = str; } } if (itsDoubleTableTop == 0) { itsData.itsDoubleTable = null; } else if (itsData.itsDoubleTable.length != itsDoubleTableTop) { double[] tmp = new double[itsDoubleTableTop]; System.arraycopy(itsData.itsDoubleTable, 0, tmp, 0, itsDoubleTableTop); itsData.itsDoubleTable = tmp; } if (itsExceptionTableTop != 0 && itsData.itsExceptionTable.length != itsExceptionTableTop) { int[] tmp = new int[itsExceptionTableTop]; System.arraycopy(itsData.itsExceptionTable, 0, tmp, 0, itsExceptionTableTop); itsData.itsExceptionTable = tmp; } itsData.itsMaxVars = scriptOrFn.getParamAndVarCount(); // itsMaxFrameArray: interpret method needs this amount for its // stack and sDbl arrays itsData.itsMaxFrameArray = itsData.itsMaxVars + itsData.itsMaxLocals + itsData.itsMaxStack; itsData.argNames = scriptOrFn.getParamAndVarNames(); itsData.argIsConst = scriptOrFn.getParamAndVarConst(); itsData.argCount = scriptOrFn.getParamCount(); itsData.encodedSourceStart = scriptOrFn.getEncodedSourceStart(); itsData.encodedSourceEnd = scriptOrFn.getEncodedSourceEnd(); if (itsLiteralIds.size() != 0) { itsData.literalIds = itsLiteralIds.toArray(); } if (Token.printICode) dumpICode(itsData); } private void generateNestedFunctions() { int functionCount = scriptOrFn.getFunctionCount(); if (functionCount == 0) return; InterpreterData[] array = new InterpreterData[functionCount]; for (int i = 0; i != functionCount; i++) { FunctionNode def = scriptOrFn.getFunctionNode(i); Interpreter jsi = new Interpreter(); jsi.compilerEnv = compilerEnv; jsi.scriptOrFn = def; jsi.itsData = new InterpreterData(itsData); jsi.generateFunctionICode(); array[i] = jsi.itsData; } itsData.itsNestedFunctions = array; } private void generateRegExpLiterals() { int N = scriptOrFn.getRegexpCount(); if (N == 0) return; Context cx = Context.getContext(); RegExpProxy rep = ScriptRuntime.checkRegExpProxy(cx); Object[] array = new Object[N]; for (int i = 0; i != N; i++) { String string = scriptOrFn.getRegexpString(i); String flags = scriptOrFn.getRegexpFlags(i); array[i] = rep.compileRegExp(cx, string, flags); } itsData.itsRegExpLiterals = array; } private void updateLineNumber(Node node) { int lineno = node.getLineno(); if (lineno != itsLineNumber && lineno >= 0) { if (itsData.firstLinePC < 0) { itsData.firstLinePC = lineno; } itsLineNumber = lineno; addIcode(Icode_LINE); addUint16(lineno & 0xFFFF); } } private RuntimeException badTree(Node node) { throw new RuntimeException(node.toString()); } private void visitStatement(Node node, int initialStackDepth) { int type = node.getType(); Node child = node.getFirstChild(); switch (type) { case Token.FUNCTION: { int fnIndex = node.getExistingIntProp(Node.FUNCTION_PROP); int fnType = scriptOrFn.getFunctionNode(fnIndex). getFunctionType(); // Only function expressions or function expression // statements need closure code creating new function // object on stack as function statements are initialized // at script/function start. // In addition, function expressions can not be present here // at statement level, they must only be present as expressions. if (fnType == FunctionNode.FUNCTION_EXPRESSION_STATEMENT) { addIndexOp(Icode_CLOSURE_STMT, fnIndex); } else { if (fnType != FunctionNode.FUNCTION_STATEMENT) { throw Kit.codeBug(); } } // For function statements or function expression statements // in scripts, we need to ensure that the result of the script // is the function if it is the last statement in the script. // For example, eval("function () {}") should return a // function, not undefined. if (!itsInFunctionFlag) { addIndexOp(Icode_CLOSURE_EXPR, fnIndex); stackChange(1); addIcode(Icode_POP_RESULT); stackChange(-1); } } break; case Token.LABEL: case Token.LOOP: case Token.BLOCK: case Token.EMPTY: case Token.WITH: updateLineNumber(node); case Token.SCRIPT: // fall through while (child != null) { visitStatement(child, initialStackDepth); child = child.getNext(); } break; case Token.ENTERWITH: visitExpression(child, 0); addToken(Token.ENTERWITH); stackChange(-1); break; case Token.LEAVEWITH: addToken(Token.LEAVEWITH); break; case Token.LOCAL_BLOCK: { int local = allocLocal(); node.putIntProp(Node.LOCAL_PROP, local); updateLineNumber(node); while (child != null) { visitStatement(child, initialStackDepth); child = child.getNext(); } addIndexOp(Icode_LOCAL_CLEAR, local); releaseLocal(local); } break; case Token.DEBUGGER: addIcode(Icode_DEBUGGER); break; case Token.SWITCH: updateLineNumber(node); // See comments in IRFactory.createSwitch() for description // of SWITCH node { visitExpression(child, 0); for (Node.Jump caseNode = (Node.Jump)child.getNext(); caseNode != null;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -