com.claritysys.jvm.builder
Class CodeBuilder

java.lang.Object
  extended by com.claritysys.jvm.builder.CodeBuilder
All Implemented Interfaces:
Opcodes, JVM

public final class CodeBuilder
extends java.lang.Object
implements Opcodes

Factory for building AttrCode objects for CfMethods, eg for generating bytecode. This is where all the really fun stuff happens.

Create a new CodeBuilder and pass it the CfMethod that is being constructed. CodeBuilder can then be used to declare local variables, define if/else blocks, emit bytecode, etc.

When done generating code, call close() to flush the newly generated bytecode to a new AttrCode attribute of the CfMethod that the builder was given originally.


Field Summary
 
Fields inherited from interface com.claritysys.jvm.builder.Opcodes
VOP_START, xDCONST, xIPUSH, xLCONST, xLOAD, xRETURN, xSTORE
 
Fields inherited from interface com.claritysys.jvm.classfile.JVM
AALOAD, AASTORE, ACC_ABSTRACT, ACC_FINAL, ACC_INTERFACE, ACC_NATIVE, ACC_PRIVATE, ACC_PROTECTED, ACC_PUBLIC, ACC_STATIC, ACC_STRICT, ACC_SUPER, ACC_SYNCHRONIZED, ACC_TRANSIENT, ACC_VOLATILE, ACCESS_NAMES, ACONST_NULL, ALOAD, ALOAD_0, ALOAD_1, ALOAD_2, ALOAD_3, ANEWARRAY, ANEWARRAY_QUICK, ARETURN, ARRAYLENGTH, ASTORE, ASTORE_0, ASTORE_1, ASTORE_2, ASTORE_3, ATHROW, ATTR_CODE, ATTR_CONSTANT_VALUE, ATTR_DEPRECATED, ATTR_EXCEPTIONS, ATTR_LINE_NUMBER_TABLE, ATTR_LOCAL_VARIABLE_TABLE, ATTR_SOURCE_FILE, ATTR_SYNTHETIC, BALOAD, BASTORE, BIPUSH, BREAKPOINT, CALOAD, CASTORE, CHECKCAST, CHECKCAST_QUICK, CONSTANT_Class, CONSTANT_Double, CONSTANT_Fieldref, CONSTANT_Float, CONSTANT_Integer, CONSTANT_InterfaceMethodref, CONSTANT_Long, CONSTANT_Methodref, CONSTANT_NameAndType, CONSTANT_NAMES, CONSTANT_String, CONSTANT_Utf8, CONSTRUCTOR_NAME, CONSUME_STACK, D2F, D2I, D2L, DADD, DALOAD, DASTORE, DCMPG, DCMPL, DCONST_0, DCONST_1, DDIV, DLOAD, DLOAD_0, DLOAD_1, DLOAD_2, DLOAD_3, DMUL, DNEG, DREM, DRETURN, DSTORE, DSTORE_0, DSTORE_1, DSTORE_2, DSTORE_3, DSUB, DUP, DUP_X1, DUP_X2, DUP2, DUP2_X1, DUP2_X2, F2D, F2I, F2L, FADD, FALOAD, FASTORE, FCMPG, FCMPL, FCONST_0, FCONST_1, FCONST_2, FDIV, FLOAD, FLOAD_0, FLOAD_1, FLOAD_2, FLOAD_3, FMUL, FNEG, FREM, FRETURN, FSTORE, FSTORE_0, FSTORE_1, FSTORE_2, FSTORE_3, FSUB, GETFIELD, GETFIELD_QUICK, GETFIELD_QUICK_W, GETFIELD2_QUICK, GETSTATIC, GETSTATIC_QUICK, GETSTATIC2_QUICK, GOTO, GOTO_W, I2B, I2C, I2D, I2F, I2L, I2S, IADD, IALOAD, IAND, IASTORE, ICONST_0, ICONST_1, ICONST_2, ICONST_3, ICONST_4, ICONST_5, ICONST_M1, IDIV, IF_ACMPEQ, IF_ACMPNE, IF_ICMPEQ, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ICMPLT, IF_ICMPNE, IFEQ, IFGE, IFGT, IFLE, IFLT, IFNE, IFNONNULL, IFNULL, IINC, ILLEGAL_OPCODE, ILLEGAL_TYPE, ILOAD, ILOAD_0, ILOAD_1, ILOAD_2, ILOAD_3, IMPDEP1, IMPDEP2, IMUL, INEG, INSTANCEOF, INSTANCEOF_QUICK, INT2BYTE, INT2CHAR, INT2SHORT, INTERFACES_IMPLEMENTED_BY_ARRAYS, INVOKEINTERFACE, INVOKEINTERFACE_QUICK, INVOKENONVIRTUAL, INVOKENONVIRTUAL_QUICK, INVOKESPECIAL, INVOKESTATIC, INVOKESTATIC_QUICK, INVOKESUPER_QUICK, INVOKEVIRTUAL, INVOKEVIRTUAL_QUICK, INVOKEVIRTUAL_QUICK_W, INVOKEVIRTUALOBJECT_QUICK, IOR, IREM, IRETURN, ISHL, ISHR, ISTORE, ISTORE_0, ISTORE_1, ISTORE_2, ISTORE_3, ISUB, IUSHR, IXOR, JSR, JSR_W, L2D, L2F, L2I, LADD, LALOAD, LAND, LASTORE, LCMP, LCONST_0, LCONST_1, LDC, LDC_QUICK, LDC_W, LDC_W_QUICK, LDC2_W, LDC2_W_QUICK, LDIV, LLOAD, LLOAD_0, LLOAD_1, LLOAD_2, LLOAD_3, LMUL, LNEG, LOOKUPSWITCH, LOR, LREM, LRETURN, LSHL, LSHR, LSTORE, LSTORE_0, LSTORE_1, LSTORE_2, LSTORE_3, LSUB, LUSHR, LXOR, MAJOR, MAJOR_1_1, MAJOR_1_2, MAJOR_1_3, MAX_ACC_FLAG, MAX_BYTE, MAX_CODE_SIZE, MAX_CP_ENTRIES, MAX_SHORT, MINOR, MINOR_1_1, MINOR_1_2, MINOR_1_3, MONITORENTER, MONITOREXIT, MULTIANEWARRAY, MULTIANEWARRAY_QUICK, NEW, NEW_QUICK, NEWARRAY, NO_OF_OPERANDS, NOP, OPCODE_NAMES, POP, POP2, PRODUCE_STACK, PUSH, PUTFIELD, PUTFIELD_QUICK, PUTFIELD_QUICK_W, PUTFIELD2_QUICK, PUTSTATIC, PUTSTATIC_QUICK, PUTSTATIC2_QUICK, RESERVED, RET, RETURN, SALOAD, SASTORE, SHORT_TYPE_NAMES, SIPUSH, STATIC_INITIALIZER_NAME, SWAP, SWITCH, T_ADDRESS, T_ARRAY, T_BOOLEAN, T_BYTE, T_CHAR, T_DOUBLE, T_FLOAT, T_INT, T_LONG, T_OBJECT, T_REFERENCE, T_SHORT, T_UNKNOWN, T_VOID, TABLESWITCH, TYPE_NAMES, TYPE_OF_OPERANDS, UNDEFINED, UNPREDICTABLE, WIDE
 
