0N/A/*
2362N/A * Copyright (c) 2001, 2004, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/Apackage sun.reflect;
0N/A
0N/Aclass ClassFileAssembler implements ClassFileConstants {
0N/A private ByteVector vec;
0N/A private short cpIdx = 0;
0N/A
0N/A public ClassFileAssembler() {
0N/A this(ByteVectorFactory.create());
0N/A }
0N/A
0N/A public ClassFileAssembler(ByteVector vec) {
0N/A this.vec = vec;
0N/A }
0N/A
0N/A public ByteVector getData() {
0N/A return vec;
0N/A }
0N/A
0N/A /** Length in bytes */
0N/A public short getLength() {
0N/A return (short) vec.getLength();
0N/A }
0N/A
0N/A public void emitMagicAndVersion() {
0N/A emitInt(0xCAFEBABE);
0N/A emitShort((short) 0);
0N/A emitShort((short) 49);
0N/A }
0N/A
0N/A public void emitInt(int val) {
0N/A emitByte((byte) (val >> 24));
0N/A emitByte((byte) ((val >> 16) & 0xFF));
0N/A emitByte((byte) ((val >> 8) & 0xFF));
0N/A emitByte((byte) (val & 0xFF));
0N/A }
0N/A
0N/A public void emitShort(short val) {
0N/A emitByte((byte) ((val >> 8) & 0xFF));
0N/A emitByte((byte) (val & 0xFF));
0N/A }
0N/A
0N/A // Support for labels; package-private
0N/A void emitShort(short bci, short val) {
0N/A vec.put(bci, (byte) ((val >> 8) & 0xFF));
0N/A vec.put(bci + 1, (byte) (val & 0xFF));
0N/A }
0N/A
0N/A public void emitByte(byte val) {
0N/A vec.add(val);
0N/A }
0N/A
0N/A public void append(ClassFileAssembler asm) {
0N/A append(asm.vec);
0N/A }
0N/A
0N/A public void append(ByteVector vec) {
0N/A for (int i = 0; i < vec.getLength(); i++) {
0N/A emitByte(vec.get(i));
0N/A }
0N/A }
0N/A
0N/A /** Keeps track of the current (one-based) constant pool index;
0N/A incremented after emitting one of the following constant pool
0N/A entries. Can fetch the current constant pool index for use in
0N/A later entries. Index points at the last valid constant pool
0N/A entry; initially invalid. It is illegal to fetch the constant
0N/A pool index before emitting at least one constant pool entry. */
0N/A public short cpi() {
0N/A if (cpIdx == 0) {
0N/A throw new RuntimeException("Illegal use of ClassFileAssembler");
0N/A }
0N/A return cpIdx;
0N/A }
0N/A
0N/A public void emitConstantPoolUTF8(String str) {
0N/A // NOTE: can not use str.getBytes("UTF-8") here because of
0N/A // bootstrapping issues with the character set converters.
0N/A byte[] bytes = UTF8.encode(str);
0N/A emitByte(CONSTANT_Utf8);
0N/A emitShort((short) bytes.length);
0N/A for (int i = 0; i < bytes.length; i++) {
0N/A emitByte(bytes[i]);
0N/A }
0N/A cpIdx++;
0N/A }
0N/A
0N/A public void emitConstantPoolClass(short index) {
0N/A emitByte(CONSTANT_Class);
0N/A emitShort(index);
0N/A cpIdx++;
0N/A }
0N/A
0N/A public void emitConstantPoolNameAndType(short nameIndex, short typeIndex) {
0N/A emitByte(CONSTANT_NameAndType);
0N/A emitShort(nameIndex);
0N/A emitShort(typeIndex);
0N/A cpIdx++;
0N/A }
0N/A
0N/A public void emitConstantPoolFieldref
0N/A (short classIndex, short nameAndTypeIndex)
0N/A {
0N/A emitByte(CONSTANT_Fieldref);
0N/A emitShort(classIndex);
0N/A emitShort(nameAndTypeIndex);
0N/A cpIdx++;
0N/A }
0N/A
0N/A public void emitConstantPoolMethodref
0N/A (short classIndex, short nameAndTypeIndex)
0N/A {
0N/A emitByte(CONSTANT_Methodref);
0N/A emitShort(classIndex);
0N/A emitShort(nameAndTypeIndex);
0N/A cpIdx++;
0N/A }
0N/A
0N/A public void emitConstantPoolInterfaceMethodref
0N/A (short classIndex, short nameAndTypeIndex)
0N/A {
0N/A emitByte(CONSTANT_InterfaceMethodref);
0N/A emitShort(classIndex);
0N/A emitShort(nameAndTypeIndex);
0N/A cpIdx++;
0N/A }
0N/A
0N/A public void emitConstantPoolString(short utf8Index) {
0N/A emitByte(CONSTANT_String);
0N/A emitShort(utf8Index);
0N/A cpIdx++;
0N/A }
0N/A
0N/A //----------------------------------------------------------------------
0N/A // Opcodes. Keeps track of maximum stack and locals. Make a new
0N/A // assembler for each piece of assembled code, then append the
0N/A // result to the previous assembler's class file.
0N/A //
0N/A
0N/A private int stack = 0;
0N/A private int maxStack = 0;
0N/A private int maxLocals = 0;
0N/A
0N/A private void incStack() {
0N/A setStack(stack + 1);
0N/A }
0N/A
0N/A private void decStack() {
0N/A --stack;
0N/A }
0N/A
0N/A public short getMaxStack() {
0N/A return (short) maxStack;
0N/A }
0N/A
0N/A public short getMaxLocals() {
0N/A return (short) maxLocals;
0N/A }
0N/A
0N/A /** It's necessary to be able to specify the number of arguments at
0N/A the beginning of the method (which translates to the initial
0N/A value of max locals) */
0N/A public void setMaxLocals(int maxLocals) {
0N/A this.maxLocals = maxLocals;
0N/A }
0N/A
0N/A /** Needed to do flow control. Returns current stack depth. */
0N/A public int getStack() {
0N/A return stack;
0N/A }
0N/A
0N/A /** Needed to do flow control. */
0N/A public void setStack(int value) {
0N/A stack = value;
0N/A if (stack > maxStack) {
0N/A maxStack = stack;
0N/A }
0N/A }
0N/A
0N/A ///////////////
0N/A // Constants //
0N/A ///////////////
0N/A
0N/A public void opc_aconst_null() {
0N/A emitByte(opc_aconst_null);
0N/A incStack();
0N/A }
0N/A
0N/A public void opc_sipush(short constant) {
0N/A emitByte(opc_sipush);
0N/A emitShort(constant);
0N/A incStack();
0N/A }
0N/A
0N/A public void opc_ldc(byte cpIdx) {
0N/A emitByte(opc_ldc);
0N/A emitByte(cpIdx);
0N/A incStack();
0N/A }
0N/A
0N/A /////////////////////////////////////
0N/A // Local variable loads and stores //
0N/A /////////////////////////////////////
0N/A
0N/A public void opc_iload_0() {
0N/A emitByte(opc_iload_0);
0N/A if (maxLocals < 1) maxLocals = 1;
0N/A incStack();
0N/A }
0N/A
0N/A public void opc_iload_1() {
0N/A emitByte(opc_iload_1);
0N/A if (maxLocals < 2) maxLocals = 2;
0N/A incStack();
0N/A }
0N/A
0N/A public void opc_iload_2() {
0N/A emitByte(opc_iload_2);
0N/A if (maxLocals < 3) maxLocals = 3;
0N/A incStack();
0N/A }
0N/A
0N/A public void opc_iload_3() {
0N/A emitByte(opc_iload_3);
0N/A if (maxLocals < 4) maxLocals = 4;
0N/A incStack();
0N/A }
0N/A
0N/A public void opc_lload_0() {
0N/A emitByte(opc_lload_0);
0N/A if (maxLocals < 2) maxLocals = 2;
0N/A incStack();
0N/A incStack();
0N/A }
0N/A
0N/A public void opc_lload_1() {
0N/A emitByte(opc_lload_1);
0N/A if (maxLocals < 3) maxLocals = 3;
0N/A incStack();
0N/A incStack();
0N/A }
0N/A
0N/A public void opc_lload_2() {
0N/A emitByte(opc_lload_2);
0N/A if (maxLocals < 4) maxLocals = 4;
0N/A incStack();
0N/A incStack();
0N/A }
0N/A
0N/A public void opc_lload_3() {
0N/A emitByte(opc_lload_3);
0N/A if (maxLocals < 5) maxLocals = 5;
0N/A incStack();
0N/A incStack();
0N/A }
0N/A
0N/A public void opc_fload_0() {
0N/A emitByte(opc_fload_0);
0N/A if (maxLocals < 1) maxLocals = 1;
0N/A incStack();
0N/A }
0N/A
0N/A public void opc_fload_1() {
0N/A emitByte(opc_fload_1);
0N/A if (maxLocals < 2) maxLocals = 2;
0N/A incStack();
0N/A }
0N/A
0N/A public void opc_fload_2() {
0N/A emitByte(opc_fload_2);
0N/A if (maxLocals < 3) maxLocals = 3;
0N/A incStack();
0N/A }
0N/A
0N/A public void opc_fload_3() {
0N/A emitByte(opc_fload_3);
0N/A if (maxLocals < 4) maxLocals = 4;
0N/A incStack();
0N/A }
0N/A
0N/A public void opc_dload_0() {
0N/A emitByte(opc_dload_0);
0N/A if (maxLocals < 2) maxLocals = 2;
0N/A incStack();
0N/A incStack();
0N/A }
0N/A
0N/A public void opc_dload_1() {
0N/A emitByte(opc_dload_1);
0N/A if (maxLocals < 3) maxLocals = 3;
0N/A incStack();
0N/A incStack();
0N/A }
0N/A
0N/A public void opc_dload_2() {
0N/A emitByte(opc_dload_2);
0N/A if (maxLocals < 4) maxLocals = 4;
0N/A incStack();
0N/A incStack();
0N/A }
0N/A
0N/A public void opc_dload_3() {
0N/A emitByte(opc_dload_3);
0N/A if (maxLocals < 5) maxLocals = 5;
0N/A incStack();
0N/A incStack();
0N/A }
0N/A
0N/A public void opc_aload_0() {
0N/A emitByte(opc_aload_0);
0N/A if (maxLocals < 1) maxLocals = 1;
0N/A incStack();
0N/A }
0N/A
0N/A public void opc_aload_1() {
0N/A emitByte(opc_aload_1);
0N/A if (maxLocals < 2) maxLocals = 2;
0N/A incStack();
0N/A }
0N/A
0N/A public void opc_aload_2() {
0N/A emitByte(opc_aload_2);
0N/A if (maxLocals < 3) maxLocals = 3;
0N/A incStack();
0N/A }
0N/A
0N/A public void opc_aload_3() {
0N/A emitByte(opc_aload_3);
0N/A if (maxLocals < 4) maxLocals = 4;
0N/A incStack();
0N/A }
0N/A
0N/A public void opc_aaload() {
0N/A emitByte(opc_aaload);
0N/A decStack();
0N/A }
0N/A
0N/A public void opc_astore_0() {
0N/A emitByte(opc_astore_0);
0N/A if (maxLocals < 1) maxLocals = 1;
0N/A decStack();
0N/A }
0N/A
0N/A public void opc_astore_1() {
0N/A emitByte(opc_astore_1);
0N/A if (maxLocals < 2) maxLocals = 2;
0N/A decStack();
0N/A }
0N/A
0N/A public void opc_astore_2() {
0N/A emitByte(opc_astore_2);
0N/A if (maxLocals < 3) maxLocals = 3;
0N/A decStack();
0N/A }
0N/A
0N/A public void opc_astore_3() {
0N/A emitByte(opc_astore_3);
0N/A if (maxLocals < 4) maxLocals = 4;
0N/A decStack();
0N/A }
0N/A
0N/A ////////////////////////
0N/A // Stack manipulation //
0N/A ////////////////////////
0N/A
0N/A public void opc_pop() {
0N/A emitByte(opc_pop);
0N/A decStack();
0N/A }
0N/A
0N/A public void opc_dup() {
0N/A emitByte(opc_dup);
0N/A incStack();
0N/A }
0N/A
0N/A public void opc_dup_x1() {
0N/A emitByte(opc_dup_x1);
0N/A incStack();
0N/A }
0N/A
0N/A public void opc_swap() {
0N/A emitByte(opc_swap);
0N/A }
0N/A
0N/A ///////////////////////////////
0N/A // Widening conversions only //
0N/A ///////////////////////////////
0N/A
0N/A public void opc_i2l() {
0N/A emitByte(opc_i2l);
0N/A }
0N/A
0N/A public void opc_i2f() {
0N/A emitByte(opc_i2f);
0N/A }
0N/A
0N/A public void opc_i2d() {
0N/A emitByte(opc_i2d);
0N/A }
0N/A
0N/A public void opc_l2f() {
0N/A emitByte(opc_l2f);
0N/A }
0N/A
0N/A public void opc_l2d() {
0N/A emitByte(opc_l2d);
0N/A }
0N/A
0N/A public void opc_f2d() {
0N/A emitByte(opc_f2d);
0N/A }
0N/A
0N/A //////////////////
0N/A // Control flow //
0N/A //////////////////
0N/A
0N/A public void opc_ifeq(short bciOffset) {
0N/A emitByte(opc_ifeq);
0N/A emitShort(bciOffset);
0N/A decStack();
0N/A }
0N/A
0N/A /** Control flow with forward-reference BCI. Stack assumes
0N/A straight-through control flow. */
0N/A public void opc_ifeq(Label l) {
0N/A short instrBCI = getLength();
0N/A emitByte(opc_ifeq);
0N/A l.add(this, instrBCI, getLength(), getStack() - 1);
0N/A emitShort((short) -1); // Must be patched later
0N/A }
0N/A
0N/A public void opc_if_icmpeq(short bciOffset) {
0N/A emitByte(opc_if_icmpeq);
0N/A emitShort(bciOffset);
0N/A setStack(getStack() - 2);
0N/A }
0N/A
0N/A /** Control flow with forward-reference BCI. Stack assumes straight
0N/A control flow. */
0N/A public void opc_if_icmpeq(Label l) {
0N/A short instrBCI = getLength();
0N/A emitByte(opc_if_icmpeq);
0N/A l.add(this, instrBCI, getLength(), getStack() - 2);
0N/A emitShort((short) -1); // Must be patched later
0N/A }
0N/A
0N/A public void opc_goto(short bciOffset) {
0N/A emitByte(opc_goto);
0N/A emitShort(bciOffset);
0N/A }
0N/A
0N/A /** Control flow with forward-reference BCI. Stack assumes straight
0N/A control flow. */
0N/A public void opc_goto(Label l) {
0N/A short instrBCI = getLength();
0N/A emitByte(opc_goto);
0N/A l.add(this, instrBCI, getLength(), getStack());
0N/A emitShort((short) -1); // Must be patched later
0N/A }
0N/A
0N/A public void opc_ifnull(short bciOffset) {
0N/A emitByte(opc_ifnull);
0N/A emitShort(bciOffset);
0N/A decStack();
0N/A }
0N/A
0N/A /** Control flow with forward-reference BCI. Stack assumes straight
0N/A control flow. */
0N/A public void opc_ifnull(Label l) {
0N/A short instrBCI = getLength();
0N/A emitByte(opc_ifnull);
0N/A l.add(this, instrBCI, getLength(), getStack() - 1);
0N/A emitShort((short) -1); // Must be patched later
0N/A decStack();
0N/A }
0N/A
0N/A public void opc_ifnonnull(short bciOffset) {
0N/A emitByte(opc_ifnonnull);
0N/A emitShort(bciOffset);
0N/A decStack();
0N/A }
0N/A
0N/A /** Control flow with forward-reference BCI. Stack assumes straight
0N/A control flow. */
0N/A public void opc_ifnonnull(Label l) {
0N/A short instrBCI = getLength();
0N/A emitByte(opc_ifnonnull);
0N/A l.add(this, instrBCI, getLength(), getStack() - 1);
0N/A emitShort((short) -1); // Must be patched later
0N/A decStack();
0N/A }
0N/A
0N/A /////////////////////////
0N/A // Return instructions //
0N/A /////////////////////////
0N/A
0N/A public void opc_ireturn() {
0N/A emitByte(opc_ireturn);
0N/A setStack(0);
0N/A }
0N/A
0N/A public void opc_lreturn() {
0N/A emitByte(opc_lreturn);
0N/A setStack(0);
0N/A }
0N/A
0N/A public void opc_freturn() {
0N/A emitByte(opc_freturn);
0N/A setStack(0);
0N/A }
0N/A
0N/A public void opc_dreturn() {
0N/A emitByte(opc_dreturn);
0N/A setStack(0);
0N/A }
0N/A
0N/A public void opc_areturn() {
0N/A emitByte(opc_areturn);
0N/A setStack(0);
0N/A }
0N/A
0N/A public void opc_return() {
0N/A emitByte(opc_return);
0N/A setStack(0);
0N/A }
0N/A
0N/A //////////////////////
0N/A // Field operations //
0N/A //////////////////////
0N/A
0N/A public void opc_getstatic(short fieldIndex, int fieldSizeInStackSlots) {
0N/A emitByte(opc_getstatic);
0N/A emitShort(fieldIndex);
0N/A setStack(getStack() + fieldSizeInStackSlots);
0N/A }
0N/A
0N/A public void opc_putstatic(short fieldIndex, int fieldSizeInStackSlots) {
0N/A emitByte(opc_putstatic);
0N/A emitShort(fieldIndex);
0N/A setStack(getStack() - fieldSizeInStackSlots);
0N/A }
0N/A
0N/A public void opc_getfield(short fieldIndex, int fieldSizeInStackSlots) {
0N/A emitByte(opc_getfield);
0N/A emitShort(fieldIndex);
0N/A setStack(getStack() + fieldSizeInStackSlots - 1);
0N/A }
0N/A
0N/A public void opc_putfield(short fieldIndex, int fieldSizeInStackSlots) {
0N/A emitByte(opc_putfield);
0N/A emitShort(fieldIndex);
0N/A setStack(getStack() - fieldSizeInStackSlots - 1);
0N/A }
0N/A
0N/A ////////////////////////
0N/A // Method invocations //
0N/A ////////////////////////
0N/A
0N/A /** Long and double arguments and return types count as 2 arguments;
0N/A other values count as 1. */
0N/A public void opc_invokevirtual(short methodIndex,
0N/A int numArgs,
0N/A int numReturnValues)
0N/A {
0N/A emitByte(opc_invokevirtual);
0N/A emitShort(methodIndex);
0N/A setStack(getStack() - numArgs - 1 + numReturnValues);
0N/A }
0N/A
0N/A /** Long and double arguments and return types count as 2 arguments;
0N/A other values count as 1. */
0N/A public void opc_invokespecial(short methodIndex,
0N/A int numArgs,
0N/A int numReturnValues)
0N/A {
0N/A emitByte(opc_invokespecial);
0N/A emitShort(methodIndex);
0N/A setStack(getStack() - numArgs - 1 + numReturnValues);
0N/A }
0N/A
0N/A /** Long and double arguments and return types count as 2 arguments;
0N/A other values count as 1. */
0N/A public void opc_invokestatic(short methodIndex,
0N/A int numArgs,
0N/A int numReturnValues)
0N/A {
0N/A emitByte(opc_invokestatic);
0N/A emitShort(methodIndex);
0N/A setStack(getStack() - numArgs + numReturnValues);
0N/A }
0N/A
0N/A /** Long and double arguments and return types count as 2 arguments;
0N/A other values count as 1. */
0N/A public void opc_invokeinterface(short methodIndex,
0N/A int numArgs,
0N/A byte count,
0N/A int numReturnValues)
0N/A {
0N/A emitByte(opc_invokeinterface);
0N/A emitShort(methodIndex);
0N/A emitByte(count);
0N/A emitByte((byte) 0);
0N/A setStack(getStack() - numArgs - 1 + numReturnValues);
0N/A }
0N/A
0N/A //////////////////
0N/A // Array length //
0N/A //////////////////
0N/A
0N/A public void opc_arraylength() {
0N/A emitByte(opc_arraylength);
0N/A }
0N/A
0N/A /////////
0N/A // New //
0N/A /////////
0N/A
0N/A public void opc_new(short classIndex) {
0N/A emitByte(opc_new);
0N/A emitShort(classIndex);
0N/A incStack();
0N/A }
0N/A
0N/A ////////////
0N/A // Athrow //
0N/A ////////////
0N/A
0N/A public void opc_athrow() {
0N/A emitByte(opc_athrow);
0N/A setStack(1);
0N/A }
0N/A
0N/A //////////////////////////////
0N/A // Checkcast and instanceof //
0N/A //////////////////////////////
0N/A
0N/A /** Assumes the checkcast succeeds */
0N/A public void opc_checkcast(short classIndex) {
0N/A emitByte(opc_checkcast);
0N/A emitShort(classIndex);
0N/A }
0N/A
0N/A public void opc_instanceof(short classIndex) {
0N/A emitByte(opc_instanceof);
0N/A emitShort(classIndex);
0N/A }
0N/A}