001/* 002 * This file is part of the Jikes RVM project (http://jikesrvm.org). 003 * 004 * This file is licensed to You under the Eclipse Public License (EPL); 005 * You may not use this file except in compliance with the License. You 006 * may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/eclipse-1.0.php 009 * 010 * See the COPYRIGHT.txt file distributed with this work for information 011 * regarding copyright ownership. 012 */ 013package org.jikesrvm.compilers.baseline; 014 015import static org.jikesrvm.classloader.BytecodeConstants.*; 016import static org.jikesrvm.classloader.ClassLoaderConstants.CP_CLASS; 017import static org.jikesrvm.classloader.ClassLoaderConstants.CP_STRING; 018import static org.jikesrvm.compilers.baseline.BBConstants.ADDRESS_TYPE; 019import static org.jikesrvm.compilers.baseline.BBConstants.DOUBLE_TYPE; 020import static org.jikesrvm.compilers.baseline.BBConstants.FLOAT_TYPE; 021import static org.jikesrvm.compilers.baseline.BBConstants.INT_TYPE; 022import static org.jikesrvm.compilers.baseline.BBConstants.LONG_TYPE; 023 024import org.jikesrvm.VM; 025import org.jikesrvm.classloader.BytecodeStream; 026import org.jikesrvm.classloader.ExceptionHandlerMap; 027import org.jikesrvm.classloader.MethodReference; 028import org.jikesrvm.classloader.NormalMethod; 029import org.jikesrvm.classloader.TypeReference; 030 031/** 032 * This class builds the reference and non-reference maps for a given method. 033 * The maps are recorded with ReferenceMaps. This class works with the baseline 034 * compiler, calculating the maps for local variables (including parameters), 035 * and the java operand stack. Given the basic blocks mapped out by BuildBB 036 * determine for each GC point (call sites and new's, etc) what the stack and 037 * variable maps are. Note that this class deals with reference maps (the term 038 * "stack maps" was not used as it is too ambiguous - does "stack" refer to the 039 * java operand stack or a C-like stack?; when processing java bytecodes it 040 * seemed best to use "stack" for java operand stack.) 041 */ 042final class BuildReferenceMaps { 043 044 /** 045 * The entry in the reference map contains a value that is not a reference. 046 */ 047 static final byte NON_REFERENCE = 0; 048 /** 049 * The entry in the reference map contains a value that is a reference. 050 */ 051 static final byte REFERENCE = 1; 052 /** 053 * The entry in the reference map contains a JSR return address. 054 */ 055 static final byte RETURN_ADDRESS = 2; 056 /** 057 * The entry in the reference map is not set in a JSR body. 058 */ 059 static final byte NOT_SET = 0; 060 /** 061 * The entry in the reference map is set to a value that is a reference within a JSR body. 062 */ 063 static final byte SET_TO_REFERENCE = 1; 064 /** 065 * The entry in the reference map is set to a value that is not a reference within a JSR body. 066 */ 067 static final byte SET_TO_NONREFERENCE = 3; 068 069 private enum PrimitiveSize { 070 ONEWORD, DOUBLEWORD 071 }; 072 073 // These two variables are used and updated by more than one method in this class, 074 // therefore they need to be instance variables; 075 int workStkTop; 076 int JSRSubNext; 077 078 /** 079 * After the analysis of the blocks of a method, examine the byte codes again, to 080 * determine the reference maps for the gc points. Record the maps with 081 * referenceMaps. 082 * 083 * @param method the method whose bytecodes are to be examined again 084 * @param stackHeights height of the expression stack at each bytecode 085 * @param localTypes the types that the locals can take 086 * @param referenceMaps the reference map. NB: the map's constructor is still running 087 * while this method is called! 088 * @param buildBB the buildBB instance that contains the results from the 089 * previous analysis 090 * 091 * @see BaselineCompiler#localTypes 092 * @see TemplateCompilerFramework#stackHeights 093 */ 094 public void buildReferenceMaps(NormalMethod method, int[] stackHeights, byte[] localTypes, 095 ReferenceMaps referenceMaps, BuildBB buildBB) { 096 //****************************************************************// 097 // These were calculated by BuildBB.determineTheBasicBlocks // 098 //****************************************************************// 099 int gcPointCount = buildBB.gcPointCount; 100 short[] byteToBlockMap = buildBB.byteToBlockMap; 101 BasicBlock[] basicBlocks = buildBB.basicBlocks; 102 int jsrCount = buildBB.numJsrs; 103 104 byte[][] bbMaps; // The starting map for each block, a block is not 105 // processed until it has a starting map. 106 int[] blockStkTop; // For each block, track where its current stack top is. 107 108 int currBBNum; // Block number of block currently being processed 109 byte[] currBBMap; // The current map, used during processing thru a block 110 int currBBStkTop; // Stack top for the current map 111 112 final int currBBStkEmpty; // Level when stack is empty - value depends on number of locals 113 int paramCount; // Number of parameters to the method being processed 114 115 // Variables for processing JSR instructions, RET instructions and JSR subroutines 116 PendingRETInfo[] bbPendingRETs = null; 117 PendingRETInfo currPendingRET; 118 JSRSubroutineInfo[] JSRSubs = null; 119 120 // Blocks that need to be processed are put on the workStk 121 short[] workStk; 122 123 // Track whether a block has already been seen once. Any recording of maps done 124 // within such a block will be processed as a "rerecording" instead of a new map. 125 // 126 boolean[] blockSeen; 127 128 // blocks that represent "catch" blocks need special processing. Catch blocks 129 // also referred to as handlers 130 // 131 ExceptionHandlerMap exceptions; // exception table class for method being processed 132 int[] tryStartPC; // array of try start indicesinto byte code table 133 int[] tryEndPC; // array of try end indices into byte code table 134 int[] tryHandlerPC; // array of try handlers start indices into bytecode 135 int tryHandlerLength; // length of try handlers array 136 int[] reachableHandlerBBNums; // array of reachable handlers from a given try block 137 int reachableHandlersCount; // Number of reachable handlers 138 boolean[] handlerProcessed; // Handler blocks are processed after the normal flow. As 139 // they may be nested, they need to be handled 140 // individually. This array is used to track which 141 // have been processed. 142 boolean handlersAllDone; 143 144 // Other local variables 145 // 146 BytecodeStream bcodes; // byte codes for the method 147 short brBBNum; // For processing branches, need block number of target 148 149 final boolean debug = false; 150 151 // Note that the mapping done here is "double mapping" of parameters. 152 // Double mapping is when the parameters for a method are included in the map of 153 // the method as well as in the map of the caller of the method. The original 154 // intent was that with double mapping call sites that are tricks 155 // (e.g. Magic.callFunctionReturnVoid ) would at least be correctly mapped on one 156 // of the two sides. However with more recent changes to the runtime stack frame 157 // layout, the parameters specified on the caller side occupy different 158 // locations than the parameters on the callee side for the baseline compiler. 159 // Thus both need to be described. 160 161 // 162 // Initialization 163 // 164 165 // Determine what stack empty looks like 166 paramCount = method.getParameterWords(); 167 if (!method.isStatic()) paramCount++; 168 169 currBBStkEmpty = TemplateCompilerFramework.stackHeightForEmptyBasicBlock(method); 170 171 if (debug) VM.sysWrite("getLocalWords() : " + method.getLocalWords() + "\n"); 172 173 // Get information from the method being processed 174 bcodes = method.getBytecodes(); 175 176 // Set up the array of maps per block; block 0 is not used 177 int numBB = buildBB.bbf.getNumberofBlocks(); 178 bbMaps = new byte[numBB + 1][]; 179 blockStkTop = new int[bbMaps.length]; 180 blockSeen = new boolean[bbMaps.length]; 181 182 // Try Handler processing initialization 183 184 exceptions = method.getExceptionHandlerMap(); 185 if (exceptions != null) { 186 tryStartPC = exceptions.getStartPC(); 187 tryEndPC = exceptions.getEndPC(); 188 tryHandlerPC = exceptions.getHandlerPC(); 189 tryHandlerLength = tryHandlerPC.length; 190 191 reachableHandlerBBNums = new int[tryStartPC.length]; 192 handlerProcessed = new boolean[tryStartPC.length]; 193 if (jsrCount > 0) { 194 JSRSubs = new JSRSubroutineInfo[jsrCount]; 195 JSRSubNext = 0; 196 bbPendingRETs = new PendingRETInfo[bbMaps.length]; 197 } 198 handlersAllDone = (tryHandlerLength == 0); 199 200 // write poison values to help distinguish different errors 201 for (int ii = 0; ii < reachableHandlerBBNums.length; ii++) { 202 reachableHandlerBBNums[ii] = -1; 203 } 204 } else { 205 tryHandlerLength = 0; 206 handlersAllDone = true; 207 tryStartPC = null; 208 tryEndPC = null; 209 tryHandlerPC = null; 210 reachableHandlerBBNums = null; 211 handlerProcessed = null; 212 } 213 reachableHandlersCount = 0; 214 215 // Start a new set of maps with the reference Map class. 216 // 3rd argument is parameter count included with the maps 217 referenceMaps.startNewMaps(gcPointCount, jsrCount, paramCount); 218 219 // Set up the Work stack 220 workStk = new short[10 + tryHandlerLength]; 221 222 // Start by putting the first block on the work stack 223 workStkTop = 0; 224 workStk[workStkTop] = byteToBlockMap[0]; 225 currBBMap = new byte[method.getOperandWords() + currBBStkEmpty + 1]; 226 227 // 228 // Need to include the parameters of this method in the map 229 // 230 TypeReference[] parameterTypes = method.getParameterTypes(); 231 int paramStart; 232 if (!method.isStatic()) { 233 currBBMap[0] = REFERENCE; // implicit "this" object 234 localTypes[0] = ADDRESS_TYPE; 235 paramStart = 1; 236 } else { 237 paramStart = 0; 238 } 239 240 for (int i = 0; i < parameterTypes.length; i++, paramStart++) { 241 TypeReference parameterType = parameterTypes[i]; 242 if (parameterType.isReferenceType()) { 243 localTypes[paramStart] = ADDRESS_TYPE; 244 currBBMap[paramStart] = REFERENCE; 245 } else { 246 currBBMap[paramStart] = NON_REFERENCE; 247 248 if (parameterType.getStackWords() == 2) { 249 if (parameterType.isLongType()) { 250 localTypes[paramStart] = LONG_TYPE; 251 } else { 252 localTypes[paramStart] = DOUBLE_TYPE; 253 } 254 paramStart++; 255 } else if (parameterType.isFloatType()) { 256 localTypes[paramStart] = FLOAT_TYPE; 257 } else if (parameterType.isIntLikeType()) { 258 localTypes[paramStart] = INT_TYPE; 259 } else { 260 localTypes[paramStart] = ADDRESS_TYPE; 261 } 262 } 263 } 264 265 // The map for the start of the first block, is stack empty, with none 266 // of the locals set yet 267 // 268 currBBStkTop = currBBStkEmpty; 269 bbMaps[byteToBlockMap[0]] = currBBMap; 270 blockStkTop[byteToBlockMap[0]] = currBBStkTop; 271 272 // For all methods, record a map at the start of the method for the corresponding 273 // conditional call to "yield". 274 275 referenceMaps.recordStkMap(0, currBBMap, currBBStkTop, false); 276 277 currBBMap = new byte[currBBMap.length]; 278 279 //---------------------------------------------------------- 280 // 281 // Keep looping until the Work Stack is empty 282 // 283 //---------------------------------------------------------- 284 while (workStkTop > -1) { 285 286 // Get the next item off the work stack 287 currBBNum = workStk[workStkTop]; 288 workStkTop--; 289 290 boolean inJSRSub = false; 291 if (bbMaps[currBBNum] != null) { 292 currBBStkTop = blockStkTop[currBBNum]; 293 for (int k = 0; k <= currBBStkTop; k++) { 294 currBBMap[k] = bbMaps[currBBNum][k]; 295 } 296 297 if (jsrCount > 0 && basicBlocks[currBBNum].isInJSR()) { 298 inJSRSub = true; 299 } 300 } else { 301 VM.sysWrite("BuildReferenceMaps, error: found a block on work stack with"); 302 VM.sysWrite(" no starting map. The block number is "); 303 VM.sysWrite(basicBlocks[currBBNum].getBlockNumber()); 304 VM.sysWrite("\n"); 305 VM.sysFail("BuildReferenceMaps work stack failure"); 306 } 307 308 int start = basicBlocks[currBBNum].getStart(); 309 int end = basicBlocks[currBBNum].getEnd(); 310 311 if (jsrCount > 0 && inJSRSub) { 312 currPendingRET = bbPendingRETs[currBBNum]; 313 if (basicBlocks[currBBNum].isTryStart()) { 314 for (int k = 0; k < tryHandlerLength; k++) { 315 if (tryStartPC[k] == start) { 316 int handlerBBNum = byteToBlockMap[tryHandlerPC[k]]; 317 bbPendingRETs[handlerBBNum] = new PendingRETInfo(currPendingRET); 318 } 319 } 320 } 321 if (currPendingRET == null) { 322 int[] preds = basicBlocks[currBBNum].getPredecessors(); 323 for (int i = 0; i < preds.length; i++) { 324 int predBB = preds[i]; 325 if (bbPendingRETs[predBB] != null) { 326 currPendingRET = bbPendingRETs[predBB]; 327 break; 328 } 329 } 330 } 331 if (VM.VerifyAssertions) { 332 if (currPendingRET == null) { 333 String msg = "No pending return found in block " + currBBNum; 334 VM._assert(VM.NOT_REACHED, msg); 335 } 336 } 337 } else { 338 currPendingRET = null; 339 } 340 341 boolean inTryBlock; 342 if (basicBlocks[currBBNum].isTryBlock()) { 343 inTryBlock = true; 344 reachableHandlersCount = 0; 345 for (int i = 0; i < tryHandlerLength; i++) { 346 if (start <= tryEndPC[i] && end >= tryStartPC[i]) { 347 reachableHandlerBBNums[reachableHandlersCount] = byteToBlockMap[tryHandlerPC[i]]; 348 reachableHandlersCount++; 349 int handlerBBNum = byteToBlockMap[tryHandlerPC[i]]; 350 if (bbMaps[handlerBBNum] == null) { 351 bbMaps[handlerBBNum] = new byte[currBBMap.length]; 352 for (int k = 0; k <= currBBStkEmpty; k++) { 353 bbMaps[handlerBBNum][k] = currBBMap[k]; 354 } 355 bbMaps[handlerBBNum][currBBStkEmpty + 1] = REFERENCE; 356 blockStkTop[handlerBBNum] = currBBStkEmpty + 1; 357 } else { 358 if (inJSRSub && basicBlocks[handlerBBNum].isInJSR()) { 359 // In JSR and handler within the same JSR. 360 // Ensure SET_TO_NONREFERENCE is carried across 361 for (int k = 0; k <= currBBStkEmpty; k++) { 362 if (currBBMap[k] == SET_TO_NONREFERENCE && bbMaps[handlerBBNum][k] != SET_TO_NONREFERENCE) { 363 handlerProcessed[i] = false; 364 bbMaps[handlerBBNum][k] = SET_TO_NONREFERENCE; 365 } 366 } 367 } else if (inJSRSub) { 368 // In JSR but handler is shared by JSR and non JSR 369 // realise JSR and SET_TO_NONREFERENCE becomes NON_REFERENCE 370 for (int k = 0; k <= currBBStkEmpty; k++) { 371 if (currBBMap[k] == SET_TO_NONREFERENCE && bbMaps[handlerBBNum][k] != NON_REFERENCE) { 372 handlerProcessed[i] = false; 373 bbMaps[handlerBBNum][k] = NON_REFERENCE; 374 } 375 } 376 } else { 377 // No JSRs involved, simply ensure NON_REFERENCE is carried over 378 for (int k = 0; k <= currBBStkEmpty; k++) { 379 if (currBBMap[k] == NON_REFERENCE && bbMaps[handlerBBNum][k] != NON_REFERENCE) { 380 handlerProcessed[i] = false; 381 bbMaps[handlerBBNum][k] = NON_REFERENCE; 382 } 383 } 384 } 385 } 386 } 387 } 388 } else { 389 inTryBlock = false; 390 } 391 392 boolean processNextBlock = true; 393 394 bcodes.reset(start); 395 while (bcodes.index() <= end) { 396 int biStart = bcodes.index(); 397 int opcode = bcodes.nextInstruction(); 398 if (stackHeights != null) { 399 if (VM.VerifyAssertions) { 400 if (currBBStkTop < currBBStkEmpty) { 401 String msg = "Stack height for current basic block is " + 402 currBBStkTop + " which is less than the stack height for " + 403 "an empty block (" + currBBStkEmpty + ")."; 404 VM._assert(VM.NOT_REACHED, msg); 405 } 406 } 407 stackHeights[biStart] = currBBStkTop; 408 } 409 410 if (debug) { 411 VM.sysWrite("opcode : " + opcode + "\n"); 412 VM.sysWrite("current map: "); 413 for (int j = 0; j <= currBBStkTop; j++) { 414 VM.sysWrite(currBBMap[j]); 415 } 416 VM.sysWrite("\n"); 417 } 418 419 switch (opcode) { 420 case JBC_nop: { 421 break; 422 } 423 case JBC_aconst_null: { 424 currBBStkTop++; 425 currBBMap[currBBStkTop] = REFERENCE; 426 break; 427 } 428 case JBC_aload_0: { 429 int localNumber = 0; 430 currBBStkTop++; 431 currBBMap[currBBStkTop] = inJSRSub ? REFERENCE : currBBMap[localNumber]; 432 break; 433 } 434 case JBC_aload_1: { 435 int localNumber = 1; 436 currBBStkTop++; 437 currBBMap[currBBStkTop] = inJSRSub ? REFERENCE : currBBMap[localNumber]; 438 break; 439 } 440 case JBC_aload_2: { 441 int localNumber = 2; 442 currBBStkTop++; 443 currBBMap[currBBStkTop] = inJSRSub ? REFERENCE : currBBMap[localNumber]; 444 break; 445 } 446 case JBC_aload_3: { 447 int localNumber = 3; 448 currBBStkTop++; 449 currBBMap[currBBStkTop] = inJSRSub ? REFERENCE : currBBMap[localNumber]; 450 break; 451 } 452 case JBC_aload: { 453 int localNumber = bcodes.getLocalNumber(); 454 currBBStkTop++; 455 currBBMap[currBBStkTop] = inJSRSub ? REFERENCE : currBBMap[localNumber]; 456 break; 457 } 458 459 case JBC_iconst_m1: 460 case JBC_iconst_0: 461 case JBC_iconst_1: 462 case JBC_iconst_2: 463 case JBC_iconst_3: 464 case JBC_iconst_4: 465 case JBC_iconst_5: 466 case JBC_fconst_0: 467 case JBC_fconst_1: 468 case JBC_fconst_2: 469 case JBC_iload_0: 470 case JBC_iload_1: 471 case JBC_iload_2: 472 case JBC_iload_3: 473 case JBC_fload_0: 474 case JBC_fload_1: 475 case JBC_fload_2: 476 case JBC_fload_3: 477 case JBC_bipush: 478 case JBC_iload: 479 case JBC_fload: 480 case JBC_sipush: 481 case JBC_i2l: 482 case JBC_i2d: 483 case JBC_f2l: 484 case JBC_f2d: { 485 currBBStkTop++; 486 currBBMap[currBBStkTop] = NON_REFERENCE; 487 bcodes.skipInstruction(); // contains mix of 1,2,3 byte bytecodes 488 break; 489 } 490 491 case JBC_lconst_0: 492 case JBC_lconst_1: 493 case JBC_dconst_0: 494 case JBC_dconst_1: 495 case JBC_lload_0: 496 case JBC_lload_1: 497 case JBC_lload_2: 498 case JBC_lload_3: 499 case JBC_dload_0: 500 case JBC_dload_1: 501 case JBC_dload_2: 502 case JBC_dload_3: 503 case JBC_ldc2_w: 504 case JBC_lload: 505 case JBC_dload: { 506 currBBStkTop++; 507 currBBMap[currBBStkTop] = NON_REFERENCE; 508 currBBStkTop++; 509 currBBMap[currBBStkTop] = NON_REFERENCE; 510 bcodes.skipInstruction(); // mix of 1, 2, and 3 byte bytecodes 511 break; 512 } 513 514 case JBC_ldc: { 515 currBBStkTop++; 516 int cpi = bcodes.getConstantIndex(); 517 int type = bcodes.getConstantType(cpi); 518 if (type == CP_STRING || type == CP_CLASS) { 519 currBBMap[currBBStkTop] = REFERENCE; 520 } else { 521 currBBMap[currBBStkTop] = NON_REFERENCE; 522 } 523 break; 524 } 525 case JBC_ldc_w: { 526 currBBStkTop++; 527 int cpi = bcodes.getWideConstantIndex(); 528 int type = bcodes.getConstantType(cpi); 529 if (type == CP_STRING || type == CP_CLASS) { 530 currBBMap[currBBStkTop] = REFERENCE; 531 } else { 532 currBBMap[currBBStkTop] = NON_REFERENCE; 533 } 534 break; 535 } 536 537 case JBC_istore: { 538 int index = bcodes.getLocalNumber(); 539 if (!inJSRSub) { 540 currBBMap[index] = NON_REFERENCE; 541 } else { 542 currBBMap[index] = SET_TO_NONREFERENCE; 543 } 544 if (inTryBlock) { 545 setHandlersMapsNonRef(index, PrimitiveSize.ONEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps); 546 } 547 currBBStkTop--; 548 localTypes[index] |= INT_TYPE; 549 break; 550 } 551 552 case JBC_fstore: { 553 int index = bcodes.getLocalNumber(); 554 if (!inJSRSub) { 555 currBBMap[index] = NON_REFERENCE; 556 } else { 557 currBBMap[index] = SET_TO_NONREFERENCE; 558 } 559 if (inTryBlock) { 560 setHandlersMapsNonRef(index, PrimitiveSize.ONEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps); 561 } 562 currBBStkTop--; 563 localTypes[index] |= FLOAT_TYPE; 564 break; 565 } 566 567 case JBC_lstore: { 568 int index = bcodes.getLocalNumber(); 569 if (!inJSRSub) { 570 currBBMap[index] = NON_REFERENCE; 571 currBBMap[index + 1] = NON_REFERENCE; 572 } else { 573 currBBMap[index] = SET_TO_NONREFERENCE; 574 currBBMap[index + 1] = SET_TO_NONREFERENCE; 575 } 576 577 if (inTryBlock) { 578 setHandlersMapsNonRef(index, PrimitiveSize.DOUBLEWORD, 579 reachableHandlerBBNums, reachableHandlersCount, inJSRSub, 580 bbMaps); 581 } 582 currBBStkTop = currBBStkTop - 2; 583 localTypes[index] |= LONG_TYPE; 584 break; 585 } 586 587 case JBC_dstore: { 588 int index = bcodes.getLocalNumber(); 589 if (!inJSRSub) { 590 currBBMap[index] = NON_REFERENCE; 591 currBBMap[index + 1] = NON_REFERENCE; 592 } else { 593 currBBMap[index] = SET_TO_NONREFERENCE; 594 currBBMap[index + 1] = SET_TO_NONREFERENCE; 595 } 596 597 if (inTryBlock) { 598 setHandlersMapsNonRef(index, PrimitiveSize.DOUBLEWORD, 599 reachableHandlerBBNums, reachableHandlersCount, inJSRSub, 600 bbMaps); 601 } 602 currBBStkTop = currBBStkTop - 2; 603 localTypes[index] |= DOUBLE_TYPE; 604 break; 605 } 606 607 case JBC_astore: { 608 int index = bcodes.getLocalNumber(); 609 currBBMap[index] = currBBMap[currBBStkTop];// may be a reference or a return address 610 if (inJSRSub) { 611 if (currBBMap[index] == RETURN_ADDRESS) { 612 currPendingRET.updateReturnAddressLocation(index); 613 } 614 if (inTryBlock) { 615 if (currBBMap[index] == REFERENCE) { 616 setHandlersMapsRef(index, reachableHandlerBBNums, reachableHandlersCount, bbMaps); 617 } else { 618 setHandlersMapsReturnAddress(index, reachableHandlerBBNums, reachableHandlersCount, bbMaps); 619 } 620 } 621 } 622 currBBStkTop--; 623 localTypes[index] |= ADDRESS_TYPE; 624 break; 625 } 626 627 case JBC_istore_0: { 628 if (!inJSRSub) { 629 currBBMap[0] = NON_REFERENCE; 630 } else { 631 currBBMap[0] = SET_TO_NONREFERENCE; 632 } 633 if (inTryBlock) { 634 setHandlersMapsNonRef(0, PrimitiveSize.ONEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps); 635 } 636 currBBStkTop--; 637 localTypes[0] |= INT_TYPE; 638 break; 639 } 640 641 case JBC_fstore_0: { 642 if (!inJSRSub) { 643 currBBMap[0] = NON_REFERENCE; 644 } else { 645 currBBMap[0] = SET_TO_NONREFERENCE; 646 } 647 if (inTryBlock) { 648 setHandlersMapsNonRef(0, PrimitiveSize.ONEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps); 649 } 650 currBBStkTop--; 651 localTypes[0] |= FLOAT_TYPE; 652 break; 653 } 654 655 case JBC_istore_1: { 656 if (!inJSRSub) { 657 currBBMap[1] = NON_REFERENCE; 658 } else { 659 currBBMap[1] = SET_TO_NONREFERENCE; 660 } 661 if (inTryBlock) { 662 setHandlersMapsNonRef(1, PrimitiveSize.ONEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps); 663 } 664 currBBStkTop--; 665 localTypes[1] |= INT_TYPE; 666 break; 667 } 668 669 case JBC_fstore_1: { 670 if (!inJSRSub) { 671 currBBMap[1] = NON_REFERENCE; 672 } else { 673 currBBMap[1] = SET_TO_NONREFERENCE; 674 } 675 if (inTryBlock) { 676 setHandlersMapsNonRef(1, PrimitiveSize.ONEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps); 677 } 678 currBBStkTop--; 679 localTypes[1] |= FLOAT_TYPE; 680 break; 681 } 682 683 case JBC_istore_2: { 684 if (!inJSRSub) { 685 currBBMap[2] = NON_REFERENCE; 686 } else { 687 currBBMap[2] = SET_TO_NONREFERENCE; 688 } 689 if (inTryBlock) { 690 setHandlersMapsNonRef(2, PrimitiveSize.ONEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps); 691 } 692 currBBStkTop--; 693 localTypes[2] |= INT_TYPE; 694 break; 695 } 696 697 case JBC_fstore_2: { 698 if (!inJSRSub) { 699 currBBMap[2] = NON_REFERENCE; 700 } else { 701 currBBMap[2] = SET_TO_NONREFERENCE; 702 } 703 if (inTryBlock) { 704 setHandlersMapsNonRef(2, PrimitiveSize.ONEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps); 705 } 706 currBBStkTop--; 707 localTypes[2] |= FLOAT_TYPE; 708 break; 709 } 710 711 case JBC_istore_3: { 712 if (!inJSRSub) { 713 currBBMap[3] = NON_REFERENCE; 714 } else { 715 currBBMap[3] = SET_TO_NONREFERENCE; 716 } 717 if (inTryBlock) { 718 setHandlersMapsNonRef(3, PrimitiveSize.ONEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps); 719 } 720 currBBStkTop--; 721 localTypes[3] |= INT_TYPE; 722 break; 723 } 724 725 case JBC_fstore_3: { 726 if (!inJSRSub) { 727 currBBMap[3] = NON_REFERENCE; 728 } else { 729 currBBMap[3] = SET_TO_NONREFERENCE; 730 } 731 if (inTryBlock) { 732 setHandlersMapsNonRef(3, PrimitiveSize.ONEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps); 733 } 734 currBBStkTop--; 735 localTypes[3] |= FLOAT_TYPE; 736 break; 737 } 738 739 case JBC_lstore_0: { 740 if (inJSRSub) { 741 currBBMap[0] = NON_REFERENCE; 742 currBBMap[1] = NON_REFERENCE; 743 } else { 744 currBBMap[0] = SET_TO_NONREFERENCE; 745 currBBMap[1] = SET_TO_NONREFERENCE; 746 } 747 if (inTryBlock) { 748 setHandlersMapsNonRef(0, PrimitiveSize.DOUBLEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps); 749 } 750 currBBStkTop = currBBStkTop - 2; 751 localTypes[0] |= LONG_TYPE; 752 break; 753 } 754 case JBC_dstore_0: { 755 if (inJSRSub) { 756 currBBMap[0] = NON_REFERENCE; 757 currBBMap[1] = NON_REFERENCE; 758 } else { 759 currBBMap[0] = SET_TO_NONREFERENCE; 760 currBBMap[1] = SET_TO_NONREFERENCE; 761 } 762 if (inTryBlock) { 763 setHandlersMapsNonRef(0, PrimitiveSize.DOUBLEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps); 764 } 765 currBBStkTop = currBBStkTop - 2; 766 localTypes[0] |= DOUBLE_TYPE; 767 break; 768 } 769 770 case JBC_lstore_1: { 771 if (!inJSRSub) { 772 currBBMap[1] = NON_REFERENCE; 773 currBBMap[2] = NON_REFERENCE; 774 } else { 775 currBBMap[1] = SET_TO_NONREFERENCE; 776 currBBMap[2] = SET_TO_NONREFERENCE; 777 } 778 if (inTryBlock) { 779 setHandlersMapsNonRef(1, PrimitiveSize.DOUBLEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps); 780 } 781 currBBStkTop = currBBStkTop - 2; 782 localTypes[1] |= LONG_TYPE; 783 break; 784 } 785 786 case JBC_dstore_1: { 787 if (!inJSRSub) { 788 currBBMap[1] = NON_REFERENCE; 789 currBBMap[2] = NON_REFERENCE; 790 } else { 791 currBBMap[1] = SET_TO_NONREFERENCE; 792 currBBMap[2] = SET_TO_NONREFERENCE; 793 } 794 if (inTryBlock) { 795 setHandlersMapsNonRef(1, PrimitiveSize.DOUBLEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps); 796 } 797 currBBStkTop = currBBStkTop - 2; 798 localTypes[1] |= DOUBLE_TYPE; 799 break; 800 } 801 802 case JBC_lstore_2: { 803 if (!inJSRSub) { 804 currBBMap[2] = NON_REFERENCE; 805 currBBMap[3] = NON_REFERENCE; 806 } else { 807 currBBMap[2] = SET_TO_NONREFERENCE; 808 currBBMap[3] = SET_TO_NONREFERENCE; 809 } 810 if (inTryBlock) { 811 setHandlersMapsNonRef(2, PrimitiveSize.DOUBLEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps); 812 } 813 currBBStkTop = currBBStkTop - 2; 814 localTypes[2] |= LONG_TYPE; 815 break; 816 } 817 818 case JBC_dstore_2: { 819 if (!inJSRSub) { 820 currBBMap[2] = NON_REFERENCE; 821 currBBMap[3] = NON_REFERENCE; 822 } else { 823 currBBMap[2] = SET_TO_NONREFERENCE; 824 currBBMap[3] = SET_TO_NONREFERENCE; 825 } 826 if (inTryBlock) { 827 setHandlersMapsNonRef(2, PrimitiveSize.DOUBLEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps); 828 } 829 currBBStkTop = currBBStkTop - 2; 830 localTypes[2] |= DOUBLE_TYPE; 831 break; 832 } 833 834 case JBC_lstore_3: { 835 if (!inJSRSub) { 836 currBBMap[3] = NON_REFERENCE; 837 currBBMap[4] = NON_REFERENCE; 838 } else { 839 currBBMap[3] = SET_TO_NONREFERENCE; 840 currBBMap[4] = SET_TO_NONREFERENCE; 841 } 842 if (inTryBlock) { 843 setHandlersMapsNonRef(3, PrimitiveSize.DOUBLEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps); 844 } 845 currBBStkTop = currBBStkTop - 2; 846 localTypes[3] |= LONG_TYPE; 847 break; 848 } 849 850 case JBC_dstore_3: { 851 if (!inJSRSub) { 852 currBBMap[3] = NON_REFERENCE; 853 currBBMap[4] = NON_REFERENCE; 854 } else { 855 currBBMap[3] = SET_TO_NONREFERENCE; 856 currBBMap[4] = SET_TO_NONREFERENCE; 857 } 858 if (inTryBlock) { 859 setHandlersMapsNonRef(3, PrimitiveSize.DOUBLEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps); 860 } 861 currBBStkTop = currBBStkTop - 2; 862 localTypes[3] |= DOUBLE_TYPE; 863 break; 864 } 865 866 case JBC_astore_0: { 867 currBBMap[0] = currBBMap[currBBStkTop]; 868 if (inJSRSub) { 869 if (currBBMap[0] == RETURN_ADDRESS) { 870 currPendingRET.updateReturnAddressLocation(0); 871 } 872 if (inTryBlock) { 873 if (currBBMap[0] == REFERENCE) { 874 setHandlersMapsRef(0, reachableHandlerBBNums, reachableHandlersCount, bbMaps); 875 } else { 876 setHandlersMapsReturnAddress(0, reachableHandlerBBNums, reachableHandlersCount, bbMaps); 877 } 878 } 879 } 880 currBBStkTop--; 881 localTypes[0] |= ADDRESS_TYPE; 882 break; 883 } 884 885 case JBC_astore_1: { 886 currBBMap[1] = currBBMap[currBBStkTop]; 887 if (inJSRSub) { 888 if (currBBMap[1] == RETURN_ADDRESS) { 889 currPendingRET.updateReturnAddressLocation(1); 890 } 891 if (inTryBlock) { 892 if (currBBMap[1] == REFERENCE) { 893 setHandlersMapsRef(1, reachableHandlerBBNums, reachableHandlersCount, bbMaps); 894 } else { 895 setHandlersMapsReturnAddress(1, reachableHandlerBBNums, reachableHandlersCount, bbMaps); 896 } 897 } 898 } 899 currBBStkTop--; 900 localTypes[1] |= ADDRESS_TYPE; 901 break; 902 } 903 904 case JBC_astore_2: { 905 currBBMap[2] = currBBMap[currBBStkTop]; 906 if (inJSRSub) { 907 if (currBBMap[2] == RETURN_ADDRESS) { 908 currPendingRET.updateReturnAddressLocation(2); 909 } 910 if (inTryBlock) { 911 if (currBBMap[2] == REFERENCE) { 912 setHandlersMapsRef(2, reachableHandlerBBNums, reachableHandlersCount, bbMaps); 913 } else { 914 setHandlersMapsReturnAddress(2, reachableHandlerBBNums, reachableHandlersCount, bbMaps); 915 } 916 } 917 } 918 currBBStkTop--; 919 localTypes[2] |= ADDRESS_TYPE; 920 break; 921 } 922 case JBC_astore_3: { 923 currBBMap[3] = currBBMap[currBBStkTop]; 924 if (inJSRSub) { 925 if (currBBMap[3] == RETURN_ADDRESS) { 926 currPendingRET.updateReturnAddressLocation(3); 927 } 928 if (inTryBlock) { 929 if (currBBMap[3] == REFERENCE) { 930 setHandlersMapsRef(3, reachableHandlerBBNums, reachableHandlersCount, bbMaps); 931 } else { 932 setHandlersMapsReturnAddress(3, reachableHandlerBBNums, reachableHandlersCount, bbMaps); 933 } 934 } 935 } 936 currBBStkTop--; 937 localTypes[3] |= ADDRESS_TYPE; 938 break; 939 } 940 941 case JBC_dup: { 942 currBBMap[currBBStkTop + 1] = currBBMap[currBBStkTop]; 943 currBBStkTop++; 944 break; 945 } 946 case JBC_dup2: { 947 currBBMap[currBBStkTop + 1] = currBBMap[currBBStkTop - 1]; 948 currBBMap[currBBStkTop + 2] = currBBMap[currBBStkTop]; 949 currBBStkTop = currBBStkTop + 2; 950 break; 951 } 952 case JBC_dup_x1: { 953 currBBMap[currBBStkTop + 1] = currBBMap[currBBStkTop]; 954 currBBMap[currBBStkTop] = currBBMap[currBBStkTop - 1]; 955 currBBMap[currBBStkTop - 1] = currBBMap[currBBStkTop + 1]; 956 currBBStkTop++; 957 break; 958 } 959 case JBC_dup2_x1: { 960 currBBMap[currBBStkTop + 2] = currBBMap[currBBStkTop]; 961 currBBMap[currBBStkTop + 1] = currBBMap[currBBStkTop - 1]; 962 currBBMap[currBBStkTop] = currBBMap[currBBStkTop - 2]; 963 currBBMap[currBBStkTop - 1] = currBBMap[currBBStkTop + 2]; 964 currBBMap[currBBStkTop - 2] = currBBMap[currBBStkTop + 1]; 965 currBBStkTop = currBBStkTop + 2; 966 break; 967 } 968 case JBC_dup_x2: { 969 currBBMap[currBBStkTop + 1] = currBBMap[currBBStkTop]; 970 currBBMap[currBBStkTop] = currBBMap[currBBStkTop - 1]; 971 currBBMap[currBBStkTop - 1] = currBBMap[currBBStkTop - 2]; 972 currBBMap[currBBStkTop - 2] = currBBMap[currBBStkTop + 1]; 973 currBBStkTop++; 974 break; 975 } 976 case JBC_dup2_x2: { 977 currBBMap[currBBStkTop + 2] = currBBMap[currBBStkTop]; 978 currBBMap[currBBStkTop + 1] = currBBMap[currBBStkTop - 1]; 979 currBBMap[currBBStkTop] = currBBMap[currBBStkTop - 2]; 980 currBBMap[currBBStkTop - 1] = currBBMap[currBBStkTop - 3]; 981 currBBMap[currBBStkTop - 2] = currBBMap[currBBStkTop + 2]; 982 currBBMap[currBBStkTop - 3] = currBBMap[currBBStkTop + 1]; 983 currBBStkTop = currBBStkTop + 2; 984 break; 985 } 986 case JBC_swap: { 987 byte temp; 988 temp = currBBMap[currBBStkTop]; 989 currBBMap[currBBStkTop] = currBBMap[currBBStkTop - 1]; 990 currBBMap[currBBStkTop - 1] = temp; 991 break; 992 } 993 case JBC_pop: 994 case JBC_iadd: 995 case JBC_fadd: 996 case JBC_isub: 997 case JBC_fsub: 998 case JBC_imul: 999 case JBC_fmul: 1000 case JBC_fdiv: 1001 case JBC_frem: 1002 case JBC_ishl: 1003 case JBC_ishr: 1004 case JBC_iushr: 1005 case JBC_lshl: // long shifts that int shift value 1006 case JBC_lshr: 1007 case JBC_lushr: 1008 case JBC_iand: 1009 case JBC_ior: 1010 case JBC_ixor: 1011 case JBC_l2i: 1012 case JBC_l2f: 1013 case JBC_d2i: 1014 case JBC_d2f: 1015 case JBC_fcmpl: 1016 case JBC_fcmpg: { 1017 currBBStkTop--; 1018 bcodes.skipInstruction(); 1019 break; 1020 } 1021 1022 case JBC_irem: 1023 case JBC_idiv: { 1024 currBBStkTop = currBBStkTop - 2; // record map after 2 integers popped off stack 1025 if (!inJSRSub) { 1026 referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]); 1027 } else { 1028 referenceMaps.recordJSRSubroutineMap(biStart, 1029 currBBMap, 1030 currBBStkTop, 1031 currPendingRET.returnAddressLocation, 1032 blockSeen[currBBNum]); 1033 } 1034 currBBStkTop++; 1035 break; 1036 } 1037 case JBC_ladd: 1038 case JBC_dadd: 1039 case JBC_lsub: 1040 case JBC_dsub: 1041 case JBC_lmul: 1042 case JBC_dmul: 1043 case JBC_ddiv: 1044 case JBC_drem: 1045 case JBC_land: 1046 case JBC_lor: 1047 case JBC_lxor: 1048 case JBC_pop2: { 1049 currBBStkTop = currBBStkTop - 2; 1050 break; 1051 } 1052 case JBC_lrem: 1053 case JBC_ldiv: { 1054 currBBStkTop = currBBStkTop - 4; // record map after 2 longs popped off stack 1055 if (!inJSRSub) { 1056 referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]); 1057 } else { 1058 referenceMaps.recordJSRSubroutineMap(biStart, 1059 currBBMap, 1060 currBBStkTop, 1061 currPendingRET.returnAddressLocation, 1062 blockSeen[currBBNum]); 1063 } 1064 currBBStkTop = currBBStkTop + 2; 1065 break; 1066 } 1067 case JBC_ineg: 1068 case JBC_lneg: 1069 case JBC_fneg: 1070 case JBC_dneg: 1071 case JBC_iinc: 1072 case JBC_i2f: 1073 case JBC_l2d: 1074 case JBC_f2i: 1075 case JBC_d2l: 1076 case JBC_int2byte: 1077 case JBC_int2char: 1078 case JBC_int2short: { 1079 bcodes.skipInstruction(); 1080 break; 1081 } 1082 1083 case JBC_lcmp: 1084 case JBC_dcmpl: 1085 case JBC_dcmpg: { 1086 currBBStkTop = currBBStkTop - 3; 1087 break; 1088 } 1089 1090 case JBC_ifeq: 1091 case JBC_ifne: 1092 case JBC_iflt: 1093 case JBC_ifge: 1094 case JBC_ifgt: 1095 case JBC_ifle: { 1096 int offset = bcodes.getBranchOffset(); 1097 if (offset <= 0) { 1098 // potential backward branch-generate reference map 1099 // Register the reference map 1100 1101 if (!inJSRSub) { 1102 referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]); 1103 } else { 1104 // in a jsr subroutine 1105 referenceMaps.recordJSRSubroutineMap(biStart, 1106 currBBMap, 1107 currBBStkTop, 1108 currPendingRET.returnAddressLocation, 1109 blockSeen[currBBNum]); 1110 } 1111 } 1112 1113 // process the basic block logic 1114 currBBStkTop--; 1115 if (offset <= 0) { 1116 short fallThruBBNum = byteToBlockMap[biStart + 3]; 1117 workStk = 1118 processBranchBB(fallThruBBNum, 1119 currBBStkTop, 1120 currBBMap, 1121 currBBStkEmpty, 1122 inJSRSub, 1123 bbMaps, 1124 blockStkTop, 1125 currPendingRET, 1126 bbPendingRETs, 1127 workStk); 1128 processNextBlock = false; 1129 } 1130 brBBNum = byteToBlockMap[biStart + offset]; 1131 workStk = 1132 processBranchBB(brBBNum, 1133 currBBStkTop, 1134 currBBMap, 1135 currBBStkEmpty, 1136 inJSRSub, 1137 bbMaps, 1138 blockStkTop, 1139 currPendingRET, 1140 bbPendingRETs, 1141 workStk); 1142 break; 1143 } 1144 1145 case JBC_if_icmpeq: 1146 case JBC_if_icmpne: 1147 case JBC_if_icmplt: 1148 case JBC_if_icmpge: 1149 case JBC_if_icmpgt: 1150 case JBC_if_icmple: 1151 case JBC_if_acmpeq: 1152 case JBC_if_acmpne: { 1153 int offset = bcodes.getBranchOffset(); 1154 if (offset <= 0) { 1155 // possible backward branch-generate reference map 1156 // Register the reference map 1157 1158 if (!inJSRSub) { 1159 referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]); 1160 } else { 1161 // in a jsr subroutine 1162 referenceMaps.recordJSRSubroutineMap(biStart, 1163 currBBMap, 1164 currBBStkTop, 1165 currPendingRET.returnAddressLocation, 1166 blockSeen[currBBNum]); 1167 } 1168 } 1169 1170 //process the basic blocks 1171 currBBStkTop = currBBStkTop - 2; 1172 if (offset <= 0) { 1173 short fallThruBBNum = byteToBlockMap[biStart + 3]; 1174 workStk = 1175 processBranchBB(fallThruBBNum, 1176 currBBStkTop, 1177 currBBMap, 1178 currBBStkEmpty, 1179 inJSRSub, 1180 bbMaps, 1181 blockStkTop, 1182 currPendingRET, 1183 bbPendingRETs, 1184 workStk); 1185 processNextBlock = false; 1186 } 1187 brBBNum = byteToBlockMap[biStart + offset]; 1188 workStk = 1189 processBranchBB(brBBNum, 1190 currBBStkTop, 1191 currBBMap, 1192 currBBStkEmpty, 1193 inJSRSub, 1194 bbMaps, 1195 blockStkTop, 1196 currPendingRET, 1197 bbPendingRETs, 1198 workStk); 1199 break; 1200 } 1201 1202 case JBC_ifnull: 1203 case JBC_ifnonnull: { 1204 int offset = bcodes.getBranchOffset(); 1205 if (offset <= 0) { 1206 // possible backward branch-generate reference map 1207 // Register the reference map 1208 1209 if (!inJSRSub) { 1210 referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]); 1211 } else { 1212 // in a jsr subroutine 1213 referenceMaps.recordJSRSubroutineMap(biStart, 1214 currBBMap, 1215 currBBStkTop, 1216 currPendingRET.returnAddressLocation, 1217 blockSeen[currBBNum]); 1218 } 1219 } 1220 1221 //process the basic block logic 1222 currBBStkTop--; 1223 if (offset <= 0) { 1224 short fallThruBBNum = byteToBlockMap[biStart + 3]; 1225 workStk = 1226 processBranchBB(fallThruBBNum, 1227 currBBStkTop, 1228 currBBMap, 1229 currBBStkEmpty, 1230 inJSRSub, 1231 bbMaps, 1232 blockStkTop, 1233 currPendingRET, 1234 bbPendingRETs, 1235 workStk); 1236 processNextBlock = false; 1237 } 1238 brBBNum = byteToBlockMap[biStart + offset]; 1239 workStk = 1240 processBranchBB(brBBNum, 1241 currBBStkTop, 1242 currBBMap, 1243 currBBStkEmpty, 1244 inJSRSub, 1245 bbMaps, 1246 blockStkTop, 1247 currPendingRET, 1248 bbPendingRETs, 1249 workStk); 1250 break; 1251 } 1252 1253 case JBC_goto: { 1254 int offset = bcodes.getBranchOffset(); 1255 if (offset <= 0) { 1256 // backward branch-generate reference map 1257 // Register the reference map 1258 if (!inJSRSub) { 1259 referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]); 1260 } else { 1261 // in a jsr subroutine 1262 referenceMaps.recordJSRSubroutineMap(biStart, 1263 currBBMap, 1264 currBBStkTop, 1265 currPendingRET.returnAddressLocation, 1266 blockSeen[currBBNum]); 1267 } 1268 } 1269 1270 // process the basic block logic 1271 brBBNum = byteToBlockMap[biStart + offset]; 1272 workStk = 1273 processBranchBB(brBBNum, 1274 currBBStkTop, 1275 currBBMap, 1276 currBBStkEmpty, 1277 inJSRSub, 1278 bbMaps, 1279 blockStkTop, 1280 currPendingRET, 1281 bbPendingRETs, 1282 workStk); 1283 processNextBlock = false; 1284 break; 1285 } 1286 case JBC_goto_w: { 1287 int offset = bcodes.getWideBranchOffset(); 1288 if (offset <= 0) { 1289 // backward branch-generate reference map 1290 // Register the reference map 1291 1292 if (!inJSRSub) { 1293 referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]); 1294 } else { 1295 // in a jsr subroutine 1296 referenceMaps.recordJSRSubroutineMap(biStart, 1297 currBBMap, 1298 currBBStkTop, 1299 currPendingRET.returnAddressLocation, 1300 blockSeen[currBBNum]); 1301 } 1302 } 1303 1304 //process basic block structures 1305 brBBNum = byteToBlockMap[biStart + offset]; 1306 workStk = 1307 processBranchBB(brBBNum, 1308 currBBStkTop, 1309 currBBMap, 1310 currBBStkEmpty, 1311 inJSRSub, 1312 bbMaps, 1313 blockStkTop, 1314 currPendingRET, 1315 bbPendingRETs, 1316 workStk); 1317 processNextBlock = false; 1318 break; 1319 } 1320 case JBC_tableswitch: { 1321 currBBStkTop--; 1322 bcodes.alignSwitch(); 1323 // get default offset and process branch to default branch point 1324 int def = bcodes.getDefaultSwitchOffset(); 1325 workStk = 1326 processBranchBB(byteToBlockMap[biStart + def], 1327 currBBStkTop, 1328 currBBMap, 1329 currBBStkEmpty, 1330 inJSRSub, 1331 bbMaps, 1332 blockStkTop, 1333 currPendingRET, 1334 bbPendingRETs, 1335 workStk); 1336 1337 int low = bcodes.getLowSwitchValue(); 1338 int high = bcodes.getHighSwitchValue(); 1339 int n = high - low + 1; 1340 // generate labels for offsets 1341 for (int k = 0; k < n; k++) { 1342 int offset = bcodes.getTableSwitchOffset(k); 1343 workStk = 1344 processBranchBB(byteToBlockMap[biStart + offset], 1345 currBBStkTop, 1346 currBBMap, 1347 currBBStkEmpty, 1348 inJSRSub, 1349 bbMaps, 1350 blockStkTop, 1351 currPendingRET, 1352 bbPendingRETs, 1353 workStk); 1354 } 1355 bcodes.skipTableSwitchOffsets(n); 1356 processNextBlock = false; 1357 break; 1358 } 1359 case JBC_lookupswitch: { 1360 currBBStkTop--; 1361 bcodes.alignSwitch(); 1362 // get default offset and process branch to default branch point 1363 int def = bcodes.getDefaultSwitchOffset(); 1364 workStk = 1365 processBranchBB(byteToBlockMap[biStart + def], 1366 currBBStkTop, 1367 currBBMap, 1368 currBBStkEmpty, 1369 inJSRSub, 1370 bbMaps, 1371 blockStkTop, 1372 currPendingRET, 1373 bbPendingRETs, 1374 workStk); 1375 1376 int npairs = bcodes.getSwitchLength(); 1377 1378 // generate label for each offset in table 1379 for (int k = 0; k < npairs; k++) { 1380 int offset = bcodes.getLookupSwitchOffset(k); 1381 workStk = 1382 processBranchBB(byteToBlockMap[biStart + offset], 1383 currBBStkTop, 1384 currBBMap, 1385 currBBStkEmpty, 1386 inJSRSub, 1387 bbMaps, 1388 blockStkTop, 1389 currPendingRET, 1390 bbPendingRETs, 1391 workStk); 1392 } 1393 bcodes.skipLookupSwitchPairs(npairs); 1394 processNextBlock = false; 1395 break; 1396 } 1397 1398 case JBC_jsr: { 1399 processNextBlock = false; 1400 int offset = bcodes.getBranchOffset(); 1401 if (!inJSRSub) { 1402 referenceMaps.recordStkMap(biStart, currBBMap, currBBStkEmpty, blockSeen[currBBNum]); 1403 } else { 1404 referenceMaps.recordJSRSubroutineMap(biStart, 1405 currBBMap, 1406 currBBStkEmpty, 1407 currPendingRET.returnAddressLocation, 1408 blockSeen[currBBNum]); 1409 } 1410 currBBStkTop++; 1411 currBBMap[currBBStkTop] = RETURN_ADDRESS; 1412 workStk = 1413 processJSR(byteToBlockMap[biStart], 1414 biStart + offset, 1415 byteToBlockMap[biStart + offset], 1416 byteToBlockMap[biStart + 3], 1417 bbMaps, 1418 currBBStkTop, 1419 currBBMap, 1420 currBBStkEmpty, 1421 blockStkTop, 1422 bbPendingRETs, 1423 currPendingRET, 1424 JSRSubs, 1425 workStk); 1426 break; 1427 } 1428 case JBC_jsr_w: { 1429 processNextBlock = false; 1430 int offset = bcodes.getWideBranchOffset(); 1431 if (!inJSRSub) { 1432 referenceMaps.recordStkMap(biStart, currBBMap, currBBStkEmpty, blockSeen[currBBNum]); 1433 } else { 1434 referenceMaps.recordJSRSubroutineMap(biStart, 1435 currBBMap, 1436 currBBStkEmpty, 1437 currPendingRET.returnAddressLocation, 1438 blockSeen[currBBNum]); 1439 } 1440 currBBStkTop++; 1441 currBBMap[currBBStkTop] = RETURN_ADDRESS; 1442 workStk = 1443 processJSR(byteToBlockMap[biStart], 1444 biStart + offset, 1445 byteToBlockMap[biStart + offset], 1446 byteToBlockMap[biStart + 5], 1447 bbMaps, 1448 currBBStkTop, 1449 currBBMap, 1450 currBBStkEmpty, 1451 blockStkTop, 1452 bbPendingRETs, 1453 currPendingRET, 1454 JSRSubs, 1455 workStk); 1456 break; 1457 } 1458 case JBC_ret: { 1459 int index = bcodes.getLocalNumber(); 1460 1461 // Can not be used again as a return addr. 1462 // 1463 currBBMap[index] = SET_TO_NONREFERENCE; 1464 processNextBlock = false; 1465 int subStart = currPendingRET.JSRSubStartByteIndex; 1466 int k; 1467 for (k = 0; k < JSRSubNext; k++) { 1468 if (JSRSubs[k].subroutineByteCodeStart == subStart) { 1469 JSRSubs[k].newEndMaps(currBBMap, currBBStkTop); 1470 break; 1471 } 1472 } 1473 1474 boolean JSRisinJSRSub = bbPendingRETs[currPendingRET.JSRBBNum] != null; 1475 workStk = 1476 computeJSRNextMaps(currPendingRET.JSRNextBBNum, 1477 currBBMap.length, 1478 k, 1479 JSRisinJSRSub, 1480 bbMaps, 1481 blockStkTop, 1482 JSRSubs, 1483 currBBStkEmpty, 1484 workStk); 1485 if (JSRisinJSRSub && bbPendingRETs[currPendingRET.JSRNextBBNum] == null) { 1486 bbPendingRETs[currPendingRET.JSRNextBBNum] = 1487 new PendingRETInfo(bbPendingRETs[currPendingRET.JSRBBNum]); 1488 } 1489 break; 1490 } 1491 case JBC_invokevirtual: 1492 case JBC_invokespecial: { 1493 MethodReference target = bcodes.getMethodReference(); 1494 currBBStkTop = 1495 processInvoke(target, 1496 biStart, 1497 currBBStkTop, 1498 currBBMap, 1499 false, 1500 inJSRSub, 1501 referenceMaps, 1502 currPendingRET, 1503 blockSeen[currBBNum], 1504 currBBStkEmpty); 1505 break; 1506 } 1507 case JBC_invokeinterface: { 1508 MethodReference target = bcodes.getMethodReference(); 1509 bcodes.alignInvokeInterface(); 1510 currBBStkTop = 1511 processInvoke(target, 1512 biStart, 1513 currBBStkTop, 1514 currBBMap, 1515 false, 1516 inJSRSub, 1517 referenceMaps, 1518 currPendingRET, 1519 blockSeen[currBBNum], 1520 currBBStkEmpty); 1521 break; 1522 } 1523 case JBC_invokestatic: { 1524 MethodReference target = bcodes.getMethodReference(); 1525 currBBStkTop = 1526 processInvoke(target, 1527 biStart, 1528 currBBStkTop, 1529 currBBMap, 1530 true, 1531 inJSRSub, 1532 referenceMaps, 1533 currPendingRET, 1534 blockSeen[currBBNum], 1535 currBBStkEmpty); 1536 break; 1537 } 1538 1539 case JBC_ireturn: 1540 case JBC_lreturn: 1541 case JBC_freturn: 1542 case JBC_dreturn: 1543 case JBC_areturn: 1544 case JBC_return: { 1545 if (VM.UseEpilogueYieldPoints || method.isSynchronized()) { 1546 referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]); 1547 } 1548 processNextBlock = false; 1549 break; 1550 } 1551 1552 case JBC_getstatic: { 1553 // Register the reference map (could cause dynamic linking) 1554 if (!inJSRSub) { 1555 referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]); 1556 } else { 1557 referenceMaps.recordJSRSubroutineMap(biStart, 1558 currBBMap, 1559 currBBStkTop, 1560 currPendingRET.returnAddressLocation, 1561 blockSeen[currBBNum]); 1562 } 1563 1564 TypeReference fieldType = bcodes.getFieldReference().getFieldContentsType(); 1565 currBBMap[++currBBStkTop] = fieldType.isPrimitiveType() ? NON_REFERENCE : REFERENCE; 1566 if (fieldType.getStackWords() == 2) { 1567 currBBMap[++currBBStkTop] = NON_REFERENCE; 1568 } 1569 break; 1570 } 1571 case JBC_putstatic: { 1572 // Register the reference map (could cause dynamic linking) 1573 if (!inJSRSub) { 1574 referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]); 1575 } else { 1576 referenceMaps.recordJSRSubroutineMap(biStart, 1577 currBBMap, 1578 currBBStkTop, 1579 currPendingRET.returnAddressLocation, 1580 blockSeen[currBBNum]); 1581 } 1582 TypeReference fieldType = bcodes.getFieldReference().getFieldContentsType(); 1583 currBBStkTop--; 1584 if (fieldType.getStackWords() == 2) { 1585 currBBStkTop--; 1586 } 1587 break; 1588 } 1589 case JBC_getfield: { 1590 TypeReference fieldType = bcodes.getFieldReference().getFieldContentsType(); 1591 // Register the reference map (could cause dynamic linking..if so there will be a NPE, but the linking happens first.) 1592 if (!inJSRSub) { 1593 referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]); 1594 } else { 1595 referenceMaps.recordJSRSubroutineMap(biStart, 1596 currBBMap, 1597 currBBStkTop, 1598 currPendingRET.returnAddressLocation, 1599 blockSeen[currBBNum]); 1600 } 1601 currBBStkTop--; // pop object pointer 1602 currBBMap[++currBBStkTop] = fieldType.isPrimitiveType() ? NON_REFERENCE : REFERENCE; 1603 if (fieldType.getStackWords() == 2) { 1604 currBBMap[++currBBStkTop] = NON_REFERENCE; 1605 } 1606 break; 1607 } 1608 case JBC_putfield: { 1609 TypeReference fieldType = bcodes.getFieldReference().getFieldContentsType(); 1610 // Register the reference map with the values still on the stack 1611 // note: putfield could result in a call to the classloader 1612 if (!inJSRSub) { 1613 referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]); 1614 } else { 1615 referenceMaps.recordJSRSubroutineMap(biStart, 1616 currBBMap, 1617 currBBStkTop, 1618 currPendingRET.returnAddressLocation, 1619 blockSeen[currBBNum]); 1620 } 1621 currBBStkTop -= 2; // remove objectref and one value 1622 if (fieldType.getStackWords() == 2) { 1623 currBBStkTop--; 1624 } 1625 break; 1626 } 1627 case JBC_checkcast: { 1628 if (!inJSRSub) { 1629 referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]); 1630 } else { 1631 referenceMaps.recordJSRSubroutineMap(biStart, 1632 currBBMap, 1633 currBBStkTop, 1634 currPendingRET.returnAddressLocation, 1635 blockSeen[currBBNum]); 1636 } 1637 bcodes.skipInstruction(); 1638 break; 1639 } 1640 case JBC_instanceof: { 1641 if (!inJSRSub) { 1642 referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]); 1643 } else { 1644 referenceMaps.recordJSRSubroutineMap(biStart, 1645 currBBMap, 1646 currBBStkTop, 1647 currPendingRET.returnAddressLocation, 1648 blockSeen[currBBNum]); 1649 } 1650 currBBMap[currBBStkTop] = NON_REFERENCE; 1651 bcodes.skipInstruction(); 1652 break; 1653 } 1654 case JBC_new: { 1655 if (!inJSRSub) { 1656 referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]); 1657 } else { 1658 referenceMaps.recordJSRSubroutineMap(biStart, 1659 currBBMap, 1660 currBBStkTop, 1661 currPendingRET.returnAddressLocation, 1662 blockSeen[currBBNum]); 1663 } 1664 currBBStkTop++; 1665 currBBMap[currBBStkTop] = REFERENCE; 1666 bcodes.skipInstruction(); 1667 break; 1668 } 1669 1670 // For the <x>aload instructions the map is needed in case GC occurs 1671 // while the array index check is taking place. Stack has not been 1672 // altered yet. 1673 case JBC_iaload: 1674 case JBC_faload: 1675 case JBC_baload: 1676 case JBC_caload: 1677 case JBC_saload: { 1678 if (!inJSRSub) { 1679 referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]); 1680 } else { 1681 referenceMaps.recordJSRSubroutineMap(biStart, 1682 currBBMap, 1683 currBBStkTop, 1684 currPendingRET.returnAddressLocation, 1685 blockSeen[currBBNum]); 1686 } 1687 currBBStkTop--; 1688 currBBMap[currBBStkTop] = NON_REFERENCE; 1689 break; 1690 } 1691 case JBC_laload: 1692 case JBC_daload: { 1693 if (!inJSRSub) { 1694 referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]); 1695 } else { 1696 referenceMaps.recordJSRSubroutineMap(biStart, 1697 currBBMap, 1698 currBBStkTop, 1699 currPendingRET.returnAddressLocation, 1700 blockSeen[currBBNum]); 1701 } 1702 currBBMap[currBBStkTop - 1] = NON_REFERENCE; 1703 break; 1704 } 1705 1706 case JBC_aaload: { 1707 if (!inJSRSub) { 1708 referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]); 1709 } else { 1710 referenceMaps.recordJSRSubroutineMap(biStart, 1711 currBBMap, 1712 currBBStkTop, 1713 currPendingRET.returnAddressLocation, 1714 blockSeen[currBBNum]); 1715 } 1716 currBBStkTop--; 1717 break; 1718 } 1719 1720 // For the <x>astore instructions the map recorded is in case GC occurs 1721 // during the array index bounds check or the arraystore check (for aastore). 1722 // Stack has not been modified at this point. 1723 case JBC_iastore: 1724 case JBC_fastore: 1725 case JBC_aastore: 1726 case JBC_bastore: 1727 case JBC_castore: 1728 case JBC_sastore: { 1729 if (!inJSRSub) { 1730 referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]); 1731 } else { 1732 referenceMaps.recordJSRSubroutineMap(biStart, 1733 currBBMap, 1734 currBBStkTop, 1735 currPendingRET.returnAddressLocation, 1736 blockSeen[currBBNum]); 1737 } 1738 currBBStkTop = currBBStkTop - 3; 1739 break; 1740 } 1741 case JBC_lastore: 1742 case JBC_dastore: { 1743 if (!inJSRSub) { 1744 referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]); 1745 } else { 1746 referenceMaps.recordJSRSubroutineMap(biStart, 1747 currBBMap, 1748 currBBStkTop, 1749 currPendingRET.returnAddressLocation, 1750 blockSeen[currBBNum]); 1751 } 1752 currBBStkTop = currBBStkTop - 4; 1753 break; 1754 } 1755 1756 case JBC_newarray: 1757 case JBC_anewarray: { 1758 if (!inJSRSub) { 1759 referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]); 1760 } else { 1761 referenceMaps.recordJSRSubroutineMap(biStart, 1762 currBBMap, 1763 currBBStkTop, 1764 currPendingRET.returnAddressLocation, 1765 blockSeen[currBBNum]); 1766 } 1767 currBBMap[currBBStkTop] = REFERENCE; 1768 bcodes.skipInstruction(); 1769 break; 1770 } 1771 1772 case JBC_multianewarray: { 1773 bcodes.getTypeReference(); 1774 int dim = bcodes.getArrayDimension(); 1775 if (!inJSRSub) { 1776 referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]); 1777 } else { 1778 referenceMaps.recordJSRSubroutineMap(biStart, 1779 currBBMap, 1780 currBBStkTop, 1781 currPendingRET.returnAddressLocation, 1782 blockSeen[currBBNum]); 1783 } 1784 currBBStkTop = currBBStkTop - dim + 1; 1785 currBBMap[currBBStkTop] = REFERENCE; 1786 break; 1787 } 1788 case JBC_arraylength: { 1789 currBBMap[currBBStkTop] = NON_REFERENCE; 1790 break; 1791 } 1792 case JBC_athrow: { 1793 if (!inJSRSub) { 1794 referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]); 1795 } else { 1796 referenceMaps.recordJSRSubroutineMap(biStart, 1797 currBBMap, 1798 currBBStkTop, 1799 currPendingRET.returnAddressLocation, 1800 blockSeen[currBBNum]); 1801 } 1802 currBBStkTop = currBBStkEmpty + 1; 1803 currBBMap[currBBStkTop] = REFERENCE; 1804 processNextBlock = false; 1805 break; 1806 } 1807 case JBC_monitorenter: 1808 case JBC_monitorexit: { 1809 currBBStkTop--; 1810 if (!inJSRSub) { 1811 referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]); 1812 } else { 1813 referenceMaps.recordJSRSubroutineMap(biStart, 1814 currBBMap, 1815 currBBStkTop, 1816 currPendingRET.returnAddressLocation, 1817 blockSeen[currBBNum]); 1818 } 1819 break; 1820 } 1821 1822 case JBC_wide: { 1823 int widecode = bcodes.getWideOpcode(); 1824 int index = bcodes.getWideLocalNumber(); 1825 switch (widecode) { 1826 case JBC_iload: 1827 case JBC_fload: { 1828 currBBStkTop++; 1829 currBBMap[currBBStkTop] = NON_REFERENCE; 1830 break; 1831 } 1832 1833 case JBC_lload: 1834 case JBC_dload: { 1835 currBBStkTop++; 1836 currBBMap[currBBStkTop] = NON_REFERENCE; 1837 currBBStkTop++; 1838 currBBMap[currBBStkTop] = NON_REFERENCE; 1839 break; 1840 } 1841 1842 case JBC_aload: { 1843 currBBStkTop++; 1844 currBBMap[currBBStkTop] = currBBMap[index]; 1845 break; 1846 } 1847 1848 case JBC_istore: { 1849 if (!inJSRSub) { 1850 currBBMap[index] = NON_REFERENCE; 1851 } else { 1852 currBBMap[index] = SET_TO_NONREFERENCE; 1853 } 1854 currBBStkTop--; 1855 localTypes[index] |= INT_TYPE; 1856 break; 1857 } 1858 1859 case JBC_fstore: { 1860 if (!inJSRSub) { 1861 currBBMap[index] = NON_REFERENCE; 1862 } else { 1863 currBBMap[index] = SET_TO_NONREFERENCE; 1864 } 1865 currBBStkTop--; 1866 localTypes[index] |= FLOAT_TYPE; 1867 break; 1868 } 1869 1870 case JBC_lstore: { 1871 if (!inJSRSub) { 1872 currBBMap[index] = NON_REFERENCE; 1873 currBBMap[index + 1] = NON_REFERENCE; 1874 } else { 1875 currBBMap[index] = SET_TO_NONREFERENCE; 1876 currBBMap[index + 1] = SET_TO_NONREFERENCE; 1877 } 1878 currBBStkTop = currBBStkTop - 2; 1879 localTypes[index] |= LONG_TYPE; 1880 break; 1881 } 1882 1883 case JBC_dstore: { 1884 if (!inJSRSub) { 1885 currBBMap[index] = NON_REFERENCE; 1886 currBBMap[index + 1] = NON_REFERENCE; 1887 } else { 1888 currBBMap[index] = SET_TO_NONREFERENCE; 1889 currBBMap[index + 1] = SET_TO_NONREFERENCE; 1890 } 1891 currBBStkTop = currBBStkTop - 2; 1892 localTypes[index] |= DOUBLE_TYPE; 1893 break; 1894 } 1895 1896 case JBC_astore: { 1897 currBBMap[index] = currBBMap[currBBStkTop]; 1898 currBBStkTop--; 1899 localTypes[index] |= ADDRESS_TYPE; 1900 break; 1901 } 1902 1903 case JBC_iinc: { 1904 bcodes.getWideIncrement(); 1905 break; 1906 } 1907 case JBC_ret: { 1908 // Can not be used again as a return addr. 1909 // 1910 currBBMap[index] = SET_TO_NONREFERENCE; 1911 processNextBlock = false; 1912 int subStart = currPendingRET.JSRSubStartByteIndex; 1913 int k; 1914 for (k = 0; k < JSRSubNext; k++) { 1915 if (JSRSubs[k].subroutineByteCodeStart == subStart) { 1916 JSRSubs[k].newEndMaps(currBBMap, currBBStkTop); 1917 break; 1918 } 1919 } 1920 1921 boolean JSRisinJSRSub = bbPendingRETs[currPendingRET.JSRBBNum] != null; 1922 workStk = 1923 computeJSRNextMaps(currPendingRET.JSRNextBBNum, 1924 currBBMap.length, 1925 k, 1926 JSRisinJSRSub, 1927 bbMaps, 1928 blockStkTop, 1929 JSRSubs, 1930 currBBStkEmpty, 1931 workStk); 1932 if (JSRisinJSRSub && bbPendingRETs[currPendingRET.JSRNextBBNum] == null) { 1933 bbPendingRETs[currPendingRET.JSRNextBBNum] = 1934 new PendingRETInfo(bbPendingRETs[currPendingRET.JSRBBNum]); 1935 } 1936 break; 1937 } 1938 default: // switch on widecode 1939 if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); 1940 } 1941 break; 1942 } // case JBC_wide: 1943 1944 default: { 1945 VM.sysFail("Unknown opcode:" + opcode); 1946 } 1947 1948 } // end switch (opcode) 1949 1950 } // for start to end 1951 1952 blockSeen[currBBNum] = true; 1953 1954 if (processNextBlock) { 1955 short fallThruBBNum = byteToBlockMap[bcodes.index()]; 1956 workStk = 1957 processBranchBB(fallThruBBNum, 1958 currBBStkTop, 1959 currBBMap, 1960 currBBStkEmpty, 1961 inJSRSub, 1962 bbMaps, 1963 blockStkTop, 1964 currPendingRET, 1965 bbPendingRETs, 1966 workStk); 1967 1968 } 1969 1970 // if the work stack is empty, we must have processed the whole program 1971 // we can now process the try handlers if there are any. 1972 // If a handler doesn't have a starting map already, then the associated try 1973 // has not been processed yet. The try and the handler must be in another 1974 // handler, so that handler must be processed first. 1975 // If one handler is in the try block associated with a second handler, then 1976 // the second handler must not be processed until the first handler has been. 1977 // 1978 if ((workStkTop == -1) && !handlersAllDone) { 1979 int i; 1980 for (i = 0; i < tryHandlerLength; i++) { 1981 // already processed this handler, or, haven't seen the 1982 // associated try block yet so no starting map is available, 1983 // the try block must be in one of the other handlers 1984 if (!handlerProcessed[i] && bbMaps[byteToBlockMap[tryHandlerPC[i]]] != null) break; 1985 } 1986 if (i == tryHandlerLength) { 1987 handlersAllDone = true; 1988 } else { 1989 int considerIndex = i; 1990 1991 while (i != tryHandlerLength) { 1992 int tryStart = tryStartPC[considerIndex]; 1993 int tryEnd = tryEndPC[considerIndex]; 1994 1995 for (i = 0; i < tryHandlerLength; i++) { 1996 // If the handler handles itself, then make the wild assumption 1997 // that the local variables will be the same......is this reasonable?? 1998 // This is a patch to deal with defect 3046. 1999 // I'm not entirely convinced this is right, but don't know what else we can do. --dave 2000 if (i == considerIndex) continue; 2001 2002 // For every handler that has not yet been processed, 2003 // but already has a known starting map, 2004 // make sure it is not in the try block part of the handler 2005 // we are considering working on. 2006 if (!handlerProcessed[i] && 2007 tryStart <= tryHandlerPC[i] && 2008 tryHandlerPC[i] < tryEnd && 2009 bbMaps[byteToBlockMap[tryHandlerPC[i]]] != null) { 2010 break; 2011 } 2012 } 2013 2014 if (i != tryHandlerLength) { 2015 considerIndex = i; 2016 } 2017 } 2018 2019 short blockNum = byteToBlockMap[tryHandlerPC[considerIndex]]; 2020 handlerProcessed[considerIndex] = true; 2021 workStk = addToWorkStk(blockNum, workStk); 2022 } 2023 } 2024 2025 } // while workStk not empty 2026 2027 // Indicate that any temporaries can be freed 2028 referenceMaps.recordingComplete(); 2029 2030 } 2031 2032 // -------------------- Private Instance Methods -------------------- 2033 2034 private short[] addToWorkStk(short blockNum, short[] workStk) { 2035 workStkTop++; 2036 if (workStkTop >= workStk.length) { 2037 short[] biggerQ = new short[workStk.length + 20]; 2038 for (int i = 0; i < workStk.length; i++) { 2039 biggerQ[i] = workStk[i]; 2040 } 2041 workStk = biggerQ; 2042 biggerQ = null; 2043 } 2044 workStk[workStkTop] = blockNum; 2045 return workStk; 2046 } 2047 2048 private short[] addUniqueToWorkStk(short blockNum, short[] workStk) { 2049 if ((workStkTop + 1) >= workStk.length) { 2050 short[] biggerQ = new short[workStk.length + 20]; 2051 boolean matchFound = false; 2052 for (int i = 0; i < workStk.length; i++) { 2053 biggerQ[i] = workStk[i]; 2054 matchFound = (workStk[i] == blockNum); 2055 } 2056 workStk = biggerQ; 2057 biggerQ = null; 2058 if (matchFound) return workStk; 2059 } else { 2060 for (int i = 0; i <= workStkTop; i++) { 2061 if (workStk[i] == blockNum) { 2062 return workStk; 2063 } 2064 } 2065 } 2066 workStkTop++; 2067 workStk[workStkTop] = blockNum; 2068 return workStk; 2069 } 2070 2071 private short[] processBranchBB(short brBBNum, int currBBStkTop, byte[] currBBMap, int currBBStkEmpty, 2072 boolean inJSRSub, byte[][] bbMaps, int[] blockStkTop, 2073 PendingRETInfo currPendingRET, PendingRETInfo[] bbPendingRETs, 2074 short[] workStk) { 2075 2076 short[] newworkStk = workStk; 2077 2078 // If the destination block doesn't already have a map, then use this 2079 // map as its map and add it to the work stack 2080 2081 if (bbMaps[brBBNum] == null) { 2082 bbMaps[brBBNum] = new byte[currBBMap.length]; 2083 for (int i = 0; i <= currBBStkTop; i++) { 2084 bbMaps[brBBNum][i] = currBBMap[i]; 2085 } 2086 blockStkTop[brBBNum] = currBBStkTop; 2087 newworkStk = addToWorkStk(brBBNum, workStk); 2088 if (inJSRSub) { 2089 bbPendingRETs[brBBNum] = new PendingRETInfo(currPendingRET); 2090 } 2091 2092 } else { 2093 // If the destination block already has a map, then check if there are any 2094 // new NONReference values. Note that a new Reference value, will not change an 2095 // existing NONReference value to Reference, as there must be a valid path where 2096 // the variable is not a reference (and not "null" - which is treated as a 2097 // reference) so the variable is unusable. 2098 // 2099 int mismatchAt = -1; 2100 byte[] blockMap = bbMaps[brBBNum]; 2101 for (int i = 0; i <= currBBStkEmpty; i++) { 2102 if ((currBBMap[i] != blockMap[i]) && (blockMap[i] != NON_REFERENCE)) { 2103 mismatchAt = i; 2104 break; 2105 } 2106 } 2107 if (mismatchAt == -1) { 2108 return newworkStk; // no further work to be done 2109 } else { 2110 newworkStk = addUniqueToWorkStk(brBBNum, workStk); 2111 for (int i = mismatchAt; i <= currBBStkEmpty; i++) { 2112 if (!inJSRSub) { 2113 blockMap[i] = (blockMap[i] == currBBMap[i]) ? blockMap[i] : NON_REFERENCE; 2114 } else { 2115 blockMap[i] = (blockMap[i] == currBBMap[i]) ? blockMap[i] : SET_TO_NONREFERENCE; 2116 } 2117 } 2118 } 2119 } 2120 return newworkStk; 2121 } 2122 2123 private int processInvoke(MethodReference target, int byteindex, int currBBStkTop, byte[] currBBMap, 2124 boolean isStatic, boolean inJSRSub, ReferenceMaps referenceMaps, 2125 PendingRETInfo currPendingRET, boolean blockSeen, int currBBStkEmpty) { 2126 boolean skipRecordingReferenceMap = false; 2127 boolean popParams = true; 2128 2129 if (target.getType().isMagicType()) { 2130 boolean producesCall = BaselineCompiler.checkForActualCall(target); 2131 if (producesCall) { 2132 // register a map, but do NOT include any of the parameters to the call. 2133 // Chances are what appear to be parameters are not parameters to 2134 // the routine that is actually called. 2135 // In any case, the callee routine will map its parameters 2136 // and we don't have to double map because we are positive that this can't be 2137 // a dynamically linked call site. 2138 for (TypeReference parameterType : target.getParameterTypes()) { 2139 currBBStkTop -= parameterType.getStackWords(); 2140 } 2141 if (!isStatic) currBBStkTop--; // pop implicit "this" object reference 2142 popParams = false; 2143 } else { 2144 skipRecordingReferenceMap = true; 2145 } 2146 } 2147 2148 if (!skipRecordingReferenceMap) { 2149 // Register the reference map, including the arguments on the stack for this call 2150 // (unless it is a magic call whose params we have popped above). 2151 if (!inJSRSub) { 2152 referenceMaps.recordStkMap(byteindex, currBBMap, currBBStkTop, blockSeen); 2153 } else { 2154 referenceMaps.recordJSRSubroutineMap(byteindex, 2155 currBBMap, 2156 currBBStkTop, 2157 currPendingRET.returnAddressLocation, 2158 blockSeen); 2159 } 2160 } 2161 2162 if (popParams) { 2163 TypeReference[] parameterTypes = target.getParameterTypes(); 2164 int pTypesLength = parameterTypes.length; 2165 2166 // Pop the arguments for this call off the stack; 2167 for (int i = 0; i < pTypesLength; i++) { 2168 currBBStkTop -= parameterTypes[i].getStackWords(); 2169 } 2170 2171 if (!isStatic) { 2172 currBBStkTop--; // pop implicit "this" object reference 2173 } 2174 } 2175 2176 // Add the return value to the stack 2177 TypeReference returnType = target.getReturnType(); 2178 if (!returnType.isVoidType()) { 2179 // a non-void return value 2180 currBBMap[++currBBStkTop] = returnType.isReferenceType() ? REFERENCE : NON_REFERENCE; 2181 if (returnType.getStackWords() == 2) { 2182 currBBMap[++currBBStkTop] = NON_REFERENCE; 2183 } 2184 } 2185 2186 // Return updated stack top 2187 return currBBStkTop; 2188 } 2189 2190 private short[] processJSR(int JSRBBNum, int JSRSubStartIndex, short brBBNum, short nextBBNum, byte[][] bbMaps, 2191 int currBBStkTop, byte[] currBBMap, int currBBStkEmpty, int[] blockStkTop, 2192 PendingRETInfo[] bbPendingRETs, PendingRETInfo currPendingRET, 2193 JSRSubroutineInfo[] JSRSubs, short[] workStk) { 2194 short[] newworkStk = workStk; 2195 2196 // If the destination block doesn't already have a map, then use this map to build 2197 // the stack portion of the reference map and add the block to the work stack. 2198 // The locals maps should be started with all zeros. 2199 2200 if (bbMaps[brBBNum] == null) { 2201 bbMaps[brBBNum] = new byte[currBBMap.length]; 2202 for (int i = currBBStkEmpty + 1; i <= currBBStkTop; i++) { 2203 bbMaps[brBBNum][i] = currBBMap[i]; 2204 } 2205 blockStkTop[brBBNum] = currBBStkTop; 2206 newworkStk = addToWorkStk(brBBNum, workStk); 2207 2208 bbPendingRETs[brBBNum] = new PendingRETInfo(JSRSubStartIndex, JSRBBNum, currBBStkTop, nextBBNum); 2209 JSRSubs[JSRSubNext++] = new JSRSubroutineInfo(JSRSubStartIndex, currBBMap, currBBStkEmpty); 2210 } else { 2211 // If the JSR subroutine block already has a map, then locate the ending map 2212 // and use that to determine the map of the next block. No need to reprocess 2213 // the JSR subroutine 2214 int matchingJSRStart; 2215 for (matchingJSRStart = 0; matchingJSRStart < JSRSubNext; matchingJSRStart++) { 2216 if (JSRSubs[matchingJSRStart].subroutineByteCodeStart == JSRSubStartIndex) { 2217 JSRSubs[matchingJSRStart].newStartMaps(currBBMap); 2218 break; 2219 } 2220 } 2221 2222 boolean JSRisinJSRSub = (currPendingRET != null); 2223 newworkStk = 2224 computeJSRNextMaps(nextBBNum, 2225 currBBMap.length, 2226 matchingJSRStart, 2227 JSRisinJSRSub, 2228 bbMaps, 2229 blockStkTop, 2230 JSRSubs, 2231 currBBStkEmpty, 2232 workStk); 2233 if (JSRisinJSRSub && bbPendingRETs[nextBBNum] == null) { 2234 bbPendingRETs[nextBBNum] = new PendingRETInfo(currPendingRET); 2235 } 2236 } 2237 2238 return newworkStk; 2239 } 2240 2241 private short[] computeJSRNextMaps(short nextBBNum, int maplength, int JSRSubIndex, boolean JSRisinJSRSub, 2242 byte[][] bbMaps, int[] blockStkTop, JSRSubroutineInfo[] JSRSubs, 2243 int currBBStkEmpty, short[] workStk) { 2244 short[] newworkStk = workStk; 2245 2246 // Calculate the new map for the block starting at the instruction after the 2247 // JSR instruction (this is the block nextBBNum) 2248 byte[] refMap; 2249 2250 refMap = JSRSubs[JSRSubIndex].computeResultingMaps(maplength); 2251 2252 // If no map is computed, then the JSR Subroutine must have ended in a return 2253 // Do NOT add the next block to the work Q. 2254 if (refMap == null) { 2255 return newworkStk; 2256 } 2257 2258 // If the block after the JSR instruction does not have a map, then the newly 2259 // computed map should be used and the block should be added to the workStk. 2260 if (bbMaps[nextBBNum] == null) { 2261 bbMaps[nextBBNum] = refMap; 2262 blockStkTop[nextBBNum] = JSRSubs[JSRSubIndex].endReferenceTop; 2263 newworkStk = addToWorkStk(nextBBNum, workStk); 2264 } else { 2265 // The block after the JSR instruction already has a reference map. 2266 // Check if the computed map matches the previous map. If so, no further 2267 // work needed. 2268 int mismatchAt = -1; 2269 byte[] blockMap = bbMaps[nextBBNum]; 2270 for (int i = 0; i <= currBBStkEmpty; i++) { 2271 if ((refMap[i] != blockMap[i]) && (blockMap[i] != NON_REFERENCE)) { 2272 mismatchAt = i; 2273 break; 2274 } 2275 } 2276 if (mismatchAt == -1) { 2277 return newworkStk; // no further work to be done 2278 } else { 2279 newworkStk = addUniqueToWorkStk(nextBBNum, workStk); 2280 for (int i = mismatchAt; i <= currBBStkEmpty; i++) { 2281 if (!JSRisinJSRSub) { 2282 blockMap[i] = (blockMap[i] == refMap[i]) ? blockMap[i] : NON_REFERENCE; 2283 } else { 2284 blockMap[i] = (blockMap[i] == refMap[i]) ? blockMap[i] : SET_TO_NONREFERENCE; 2285 } 2286 } 2287 } 2288 } 2289 return newworkStk; 2290 } 2291 2292 /** 2293 * For each of the reachable handlers (catch blocks) from the try block, track that 2294 * the local variable given by the index with 1 or 2 words, has been set to a 2295 * non reference value (eg int, float, etc) 2296 * 2297 * @param localVariable Variable index in the map 2298 * @param wordCount 2 for doubles and longs, 1 otherwise 2299 * @param reachableHandlerBBNums The array with all the block numbers of 2300 * reachable handlers 2301 * @param reachableHandlerCount 0 through <code>reachableHandlerCount 2302 * - 1 </code> will all be valid 2303 * array indices 2304 * @param inJSRSub TODO Document ME XXX 2305 * @param bbMaps TODO Document ME XXX 2306 */ 2307 private void setHandlersMapsNonRef(int localVariable, PrimitiveSize wordCount, int[] reachableHandlerBBNums, 2308 int reachableHandlerCount, boolean inJSRSub, byte[][] bbMaps) { 2309 if (!inJSRSub) { 2310 for (int i = 0; i < reachableHandlerCount; i++) { 2311 bbMaps[reachableHandlerBBNums[i]][localVariable] = NON_REFERENCE; 2312 if (wordCount == PrimitiveSize.DOUBLEWORD) { 2313 bbMaps[reachableHandlerBBNums[i]][localVariable + 1] = NON_REFERENCE; 2314 } 2315 } 2316 } else { 2317 for (int i = 0; i < reachableHandlerCount; i++) { 2318 bbMaps[reachableHandlerBBNums[i]][localVariable] = SET_TO_NONREFERENCE; 2319 if (wordCount == PrimitiveSize.DOUBLEWORD) { 2320 bbMaps[reachableHandlerBBNums[i]][localVariable + 1] = SET_TO_NONREFERENCE; 2321 } 2322 } 2323 } 2324 2325 } 2326 2327 /** 2328 * For each of the reachable handlers (catch blocks) from the try block, 2329 * track that 2330 * the local variable given by the index, has been set to a reference value. 2331 * Only call this method if the try block is in a JSR subroutine. 2332 * If a non-reference value becomes a reference value, 2333 * then it can not be used as 2334 * as reference value within the handler 2335 * (there is a path to the handler where the 2336 * value is not a reference) so mark the local variable as 2337 * a non-reference if we 2338 * are tracking the difference maps (for a JSR subroutine). 2339 * 2340 * @param localVariable Variable index in the map 2341 * @param reachableHandlerBBNums The array with all the block numbers of 2342 * reachable handlers 2343 * @param reachableHandlerCount 0 through <code>reachableHandlerCount 2344 * - 1 </code> will all be valid 2345 * array indices 2346 * @param bbMaps TODO Document ME XXX 2347 */ 2348 private void setHandlersMapsRef(int localVariable, int[] reachableHandlerBBNums, int reachableHandlerCount, 2349 byte[][] bbMaps) { 2350 for (int i = 0; i < reachableHandlerCount; i++) { 2351 if (bbMaps[reachableHandlerBBNums[i]][localVariable] != REFERENCE) { 2352 bbMaps[reachableHandlerBBNums[i]][localVariable] = SET_TO_NONREFERENCE; 2353 } 2354 } 2355 } 2356 2357 /** 2358 * For each of the reachable handlers (catch blocks) 2359 * from the try block, track that 2360 * the local variable given by the index, 2361 * has been set to a return address value. 2362 * Only call this routine within a JSR subroutine. 2363 * If a non-reference, or reference value becomes a return address value, 2364 * then it 2365 * cannot be used as any of these values within the handler 2366 * (there is a path to 2367 * the handler where the value is not an internal reference, 2368 * and a path where it 2369 * is an internal reference) so mark the local variable as a 2370 * non-reference if we 2371 * are tracking the difference maps (for a JSR subroutine). 2372 * 2373 * @param localVariable variable index in the map 2374 * @param reachableHandlerBBNums the array with all the block numbers of 2375 * reachable handlers 2376 * @param reachableHandlerCount 0 through <code>reachableHandlerCount 2377 * - 1 </code> will all be valid 2378 * array indices 2379 * @param bbMaps TODO Document ME XXX 2380 */ 2381 private void setHandlersMapsReturnAddress(int localVariable, int[] reachableHandlerBBNums, int reachableHandlerCount, 2382 byte[][] bbMaps) { 2383 for (int i = 0; i < reachableHandlerCount; i++) { 2384 if (bbMaps[reachableHandlerBBNums[i]][localVariable] != RETURN_ADDRESS) { 2385 bbMaps[reachableHandlerBBNums[i]][localVariable] = SET_TO_NONREFERENCE; 2386 } 2387 } 2388 2389 } 2390}