Constructor Summary
CodeBuilder(CfMethod cfMethod)
          Create a new builder attached to the given method.
 
Method Summary
 void add(short opcode)
          Append an opcode that takes no arguments.
 void add(short opcode, CfField field)
          Add a field opcode, such as PUTFIELD, GETFIELD, PUTSTATIC, GETSTATIC.
 void add(short opcode, CfMethod method)
          Add a method opcode such as INVOKEVIRTUAL.
 void add(short opcode, java.lang.Class clas)
          Add an opcode that takes a CONSTANT_Class_info index.
 void add(short opcode, CpClass clas)
          Add an opcode that takes a CONSTANT_Class_info index.
 void add(short opcode, CpRef ref)
          Add a field or method opcode.
 void add(short opcode, double d)
           
 void add(short opcode, int i)
          Add an instruction that takes a single byte, short, or int parameter.
 void add(short opcode, Label f)
          Add a branch instruction, to branch to the given Label.
 void add(short opcode, LocalVariable var)
          Add a LOAD/STORE instruction referencing the given local variable.
 void add(short opcode, LocalVariable var, int n)
          Generate an IINC, which takes both a local and an amount.
 void add(short opcode, long l)
          Add an xLCONST instruction, with a long parameter.
 void add(short opcode, java.lang.String s1)
          Process an opcode with a single String argument -- obviously no opcodes actually take a String as an argument, so the argument must first be converted into a constant String index, a constant methodref index, or a constant class index.
 void add(short opcode, java.lang.String type, int count)
          Add a MULTIANEWARRAY instruction, the only instruction with this particular format.
 void add(short opcode, java.lang.String s1, java.lang.String s2)
          Process an opcode that can concievably take two String arguments ...
 void add(short opcode, java.lang.String className, java.lang.String methodName, java.lang.Class returnType, java.lang.Class[] paramTypes)
          A convenient form for a methodref based opcode, especially when dealing with Java Method reflection.
 void add(short opcode, java.lang.String className, java.lang.String methodName, java.lang.String sig)
          Add an opcode that takes a CpRef (MethodRef) as an argument.
 java.lang.String addImport(java.lang.String fqClassName)
          Convenience method to add import to ConstantPool SigConverter.
 LocalVariable addLocal(CpClass type)
           
 LocalVariable addLocal(CpClass type, java.lang.String name)
           
 LocalVariable addLocal(java.lang.String sig)
           
 LocalVariable addLocal(java.lang.String sig, java.lang.String name)
          Declare a local variable within the current code block (within the method if there is no active code block).
 void blockCatch(LocalVariable catchAndStore)
          Start a catch block, for catching the exception with the same type as the given local variable and storing it automatically in that variable (adds an ASTORE automatically).
 void blockCatch(java.lang.String exceptionType)
          Start a catch block to catch the given type.
 void blockElse()
          Start an else block.
 void blockEnd()
          End the current block, be it a generic block, and if/else block, or a try/catch/finally block.
 void blockFinally()
          Start the finally clause.
 void blockIf(short opcode)
          Start an If block, executing the THEN block if the given opcode fails to branch.
 void blockIfEQ()
          Start an If block, executing the THEN block if the stack operand is equal to zero.
 void blockIfEQ(int type)
          Start an If block, executing the THEN block if the top two primitive operands are equal in value (of the given type).
 void blockIfFalse()
          Start an If block, executing the THEN block if the stack operand is equal to zero (aka "false").
 void blockIfNE()
          Start an If block, executing the THEN block if the stack operand is not equal to zero.
 void blockIfNotNull()
          Start an If block, executing the THEN block if the stack operand is not null.
 void blockIfNull()
          Start an If block, executing the THEN block if the stack operand is null.
 void blockIfObjectsEQ()
          Start an If block, executing the THEN block block if the two top stack operands are equivalent object references (IF_ACMPEQ).
 void blockIfObjectsNE()
          Start an If block, executing the THEN block block if the two top stack operands are different object references (IF_ACMPNE).
 void blockIfTrue()
          Start an If block, executing the THEN block if the stack operand is not equal to zero (aka "true").
 void blockStart()
          Start a generic (ie, "scope") block.
 void blockTry()
          Begin a try/catch/finally block.
 Label createLabel()
          Create a new Label to be used in branch/goto instructions.
 Label defineLabel()
          Create and define a new Label to be used in branch/goto instructions.
 void defineLocals(LocalVariable undeclaredLocals, int endPc)
          Define the given linked-list of local variables as ending on the given PC.
 void flush()
          Update the attached CfMethod's AttrCode based on the current contents of the bytecode, local variables, exceptions, etc.
 ByteArray getByteArray()
          Returns the ByteArray that bytecode is written to.
 LocalVariable getLocal(int slot)
          Return the LocalVariable currently occupying the requested local variable index.
 int getMaxLocals()
           
 int getMaxStack()
           
 CfMethod getMethod()
           
 void init(CfMethod cfMethod)
          Reinitialize this builder with the given method builder.
 void setLineNumber(int line)
          Attach the given line number to the current program counter offset.
 void setMethod(CfMethod method)
          Set the method to be built.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Constructor Detail

