📄 codewriter.java
字号:
/***
* ASM: a very small and fast Java bytecode manipulation framework
* Copyright (c) 2000,2002,2003 INRIA, France Telecom
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.objectweb.asm153;
/**
* A {@link CodeVisitor CodeVisitor} that generates Java bytecode instructions.
* Each visit method of this class appends the bytecode corresponding to the
* visited instruction to a byte vector, in the order these methods are called.
*
* @author Eric Bruneton
*/
public class CodeWriter implements CodeVisitor {
/**
* <tt>true</tt> if preconditions must be checked at runtime or not.
*/
final static boolean CHECK = false;
/**
* Next code writer (see {@link ClassWriter#firstMethod firstMethod}).
*/
CodeWriter next;
/**
* The class writer to which this method must be added.
*/
private ClassWriter cw;
/**
* The index of the constant pool item that contains the name of this method.
*/
private int name;
/**
* The index of the constant pool item that contains the descriptor of this
* method.
*/
private int desc;
/**
* Access flags of this method.
*/
private int access;
/**
* Maximum stack size of this method.
*/
private int maxStack;
/**
* Maximum number of local variables for this method.
*/
private int maxLocals;
/**
* The bytecode of this method.
*/
private ByteVector code = new ByteVector();
/**
* Number of entries in the catch table of this method.
*/
private int catchCount;
/**
* The catch table of this method.
*/
private ByteVector catchTable;
/**
* Number of exceptions that can be thrown by this method.
*/
private int exceptionCount;
/**
* The exceptions that can be thrown by this method. More
* precisely, this array contains the indexes of the constant pool items
* that contain the internal names of these exception classes.
*/
private int[] exceptions;
/**
* The non standard attributes of the method.
*/
private Attribute attrs;
/**
* Number of entries in the LocalVariableTable attribute.
*/
private int localVarCount;
/**
* The LocalVariableTable attribute.
*/
private ByteVector localVar;
/**
* Number of entries in the LineNumberTable attribute.
*/
private int lineNumberCount;
/**
* The LineNumberTable attribute.
*/
private ByteVector lineNumber;
/**
* The non standard attributes of the method's code.
*/
private Attribute cattrs;
/**
* Indicates if some jump instructions are too small and need to be resized.
*/
private boolean resize;
// --------------------------------------------------------------------------
// Fields for the control flow graph analysis algorithm (used to compute the
// maximum stack size). A control flow graph contains one node per "basic
// block", and one edge per "jump" from one basic block to another. Each node
// (i.e., each basic block) is represented by the Label object that
// corresponds to the first instruction of this basic block. Each node also
// stores the list of its successors in the graph, as a linked list of Edge
// objects.
// --------------------------------------------------------------------------
/**
* <tt>true</tt> if the maximum stack size and number of local variables must
* be automatically computed.
*/
private final boolean computeMaxs;
/**
* The (relative) stack size after the last visited instruction. This size is
* relative to the beginning of the current basic block, i.e., the true stack
* size after the last visited instruction is equal to the {@link
* Label#beginStackSize beginStackSize} of the current basic block plus
* <tt>stackSize</tt>.
*/
private int stackSize;
/**
* The (relative) maximum stack size after the last visited instruction. This
* size is relative to the beginning of the current basic block, i.e., the
* true maximum stack size after the last visited instruction is equal to the
* {@link Label#beginStackSize beginStackSize} of the current basic block plus
* <tt>stackSize</tt>.
*/
private int maxStackSize;
/**
* The current basic block. This block is the basic block to which the next
* instruction to be visited must be added.
*/
private Label currentBlock;
/**
* The basic block stack used by the control flow analysis algorithm. This
* stack is represented by a linked list of {@link Label Label} objects,
* linked to each other by their {@link Label#next} field. This stack must
* not be confused with the JVM stack used to execute the JVM instructions!
*/
private Label blockStack;
/**
* The stack size variation corresponding to each JVM instruction. This stack
* variation is equal to the size of the values produced by an instruction,
* minus the size of the values consumed by this instruction.
*/
private final static int[] SIZE;
// --------------------------------------------------------------------------
// Fields to optimize the creation of {@link Edge Edge} objects by using a
// pool of reusable objects. The (shared) pool is a linked list of Edge
// objects, linked to each other by their {@link Edge#poolNext} field. Each
// time a CodeWriter needs to allocate an Edge, it removes the first Edge
// of the pool and adds it to a private list of Edge objects. After the end
// of the control flow analysis algorithm, the Edge objects in the private
// list of the CodeWriter are added back to the pool (by appending this
// private list to the pool list; in order to do this in constant time, both
// head and tail of the private list are stored in this CodeWriter).
// --------------------------------------------------------------------------
/**
* The head of the list of {@link Edge Edge} objects used by this {@link
* CodeWriter CodeWriter}. These objects, linked to each other by their
* {@link Edge#poolNext} field, are added back to the shared pool at the
* end of the control flow analysis algorithm.
*/
private Edge head;
/**
* The tail of the list of {@link Edge Edge} objects used by this {@link
* CodeWriter CodeWriter}. These objects, linked to each other by their
* {@link Edge#poolNext} field, are added back to the shared pool at the
* end of the control flow analysis algorithm.
*/
private Edge tail;
/**
* The shared pool of {@link Edge Edge} objects. This pool is a linked list
* of Edge objects, linked to each other by their {@link Edge#poolNext} field.
*/
private static Edge pool;
// --------------------------------------------------------------------------
// Static initializer
// --------------------------------------------------------------------------
/**
* Computes the stack size variation corresponding to each JVM instruction.
*/
static {
int i;
int[] b = new int[202];
String s =
"EFFFFFFFFGGFFFGGFFFEEFGFGFEEEEEEEEEEEEEEEEEEEEDEDEDDDDDCDCDEEEEEEEEE" +
"EEEEEEEEEEEBABABBBBDCFFFGGGEDCDCDCDCDCDCDCDCDCDCEEEEDDDDDDDCDCDCEFEF" +
"DDEEFFDEDEEEBDDBBDDDDDDCCCCCCCCEFEDDDCDCDEEEEEEEEEEFEEEEEEDDEEDDEE";
for (i = 0; i < b.length; ++i) {
b[i] = s.charAt(i) - 'E';
}
SIZE = b;
/* code to generate the above string
int NA = 0; // not applicable (unused opcode or variable size opcode)
b = new int[] {
0, //NOP, // visitInsn
1, //ACONST_NULL, // -
1, //ICONST_M1, // -
1, //ICONST_0, // -
1, //ICONST_1, // -
1, //ICONST_2, // -
1, //ICONST_3, // -
1, //ICONST_4, // -
1, //ICONST_5, // -
2, //LCONST_0, // -
2, //LCONST_1, // -
1, //FCONST_0, // -
1, //FCONST_1, // -
1, //FCONST_2, // -
2, //DCONST_0, // -
2, //DCONST_1, // -
1, //BIPUSH, // visitIntInsn
1, //SIPUSH, // -
1, //LDC, // visitLdcInsn
NA, //LDC_W, // -
NA, //LDC2_W, // -
1, //ILOAD, // visitVarInsn
2, //LLOAD, // -
1, //FLOAD, // -
2, //DLOAD, // -
1, //ALOAD, // -
NA, //ILOAD_0, // -
NA, //ILOAD_1, // -
NA, //ILOAD_2, // -
NA, //ILOAD_3, // -
NA, //LLOAD_0, // -
NA, //LLOAD_1, // -
NA, //LLOAD_2, // -
NA, //LLOAD_3, // -
NA, //FLOAD_0, // -
NA, //FLOAD_1, // -
NA, //FLOAD_2, // -
NA, //FLOAD_3, // -
NA, //DLOAD_0, // -
NA, //DLOAD_1, // -
NA, //DLOAD_2, // -
NA, //DLOAD_3, // -
NA, //ALOAD_0, // -
NA, //ALOAD_1, // -
NA, //ALOAD_2, // -
NA, //ALOAD_3, // -
-1, //IALOAD, // visitInsn
0, //LALOAD, // -
-1, //FALOAD, // -
0, //DALOAD, // -
-1, //AALOAD, // -
-1, //BALOAD, // -
-1, //CALOAD, // -
-1, //SALOAD, // -
-1, //ISTORE, // visitVarInsn
-2, //LSTORE, // -
-1, //FSTORE, // -
-2, //DSTORE, // -
-1, //ASTORE, // -
NA, //ISTORE_0, // -
NA, //ISTORE_1, // -
NA, //ISTORE_2, // -
NA, //ISTORE_3, // -
NA, //LSTORE_0, // -
NA, //LSTORE_1, // -
NA, //LSTORE_2, // -
NA, //LSTORE_3, // -
NA, //FSTORE_0, // -
NA, //FSTORE_1, // -
NA, //FSTORE_2, // -
NA, //FSTORE_3, // -
NA, //DSTORE_0, // -
NA, //DSTORE_1, // -
NA, //DSTORE_2, // -
NA, //DSTORE_3, // -
NA, //ASTORE_0, // -
NA, //ASTORE_1, // -
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -