⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 classfilewriter.java

📁 java中比较著名的js引擎当属mozilla开源的rhino
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
    }    public void setTableSwitchJump(int switchStart, int caseIndex,                                   int jumpTarget)    {        if (!(0 <= jumpTarget && jumpTarget <= itsCodeBufferTop))            throw new IllegalArgumentException("Bad jump target: "+jumpTarget);        if (!(caseIndex >= -1))            throw new IllegalArgumentException("Bad case index: "+caseIndex);        int padSize = 3 & ~switchStart; // == 3 - switchStart % 4        int caseOffset;        if (caseIndex < 0) {            // default label            caseOffset = switchStart + 1 + padSize;        } else {            caseOffset = switchStart + 1 + padSize + 4 * (3 + caseIndex);        }        if (!(0 <= switchStart              && switchStart <= itsCodeBufferTop - 4 * 4 - padSize - 1))        {            throw new IllegalArgumentException(                switchStart+" is outside a possible range of tableswitch"                +" in already generated code");        }        if ((0xFF & itsCodeBuffer[switchStart]) != ByteCode.TABLESWITCH) {            throw new IllegalArgumentException(                switchStart+" is not offset of tableswitch statement");        }        if (!(0 <= caseOffset && caseOffset + 4 <= itsCodeBufferTop)) {            // caseIndex >= -1 does not guarantee that caseOffset >= 0 due            // to a possible overflow.            throw new IllegalArgumentException(                "Too big case index: "+caseIndex);        }        // ALERT: perhaps check against case bounds?        putInt32(jumpTarget - switchStart, itsCodeBuffer, caseOffset);    }    public int acquireLabel()    {        int top = itsLabelTableTop;        if (itsLabelTable == null || top == 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, top);                itsLabelTable = tmp;            }        }        itsLabelTableTop = top + 1;        itsLabelTable[top] = -1;        return top | 0x80000000;    }    public void markLabel(int label)    {        if (!(label < 0))            throw new IllegalArgumentException("Bad label, no biscuit");        label &= 0x7FFFFFFF;        if (label > itsLabelTableTop)            throw new IllegalArgumentException("Bad label");        if (itsLabelTable[label] != -1) {            throw new IllegalStateException("Can only mark label once");        }        itsLabelTable[label] = itsCodeBufferTop;    }    public void markLabel(int label, short stackTop)    {        markLabel(label);        itsStackTop = stackTop;    }    public void markHandler(int theLabel) {        itsStackTop = 1;        markLabel(theLabel);    }    private int getLabelPC(int label)    {        if (!(label < 0))            throw new IllegalArgumentException("Bad label, no biscuit");        label &= 0x7FFFFFFF;        if (!(label < itsLabelTableTop))            throw new IllegalArgumentException("Bad label");        return itsLabelTable[label];    }    private void addLabelFixup(int label, int fixupSite)    {        if (!(label < 0))            throw new IllegalArgumentException("Bad label, no biscuit");        label &= 0x7FFFFFFF;        if (!(label < itsLabelTableTop))            throw new IllegalArgumentException("Bad label");        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) | fixupSite;    }    private  void fixLabelGotos()    {        byte[] codeBuffer = itsCodeBuffer;        for (int i = 0; i < itsFixupTableTop; i++) {            long fixup = itsFixupTable[i];            int label = (int)(fixup >> 32);            int fixupSite = (int)fixup;            int pc = itsLabelTable[label];            if (pc == -1) {                // Unlocated label                throw new RuntimeException();            }            // -1 to get delta from instruction start            int offset = pc - (fixupSite - 1);            if ((short)offset != offset) {                throw new RuntimeException                    ("Program too complex: too big jump offset");            }            codeBuffer[fixupSite] = (byte)(offset >> 8);            codeBuffer[fixupSite + 1] = (byte)offset;        }        itsFixupTableTop = 0;    }    /**     * Get the current offset into the code of the current method.     *     * @return an integer representing the offset     */    public int getCurrentCodeOffset() {        return itsCodeBufferTop;    }    public short getStackTop() {        return itsStackTop;    }    public void adjustStackTop(int delta) {        int newStack = itsStackTop + delta;        if (newStack < 0 || Short.MAX_VALUE < newStack) badStack(newStack);        itsStackTop = (short)newStack;        if (newStack > itsMaxStack) itsMaxStack = (short)newStack;        if (DEBUGSTACK) {            System.out.println("After "+"adjustStackTop("+delta+")"                               +" stack = "+itsStackTop);        }    }    private void addToCodeBuffer(int b)    {        int N = addReservedCodeSpace(1);        itsCodeBuffer[N] = (byte)b;    }    private void addToCodeInt16(int value)    {        int N = addReservedCodeSpace(2);        putInt16(value, itsCodeBuffer, N);    }    private int addReservedCodeSpace(int size)    {        if (itsCurrentMethod == null)            throw new IllegalArgumentException("No method to add to");        int oldTop = itsCodeBufferTop;        int newTop = oldTop + size;        if (newTop > itsCodeBuffer.length) {            int newSize = itsCodeBuffer.length * 2;            if (newTop > newSize) { newSize = newTop; }            byte[] tmp = new byte[newSize];            System.arraycopy(itsCodeBuffer, 0, tmp, 0, oldTop);            itsCodeBuffer = tmp;        }        itsCodeBufferTop = newTop;        return oldTop;    }    public void addExceptionHandler(int startLabel, int endLabel,                                    int handlerLabel, String catchClassName)    {        if ((startLabel & 0x80000000) != 0x80000000)            throw new IllegalArgumentException("Bad startLabel");        if ((endLabel & 0x80000000) != 0x80000000)            throw new IllegalArgumentException("Bad endLabel");        if ((handlerLabel & 0x80000000) != 0x80000000)            throw new IllegalArgumentException("Bad handlerLabel");        /*         * If catchClassName is null, use 0 for the catch_type_index; which         * means catch everything.  (Even when the verifier has let you throw         * something other than a Throwable.)         */        short catch_type_index = (catchClassName == null)                                 ? 0                                 : itsConstantPool.addClass(catchClassName);        ExceptionTableEntry newEntry = new ExceptionTableEntry(                                           startLabel,                                           endLabel,                                           handlerLabel,                                           catch_type_index);        int N = itsExceptionTableTop;        if (N == 0) {            itsExceptionTable = new ExceptionTableEntry[ExceptionTableSize];        } else if (N == itsExceptionTable.length) {            ExceptionTableEntry[] tmp = new ExceptionTableEntry[N * 2];            System.arraycopy(itsExceptionTable, 0, tmp, 0, N);            itsExceptionTable = tmp;        }        itsExceptionTable[N] = newEntry;        itsExceptionTableTop = N + 1;    }    public void addLineNumberEntry(short lineNumber) {        if (itsCurrentMethod == null)            throw new IllegalArgumentException("No method to stop");        int N = itsLineNumberTableTop;        if (N == 0) {            itsLineNumberTable = new int[LineNumberTableSize];        } else if (N == itsLineNumberTable.length) {            int[] tmp = new int[N * 2];            System.arraycopy(itsLineNumberTable, 0, tmp, 0, N);            itsLineNumberTable = tmp;        }        itsLineNumberTable[N] = (itsCodeBufferTop << 16) + lineNumber;        itsLineNumberTableTop = N + 1;    }    /**     * Write the class file to the OutputStream.     *     * @param oStream the stream to write to     * @throws IOException if writing to the stream produces an exception     */    public void write(OutputStream oStream)        throws IOException    {        byte[] array = toByteArray();        oStream.write(array);    }    private int getWriteSize()    {        int size = 0;        if (itsSourceFileNameIndex != 0) {            itsConstantPool.addUtf8("SourceFile");        }        size += 8; //writeLong(FileHeaderConstant);        size += itsConstantPool.getWriteSize();        size += 2; //writeShort(itsFlags);        size += 2; //writeShort(itsThisClassIndex);        size += 2; //writeShort(itsSuperClassIndex);        size += 2; //writeShort(itsInterfaces.size());        size += 2 * itsInterfaces.size();        size += 2; //writeShort(itsFields.size());        for (int i = 0; i < itsFields.size(); i++) {            size += ((ClassFileField)(itsFields.get(i))).getWriteSize();        }        size += 2; //writeShort(itsMethods.size());        for (int i = 0; i < itsMethods.size(); i++) {            size += ((ClassFileMethod)(itsMethods.get(i))).getWriteSize();        }        if (itsSourceFileNameIndex != 0) {            size += 2; //writeShort(1);  attributes count            size += 2; //writeShort(sourceFileAttributeNameIndex);            size += 4; //writeInt(2);            size += 2; //writeShort(itsSourceFileNameIndex);        }else {            size += 2; //out.writeShort(0);  no attributes        }        return size;    }    /**     * Get the class file as array of bytesto the OutputStream.     */    public byte[] toByteArray()    {        int dataSize = getWriteSize();        byte[] data = new byte[dataSize];        int offset = 0;        short sourceFileAttributeNameIndex = 0;        if (itsSourceFileNameIndex != 0) {            sourceFileAttributeNameIndex = itsConstantPool.addUtf8(                                               "SourceFile");        }        offset = putInt64(FileHeaderConstant, data, offset);        offset = itsConstantPool.write(data, offset);        offset = putInt16(itsFlags, data, offset);        offset = putInt16(itsThisClassIndex, data, offset);        offset = putInt16(itsSuperClassIndex, data, offset);        offset = putInt16(itsInterfaces.size(), data, offset);        for (int i = 0; i < itsInterfaces.size(); i++) {            int interfaceIndex = ((Short)(itsInterfaces.get(i))).shortValue();            offset = putInt16(interfaceIndex, data, offset);        }        offset = putInt16(itsFields.size(), data, offset);        for (int i = 0; i < itsFields.size(); i++) {            ClassFileField field = (ClassFileField)itsFields.get(i);            offset = field.write(data, offset);        }        offset = putInt16(itsMethods.size(), data, offset);        for (int i = 0; i < itsMethods.size(); i++) {            ClassFileMethod method = (ClassFileMethod)itsMethods.get(i);            offset = method.write(data, offset);        }        if (itsSourceFileNameIndex != 0) {            offset = putInt16(1, data, offset); // attributes count            offset = putInt16(sourceFileAttributeNameIndex, data, offset);            offset = putInt32(2, data, offset);            offset = putInt16(itsSourceFileNameIndex, data, offset);        } else {            offset = putInt16(0, data, offset); // no attributes        }        if (offset != dataSize) {            // Check getWriteSize is consistent with write!            throw new RuntimeException();        }        return data;    }    static int putInt64(long value, byte[] array, int offset)    {        offset = putInt32((int)(value >>> 32), array, offset);        return putInt32((int)value, array, offset);    }    private static void badStack(int value)    {        String s;        if (value < 0) { s = "Stack underflow: "+value; }        else { s = "Too big stack: "+value; }        throw new IllegalStateException(s);    }    /*        Really weird. Returns an int with # parameters in hi 16 bits, and        stack difference removal of parameters from stack and pushing the        result (it does not take into account removal of this in case of        non-static methods).        If Java really supported references we wouldn't have to be this        perverted.    */    private static int sizeOfParameters(String pString)    {        int length = pString.length();        int rightParenthesis = pString.lastIndexOf(')');        if (3 <= length /* minimal signature takes at least 3 chars: ()V */            && pString.charAt(0) == '('            && 1 <= rightParenthesis && rightParenthesis + 1 < length)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -