use of org.jikesrvm.classloader.RVMClass in project JikesRVM by JikesRVM.
the class BytecodeTraverser method scanBlocks.
// //////////////////////////
// IMPLEMENTATION
// /////////////////////////
/* return true --> hit the bytecode pointed by PC */
private // which method
boolean scanBlocks(// which method
NormalMethod method, // the bytecodes
BytecodeStream bytecodes, // do a DFS or one-pass scan
boolean doDFS, // the target pcs, if doDFS
int pcs, // the local types if doDFS
byte[] ltypes, // the stack types if doDFS
byte[] stypes, // start pc
int startpc, // stack
TypeStack S, int[] stackHeights) {
// the stack height if not doDFS
int localsize = method.getLocalWords() - 1;
RVMClass declaringClass = method.getDeclaringClass();
bytecodes.reset(startpc);
boolean found = false;
while (bytecodes.hasMoreBytecodes()) {
// get current pc
int pc = bytecodes.index();
if (visitedpc[pc] == 1) {
return false;
} else {
visitedpc[pc] = 1;
}
if (doDFS && (pc == pcs)) {
/* make a copy of stack frame and put into stypes. */
byte[] stack = S.snapshot();
System.arraycopy(stack, 0, stypes, 0, stack.length);
return true;
}
if (!doDFS) {
// record stack heights
stackHeights[pc] = localsize + S.depth();
}
/* let's continue */
int bcode = bytecodes.nextInstruction();
if (TRACE) {
if (bcode <= JBC_jsr_w) {
VM.sysWriteln(pc + " : " + S.depth() + " : " + JBC_name(bcode));
} else {
VM.sysWriteln(pc + " : " + S.depth() + " : impdep1");
}
}
switch(bcode) {
case JBC_nop:
break;
case JBC_aconst_null:
S.push(ClassTypeCode);
break;
case JBC_iconst_m1:
case JBC_iconst_0:
case JBC_iconst_1:
case JBC_iconst_2:
case JBC_iconst_3:
case JBC_iconst_4:
case JBC_iconst_5:
S.push(IntTypeCode);
break;
case JBC_lconst_0:
case JBC_lconst_1:
/* we should do the save order as opt compiler */
S.push(VoidTypeCode);
S.push(LongTypeCode);
break;
case JBC_fconst_0:
case JBC_fconst_1:
case JBC_fconst_2:
S.push(FloatTypeCode);
break;
case JBC_dconst_0:
case JBC_dconst_1:
S.push(VoidTypeCode);
S.push(DoubleTypeCode);
break;
case JBC_bipush:
bytecodes.getByteValue();
S.push(IntTypeCode);
break;
case JBC_sipush:
bytecodes.getShortValue();
S.push(IntTypeCode);
break;
case JBC_ldc:
case JBC_ldc_w:
{
int cpoolidx = (bcode == JBC_ldc) ? bytecodes.getConstantIndex() : bytecodes.getWideConstantIndex();
byte tdesc = declaringClass.getLiteralDescription(cpoolidx);
switch(tdesc) {
case CP_INT:
S.push(IntTypeCode);
break;
case CP_FLOAT:
S.push(FloatTypeCode);
break;
case CP_STRING:
S.push(ClassTypeCode);
break;
case CP_CLASS:
S.push(ClassTypeCode);
break;
default:
if (VM.TraceOnStackReplacement)
VM.sysWriteln("ldc unknown type " + tdesc);
if (VM.VerifyAssertions)
VM._assert(VM.NOT_REACHED);
break;
}
// end of switch
}
break;
case JBC_ldc2_w:
{
int cpoolidx = bytecodes.getWideConstantIndex();
byte tdesc = declaringClass.getLiteralDescription(cpoolidx);
S.push(VoidTypeCode);
switch(tdesc) {
case CP_LONG:
S.push(LongTypeCode);
break;
case CP_DOUBLE:
S.push(DoubleTypeCode);
break;
default:
if (VM.TraceOnStackReplacement)
VM.sysWriteln("ldc2_w unknown type " + tdesc);
if (VM.VerifyAssertions)
VM._assert(VM.NOT_REACHED);
break;
}
// end of switch
}
break;
case JBC_iload:
// skip local
bytecodes.getLocalNumber();
S.push(IntTypeCode);
break;
case JBC_lload:
// skip local
bytecodes.getLocalNumber();
S.push(VoidTypeCode);
S.push(LongTypeCode);
break;
case JBC_fload:
// skip local
bytecodes.getLocalNumber();
S.push(FloatTypeCode);
break;
case JBC_dload:
bytecodes.getLocalNumber();
S.push(VoidTypeCode);
S.push(DoubleTypeCode);
break;
case JBC_aload:
bytecodes.getLocalNumber();
S.push(ClassTypeCode);
break;
case JBC_iload_0:
case JBC_iload_1:
case JBC_iload_2:
case JBC_iload_3:
S.push(IntTypeCode);
break;
case JBC_lload_0:
case JBC_lload_1:
case JBC_lload_2:
case JBC_lload_3:
S.push(VoidTypeCode);
S.push(LongTypeCode);
break;
case JBC_fload_0:
case JBC_fload_1:
case JBC_fload_2:
case JBC_fload_3:
S.push(FloatTypeCode);
break;
case JBC_dload_0:
case JBC_dload_1:
case JBC_dload_2:
case JBC_dload_3:
S.push(VoidTypeCode);
S.push(DoubleTypeCode);
break;
case JBC_aload_0:
case JBC_aload_1:
case JBC_aload_2:
case JBC_aload_3:
S.push(ClassTypeCode);
break;
case JBC_iaload:
case JBC_baload:
case JBC_caload:
case JBC_saload:
S.pop();
S.pop();
S.push(IntTypeCode);
break;
case JBC_laload:
S.pop();
S.pop();
S.push(VoidTypeCode);
S.push(LongTypeCode);
break;
case JBC_faload:
S.pop();
S.pop();
S.push(FloatTypeCode);
break;
case JBC_daload:
S.pop();
S.pop();
S.push(VoidTypeCode);
S.push(DoubleTypeCode);
break;
case JBC_aaload:
S.pop();
S.pop();
S.push(ClassTypeCode);
break;
case JBC_istore:
{
S.pop();
int index = bytecodes.getLocalNumber();
if (doDFS)
ltypes[index] = IntTypeCode;
}
break;
case JBC_istore_0:
case JBC_istore_1:
case JBC_istore_2:
case JBC_istore_3:
{
S.pop();
int index = bcode - JBC_istore_0;
if (doDFS)
ltypes[index] = IntTypeCode;
}
break;
case JBC_lstore:
{
S.pop();
S.pop();
int index = bytecodes.getLocalNumber();
if (doDFS) {
ltypes[index] = LongTypeCode;
ltypes[index + 1] = VoidTypeCode;
}
}
break;
case JBC_lstore_0:
case JBC_lstore_1:
case JBC_lstore_2:
case JBC_lstore_3:
{
S.pop();
S.pop();
int index = bcode - JBC_lstore_0;
if (doDFS) {
ltypes[index] = LongTypeCode;
ltypes[index + 1] = VoidTypeCode;
}
}
break;
case JBC_fstore:
{
S.pop();
int index = bytecodes.getLocalNumber();
if (doDFS)
ltypes[index] = FloatTypeCode;
}
break;
case JBC_fstore_0:
case JBC_fstore_1:
case JBC_fstore_2:
case JBC_fstore_3:
{
S.pop();
int index = bcode - JBC_fstore_0;
if (doDFS)
ltypes[index] = FloatTypeCode;
}
break;
case JBC_dstore:
{
S.pop();
S.pop();
int index = bytecodes.getLocalNumber();
if (doDFS) {
ltypes[index] = DoubleTypeCode;
ltypes[index + 1] = VoidTypeCode;
}
}
break;
case JBC_dstore_0:
case JBC_dstore_1:
case JBC_dstore_2:
case JBC_dstore_3:
{
S.pop();
S.pop();
int index = bcode - JBC_dstore_0;
if (doDFS) {
ltypes[index] = DoubleTypeCode;
ltypes[index + 1] = VoidTypeCode;
}
}
break;
case JBC_astore:
{
// caution: astore may save return address type
int index = bytecodes.getLocalNumber();
byte tcode = S.pop();
if (doDFS)
ltypes[index] = tcode;
// for ret address.
if (tcode == ReturnAddressTypeCode) {
retaddr[index] = addr;
addr = -1;
}
}
break;
case JBC_astore_0:
case JBC_astore_1:
case JBC_astore_2:
case JBC_astore_3:
{
// caution: astore may save return address type
int index = bcode - JBC_astore_0;
byte tcode = S.pop();
if (doDFS)
ltypes[index] = tcode;
// for ret address.
if (tcode == ReturnAddressTypeCode) {
retaddr[index] = addr;
addr = -1;
}
}
break;
case JBC_iastore:
case JBC_bastore:
case JBC_castore:
case JBC_sastore:
S.pop(3);
break;
case JBC_lastore:
S.pop(4);
break;
case JBC_fastore:
S.pop(3);
break;
case JBC_dastore:
S.pop(4);
break;
case JBC_aastore:
S.pop(3);
break;
case JBC_pop:
S.pop();
break;
case JBC_pop2:
S.pop(2);
break;
case JBC_dup:
{
byte v1 = S.peek();
S.push(v1);
}
break;
case JBC_dup_x1:
{
byte v1 = S.peek();
S.pop();
byte v2 = S.peek();
S.pop();
S.push(v1);
S.push(v2);
S.push(v1);
}
break;
case JBC_dup_x2:
{
byte v1 = S.peek();
S.pop();
byte v2 = S.peek();
S.pop();
byte v3 = S.peek();
S.pop();
S.push(v1);
S.push(v3);
S.push(v2);
S.push(v1);
}
break;
case JBC_dup2:
{
byte v1 = S.peek();
S.pop();
byte v2 = S.peek();
S.push(v1);
S.push(v2);
S.push(v1);
}
break;
case JBC_dup2_x1:
{
byte v1 = S.peek();
S.pop();
byte v2 = S.peek();
S.pop();
byte v3 = S.peek();
S.pop();
S.push(v2);
S.push(v1);
S.push(v3);
S.push(v2);
S.push(v1);
}
break;
case JBC_dup2_x2:
{
byte v1 = S.peek();
S.pop();
byte v2 = S.peek();
S.pop();
byte v3 = S.peek();
S.pop();
byte v4 = S.peek();
S.pop();
S.push(v2);
S.push(v1);
S.push(v4);
S.push(v3);
S.push(v2);
S.push(v1);
}
break;
case JBC_swap:
{
byte v1 = S.peek();
S.pop();
byte v2 = S.peek();
S.pop();
S.push(v1);
S.push(v2);
}
break;
case JBC_iadd:
case JBC_isub:
case JBC_imul:
case JBC_idiv:
case JBC_irem:
case JBC_iand:
case JBC_ior:
case JBC_ixor:
case JBC_ishl:
case JBC_ishr:
case JBC_iushr:
S.pop();
break;
case JBC_ladd:
case JBC_lsub:
case JBC_lmul:
case JBC_ldiv:
case JBC_lrem:
case JBC_land:
case JBC_lor:
case JBC_lxor:
S.pop(2);
break;
case JBC_lshl:
case JBC_lshr:
case JBC_lushr:
S.pop();
break;
case JBC_fadd:
case JBC_fsub:
case JBC_fmul:
case JBC_fdiv:
case JBC_frem:
S.pop();
break;
case JBC_dadd:
case JBC_dsub:
case JBC_dmul:
case JBC_ddiv:
case JBC_drem:
S.pop(2);
break;
case JBC_ineg:
case JBC_lneg:
case JBC_fneg:
case JBC_dneg:
break;
case JBC_iinc:
{
int index = bytecodes.getLocalNumber();
/* int value = */
bytecodes.getIncrement();
if (doDFS)
ltypes[index] = IntTypeCode;
}
break;
case JBC_i2l:
S.pop();
S.push(VoidTypeCode);
S.push(LongTypeCode);
break;
case JBC_i2f:
S.pop();
S.push(FloatTypeCode);
break;
case JBC_i2d:
S.pop();
S.push(VoidTypeCode);
S.push(DoubleTypeCode);
break;
case JBC_l2i:
S.pop(2);
S.push(IntTypeCode);
break;
case JBC_l2f:
S.pop(2);
S.push(FloatTypeCode);
break;
case JBC_l2d:
S.pop(2);
S.push(VoidTypeCode);
S.push(DoubleTypeCode);
break;
case JBC_f2i:
S.pop();
S.push(IntTypeCode);
break;
case JBC_f2l:
S.pop();
S.push(VoidTypeCode);
S.push(LongTypeCode);
break;
case JBC_f2d:
S.pop();
S.push(VoidTypeCode);
S.push(DoubleTypeCode);
break;
case JBC_d2i:
S.pop(2);
S.push(IntTypeCode);
break;
case JBC_d2l:
S.pop(2);
S.push(VoidTypeCode);
S.push(LongTypeCode);
break;
case JBC_d2f:
S.pop(2);
S.push(FloatTypeCode);
break;
case JBC_int2byte:
case JBC_int2char:
case JBC_int2short:
break;
case JBC_lcmp:
S.pop(4);
S.push(IntTypeCode);
break;
case JBC_fcmpl:
case JBC_fcmpg:
S.pop(2);
S.push(IntTypeCode);
break;
case JBC_dcmpl:
case JBC_dcmpg:
S.pop(4);
S.push(IntTypeCode);
break;
case JBC_ifeq:
case JBC_ifne:
case JBC_iflt:
case JBC_ifge:
case JBC_ifgt:
case JBC_ifle:
case JBC_ifnull:
case JBC_ifnonnull:
{
S.pop();
// flowthrough first
int nextpc = pc + 3;
int target = pc + bytecodes.getBranchOffset();
if (doDFS) {
// make a copy of ltypes, stypes to pass in
byte[] newltypes = new byte[ltypes.length];
byte[] newstypes = new byte[stypes.length];
System.arraycopy(ltypes, 0, newltypes, 0, ltypes.length);
System.arraycopy(stypes, 0, newstypes, 0, stypes.length);
found = scanBlocks(method, bytecodes, true, pcs, newltypes, newstypes, nextpc, new TypeStack(S), null);
if (found) {
// copy back the ltypes and stypes
System.arraycopy(newltypes, 0, ltypes, 0, ltypes.length);
System.arraycopy(newstypes, 0, stypes, 0, stypes.length);
return true;
}
} else {
found = scanBlocks(method, bytecodes, false, -1, null, null, nextpc, new TypeStack(S), stackHeights);
}
bytecodes.reset(target);
}
break;
case JBC_if_icmpeq:
case JBC_if_icmpne:
case JBC_if_icmplt:
case JBC_if_icmpge:
case JBC_if_icmpgt:
case JBC_if_icmple:
case JBC_if_acmpeq:
case JBC_if_acmpne:
{
S.pop(2);
// flowthrough first
int nextpc = pc + 3;
int target = pc + bytecodes.getBranchOffset();
if (doDFS) {
// make a copy of ltypes, stypes to pass in
byte[] newltypes = new byte[ltypes.length];
byte[] newstypes = new byte[stypes.length];
System.arraycopy(ltypes, 0, newltypes, 0, ltypes.length);
System.arraycopy(stypes, 0, newstypes, 0, stypes.length);
found = scanBlocks(method, bytecodes, true, pcs, newltypes, newstypes, nextpc, new TypeStack(S), null);
if (found) {
// copy back the ltypes and stypes
System.arraycopy(newltypes, 0, ltypes, 0, ltypes.length);
System.arraycopy(newstypes, 0, stypes, 0, stypes.length);
return true;
}
} else {
found = scanBlocks(method, bytecodes, false, -1, null, null, nextpc, new TypeStack(S), stackHeights);
}
bytecodes.reset(target);
}
break;
case JBC_goto:
{
int offset = bytecodes.getBranchOffset();
if (!ignoreGotos) {
bytecodes.reset(pc + offset);
}
}
break;
case JBC_goto_w:
{
int offset = bytecodes.getWideBranchOffset();
if (!ignoreGotos) {
bytecodes.reset(pc + offset);
}
}
break;
case JBC_jsr:
case JBC_jsr_w:
{
// flow through firs
int nextpc = pc + ((bcode == JBC_jsr) ? 3 : 5);
int target = pc + ((bcode == JBC_jsr) ? bytecodes.getBranchOffset() : bytecodes.getWideBranchOffset());
if (doDFS) {
// make a copy of ltypes, stypes to pass in
byte[] newltypes = new byte[ltypes.length];
byte[] newstypes = new byte[stypes.length];
System.arraycopy(ltypes, 0, newltypes, 0, ltypes.length);
System.arraycopy(stypes, 0, newstypes, 0, stypes.length);
found = scanBlocks(method, bytecodes, true, pcs, newltypes, newstypes, nextpc, new TypeStack(S), null);
if (found) {
// copy back the ltypes and stypes
System.arraycopy(newltypes, 0, ltypes, 0, ltypes.length);
System.arraycopy(newstypes, 0, stypes, 0, stypes.length);
return true;
}
} else {
found = scanBlocks(method, bytecodes, false, -1, null, null, nextpc, new TypeStack(S), stackHeights);
}
// branch to jsr subroutine
// remember return address for ret.
addr = pc + ((bcode == JBC_jsr) ? 3 : 5);
S.push(ReturnAddressTypeCode);
bytecodes.reset(target);
}
break;
case JBC_ret:
{
// the OPT compiler set local to null after _ret instruction,
// then we should clean it here also, otherwise it will
// throw a null pointer exception.
// HOWEVER, it is not part of JVM spec.
int index = bytecodes.getLocalNumber();
if (doDFS)
ltypes[index] = VoidTypeCode;
/* the ret address may be saved by a PSEUDO_LoadRetAddrConstant
*/
if (retaddr[index] != -1) {
bytecodes.reset(retaddr[index]);
retaddr[index] = -1;
} else {
// now we hit ret, return out
return false;
}
}
break;
case JBC_tableswitch:
{
S.pop();
bytecodes.alignSwitch();
int defaultval = bytecodes.getDefaultSwitchOffset();
int low = bytecodes.getLowSwitchValue();
int high = bytecodes.getHighSwitchValue();
// write down a list of targets
int npairs = high - low + 1;
int[] offsets = new int[npairs];
for (int i = 0; i < npairs; i++) {
offsets[i] = bytecodes.getTableSwitchOffset(i);
}
for (int i = 0; i < npairs; i++) {
int tgtpc = pc + offsets[i];
if (doDFS) {
// make a copy of ltypes, stypes to pass in
byte[] newltypes = new byte[ltypes.length];
byte[] newstypes = new byte[stypes.length];
System.arraycopy(ltypes, 0, newltypes, 0, ltypes.length);
System.arraycopy(stypes, 0, newstypes, 0, stypes.length);
found = scanBlocks(method, bytecodes, true, pcs, newltypes, newstypes, tgtpc, new TypeStack(S), null);
if (found) {
// copy back the ltypes and stypes
System.arraycopy(newltypes, 0, ltypes, 0, ltypes.length);
System.arraycopy(newstypes, 0, stypes, 0, stypes.length);
return true;
}
} else {
found = scanBlocks(method, bytecodes, false, -1, null, null, tgtpc, new TypeStack(S), stackHeights);
}
}
// default
{
int tgtpc = pc + defaultval;
if (doDFS) {
// make a copy of ltypes, stypes to pass in
byte[] newltypes = new byte[ltypes.length];
byte[] newstypes = new byte[stypes.length];
System.arraycopy(ltypes, 0, newltypes, 0, ltypes.length);
System.arraycopy(stypes, 0, newstypes, 0, stypes.length);
found = scanBlocks(method, bytecodes, true, pcs, newltypes, newstypes, tgtpc, new TypeStack(S), null);
if (found) {
// copy back the ltypes and stypes
System.arraycopy(newltypes, 0, ltypes, 0, ltypes.length);
System.arraycopy(newstypes, 0, stypes, 0, stypes.length);
}
} else {
found = scanBlocks(method, bytecodes, false, -1, null, null, tgtpc, new TypeStack(S), stackHeights);
}
return found;
}
}
case JBC_lookupswitch:
{
// pop the key
S.pop();
bytecodes.alignSwitch();
int defaultval = bytecodes.getDefaultSwitchOffset();
int npairs = bytecodes.getSwitchLength();
int[] matches = new int[npairs];
int[] offsets = new int[npairs];
for (int i = 0; i < npairs; i++) {
matches[i] = bytecodes.getLookupSwitchValue(i);
offsets[i] = bytecodes.getLookupSwitchOffset(i);
}
for (int i = 0; i < npairs; i++) {
// int match = matches[i];
int offset = offsets[i];
int tgtpc = pc + offset;
if (doDFS) {
// make a copy of ltypes, stypes to pass in
byte[] newltypes = new byte[ltypes.length];
byte[] newstypes = new byte[stypes.length];
System.arraycopy(ltypes, 0, newltypes, 0, ltypes.length);
System.arraycopy(stypes, 0, newstypes, 0, stypes.length);
found = scanBlocks(method, bytecodes, true, pcs, newltypes, newstypes, tgtpc, new TypeStack(S), null);
if (found) {
// copy back the ltypes and stypes
System.arraycopy(newltypes, 0, ltypes, 0, ltypes.length);
System.arraycopy(newstypes, 0, stypes, 0, stypes.length);
return true;
}
} else {
found = scanBlocks(method, bytecodes, false, -1, null, null, tgtpc, new TypeStack(S), stackHeights);
}
}
// default
{
int tgtpc = pc + defaultval;
if (doDFS) {
// make a copy of ltypes, stypes to pass in
byte[] newltypes = new byte[ltypes.length];
byte[] newstypes = new byte[stypes.length];
System.arraycopy(ltypes, 0, newltypes, 0, ltypes.length);
System.arraycopy(stypes, 0, newstypes, 0, stypes.length);
found = scanBlocks(method, bytecodes, true, pcs, newltypes, newstypes, tgtpc, new TypeStack(S), null);
if (found) {
// copy back the ltypes and stypes
System.arraycopy(newltypes, 0, ltypes, 0, ltypes.length);
System.arraycopy(newstypes, 0, stypes, 0, stypes.length);
}
} else {
found = scanBlocks(method, bytecodes, false, -1, null, null, tgtpc, new TypeStack(S), stackHeights);
}
}
}
return found;
case JBC_ireturn:
S.pop();
return false;
case JBC_lreturn:
S.pop(2);
return false;
case JBC_freturn:
S.pop();
return false;
case JBC_dreturn:
S.pop(2);
return false;
case JBC_areturn:
S.pop();
return false;
case JBC_return:
return false;
case JBC_getfield:
S.pop();
case JBC_getstatic:
{
FieldReference fieldRef = bytecodes.getFieldReference();
TypeReference ftype = fieldRef.getFieldContentsType();
byte tcode = ftype.getName().parseForTypeCode();
if ((tcode == LongTypeCode) || (tcode == DoubleTypeCode)) {
S.push(VoidTypeCode);
}
S.push(tcode);
}
break;
case JBC_putstatic:
{
FieldReference fieldRef = bytecodes.getFieldReference();
TypeReference ftype = fieldRef.getFieldContentsType();
byte tcode = ftype.getName().parseForTypeCode();
if ((tcode == LongTypeCode) || (tcode == DoubleTypeCode)) {
S.pop(2);
} else {
S.pop();
}
}
break;
case JBC_putfield:
{
FieldReference fieldRef = bytecodes.getFieldReference();
TypeReference ftype = fieldRef.getFieldContentsType();
byte tcode = ftype.getName().parseForTypeCode();
if ((tcode == LongTypeCode) || (tcode == DoubleTypeCode)) {
S.pop(2);
} else {
S.pop();
}
}
S.pop();
break;
case JBC_invokevirtual:
case JBC_invokespecial:
case JBC_invokestatic:
case JBC_invokeinterface:
{
MethodReference callee = bytecodes.getMethodReference();
int psize = callee.getParameterWords();
S.pop(psize);
if (bcode != JBC_invokestatic) {
// pop the object reference
S.pop();
}
TypeReference rtype = callee.getReturnType();
byte tcode = rtype.getName().parseForTypeCode();
if (tcode == VoidTypeCode) {
// nothing to do with void return type
} else {
if ((tcode == LongTypeCode) || (tcode == DoubleTypeCode)) {
S.push(VoidTypeCode);
}
S.push(tcode);
}
if (bcode == JBC_invokeinterface) {
bytecodes.alignInvokeInterface();
}
}
break;
case JBC_invokedynamic:
break;
case JBC_new:
// skip cpi of type
bytecodes.getTypeReference();
S.push(ClassTypeCode);
break;
case JBC_newarray:
S.pop();
S.push(ArrayTypeCode);
// skip cpi of element type
bytecodes.getArrayElementType();
break;
case JBC_anewarray:
S.pop();
S.push(ArrayTypeCode);
// skip cpi of reference type
bytecodes.getTypeReference();
break;
case JBC_arraylength:
S.pop();
S.push(IntTypeCode);
break;
case JBC_athrow:
S.clear();
S.push(ClassTypeCode);
return false;
case JBC_checkcast:
// skip cpi of reference type
bytecodes.getTypeReference();
break;
case JBC_instanceof:
S.pop();
S.push(IntTypeCode);
// skip cpi of reference type
bytecodes.getTypeReference();
break;
case JBC_monitorenter:
case JBC_monitorexit:
S.pop();
break;
case JBC_wide:
{
int widecode = bytecodes.getWideOpcode();
int index = bytecodes.getWideLocalNumber();
switch(widecode) {
case JBC_iload:
S.push(IntTypeCode);
break;
case JBC_lload:
S.push(LongTypeCode);
break;
case JBC_fload:
S.push(FloatTypeCode);
break;
case JBC_dload:
S.push(DoubleTypeCode);
break;
case JBC_aload:
S.push(ClassTypeCode);
break;
case JBC_istore:
S.pop();
if (doDFS)
ltypes[index] = IntTypeCode;
break;
case JBC_lstore:
S.pop();
if (doDFS)
ltypes[index] = LongTypeCode;
break;
case JBC_fstore:
S.pop();
if (doDFS)
ltypes[index] = FloatTypeCode;
break;
case JBC_dstore:
S.pop();
if (doDFS)
ltypes[index] = DoubleTypeCode;
break;
case JBC_astore:
{
byte tcode = S.pop();
if (doDFS)
ltypes[index] = tcode;
// for ret address.
if (tcode == ReturnAddressTypeCode) {
retaddr[index] = addr;
addr = -1;
}
}
break;
case JBC_iinc:
{
// skip increment
bytecodes.getWideIncrement();
if (doDFS)
ltypes[index] = IntTypeCode;
}
break;
case JBC_ret:
if (doDFS)
ltypes[index] = VoidTypeCode;
if (retaddr[index] != -1) {
bytecodes.reset(retaddr[index]);
retaddr[index] = -1;
} else {
// now we hit ret, return out
return false;
}
break;
default:
if (VM.VerifyAssertions)
VM._assert(VM.NOT_REACHED);
break;
}
break;
}
case JBC_multianewarray:
{
// skip type reference
bytecodes.getTypeReference();
int dims = bytecodes.getArrayDimension();
S.pop(dims);
S.push(ArrayTypeCode);
}
break;
case JBC_impdep1:
{
int pseudo_opcode = bytecodes.nextPseudoInstruction();
switch(pseudo_opcode) {
case PSEUDO_LoadIntConst:
// skip value
bytecodes.readIntConst();
S.push(IntTypeCode);
break;
case PSEUDO_LoadLongConst:
// skip value
bytecodes.readLongConst();
S.push(VoidTypeCode);
S.push(LongTypeCode);
break;
case PSEUDO_LoadWordConst:
if (VM.BuildFor32Addr) {
bytecodes.readIntConst();
} else {
// skip value
bytecodes.readLongConst();
}
S.push(WordTypeCode);
break;
case PSEUDO_LoadFloatConst:
// skip value
bytecodes.readIntConst();
S.push(FloatTypeCode);
break;
case PSEUDO_LoadDoubleConst:
// skip value
bytecodes.readLongConst();
S.push(VoidTypeCode);
S.push(DoubleTypeCode);
break;
case PSEUDO_LoadRetAddrConst:
// remember the address for ret.
// get address
addr = bytecodes.readIntConst();
S.push(ReturnAddressTypeCode);
break;
case PSEUDO_InvokeStatic:
{
// get METHIDX
int mid = bytecodes.readIntConst();
RVMMethod callee = InvokeStatic.targetMethod(mid);
int psize = callee.getParameterWords();
S.pop(psize);
TypeReference rtype = callee.getReturnType();
byte tcode = rtype.getName().parseForTypeCode();
if (tcode == VoidTypeCode) {
// nothing to do with void return type
} else {
if ((tcode == LongTypeCode) || (tcode == DoubleTypeCode)) {
S.push(VoidTypeCode);
}
S.push(tcode);
}
break;
}
/*
case PSEUDO_CheckCast:
bytecodes.readIntConst(); // skip type id
break;
*/
case PSEUDO_InvokeCompiledMethod:
// cmid
int cmid = bytecodes.readIntConst();
// skip bcindex
bytecodes.readIntConst();
RVMMethod callee = CompiledMethods.getCompiledMethod(cmid).getMethod();
int psize = callee.getParameterWords();
S.pop(psize);
if (!callee.isStatic()) {
// pop receiver
S.pop();
}
TypeReference rtype = callee.getReturnType();
byte tcode = rtype.getName().parseForTypeCode();
if (tcode == VoidTypeCode) {
// nothing to do with void return type
} else {
if ((tcode == LongTypeCode) || (tcode == DoubleTypeCode)) {
S.push(VoidTypeCode);
}
S.push(tcode);
}
break;
case PSEUDO_ParamInitEnd:
break;
default:
if (VM.VerifyAssertions) {
VM.sysWriteln(" Error, no such pseudo code : " + pseudo_opcode);
VM._assert(VM.NOT_REACHED);
}
return false;
}
break;
}
default:
VM.sysWriteln("Unknown bytecode : " + bcode);
return false;
}
}
/* did not found the PC. */
return false;
}
use of org.jikesrvm.classloader.RVMClass in project JikesRVM by JikesRVM.
the class MemoryManager method pickAllocator.
/**
* Returns the appropriate allocation scheme/area for the given type
* and given method requesting the allocation.
*
* @param type the type of the object to be allocated
* @param method the method requesting the allocation
* @return the identifier of the appropriate allocator
*/
@Interruptible
public static int pickAllocator(RVMType type, RVMMethod method) {
if (traceAllocator) {
VM.sysWrite("allocator for ");
VM.sysWrite(type.getDescriptor());
VM.sysWrite(": ");
}
if (method != null) {
// We should strive to be allocation-free here.
RVMClass cls = method.getDeclaringClass();
byte[] clsBA = cls.getDescriptor().toByteArray();
if (Selected.Constraints.get().withGCspy()) {
if (isPrefix("Lorg/mmtk/vm/gcspy/", clsBA) || isPrefix("[Lorg/mmtk/vm/gcspy/", clsBA)) {
if (traceAllocator) {
VM.sysWriteln("GCSPY");
}
return Plan.ALLOC_GCSPY;
}
}
if (isPrefix("Lorg/jikesrvm/mm/mmtk/ReferenceProcessor", clsBA)) {
if (traceAllocator) {
VM.sysWriteln("DEFAULT");
}
return Plan.ALLOC_DEFAULT;
}
if (isPrefix("Lorg/mmtk/", clsBA) || isPrefix("Lorg/jikesrvm/mm/", clsBA)) {
if (traceAllocator) {
VM.sysWriteln("NONMOVING");
}
return Plan.ALLOC_NON_MOVING;
}
if (method.isNonMovingAllocation()) {
return Plan.ALLOC_NON_MOVING;
}
}
if (traceAllocator) {
VM.sysWriteln(type.getMMAllocator());
}
return type.getMMAllocator();
}
use of org.jikesrvm.classloader.RVMClass in project JikesRVM by JikesRVM.
the class JNIFunctions method AllocObject.
/**
* AllocObject: allocate the space for an object without running any constructor
* the header is filled and the fields are initialized to null
* @param env A JREF index for the JNI environment object
* @param classJREF a JREF index for the class object
* @return a JREF index for the uninitialized object
* @throws InstantiationException if the class is abstract or is an interface
* @throws OutOfMemoryError if no more memory to allocate
*/
private static int AllocObject(JNIEnvironment env, int classJREF) throws InstantiationException, OutOfMemoryError {
if (traceJNI)
VM.sysWriteln("JNI called: AllocObject");
RuntimeEntrypoints.checkJNICountDownToGC();
try {
Class<?> javaCls = (Class<?>) env.getJNIRef(classJREF);
RVMType type = java.lang.JikesRVMSupport.getTypeForClass(javaCls);
if (type.isArrayType() || type.isPrimitiveType() || type.isUnboxedType()) {
env.recordException(new InstantiationException());
return 0;
}
RVMClass cls = type.asClass();
if (cls.isAbstract() || cls.isInterface()) {
env.recordException(new InstantiationException());
return 0;
}
Object newObj = RuntimeEntrypoints.resolvedNewScalar(cls);
return env.pushJNIRef(newObj);
} catch (Throwable unexpected) {
if (traceJNI)
unexpected.printStackTrace(System.err);
env.recordException(unexpected);
return 0;
}
}
use of org.jikesrvm.classloader.RVMClass in project JikesRVM by JikesRVM.
the class JNIFunctions method GetFieldID.
/**
* GetFieldID: return a field id, which can be cached in native code and reused
* @param env A JREF index for the JNI environment object
* @param classJREF a JREF index for the RVMClass object
* @param fieldNameAddress a raw address to a null-terminated string in C for the field name
* @param descriptorAddress a raw address to a null-terminated string in C for the descriptor
* @return the fieldID of an instance field given the class, field name
* and type. Return 0 if the field is not found
* @throws NoSuchFieldError if the specified field cannot be found
* @throws ExceptionInInitializerError if the class initializer fails
* @throws OutOfMemoryError if the system runs out of memory
*/
private static int GetFieldID(JNIEnvironment env, int classJREF, Address fieldNameAddress, Address descriptorAddress) {
if (traceJNI)
VM.sysWriteln("JNI called: GetFieldID");
RuntimeEntrypoints.checkJNICountDownToGC();
try {
if (traceJNI)
VM.sysWriteln("called GetFieldID with classJREF = ", classJREF);
Class<?> cls = (Class<?>) env.getJNIRef(classJREF);
if (VM.VerifyAssertions)
VM._assert(cls != null);
String fieldString = JNIGenericHelpers.createStringFromC(fieldNameAddress);
Atom fieldName = Atom.findOrCreateAsciiAtom(fieldString);
String descriptorString = JNIGenericHelpers.createStringFromC(descriptorAddress);
Atom descriptor = Atom.findOrCreateAsciiAtom(descriptorString);
// list of all instance fields including superclasses.
// Iterate in reverse order since if there are multiple instance
// fields of the same name & descriptor we want to find the most derived one.
RVMField[] fields = java.lang.JikesRVMSupport.getTypeForClass(cls).getInstanceFields();
for (int i = fields.length - 1; i >= 0; i--) {
RVMField f = fields[i];
if (f.getName() == fieldName && f.getDescriptor() == descriptor) {
return f.getId();
}
}
// create exception and return 0 if not found
env.recordException(new NoSuchFieldError(fieldString + ", " + descriptorString + " of " + cls));
return 0;
} catch (Throwable unexpected) {
if (traceJNI)
unexpected.printStackTrace(System.err);
env.recordException(unexpected);
return 0;
}
}
Aggregations