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