use of org.jikesrvm.classloader.TypeReference in project JikesRVM by JikesRVM.
the class BuildReferenceMaps method buildReferenceMaps.
/**
* After the analysis of the blocks of a method, examine the byte codes again, to
* determine the reference maps for the gc points. Record the maps with
* referenceMaps.
*
* @param method the method whose bytecodes are to be examined again
* @param stackHeights height of the expression stack at each bytecode
* @param localTypes the types that the locals can take
* @param referenceMaps the reference map. NB: the map's constructor is still running
* while this method is called!
* @param buildBB the buildBB instance that contains the results from the
* previous analysis
*
* @see BaselineCompiler#localTypes
* @see TemplateCompilerFramework#stackHeights
*/
public void buildReferenceMaps(NormalMethod method, int[] stackHeights, byte[] localTypes, ReferenceMaps referenceMaps, BuildBB buildBB) {
// ****************************************************************//
// These were calculated by BuildBB.determineTheBasicBlocks //
// ****************************************************************//
int gcPointCount = buildBB.gcPointCount;
short[] byteToBlockMap = buildBB.byteToBlockMap;
BasicBlock[] basicBlocks = buildBB.basicBlocks;
int jsrCount = buildBB.numJsrs;
// The starting map for each block, a block is not
byte[][] bbMaps;
// processed until it has a starting map.
// For each block, track where its current stack top is.
int[] blockStkTop;
// Block number of block currently being processed
int currBBNum;
// The current map, used during processing thru a block
byte[] currBBMap;
// Stack top for the current map
int currBBStkTop;
// Level when stack is empty - value depends on number of locals
final int currBBStkEmpty;
// Number of parameters to the method being processed
int paramCount;
// Variables for processing JSR instructions, RET instructions and JSR subroutines
PendingRETInfo[] bbPendingRETs = null;
PendingRETInfo currPendingRET;
JSRSubroutineInfo[] JSRSubs = null;
// Blocks that need to be processed are put on the workStk
short[] workStk;
// Track whether a block has already been seen once. Any recording of maps done
// within such a block will be processed as a "rerecording" instead of a new map.
//
boolean[] blockSeen;
// blocks that represent "catch" blocks need special processing. Catch blocks
// also referred to as handlers
//
// exception table class for method being processed
ExceptionHandlerMap exceptions;
// array of try start indicesinto byte code table
int[] tryStartPC;
// array of try end indices into byte code table
int[] tryEndPC;
// array of try handlers start indices into bytecode
int[] tryHandlerPC;
// length of try handlers array
int tryHandlerLength;
// array of reachable handlers from a given try block
int[] reachableHandlerBBNums;
// Number of reachable handlers
int reachableHandlersCount;
// Handler blocks are processed after the normal flow. As
boolean[] handlerProcessed;
// they may be nested, they need to be handled
// individually. This array is used to track which
// have been processed.
boolean handlersAllDone;
// Other local variables
//
// byte codes for the method
BytecodeStream bcodes;
// For processing branches, need block number of target
short brBBNum;
final boolean debug = false;
// Note that the mapping done here is "double mapping" of parameters.
// Double mapping is when the parameters for a method are included in the map of
// the method as well as in the map of the caller of the method. The original
// intent was that with double mapping call sites that are tricks
// (e.g. Magic.callFunctionReturnVoid ) would at least be correctly mapped on one
// of the two sides. However with more recent changes to the runtime stack frame
// layout, the parameters specified on the caller side occupy different
// locations than the parameters on the callee side for the baseline compiler.
// Thus both need to be described.
//
// Initialization
//
// Determine what stack empty looks like
paramCount = method.getParameterWords();
if (!method.isStatic())
paramCount++;
currBBStkEmpty = TemplateCompilerFramework.stackHeightForEmptyBasicBlock(method);
if (debug) {
VM.sysWriteln("getLocalWords() : " + method.getLocalWords());
VM.sysWriteln("getOperandWords() : " + method.getOperandWords());
VM.sysWriteln("getParameterWords() : " + method.getParameterWords());
}
// Get information from the method being processed
bcodes = method.getBytecodes();
// Set up the array of maps per block; block 0 is not used
int numBB = buildBB.bbf.getNumberofBlocks();
bbMaps = new byte[numBB + 1][];
blockStkTop = new int[bbMaps.length];
blockSeen = new boolean[bbMaps.length];
// Try Handler processing initialization
exceptions = method.getExceptionHandlerMap();
if (exceptions != null) {
tryStartPC = exceptions.getStartPC();
tryEndPC = exceptions.getEndPC();
tryHandlerPC = exceptions.getHandlerPC();
tryHandlerLength = tryHandlerPC.length;
reachableHandlerBBNums = new int[tryStartPC.length];
handlerProcessed = new boolean[tryStartPC.length];
if (jsrCount > 0) {
JSRSubs = new JSRSubroutineInfo[jsrCount];
JSRSubNext = 0;
bbPendingRETs = new PendingRETInfo[bbMaps.length];
}
handlersAllDone = (tryHandlerLength == 0);
// write poison values to help distinguish different errors
for (int ii = 0; ii < reachableHandlerBBNums.length; ii++) {
reachableHandlerBBNums[ii] = -1;
}
} else {
tryHandlerLength = 0;
handlersAllDone = true;
tryStartPC = null;
tryEndPC = null;
tryHandlerPC = null;
reachableHandlerBBNums = null;
handlerProcessed = null;
}
reachableHandlersCount = 0;
// Start a new set of maps with the reference Map class.
// 3rd argument is parameter count included with the maps
referenceMaps.startNewMaps(gcPointCount, jsrCount, paramCount);
// Set up the Work stack
workStk = new short[10 + tryHandlerLength];
// Start by putting the first block on the work stack
workStkTop = 0;
workStk[workStkTop] = byteToBlockMap[0];
currBBMap = new byte[method.getOperandWords() + currBBStkEmpty + 1];
//
// Need to include the parameters of this method in the map
//
TypeReference[] parameterTypes = method.getParameterTypes();
int paramStart;
if (!method.isStatic()) {
// implicit "this" object
currBBMap[0] = REFERENCE;
localTypes[0] = ADDRESS_TYPE;
paramStart = 1;
} else {
paramStart = 0;
}
for (int i = 0; i < parameterTypes.length; i++, paramStart++) {
TypeReference parameterType = parameterTypes[i];
if (parameterType.isReferenceType()) {
localTypes[paramStart] = ADDRESS_TYPE;
currBBMap[paramStart] = REFERENCE;
} else {
currBBMap[paramStart] = NON_REFERENCE;
if (parameterType.getStackWords() == 2) {
if (parameterType.isLongType()) {
localTypes[paramStart] = LONG_TYPE;
} else {
localTypes[paramStart] = DOUBLE_TYPE;
}
paramStart++;
} else if (parameterType.isFloatType()) {
localTypes[paramStart] = FLOAT_TYPE;
} else if (parameterType.isIntLikeType()) {
localTypes[paramStart] = INT_TYPE;
} else {
localTypes[paramStart] = ADDRESS_TYPE;
}
}
}
// The map for the start of the first block, is stack empty, with none
// of the locals set yet
//
currBBStkTop = currBBStkEmpty;
bbMaps[byteToBlockMap[0]] = currBBMap;
blockStkTop[byteToBlockMap[0]] = currBBStkTop;
// For all methods, record a map at the start of the method for the corresponding
// conditional call to "yield".
referenceMaps.recordStkMap(0, currBBMap, currBBStkTop, false);
currBBMap = new byte[currBBMap.length];
// ----------------------------------------------------------
while (workStkTop > -1) {
// Get the next item off the work stack
currBBNum = workStk[workStkTop];
workStkTop--;
boolean inJSRSub = false;
if (bbMaps[currBBNum] != null) {
currBBStkTop = blockStkTop[currBBNum];
for (int k = 0; k <= currBBStkTop; k++) {
currBBMap[k] = bbMaps[currBBNum][k];
}
if (jsrCount > 0 && basicBlocks[currBBNum].isInJSR()) {
inJSRSub = true;
}
} else {
VM.sysWrite("BuildReferenceMaps, error: found a block on work stack with");
VM.sysWrite(" no starting map. The block number is ");
VM.sysWrite(basicBlocks[currBBNum].getBlockNumber());
VM.sysWriteln();
VM.sysFail("BuildReferenceMaps work stack failure");
}
int start = basicBlocks[currBBNum].getStart();
int end = basicBlocks[currBBNum].getEnd();
if (jsrCount > 0 && inJSRSub) {
currPendingRET = bbPendingRETs[currBBNum];
if (basicBlocks[currBBNum].isTryStart()) {
for (int k = 0; k < tryHandlerLength; k++) {
if (tryStartPC[k] == start) {
int handlerBBNum = byteToBlockMap[tryHandlerPC[k]];
bbPendingRETs[handlerBBNum] = new PendingRETInfo(currPendingRET);
}
}
}
if (currPendingRET == null) {
int[] preds = basicBlocks[currBBNum].getPredecessors();
for (int i = 0; i < preds.length; i++) {
int predBB = preds[i];
if (bbPendingRETs[predBB] != null) {
currPendingRET = bbPendingRETs[predBB];
break;
}
}
}
if (VM.VerifyAssertions) {
if (currPendingRET == null) {
String msg = "No pending return found in block " + currBBNum;
VM._assert(VM.NOT_REACHED, msg);
}
}
} else {
currPendingRET = null;
}
boolean inTryBlock;
if (basicBlocks[currBBNum].isTryBlock()) {
inTryBlock = true;
reachableHandlersCount = 0;
for (int i = 0; i < tryHandlerLength; i++) {
if (start <= tryEndPC[i] && end >= tryStartPC[i]) {
reachableHandlerBBNums[reachableHandlersCount] = byteToBlockMap[tryHandlerPC[i]];
reachableHandlersCount++;
int handlerBBNum = byteToBlockMap[tryHandlerPC[i]];
if (bbMaps[handlerBBNum] == null) {
bbMaps[handlerBBNum] = new byte[currBBMap.length];
for (int k = 0; k <= currBBStkEmpty; k++) {
bbMaps[handlerBBNum][k] = currBBMap[k];
}
bbMaps[handlerBBNum][currBBStkEmpty + 1] = REFERENCE;
blockStkTop[handlerBBNum] = currBBStkEmpty + 1;
} else {
if (inJSRSub && basicBlocks[handlerBBNum].isInJSR()) {
// Ensure SET_TO_NONREFERENCE is carried across
for (int k = 0; k <= currBBStkEmpty; k++) {
if (currBBMap[k] == SET_TO_NONREFERENCE && bbMaps[handlerBBNum][k] != SET_TO_NONREFERENCE) {
handlerProcessed[i] = false;
bbMaps[handlerBBNum][k] = SET_TO_NONREFERENCE;
}
}
} else if (inJSRSub) {
// realise JSR and SET_TO_NONREFERENCE becomes NON_REFERENCE
for (int k = 0; k <= currBBStkEmpty; k++) {
if (currBBMap[k] == SET_TO_NONREFERENCE && bbMaps[handlerBBNum][k] != NON_REFERENCE) {
handlerProcessed[i] = false;
bbMaps[handlerBBNum][k] = NON_REFERENCE;
}
}
} else {
// No JSRs involved, simply ensure NON_REFERENCE is carried over
for (int k = 0; k <= currBBStkEmpty; k++) {
if (currBBMap[k] == NON_REFERENCE && bbMaps[handlerBBNum][k] != NON_REFERENCE) {
handlerProcessed[i] = false;
bbMaps[handlerBBNum][k] = NON_REFERENCE;
}
}
}
}
}
}
} else {
inTryBlock = false;
}
boolean processNextBlock = true;
bcodes.reset(start);
while (bcodes.index() <= end) {
int biStart = bcodes.index();
int opcode = bcodes.nextInstruction();
if (stackHeights != null) {
if (VM.VerifyAssertions) {
if (currBBStkTop < currBBStkEmpty) {
String msg = "Stack height for current basic block is " + currBBStkTop + " which is less than the stack height for " + "an empty block (" + currBBStkEmpty + ").";
VM._assert(VM.NOT_REACHED, msg);
}
}
stackHeights[biStart] = currBBStkTop;
}
if (debug) {
VM.sysWriteln("bytecode: " + JBC_name(opcode) + " (opcode : " + opcode + ")");
VM.sysWrite("current map: ");
for (int j = 0; j <= currBBStkTop; j++) {
VM.sysWrite(currBBMap[j]);
}
VM.sysWriteln();
}
switch(opcode) {
case JBC_nop:
{
break;
}
case JBC_aconst_null:
{
currBBStkTop++;
currBBMap[currBBStkTop] = REFERENCE;
break;
}
case JBC_aload_0:
{
int localNumber = 0;
currBBStkTop++;
currBBMap[currBBStkTop] = inJSRSub ? REFERENCE : currBBMap[localNumber];
break;
}
case JBC_aload_1:
{
int localNumber = 1;
currBBStkTop++;
currBBMap[currBBStkTop] = inJSRSub ? REFERENCE : currBBMap[localNumber];
break;
}
case JBC_aload_2:
{
int localNumber = 2;
currBBStkTop++;
currBBMap[currBBStkTop] = inJSRSub ? REFERENCE : currBBMap[localNumber];
break;
}
case JBC_aload_3:
{
int localNumber = 3;
currBBStkTop++;
currBBMap[currBBStkTop] = inJSRSub ? REFERENCE : currBBMap[localNumber];
break;
}
case JBC_aload:
{
int localNumber = bcodes.getLocalNumber();
currBBStkTop++;
currBBMap[currBBStkTop] = inJSRSub ? REFERENCE : currBBMap[localNumber];
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:
case JBC_fconst_0:
case JBC_fconst_1:
case JBC_fconst_2:
case JBC_iload_0:
case JBC_iload_1:
case JBC_iload_2:
case JBC_iload_3:
case JBC_fload_0:
case JBC_fload_1:
case JBC_fload_2:
case JBC_fload_3:
case JBC_bipush:
case JBC_iload:
case JBC_fload:
case JBC_sipush:
case JBC_i2l:
case JBC_i2d:
case JBC_f2l:
case JBC_f2d:
{
currBBStkTop++;
currBBMap[currBBStkTop] = NON_REFERENCE;
// contains mix of 1,2,3 byte bytecodes
bcodes.skipInstruction();
break;
}
case JBC_lconst_0:
case JBC_lconst_1:
case JBC_dconst_0:
case JBC_dconst_1:
case JBC_lload_0:
case JBC_lload_1:
case JBC_lload_2:
case JBC_lload_3:
case JBC_dload_0:
case JBC_dload_1:
case JBC_dload_2:
case JBC_dload_3:
case JBC_ldc2_w:
case JBC_lload:
case JBC_dload:
{
currBBStkTop++;
currBBMap[currBBStkTop] = NON_REFERENCE;
currBBStkTop++;
currBBMap[currBBStkTop] = NON_REFERENCE;
// mix of 1, 2, and 3 byte bytecodes
bcodes.skipInstruction();
break;
}
case JBC_ldc:
{
currBBStkTop++;
int cpi = bcodes.getConstantIndex();
int type = bcodes.getConstantType(cpi);
if (type == CP_STRING || type == CP_CLASS) {
currBBMap[currBBStkTop] = REFERENCE;
} else {
currBBMap[currBBStkTop] = NON_REFERENCE;
}
break;
}
case JBC_ldc_w:
{
currBBStkTop++;
int cpi = bcodes.getWideConstantIndex();
int type = bcodes.getConstantType(cpi);
if (type == CP_STRING || type == CP_CLASS) {
currBBMap[currBBStkTop] = REFERENCE;
} else {
currBBMap[currBBStkTop] = NON_REFERENCE;
}
break;
}
case JBC_istore:
{
int index = bcodes.getLocalNumber();
if (!inJSRSub) {
currBBMap[index] = NON_REFERENCE;
} else {
currBBMap[index] = SET_TO_NONREFERENCE;
}
if (inTryBlock) {
setHandlersMapsNonRef(index, PrimitiveSize.ONEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
}
currBBStkTop--;
localTypes[index] |= INT_TYPE;
break;
}
case JBC_fstore:
{
int index = bcodes.getLocalNumber();
if (!inJSRSub) {
currBBMap[index] = NON_REFERENCE;
} else {
currBBMap[index] = SET_TO_NONREFERENCE;
}
if (inTryBlock) {
setHandlersMapsNonRef(index, PrimitiveSize.ONEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
}
currBBStkTop--;
localTypes[index] |= FLOAT_TYPE;
break;
}
case JBC_lstore:
{
int index = bcodes.getLocalNumber();
if (!inJSRSub) {
currBBMap[index] = NON_REFERENCE;
currBBMap[index + 1] = NON_REFERENCE;
} else {
currBBMap[index] = SET_TO_NONREFERENCE;
currBBMap[index + 1] = SET_TO_NONREFERENCE;
}
if (inTryBlock) {
setHandlersMapsNonRef(index, PrimitiveSize.DOUBLEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
}
currBBStkTop = currBBStkTop - 2;
localTypes[index] |= LONG_TYPE;
break;
}
case JBC_dstore:
{
int index = bcodes.getLocalNumber();
if (!inJSRSub) {
currBBMap[index] = NON_REFERENCE;
currBBMap[index + 1] = NON_REFERENCE;
} else {
currBBMap[index] = SET_TO_NONREFERENCE;
currBBMap[index + 1] = SET_TO_NONREFERENCE;
}
if (inTryBlock) {
setHandlersMapsNonRef(index, PrimitiveSize.DOUBLEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
}
currBBStkTop = currBBStkTop - 2;
localTypes[index] |= DOUBLE_TYPE;
break;
}
case JBC_astore:
{
int index = bcodes.getLocalNumber();
// may be a reference or a return address
currBBMap[index] = currBBMap[currBBStkTop];
if (inJSRSub) {
if (currBBMap[index] == RETURN_ADDRESS) {
currPendingRET.updateReturnAddressLocation(index);
}
if (inTryBlock) {
if (currBBMap[index] == REFERENCE) {
setHandlersMapsRef(index, reachableHandlerBBNums, reachableHandlersCount, bbMaps);
} else {
setHandlersMapsReturnAddress(index, reachableHandlerBBNums, reachableHandlersCount, bbMaps);
}
}
}
currBBStkTop--;
localTypes[index] |= ADDRESS_TYPE;
break;
}
case JBC_istore_0:
{
if (!inJSRSub) {
currBBMap[0] = NON_REFERENCE;
} else {
currBBMap[0] = SET_TO_NONREFERENCE;
}
if (inTryBlock) {
setHandlersMapsNonRef(0, PrimitiveSize.ONEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
}
currBBStkTop--;
localTypes[0] |= INT_TYPE;
break;
}
case JBC_fstore_0:
{
if (!inJSRSub) {
currBBMap[0] = NON_REFERENCE;
} else {
currBBMap[0] = SET_TO_NONREFERENCE;
}
if (inTryBlock) {
setHandlersMapsNonRef(0, PrimitiveSize.ONEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
}
currBBStkTop--;
localTypes[0] |= FLOAT_TYPE;
break;
}
case JBC_istore_1:
{
if (!inJSRSub) {
currBBMap[1] = NON_REFERENCE;
} else {
currBBMap[1] = SET_TO_NONREFERENCE;
}
if (inTryBlock) {
setHandlersMapsNonRef(1, PrimitiveSize.ONEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
}
currBBStkTop--;
localTypes[1] |= INT_TYPE;
break;
}
case JBC_fstore_1:
{
if (!inJSRSub) {
currBBMap[1] = NON_REFERENCE;
} else {
currBBMap[1] = SET_TO_NONREFERENCE;
}
if (inTryBlock) {
setHandlersMapsNonRef(1, PrimitiveSize.ONEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
}
currBBStkTop--;
localTypes[1] |= FLOAT_TYPE;
break;
}
case JBC_istore_2:
{
if (!inJSRSub) {
currBBMap[2] = NON_REFERENCE;
} else {
currBBMap[2] = SET_TO_NONREFERENCE;
}
if (inTryBlock) {
setHandlersMapsNonRef(2, PrimitiveSize.ONEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
}
currBBStkTop--;
localTypes[2] |= INT_TYPE;
break;
}
case JBC_fstore_2:
{
if (!inJSRSub) {
currBBMap[2] = NON_REFERENCE;
} else {
currBBMap[2] = SET_TO_NONREFERENCE;
}
if (inTryBlock) {
setHandlersMapsNonRef(2, PrimitiveSize.ONEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
}
currBBStkTop--;
localTypes[2] |= FLOAT_TYPE;
break;
}
case JBC_istore_3:
{
if (!inJSRSub) {
currBBMap[3] = NON_REFERENCE;
} else {
currBBMap[3] = SET_TO_NONREFERENCE;
}
if (inTryBlock) {
setHandlersMapsNonRef(3, PrimitiveSize.ONEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
}
currBBStkTop--;
localTypes[3] |= INT_TYPE;
break;
}
case JBC_fstore_3:
{
if (!inJSRSub) {
currBBMap[3] = NON_REFERENCE;
} else {
currBBMap[3] = SET_TO_NONREFERENCE;
}
if (inTryBlock) {
setHandlersMapsNonRef(3, PrimitiveSize.ONEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
}
currBBStkTop--;
localTypes[3] |= FLOAT_TYPE;
break;
}
case JBC_lstore_0:
{
if (inJSRSub) {
currBBMap[0] = NON_REFERENCE;
currBBMap[1] = NON_REFERENCE;
} else {
currBBMap[0] = SET_TO_NONREFERENCE;
currBBMap[1] = SET_TO_NONREFERENCE;
}
if (inTryBlock) {
setHandlersMapsNonRef(0, PrimitiveSize.DOUBLEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
}
currBBStkTop = currBBStkTop - 2;
localTypes[0] |= LONG_TYPE;
break;
}
case JBC_dstore_0:
{
if (inJSRSub) {
currBBMap[0] = NON_REFERENCE;
currBBMap[1] = NON_REFERENCE;
} else {
currBBMap[0] = SET_TO_NONREFERENCE;
currBBMap[1] = SET_TO_NONREFERENCE;
}
if (inTryBlock) {
setHandlersMapsNonRef(0, PrimitiveSize.DOUBLEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
}
currBBStkTop = currBBStkTop - 2;
localTypes[0] |= DOUBLE_TYPE;
break;
}
case JBC_lstore_1:
{
if (!inJSRSub) {
currBBMap[1] = NON_REFERENCE;
currBBMap[2] = NON_REFERENCE;
} else {
currBBMap[1] = SET_TO_NONREFERENCE;
currBBMap[2] = SET_TO_NONREFERENCE;
}
if (inTryBlock) {
setHandlersMapsNonRef(1, PrimitiveSize.DOUBLEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
}
currBBStkTop = currBBStkTop - 2;
localTypes[1] |= LONG_TYPE;
break;
}
case JBC_dstore_1:
{
if (!inJSRSub) {
currBBMap[1] = NON_REFERENCE;
currBBMap[2] = NON_REFERENCE;
} else {
currBBMap[1] = SET_TO_NONREFERENCE;
currBBMap[2] = SET_TO_NONREFERENCE;
}
if (inTryBlock) {
setHandlersMapsNonRef(1, PrimitiveSize.DOUBLEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
}
currBBStkTop = currBBStkTop - 2;
localTypes[1] |= DOUBLE_TYPE;
break;
}
case JBC_lstore_2:
{
if (!inJSRSub) {
currBBMap[2] = NON_REFERENCE;
currBBMap[3] = NON_REFERENCE;
} else {
currBBMap[2] = SET_TO_NONREFERENCE;
currBBMap[3] = SET_TO_NONREFERENCE;
}
if (inTryBlock) {
setHandlersMapsNonRef(2, PrimitiveSize.DOUBLEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
}
currBBStkTop = currBBStkTop - 2;
localTypes[2] |= LONG_TYPE;
break;
}
case JBC_dstore_2:
{
if (!inJSRSub) {
currBBMap[2] = NON_REFERENCE;
currBBMap[3] = NON_REFERENCE;
} else {
currBBMap[2] = SET_TO_NONREFERENCE;
currBBMap[3] = SET_TO_NONREFERENCE;
}
if (inTryBlock) {
setHandlersMapsNonRef(2, PrimitiveSize.DOUBLEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
}
currBBStkTop = currBBStkTop - 2;
localTypes[2] |= DOUBLE_TYPE;
break;
}
case JBC_lstore_3:
{
if (!inJSRSub) {
currBBMap[3] = NON_REFERENCE;
currBBMap[4] = NON_REFERENCE;
} else {
currBBMap[3] = SET_TO_NONREFERENCE;
currBBMap[4] = SET_TO_NONREFERENCE;
}
if (inTryBlock) {
setHandlersMapsNonRef(3, PrimitiveSize.DOUBLEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
}
currBBStkTop = currBBStkTop - 2;
localTypes[3] |= LONG_TYPE;
break;
}
case JBC_dstore_3:
{
if (!inJSRSub) {
currBBMap[3] = NON_REFERENCE;
currBBMap[4] = NON_REFERENCE;
} else {
currBBMap[3] = SET_TO_NONREFERENCE;
currBBMap[4] = SET_TO_NONREFERENCE;
}
if (inTryBlock) {
setHandlersMapsNonRef(3, PrimitiveSize.DOUBLEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
}
currBBStkTop = currBBStkTop - 2;
localTypes[3] |= DOUBLE_TYPE;
break;
}
case JBC_astore_0:
{
currBBMap[0] = currBBMap[currBBStkTop];
if (inJSRSub) {
if (currBBMap[0] == RETURN_ADDRESS) {
currPendingRET.updateReturnAddressLocation(0);
}
if (inTryBlock) {
if (currBBMap[0] == REFERENCE) {
setHandlersMapsRef(0, reachableHandlerBBNums, reachableHandlersCount, bbMaps);
} else {
setHandlersMapsReturnAddress(0, reachableHandlerBBNums, reachableHandlersCount, bbMaps);
}
}
}
currBBStkTop--;
localTypes[0] |= ADDRESS_TYPE;
break;
}
case JBC_astore_1:
{
currBBMap[1] = currBBMap[currBBStkTop];
if (inJSRSub) {
if (currBBMap[1] == RETURN_ADDRESS) {
currPendingRET.updateReturnAddressLocation(1);
}
if (inTryBlock) {
if (currBBMap[1] == REFERENCE) {
setHandlersMapsRef(1, reachableHandlerBBNums, reachableHandlersCount, bbMaps);
} else {
setHandlersMapsReturnAddress(1, reachableHandlerBBNums, reachableHandlersCount, bbMaps);
}
}
}
currBBStkTop--;
localTypes[1] |= ADDRESS_TYPE;
break;
}
case JBC_astore_2:
{
currBBMap[2] = currBBMap[currBBStkTop];
if (inJSRSub) {
if (currBBMap[2] == RETURN_ADDRESS) {
currPendingRET.updateReturnAddressLocation(2);
}
if (inTryBlock) {
if (currBBMap[2] == REFERENCE) {
setHandlersMapsRef(2, reachableHandlerBBNums, reachableHandlersCount, bbMaps);
} else {
setHandlersMapsReturnAddress(2, reachableHandlerBBNums, reachableHandlersCount, bbMaps);
}
}
}
currBBStkTop--;
localTypes[2] |= ADDRESS_TYPE;
break;
}
case JBC_astore_3:
{
currBBMap[3] = currBBMap[currBBStkTop];
if (inJSRSub) {
if (currBBMap[3] == RETURN_ADDRESS) {
currPendingRET.updateReturnAddressLocation(3);
}
if (inTryBlock) {
if (currBBMap[3] == REFERENCE) {
setHandlersMapsRef(3, reachableHandlerBBNums, reachableHandlersCount, bbMaps);
} else {
setHandlersMapsReturnAddress(3, reachableHandlerBBNums, reachableHandlersCount, bbMaps);
}
}
}
currBBStkTop--;
localTypes[3] |= ADDRESS_TYPE;
break;
}
case JBC_dup:
{
currBBMap[currBBStkTop + 1] = currBBMap[currBBStkTop];
currBBStkTop++;
break;
}
case JBC_dup2:
{
currBBMap[currBBStkTop + 1] = currBBMap[currBBStkTop - 1];
currBBMap[currBBStkTop + 2] = currBBMap[currBBStkTop];
currBBStkTop = currBBStkTop + 2;
break;
}
case JBC_dup_x1:
{
currBBMap[currBBStkTop + 1] = currBBMap[currBBStkTop];
currBBMap[currBBStkTop] = currBBMap[currBBStkTop - 1];
currBBMap[currBBStkTop - 1] = currBBMap[currBBStkTop + 1];
currBBStkTop++;
break;
}
case JBC_dup2_x1:
{
currBBMap[currBBStkTop + 2] = currBBMap[currBBStkTop];
currBBMap[currBBStkTop + 1] = currBBMap[currBBStkTop - 1];
currBBMap[currBBStkTop] = currBBMap[currBBStkTop - 2];
currBBMap[currBBStkTop - 1] = currBBMap[currBBStkTop + 2];
currBBMap[currBBStkTop - 2] = currBBMap[currBBStkTop + 1];
currBBStkTop = currBBStkTop + 2;
break;
}
case JBC_dup_x2:
{
currBBMap[currBBStkTop + 1] = currBBMap[currBBStkTop];
currBBMap[currBBStkTop] = currBBMap[currBBStkTop - 1];
currBBMap[currBBStkTop - 1] = currBBMap[currBBStkTop - 2];
currBBMap[currBBStkTop - 2] = currBBMap[currBBStkTop + 1];
currBBStkTop++;
break;
}
case JBC_dup2_x2:
{
currBBMap[currBBStkTop + 2] = currBBMap[currBBStkTop];
currBBMap[currBBStkTop + 1] = currBBMap[currBBStkTop - 1];
currBBMap[currBBStkTop] = currBBMap[currBBStkTop - 2];
currBBMap[currBBStkTop - 1] = currBBMap[currBBStkTop - 3];
currBBMap[currBBStkTop - 2] = currBBMap[currBBStkTop + 2];
currBBMap[currBBStkTop - 3] = currBBMap[currBBStkTop + 1];
currBBStkTop = currBBStkTop + 2;
break;
}
case JBC_swap:
{
byte temp;
temp = currBBMap[currBBStkTop];
currBBMap[currBBStkTop] = currBBMap[currBBStkTop - 1];
currBBMap[currBBStkTop - 1] = temp;
break;
}
case JBC_pop:
case JBC_iadd:
case JBC_fadd:
case JBC_isub:
case JBC_fsub:
case JBC_imul:
case JBC_fmul:
case JBC_fdiv:
case JBC_frem:
case JBC_ishl:
case JBC_ishr:
case JBC_iushr:
// long shifts that int shift value
case JBC_lshl:
case JBC_lshr:
case JBC_lushr:
case JBC_iand:
case JBC_ior:
case JBC_ixor:
case JBC_l2i:
case JBC_l2f:
case JBC_d2i:
case JBC_d2f:
case JBC_fcmpl:
case JBC_fcmpg:
{
currBBStkTop--;
bcodes.skipInstruction();
break;
}
case JBC_irem:
case JBC_idiv:
{
// record map after 2 integers popped off stack
currBBStkTop = currBBStkTop - 2;
if (!inJSRSub) {
referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
} else {
referenceMaps.recordJSRSubroutineMap(biStart, currBBMap, currBBStkTop, currPendingRET.returnAddressLocation, blockSeen[currBBNum]);
}
currBBStkTop++;
break;
}
case JBC_ladd:
case JBC_dadd:
case JBC_lsub:
case JBC_dsub:
case JBC_lmul:
case JBC_dmul:
case JBC_ddiv:
case JBC_drem:
case JBC_land:
case JBC_lor:
case JBC_lxor:
case JBC_pop2:
{
currBBStkTop = currBBStkTop - 2;
break;
}
case JBC_lrem:
case JBC_ldiv:
{
// record map after 2 longs popped off stack
currBBStkTop = currBBStkTop - 4;
if (!inJSRSub) {
referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
} else {
referenceMaps.recordJSRSubroutineMap(biStart, currBBMap, currBBStkTop, currPendingRET.returnAddressLocation, blockSeen[currBBNum]);
}
currBBStkTop = currBBStkTop + 2;
break;
}
case JBC_ineg:
case JBC_lneg:
case JBC_fneg:
case JBC_dneg:
case JBC_iinc:
case JBC_i2f:
case JBC_l2d:
case JBC_f2i:
case JBC_d2l:
case JBC_int2byte:
case JBC_int2char:
case JBC_int2short:
{
bcodes.skipInstruction();
break;
}
case JBC_lcmp:
case JBC_dcmpl:
case JBC_dcmpg:
{
currBBStkTop = currBBStkTop - 3;
break;
}
case JBC_ifeq:
case JBC_ifne:
case JBC_iflt:
case JBC_ifge:
case JBC_ifgt:
case JBC_ifle:
{
int offset = bcodes.getBranchOffset();
if (offset <= 0) {
if (!inJSRSub) {
referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
} else {
// in a jsr subroutine
referenceMaps.recordJSRSubroutineMap(biStart, currBBMap, currBBStkTop, currPendingRET.returnAddressLocation, blockSeen[currBBNum]);
}
}
// process the basic block logic
currBBStkTop--;
if (offset <= 0) {
short fallThruBBNum = byteToBlockMap[biStart + 3];
workStk = processBranchBB(fallThruBBNum, currBBStkTop, currBBMap, currBBStkEmpty, inJSRSub, bbMaps, blockStkTop, currPendingRET, bbPendingRETs, workStk);
processNextBlock = false;
}
brBBNum = byteToBlockMap[biStart + offset];
workStk = processBranchBB(brBBNum, currBBStkTop, currBBMap, currBBStkEmpty, inJSRSub, bbMaps, blockStkTop, currPendingRET, bbPendingRETs, workStk);
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:
{
int offset = bcodes.getBranchOffset();
if (offset <= 0) {
if (!inJSRSub) {
referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
} else {
// in a jsr subroutine
referenceMaps.recordJSRSubroutineMap(biStart, currBBMap, currBBStkTop, currPendingRET.returnAddressLocation, blockSeen[currBBNum]);
}
}
// process the basic blocks
currBBStkTop = currBBStkTop - 2;
if (offset <= 0) {
short fallThruBBNum = byteToBlockMap[biStart + 3];
workStk = processBranchBB(fallThruBBNum, currBBStkTop, currBBMap, currBBStkEmpty, inJSRSub, bbMaps, blockStkTop, currPendingRET, bbPendingRETs, workStk);
processNextBlock = false;
}
brBBNum = byteToBlockMap[biStart + offset];
workStk = processBranchBB(brBBNum, currBBStkTop, currBBMap, currBBStkEmpty, inJSRSub, bbMaps, blockStkTop, currPendingRET, bbPendingRETs, workStk);
break;
}
case JBC_ifnull:
case JBC_ifnonnull:
{
int offset = bcodes.getBranchOffset();
if (offset <= 0) {
if (!inJSRSub) {
referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
} else {
// in a jsr subroutine
referenceMaps.recordJSRSubroutineMap(biStart, currBBMap, currBBStkTop, currPendingRET.returnAddressLocation, blockSeen[currBBNum]);
}
}
// process the basic block logic
currBBStkTop--;
if (offset <= 0) {
short fallThruBBNum = byteToBlockMap[biStart + 3];
workStk = processBranchBB(fallThruBBNum, currBBStkTop, currBBMap, currBBStkEmpty, inJSRSub, bbMaps, blockStkTop, currPendingRET, bbPendingRETs, workStk);
processNextBlock = false;
}
brBBNum = byteToBlockMap[biStart + offset];
workStk = processBranchBB(brBBNum, currBBStkTop, currBBMap, currBBStkEmpty, inJSRSub, bbMaps, blockStkTop, currPendingRET, bbPendingRETs, workStk);
break;
}
case JBC_goto:
{
int offset = bcodes.getBranchOffset();
if (offset <= 0) {
// Register the reference map
if (!inJSRSub) {
referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
} else {
// in a jsr subroutine
referenceMaps.recordJSRSubroutineMap(biStart, currBBMap, currBBStkTop, currPendingRET.returnAddressLocation, blockSeen[currBBNum]);
}
}
// process the basic block logic
brBBNum = byteToBlockMap[biStart + offset];
workStk = processBranchBB(brBBNum, currBBStkTop, currBBMap, currBBStkEmpty, inJSRSub, bbMaps, blockStkTop, currPendingRET, bbPendingRETs, workStk);
processNextBlock = false;
break;
}
case JBC_goto_w:
{
int offset = bcodes.getWideBranchOffset();
if (offset <= 0) {
if (!inJSRSub) {
referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
} else {
// in a jsr subroutine
referenceMaps.recordJSRSubroutineMap(biStart, currBBMap, currBBStkTop, currPendingRET.returnAddressLocation, blockSeen[currBBNum]);
}
}
// process basic block structures
brBBNum = byteToBlockMap[biStart + offset];
workStk = processBranchBB(brBBNum, currBBStkTop, currBBMap, currBBStkEmpty, inJSRSub, bbMaps, blockStkTop, currPendingRET, bbPendingRETs, workStk);
processNextBlock = false;
break;
}
case JBC_tableswitch:
{
currBBStkTop--;
bcodes.alignSwitch();
// get default offset and process branch to default branch point
int def = bcodes.getDefaultSwitchOffset();
workStk = processBranchBB(byteToBlockMap[biStart + def], currBBStkTop, currBBMap, currBBStkEmpty, inJSRSub, bbMaps, blockStkTop, currPendingRET, bbPendingRETs, workStk);
int low = bcodes.getLowSwitchValue();
int high = bcodes.getHighSwitchValue();
int n = high - low + 1;
// generate labels for offsets
for (int k = 0; k < n; k++) {
int offset = bcodes.getTableSwitchOffset(k);
workStk = processBranchBB(byteToBlockMap[biStart + offset], currBBStkTop, currBBMap, currBBStkEmpty, inJSRSub, bbMaps, blockStkTop, currPendingRET, bbPendingRETs, workStk);
}
bcodes.skipTableSwitchOffsets(n);
processNextBlock = false;
break;
}
case JBC_lookupswitch:
{
currBBStkTop--;
bcodes.alignSwitch();
// get default offset and process branch to default branch point
int def = bcodes.getDefaultSwitchOffset();
workStk = processBranchBB(byteToBlockMap[biStart + def], currBBStkTop, currBBMap, currBBStkEmpty, inJSRSub, bbMaps, blockStkTop, currPendingRET, bbPendingRETs, workStk);
int npairs = bcodes.getSwitchLength();
// generate label for each offset in table
for (int k = 0; k < npairs; k++) {
int offset = bcodes.getLookupSwitchOffset(k);
workStk = processBranchBB(byteToBlockMap[biStart + offset], currBBStkTop, currBBMap, currBBStkEmpty, inJSRSub, bbMaps, blockStkTop, currPendingRET, bbPendingRETs, workStk);
}
bcodes.skipLookupSwitchPairs(npairs);
processNextBlock = false;
break;
}
case JBC_jsr:
{
processNextBlock = false;
int offset = bcodes.getBranchOffset();
if (!inJSRSub) {
referenceMaps.recordStkMap(biStart, currBBMap, currBBStkEmpty, blockSeen[currBBNum]);
} else {
referenceMaps.recordJSRSubroutineMap(biStart, currBBMap, currBBStkEmpty, currPendingRET.returnAddressLocation, blockSeen[currBBNum]);
}
currBBStkTop++;
currBBMap[currBBStkTop] = RETURN_ADDRESS;
workStk = processJSR(byteToBlockMap[biStart], biStart + offset, byteToBlockMap[biStart + offset], byteToBlockMap[biStart + 3], bbMaps, currBBStkTop, currBBMap, currBBStkEmpty, blockStkTop, bbPendingRETs, currPendingRET, JSRSubs, workStk);
break;
}
case JBC_jsr_w:
{
processNextBlock = false;
int offset = bcodes.getWideBranchOffset();
if (!inJSRSub) {
referenceMaps.recordStkMap(biStart, currBBMap, currBBStkEmpty, blockSeen[currBBNum]);
} else {
referenceMaps.recordJSRSubroutineMap(biStart, currBBMap, currBBStkEmpty, currPendingRET.returnAddressLocation, blockSeen[currBBNum]);
}
currBBStkTop++;
currBBMap[currBBStkTop] = RETURN_ADDRESS;
workStk = processJSR(byteToBlockMap[biStart], biStart + offset, byteToBlockMap[biStart + offset], byteToBlockMap[biStart + 5], bbMaps, currBBStkTop, currBBMap, currBBStkEmpty, blockStkTop, bbPendingRETs, currPendingRET, JSRSubs, workStk);
break;
}
case JBC_ret:
{
int index = bcodes.getLocalNumber();
// Can not be used again as a return addr.
//
currBBMap[index] = SET_TO_NONREFERENCE;
processNextBlock = false;
int subStart = currPendingRET.JSRSubStartByteIndex;
int k;
for (k = 0; k < JSRSubNext; k++) {
if (JSRSubs[k].subroutineByteCodeStart == subStart) {
JSRSubs[k].newEndMaps(currBBMap, currBBStkTop);
break;
}
}
boolean JSRisinJSRSub = bbPendingRETs[currPendingRET.JSRBBNum] != null;
workStk = computeJSRNextMaps(currPendingRET.JSRNextBBNum, currBBMap.length, k, JSRisinJSRSub, bbMaps, blockStkTop, JSRSubs, currBBStkEmpty, workStk);
if (JSRisinJSRSub && bbPendingRETs[currPendingRET.JSRNextBBNum] == null) {
bbPendingRETs[currPendingRET.JSRNextBBNum] = new PendingRETInfo(bbPendingRETs[currPendingRET.JSRBBNum]);
}
break;
}
case JBC_invokevirtual:
case JBC_invokespecial:
{
MethodReference target = bcodes.getMethodReference();
currBBStkTop = processInvoke(target, biStart, currBBStkTop, currBBMap, false, inJSRSub, referenceMaps, currPendingRET, blockSeen[currBBNum], currBBStkEmpty);
break;
}
case JBC_invokeinterface:
{
MethodReference target = bcodes.getMethodReference();
bcodes.alignInvokeInterface();
currBBStkTop = processInvoke(target, biStart, currBBStkTop, currBBMap, false, inJSRSub, referenceMaps, currPendingRET, blockSeen[currBBNum], currBBStkEmpty);
break;
}
case JBC_invokestatic:
{
MethodReference target = bcodes.getMethodReference();
currBBStkTop = processInvoke(target, biStart, currBBStkTop, currBBMap, true, inJSRSub, referenceMaps, currPendingRET, blockSeen[currBBNum], currBBStkEmpty);
break;
}
case JBC_ireturn:
case JBC_lreturn:
case JBC_freturn:
case JBC_dreturn:
case JBC_areturn:
case JBC_return:
{
if (VM.UseEpilogueYieldPoints || method.isSynchronized()) {
referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
}
processNextBlock = false;
break;
}
case JBC_getstatic:
{
// Register the reference map (could cause dynamic linking)
if (!inJSRSub) {
referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
} else {
referenceMaps.recordJSRSubroutineMap(biStart, currBBMap, currBBStkTop, currPendingRET.returnAddressLocation, blockSeen[currBBNum]);
}
TypeReference fieldType = bcodes.getFieldReference().getFieldContentsType();
currBBMap[++currBBStkTop] = fieldType.isPrimitiveType() ? NON_REFERENCE : REFERENCE;
if (fieldType.getStackWords() == 2) {
currBBMap[++currBBStkTop] = NON_REFERENCE;
}
break;
}
case JBC_putstatic:
{
// Register the reference map (could cause dynamic linking)
if (!inJSRSub) {
referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
} else {
referenceMaps.recordJSRSubroutineMap(biStart, currBBMap, currBBStkTop, currPendingRET.returnAddressLocation, blockSeen[currBBNum]);
}
TypeReference fieldType = bcodes.getFieldReference().getFieldContentsType();
currBBStkTop--;
if (fieldType.getStackWords() == 2) {
currBBStkTop--;
}
break;
}
case JBC_getfield:
{
TypeReference fieldType = bcodes.getFieldReference().getFieldContentsType();
// Register the reference map (could cause dynamic linking..if so there will be a NPE, but the linking happens first.)
if (!inJSRSub) {
referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
} else {
referenceMaps.recordJSRSubroutineMap(biStart, currBBMap, currBBStkTop, currPendingRET.returnAddressLocation, blockSeen[currBBNum]);
}
// pop object pointer
currBBStkTop--;
currBBMap[++currBBStkTop] = fieldType.isPrimitiveType() ? NON_REFERENCE : REFERENCE;
if (fieldType.getStackWords() == 2) {
currBBMap[++currBBStkTop] = NON_REFERENCE;
}
break;
}
case JBC_putfield:
{
TypeReference fieldType = bcodes.getFieldReference().getFieldContentsType();
// note: putfield could result in a call to the classloader
if (!inJSRSub) {
referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
} else {
referenceMaps.recordJSRSubroutineMap(biStart, currBBMap, currBBStkTop, currPendingRET.returnAddressLocation, blockSeen[currBBNum]);
}
// remove objectref and one value
currBBStkTop -= 2;
if (fieldType.getStackWords() == 2) {
currBBStkTop--;
}
break;
}
case JBC_checkcast:
{
if (!inJSRSub) {
referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
} else {
referenceMaps.recordJSRSubroutineMap(biStart, currBBMap, currBBStkTop, currPendingRET.returnAddressLocation, blockSeen[currBBNum]);
}
bcodes.skipInstruction();
break;
}
case JBC_instanceof:
{
if (!inJSRSub) {
referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
} else {
referenceMaps.recordJSRSubroutineMap(biStart, currBBMap, currBBStkTop, currPendingRET.returnAddressLocation, blockSeen[currBBNum]);
}
currBBMap[currBBStkTop] = NON_REFERENCE;
bcodes.skipInstruction();
break;
}
case JBC_new:
{
if (!inJSRSub) {
referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
} else {
referenceMaps.recordJSRSubroutineMap(biStart, currBBMap, currBBStkTop, currPendingRET.returnAddressLocation, blockSeen[currBBNum]);
}
currBBStkTop++;
currBBMap[currBBStkTop] = REFERENCE;
bcodes.skipInstruction();
break;
}
// altered yet.
case JBC_iaload:
case JBC_faload:
case JBC_baload:
case JBC_caload:
case JBC_saload:
{
if (!inJSRSub) {
referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
} else {
referenceMaps.recordJSRSubroutineMap(biStart, currBBMap, currBBStkTop, currPendingRET.returnAddressLocation, blockSeen[currBBNum]);
}
currBBStkTop--;
currBBMap[currBBStkTop] = NON_REFERENCE;
break;
}
case JBC_laload:
case JBC_daload:
{
if (!inJSRSub) {
referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
} else {
referenceMaps.recordJSRSubroutineMap(biStart, currBBMap, currBBStkTop, currPendingRET.returnAddressLocation, blockSeen[currBBNum]);
}
currBBMap[currBBStkTop - 1] = NON_REFERENCE;
break;
}
case JBC_aaload:
{
if (!inJSRSub) {
referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
} else {
referenceMaps.recordJSRSubroutineMap(biStart, currBBMap, currBBStkTop, currPendingRET.returnAddressLocation, blockSeen[currBBNum]);
}
currBBStkTop--;
break;
}
// Stack has not been modified at this point.
case JBC_iastore:
case JBC_fastore:
case JBC_aastore:
case JBC_bastore:
case JBC_castore:
case JBC_sastore:
{
if (!inJSRSub) {
referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
} else {
referenceMaps.recordJSRSubroutineMap(biStart, currBBMap, currBBStkTop, currPendingRET.returnAddressLocation, blockSeen[currBBNum]);
}
currBBStkTop = currBBStkTop - 3;
break;
}
case JBC_lastore:
case JBC_dastore:
{
if (!inJSRSub) {
referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
} else {
referenceMaps.recordJSRSubroutineMap(biStart, currBBMap, currBBStkTop, currPendingRET.returnAddressLocation, blockSeen[currBBNum]);
}
currBBStkTop = currBBStkTop - 4;
break;
}
case JBC_newarray:
case JBC_anewarray:
{
if (!inJSRSub) {
referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
} else {
referenceMaps.recordJSRSubroutineMap(biStart, currBBMap, currBBStkTop, currPendingRET.returnAddressLocation, blockSeen[currBBNum]);
}
currBBMap[currBBStkTop] = REFERENCE;
bcodes.skipInstruction();
break;
}
case JBC_multianewarray:
{
bcodes.getTypeReference();
int dim = bcodes.getArrayDimension();
if (!inJSRSub) {
referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
} else {
referenceMaps.recordJSRSubroutineMap(biStart, currBBMap, currBBStkTop, currPendingRET.returnAddressLocation, blockSeen[currBBNum]);
}
currBBStkTop = currBBStkTop - dim + 1;
currBBMap[currBBStkTop] = REFERENCE;
break;
}
case JBC_arraylength:
{
currBBMap[currBBStkTop] = NON_REFERENCE;
break;
}
case JBC_athrow:
{
if (!inJSRSub) {
referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
} else {
referenceMaps.recordJSRSubroutineMap(biStart, currBBMap, currBBStkTop, currPendingRET.returnAddressLocation, blockSeen[currBBNum]);
}
currBBStkTop = currBBStkEmpty + 1;
currBBMap[currBBStkTop] = REFERENCE;
processNextBlock = false;
break;
}
case JBC_monitorenter:
case JBC_monitorexit:
{
currBBStkTop--;
if (!inJSRSub) {
referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
} else {
referenceMaps.recordJSRSubroutineMap(biStart, currBBMap, currBBStkTop, currPendingRET.returnAddressLocation, blockSeen[currBBNum]);
}
break;
}
case JBC_wide:
{
int widecode = bcodes.getWideOpcode();
int index = bcodes.getWideLocalNumber();
switch(widecode) {
case JBC_iload:
case JBC_fload:
{
currBBStkTop++;
currBBMap[currBBStkTop] = NON_REFERENCE;
break;
}
case JBC_lload:
case JBC_dload:
{
currBBStkTop++;
currBBMap[currBBStkTop] = NON_REFERENCE;
currBBStkTop++;
currBBMap[currBBStkTop] = NON_REFERENCE;
break;
}
case JBC_aload:
{
currBBStkTop++;
currBBMap[currBBStkTop] = currBBMap[index];
break;
}
case JBC_istore:
{
if (!inJSRSub) {
currBBMap[index] = NON_REFERENCE;
} else {
currBBMap[index] = SET_TO_NONREFERENCE;
}
currBBStkTop--;
localTypes[index] |= INT_TYPE;
break;
}
case JBC_fstore:
{
if (!inJSRSub) {
currBBMap[index] = NON_REFERENCE;
} else {
currBBMap[index] = SET_TO_NONREFERENCE;
}
currBBStkTop--;
localTypes[index] |= FLOAT_TYPE;
break;
}
case JBC_lstore:
{
if (!inJSRSub) {
currBBMap[index] = NON_REFERENCE;
currBBMap[index + 1] = NON_REFERENCE;
} else {
currBBMap[index] = SET_TO_NONREFERENCE;
currBBMap[index + 1] = SET_TO_NONREFERENCE;
}
currBBStkTop = currBBStkTop - 2;
localTypes[index] |= LONG_TYPE;
break;
}
case JBC_dstore:
{
if (!inJSRSub) {
currBBMap[index] = NON_REFERENCE;
currBBMap[index + 1] = NON_REFERENCE;
} else {
currBBMap[index] = SET_TO_NONREFERENCE;
currBBMap[index + 1] = SET_TO_NONREFERENCE;
}
currBBStkTop = currBBStkTop - 2;
localTypes[index] |= DOUBLE_TYPE;
break;
}
case JBC_astore:
{
currBBMap[index] = currBBMap[currBBStkTop];
currBBStkTop--;
localTypes[index] |= ADDRESS_TYPE;
break;
}
case JBC_iinc:
{
bcodes.getWideIncrement();
break;
}
case JBC_ret:
{
// Can not be used again as a return addr.
//
currBBMap[index] = SET_TO_NONREFERENCE;
processNextBlock = false;
int subStart = currPendingRET.JSRSubStartByteIndex;
int k;
for (k = 0; k < JSRSubNext; k++) {
if (JSRSubs[k].subroutineByteCodeStart == subStart) {
JSRSubs[k].newEndMaps(currBBMap, currBBStkTop);
break;
}
}
boolean JSRisinJSRSub = bbPendingRETs[currPendingRET.JSRBBNum] != null;
workStk = computeJSRNextMaps(currPendingRET.JSRNextBBNum, currBBMap.length, k, JSRisinJSRSub, bbMaps, blockStkTop, JSRSubs, currBBStkEmpty, workStk);
if (JSRisinJSRSub && bbPendingRETs[currPendingRET.JSRNextBBNum] == null) {
bbPendingRETs[currPendingRET.JSRNextBBNum] = new PendingRETInfo(bbPendingRETs[currPendingRET.JSRBBNum]);
}
break;
}
default:
// switch on widecode
if (VM.VerifyAssertions)
VM._assert(VM.NOT_REACHED);
}
break;
}
default:
{
VM.sysFail("Unknown opcode:" + opcode);
}
}
// end switch (opcode)
}
// for start to end
blockSeen[currBBNum] = true;
if (processNextBlock) {
short fallThruBBNum = byteToBlockMap[bcodes.index()];
workStk = processBranchBB(fallThruBBNum, currBBStkTop, currBBMap, currBBStkEmpty, inJSRSub, bbMaps, blockStkTop, currPendingRET, bbPendingRETs, workStk);
}
//
if ((workStkTop == -1) && !handlersAllDone) {
int i;
for (i = 0; i < tryHandlerLength; i++) {
// the try block must be in one of the other handlers
if (!handlerProcessed[i] && bbMaps[byteToBlockMap[tryHandlerPC[i]]] != null)
break;
}
if (i == tryHandlerLength) {
handlersAllDone = true;
} else {
int considerIndex = i;
while (i != tryHandlerLength) {
int tryStart = tryStartPC[considerIndex];
int tryEnd = tryEndPC[considerIndex];
for (i = 0; i < tryHandlerLength; i++) {
// I'm not entirely convinced this is right, but don't know what else we can do. --dave
if (i == considerIndex)
continue;
// we are considering working on.
if (!handlerProcessed[i] && tryStart <= tryHandlerPC[i] && tryHandlerPC[i] < tryEnd && bbMaps[byteToBlockMap[tryHandlerPC[i]]] != null) {
break;
}
}
if (i != tryHandlerLength) {
considerIndex = i;
}
}
short blockNum = byteToBlockMap[tryHandlerPC[considerIndex]];
handlerProcessed[considerIndex] = true;
workStk = addToWorkStk(blockNum, workStk);
}
}
}
// while workStk not empty
// Indicate that any temporaries can be freed
referenceMaps.recordingComplete();
}
use of org.jikesrvm.classloader.TypeReference in project JikesRVM by JikesRVM.
the class VM method runClassInitializer.
/**
* Run {@code <clinit>} method of specified class, if that class appears
* in bootimage and actually has a clinit method (we are flexible to
* allow one list of classes to work with different bootimages and
* different version of classpath (eg 0.05 vs. cvs head).
* <p>
* This method is called only while the VM boots.
*
* @param className class whose initializer needs to be run
*/
@Interruptible
static void runClassInitializer(String className) {
if (verboseBoot >= 2) {
sysWrite("running class initializer for ");
sysWriteln(className);
}
Atom classDescriptor = Atom.findOrCreateAsciiAtom(className.replace('.', '/')).descriptorFromClassName();
TypeReference tRef = TypeReference.findOrCreate(BootstrapClassLoader.getBootstrapClassLoader(), classDescriptor);
RVMClass cls = (RVMClass) tRef.peekType();
if (null == cls) {
sysWrite("Failed to run class initializer for ");
sysWrite(className);
sysWriteln(" as the class does not exist.");
} else if (!cls.isInBootImage()) {
sysWrite("Failed to run class initializer for ");
sysWrite(className);
sysWriteln(" as the class is not in the boot image.");
} else {
RVMMethod clinit = cls.getClassInitializerMethod();
if (clinit != null) {
clinit.compile();
if (verboseBoot >= 10)
VM.sysWriteln("invoking method " + clinit);
try {
Magic.invokeClassInitializer(clinit.getCurrentEntryCodeArray());
} catch (Error e) {
throw e;
} catch (Throwable t) {
ExceptionInInitializerError eieio = new ExceptionInInitializerError(t);
throw eieio;
}
// <clinit> is no longer needed: reclaim space by removing references to it
clinit.invalidateCompiledMethod(clinit.getCurrentCompiledMethod());
} else {
if (verboseBoot >= 10)
VM.sysWriteln("has no clinit method ");
}
cls.setAllFinalStaticJTOCEntries();
}
}
use of org.jikesrvm.classloader.TypeReference in project JikesRVM by JikesRVM.
the class Class method getDeclaredClasses.
public Class<?>[] getDeclaredClasses() throws SecurityException {
checkMemberAccess(Member.DECLARED);
if (!type.isClassType())
return new Class[0];
// Get array of declared classes from RVMClass object
RVMClass cls = type.asClass();
TypeReference[] declaredClasses = cls.getDeclaredClasses();
// The array can be null if the class has no declared inner class members
if (declaredClasses == null)
return new Class[0];
// Count the number of actual declared inner and static classes.
// (The array may contain null elements, which we want to skip.)
int count = 0;
int length = declaredClasses.length;
for (int i = 0; i < length; ++i) {
if (declaredClasses[i] != null) {
++count;
}
}
// Now build actual result array.
Class<?>[] result = new Class[count];
count = 0;
for (int i = 0; i < length; ++i) {
if (declaredClasses[i] != null) {
result[count++] = declaredClasses[i].resolve().getClassForType();
}
}
return result;
}
use of org.jikesrvm.classloader.TypeReference in project JikesRVM by JikesRVM.
the class BulkCompile method compileAllMethods.
/**
* Compile all methods nominated in the compiler advice,
* which should have been provided in a .ca advice file.<p>
*
* This method will be called at boot time (via notifyStartup())
* if ENABLE_PRECOMPILE is true. For replay compilation, this
* method needs to be called explicitly from within the application
* or benchmark harness. Typical usage in a benchmarking context
* would be to call this method at the end of the first iteration
* of the benchmark so that all/most classes were loaded, and
* compilation could occur prior to the second iteration.
*/
public static void compileAllMethods() {
if (!(Controller.options.ENABLE_BULK_COMPILE || Controller.options.ENABLE_PRECOMPILE)) {
/* should not be here */
VM.sysFail("Attempt to perform bulk compilation without setting either -X:aos:enable_bulk_compile=true or -X:aos:enable_precompile=true");
}
EdgeCounts.loadCountsFromFileIfAvailable(VM.EdgeCounterFile);
CompilerAdvice.readCompilerAdvice();
if (Controller.options.BULK_COMPILATION_VERBOSITY >= 1)
VM.sysWriteln(Controller.options.ENABLE_PRECOMPILE ? "Start precompile" : "Start bulk compile");
for (CompilerAdviceAttribute value : CompilerAdviceAttribute.values()) {
if (value.getOptLevel() == -1) {
if (Controller.options.BULK_COMPILATION_VERBOSITY > 1) {
VM.sysWriteln("Skipping base method: ", value.toString());
} else if (Controller.options.BULK_COMPILATION_VERBOSITY == 1) {
VM.sysWrite(".");
}
continue;
}
ClassLoader cl = RVMClassLoader.findWorkableClassloader(value.getClassName());
if (cl == null)
continue;
TypeReference tRef = TypeReference.findOrCreate(cl, value.getClassName());
RVMClass cls = (RVMClass) tRef.peekType();
if (cls != null) {
// Ensure the class is properly loaded
if (!cls.isInstantiated()) {
if (!cls.isResolved()) {
if (Controller.options.BULK_COMPILATION_VERBOSITY > 1) {
VM.sysWriteln("Resolving class: ", cls.toString());
} else if (Controller.options.BULK_COMPILATION_VERBOSITY == 1) {
VM.sysWrite("R");
}
cls.resolve();
}
if (Controller.options.BULK_COMPILATION_VERBOSITY > 1) {
VM.sysWriteln("Instantiating class: ", cls.toString());
} else if (Controller.options.BULK_COMPILATION_VERBOSITY == 1) {
VM.sysWrite("I");
}
cls.instantiate();
}
// Find the method
RVMMethod method = cls.findDeclaredMethod(value.getMethodName(), value.getMethodSig());
// If found, compile it
if ((method != null) && !method.hasNoOptCompileAnnotation() && (method instanceof org.jikesrvm.classloader.NormalMethod)) {
// if user's requirement is higher than advice
if (value.getOptLevel() > Controller.options.DERIVED_MAX_OPT_LEVEL) {
if (Controller.options.BULK_COMPILATION_VERBOSITY > 1) {
VM.sysWrite("Replay advice overriden by default opt levels. Wanted ");
VM.sysWrite(value.getOptLevel());
VM.sysWrite(", but Controller.options.DERIVED_MAX_OPT_LEVEL: ");
VM.sysWrite(Controller.options.DERIVED_MAX_OPT_LEVEL);
VM.sysWrite(" ");
VM.sysWriteln(value.toString());
} else if (Controller.options.BULK_COMPILATION_VERBOSITY == 1) {
VM.sysWrite(value.getOptLevel(), "!");
}
method.compile();
} else {
CompilationPlan compPlan;
if (Controller.options.counters()) {
// for invocation counter, we only use one optimization level
compPlan = InvocationCounts.createCompilationPlan((NormalMethod) method);
AOSLogging.logger.recompilationStarted(compPlan);
if (Controller.options.BULK_COMPILATION_VERBOSITY > 1) {
VM.sysWrite("Bulk compiling for counters ");
VM.sysWriteln(value.toString());
}
RuntimeCompiler.recompileWithOpt(compPlan);
AOSLogging.logger.recompilationCompleted(compPlan);
} else if (Controller.options.sampling()) {
// Create our set of standard optimization plans.
compPlan = Controller.recompilationStrategy.createCompilationPlan((NormalMethod) method, value.getOptLevel(), null);
if (Controller.options.BULK_COMPILATION_VERBOSITY > 1) {
VM.sysWrite("Bulk compiling for sampling ");
VM.sysWriteln(value.toString());
}
if (Controller.options.BULK_COMPILATION_VERBOSITY == 1) {
VM.sysWrite(value.getOptLevel());
}
AOSLogging.logger.recompilationStarted(compPlan);
RuntimeCompiler.recompileWithOpt(compPlan);
AOSLogging.logger.recompilationCompleted(compPlan);
} else {
if (Controller.options.BULK_COMPILATION_VERBOSITY > 1) {
VM.sysWrite("Compiler advice file overridden ");
VM.sysWriteln(value.toString());
}
method.compile();
}
}
} else {
if (Controller.options.BULK_COMPILATION_VERBOSITY > 1) {
VM.sysWrite("Replay failed for ");
VM.sysWrite(value.toString());
VM.sysWrite(" ");
VM.sysWriteln(cl.toString());
} else if (Controller.options.BULK_COMPILATION_VERBOSITY == 1) {
VM.sysWrite("*");
}
}
}
}
AOSLogging.logger.compileAllMethodsCompleted();
if (Controller.options.BULK_COMPILATION_VERBOSITY >= 1)
VM.sysWriteln();
if (Controller.options.BULK_COMPILATION_VERBOSITY >= 1)
VM.sysWriteln("Recompilation complete");
}
use of org.jikesrvm.classloader.TypeReference in project JikesRVM by JikesRVM.
the class BootImageWriter method writeAddressMap.
/**
* Write method address map for use with dbx debugger.
*
* @param fileName name of file to write the map to
*/
private static void writeAddressMap(String mapFileName) throws IOException {
if (verbosity.isAtLeast(SUMMARY))
say("writing ", mapFileName);
// Restore previously unnecessary Statics data structures
Statics.bootImageReportGeneration(staticsJunk);
FileOutputStream fos = new FileOutputStream(mapFileName);
BufferedOutputStream bos = new BufferedOutputStream(fos, 128);
PrintStream out = new PrintStream(bos, false);
out.println("#! /bin/bash");
out.println("# This is a method address map, for use with the ``dbx'' debugger.");
out.println("# To sort by \"code\" address, type \"bash <name-of-this-file>\".");
out.println("# Bootimage data: " + Integer.toHexString(BOOT_IMAGE_DATA_START.toInt()) + "..." + Integer.toHexString(BOOT_IMAGE_DATA_START.toInt() + bootImage.getDataSize()));
out.println("# Bootimage code: " + Integer.toHexString(BOOT_IMAGE_CODE_START.toInt()) + "..." + Integer.toHexString(BOOT_IMAGE_CODE_START.toInt() + bootImage.getCodeSize()));
out.println("# Bootimage refs: " + Integer.toHexString(BOOT_IMAGE_RMAP_START.toInt()) + "..." + Integer.toHexString(BOOT_IMAGE_RMAP_START.toInt() + bootImage.getRMapSize()));
out.println();
out.println("(/bin/grep 'code 0x' | /bin/sort -k 4.3,4) << EOF-EOF-EOF");
out.println();
out.println("JTOC Map");
out.println("--------");
out.println("slot offset category contents details");
out.println("---- ------ -------- -------- -------");
String pad = " ";
// Numeric JTOC fields
for (int jtocSlot = Statics.getLowestInUseSlot(); jtocSlot < Statics.middleOfTable; jtocSlot++) {
Offset jtocOff = Statics.slotAsOffset(jtocSlot);
String category;
String contents;
String details;
RVMField field = getRvmStaticField(jtocOff);
RVMField field2 = getRvmStaticField(jtocOff.plus(4));
boolean couldBeLongLiteral = Statics.isLongSizeLiteral(jtocSlot);
boolean couldBeIntLiteral = Statics.isIntSizeLiteral(jtocSlot);
if (couldBeLongLiteral && ((field == null) || (field2 == null))) {
if ((field == null) && (field2 == null)) {
category = "literal ";
long lval = Statics.getSlotContentsAsLong(jtocOff);
contents = Services.intAsHexString((int) (lval >> 32)) + Services.intAsHexString((int) (lval & 0xffffffffL)).substring(2);
details = lval + "L";
} else if ((field == null) && (field2 != null)) {
category = "literal/field";
long lval = Statics.getSlotContentsAsLong(jtocOff);
contents = Services.intAsHexString((int) (lval >> 32)) + Services.intAsHexString((int) (lval & 0xffffffffL)).substring(2);
details = lval + "L / " + field2.toString();
} else if ((field != null) && (field2 == null)) {
category = "literal/field";
long lval = Statics.getSlotContentsAsLong(jtocOff);
contents = Services.intAsHexString((int) (lval >> 32)) + Services.intAsHexString((int) (lval & 0xffffffffL)).substring(2);
details = lval + "L / " + field.toString();
} else {
throw new Error("Unreachable");
}
jtocSlot++;
} else if (couldBeIntLiteral) {
if (field != null) {
category = "literal/field";
int ival = Statics.getSlotContentsAsInt(jtocOff);
contents = Services.intAsHexString(ival) + pad;
details = Integer.toString(ival) + " / " + field.toString();
} else {
category = "literal ";
int ival = Statics.getSlotContentsAsInt(jtocOff);
contents = Services.intAsHexString(ival) + pad;
details = Integer.toString(ival);
}
} else {
if (field != null) {
category = "field ";
details = field.toString();
TypeReference type = field.getType();
if (type.isIntLikeType()) {
int ival = Statics.getSlotContentsAsInt(jtocOff);
contents = Services.intAsHexString(ival) + pad;
} else if (type.isLongType()) {
long lval = Statics.getSlotContentsAsLong(jtocOff);
contents = Services.intAsHexString((int) (lval >> 32)) + Services.intAsHexString((int) (lval & 0xffffffffL)).substring(2);
jtocSlot++;
} else if (type.isFloatType()) {
int ival = Statics.getSlotContentsAsInt(jtocOff);
contents = Float.toString(Float.intBitsToFloat(ival)) + pad;
} else if (type.isDoubleType()) {
long lval = Statics.getSlotContentsAsLong(jtocOff);
contents = Double.toString(Double.longBitsToDouble(lval)) + pad;
jtocSlot++;
} else if (type.isWordLikeType()) {
if (VM.BuildFor32Addr) {
int ival = Statics.getSlotContentsAsInt(jtocOff);
contents = Services.intAsHexString(ival) + pad;
} else {
long lval = Statics.getSlotContentsAsLong(jtocOff);
contents = Services.intAsHexString((int) (lval >> 32)) + Services.intAsHexString((int) (lval & 0xffffffffL)).substring(2);
jtocSlot++;
}
} else {
// Unknown?
int ival = Statics.getSlotContentsAsInt(jtocOff);
category = "<? - field> ";
details = "<? - " + field.toString() + ">";
contents = Services.intAsHexString(ival) + pad;
}
} else {
// Unknown?
int ival = Statics.getSlotContentsAsInt(jtocOff);
category = "<?> ";
details = "<?>";
contents = Services.intAsHexString(ival) + pad;
}
}
out.println((jtocSlot + " ").substring(0, 8) + Services.addressAsHexString(jtocOff.toWord().toAddress()) + " " + category + " " + contents + " " + details);
}
// Reference JTOC fields
for (int jtocSlot = Statics.middleOfTable, n = Statics.getHighestInUseSlot(); jtocSlot <= n; jtocSlot += Statics.getReferenceSlotSize()) {
Offset jtocOff = Statics.slotAsOffset(jtocSlot);
Object obj = BootImageMap.getObject(getIVal(jtocOff));
String category;
String details;
String contents = Services.addressAsHexString(getReferenceAddr(jtocOff, false)) + pad;
RVMField field = getRvmStaticField(jtocOff);
if (Statics.isReferenceLiteral(jtocSlot)) {
if (field != null) {
category = "literal/field";
} else {
category = "literal ";
}
if (obj == null) {
details = "(null)";
} else if (obj instanceof String) {
details = "\"" + obj + "\"";
} else if (obj instanceof Class) {
details = obj.toString();
;
} else if (obj instanceof TIB) {
category = "literal tib ";
RVMType type = ((TIB) obj).getType();
details = (type == null) ? "?" : type.toString();
} else {
details = "object " + obj.getClass();
}
if (field != null) {
details += " / " + field.toString();
}
} else if (field != null) {
category = "field ";
details = field.toString();
} else if (obj instanceof TIB) {
// TIBs confuse the statics as their backing is written into the boot image
category = "tib ";
RVMType type = ((TIB) obj).getType();
details = (type == null) ? "?" : type.toString();
} else {
category = "unknown ";
if (obj instanceof String) {
details = "\"" + obj + "\"";
} else if (obj instanceof Class) {
details = obj.toString();
} else {
CompiledMethod m = findMethodOfCode(obj);
if (m != null) {
category = "code ";
details = m.getMethod().toString();
} else if (obj != null) {
details = "<?> - unrecognized field or literal of type " + obj.getClass();
} else {
details = "<?>";
}
}
}
out.println((jtocSlot + " ").substring(0, 8) + Services.addressAsHexString(jtocOff.toWord().toAddress()) + " " + category + " " + contents + " " + details);
}
out.println();
out.println("Method Map");
out.println("----------");
out.println(" address method");
out.println(" ------- ------");
out.println();
for (int i = 0; i < CompiledMethods.numCompiledMethods(); ++i) {
CompiledMethod compiledMethod = CompiledMethods.getCompiledMethodUnchecked(i);
if (compiledMethod != null) {
RVMMethod m = compiledMethod.getMethod();
if (m != null && compiledMethod.isCompiled()) {
CodeArray instructions = compiledMethod.getEntryCodeArray();
Address code = BootImageMap.getImageAddress(instructions.getBacking(), true);
out.println(". . code " + Services.addressAsHexString(code) + " " + compiledMethod.getMethod());
}
}
}
// Extra information on the layout of objects in the boot image
if (false) {
out.println();
out.println("Object Map");
out.println("----------");
out.println(" address type");
out.println(" ------- ------");
out.println();
SortedSet<BootImageMap.Entry> set = new TreeSet<BootImageMap.Entry>(new Comparator<BootImageMap.Entry>() {
@Override
public int compare(BootImageMap.Entry a, BootImageMap.Entry b) {
return Integer.valueOf(a.imageAddress.toInt()).compareTo(b.imageAddress.toInt());
}
});
for (Enumeration<BootImageMap.Entry> e = BootImageMap.elements(); e.hasMoreElements(); ) {
BootImageMap.Entry entry = e.nextElement();
set.add(entry);
}
for (Iterator<BootImageMap.Entry> i = set.iterator(); i.hasNext(); ) {
BootImageMap.Entry entry = i.next();
Address data = entry.imageAddress;
out.println(". . data " + Services.addressAsHexString(data) + " " + entry.jdkObject.getClass());
}
}
out.println();
out.println("EOF-EOF-EOF");
out.flush();
out.close();
}
Aggregations