class 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 and 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 and Description |
---|
BCMethod(ClassBuilder cb,
java.lang.String returnType,
java.lang.String methodName,
int modifiers,
java.lang.String[] parms,
BCJava factory) |
Modifier and Type | Method and 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(java.lang.Object methodDescriptor)
Call a method previously described by describeMethod().
|
int |
callMethod(short opcode,
java.lang.String declaringClass,
java.lang.String methodName,
java.lang.String returnType,
int numArgs)
Call a method.
|
(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.
|
void |
getField(LocalField field)
Push the contents of the local field onto the stack.
|
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.
|
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
Stack ..., value =>
...
|
private Type |
popStack() |
void |
push(boolean value)
Push a boolean constant onto the stack
Stack ...
|
void |
push(byte value)
Push a byte constant onto the stack
Stack ...
|
void |
push(double value)
Push a double constant onto the stack
Stack ...
|
void |
push(float value)
Push a float constant onto the stack
Stack ...
|
void |
push(int value)
Push a int constant onto the stack
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
Stack ...
|
void |
push(java.lang.String value)
Push a String constant onto the stack
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
Stack ...
|
void |
pushThis()
Push this onto the stack.
|
void |
putField(LocalField field)
Upon entry the top word(s) on the stack is
the value to be put into the field.
|
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.
|
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 MethodBuilder
public void getParameter(int id)
MethodBuilder
Stack ... => ...,param_value
getParameter
in interface MethodBuilder
id
- position of the parameter (zero based).public void addThrownException(java.lang.String exceptionClass)
addThrownException
in interface MethodBuilder
public void complete()
further alterations of the method will not be reflected in the code generated for it.
complete
in interface MethodBuilder
private 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 MethodBuilder
public void push(byte value)
MethodBuilder
Stack ... => ...,byte_value
push
in interface MethodBuilder
public void push(boolean value)
MethodBuilder
Stack ... => ...,boolean_value
push
in interface MethodBuilder
public void push(short value)
MethodBuilder
Stack ... => ...,short_value
push
in interface MethodBuilder
public void push(int value)
MethodBuilder
Stack ... => ...,int_value
push
in interface MethodBuilder
public void dup()
MethodBuilder
Stack ...,value => ...,value,value
dup
in interface MethodBuilder
public void swap()
MethodBuilder
Stack ...,valueA,valueB => ...,valueB,valueA
swap
in interface MethodBuilder
private void push(int value, Type type)
value
- Value to be pushedtype
- Final type of the value.public void push(long value)
push
in interface MethodBuilder
public void push(float value)
MethodBuilder
Stack ... => ...,float_value
push
in interface MethodBuilder
public void push(double value)
MethodBuilder
Stack ... => ...,double_value
push
in interface MethodBuilder
public void push(java.lang.String value)
MethodBuilder
Stack ... => ...,String_value
push
in interface MethodBuilder
public void methodReturn()
MethodBuilder
Stack value => :empty: or Stack :empty: => :empty:.
methodReturn
in interface MethodBuilder
public java.lang.Object describeMethod(short opcode, java.lang.String declaringClass, java.lang.String methodName, java.lang.String returnType)
MethodBuilder
describeMethod
in interface MethodBuilder
public 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 MethodBuilder
public 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 MethodBuilder
opcode
- 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 MethodBuilder
public void pushNewStart(java.lang.String className)
MethodBuilder
Stack ... => [unchanged] ...
pushNewStart
in interface MethodBuilder
className
- 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 MethodBuilder
numArgs
- number of arguments to the constructor (can be 0).public void upCast(java.lang.String className)
MethodBuilder
Stack ...,ref => ...,ref
upCast
in interface MethodBuilder
public void cast(java.lang.String className)
MethodBuilder
Stack ...,value => ...,cast_value
cast
in interface MethodBuilder
className
- type (primitive, interface or class) to cast to.public void isInstanceOf(java.lang.String className)
MethodBuilder
Stack ...,ref => ...,boolean_value.
isInstanceOf
in interface MethodBuilder
public void pushNull(java.lang.String type)
MethodBuilder
Stack ... => ...,null
pushNull
in interface MethodBuilder
public void getField(LocalField field)
MethodBuilder
Stack ... => ...,field_value
getField
in interface MethodBuilder
public void getField(java.lang.String declaringClass, java.lang.String fieldName, java.lang.String fieldType)
MethodBuilder
Stack ...,field_ref => ...,field_value
getField
in interface MethodBuilder
public void getStaticField(java.lang.String declaringClass, java.lang.String fieldName, java.lang.String fieldType)
getStaticField
in interface MethodBuilder
private void getField(short opcode, java.lang.String declaringClass, java.lang.String fieldName, java.lang.String fieldType)
public void setField(LocalField field)
setField
in interface MethodBuilder
public void putField(LocalField field)
wordBefore the call we need
word this wordword2,word1 -> word2, word1, word2 So that we are left with word after the put.
putField
in interface MethodBuilder
public void putField(java.lang.String fieldName, java.lang.String fieldType)
putField
in interface MethodBuilder
private 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 MethodBuilder
public 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 stackEach path through the ?: statement must leave the stack at the same depth as the other.
Stack ...,ref => ....
conditionalIfNull
in interface MethodBuilder
public void conditionalIf()
MethodBuilder
Stack ...,boolean_value => ....
conditionalIf
in interface MethodBuilder
private void conditionalIf(short opcode)
public void startElseCode()
MethodBuilder
startElseCode
in interface MethodBuilder
public void completeConditional()
MethodBuilder
completeConditional
in interface MethodBuilder
public void pop()
MethodBuilder
Stack ..., value => ....
pop
in interface MethodBuilder
public void endStatement()
MethodBuilder
Stack value => :empty: or Stack :empty: => :empty:.
endStatement
in interface MethodBuilder
public void getArrayElement(int element)
MethodBuilder
Stack ...,array_ref => ...,value
getArrayElement
in interface MethodBuilder
element
- Offset into the array (zero based)public void setArrayElement(int element)
MethodBuilder
Stack ...,array_ref, value => ...
setArrayElement
in interface MethodBuilder
element
- Offset into the array (zero based)public void pushNewArray(java.lang.String className, int size)
pushNewArray
in interface MethodBuilder
className
- - type of array.size
- - number of elements in the arrayprivate void addInstrCPE(short opcode, int cpe)
public boolean statementNumHitLimit(int noStatementsAdded)
statementNumHitLimit
in interface MethodBuilder
private 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.13 Internals - Copyright © 2004,2016 The Apache Software Foundation. All Rights Reserved.