CodeBuilder

public CodeBuilder(CfMethod cfMethod)
Create a new builder attached to the given method.

Method Detail

setMethod

public void setMethod(CfMethod method)
Set the method to be built. Error if last method wasn't flushed.


init

public void init(CfMethod cfMethod)
Reinitialize this builder with the given method builder.


getByteArray

public ByteArray getByteArray()
Returns the ByteArray that bytecode is written to.


getLocal

public LocalVariable getLocal(int slot)
Return the LocalVariable currently occupying the requested local variable index.

Remember that doubles and longs occupy 2 consecutive indexes.

This can be used to access the method arguments as LocalVariables.

NOTE - at present the CodeBuilder does not re-use locals, so a declared local is scoped to the entire method code body.

Note that newly added LocalVariables are not added to the CfMethod until the CodeBuilder is closed. This method does, however, search both the method and any pending declarations, so it will return a newly declared local.

Parameters:
slot - The local slot number. For a static method the first arg is zero, for a non-static method the first is 1 (as zero is 'this').
Returns:
A LocalVariable representing the slot/type of the requested local number.
Throws:
java.util.NoSuchElementException - If no local can be found with the requested index.

addLocal

public LocalVariable addLocal(java.lang.String sig,
                              java.lang.String name)
Declare a local variable within the current code block (within the method if there is no active code block).

