MethodBuilderclass BCMethod extends java.lang.Object implements MethodBuilder
When a method is first created, it has:
MethodBuilder implementations are required to supply a way for Statements and Expressions to give them code. Most typically, they may have a stream to which their contents writes the code that is of the type to satisfy what the contents represent. MethodBuilder implementations also have to have a way to supply ClassBuilders with their code, that satisfies the type of class builder they are implemented with. This is implementation-dependent, so ClassBuilders, MethodBuilders, Statements, and Expressions all have to be of the same implementation in order to interact to generate a class.
Method Builder implementation for generating bytecode.
| Modifier and Type | Field | Description |
|---|---|---|
(package private) BCClass |
cb |
|
(package private) static int |
CODE_SPLIT_LENGTH |
Code length at which to split into sub-methods.
|
private Conditional |
condition |
|
private int |
currentVarNum |
|
private boolean |
handlingOverflow |
True if we are currently switching control
over to a sub method to avoid hitting the code generation
limit of 65535 bytes per method.
|
(package private) int |
maxStack |
Maximum stack depth seen in this method, measured in words.
|
protected ClassHolder |
modClass |
|
(package private) CodeChunk |
myCode |
|
protected ClassMember |
myEntry |
|
private java.lang.String |
myName |
The original name of the method, this
represents how any user would call this method.
|
(package private) java.lang.String |
myReturnType |
|
private static byte[] |
newArrayElementTypeMap |
this array maps the BCExpr vm_* constants 0..6 to
the expected VM type constants for the newarray instruction.
|
(package private) BCLocalField[] |
parameters |
Fast access for the parametes, will be null
if the method has no parameters.
|
private java.lang.String[] |
parameterTypes |
List of parameter types with java language class names.
|
private int |
stackDepth |
Current stack depth in this method, measured in words.
|
private int |
stackTypeOffset |
Points to the next array offset in stackTypes
to be used.
|
private Type[] |
stackTypes |
Array of the current types of the values on the stack.
|
private int |
statementNum |
|
private int |
subMethodCount |
How many sub-methods we have overflowed to.
|
(package private) static byte |
T_BOOLEAN |
|
(package private) java.util.Vector<java.lang.String> |
thrownExceptions |
| Constructor | Description |
|---|---|
BCMethod(ClassBuilder cb,
java.lang.String returnType,
java.lang.String methodName,
int modifiers,
java.lang.String[] parms,
BCJava factory) |
| Modifier and Type | Method | Description |
|---|---|---|
private void |
addInstrCPE(short opcode,
int cpe) |
Write a instruction that uses a constant pool entry
as an operand, add a limit exceeded message if
the number of constant pool entries has exceeded
the limit.
|
void |
addThrownException(java.lang.String exceptionClass) |
a throwable can be added to the end of
the list of thrownExceptions.
|
int |
callMethod(short opcode,
java.lang.String declaringClass,
java.lang.String methodName,
java.lang.String returnType,
int numArgs) |
Call a method.
|
int |
callMethod(java.lang.Object methodDescriptor) |
Call a method previously described by describeMethod().
|
(package private) void |
callSubMethod(BCMethod subMethod) |
Call a sub-method created by getNewSubMethod handling parameters
correctly.
|
void |
callSuper() |
Call super().
|
void |
cast(java.lang.String className) |
Cast the top stack value.
|
void |
complete() |
when the method has had all of its parameters
and thrown exceptions defined, and its statement
block has been completed, it can be completed and
its class file information generated.
|
void |
completeConditional() |
Complete a conditional which completes the false code path.
|
void |
conditionalIf() |
Initiate a conditional sequence.
|
private void |
conditionalIf(short opcode) |
|
void |
conditionalIfNull() |
Initiate a conditional sequence.
|
(package private) ClassHolder |
constantPool() |
In their giveCode methods, the parts of the method body will want to get
to the constant pool to add their constants.
|
private Type[] |
copyStack() |
|
java.lang.Object |
describeMethod(short opcode,
java.lang.String declaringClass,
java.lang.String methodName,
java.lang.String returnType) |
Return an object that efficiently (to the implementation) describes a zero-argument method and
can be used with the single argument callMethod().
|
void |
dup() |
Duplicate the top value on the stack.
|
void |
endStatement() |
End a statement.
|
void |
getArrayElement(int element) |
Pop an array refrence off the stack and push an element from that array.
|
private void |
getField(short opcode,
java.lang.String declaringClass,
java.lang.String fieldName,
java.lang.String fieldType) |
|
void |
getField(java.lang.String declaringClass,
java.lang.String fieldName,
java.lang.String fieldType) |
Push the contents of the described field onto the stack.
|
void |
getField(LocalField field) |
Push the contents of the local field onto the stack.
|
java.lang.String |
getName() |
Return the logical name of the method.
|
(package private) BCMethod |
getNewSubMethod(java.lang.String returnType,
boolean withParameters) |
Create a sub-method from this method to allow the code builder to split a
single logical method into multiple methods to avoid the 64k per-method
code size limit.
|
void |
getParameter(int id) |
Push a parameter value.
|
void |
getStaticField(java.lang.String declaringClass,
java.lang.String fieldName,
java.lang.String fieldType) |
Push the contents of the described static field onto the stack.
|
private void |
growStack(int size,
Type type) |
|
private void |
growStack(Type type) |
|
void |
isInstanceOf(java.lang.String className) |
Pop the top stack value and push a boolean that is the result of
an instanceof check on the popped reference.
|
void |
methodReturn() |
Return from a method, optionally with a value.
|
private void |
overflowMethodCheck() |
Check to see if the current method byte code is nearing the
limit of 65535.
|
void |
pop() |
Pop the top value off the stack
|
private Type |
popStack() |
|
void |
push(boolean value) |
Push a boolean constant onto the stack
|
void |
push(byte value) |
Push a byte constant onto the stack
|
void |
push(double value) |
Push a double constant onto the stack
|
void |
push(float value) |
Push a float constant onto the stack
|
void |
push(int value) |
Push a int constant onto the stack
|
private void |
push(int value,
Type type) |
Push an integer value.
|
void |
push(long value) |
Push a long value onto the stack.
|
void |
push(short value) |
Push a short constant onto the stack
|
void |
push(java.lang.String value) |
Push a String constant onto the stack
|
void |
pushNewArray(java.lang.String className,
int size) |
Create an array instance
Stack
|
void |
pushNewComplete(int numArgs) |
Complete the sequence that was started with pushNewStart().
|
void |
pushNewStart(java.lang.String className) |
Initiate a sequence that calls a constructor, equivalent to the new operator in Java.
|
void |
pushNull(java.lang.String type) |
Push a typed null onto the stack
|
void |
pushThis() |
Push this onto the stack.
|
void |
putField(java.lang.String fieldName,
java.lang.String fieldType) |
Pop the top stack value and store it in the instance field of this class.
|
void |
putField(java.lang.String declaringClass,
java.lang.String fieldName,
java.lang.String fieldType) |
Pop the top stack value and store it in the field.
|
void |
putField(LocalField field) |
Upon entry the top word(s) on the stack is
the value to be put into the field.
|
private void |
putField(Type fieldType,
int cpi,
boolean dup) |
|
void |
setArrayElement(int element) |
Pop an array reference off the stack, store a value in the array at the passed in offset.
|
void |
setField(LocalField field) |
Set the field but don't duplicate its value so
nothing is left on the stack after this call.
|
private void |
splitMethod() |
Attempt to split a large method by pushing code out to several
sub-methods.
|
void |
startElseCode() |
Complete the true code path of a conditional.
|
boolean |
statementNumHitLimit(int noStatementsAdded) |
Tell if statement number in this method builder hits limit.
|
void |
swap() |
Swap the top two values on the stack.
|
void |
upCast(java.lang.String className) |
Upcast the top stack value.
|
private Type |
vmNameDeclaringClass(java.lang.String declaringClass) |
|
protected void |
writeExceptions() |
sets exceptionBytes to the attribute_info needed
for a method's Exceptions attribute.
|
static final int CODE_SPLIT_LENGTH
final BCClass cb
protected final ClassHolder modClass
final java.lang.String myReturnType
private final java.lang.String myName
BCLocalField[] parameters
private final java.lang.String[] parameterTypes
java.util.Vector<java.lang.String> thrownExceptions
CodeChunk myCode
protected ClassMember myEntry
private int currentVarNum
private int statementNum
private boolean handlingOverflow
private int subMethodCount
private Type[] stackTypes
private int stackTypeOffset
int maxStack
private int stackDepth
private Conditional condition
private static final byte[] newArrayElementTypeMap
Because boolean was mapped to integer for general instructions, it will have to be specially matched and mapped to its value directly (4).
static final byte T_BOOLEAN
BCMethod(ClassBuilder cb, java.lang.String returnType, java.lang.String methodName, int modifiers, java.lang.String[] parms, BCJava factory)
public java.lang.String getName()
getName in interface MethodBuilderpublic void getParameter(int id)
MethodBuilder
Stack ... =>
...,param_value
getParameter in interface MethodBuilderid - position of the parameter (zero based).public void addThrownException(java.lang.String exceptionClass)
addThrownException in interface MethodBuilderpublic void complete()
further alterations of the method will not be reflected in the code generated for it.
complete in interface MethodBuilderprivate void splitMethod()
ClassHolder constantPool()
protected void writeExceptions()
private void growStack(int size,
Type type)
private void growStack(Type type)
private Type popStack()
private Type[] copyStack()
public void pushThis()
MethodBuilder
Stack ... =>
...,this_ref
pushThis in interface MethodBuilderpublic void push(byte value)
MethodBuilder
Stack ... =>
...,byte_value
push in interface MethodBuilderpublic void push(boolean value)
MethodBuilder
Stack ... =>
...,boolean_value
push in interface MethodBuilderpublic void push(short value)
MethodBuilder
Stack ... =>
...,short_value
push in interface MethodBuilderpublic void push(int value)
MethodBuilder
Stack ... =>
...,int_value
push in interface MethodBuilderpublic void dup()
MethodBuilder
Stack ...,value =>
...,value,value
dup in interface MethodBuilderpublic void swap()
MethodBuilder
Stack ...,valueA,valueB =>
...,valueB,valueA
swap in interface MethodBuilderprivate void push(int value,
Type type)
value - Value to be pushedtype - Final type of the value.public void push(long value)
push in interface MethodBuilderpublic void push(float value)
MethodBuilder
Stack ... =>
...,float_value
push in interface MethodBuilderpublic void push(double value)
MethodBuilder
Stack ... =>
...,double_value
push in interface MethodBuilderpublic void push(java.lang.String value)
MethodBuilder
Stack ... =>
...,String_value
push in interface MethodBuilderpublic void methodReturn()
MethodBuilder
Stack value =>
:empty:
or
Stack :empty: =>
:empty:
.methodReturn in interface MethodBuilderpublic java.lang.Object describeMethod(short opcode,
java.lang.String declaringClass,
java.lang.String methodName,
java.lang.String returnType)
MethodBuilderdescribeMethod in interface MethodBuilderpublic int callMethod(java.lang.Object methodDescriptor)
MethodBuilder
static methods
Stack ...,value* => [numArgs number of values will be popped]
...,return_value [void methods will not push a value]
non-static methods
Stack ...,ref,value* => [numArgs number of values will be popped]
...,return_value [void methods will not push a value]
callMethod in interface MethodBuilderpublic int callMethod(short opcode,
java.lang.String declaringClass,
java.lang.String methodName,
java.lang.String returnType,
int numArgs)
MethodBuilder
static methods
Stack ...,value* => [numArgs number of values will be popped]
...,return_value [void methods will not push a value]
non-static methods
Stack ...,ref,value* => [numArgs number of values will be popped]
...,return_value [void methods will not push a value]
callMethod in interface MethodBuilderopcode - type of method invocationdeclaringClass - Class or interface the method is declared in. If it is a non-static
method call then if declaringClass is null, the declared type is taken to be the
type of the reference that will be popped.methodName - name of the methodreturnType - class name or primitive type (including "void") of the return type of the method, can not be null.numArgs - number of arguments to the method (can be 0).private Type vmNameDeclaringClass(java.lang.String declaringClass)
public void callSuper()
MethodBuilder
Stack ... =>
...
callSuper in interface MethodBuilderpublic void pushNewStart(java.lang.String className)
MethodBuilder
Stack ... => [unchanged]
...
pushNewStart in interface MethodBuilderclassName - class name of object to be created.public void pushNewComplete(int numArgs)
MethodBuilder
Stack ...,value* => [numArgs number of values will be popped]
...,new_ref
pushNewComplete in interface MethodBuildernumArgs - number of arguments to the constructor (can be 0).public void upCast(java.lang.String className)
MethodBuilder
Stack ...,ref =>
...,ref
upCast in interface MethodBuilderpublic void cast(java.lang.String className)
MethodBuilder
Stack ...,value =>
...,cast_value
cast in interface MethodBuilderclassName - type (primitive, interface or class) to cast to.public void isInstanceOf(java.lang.String className)
MethodBuilder
Stack ...,ref =>
...,boolean_value
.isInstanceOf in interface MethodBuilderpublic void pushNull(java.lang.String type)
MethodBuilder
Stack ... =>
...,null
pushNull in interface MethodBuilderpublic void getField(LocalField field)
MethodBuilder
Stack ... =>
...,field_value
getField in interface MethodBuilderpublic void getField(java.lang.String declaringClass,
java.lang.String fieldName,
java.lang.String fieldType)
MethodBuilder
Stack ...,field_ref =>
...,field_value
getField in interface MethodBuilderpublic void getStaticField(java.lang.String declaringClass,
java.lang.String fieldName,
java.lang.String fieldType)
getStaticField in interface MethodBuilderprivate void getField(short opcode,
java.lang.String declaringClass,
java.lang.String fieldName,
java.lang.String fieldType)
public void setField(LocalField field)
setField in interface MethodBuilderpublic void putField(LocalField field)
word
Before the call we need
word
this
word
word2,word1 -> word2, word1, word2
So that we are left with word after the put.putField in interface MethodBuilderpublic void putField(java.lang.String fieldName,
java.lang.String fieldType)
putField in interface MethodBuilderprivate void putField(Type fieldType, int cpi, boolean dup)
public void putField(java.lang.String declaringClass,
java.lang.String fieldName,
java.lang.String fieldType)
putField in interface MethodBuilderpublic void conditionalIfNull()
MethodBuilder
mb.callMethod(...); // pushes an object onto the stack
mb.conditionalIfNull();
mb.push(3);
mb.startElseCode();
mb.push(5);
mb.completeConditional();
// at this point 3 or 5 will be on the stack
Each path through the ?: statement must leave the stack at the same depth
as the other.
Stack ...,ref =>
...
.conditionalIfNull in interface MethodBuilderpublic void conditionalIf()
MethodBuilder
Stack ...,boolean_value =>
...
.conditionalIf in interface MethodBuilderprivate void conditionalIf(short opcode)
public void startElseCode()
MethodBuilderstartElseCode in interface MethodBuilderpublic void completeConditional()
MethodBuildercompleteConditional in interface MethodBuilderpublic void pop()
MethodBuilder
Stack ..., value =>
...
.pop in interface MethodBuilderpublic void endStatement()
MethodBuilder
Stack value =>
:empty:
or
Stack :empty: =>
:empty:
.endStatement in interface MethodBuilderpublic void getArrayElement(int element)
MethodBuilder
Stack ...,array_ref =>
...,value
getArrayElement in interface MethodBuilderelement - Offset into the array (zero based)public void setArrayElement(int element)
MethodBuilder
Stack ...,array_ref, value =>
...
setArrayElement in interface MethodBuilderelement - Offset into the array (zero based)public void pushNewArray(java.lang.String className,
int size)
pushNewArray in interface MethodBuilderclassName - - type of array.size - - number of elements in the arrayprivate void addInstrCPE(short opcode,
int cpe)
public boolean statementNumHitLimit(int noStatementsAdded)
statementNumHitLimit in interface MethodBuilderprivate void overflowMethodCheck()
Overflow is handled for a method named e23 as:
public Object e23()
{
... existing code
// split point
return e23_0();
}
private Object e23_0()
{
... first set overflowed code
// split point
return e23_1();
}
private Object e23_1()
{
... second set overflowed code
// method complete
return result;
}
These overflow methods are hidden from the code using this MethodBuilder,
it continues to think that it is building a single method with the
original name.
Restrictions:
final BCMethod getNewSubMethod(java.lang.String returnType, boolean withParameters)
returnType - Return type of the new methodwithParameters - True to define the method with matching parameters false to
define it with no parameters.final void callSubMethod(BCMethod subMethod)
Apache Derby V10.14 Internals - Copyright © 2004,2018 The Apache Software Foundation. All Rights Reserved.