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.osr; 014 015 import org.jikesrvm.VM; 016 import org.jikesrvm.classloader.BytecodeConstants; 017 import org.jikesrvm.classloader.BytecodeStream; 018 import org.jikesrvm.classloader.ClassLoaderConstants; 019 import org.jikesrvm.classloader.RVMClass; 020 import org.jikesrvm.classloader.ExceptionHandlerMap; 021 import org.jikesrvm.classloader.FieldReference; 022 import org.jikesrvm.classloader.RVMMethod; 023 import org.jikesrvm.classloader.MethodReference; 024 import org.jikesrvm.classloader.NormalMethod; 025 import org.jikesrvm.classloader.TypeReference; 026 import org.jikesrvm.compilers.common.CompiledMethods; 027 import org.jikesrvm.osr.bytecodes.InvokeStatic; 028 029 /** 030 * BytecodeTraverser does depth first search on a bytecode 031 * array, determines the type information of locals and stacks at 032 * Interesting point. 033 * <p> 034 * This class only intends to provide type information for on-stack 035 * replacement, which needs to know the type of a value. This class 036 * can only tells basic type information such as : REFERENCE, LONG, 037 * DOUBLE, FLOAT, INT, and ReturnAddress. Not like GCMap which tells 038 * GC a value is REFERENCE or NON-REFERENCE we also want to know it 039 * is INT or DOUBLE, and takes two words value or one word. 040 * <p> 041 * The produced type information has to be adjusted by consulting 042 * GC maps because two different types may merge at one program point 043 * (REF and non-REF types). Bytecode verifier will make the type info 044 * undefined in that case. But this class won't know. So the caller 045 * should check the GC map to validate a REF type variable. 046 * <p> 047 * More or less, this class needs to do the same work as a bytecode 048 * verifier, which tells the type and size of each locals and stacks. 049 * The JSR/RET instructions pose the difficulty to our case. However, 050 * we can assume the bytecode is verified. We use following assumptions: 051 * <ol> 052 * <li> After JSR, the stack was not changed, only local variable 053 * type needs to merge with FINALLY clause. 054 * <li> We need program-point specific stack type, but only need 055 * the summary of local types. Thus, after analysis, local 056 * types are same for all PCs. 057 * </ol> 058 */ 059 public class BytecodeTraverser implements BytecodeConstants, ClassLoaderConstants, OSRConstants { 060 061 /////// COMMON 062 /* to handle ret address which is not produced by JSR, we need a 063 * separate array to track that. 064 */ 065 private int[] retaddr; 066 private int addr; 067 068 private byte[] visitedpc; 069 private boolean TRACE = false; 070 071 // when computing infor for partial bytecodes 072 // donot following bytecodes out of range 073 private boolean ignoreGotos = false; 074 private BytecodeStream bytecodes; 075 076 /////// COMPUTING_TYPE_INFO 077 /* type information of local variables and stack slots */ 078 private byte[] ltypes; 079 private byte[] stypes; 080 081 /////////////////////////// 082 // COMPUTE TYPE INFORMATION 083 ////////////////////////// 084 /** 085 * Computes types of local variable and stack slots at an interesting point 086 * for future querying. Computing type info and retrieval should not be 087 * reentered. The type info of local variable is not accurate about reference 088 * types, see JVM SPEC (2nd edition) p 146. The caller can consult GC map 089 * to verify if a local is a reference or not. 090 * 091 * @param method whose bytecode to be queried 092 * @param bcpoint the bytecode index which is the interesting point 093 * at the mean time, we only support one PC. 094 * @return whether the pc is a valid program point of the method 095 */ 096 public boolean computeLocalStackTypes(NormalMethod method, int bcpoint) { 097 if (VM.TraceOnStackReplacement) { 098 VM.sysWrite("computing local and stack types of " + method + "\n"); 099 } 100 101 int localsize = method.getLocalWords(); 102 ltypes = new byte[localsize]; 103 104 if (VM.TraceOnStackReplacement) { 105 VM.sysWrite("local size : "); 106 VM.sysWrite(localsize); 107 VM.sysWrite("\n"); 108 } 109 110 retaddr = new int[localsize]; 111 for (int i = 0; i < localsize; i++) { 112 retaddr[i] = -1; 113 } 114 addr = -1; 115 116 int stacksize = method.getOperandWords(); 117 stypes = new byte[stacksize]; 118 119 /* set marks for each byte code. */ 120 // always operate on original method 121 this.bytecodes = method.getBytecodes(); 122 123 visitedpc = new byte[bytecodes.length()]; 124 125 /* then we initialize all stack and local type as void. */ 126 for (int i = 0, n = ltypes.length; i < n; i++) { 127 ltypes[i] = VoidTypeCode; 128 } 129 130 TypeStack simstacks = new TypeStack(stacksize, VoidTypeCode); 131 132 /* initialize local types from method signature.*/ 133 { 134 TypeReference[] ptypes = method.getParameterTypes(); 135 int lidx = 0; 136 if (!method.isStatic()) { 137 ltypes[lidx++] = ClassTypeCode; 138 } 139 for (int i = 0, n = ptypes.length; i < n; i++) { 140 byte tcode = ptypes[i].getName().parseForTypeCode(); 141 ltypes[lidx++] = tcode; 142 if ((tcode == LongTypeCode) || (tcode == DoubleTypeCode)) { 143 ltypes[lidx++] = VoidTypeCode; 144 } 145 } 146 } 147 148 /* scan start from method entry */ 149 boolean found = scanBlocks(method, bytecodes, true, bcpoint, ltypes, stypes, 0, simstacks, null); 150 /* scan for exception handler. */ 151 if (!found) { 152 ExceptionHandlerMap ehmap = method.getExceptionHandlerMap(); 153 if (ehmap != null) { 154 int[] handlerPCs = ehmap.getHandlerPC(); 155 for (int i = 0, n = handlerPCs.length; i < n; i++) { 156 simstacks.clear(); 157 simstacks.push(ClassTypeCode); 158 int startpc = handlerPCs[i]; 159 found = scanBlocks(method, bytecodes, true, bcpoint, ltypes, stypes, startpc, simstacks, null); 160 if (found) { 161 break; 162 } 163 } 164 } 165 } 166 visitedpc = null; 167 168 return true; 169 } 170 171 /** 172 * Returns an array of type information of locals at the registered 173 * program point. The size of array is fixed by MAX_LOCALS, the type 174 * descriptor can be found in "ClassLoadConstants.java". 175 * 176 * @return an array of type information, or null 177 */ 178 public byte[] getLocalTypes() { 179 return ltypes; 180 } 181 182 /** 183 * Returns an array of type information of stacks at a program 184 * point. The size of array is fixed by MAX_STACKS, the type 185 * descriptor can be found in "ClassLoadConstants.java". 186 * 187 * @return an array of type information, or null 188 */ 189 public byte[] getStackTypes() { 190 return stypes; 191 } 192 193 ////////////////////////// 194 // COMPUTE STACK HEIGHTS 195 ////////////////////////// 196 public void computeStackHeights(NormalMethod method, BytecodeStream bcodes, int[] stackHeights, 197 boolean adjustExptable) { 198 if (VM.TraceOnStackReplacement) { 199 VM.sysWriteln("computing stack heights of method " + method.toString()); 200 } 201 202 /* set marks for each byte code. */ 203 // this may be the specialized method 204 bytecodes = bcodes; 205 visitedpc = new byte[bytecodes.length()]; 206 207 int localsize = method.getLocalWords(); 208 retaddr = new int[localsize]; 209 for (int i = 0; i < localsize; i++) { 210 retaddr[i] = -1; 211 } 212 addr = -1; 213 214 int stacksize = method.getOperandWords(); 215 TypeStack simstacks = new TypeStack(stacksize, VoidTypeCode); 216 217 /* scan start from method entry */ 218 { 219 int startpc = 0; 220 scanBlocks(method, bytecodes, false, -1, null, null, startpc, simstacks, stackHeights); 221 } 222 /* scan for exception handler. */ 223 { 224 ExceptionHandlerMap ehmap = method.getExceptionHandlerMap(); 225 if (ehmap != null) { 226 int[] handlerPCs = ehmap.getHandlerPC(); 227 228 for (int i = 0, n = handlerPCs.length; i < n; i++) { 229 int startpc = handlerPCs[i]; 230 231 /* for baseline compilation, the SpecialCompiler 232 * didnot adjust exception table, we has to adjust it 233 * here. 234 */ 235 if (adjustExptable && method.isForOsrSpecialization()) { 236 startpc += method.getOsrPrologueLength(); 237 } 238 239 simstacks.clear(); 240 simstacks.push(ClassTypeCode); 241 scanBlocks(method, bytecodes, false, -1, null, null, startpc, simstacks, stackHeights); 242 } 243 } 244 } 245 visitedpc = null; 246 } 247 248 /** 249 * Compute stack heights of bytecode stream (used for osr prologue) 250 */ 251 public void prologueStackHeights(NormalMethod method, BytecodeStream bcodes, int[] stackHeights) { 252 if (VM.TraceOnStackReplacement) { 253 VM.sysWriteln("computing stack heights of method " + method.toString()); 254 } 255 256 /* set marks for each byte code. */ 257 // this may be the specialized method 258 bytecodes = bcodes; 259 visitedpc = new byte[bytecodes.length()]; 260 261 ignoreGotos = true; 262 263 int localsize = method.getLocalWords(); 264 retaddr = new int[localsize]; 265 for (int i = 0; i < localsize; i++) { 266 retaddr[i] = -1; 267 } 268 addr = -1; 269 270 int stacksize = method.getOperandWords(); 271 TypeStack simstacks = new TypeStack(stacksize, VoidTypeCode); 272 273 /* scan start from method entry */ 274 { 275 int startpc = 0; 276 scanBlocks(method, bytecodes, false, -1, null, null, startpc, simstacks, stackHeights); 277 } 278 visitedpc = null; 279 } 280 281 /* returns type code of the return type from the signature. 282 * SEE also : Atom.parseForReturnType 283 */ 284 @SuppressWarnings("unused") 285 private byte getReturnCodeFromSignature(String sig) { 286 byte[] val = sig.getBytes(); 287 288 int i = 0; 289 while (val[i++] != ')') ; 290 return (val[i]); 291 } 292 293 //////////////////////////// 294 // IMPLEMENTATION 295 /////////////////////////// 296 297 /* return true --> hit the bytecode pointed by PC */ 298 299 private boolean scanBlocks(NormalMethod method, // which method 300 BytecodeStream bytecodes, // the bytecodes 301 boolean doDFS, // do a DFS or one-pass scan 302 int pcs, // the target pcs, if doDFS 303 byte[] ltypes, // the local types if doDFS 304 byte[] stypes, // the stack types if doDFS 305 int startpc, // start pc 306 TypeStack S, // stack 307 int[] stackHeights) { // the stack height if not doDFS 308 309 int localsize = method.getLocalWords() - 1; 310 RVMClass declaringClass = method.getDeclaringClass(); 311 bytecodes.reset(startpc); 312 313 boolean found = false; 314 315 while (bytecodes.hasMoreBytecodes()) { 316 int pc = bytecodes.index(); // get current pc 317 if (visitedpc[pc] == 1) { 318 return false; 319 } else { 320 visitedpc[pc] = 1; 321 } 322 323 if (doDFS && (pc == pcs)) { 324 /* make a copy of stack frame and put into stypes. */ 325 byte[] stack = S.snapshot(); 326 System.arraycopy(stack, 0, stypes, 0, stack.length); 327 return true; 328 } 329 330 if (!doDFS) { 331 // record stack heights 332 stackHeights[pc] = localsize + S.depth(); 333 } 334 335 /* let's continue */ 336 int bcode = bytecodes.nextInstruction(); 337 338 if (TRACE) { 339 if (bcode <= JBC_jsr_w) { 340 VM.sysWriteln(pc + " : " + S.depth() + " : " + JBC_name[bcode]); 341 } else { 342 VM.sysWriteln(pc + " : " + S.depth() + " : impdep1"); 343 } 344 } 345 346 switch (bcode) { 347 case JBC_nop: 348 break; 349 case JBC_aconst_null: 350 S.push(ClassTypeCode); 351 break; 352 case JBC_iconst_m1: 353 case JBC_iconst_0: 354 case JBC_iconst_1: 355 case JBC_iconst_2: 356 case JBC_iconst_3: 357 case JBC_iconst_4: 358 case JBC_iconst_5: 359 S.push(IntTypeCode); 360 break; 361 case JBC_lconst_0: 362 case JBC_lconst_1: 363 /* we should do the save order as opt compiler */ 364 S.push(VoidTypeCode); 365 S.push(LongTypeCode); 366 break; 367 case JBC_fconst_0: 368 case JBC_fconst_1: 369 case JBC_fconst_2: 370 S.push(FloatTypeCode); 371 break; 372 case JBC_dconst_0: 373 case JBC_dconst_1: 374 S.push(VoidTypeCode); 375 S.push(DoubleTypeCode); 376 break; 377 case JBC_bipush: 378 bytecodes.getByteValue(); 379 S.push(IntTypeCode); 380 break; 381 case JBC_sipush: 382 bytecodes.getShortValue(); 383 S.push(IntTypeCode); 384 break; 385 case JBC_ldc: 386 case JBC_ldc_w: { 387 int cpoolidx = (bcode == JBC_ldc) ? bytecodes.getConstantIndex() : bytecodes.getWideConstantIndex(); 388 byte tdesc = declaringClass.getLiteralDescription(cpoolidx); 389 switch (tdesc) { 390 case CP_INT: 391 S.push(IntTypeCode); 392 break; 393 case CP_FLOAT: 394 S.push(FloatTypeCode); 395 break; 396 case CP_STRING: 397 S.push(ClassTypeCode); 398 break; 399 case CP_CLASS: 400 S.push(ClassTypeCode); 401 break; 402 default: 403 if (VM.TraceOnStackReplacement) VM.sysWriteln("ldc unknown type " + tdesc); 404 if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); 405 break; 406 } // end of switch 407 } 408 break; 409 case JBC_ldc2_w: { 410 int cpoolidx = bytecodes.getWideConstantIndex(); 411 byte tdesc = declaringClass.getLiteralDescription(cpoolidx); 412 S.push(VoidTypeCode); 413 switch (tdesc) { 414 case CP_LONG: 415 S.push(LongTypeCode); 416 break; 417 case CP_DOUBLE: 418 S.push(DoubleTypeCode); 419 break; 420 default: 421 if (VM.TraceOnStackReplacement) VM.sysWriteln("ldc2_w unknown type " + tdesc); 422 if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); 423 break; 424 } // end of switch 425 } 426 break; 427 case JBC_iload: 428 bytecodes.getLocalNumber(); // skip local 429 S.push(IntTypeCode); 430 break; 431 case JBC_lload: 432 bytecodes.getLocalNumber(); // skip local 433 S.push(VoidTypeCode); 434 S.push(LongTypeCode); 435 break; 436 case JBC_fload: 437 bytecodes.getLocalNumber(); // skip local 438 S.push(FloatTypeCode); 439 break; 440 case JBC_dload: 441 bytecodes.getLocalNumber(); 442 S.push(VoidTypeCode); 443 S.push(DoubleTypeCode); 444 break; 445 case JBC_aload: 446 bytecodes.getLocalNumber(); 447 S.push(ClassTypeCode); 448 break; 449 case JBC_iload_0: 450 case JBC_iload_1: 451 case JBC_iload_2: 452 case JBC_iload_3: 453 S.push(IntTypeCode); 454 break; 455 case JBC_lload_0: 456 case JBC_lload_1: 457 case JBC_lload_2: 458 case JBC_lload_3: 459 S.push(VoidTypeCode); 460 S.push(LongTypeCode); 461 break; 462 case JBC_fload_0: 463 case JBC_fload_1: 464 case JBC_fload_2: 465 case JBC_fload_3: 466 S.push(FloatTypeCode); 467 break; 468 case JBC_dload_0: 469 case JBC_dload_1: 470 case JBC_dload_2: 471 case JBC_dload_3: 472 S.push(VoidTypeCode); 473 S.push(DoubleTypeCode); 474 break; 475 case JBC_aload_0: 476 case JBC_aload_1: 477 case JBC_aload_2: 478 case JBC_aload_3: 479 S.push(ClassTypeCode); 480 break; 481 case JBC_iaload: 482 case JBC_baload: 483 case JBC_caload: 484 case JBC_saload: 485 S.pop(); 486 S.pop(); 487 S.push(IntTypeCode); 488 break; 489 case JBC_laload: 490 S.pop(); 491 S.pop(); 492 S.push(VoidTypeCode); 493 S.push(LongTypeCode); 494 break; 495 case JBC_faload: 496 S.pop(); 497 S.pop(); 498 S.push(FloatTypeCode); 499 break; 500 case JBC_daload: 501 S.pop(); 502 S.pop(); 503 S.push(VoidTypeCode); 504 S.push(DoubleTypeCode); 505 break; 506 case JBC_aaload: 507 S.pop(); 508 S.pop(); 509 S.push(ClassTypeCode); 510 break; 511 case JBC_istore: { 512 S.pop(); 513 int index = bytecodes.getLocalNumber(); 514 if (doDFS) ltypes[index] = IntTypeCode; 515 } 516 break; 517 case JBC_istore_0: 518 case JBC_istore_1: 519 case JBC_istore_2: 520 case JBC_istore_3: { 521 S.pop(); 522 int index = bcode - JBC_istore_0; 523 if (doDFS) ltypes[index] = IntTypeCode; 524 } 525 break; 526 case JBC_lstore: { 527 S.pop(); 528 S.pop(); 529 int index = bytecodes.getLocalNumber(); 530 if (doDFS) { 531 ltypes[index] = LongTypeCode; 532 ltypes[index + 1] = VoidTypeCode; 533 } 534 } 535 break; 536 case JBC_lstore_0: 537 case JBC_lstore_1: 538 case JBC_lstore_2: 539 case JBC_lstore_3: { 540 S.pop(); 541 S.pop(); 542 int index = bcode - JBC_lstore_0; 543 if (doDFS) { 544 ltypes[index] = LongTypeCode; 545 ltypes[index + 1] = VoidTypeCode; 546 } 547 } 548 break; 549 case JBC_fstore: { 550 S.pop(); 551 int index = bytecodes.getLocalNumber(); 552 if (doDFS) ltypes[index] = FloatTypeCode; 553 } 554 break; 555 case JBC_fstore_0: 556 case JBC_fstore_1: 557 case JBC_fstore_2: 558 case JBC_fstore_3: { 559 S.pop(); 560 int index = bcode - JBC_fstore_0; 561 if (doDFS) ltypes[index] = FloatTypeCode; 562 } 563 break; 564 case JBC_dstore: { 565 S.pop(); 566 S.pop(); 567 int index = bytecodes.getLocalNumber(); 568 if (doDFS) { 569 ltypes[index] = DoubleTypeCode; 570 ltypes[index + 1] = VoidTypeCode; 571 } 572 } 573 break; 574 case JBC_dstore_0: 575 case JBC_dstore_1: 576 case JBC_dstore_2: 577 case JBC_dstore_3: { 578 S.pop(); 579 S.pop(); 580 int index = bcode - JBC_dstore_0; 581 if (doDFS) { 582 ltypes[index] = DoubleTypeCode; 583 ltypes[index + 1] = VoidTypeCode; 584 } 585 } 586 break; 587 case JBC_astore: { 588 // caution: astore may save return address type 589 int index = bytecodes.getLocalNumber(); 590 byte tcode = S.pop(); 591 592 if (doDFS) ltypes[index] = tcode; 593 594 // for ret address. 595 if (tcode == ReturnAddressTypeCode) { 596 retaddr[index] = addr; 597 addr = -1; 598 } 599 } 600 break; 601 case JBC_astore_0: 602 case JBC_astore_1: 603 case JBC_astore_2: 604 case JBC_astore_3: { 605 // caution: astore may save return address type 606 int index = bcode - JBC_astore_0; 607 byte tcode = S.pop(); 608 609 if (doDFS) ltypes[index] = tcode; 610 611 // for ret address. 612 if (tcode == ReturnAddressTypeCode) { 613 retaddr[index] = addr; 614 addr = -1; 615 } 616 } 617 break; 618 case JBC_iastore: 619 case JBC_bastore: 620 case JBC_castore: 621 case JBC_sastore: 622 S.pop(3); 623 break; 624 case JBC_lastore: 625 S.pop(4); 626 break; 627 case JBC_fastore: 628 S.pop(3); 629 break; 630 case JBC_dastore: 631 S.pop(4); 632 break; 633 case JBC_aastore: 634 S.pop(3); 635 break; 636 case JBC_pop: 637 S.pop(); 638 break; 639 case JBC_pop2: 640 S.pop(2); 641 break; 642 case JBC_dup: { 643 byte v1 = S.peek(); 644 S.push(v1); 645 } 646 break; 647 case JBC_dup_x1: { 648 byte v1 = S.peek(); 649 S.pop(); 650 byte v2 = S.peek(); 651 S.pop(); 652 S.push(v1); 653 S.push(v2); 654 S.push(v1); 655 } 656 break; 657 case JBC_dup_x2: { 658 byte v1 = S.peek(); 659 S.pop(); 660 byte v2 = S.peek(); 661 S.pop(); 662 byte v3 = S.peek(); 663 S.pop(); 664 S.push(v1); 665 S.push(v3); 666 S.push(v2); 667 S.push(v1); 668 } 669 break; 670 case JBC_dup2: { 671 byte v1 = S.peek(); 672 S.pop(); 673 byte v2 = S.peek(); 674 S.push(v1); 675 S.push(v2); 676 S.push(v1); 677 } 678 break; 679 case JBC_dup2_x1: { 680 byte v1 = S.peek(); 681 S.pop(); 682 byte v2 = S.peek(); 683 S.pop(); 684 byte v3 = S.peek(); 685 S.pop(); 686 S.push(v2); 687 S.push(v1); 688 S.push(v3); 689 S.push(v2); 690 S.push(v1); 691 } 692 break; 693 case JBC_dup2_x2: { 694 byte v1 = S.peek(); 695 S.pop(); 696 byte v2 = S.peek(); 697 S.pop(); 698 byte v3 = S.peek(); 699 S.pop(); 700 byte v4 = S.peek(); 701 S.pop(); 702 S.push(v2); 703 S.push(v1); 704 S.push(v4); 705 S.push(v3); 706 S.push(v2); 707 S.push(v1); 708 } 709 break; 710 case JBC_swap: { 711 byte v1 = S.peek(); 712 S.pop(); 713 byte v2 = S.peek(); 714 S.pop(); 715 S.push(v1); 716 S.push(v2); 717 } 718 break; 719 case JBC_iadd: 720 case JBC_isub: 721 case JBC_imul: 722 case JBC_idiv: 723 case JBC_irem: 724 case JBC_iand: 725 case JBC_ior: 726 case JBC_ixor: 727 case JBC_ishl: 728 case JBC_ishr: 729 case JBC_iushr: 730 S.pop(); 731 break; 732 case JBC_ladd: 733 case JBC_lsub: 734 case JBC_lmul: 735 case JBC_ldiv: 736 case JBC_lrem: 737 case JBC_land: 738 case JBC_lor: 739 case JBC_lxor: 740 S.pop(2); 741 break; 742 case JBC_lshl: 743 case JBC_lshr: 744 case JBC_lushr: 745 S.pop(); 746 break; 747 case JBC_fadd: 748 case JBC_fsub: 749 case JBC_fmul: 750 case JBC_fdiv: 751 case JBC_frem: 752 S.pop(); 753 break; 754 case JBC_dadd: 755 case JBC_dsub: 756 case JBC_dmul: 757 case JBC_ddiv: 758 case JBC_drem: 759 S.pop(2); 760 break; 761 case JBC_ineg: 762 case JBC_lneg: 763 case JBC_fneg: 764 case JBC_dneg: 765 break; 766 case JBC_iinc: { 767 int index = bytecodes.getLocalNumber(); 768 /* int value = */ 769 bytecodes.getIncrement(); 770 if (doDFS) ltypes[index] = IntTypeCode; 771 } 772 break; 773 case JBC_i2l: 774 S.pop(); 775 S.push(VoidTypeCode); 776 S.push(LongTypeCode); 777 break; 778 case JBC_i2f: 779 S.pop(); 780 S.push(FloatTypeCode); 781 break; 782 case JBC_i2d: 783 S.pop(); 784 S.push(VoidTypeCode); 785 S.push(DoubleTypeCode); 786 break; 787 case JBC_l2i: 788 S.pop(2); 789 S.push(IntTypeCode); 790 break; 791 case JBC_l2f: 792 S.pop(2); 793 S.push(FloatTypeCode); 794 break; 795 case JBC_l2d: 796 S.pop(2); 797 S.push(VoidTypeCode); 798 S.push(DoubleTypeCode); 799 break; 800 case JBC_f2i: 801 S.pop(); 802 S.push(IntTypeCode); 803 break; 804 case JBC_f2l: 805 S.pop(); 806 S.push(VoidTypeCode); 807 S.push(LongTypeCode); 808 break; 809 case JBC_f2d: 810 S.pop(); 811 S.push(VoidTypeCode); 812 S.push(DoubleTypeCode); 813 break; 814 case JBC_d2i: 815 S.pop(2); 816 S.push(IntTypeCode); 817 break; 818 case JBC_d2l: 819 S.pop(2); 820 S.push(VoidTypeCode); 821 S.push(LongTypeCode); 822 break; 823 case JBC_d2f: 824 S.pop(2); 825 S.push(FloatTypeCode); 826 break; 827 case JBC_int2byte: 828 case JBC_int2char: 829 case JBC_int2short: 830 break; 831 case JBC_lcmp: 832 S.pop(4); 833 S.push(IntTypeCode); 834 break; 835 case JBC_fcmpl: 836 case JBC_fcmpg: 837 S.pop(2); 838 S.push(IntTypeCode); 839 break; 840 case JBC_dcmpl: 841 case JBC_dcmpg: 842 S.pop(4); 843 S.push(IntTypeCode); 844 break; 845 case JBC_ifeq: 846 case JBC_ifne: 847 case JBC_iflt: 848 case JBC_ifge: 849 case JBC_ifgt: 850 case JBC_ifle: 851 case JBC_ifnull: 852 case JBC_ifnonnull: { 853 S.pop(); 854 855 // flowthrough first 856 int nextpc = pc + 3; 857 int target = pc + bytecodes.getBranchOffset(); 858 if (doDFS) { 859 // make a copy of ltypes, stypes to pass in 860 byte[] newltypes = new byte[ltypes.length]; 861 byte[] newstypes = new byte[stypes.length]; 862 System.arraycopy(ltypes, 0, newltypes, 0, ltypes.length); 863 System.arraycopy(stypes, 0, newstypes, 0, stypes.length); 864 found = scanBlocks(method, bytecodes, true, pcs, newltypes, newstypes, nextpc, new TypeStack(S), null); 865 if (found) { 866 // copy back the ltypes and stypes 867 System.arraycopy(newltypes, 0, ltypes, 0, ltypes.length); 868 System.arraycopy(newstypes, 0, stypes, 0, stypes.length); 869 870 return true; 871 } 872 } else { 873 found = scanBlocks(method, bytecodes, false, -1, null, null, nextpc, new TypeStack(S), stackHeights); 874 } 875 bytecodes.reset(target); 876 } 877 break; 878 case JBC_if_icmpeq: 879 case JBC_if_icmpne: 880 case JBC_if_icmplt: 881 case JBC_if_icmpge: 882 case JBC_if_icmpgt: 883 case JBC_if_icmple: 884 case JBC_if_acmpeq: 885 case JBC_if_acmpne: { 886 S.pop(2); 887 888 // flowthrough first 889 int nextpc = pc + 3; 890 int target = pc + bytecodes.getBranchOffset(); 891 892 if (doDFS) { 893 // make a copy of ltypes, stypes to pass in 894 byte[] newltypes = new byte[ltypes.length]; 895 byte[] newstypes = new byte[stypes.length]; 896 System.arraycopy(ltypes, 0, newltypes, 0, ltypes.length); 897 System.arraycopy(stypes, 0, newstypes, 0, stypes.length); 898 found = scanBlocks(method, bytecodes, true, pcs, newltypes, newstypes, nextpc, new TypeStack(S), null); 899 if (found) { 900 // copy back the ltypes and stypes 901 System.arraycopy(newltypes, 0, ltypes, 0, ltypes.length); 902 System.arraycopy(newstypes, 0, stypes, 0, stypes.length); 903 904 return true; 905 } 906 } else { 907 found = scanBlocks(method, bytecodes, false, -1, null, null, nextpc, new TypeStack(S), stackHeights); 908 } 909 910 bytecodes.reset(target); 911 } 912 break; 913 case JBC_goto: { 914 int offset = bytecodes.getBranchOffset(); 915 if (!ignoreGotos) { 916 bytecodes.reset(pc + offset); 917 } 918 } 919 break; 920 case JBC_goto_w: { 921 int offset = bytecodes.getWideBranchOffset(); 922 if (!ignoreGotos) { 923 bytecodes.reset(pc + offset); 924 } 925 } 926 break; 927 case JBC_jsr: 928 case JBC_jsr_w: { 929 // flow through firs 930 int nextpc = pc + ((bcode == JBC_jsr) ? 3 : 5); 931 int target = pc + ((bcode == JBC_jsr) ? bytecodes.getBranchOffset() : bytecodes.getWideBranchOffset()); 932 933 if (doDFS) { 934 // make a copy of ltypes, stypes to pass in 935 byte[] newltypes = new byte[ltypes.length]; 936 byte[] newstypes = new byte[stypes.length]; 937 System.arraycopy(ltypes, 0, newltypes, 0, ltypes.length); 938 System.arraycopy(stypes, 0, newstypes, 0, stypes.length); 939 found = scanBlocks(method, bytecodes, true, pcs, newltypes, newstypes, nextpc, new TypeStack(S), null); 940 if (found) { 941 // copy back the ltypes and stypes 942 System.arraycopy(newltypes, 0, ltypes, 0, ltypes.length); 943 System.arraycopy(newstypes, 0, stypes, 0, stypes.length); 944 945 return true; 946 } 947 } else { 948 found = scanBlocks(method, bytecodes, false, -1, null, null, nextpc, new TypeStack(S), stackHeights); 949 } 950 951 // branch to jsr subroutine 952 // remember return address for ret. 953 addr = pc + ((bcode == JBC_jsr) ? 3 : 5); 954 S.push(ReturnAddressTypeCode); 955 bytecodes.reset(target); 956 } 957 break; 958 case JBC_ret: { 959 // the OPT compiler set local to null after _ret instruction, 960 // then we should clean it here also, otherwise it will 961 // throw a null pointer exception. 962 // HOWEVER, it is not part of JVM spec. 963 int index = bytecodes.getLocalNumber(); 964 965 if (doDFS) ltypes[index] = VoidTypeCode; 966 967 /* the ret address may be saved by a PSEUDO_LoadRetAddrConstant 968 */ 969 if (retaddr[index] != -1) { 970 bytecodes.reset(retaddr[index]); 971 retaddr[index] = -1; 972 } else { 973 // now we hit ret, return out 974 return false; 975 } 976 } 977 break; 978 case JBC_tableswitch: { 979 S.pop(); 980 bytecodes.alignSwitch(); 981 int defaultval = bytecodes.getDefaultSwitchOffset(); 982 int low = bytecodes.getLowSwitchValue(); 983 int high = bytecodes.getHighSwitchValue(); 984 985 // write down a list of targets 986 int npairs = high - low + 1; 987 int[] offsets = new int[npairs]; 988 for (int i = 0; i < npairs; i++) { 989 offsets[i] = bytecodes.getTableSwitchOffset(i); 990 } 991 992 for (int i = 0; i < npairs; i++) { 993 int tgtpc = pc + offsets[i]; 994 995 if (doDFS) { 996 // make a copy of ltypes, stypes to pass in 997 byte[] newltypes = new byte[ltypes.length]; 998 byte[] newstypes = new byte[stypes.length]; 999 1000 System.arraycopy(ltypes, 0, newltypes, 0, ltypes.length); 1001 System.arraycopy(stypes, 0, newstypes, 0, stypes.length); 1002 found = scanBlocks(method, bytecodes, true, pcs, newltypes, newstypes, tgtpc, new TypeStack(S), null); 1003 if (found) { 1004 // copy back the ltypes and stypes 1005 System.arraycopy(newltypes, 0, ltypes, 0, ltypes.length); 1006 System.arraycopy(newstypes, 0, stypes, 0, stypes.length); 1007 1008 return true; 1009 } 1010 } else { 1011 found = scanBlocks(method, bytecodes, false, -1, null, null, tgtpc, new TypeStack(S), stackHeights); 1012 } 1013 } 1014 1015 // default 1016 { 1017 int tgtpc = pc + defaultval; 1018 1019 if (doDFS) { 1020 // make a copy of ltypes, stypes to pass in 1021 byte[] newltypes = new byte[ltypes.length]; 1022 byte[] newstypes = new byte[stypes.length]; 1023 System.arraycopy(ltypes, 0, newltypes, 0, ltypes.length); 1024 System.arraycopy(stypes, 0, newstypes, 0, stypes.length); 1025 found = scanBlocks(method, bytecodes, true, pcs, newltypes, newstypes, tgtpc, new TypeStack(S), null); 1026 if (found) { 1027 // copy back the ltypes and stypes 1028 System.arraycopy(newltypes, 0, ltypes, 0, ltypes.length); 1029 System.arraycopy(newstypes, 0, stypes, 0, stypes.length); 1030 } 1031 } else { 1032 found = scanBlocks(method, bytecodes, false, -1, null, null, tgtpc, new TypeStack(S), stackHeights); 1033 } 1034 return found; 1035 } 1036 } 1037 case JBC_lookupswitch: { 1038 S.pop(); // pop the key 1039 bytecodes.alignSwitch(); 1040 int defaultval = bytecodes.getDefaultSwitchOffset(); 1041 int npairs = bytecodes.getSwitchLength(); 1042 1043 int[] matches = new int[npairs]; 1044 int[] offsets = new int[npairs]; 1045 for (int i = 0; i < npairs; i++) { 1046 matches[i] = bytecodes.getLookupSwitchValue(i); 1047 offsets[i] = bytecodes.getLookupSwitchOffset(i); 1048 } 1049 1050 for (int i = 0; i < npairs; i++) { 1051 //int match = matches[i]; 1052 int offset = offsets[i]; 1053 1054 int tgtpc = pc + offset; 1055 1056 if (doDFS) { 1057 // make a copy of ltypes, stypes to pass in 1058 byte[] newltypes = new byte[ltypes.length]; 1059 byte[] newstypes = new byte[stypes.length]; 1060 1061 System.arraycopy(ltypes, 0, newltypes, 0, ltypes.length); 1062 System.arraycopy(stypes, 0, newstypes, 0, stypes.length); 1063 found = scanBlocks(method, bytecodes, true, pcs, newltypes, newstypes, tgtpc, new TypeStack(S), null); 1064 if (found) { 1065 // copy back the ltypes and stypes 1066 System.arraycopy(newltypes, 0, ltypes, 0, ltypes.length); 1067 System.arraycopy(newstypes, 0, stypes, 0, stypes.length); 1068 1069 return true; 1070 } 1071 } else { 1072 found = scanBlocks(method, bytecodes, false, -1, null, null, tgtpc, new TypeStack(S), stackHeights); 1073 } 1074 } 1075 1076 // default 1077 { 1078 int tgtpc = pc + defaultval; 1079 1080 if (doDFS) { 1081 // make a copy of ltypes, stypes to pass in 1082 byte[] newltypes = new byte[ltypes.length]; 1083 byte[] newstypes = new byte[stypes.length]; 1084 1085 System.arraycopy(ltypes, 0, newltypes, 0, ltypes.length); 1086 System.arraycopy(stypes, 0, newstypes, 0, stypes.length); 1087 found = scanBlocks(method, bytecodes, true, pcs, newltypes, newstypes, tgtpc, new TypeStack(S), null); 1088 if (found) { 1089 // copy back the ltypes and stypes 1090 System.arraycopy(newltypes, 0, ltypes, 0, ltypes.length); 1091 System.arraycopy(newstypes, 0, stypes, 0, stypes.length); 1092 } 1093 } else { 1094 found = scanBlocks(method, bytecodes, false, -1, null, null, tgtpc, new TypeStack(S), stackHeights); 1095 } 1096 } 1097 } 1098 return found; 1099 case JBC_ireturn: 1100 S.pop(); 1101 return false; 1102 case JBC_lreturn: 1103 S.pop(2); 1104 return false; 1105 case JBC_freturn: 1106 S.pop(); 1107 return false; 1108 case JBC_dreturn: 1109 S.pop(2); 1110 return false; 1111 case JBC_areturn: 1112 S.pop(); 1113 return false; 1114 case JBC_return: 1115 return false; 1116 case JBC_getfield: 1117 S.pop(); 1118 case JBC_getstatic: { 1119 FieldReference fieldRef = bytecodes.getFieldReference(); 1120 TypeReference ftype = fieldRef.getFieldContentsType(); 1121 byte tcode = ftype.getName().parseForTypeCode(); 1122 if ((tcode == LongTypeCode) || (tcode == DoubleTypeCode)) { 1123 S.push(VoidTypeCode); 1124 } 1125 S.push(tcode); 1126 } 1127 break; 1128 case JBC_putstatic: { 1129 FieldReference fieldRef = bytecodes.getFieldReference(); 1130 TypeReference ftype = fieldRef.getFieldContentsType(); 1131 byte tcode = ftype.getName().parseForTypeCode(); 1132 if ((tcode == LongTypeCode) || (tcode == DoubleTypeCode)) { 1133 S.pop(2); 1134 } else { 1135 S.pop(); 1136 } 1137 } 1138 break; 1139 case JBC_putfield: { 1140 FieldReference fieldRef = bytecodes.getFieldReference(); 1141 TypeReference ftype = fieldRef.getFieldContentsType(); 1142 byte tcode = ftype.getName().parseForTypeCode(); 1143 if ((tcode == LongTypeCode) || (tcode == DoubleTypeCode)) { 1144 S.pop(2); 1145 } else { 1146 S.pop(); 1147 } 1148 } 1149 S.pop(); 1150 break; 1151 case JBC_invokevirtual: 1152 case JBC_invokespecial: 1153 case JBC_invokestatic: 1154 case JBC_invokeinterface: { 1155 MethodReference callee = bytecodes.getMethodReference(); 1156 1157 int psize = callee.getParameterWords(); 1158 1159 S.pop(psize); 1160 1161 if (bcode != JBC_invokestatic) { 1162 S.pop(); // pop the object reference 1163 } 1164 1165 TypeReference rtype = callee.getReturnType(); 1166 byte tcode = rtype.getName().parseForTypeCode(); 1167 1168 if (tcode == VoidTypeCode) { 1169 // nothing to do with void return type 1170 } else { 1171 if ((tcode == LongTypeCode) || (tcode == DoubleTypeCode)) { 1172 S.push(VoidTypeCode); 1173 } 1174 S.push(tcode); 1175 } 1176 1177 if (bcode == JBC_invokeinterface) { 1178 bytecodes.alignInvokeInterface(); 1179 } 1180 } 1181 break; 1182 case JBC_xxxunusedxxx: 1183 break; 1184 1185 case JBC_new: 1186 bytecodes.getTypeReference(); // skip cpi of type 1187 S.push(ClassTypeCode); 1188 break; 1189 case JBC_newarray: 1190 S.pop(); 1191 S.push(ArrayTypeCode); 1192 bytecodes.getArrayElementType(); // skip cpi of element type 1193 break; 1194 case JBC_anewarray: 1195 S.pop(); 1196 S.push(ArrayTypeCode); 1197 bytecodes.getTypeReference(); // skip cpi of reference type 1198 break; 1199 case JBC_arraylength: 1200 S.pop(); 1201 S.push(IntTypeCode); 1202 break; 1203 case JBC_athrow: 1204 S.clear(); 1205 S.push(ClassTypeCode); 1206 return false; 1207 case JBC_checkcast: 1208 bytecodes.getTypeReference(); // skip cpi of reference type 1209 break; 1210 case JBC_instanceof: 1211 S.pop(); 1212 S.push(IntTypeCode); 1213 bytecodes.getTypeReference(); // skip cpi of reference type 1214 break; 1215 case JBC_monitorenter: 1216 case JBC_monitorexit: 1217 S.pop(); 1218 break; 1219 case JBC_wide: { 1220 int widecode = bytecodes.getWideOpcode(); 1221 int index = bytecodes.getWideLocalNumber(); 1222 switch (widecode) { 1223 case JBC_iload: 1224 S.push(IntTypeCode); 1225 break; 1226 case JBC_lload: 1227 S.push(LongTypeCode); 1228 break; 1229 case JBC_fload: 1230 S.push(FloatTypeCode); 1231 break; 1232 case JBC_dload: 1233 S.push(DoubleTypeCode); 1234 break; 1235 case JBC_aload: 1236 S.push(ClassTypeCode); 1237 break; 1238 case JBC_istore: 1239 S.pop(); 1240 if (doDFS) ltypes[index] = IntTypeCode; 1241 break; 1242 case JBC_lstore: 1243 S.pop(); 1244 if (doDFS) ltypes[index] = LongTypeCode; 1245 break; 1246 case JBC_fstore: 1247 S.pop(); 1248 if (doDFS) ltypes[index] = FloatTypeCode; 1249 break; 1250 case JBC_dstore: 1251 S.pop(); 1252 if (doDFS) ltypes[index] = DoubleTypeCode; 1253 break; 1254 case JBC_astore: { 1255 byte tcode = S.pop(); 1256 if (doDFS) ltypes[index] = tcode; 1257 1258 // for ret address. 1259 if (tcode == ReturnAddressTypeCode) { 1260 retaddr[index] = addr; 1261 addr = -1; 1262 } 1263 } 1264 break; 1265 case JBC_iinc: { 1266 bytecodes.getWideIncrement(); // skip increment 1267 if (doDFS) ltypes[index] = IntTypeCode; 1268 } 1269 break; 1270 case JBC_ret: 1271 if (doDFS) ltypes[index] = VoidTypeCode; 1272 1273 if (retaddr[index] != -1) { 1274 bytecodes.reset(retaddr[index]); 1275 retaddr[index] = -1; 1276 } else { 1277 // now we hit ret, return out 1278 return false; 1279 } 1280 break; 1281 default: 1282 if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); 1283 break; 1284 } 1285 break; 1286 } 1287 case JBC_multianewarray: { 1288 bytecodes.getTypeReference(); // skip type reference 1289 int dims = bytecodes.getArrayDimension(); 1290 S.pop(dims); 1291 S.push(ArrayTypeCode); 1292 } 1293 break; 1294 case JBC_impdep1: { 1295 int pseudo_opcode = bytecodes.nextPseudoInstruction(); 1296 switch (pseudo_opcode) { 1297 case PSEUDO_LoadIntConst: 1298 bytecodes.readIntConst(); // skip value 1299 S.push(IntTypeCode); 1300 break; 1301 case PSEUDO_LoadLongConst: 1302 bytecodes.readLongConst(); // skip value 1303 S.push(VoidTypeCode); 1304 S.push(LongTypeCode); 1305 break; 1306 case PSEUDO_LoadWordConst: 1307 if (VM.BuildFor32Addr) { 1308 bytecodes.readIntConst(); 1309 } else { 1310 bytecodes.readLongConst(); // skip value 1311 } 1312 S.push(WordTypeCode); 1313 break; 1314 case PSEUDO_LoadFloatConst: 1315 bytecodes.readIntConst(); // skip value 1316 S.push(FloatTypeCode); 1317 break; 1318 case PSEUDO_LoadDoubleConst: 1319 bytecodes.readLongConst(); // skip value 1320 S.push(VoidTypeCode); 1321 S.push(DoubleTypeCode); 1322 break; 1323 case PSEUDO_LoadRetAddrConst: 1324 // remember the address for ret. 1325 addr = bytecodes.readIntConst(); // get address 1326 S.push(ReturnAddressTypeCode); 1327 break; 1328 case PSEUDO_InvokeStatic: { 1329 int mid = bytecodes.readIntConst(); // get METHIDX 1330 RVMMethod callee = InvokeStatic.targetMethod(mid); 1331 1332 int psize = callee.getParameterWords(); 1333 S.pop(psize); 1334 1335 TypeReference rtype = callee.getReturnType(); 1336 byte tcode = rtype.getName().parseForTypeCode(); 1337 1338 if (tcode == VoidTypeCode) { 1339 // nothing to do with void return type 1340 } else { 1341 if ((tcode == LongTypeCode) || (tcode == DoubleTypeCode)) { 1342 S.push(VoidTypeCode); 1343 } 1344 S.push(tcode); 1345 } 1346 break; 1347 } 1348 /* 1349 case PSEUDO_CheckCast: 1350 bytecodes.readIntConst(); // skip type id 1351 break; 1352 */ 1353 case PSEUDO_InvokeCompiledMethod: 1354 int cmid = bytecodes.readIntConst(); // cmid 1355 bytecodes.readIntConst(); // skip bcindex 1356 1357 RVMMethod callee = CompiledMethods.getCompiledMethod(cmid).getMethod(); 1358 int psize = callee.getParameterWords(); 1359 1360 S.pop(psize); 1361 1362 if (!callee.isStatic()) { 1363 S.pop(); // pop receiver 1364 } 1365 1366 TypeReference rtype = callee.getReturnType(); 1367 byte tcode = rtype.getName().parseForTypeCode(); 1368 1369 if (tcode == VoidTypeCode) { 1370 // nothing to do with void return type 1371 } else { 1372 if ((tcode == LongTypeCode) || (tcode == DoubleTypeCode)) { 1373 S.push(VoidTypeCode); 1374 } 1375 S.push(tcode); 1376 } 1377 break; 1378 case PSEUDO_ParamInitEnd: 1379 break; 1380 default: 1381 if (VM.VerifyAssertions) { 1382 VM.sysWrite(" Error, no such pseudo code : " + pseudo_opcode + "\n"); 1383 VM._assert(VM.NOT_REACHED); 1384 } 1385 return false; 1386 } 1387 break; 1388 } 1389 default: 1390 VM.sysWrite("Unknown bytecode : " + bcode + "\n"); 1391 return false; 1392 } 1393 } 1394 1395 /* did not found the PC. */ 1396 return false; 1397 } 1398 } 1399