The local will not appear in the method's list of locals until the code block is ended. However, it can be found by calling getLocal(int), which searches pending declarations as well as the method's existing local variable table.

Parameters:
sig - A type signature, in VM format.
name - An optional name for the local. If no name is given it will assign it the name "local_X", where X is the slot number assigned.
Returns:
The newly defined LocalVariable.

addLocal

public LocalVariable addLocal(java.lang.String sig)

addLocal

public LocalVariable addLocal(CpClass type)

addLocal

public LocalVariable addLocal(CpClass type,
                              java.lang.String name)

setLineNumber

public void setLineNumber(int line)
Attach the given line number to the current program counter offset.

This will generate a LineNumber in the line number table of the attached CfMethod. It does not check for duplicates.


getMethod

public CfMethod getMethod()

getMaxLocals

public int getMaxLocals()

getMaxStack

public int getMaxStack()

createLabel

public Label createLabel()
Create a new Label to be used in branch/goto instructions. The caller must invoke Label.define() at the appropriate time during bytecode generation, to define the label at the proper target point.

Returns:
A newly created (but undefined) label.

defineLabel

public Label defineLabel()
Create and define a new Label to be used in branch/goto instructions. The Label will be defined to have the current PC.

Returns:
A newly created and defined label.

flush

public void flush()
Update the attached CfMethod's AttrCode based on the current contents of the bytecode, local variables, exceptions, etc. The builder should not be used after this point.


defineLocals

public void defineLocals(LocalVariable undeclaredLocals,
                         int endPc)
Define the given linked-list of local variables as ending on the given PC.

Parameters:
undeclaredLocals - Linked list of LocalVariable
endPc - The ending program counter, generally the current PC.

addImport

public java.lang.String addImport(java.lang.String fqClassName)
Convenience method to add import to ConstantPool SigConverter.

See Also:
ConstantPool#addImport}

add

public void add(short opcode)
Append an opcode that takes no arguments.

The opcode is tested to ensure it really takes no arguments.


add

public void add(short opcode,
                long l)
Add an xLCONST instruction, with a long parameter.

To push a long zero or one on the stack just use:

    code.add (LCONST_0);
 or
    code.add (LCONST_1);
 

 

