📄 interpreter.java
字号:
if (skipIndexes == null) { addToken(Token.ARRAYLIT); } else { int index = itsLiteralIds.size(); itsLiteralIds.add(skipIndexes); addIndexOp(Icode_SPARE_ARRAYLIT, index); } } else { int index = itsLiteralIds.size(); itsLiteralIds.add(propertyIds); addIndexOp(Token.OBJECTLIT, index); } stackChange(-1); } private void visitArrayComprehension(Node node, Node initStmt, Node expr) { // A bit of a hack: array comprehensions are implemented using // statement nodes for the iteration, yet they appear in an // expression context. So we pass the current stack depth to // visitStatement so it can check that the depth is not altered // by statements. visitStatement(initStmt, itsStackDepth); visitExpression(expr, 0); } private int getLocalBlockRef(Node node) { Node localBlock = (Node)node.getProp(Node.LOCAL_BLOCK_PROP); return localBlock.getExistingIntProp(Node.LOCAL_PROP); } private int getTargetLabel(Node target) { int label = target.labelId(); if (label != -1) { return label; } label = itsLabelTableTop; if (itsLabelTable == null || label == itsLabelTable.length) { if (itsLabelTable == null) { itsLabelTable = new int[MIN_LABEL_TABLE_SIZE]; }else { int[] tmp = new int[itsLabelTable.length * 2]; System.arraycopy(itsLabelTable, 0, tmp, 0, label); itsLabelTable = tmp; } } itsLabelTableTop = label + 1; itsLabelTable[label] = -1; target.labelId(label); return label; } private void markTargetLabel(Node target) { int label = getTargetLabel(target); if (itsLabelTable[label] != -1) { // Can mark label only once Kit.codeBug(); } itsLabelTable[label] = itsICodeTop; } private void addGoto(Node target, int gotoOp) { int label = getTargetLabel(target); if (!(label < itsLabelTableTop)) Kit.codeBug(); int targetPC = itsLabelTable[label]; if (targetPC != -1) { addBackwardGoto(gotoOp, targetPC); } else { int gotoPC = itsICodeTop; addGotoOp(gotoOp); int top = itsFixupTableTop; if (itsFixupTable == null || top == itsFixupTable.length) { if (itsFixupTable == null) { itsFixupTable = new long[MIN_FIXUP_TABLE_SIZE]; } else { long[] tmp = new long[itsFixupTable.length * 2]; System.arraycopy(itsFixupTable, 0, tmp, 0, top); itsFixupTable = tmp; } } itsFixupTableTop = top + 1; itsFixupTable[top] = ((long)label << 32) | gotoPC; } } private void fixLabelGotos() { for (int i = 0; i < itsFixupTableTop; i++) { long fixup = itsFixupTable[i]; int label = (int)(fixup >> 32); int jumpSource = (int)fixup; int pc = itsLabelTable[label]; if (pc == -1) { // Unlocated label throw Kit.codeBug(); } resolveGoto(jumpSource, pc); } itsFixupTableTop = 0; } private void addBackwardGoto(int gotoOp, int jumpPC) { int fromPC = itsICodeTop; // Ensure that this is a jump backward if (fromPC <= jumpPC) throw Kit.codeBug(); addGotoOp(gotoOp); resolveGoto(fromPC, jumpPC); } private void resolveForwardGoto(int fromPC) { // Ensure that forward jump skips at least self bytecode if (itsICodeTop < fromPC + 3) throw Kit.codeBug(); resolveGoto(fromPC, itsICodeTop); } private void resolveGoto(int fromPC, int jumpPC) { int offset = jumpPC - fromPC; // Ensure that jumps do not overlap if (0 <= offset && offset <= 2) throw Kit.codeBug(); int offsetSite = fromPC + 1; if (offset != (short)offset) { if (itsData.longJumps == null) { itsData.longJumps = new UintMap(); } itsData.longJumps.put(offsetSite, jumpPC); offset = 0; } byte[] array = itsData.itsICode; array[offsetSite] = (byte)(offset >> 8); array[offsetSite + 1] = (byte)offset; } private void addToken(int token) { if (!validTokenCode(token)) throw Kit.codeBug(); addUint8(token); } private void addIcode(int icode) { if (!validIcode(icode)) throw Kit.codeBug(); // Write negative icode as uint8 bits addUint8(icode & 0xFF); } private void addUint8(int value) { if ((value & ~0xFF) != 0) throw Kit.codeBug(); byte[] array = itsData.itsICode; int top = itsICodeTop; if (top == array.length) { array = increaseICodeCapacity(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 = increaseICodeCapacity(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 = increaseICodeCapacity(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 = increaseICodeCapacity(3); } array[top] = (byte)gotoOp; // Offset would written later itsICodeTop = top + 1 + 2; } private void addVarOp(int op, int varIndex) { switch (op) { case Token.SETCONSTVAR: if (varIndex < 128) { addIcode(Icode_SETCONSTVAR1); addUint8(varIndex); return; } addIndexOp(Icode_SETCONSTVAR, varIndex); return; 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[] increaseICodeCapacity(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) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -