123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497 |
- /*
- * Javassist, a Java-bytecode translator toolkit.
- * Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. Alternatively, the contents of this file may be used under
- * the terms of the GNU Lesser General Public License Version 2.1 or later,
- * or the Apache License Version 2.0.
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- */
-
- package javassist.bytecode;
-
- import javassist.CtClass;
- import javassist.CtPrimitiveType;
-
- class ByteVector implements Cloneable {
- private byte[] buffer;
- private int size;
-
- public ByteVector() {
- buffer = new byte[64];
- size = 0;
- }
-
- @Override
- public Object clone() throws CloneNotSupportedException {
- ByteVector bv = (ByteVector)super.clone();
- bv.buffer = (byte[])buffer.clone();
- return bv;
- }
-
- public final int getSize() { return size; }
-
- public final byte[] copy() {
- byte[] b = new byte[size];
- System.arraycopy(buffer, 0, b, 0, size);
- return b;
- }
-
- public int read(int offset) {
- if (offset < 0 || size <= offset)
- throw new ArrayIndexOutOfBoundsException(offset);
-
- return buffer[offset];
- }
-
- public void write(int offset, int value) {
- if (offset < 0 || size <= offset)
- throw new ArrayIndexOutOfBoundsException(offset);
-
- buffer[offset] = (byte)value;
- }
-
- public void add(int code) {
- addGap(1);
- buffer[size - 1] = (byte)code;
- }
-
- public void add(int b1, int b2) {
- addGap(2);
- buffer[size - 2] = (byte)b1;
- buffer[size - 1] = (byte)b2;
- }
-
- public void add(int b1, int b2, int b3, int b4) {
- addGap(4);
- buffer[size - 4] = (byte)b1;
- buffer[size - 3] = (byte)b2;
- buffer[size - 2] = (byte)b3;
- buffer[size - 1] = (byte)b4;
- }
-
- public void addGap(int length) {
- if (size + length > buffer.length) {
- int newSize = size << 1;
- if (newSize < size + length)
- newSize = size + length;
-
- byte[] newBuf = new byte[newSize];
- System.arraycopy(buffer, 0, newBuf, 0, size);
- buffer = newBuf;
- }
-
- size += length;
- }
- }
-
- /**
- * A utility class for producing a bytecode sequence.
- *
- * <p>A <code>Bytecode</code> object is an unbounded array
- * containing bytecode. For example,
- *
- * <pre>
- * ConstPool cp = ...; // constant pool table
- * Bytecode b = new Bytecode(cp, 1, 0);
- * b.addIconst(3);
- * b.addReturn(CtClass.intType);
- * CodeAttribute ca = b.toCodeAttribute();</pre>
- *
- * <p>This program produces a Code attribute including a bytecode
- * sequence:
- *
- * <pre>
- * iconst_3
- * ireturn</pre>
- *
- * @see ConstPool
- * @see CodeAttribute
- */
- public class Bytecode extends ByteVector implements Cloneable, Opcode {
- /**
- * Represents the <code>CtClass</code> file using the
- * constant pool table given to this <code>Bytecode</code> object.
- */
- public static final CtClass THIS = ConstPool.THIS;
-
- ConstPool constPool;
- int maxStack, maxLocals;
- ExceptionTable tryblocks;
- private int stackDepth;
-
- /**
- * Constructs a <code>Bytecode</code> object with an empty bytecode
- * sequence.
- *
- * <p>The parameters <code>stacksize</code> and <code>localvars</code>
- * specify initial values
- * of <code>max_stack</code> and <code>max_locals</code>.
- * They can be changed later.
- *
- * @param cp constant pool table.
- * @param stacksize <code>max_stack</code>.
- * @param localvars <code>max_locals</code>.
- */
- public Bytecode(ConstPool cp, int stacksize, int localvars) {
- constPool = cp;
- maxStack = stacksize;
- maxLocals = localvars;
- tryblocks = new ExceptionTable(cp);
- stackDepth = 0;
- }
-
- /**
- * Constructs a <code>Bytecode</code> object with an empty bytecode
- * sequence. The initial values of <code>max_stack</code> and
- * <code>max_locals</code> are zero.
- *
- * @param cp constant pool table.
- * @see Bytecode#setMaxStack(int)
- * @see Bytecode#setMaxLocals(int)
- */
- public Bytecode(ConstPool cp) {
- this(cp, 0, 0);
- }
-
- /**
- * Creates and returns a copy of this object.
- * The constant pool object is shared between this object
- * and the cloned object.
- */
- @Override
- public Object clone() {
- try {
- Bytecode bc = (Bytecode)super.clone();
- bc.tryblocks = (ExceptionTable)tryblocks.clone();
- return bc;
- }
- catch (CloneNotSupportedException cnse) {
- throw new RuntimeException(cnse);
- }
- }
-
- /**
- * Gets a constant pool table.
- */
- public ConstPool getConstPool() { return constPool; }
-
- /**
- * Returns <code>exception_table</code>.
- */
- public ExceptionTable getExceptionTable() { return tryblocks; }
-
- /**
- * Converts to a <code>CodeAttribute</code>.
- */
- public CodeAttribute toCodeAttribute() {
- return new CodeAttribute(constPool, maxStack, maxLocals,
- get(), tryblocks);
- }
-
- /**
- * Returns the length of the bytecode sequence.
- */
- public int length() {
- return getSize();
- }
-
- /**
- * Returns the produced bytecode sequence.
- */
- public byte[] get() {
- return copy();
- }
-
- /**
- * Gets <code>max_stack</code>.
- */
- public int getMaxStack() { return maxStack; }
-
- /**
- * Sets <code>max_stack</code>.
- *
- * <p>This value may be automatically updated when an instruction
- * is appended. A <code>Bytecode</code> object maintains the current
- * stack depth whenever an instruction is added
- * by <code>addOpcode()</code>. For example, if DUP is appended,
- * the current stack depth is increased by one. If the new stack
- * depth is more than <code>max_stack</code>, then it is assigned
- * to <code>max_stack</code>. However, if branch instructions are
- * appended, the current stack depth may not be correctly maintained.
- *
- * @see #addOpcode(int)
- */
- public void setMaxStack(int size) {
- maxStack = size;
- }
-
- /**
- * Gets <code>max_locals</code>.
- */
- public int getMaxLocals() { return maxLocals; }
-
- /**
- * Sets <code>max_locals</code>.
- */
- public void setMaxLocals(int size) {
- maxLocals = size;
- }
-
- /**
- * Sets <code>max_locals</code>.
- *
- * <p>This computes the number of local variables
- * used to pass method parameters and sets <code>max_locals</code>
- * to that number plus <code>locals</code>.
- *
- * @param isStatic true if <code>params</code> must be
- * interpreted as parameters to a static method.
- * @param params parameter types.
- * @param locals the number of local variables excluding
- * ones used to pass parameters.
- */
- public void setMaxLocals(boolean isStatic, CtClass[] params,
- int locals) {
- if (!isStatic)
- ++locals;
-
- if (params != null) {
- CtClass doubleType = CtClass.doubleType;
- CtClass longType = CtClass.longType;
- int n = params.length;
- for (int i = 0; i < n; ++i) {
- CtClass type = params[i];
- if (type == doubleType || type == longType)
- locals += 2;
- else
- ++locals;
- }
- }
-
- maxLocals = locals;
- }
-
- /**
- * Increments <code>max_locals</code>.
- */
- public void incMaxLocals(int diff) {
- maxLocals += diff;
- }
-
- /**
- * Adds a new entry of <code>exception_table</code>.
- */
- public void addExceptionHandler(int start, int end,
- int handler, CtClass type) {
- addExceptionHandler(start, end, handler,
- constPool.addClassInfo(type));
- }
-
- /**
- * Adds a new entry of <code>exception_table</code>.
- *
- * @param type the fully-qualified name of a throwable class.
- */
- public void addExceptionHandler(int start, int end,
- int handler, String type) {
- addExceptionHandler(start, end, handler,
- constPool.addClassInfo(type));
- }
-
- /**
- * Adds a new entry of <code>exception_table</code>.
- */
- public void addExceptionHandler(int start, int end,
- int handler, int type) {
- tryblocks.add(start, end, handler, type);
- }
-
- /**
- * Returns the length of bytecode sequence
- * that have been added so far.
- */
- public int currentPc() {
- return getSize();
- }
-
- /**
- * Reads a signed 8bit value at the offset from the beginning of the
- * bytecode sequence.
- *
- * @throws ArrayIndexOutOfBoundsException if offset is invalid.
- */
- @Override
- public int read(int offset) {
- return super.read(offset);
- }
-
- /**
- * Reads a signed 16bit value at the offset from the beginning of the
- * bytecode sequence.
- */
- public int read16bit(int offset) {
- int v1 = read(offset);
- int v2 = read(offset + 1);
- return (v1 << 8) + (v2 & 0xff);
- }
-
- /**
- * Reads a signed 32bit value at the offset from the beginning of the
- * bytecode sequence.
- */
- public int read32bit(int offset) {
- int v1 = read16bit(offset);
- int v2 = read16bit(offset + 2);
- return (v1 << 16) + (v2 & 0xffff);
- }
-
- /**
- * Writes an 8bit value at the offset from the beginning of the
- * bytecode sequence.
- *
- * @throws ArrayIndexOutOfBoundsException if offset is invalid.
- */
- @Override
- public void write(int offset, int value) {
- super.write(offset, value);
- }
-
- /**
- * Writes an 16bit value at the offset from the beginning of the
- * bytecode sequence.
- */
- public void write16bit(int offset, int value) {
- write(offset, value >> 8);
- write(offset + 1, value);
- }
-
- /**
- * Writes an 32bit value at the offset from the beginning of the
- * bytecode sequence.
- */
- public void write32bit(int offset, int value) {
- write16bit(offset, value >> 16);
- write16bit(offset + 2, value);
- }
-
- /**
- * Appends an 8bit value to the end of the bytecode sequence.
- */
- @Override
- public void add(int code) {
- super.add(code);
- }
-
- /**
- * Appends a 32bit value to the end of the bytecode sequence.
- */
- public void add32bit(int value) {
- add(value >> 24, value >> 16, value >> 8, value);
- }
-
- /**
- * Appends the length-byte gap to the end of the bytecode sequence.
- *
- * @param length the gap length in byte.
- */
- @Override
- public void addGap(int length) {
- super.addGap(length);
- }
-
- /**
- * Appends an 8bit opcode to the end of the bytecode sequence.
- * The current stack depth is updated.
- * <code>max_stack</code> is updated if the current stack depth
- * is the deepest so far.
- *
- * <p>Note: some instructions such as INVOKEVIRTUAL does not
- * update the current stack depth since the increment depends
- * on the method signature.
- * <code>growStack()</code> must be explicitly called.
- */
- public void addOpcode(int code) {
- add(code);
- growStack(STACK_GROW[code]);
- }
-
- /**
- * Increases the current stack depth.
- * It also updates <code>max_stack</code> if the current stack depth
- * is the deepest so far.
- *
- * @param diff the number added to the current stack depth.
- */
- public void growStack(int diff) {
- setStackDepth(stackDepth + diff);
- }
-
- /**
- * Returns the current stack depth.
- */
- public int getStackDepth() { return stackDepth; }
-
- /**
- * Sets the current stack depth.
- * It also updates <code>max_stack</code> if the current stack depth
- * is the deepest so far.
- *
- * @param depth new value.
- */
- public void setStackDepth(int depth) {
- stackDepth = depth;
- if (stackDepth > maxStack)
- maxStack = stackDepth;
- }
-
- /**
- * Appends a 16bit value to the end of the bytecode sequence.
- * It never changes the current stack depth.
- */
- public void addIndex(int index) {
- add(index >> 8, index);
- }
-
- /**
- * Appends ALOAD or (WIDE) ALOAD_<n>
- *
- * @param n an index into the local variable array.
- */
- public void addAload(int n) {
- if (n < 4)
- addOpcode(42 + n); // aload_<n>
- else if (n < 0x100) {
- addOpcode(ALOAD); // aload
- add(n);
- }
- else {
- addOpcode(WIDE);
- addOpcode(ALOAD);
- addIndex(n);
- }
- }
-
- /**
- * Appends ASTORE or (WIDE) ASTORE_<n>
- *
- * @param n an index into the local variable array.
- */
- public void addAstore(int n) {
- if (n < 4)
- addOpcode(75 + n); // astore_<n>
- else if (n < 0x100) {
- addOpcode(ASTORE); // astore
- add(n);
- }
- else {
- addOpcode(WIDE);
- addOpcode(ASTORE);
- addIndex(n);
- }
- }
-
- /**
- * Appends ICONST or ICONST_<n>
- *
- * @param n the pushed integer constant.
- */
- public void addIconst(int n) {
- if (n < 6 && -2 < n)
- addOpcode(3 + n); // iconst_<i> -1..5
- else if (n <= 127 && -128 <= n) {
- addOpcode(16); // bipush
- add(n);
- }
- else if (n <= 32767 && -32768 <= n) {
- addOpcode(17); // sipush
- add(n >> 8);
- add(n);
- }
- else
- addLdc(constPool.addIntegerInfo(n));
- }
-
- /**
- * Appends an instruction for pushing zero or null on the stack.
- * If the type is void, this method does not append any instruction.
- *
- * @param type the type of the zero value (or null).
- */
- public void addConstZero(CtClass type) {
- if (type.isPrimitive()) {
- if (type == CtClass.longType)
- addOpcode(LCONST_0);
- else if (type == CtClass.floatType)
- addOpcode(FCONST_0);
- else if (type == CtClass.doubleType)
- addOpcode(DCONST_0);
- else if (type == CtClass.voidType)
- throw new RuntimeException("void type?");
- else
- addOpcode(ICONST_0);
- }
- else
- addOpcode(ACONST_NULL);
- }
-
- /**
- * Appends ILOAD or (WIDE) ILOAD_<n>
- *
- * @param n an index into the local variable array.
- */
- public void addIload(int n) {
- if (n < 4)
- addOpcode(26 + n); // iload_<n>
- else if (n < 0x100) {
- addOpcode(ILOAD); // iload
- add(n);
- }
- else {
- addOpcode(WIDE);
- addOpcode(ILOAD);
- addIndex(n);
- }
- }
-
- /**
- * Appends ISTORE or (WIDE) ISTORE_<n>
- *
- * @param n an index into the local variable array.
- */
- public void addIstore(int n) {
- if (n < 4)
- addOpcode(59 + n); // istore_<n>
- else if (n < 0x100) {
- addOpcode(ISTORE); // istore
- add(n);
- }
- else {
- addOpcode(WIDE);
- addOpcode(ISTORE);
- addIndex(n);
- }
- }
-
- /**
- * Appends LCONST or LCONST_<n>
- *
- * @param n the pushed long integer constant.
- */
- public void addLconst(long n) {
- if (n == 0 || n == 1)
- addOpcode(9 + (int)n); // lconst_<n>
- else
- addLdc2w(n);
- }
-
- /**
- * Appends LLOAD or (WIDE) LLOAD_<n>
- *
- * @param n an index into the local variable array.
- */
- public void addLload(int n) {
- if (n < 4)
- addOpcode(30 + n); // lload_<n>
- else if (n < 0x100) {
- addOpcode(LLOAD); // lload
- add(n);
- }
- else {
- addOpcode(WIDE);
- addOpcode(LLOAD);
- addIndex(n);
- }
- }
-
- /**
- * Appends LSTORE or LSTORE_<n>
- *
- * @param n an index into the local variable array.
- */
- public void addLstore(int n) {
- if (n < 4)
- addOpcode(63 + n); // lstore_<n>
- else if (n < 0x100) {
- addOpcode(LSTORE); // lstore
- add(n);
- }
- else {
- addOpcode(WIDE);
- addOpcode(LSTORE);
- addIndex(n);
- }
- }
-
- /**
- * Appends DCONST or DCONST_<n>
- *
- * @param d the pushed double constant.
- */
- public void addDconst(double d) {
- if (d == 0.0 || d == 1.0)
- addOpcode(14 + (int)d); // dconst_<n>
- else
- addLdc2w(d);
- }
-
- /**
- * Appends DLOAD or (WIDE) DLOAD_<n>
- *
- * @param n an index into the local variable array.
- */
- public void addDload(int n) {
- if (n < 4)
- addOpcode(38 + n); // dload_<n>
- else if (n < 0x100) {
- addOpcode(DLOAD); // dload
- add(n);
- }
- else {
- addOpcode(WIDE);
- addOpcode(DLOAD);
- addIndex(n);
- }
- }
-
- /**
- * Appends DSTORE or (WIDE) DSTORE_<n>
- *
- * @param n an index into the local variable array.
- */
- public void addDstore(int n) {
- if (n < 4)
- addOpcode(71 + n); // dstore_<n>
- else if (n < 0x100) {
- addOpcode(DSTORE); // dstore
- add(n);
- }
- else {
- addOpcode(WIDE);
- addOpcode(DSTORE);
- addIndex(n);
- }
- }
-
- /**
- * Appends FCONST or FCONST_<n>
- *
- * @param f the pushed float constant.
- */
- public void addFconst(float f) {
- if (f == 0.0f || f == 1.0f || f == 2.0f)
- addOpcode(11 + (int)f); // fconst_<n>
- else
- addLdc(constPool.addFloatInfo(f));
- }
-
- /**
- * Appends FLOAD or (WIDE) FLOAD_<n>
- *
- * @param n an index into the local variable array.
- */
- public void addFload(int n) {
- if (n < 4)
- addOpcode(34 + n); // fload_<n>
- else if (n < 0x100) {
- addOpcode(FLOAD); // fload
- add(n);
- }
- else {
- addOpcode(WIDE);
- addOpcode(FLOAD);
- addIndex(n);
- }
- }
-
- /**
- * Appends FSTORE or FSTORE_<n>
- *
- * @param n an index into the local variable array.
- */
- public void addFstore(int n) {
- if (n < 4)
- addOpcode(67 + n); // fstore_<n>
- else if (n < 0x100) {
- addOpcode(FSTORE); // fstore
- add(n);
- }
- else {
- addOpcode(WIDE);
- addOpcode(FSTORE);
- addIndex(n);
- }
- }
-
- /**
- * Appends an instruction for loading a value from the
- * local variable at the index <code>n</code>.
- *
- * @param n the index.
- * @param type the type of the loaded value.
- * @return the size of the value (1 or 2 word).
- */
- public int addLoad(int n, CtClass type) {
- if (type.isPrimitive()) {
- if (type == CtClass.booleanType || type == CtClass.charType
- || type == CtClass.byteType || type == CtClass.shortType
- || type == CtClass.intType)
- addIload(n);
- else if (type == CtClass.longType) {
- addLload(n);
- return 2;
- }
- else if(type == CtClass.floatType)
- addFload(n);
- else if(type == CtClass.doubleType) {
- addDload(n);
- return 2;
- }
- else
- throw new RuntimeException("void type?");
- }
- else
- addAload(n);
-
- return 1;
- }
-
- /**
- * Appends an instruction for storing a value into the
- * local variable at the index <code>n</code>.
- *
- * @param n the index.
- * @param type the type of the stored value.
- * @return 2 if the type is long or double. Otherwise 1.
- */
- public int addStore(int n, CtClass type) {
- if (type.isPrimitive()) {
- if (type == CtClass.booleanType || type == CtClass.charType
- || type == CtClass.byteType || type == CtClass.shortType
- || type == CtClass.intType)
- addIstore(n);
- else if (type == CtClass.longType) {
- addLstore(n);
- return 2;
- }
- else if (type == CtClass.floatType)
- addFstore(n);
- else if (type == CtClass.doubleType) {
- addDstore(n);
- return 2;
- }
- else
- throw new RuntimeException("void type?");
- }
- else
- addAstore(n);
-
- return 1;
- }
-
- /**
- * Appends instructions for loading all the parameters onto the
- * operand stack.
- *
- * @param offset the index of the first parameter. It is 0
- * if the method is static. Otherwise, it is 1.
- */
- public int addLoadParameters(CtClass[] params, int offset) {
- int stacksize = 0;
- if (params != null) {
- int n = params.length;
- for (int i = 0; i < n; ++i)
- stacksize += addLoad(stacksize + offset, params[i]);
- }
-
- return stacksize;
- }
-
- /**
- * Appends CHECKCAST.
- *
- * @param c the type.
- */
- public void addCheckcast(CtClass c) {
- addOpcode(CHECKCAST);
- addIndex(constPool.addClassInfo(c));
- }
-
- /**
- * Appends CHECKCAST.
- *
- * @param classname a fully-qualified class name.
- */
- public void addCheckcast(String classname) {
- addOpcode(CHECKCAST);
- addIndex(constPool.addClassInfo(classname));
- }
-
- /**
- * Appends INSTANCEOF.
- *
- * @param classname the class name.
- */
- public void addInstanceof(String classname) {
- addOpcode(INSTANCEOF);
- addIndex(constPool.addClassInfo(classname));
- }
-
- /**
- * Appends GETFIELD.
- *
- * @param c the class.
- * @param name the field name.
- * @param type the descriptor of the field type.
- *
- * @see Descriptor#of(CtClass)
- */
- public void addGetfield(CtClass c, String name, String type) {
- add(GETFIELD);
- int ci = constPool.addClassInfo(c);
- addIndex(constPool.addFieldrefInfo(ci, name, type));
- growStack(Descriptor.dataSize(type) - 1);
- }
-
- /**
- * Appends GETFIELD.
- *
- * @param c the fully-qualified class name.
- * @param name the field name.
- * @param type the descriptor of the field type.
- *
- * @see Descriptor#of(CtClass)
- */
- public void addGetfield(String c, String name, String type) {
- add(GETFIELD);
- int ci = constPool.addClassInfo(c);
- addIndex(constPool.addFieldrefInfo(ci, name, type));
- growStack(Descriptor.dataSize(type) - 1);
- }
-
- /**
- * Appends GETSTATIC.
- *
- * @param c the class
- * @param name the field name
- * @param type the descriptor of the field type.
- *
- * @see Descriptor#of(CtClass)
- */
- public void addGetstatic(CtClass c, String name, String type) {
- add(GETSTATIC);
- int ci = constPool.addClassInfo(c);
- addIndex(constPool.addFieldrefInfo(ci, name, type));
- growStack(Descriptor.dataSize(type));
- }
-
- /**
- * Appends GETSTATIC.
- *
- * @param c the fully-qualified class name
- * @param name the field name
- * @param type the descriptor of the field type.
- *
- * @see Descriptor#of(CtClass)
- */
- public void addGetstatic(String c, String name, String type) {
- add(GETSTATIC);
- int ci = constPool.addClassInfo(c);
- addIndex(constPool.addFieldrefInfo(ci, name, type));
- growStack(Descriptor.dataSize(type));
- }
-
- /**
- * Appends INVOKESPECIAL.
- *
- * @param clazz the target class.
- * @param name the method name.
- * @param returnType the return type.
- * @param paramTypes the parameter types.
- */
- public void addInvokespecial(CtClass clazz, String name,
- CtClass returnType, CtClass[] paramTypes) {
- String desc = Descriptor.ofMethod(returnType, paramTypes);
- addInvokespecial(clazz, name, desc);
- }
-
- /**
- * Appends INVOKESPECIAL.
- *
- * @param clazz the target class.
- * @param name the method name
- * @param desc the descriptor of the method signature.
- *
- * @see Descriptor#ofMethod(CtClass,CtClass[])
- * @see Descriptor#ofConstructor(CtClass[])
- */
- public void addInvokespecial(CtClass clazz, String name, String desc) {
- boolean isInterface = clazz == null ? false : clazz.isInterface();
- addInvokespecial(isInterface,
- constPool.addClassInfo(clazz), name, desc);
- }
-
- /**
- * Appends INVOKESPECIAL. The invoked method must not be a default
- * method declared in an interface.
- *
- * @param clazz the fully-qualified class name.
- * @param name the method name
- * @param desc the descriptor of the method signature.
- *
- * @see Descriptor#ofMethod(CtClass,CtClass[])
- * @see Descriptor#ofConstructor(CtClass[])
- */
- public void addInvokespecial(String clazz, String name, String desc) {
- addInvokespecial(false, constPool.addClassInfo(clazz), name, desc);
- }
-
- /**
- * Appends INVOKESPECIAL. The invoked method must not be a default
- * method declared in an interface.
- *
- * @param clazz the index of <code>CONSTANT_Class_info</code>
- * structure.
- * @param name the method name
- * @param desc the descriptor of the method signature.
- *
- * @see Descriptor#ofMethod(CtClass,CtClass[])
- * @see Descriptor#ofConstructor(CtClass[])
- */
- public void addInvokespecial(int clazz, String name, String desc) {
- addInvokespecial(false, clazz, name, desc);
- }
-
- /**
- * Appends INVOKESPECIAL.
- *
- * @param isInterface true if the invoked method is a default method
- * declared in an interface.
- * @param clazz the index of <code>CONSTANT_Class_info</code>
- * structure.
- * @param name the method name
- * @param desc the descriptor of the method signature.
- *
- * @see Descriptor#ofMethod(CtClass,CtClass[])
- * @see Descriptor#ofConstructor(CtClass[])
- */
- public void addInvokespecial(boolean isInterface, int clazz, String name, String desc) {
- int index;
- if (isInterface)
- index = constPool.addInterfaceMethodrefInfo(clazz, name, desc);
- else
- index = constPool.addMethodrefInfo(clazz, name, desc);
-
- addInvokespecial(index, desc);
- }
-
- /**
- * Appends INVOKESPECIAL.
- *
- * @param index the index of <code>CONSTANT_Methodref_info</code>
- * or <code>CONSTANT_InterfaceMethodref_info</code>
- * @param desc the descriptor of the method signature.
- *
- * @see Descriptor#ofMethod(CtClass,CtClass[])
- * @see Descriptor#ofConstructor(CtClass[])
- */
- public void addInvokespecial(int index, String desc) {
- add(INVOKESPECIAL);
- addIndex(index);
- growStack(Descriptor.dataSize(desc) - 1);
- }
-
- /**
- * Appends INVOKESTATIC.
- *
- * @param clazz the target class.
- * @param name the method name
- * @param returnType the return type.
- * @param paramTypes the parameter types.
- */
- public void addInvokestatic(CtClass clazz, String name,
- CtClass returnType, CtClass[] paramTypes) {
- String desc = Descriptor.ofMethod(returnType, paramTypes);
- addInvokestatic(clazz, name, desc);
- }
-
- /**
- * Appends INVOKESTATIC.
- *
- * @param clazz the target class.
- * @param name the method name
- * @param desc the descriptor of the method signature.
- *
- * @see Descriptor#ofMethod(CtClass,CtClass[])
- */
- public void addInvokestatic(CtClass clazz, String name, String desc) {
- boolean isInterface;
- if (clazz == THIS)
- isInterface = false;
- else
- isInterface = clazz.isInterface();
-
- addInvokestatic(constPool.addClassInfo(clazz), name, desc, isInterface);
- }
-
- /**
- * Appends INVOKESTATIC.
- *
- * @param classname the fully-qualified class name.
- * It must not be an interface-type name.
- * @param name the method name
- * @param desc the descriptor of the method signature.
- *
- * @see Descriptor#ofMethod(CtClass,CtClass[])
- */
- public void addInvokestatic(String classname, String name, String desc) {
- addInvokestatic(constPool.addClassInfo(classname), name, desc);
- }
-
- /**
- * Appends INVOKESTATIC.
- *
- * @param clazz the index of <code>CONSTANT_Class_info</code>
- * structure. It must not be an interface type.
- * @param name the method name
- * @param desc the descriptor of the method signature.
- *
- * @see Descriptor#ofMethod(CtClass,CtClass[])
- */
- public void addInvokestatic(int clazz, String name, String desc) {
- addInvokestatic(clazz, name, desc, false);
- }
-
- private void addInvokestatic(int clazz, String name, String desc,
- boolean isInterface) {
- add(INVOKESTATIC);
- int index;
- if (isInterface)
- index = constPool.addInterfaceMethodrefInfo(clazz, name, desc);
- else
- index = constPool.addMethodrefInfo(clazz, name, desc);
-
- addIndex(index);
- growStack(Descriptor.dataSize(desc));
- }
-
- /**
- * Appends INVOKEVIRTUAL.
- *
- * <p>The specified method must not be an inherited method.
- * It must be directly declared in the class specified
- * in <code>clazz</code>.
- *
- * @param clazz the target class.
- * @param name the method name
- * @param returnType the return type.
- * @param paramTypes the parameter types.
- */
- public void addInvokevirtual(CtClass clazz, String name,
- CtClass returnType, CtClass[] paramTypes) {
- String desc = Descriptor.ofMethod(returnType, paramTypes);
- addInvokevirtual(clazz, name, desc);
- }
-
- /**
- * Appends INVOKEVIRTUAL.
- *
- * <p>The specified method must not be an inherited method.
- * It must be directly declared in the class specified
- * in <code>clazz</code>.
- *
- * @param clazz the target class.
- * @param name the method name
- * @param desc the descriptor of the method signature.
- *
- * @see Descriptor#ofMethod(CtClass,CtClass[])
- */
- public void addInvokevirtual(CtClass clazz, String name, String desc) {
- addInvokevirtual(constPool.addClassInfo(clazz), name, desc);
- }
-
- /**
- * Appends INVOKEVIRTUAL.
- *
- * <p>The specified method must not be an inherited method.
- * It must be directly declared in the class specified
- * in <code>classname</code>.
- *
- * @param classname the fully-qualified class name.
- * @param name the method name
- * @param desc the descriptor of the method signature.
- *
- * @see Descriptor#ofMethod(CtClass,CtClass[])
- */
- public void addInvokevirtual(String classname, String name, String desc) {
- addInvokevirtual(constPool.addClassInfo(classname), name, desc);
- }
-
- /**
- * Appends INVOKEVIRTUAL.
- *
- * <p>The specified method must not be an inherited method.
- * It must be directly declared in the class specified
- * by <code>clazz</code>.
- *
- * @param clazz the index of <code>CONSTANT_Class_info</code>
- * structure.
- * @param name the method name
- * @param desc the descriptor of the method signature.
- *
- * @see Descriptor#ofMethod(CtClass,CtClass[])
- */
- public void addInvokevirtual(int clazz, String name, String desc) {
- add(INVOKEVIRTUAL);
- addIndex(constPool.addMethodrefInfo(clazz, name, desc));
- growStack(Descriptor.dataSize(desc) - 1);
- }
-
- /**
- * Appends INVOKEINTERFACE.
- *
- * @param clazz the target class.
- * @param name the method name
- * @param returnType the return type.
- * @param paramTypes the parameter types.
- * @param count the count operand of the instruction.
- */
- public void addInvokeinterface(CtClass clazz, String name,
- CtClass returnType, CtClass[] paramTypes,
- int count) {
- String desc = Descriptor.ofMethod(returnType, paramTypes);
- addInvokeinterface(clazz, name, desc, count);
- }
-
- /**
- * Appends INVOKEINTERFACE.
- *
- * @param clazz the target class.
- * @param name the method name
- * @param desc the descriptor of the method signature.
- * @param count the count operand of the instruction.
- *
- * @see Descriptor#ofMethod(CtClass,CtClass[])
- */
- public void addInvokeinterface(CtClass clazz, String name,
- String desc, int count) {
- addInvokeinterface(constPool.addClassInfo(clazz), name, desc,
- count);
- }
-
- /**
- * Appends INVOKEINTERFACE.
- *
- * @param classname the fully-qualified class name.
- * @param name the method name
- * @param desc the descriptor of the method signature.
- * @param count the count operand of the instruction.
- *
- * @see Descriptor#ofMethod(CtClass,CtClass[])
- */
- public void addInvokeinterface(String classname, String name,
- String desc, int count) {
- addInvokeinterface(constPool.addClassInfo(classname), name, desc,
- count);
- }
-
- /**
- * Appends INVOKEINTERFACE.
- *
- * @param clazz the index of <code>CONSTANT_Class_info</code>
- * structure.
- * @param name the method name
- * @param desc the descriptor of the method signature.
- * @param count the count operand of the instruction.
- *
- * @see Descriptor#ofMethod(CtClass,CtClass[])
- */
- public void addInvokeinterface(int clazz, String name,
- String desc, int count) {
- add(INVOKEINTERFACE);
- addIndex(constPool.addInterfaceMethodrefInfo(clazz, name, desc));
- add(count);
- add(0);
- growStack(Descriptor.dataSize(desc) - 1);
- }
-
- /**
- * Appends INVOKEDYNAMIC.
- *
- * @param bootstrap an index into the <code>bootstrap_methods</code> array
- * of the bootstrap method table.
- * @param name the method name.
- * @param desc the method descriptor.
- * @see Descriptor#ofMethod(CtClass,CtClass[])
- * @since 3.17
- */
- public void addInvokedynamic(int bootstrap, String name, String desc) {
- int nt = constPool.addNameAndTypeInfo(name, desc);
- int dyn = constPool.addInvokeDynamicInfo(bootstrap, nt);
- add(INVOKEDYNAMIC);
- addIndex(dyn);
- add(0, 0);
- growStack(Descriptor.dataSize(desc)); // assume ConstPool#REF_invokeStatic
- }
-
- /**
- * Appends LDC or LDC_W. The pushed item is a <code>String</code>
- * object.
- *
- * @param s the character string pushed by LDC or LDC_W.
- */
- public void addLdc(String s) {
- addLdc(constPool.addStringInfo(s));
- }
-
- /**
- * Appends LDC or LDC_W.
- *
- * @param i index into the constant pool.
- */
- public void addLdc(int i) {
- if (i > 0xFF) {
- addOpcode(LDC_W);
- addIndex(i);
- }
- else {
- addOpcode(LDC);
- add(i);
- }
- }
-
- /**
- * Appends LDC2_W. The pushed item is a long value.
- */
- public void addLdc2w(long l) {
- addOpcode(LDC2_W);
- addIndex(constPool.addLongInfo(l));
- }
-
- /**
- * Appends LDC2_W. The pushed item is a double value.
- */
- public void addLdc2w(double d) {
- addOpcode(LDC2_W);
- addIndex(constPool.addDoubleInfo(d));
- }
-
- /**
- * Appends NEW.
- *
- * @param clazz the class of the created instance.
- */
- public void addNew(CtClass clazz) {
- addOpcode(NEW);
- addIndex(constPool.addClassInfo(clazz));
- }
-
- /**
- * Appends NEW.
- *
- * @param classname the fully-qualified class name.
- */
- public void addNew(String classname) {
- addOpcode(NEW);
- addIndex(constPool.addClassInfo(classname));
- }
-
- /**
- * Appends ANEWARRAY.
- *
- * @param classname the qualified class name of the element type.
- */
- public void addAnewarray(String classname) {
- addOpcode(ANEWARRAY);
- addIndex(constPool.addClassInfo(classname));
- }
-
- /**
- * Appends ICONST and ANEWARRAY.
- *
- * @param clazz the elememnt type.
- * @param length the array length.
- */
- public void addAnewarray(CtClass clazz, int length) {
- addIconst(length);
- addOpcode(ANEWARRAY);
- addIndex(constPool.addClassInfo(clazz));
- }
-
- /**
- * Appends NEWARRAY for primitive types.
- *
- * @param atype <code>T_BOOLEAN</code>, <code>T_CHAR</code>, ...
- * @see Opcode
- */
- public void addNewarray(int atype, int length) {
- addIconst(length);
- addOpcode(NEWARRAY);
- add(atype);
- }
-
- /**
- * Appends MULTINEWARRAY.
- *
- * @param clazz the array type.
- * @param dimensions the sizes of all dimensions.
- * @return the length of <code>dimensions</code>.
- */
- public int addMultiNewarray(CtClass clazz, int[] dimensions) {
- int len = dimensions.length;
- for (int i = 0; i < len; ++i)
- addIconst(dimensions[i]);
-
- growStack(len);
- return addMultiNewarray(clazz, len);
- }
-
- /**
- * Appends MULTINEWARRAY. The size of every dimension must have been
- * already pushed on the stack.
- *
- * @param clazz the array type.
- * @param dim the number of the dimensions.
- * @return the value of <code>dim</code>.
- */
- public int addMultiNewarray(CtClass clazz, int dim) {
- add(MULTIANEWARRAY);
- addIndex(constPool.addClassInfo(clazz));
- add(dim);
- growStack(1 - dim);
- return dim;
- }
-
- /**
- * Appends MULTINEWARRAY.
- *
- * @param desc the type descriptor of the created array.
- * @param dim dimensions.
- * @return the value of <code>dim</code>.
- */
- public int addMultiNewarray(String desc, int dim) {
- add(MULTIANEWARRAY);
- addIndex(constPool.addClassInfo(desc));
- add(dim);
- growStack(1 - dim);
- return dim;
- }
-
- /**
- * Appends PUTFIELD.
- *
- * @param c the target class.
- * @param name the field name.
- * @param desc the descriptor of the field type.
- */
- public void addPutfield(CtClass c, String name, String desc) {
- addPutfield0(c, null, name, desc);
- }
-
- /**
- * Appends PUTFIELD.
- *
- * @param classname the fully-qualified name of the target class.
- * @param name the field name.
- * @param desc the descriptor of the field type.
- */
- public void addPutfield(String classname, String name, String desc) {
- // if classnaem is null, the target class is THIS.
- addPutfield0(null, classname, name, desc);
- }
-
- private void addPutfield0(CtClass target, String classname,
- String name, String desc) {
- add(PUTFIELD);
- // target is null if it represents THIS.
- int ci = classname == null ? constPool.addClassInfo(target)
- : constPool.addClassInfo(classname);
- addIndex(constPool.addFieldrefInfo(ci, name, desc));
- growStack(-1 - Descriptor.dataSize(desc));
- }
-
- /**
- * Appends PUTSTATIC.
- *
- * @param c the target class.
- * @param name the field name.
- * @param desc the descriptor of the field type.
- */
- public void addPutstatic(CtClass c, String name, String desc) {
- addPutstatic0(c, null, name, desc);
- }
-
- /**
- * Appends PUTSTATIC.
- *
- * @param classname the fully-qualified name of the target class.
- * @param fieldName the field name.
- * @param desc the descriptor of the field type.
- */
- public void addPutstatic(String classname, String fieldName, String desc) {
- // if classname is null, the target class is THIS.
- addPutstatic0(null, classname, fieldName, desc);
- }
-
- private void addPutstatic0(CtClass target, String classname,
- String fieldName, String desc) {
- add(PUTSTATIC);
- // target is null if it represents THIS.
- int ci = classname == null ? constPool.addClassInfo(target)
- : constPool.addClassInfo(classname);
- addIndex(constPool.addFieldrefInfo(ci, fieldName, desc));
- growStack(-Descriptor.dataSize(desc));
- }
-
- /**
- * Appends ARETURN, IRETURN, .., or RETURN.
- *
- * @param type the return type.
- */
- public void addReturn(CtClass type) {
- if (type == null)
- addOpcode(RETURN);
- else if (type.isPrimitive()) {
- CtPrimitiveType ptype = (CtPrimitiveType)type;
- addOpcode(ptype.getReturnOp());
- }
- else
- addOpcode(ARETURN);
- }
-
- /**
- * Appends RET.
- *
- * @param var local variable
- */
- public void addRet(int var) {
- if (var < 0x100) {
- addOpcode(RET);
- add(var);
- }
- else {
- addOpcode(WIDE);
- addOpcode(RET);
- addIndex(var);
- }
- }
-
- /**
- * Appends instructions for executing
- * <code>java.lang.System.println(<i>message</i>)</code>.
- *
- * @param message printed message.
- */
- public void addPrintln(String message) {
- addGetstatic("java.lang.System", "err", "Ljava/io/PrintStream;");
- addLdc(message);
- addInvokevirtual("java.io.PrintStream",
- "println", "(Ljava/lang/String;)V");
- }
- }
|