This method provides support for:

   code.add (xLCONST, (long) someValue);
 

 

It automatically generates LCONST_0 or LCONST_1 if the argument is a zero or one.

Parameters:
opcode -
l -

add

public void add(short opcode,
                double d)

add

public void add(short opcode,
                int i)
Add an instruction that takes a single byte, short, or int parameter.

Supports Virtual Opcode "xPUSH " instruction, to push an int of any size (whether ICONST_X, BIPUSH, SIPUSH, or LDC or LDC_W). Use this rather than LDC.


add

public void add(short opcode,
                java.lang.Class clas)
Add an opcode that takes a CONSTANT_Class_info index.


add

public void add(short opcode,
                CpClass clas)
Add an opcode that takes a CONSTANT_Class_info index.

These would be instructions like CHECKCAST, NEW, INSTANCEOF, etc.


add

public void add(short opcode,
                java.lang.String s1)
Process an opcode with a single String argument -- obviously no opcodes actually take a String as an argument, so the argument must first be converted into a constant String index, a constant methodref index, or a constant class index.

Allowed opcodes: ANEWARRAY, CHECKCAST, INSTANCEOF, INVOKEINTERFACE, INVOKESPECIAL, INVOKESTATIC, INVOKEVIRTUAL, LDC, LDC2_W, LDC_W, NEW.

Parameters:
opcode - ANEWARRAY, CHECKCAST, INSTANCEOF, INVOKEINTERFACE, INVOKESPECIAL, INVOKESTATIC, INVOKEVIRTUAL, LDC, LDC2_W, LDC_W, NEW.
s1 - will be converted into a CpClass, a CpRef, or a CpString based on the given opcode and what it requires.

add

public void add(short opcode,
                java.lang.String type,
                int count)
Add a MULTIANEWARRAY instruction, the only instruction with this particular format.


add

public void add(short opcode,
                java.lang.String s1,
                java.lang.String s2)
Process an opcode that can concievably take two String arguments ... actually, only Field-based opcodes are allowed here.

Parameters:
opcode - The opcode for GETFIELD, PUTFIELD, GETSTATIC, or PUTSTATIC.
s1 - The Java Language signature for the field, such as "int[][]".
s2 - The name of the class, followed by the name of the field.

add

public void add(short opcode,
                Label f)
Add a branch instruction, to branch to the given Label.

This Label may not have been resolved yet, that's okay, the code will be backpatched automatically when needed.


add

public void add(short opcode,
                java.lang.String className,
                java.lang.String methodName,
                java.lang.Class returnType,
                java.lang.Class[] paramTypes)
A convenient form for a methodref based opcode, especially when dealing with Java Method reflection.

Parameters:
opcode -
className - Either VM or short format class name.
methodName -
returnType -
paramTypes -

add

public void add(short opcode,
                java.lang.String className,
                java.lang.String methodName,
                java.lang.String sig)
Add an opcode that takes a CpRef (MethodRef) as an argument.

Parameters:
opcode -
className -
methodName -
sig -

add

public void add(short opcode,
                CfField field)
Add a field opcode, such as PUTFIELD, GETFIELD, PUTSTATIC, GETSTATIC.

The argument is a CfField.


add

public void add(short opcode,
                CfMethod method)
Add a method opcode such as INVOKEVIRTUAL.

The argument is a CfMethod.


add

public void add(short opcode,
                CpRef ref)
Add a field or method opcode.


add

public void add(short opcode,
                LocalVariable var)
Add a LOAD/STORE instruction referencing the given local variable.

This also supports the virtual xLOAD and xSTORE opcodes, which automatically determine which opcode to use based on the type of the local.

For example, an 'int' local will generate an ILOAD instruction.

This method will also select the best form of the instruction, shortening ILOAD, 2 to ILOAD_2.


add

public void add(short opcode,
                LocalVariable var,
                int n)
Generate an IINC, which takes both a local and an amount.

Parameters:
opcode - must be IINC.
var - variable to increment.
n - amount to increment local var.

