use of org.jikesrvm.osr.bytecodes.PseudoBytecode in project JikesRVM by JikesRVM.
the class ExecutionState method paddingBytecode.
/**
* Adds padding (NOP) at the beginning of pseudo bytecode
* to make the new bytecode size dividable by 4, then no branch
* target adjustment is needed in the original code.
* @param head the first pseudo bytecode (must be NOP)
* @return the new bytecode size
*/
private static int paddingBytecode(PseudoBytecode head) {
/* skip the first Nop. */
PseudoBytecode bcode = head.next;
/* count the total size of prologue code. */
int bsize = 0;
while (bcode != null) {
bsize += bcode.getSize();
bcode = bcode.next;
}
/* insert Nop at the beginning to make the code size of x4. */
int padding = 3 - (bsize + 3) & 0x03;
for (int i = 0; i < padding; i++) {
bcode = new Nop();
bcode.next = head.next;
head.next = bcode;
}
bsize += padding;
return bsize;
}
use of org.jikesrvm.osr.bytecodes.PseudoBytecode in project JikesRVM by JikesRVM.
the class ExecutionState method generateBinaries.
/**
* Generating binary code from pseudo code, the size and the code
* list are padded and well calculated.
*
* @param bhead the first pseude bytecode (must be a NOP)
* @param bsize the size of the bytecode
* @return generated bytecodes
*/
private static byte[] generateBinaries(PseudoBytecode bhead, int bsize) {
/* patch the LoalAddrConst instruction, and generate codes. */
byte[] codes = new byte[bsize];
/* skip the first NOP */
PseudoBytecode bcode = bhead.next;
int pos = 0;
while (bcode != null) {
int size = bcode.getSize();
if (bcode instanceof LoadRetAddrConst) {
LoadRetAddrConst laddr = (LoadRetAddrConst) bcode;
/* CAUTION: path relative offset only. */
laddr.patch(laddr.getOffset() + bsize);
}
if (VM.TraceOnStackReplacement)
VM.sysWriteln(pos + " : " + bcode.toString());
System.arraycopy(bcode.getBytes(), 0, codes, pos, size);
pos += size;
bcode = bcode.next;
}
return codes;
}
use of org.jikesrvm.osr.bytecodes.PseudoBytecode in project JikesRVM by JikesRVM.
the class ExecutionState method computeStackHeight.
private int computeStackHeight(PseudoBytecode head) {
/* skip the first Nop */
PseudoBytecode bcode = head.next;
short height = 0;
while (bcode != null) {
height += bcode.stackChanges();
if (height > this.maxStackHeight) {
this.maxStackHeight = height;
}
bcode = bcode.next;
}
if (VM.VerifyAssertions)
VM._assert(height >= 0);
return height;
}
use of org.jikesrvm.osr.bytecodes.PseudoBytecode in project JikesRVM by JikesRVM.
the class ExecutionState method generatePrologue.
/**
* Goes through variable elements and produces specialized
* prologue using pseudo-bytecode.
*
* @return the specialized prologue
*/
public byte[] generatePrologue() {
int size = varElms.size();
this.objs = new Object[size];
this.objnum = 0;
this.rid = ObjectHolder.handinRefs(this.objs);
PseudoBytecode head = new Nop();
PseudoBytecode tail = head;
int elmcount = 0;
// restore "this"
if (!this.meth.isStatic()) {
VariableElement var = varElms.get(elmcount);
tail = processElement(var, tail, elmcount);
elmcount++;
if (VM.VerifyAssertions) {
VM._assert(var.isLocal() && (var.getNumber() == 0));
}
}
// restore other parameters,
int paranum = this.meth.getParameterTypes().length;
for (int i = 0; i < paranum; i++) {
VariableElement var = varElms.get(elmcount);
tail = processElement(var, tail, elmcount);
elmcount++;
if (VM.VerifyAssertions) {
VM._assert(var.isLocal());
// the number may not match because of long and double type
}
}
// ok, ready to indicate param initialized, thread switch
// and stack overflow check happens here
tail.next = new ParamInitEnd();
tail = tail.next;
// were sorted
for (; elmcount < size; elmcount++) {
VariableElement var = varElms.get(elmcount);
tail = processElement(var, tail, elmcount);
}
if (this.objnum != 0) {
tail.next = new LoadIntConst(this.rid);
tail = tail.next;
tail.next = new InvokeStatic(CLEANREFS);
tail = tail.next;
} else {
ObjectHolder.cleanRefs(this.rid);
}
// default situation
int branchTarget = this.bcIndex;
/* when this method must start with a call of callee,
* we are using invokeCompiledMethod,
*/
if (callee_cmid != -1) {
// remember the callee's cmid, and the index of original index
tail.next = new InvokeCompiledMethod(callee_cmid, this.bcIndex);
tail = tail.next;
// if this method needs a call, than we must jump to
// the instruction after the call.
BytecodeStream bcodes = this.meth.getBytecodes();
bcodes.reset(this.bcIndex);
int code = bcodes.nextInstruction();
if (JBC_isJava6Call(code)) {
branchTarget = this.bcIndex + JBC_length(code);
} else {
if (VM.VerifyAssertions) {
String msg = "ExecutionState: unknown bytecode " + code + " at " + this.bcIndex + "@" + this.meth;
VM._assert(VM.NOT_REACHED, msg);
}
}
}
// add goto statement, be careful, after goto
// there may be several pop instructions
int pops = computeStackHeight(head);
// preserve space
branchTarget += pops;
{
Goto togo = new Goto(branchTarget);
int osize = togo.getSize();
togo.patch(branchTarget + osize);
int nsize = togo.getSize();
if (nsize != osize) {
togo.patch(branchTarget + nsize);
}
tail.next = togo;
tail = tail.next;
}
// compute stack heights and padding pops
tail = adjustStackHeight(tail, pops);
int bsize = paddingBytecode(head);
byte[] prologue = generateBinaries(head, bsize);
// clean fields
this.objs = null;
this.objnum = 0;
return prologue;
}
Aggregations