Path: blob/master/src/java.base/share/classes/jdk/internal/reflect/ClassFileAssembler.java
41159 views
/*1* Copyright (c) 2001, 2004, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package jdk.internal.reflect;2627class ClassFileAssembler implements ClassFileConstants {28private ByteVector vec;29private short cpIdx = 0;3031public ClassFileAssembler() {32this(ByteVectorFactory.create());33}3435public ClassFileAssembler(ByteVector vec) {36this.vec = vec;37}3839public ByteVector getData() {40return vec;41}4243/** Length in bytes */44public short getLength() {45return (short) vec.getLength();46}4748public void emitMagicAndVersion() {49emitInt(0xCAFEBABE);50emitShort((short) 0);51emitShort((short) 49);52}5354public void emitInt(int val) {55emitByte((byte) (val >> 24));56emitByte((byte) ((val >> 16) & 0xFF));57emitByte((byte) ((val >> 8) & 0xFF));58emitByte((byte) (val & 0xFF));59}6061public void emitShort(short val) {62emitByte((byte) ((val >> 8) & 0xFF));63emitByte((byte) (val & 0xFF));64}6566// Support for labels; package-private67void emitShort(short bci, short val) {68vec.put(bci, (byte) ((val >> 8) & 0xFF));69vec.put(bci + 1, (byte) (val & 0xFF));70}7172public void emitByte(byte val) {73vec.add(val);74}7576public void append(ClassFileAssembler asm) {77append(asm.vec);78}7980public void append(ByteVector vec) {81for (int i = 0; i < vec.getLength(); i++) {82emitByte(vec.get(i));83}84}8586/** Keeps track of the current (one-based) constant pool index;87incremented after emitting one of the following constant pool88entries. Can fetch the current constant pool index for use in89later entries. Index points at the last valid constant pool90entry; initially invalid. It is illegal to fetch the constant91pool index before emitting at least one constant pool entry. */92public short cpi() {93if (cpIdx == 0) {94throw new RuntimeException("Illegal use of ClassFileAssembler");95}96return cpIdx;97}9899public void emitConstantPoolUTF8(String str) {100// NOTE: can not use str.getBytes("UTF-8") here because of101// bootstrapping issues with the character set converters.102byte[] bytes = UTF8.encode(str);103emitByte(CONSTANT_Utf8);104emitShort((short) bytes.length);105for (int i = 0; i < bytes.length; i++) {106emitByte(bytes[i]);107}108cpIdx++;109}110111public void emitConstantPoolClass(short index) {112emitByte(CONSTANT_Class);113emitShort(index);114cpIdx++;115}116117public void emitConstantPoolNameAndType(short nameIndex, short typeIndex) {118emitByte(CONSTANT_NameAndType);119emitShort(nameIndex);120emitShort(typeIndex);121cpIdx++;122}123124public void emitConstantPoolFieldref125(short classIndex, short nameAndTypeIndex)126{127emitByte(CONSTANT_Fieldref);128emitShort(classIndex);129emitShort(nameAndTypeIndex);130cpIdx++;131}132133public void emitConstantPoolMethodref134(short classIndex, short nameAndTypeIndex)135{136emitByte(CONSTANT_Methodref);137emitShort(classIndex);138emitShort(nameAndTypeIndex);139cpIdx++;140}141142public void emitConstantPoolInterfaceMethodref143(short classIndex, short nameAndTypeIndex)144{145emitByte(CONSTANT_InterfaceMethodref);146emitShort(classIndex);147emitShort(nameAndTypeIndex);148cpIdx++;149}150151public void emitConstantPoolString(short utf8Index) {152emitByte(CONSTANT_String);153emitShort(utf8Index);154cpIdx++;155}156157//----------------------------------------------------------------------158// Opcodes. Keeps track of maximum stack and locals. Make a new159// assembler for each piece of assembled code, then append the160// result to the previous assembler's class file.161//162163private int stack = 0;164private int maxStack = 0;165private int maxLocals = 0;166167private void incStack() {168setStack(stack + 1);169}170171private void decStack() {172--stack;173}174175public short getMaxStack() {176return (short) maxStack;177}178179public short getMaxLocals() {180return (short) maxLocals;181}182183/** It's necessary to be able to specify the number of arguments at184the beginning of the method (which translates to the initial185value of max locals) */186public void setMaxLocals(int maxLocals) {187this.maxLocals = maxLocals;188}189190/** Needed to do flow control. Returns current stack depth. */191public int getStack() {192return stack;193}194195/** Needed to do flow control. */196public void setStack(int value) {197stack = value;198if (stack > maxStack) {199maxStack = stack;200}201}202203///////////////204// Constants //205///////////////206207public void opc_aconst_null() {208emitByte(opc_aconst_null);209incStack();210}211212public void opc_sipush(short constant) {213emitByte(opc_sipush);214emitShort(constant);215incStack();216}217218public void opc_ldc(byte cpIdx) {219emitByte(opc_ldc);220emitByte(cpIdx);221incStack();222}223224/////////////////////////////////////225// Local variable loads and stores //226/////////////////////////////////////227228public void opc_iload_0() {229emitByte(opc_iload_0);230if (maxLocals < 1) maxLocals = 1;231incStack();232}233234public void opc_iload_1() {235emitByte(opc_iload_1);236if (maxLocals < 2) maxLocals = 2;237incStack();238}239240public void opc_iload_2() {241emitByte(opc_iload_2);242if (maxLocals < 3) maxLocals = 3;243incStack();244}245246public void opc_iload_3() {247emitByte(opc_iload_3);248if (maxLocals < 4) maxLocals = 4;249incStack();250}251252public void opc_lload_0() {253emitByte(opc_lload_0);254if (maxLocals < 2) maxLocals = 2;255incStack();256incStack();257}258259public void opc_lload_1() {260emitByte(opc_lload_1);261if (maxLocals < 3) maxLocals = 3;262incStack();263incStack();264}265266public void opc_lload_2() {267emitByte(opc_lload_2);268if (maxLocals < 4) maxLocals = 4;269incStack();270incStack();271}272273public void opc_lload_3() {274emitByte(opc_lload_3);275if (maxLocals < 5) maxLocals = 5;276incStack();277incStack();278}279280public void opc_fload_0() {281emitByte(opc_fload_0);282if (maxLocals < 1) maxLocals = 1;283incStack();284}285286public void opc_fload_1() {287emitByte(opc_fload_1);288if (maxLocals < 2) maxLocals = 2;289incStack();290}291292public void opc_fload_2() {293emitByte(opc_fload_2);294if (maxLocals < 3) maxLocals = 3;295incStack();296}297298public void opc_fload_3() {299emitByte(opc_fload_3);300if (maxLocals < 4) maxLocals = 4;301incStack();302}303304public void opc_dload_0() {305emitByte(opc_dload_0);306if (maxLocals < 2) maxLocals = 2;307incStack();308incStack();309}310311public void opc_dload_1() {312emitByte(opc_dload_1);313if (maxLocals < 3) maxLocals = 3;314incStack();315incStack();316}317318public void opc_dload_2() {319emitByte(opc_dload_2);320if (maxLocals < 4) maxLocals = 4;321incStack();322incStack();323}324325public void opc_dload_3() {326emitByte(opc_dload_3);327if (maxLocals < 5) maxLocals = 5;328incStack();329incStack();330}331332public void opc_aload_0() {333emitByte(opc_aload_0);334if (maxLocals < 1) maxLocals = 1;335incStack();336}337338public void opc_aload_1() {339emitByte(opc_aload_1);340if (maxLocals < 2) maxLocals = 2;341incStack();342}343344public void opc_aload_2() {345emitByte(opc_aload_2);346if (maxLocals < 3) maxLocals = 3;347incStack();348}349350public void opc_aload_3() {351emitByte(opc_aload_3);352if (maxLocals < 4) maxLocals = 4;353incStack();354}355356public void opc_aaload() {357emitByte(opc_aaload);358decStack();359}360361public void opc_astore_0() {362emitByte(opc_astore_0);363if (maxLocals < 1) maxLocals = 1;364decStack();365}366367public void opc_astore_1() {368emitByte(opc_astore_1);369if (maxLocals < 2) maxLocals = 2;370decStack();371}372373public void opc_astore_2() {374emitByte(opc_astore_2);375if (maxLocals < 3) maxLocals = 3;376decStack();377}378379public void opc_astore_3() {380emitByte(opc_astore_3);381if (maxLocals < 4) maxLocals = 4;382decStack();383}384385////////////////////////386// Stack manipulation //387////////////////////////388389public void opc_pop() {390emitByte(opc_pop);391decStack();392}393394public void opc_dup() {395emitByte(opc_dup);396incStack();397}398399public void opc_dup_x1() {400emitByte(opc_dup_x1);401incStack();402}403404public void opc_swap() {405emitByte(opc_swap);406}407408///////////////////////////////409// Widening conversions only //410///////////////////////////////411412public void opc_i2l() {413emitByte(opc_i2l);414}415416public void opc_i2f() {417emitByte(opc_i2f);418}419420public void opc_i2d() {421emitByte(opc_i2d);422}423424public void opc_l2f() {425emitByte(opc_l2f);426}427428public void opc_l2d() {429emitByte(opc_l2d);430}431432public void opc_f2d() {433emitByte(opc_f2d);434}435436//////////////////437// Control flow //438//////////////////439440public void opc_ifeq(short bciOffset) {441emitByte(opc_ifeq);442emitShort(bciOffset);443decStack();444}445446/** Control flow with forward-reference BCI. Stack assumes447straight-through control flow. */448public void opc_ifeq(Label l) {449short instrBCI = getLength();450emitByte(opc_ifeq);451l.add(this, instrBCI, getLength(), getStack() - 1);452emitShort((short) -1); // Must be patched later453}454455public void opc_if_icmpeq(short bciOffset) {456emitByte(opc_if_icmpeq);457emitShort(bciOffset);458setStack(getStack() - 2);459}460461/** Control flow with forward-reference BCI. Stack assumes straight462control flow. */463public void opc_if_icmpeq(Label l) {464short instrBCI = getLength();465emitByte(opc_if_icmpeq);466l.add(this, instrBCI, getLength(), getStack() - 2);467emitShort((short) -1); // Must be patched later468}469470public void opc_goto(short bciOffset) {471emitByte(opc_goto);472emitShort(bciOffset);473}474475/** Control flow with forward-reference BCI. Stack assumes straight476control flow. */477public void opc_goto(Label l) {478short instrBCI = getLength();479emitByte(opc_goto);480l.add(this, instrBCI, getLength(), getStack());481emitShort((short) -1); // Must be patched later482}483484public void opc_ifnull(short bciOffset) {485emitByte(opc_ifnull);486emitShort(bciOffset);487decStack();488}489490/** Control flow with forward-reference BCI. Stack assumes straight491control flow. */492public void opc_ifnull(Label l) {493short instrBCI = getLength();494emitByte(opc_ifnull);495l.add(this, instrBCI, getLength(), getStack() - 1);496emitShort((short) -1); // Must be patched later497decStack();498}499500public void opc_ifnonnull(short bciOffset) {501emitByte(opc_ifnonnull);502emitShort(bciOffset);503decStack();504}505506/** Control flow with forward-reference BCI. Stack assumes straight507control flow. */508public void opc_ifnonnull(Label l) {509short instrBCI = getLength();510emitByte(opc_ifnonnull);511l.add(this, instrBCI, getLength(), getStack() - 1);512emitShort((short) -1); // Must be patched later513decStack();514}515516/////////////////////////517// Return instructions //518/////////////////////////519520public void opc_ireturn() {521emitByte(opc_ireturn);522setStack(0);523}524525public void opc_lreturn() {526emitByte(opc_lreturn);527setStack(0);528}529530public void opc_freturn() {531emitByte(opc_freturn);532setStack(0);533}534535public void opc_dreturn() {536emitByte(opc_dreturn);537setStack(0);538}539540public void opc_areturn() {541emitByte(opc_areturn);542setStack(0);543}544545public void opc_return() {546emitByte(opc_return);547setStack(0);548}549550//////////////////////551// Field operations //552//////////////////////553554public void opc_getstatic(short fieldIndex, int fieldSizeInStackSlots) {555emitByte(opc_getstatic);556emitShort(fieldIndex);557setStack(getStack() + fieldSizeInStackSlots);558}559560public void opc_putstatic(short fieldIndex, int fieldSizeInStackSlots) {561emitByte(opc_putstatic);562emitShort(fieldIndex);563setStack(getStack() - fieldSizeInStackSlots);564}565566public void opc_getfield(short fieldIndex, int fieldSizeInStackSlots) {567emitByte(opc_getfield);568emitShort(fieldIndex);569setStack(getStack() + fieldSizeInStackSlots - 1);570}571572public void opc_putfield(short fieldIndex, int fieldSizeInStackSlots) {573emitByte(opc_putfield);574emitShort(fieldIndex);575setStack(getStack() - fieldSizeInStackSlots - 1);576}577578////////////////////////579// Method invocations //580////////////////////////581582/** Long and double arguments and return types count as 2 arguments;583other values count as 1. */584public void opc_invokevirtual(short methodIndex,585int numArgs,586int numReturnValues)587{588emitByte(opc_invokevirtual);589emitShort(methodIndex);590setStack(getStack() - numArgs - 1 + numReturnValues);591}592593/** Long and double arguments and return types count as 2 arguments;594other values count as 1. */595public void opc_invokespecial(short methodIndex,596int numArgs,597int numReturnValues)598{599emitByte(opc_invokespecial);600emitShort(methodIndex);601setStack(getStack() - numArgs - 1 + numReturnValues);602}603604/** Long and double arguments and return types count as 2 arguments;605other values count as 1. */606public void opc_invokestatic(short methodIndex,607int numArgs,608int numReturnValues)609{610emitByte(opc_invokestatic);611emitShort(methodIndex);612setStack(getStack() - numArgs + numReturnValues);613}614615/** Long and double arguments and return types count as 2 arguments;616other values count as 1. */617public void opc_invokeinterface(short methodIndex,618int numArgs,619byte count,620int numReturnValues)621{622emitByte(opc_invokeinterface);623emitShort(methodIndex);624emitByte(count);625emitByte((byte) 0);626setStack(getStack() - numArgs - 1 + numReturnValues);627}628629//////////////////630// Array length //631//////////////////632633public void opc_arraylength() {634emitByte(opc_arraylength);635}636637/////////638// New //639/////////640641public void opc_new(short classIndex) {642emitByte(opc_new);643emitShort(classIndex);644incStack();645}646647////////////648// Athrow //649////////////650651public void opc_athrow() {652emitByte(opc_athrow);653setStack(1);654}655656//////////////////////////////657// Checkcast and instanceof //658//////////////////////////////659660/** Assumes the checkcast succeeds */661public void opc_checkcast(short classIndex) {662emitByte(opc_checkcast);663emitShort(classIndex);664}665666public void opc_instanceof(short classIndex) {667emitByte(opc_instanceof);668emitShort(classIndex);669}670}671672673