blockEnd

public void blockEnd()
End the current block, be it a generic block, and if/else block, or a try/catch/finally block.


blockStart

public void blockStart()
Start a generic (ie, "scope") block.


blockIf

public void blockIf(short opcode)
Start an If block, executing the THEN block if the given opcode fails to branch. This is used by the other blockIfXX methods, to generate their code.

If there is an ELSE block, the THEN block will end with a GOTO to jump around it (automatically).


blockIfEQ

public void blockIfEQ()
Start an If block, executing the THEN block if the stack operand is equal to zero.

This generates the inverse instruction, which branches around the THEN block (ie, to the ELSE block if there is one, or to the end of the THEN block if not).

If there is an ELSE block, the THEN block will end with a GOTO to jump around it (automatically).


blockIfNE

public void blockIfNE()
Start an If block, executing the THEN block if the stack operand is not equal to zero.

This generates the inverse instruction, which branches around the THEN block (ie, to the ELSE block if there is one, or to the end of the THEN block if not).

If there is an ELSE block, the THEN block will end with a GOTO to jump around it (automatically).


blockIfEQ

public void blockIfEQ(int type)
Start an If block, executing the THEN block if the top two primitive operands are equal in value (of the given type).

This generates the inverse instruction, which branches around the THEN block (ie, to the ELSE block if there is one, or to the end of the THEN block if not).

If there is an ELSE block, the THEN block will end with a GOTO to jump around it (automatically).

Parameters:
type - On of the JVM.T_XXX constants, to generate the proper comparison bytecodes.

blockIfObjectsEQ

public void blockIfObjectsEQ()
Start an If block, executing the THEN block block if the two top stack operands are equivalent object references (IF_ACMPEQ).

This generates the inverse instruction, which branches around the THEN block (ie, to the ELSE block if there is one, or to the end of the THEN block if not).

If there is an ELSE block, the THEN block will end with a GOTO to jump around it (automatically).


blockIfObjectsNE

public void blockIfObjectsNE()
Start an If block, executing the THEN block block if the two top stack operands are different object references (IF_ACMPNE).

This generates the inverse instruction, which branches around the THEN block (ie, to the ELSE block if there is one, or to the end of the THEN block if not).

If there is an ELSE block, the THEN block will end with a GOTO to jump around it (automatically).


blockIfNull

public void blockIfNull()
Start an If block, executing the THEN block if the stack operand is null.

This generates the inverse instruction, which branches around the THEN block (ie, to the ELSE block if there is one, or to the end of the THEN block if not).

If there is an ELSE block, the THEN block will end with a GOTO to jump around it (automatically).


blockIfNotNull

public void blockIfNotNull()
Start an If block, executing the THEN block if the stack operand is not null.

This generates the inverse instruction, which branches around the THEN block (ie, to the ELSE block if there is one, or to the end of the THEN block if not).

If there is an ELSE block, the THEN block will end with a GOTO to jump around it (automatically).


blockIfFalse

public void blockIfFalse()
Start an If block, executing the THEN block if the stack operand is equal to zero (aka "false").

Synonymous with blockIfEQ().


blockIfTrue

public void blockIfTrue()
Start an If block, executing the THEN block if the stack operand is not equal to zero (aka "true").

Synonymous with blockIfNE().


blockElse

public void blockElse()
Start an else block. There must be a current If block in scope.


blockTry

public void blockTry()
Begin a try/catch/finally block.


blockCatch

public void blockCatch(LocalVariable catchAndStore)
Start a catch block, for catching the exception with the same type as the given local variable and storing it automatically in that variable (adds an ASTORE automatically).

The caught exception will be stored in the given local.


blockCatch

public void blockCatch(java.lang.String exceptionType)
Start a catch block to catch the given type.

The caught exception will be on the stack.

Parameters:
exceptionType - An exception type in JVM format, such as "java/lang/IllegalArgumentException".

blockFinally

public void blockFinally()
Start the finally clause.



Copyright ? 2000-2003 Clarity Systems Group, LLC. All Rights Reserved.