📄 interpreter.java
字号:
private void addUint8(int value) { if ((value & ~0xFF) != 0) throw Kit.codeBug(); byte[] array = itsData.itsICode; int top = itsICodeTop; if (top == array.length) { array = increaseICodeCapasity(1); } array[top] = (byte)value; itsICodeTop = top + 1; } private void addUint16(int value) { if ((value & ~0xFFFF) != 0) throw Kit.codeBug(); byte[] array = itsData.itsICode; int top = itsICodeTop; if (top + 2 > array.length) { array = increaseICodeCapasity(2); } array[top] = (byte)(value >>> 8); array[top + 1] = (byte)value; itsICodeTop = top + 2; } private void addInt(int i) { byte[] array = itsData.itsICode; int top = itsICodeTop; if (top + 4 > array.length) { array = increaseICodeCapasity(4); } array[top] = (byte)(i >>> 24); array[top + 1] = (byte)(i >>> 16); array[top + 2] = (byte)(i >>> 8); array[top + 3] = (byte)i; itsICodeTop = top + 4; } private int getDoubleIndex(double num) { int index = itsDoubleTableTop; if (index == 0) { itsData.itsDoubleTable = new double[64]; } else if (itsData.itsDoubleTable.length == index) { double[] na = new double[index * 2]; System.arraycopy(itsData.itsDoubleTable, 0, na, 0, index); itsData.itsDoubleTable = na; } itsData.itsDoubleTable[index] = num; itsDoubleTableTop = index + 1; return index; } private void addGotoOp(int gotoOp) { byte[] array = itsData.itsICode; int top = itsICodeTop; if (top + 3 > array.length) { array = increaseICodeCapasity(3); } array[top] = (byte)gotoOp; // Offset would written later itsICodeTop = top + 1 + 2; } private void addVarOp(int op, int varIndex) { switch (op) { case Token.GETVAR: case Token.SETVAR: if (varIndex < 128) { addIcode(op == Token.GETVAR ? Icode_GETVAR1 : Icode_SETVAR1); addUint8(varIndex); return; } // fallthrough case Icode_VAR_INC_DEC: addIndexOp(op, varIndex); return; } throw Kit.codeBug(); } private void addStringOp(int op, String str) { addStringPrefix(str); if (validIcode(op)) { addIcode(op); } else { addToken(op); } } private void addIndexOp(int op, int index) { addIndexPrefix(index); if (validIcode(op)) { addIcode(op); } else { addToken(op); } } private void addStringPrefix(String str) { int index = itsStrings.get(str, -1); if (index == -1) { index = itsStrings.size(); itsStrings.put(str, index); } if (index < 4) { addIcode(Icode_REG_STR_C0 - index); } else if (index <= 0xFF) { addIcode(Icode_REG_STR1); addUint8(index); } else if (index <= 0xFFFF) { addIcode(Icode_REG_STR2); addUint16(index); } else { addIcode(Icode_REG_STR4); addInt(index); } } private void addIndexPrefix(int index) { if (index < 0) Kit.codeBug(); if (index < 6) { addIcode(Icode_REG_IND_C0 - index); } else if (index <= 0xFF) { addIcode(Icode_REG_IND1); addUint8(index); } else if (index <= 0xFFFF) { addIcode(Icode_REG_IND2); addUint16(index); } else { addIcode(Icode_REG_IND4); addInt(index); } } private void addExceptionHandler(int icodeStart, int icodeEnd, int handlerStart, boolean isFinally, int exceptionObjectLocal, int scopeLocal) { int top = itsExceptionTableTop; int[] table = itsData.itsExceptionTable; if (table == null) { if (top != 0) Kit.codeBug(); table = new int[EXCEPTION_SLOT_SIZE * 2]; itsData.itsExceptionTable = table; } else if (table.length == top) { table = new int[table.length * 2]; System.arraycopy(itsData.itsExceptionTable, 0, table, 0, top); itsData.itsExceptionTable = table; } table[top + EXCEPTION_TRY_START_SLOT] = icodeStart; table[top + EXCEPTION_TRY_END_SLOT] = icodeEnd; table[top + EXCEPTION_HANDLER_SLOT] = handlerStart; table[top + EXCEPTION_TYPE_SLOT] = isFinally ? 1 : 0; table[top + EXCEPTION_LOCAL_SLOT] = exceptionObjectLocal; table[top + EXCEPTION_SCOPE_SLOT] = scopeLocal; itsExceptionTableTop = top + EXCEPTION_SLOT_SIZE; } private byte[] increaseICodeCapasity(int extraSize) { int capacity = itsData.itsICode.length; int top = itsICodeTop; if (top + extraSize <= capacity) throw Kit.codeBug(); capacity *= 2; if (top + extraSize > capacity) { capacity = top + extraSize; } byte[] array = new byte[capacity]; System.arraycopy(itsData.itsICode, 0, array, 0, top); itsData.itsICode = array; return array; } private void stackChange(int change) { if (change <= 0) { itsStackDepth += change; } else { int newDepth = itsStackDepth + change; if (newDepth > itsData.itsMaxStack) { itsData.itsMaxStack = newDepth; } itsStackDepth = newDepth; } } private int allocLocal() { int localSlot = itsLocalTop; ++itsLocalTop; if (itsLocalTop > itsData.itsMaxLocals) { itsData.itsMaxLocals = itsLocalTop; } return localSlot; } private void releaseLocal(int localSlot) { --itsLocalTop; if (localSlot != itsLocalTop) Kit.codeBug(); } private static int getShort(byte[] iCode, int pc) { return (iCode[pc] << 8) | (iCode[pc + 1] & 0xFF); } private static int getIndex(byte[] iCode, int pc) { return ((iCode[pc] & 0xFF) << 8) | (iCode[pc + 1] & 0xFF); } private static int getInt(byte[] iCode, int pc) { return (iCode[pc] << 24) | ((iCode[pc + 1] & 0xFF) << 16) | ((iCode[pc + 2] & 0xFF) << 8) | (iCode[pc + 3] & 0xFF); } private static int getExceptionHandler(CallFrame frame, boolean onlyFinally) { int[] exceptionTable = frame.idata.itsExceptionTable; if (exceptionTable == null) { // No exception handlers return -1; } // Icode switch in the interpreter increments PC immediately // and it is necessary to subtract 1 from the saved PC // to point it before the start of the next instruction. int pc = frame.pc - 1; // OPT: use binary search int best = -1, bestStart = 0, bestEnd = 0; for (int i = 0; i != exceptionTable.length; i += EXCEPTION_SLOT_SIZE) { int start = exceptionTable[i + EXCEPTION_TRY_START_SLOT]; int end = exceptionTable[i + EXCEPTION_TRY_END_SLOT]; if (!(start <= pc && pc < end)) { continue; } if (onlyFinally && exceptionTable[i + EXCEPTION_TYPE_SLOT] != 1) { continue; } if (best >= 0) { // Since handlers always nest and they never have shared end // although they can share start it is sufficient to compare // handlers ends if (bestEnd < end) { continue; } // Check the above assumption if (bestStart > start) Kit.codeBug(); // should be nested if (bestEnd == end) Kit.codeBug(); // no ens sharing } best = i; bestStart = start; bestEnd = end; } return best; } private static void dumpICode(InterpreterData idata) { if (!Token.printICode) { return; } byte iCode[] = idata.itsICode; int iCodeLength = iCode.length; String[] strings = idata.itsStringTable; PrintStream out = System.out; out.println("ICode dump, for " + idata.itsName + ", length = " + iCodeLength); out.println("MaxStack = " + idata.itsMaxStack); int indexReg = 0; for (int pc = 0; pc < iCodeLength; ) { out.flush(); out.print(" [" + pc + "] "); int token = iCode[pc]; int icodeLength = bytecodeSpan(token); String tname = bytecodeName(token); int old_pc = pc; ++pc; switch (token) { default: if (icodeLength != 1) Kit.codeBug(); out.println(tname); break; case Icode_GOSUB : case Token.GOTO : case Token.IFEQ : case Token.IFNE : case Icode_IFEQ_POP : case Icode_LEAVEDQ : { int newPC = pc + getShort(iCode, pc) - 1; out.println(tname + " " + newPC); pc += 2; break; } case Icode_VAR_INC_DEC : case Icode_NAME_INC_DEC : case Icode_PROP_INC_DEC : case Icode_ELEM_INC_DEC : case Icode_REF_INC_DEC: { int incrDecrType = iCode[pc]; out.println(tname + " " + incrDecrType); ++pc; break; } case Icode_CALLSPECIAL : { int callType = iCode[pc] & 0xFF; boolean isNew = (iCode[pc + 1] != 0); int line = getIndex(iCode, pc+2); out.println(tname+" "+callType+" "+isNew+" "+indexReg+" "+line); pc += 4; break; } case Token.CATCH_SCOPE: { boolean afterFisrtFlag = (iCode[pc] != 0); out.println(tname+" "+afterFisrtFlag); ++pc; } break; case Token.REGEXP : out.println(tname+" "+idata.itsRegExpLiterals[indexReg]); break; case Token.OBJECTLIT : case Icode_SPARE_ARRAYLIT : out.println(tname+" "+idata.literalIds[indexReg]); break; case Icode_CLOSURE_EXPR : case Icode_CLOSURE_STMT : out.println(tname+" "+idata.itsNestedFunctions[indexReg]); break; case Token.CALL : case Icode_TAIL_CALL : case Token.REF_CALL : case Token.NEW : out.println(tname+' '+indexReg); break; case Token.THROW : { int line = getIndex(iCode, pc); out.println(tname + " : " + line); pc += 2; break; } case Icode_SHORTNUMBER : { int value = getShort(iCode, pc); out.println(tname + " " + value); pc += 2; break; } case Icode_INTNUMBER : { int value = getInt(iCode, pc); out.println(tname + " " + value); pc += 4; break; } case Token.NUMBER : { double value = idata.itsDoubleTable[indexReg]; out.println(tname + " " + value); pc += 2; break; } case Icode_LINE : { int line = getIndex(iCode, pc); out.println(tname + " : " + line); pc += 2; break; } case Icode_REG_STR1: {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -