1 21 package proguard.evaluation; 22 23 import proguard.classfile.*; 24 import proguard.classfile.attribute.CodeAttribute; 25 import proguard.classfile.constant.*; 26 import proguard.classfile.constant.visitor.ConstantVisitor; 27 import proguard.classfile.instruction.*; 28 import proguard.classfile.instruction.visitor.InstructionVisitor; 29 import proguard.classfile.util.*; 30 import proguard.evaluation.value.*; 31 32 38 public class Processor 39 extends SimplifiedVisitor 40 implements InstructionVisitor, 41 ConstantVisitor 42 { 43 private Variables variables; 44 private Stack stack; 45 private ValueFactory valueFactory; 46 private BranchUnit branchUnit; 47 private InvocationUnit invocationUnit; 48 49 private boolean handleClassConstantAsClassValue; 51 private Value cpValue; 52 53 54 61 public Processor(Variables variables, 62 Stack stack, 63 ValueFactory valueFactory, 64 BranchUnit branchUnit, 65 InvocationUnit invocationUnit) 66 { 67 this.variables = variables; 68 this.stack = stack; 69 this.valueFactory = valueFactory; 70 this.branchUnit = branchUnit; 71 this.invocationUnit = invocationUnit; 72 } 73 74 75 77 public void visitSimpleInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SimpleInstruction simpleInstruction) 78 { 79 switch (simpleInstruction.opcode) 80 { 81 case InstructionConstants.OP_NOP: 82 break; 83 84 case InstructionConstants.OP_ACONST_NULL: 85 stack.push(valueFactory.createReferenceValueNull()); 86 break; 87 88 case InstructionConstants.OP_ICONST_M1: 89 case InstructionConstants.OP_ICONST_0: 90 case InstructionConstants.OP_ICONST_1: 91 case InstructionConstants.OP_ICONST_2: 92 case InstructionConstants.OP_ICONST_3: 93 case InstructionConstants.OP_ICONST_4: 94 case InstructionConstants.OP_ICONST_5: 95 case InstructionConstants.OP_BIPUSH: 96 case InstructionConstants.OP_SIPUSH: 97 stack.push(valueFactory.createIntegerValue(simpleInstruction.constant)); 98 break; 99 100 case InstructionConstants.OP_LCONST_0: 101 case InstructionConstants.OP_LCONST_1: 102 stack.push(valueFactory.createLongValue(simpleInstruction.constant)); 103 break; 104 105 case InstructionConstants.OP_FCONST_0: 106 case InstructionConstants.OP_FCONST_1: 107 case InstructionConstants.OP_FCONST_2: 108 stack.push(valueFactory.createFloatValue((float)simpleInstruction.constant)); 109 break; 110 111 case InstructionConstants.OP_DCONST_0: 112 case InstructionConstants.OP_DCONST_1: 113 stack.push(valueFactory.createDoubleValue((double)simpleInstruction.constant)); 114 break; 115 116 case InstructionConstants.OP_IALOAD: 117 case InstructionConstants.OP_BALOAD: 118 case InstructionConstants.OP_CALOAD: 119 case InstructionConstants.OP_SALOAD: 120 stack.ipop(); 121 stack.apop(); 122 stack.push(valueFactory.createIntegerValue()); 123 break; 124 125 case InstructionConstants.OP_LALOAD: 126 stack.ipop(); 127 stack.apop(); 128 stack.push(valueFactory.createLongValue()); 129 break; 130 131 case InstructionConstants.OP_FALOAD: 132 stack.ipop(); 133 stack.apop(); 134 stack.push(valueFactory.createFloatValue()); 135 break; 136 137 case InstructionConstants.OP_DALOAD: 138 stack.ipop(); 139 stack.apop(); 140 stack.push(valueFactory.createDoubleValue()); 141 break; 142 143 case InstructionConstants.OP_AALOAD: 144 { 145 IntegerValue arrayIndex = stack.ipop(); 146 ReferenceValue arrayReference = stack.apop(); 147 stack.push(arrayReference.arrayLoad(arrayIndex, valueFactory)); 148 break; 149 } 150 151 case InstructionConstants.OP_IASTORE: 152 case InstructionConstants.OP_BASTORE: 153 case InstructionConstants.OP_CASTORE: 154 case InstructionConstants.OP_SASTORE: 155 stack.ipop(); 156 stack.ipop(); 157 stack.apop(); 158 break; 159 160 case InstructionConstants.OP_LASTORE: 161 stack.lpop(); 162 stack.ipop(); 163 stack.apop(); 164 break; 165 166 case InstructionConstants.OP_FASTORE: 167 stack.fpop(); 168 stack.ipop(); 169 stack.apop(); 170 break; 171 172 case InstructionConstants.OP_DASTORE: 173 stack.dpop(); 174 stack.ipop(); 175 stack.apop(); 176 break; 177 178 case InstructionConstants.OP_AASTORE: 179 stack.apop(); 180 stack.ipop(); 181 stack.apop(); 182 break; 183 184 case InstructionConstants.OP_POP: 185 stack.pop1(); 186 break; 187 188 case InstructionConstants.OP_POP2: 189 stack.pop2(); 190 break; 191 192 case InstructionConstants.OP_DUP: 193 stack.dup(); 194 break; 195 196 case InstructionConstants.OP_DUP_X1: 197 stack.dup_x1(); 198 break; 199 200 case InstructionConstants.OP_DUP_X2: 201 stack.dup_x2(); 202 break; 203 204 case InstructionConstants.OP_DUP2: 205 stack.dup2(); 206 break; 207 208 case InstructionConstants.OP_DUP2_X1: 209 stack.dup2_x1(); 210 break; 211 212 case InstructionConstants.OP_DUP2_X2: 213 stack.dup2_x2(); 214 break; 215 216 case InstructionConstants.OP_SWAP: 217 stack.swap(); 218 break; 219 220 case InstructionConstants.OP_IADD: 221 stack.push(stack.ipop().add(stack.ipop())); 222 break; 223 224 case InstructionConstants.OP_LADD: 225 stack.push(stack.lpop().add(stack.lpop())); 226 break; 227 228 case InstructionConstants.OP_FADD: 229 stack.push(stack.fpop().add(stack.fpop())); 230 break; 231 232 case InstructionConstants.OP_DADD: 233 stack.push(stack.dpop().add(stack.dpop())); 234 break; 235 236 case InstructionConstants.OP_ISUB: 237 stack.push(stack.ipop().subtractFrom(stack.ipop())); 238 break; 239 240 case InstructionConstants.OP_LSUB: 241 stack.push(stack.lpop().subtractFrom(stack.lpop())); 242 break; 243 244 case InstructionConstants.OP_FSUB: 245 stack.push(stack.fpop().subtractFrom(stack.fpop())); 246 break; 247 248 case InstructionConstants.OP_DSUB: 249 stack.push(stack.dpop().subtractFrom(stack.dpop())); 250 break; 251 252 case InstructionConstants.OP_IMUL: 253 stack.push(stack.ipop().multiply(stack.ipop())); 254 break; 255 256 case InstructionConstants.OP_LMUL: 257 stack.push(stack.lpop().multiply(stack.lpop())); 258 break; 259 260 case InstructionConstants.OP_FMUL: 261 stack.push(stack.fpop().multiply(stack.fpop())); 262 break; 263 264 case InstructionConstants.OP_DMUL: 265 stack.push(stack.dpop().multiply(stack.dpop())); 266 break; 267 268 case InstructionConstants.OP_IDIV: 269 try 270 { 271 stack.push(stack.ipop().divideOf(stack.ipop())); 272 } 273 catch (ArithmeticException ex) 274 { 275 stack.push(valueFactory.createIntegerValue()); 276 } 281 break; 282 283 case InstructionConstants.OP_LDIV: 284 try 285 { 286 stack.push(stack.lpop().divideOf(stack.lpop())); 287 } 288 catch (ArithmeticException ex) 289 { 290 stack.push(valueFactory.createLongValue()); 291 } 296 break; 297 298 case InstructionConstants.OP_FDIV: 299 stack.push(stack.fpop().divideOf(stack.fpop())); 300 break; 301 302 case InstructionConstants.OP_DDIV: 303 stack.push(stack.dpop().divideOf(stack.dpop())); 304 break; 305 306 case InstructionConstants.OP_IREM: 307 try 308 { 309 stack.push(stack.ipop().remainderOf(stack.ipop())); 310 } 311 catch (ArithmeticException ex) 312 { 313 stack.push(valueFactory.createIntegerValue()); 314 } 319 break; 320 321 case InstructionConstants.OP_LREM: 322 try 323 { 324 stack.push(stack.lpop().remainderOf(stack.lpop())); 325 } 326 catch (ArithmeticException ex) 327 { 328 stack.push(valueFactory.createLongValue()); 329 } 334 break; 335 336 case InstructionConstants.OP_FREM: 337 stack.push(stack.fpop().remainderOf(stack.fpop())); 338 break; 339 340 case InstructionConstants.OP_DREM: 341 stack.push(stack.dpop().remainderOf(stack.dpop())); 342 break; 343 344 case InstructionConstants.OP_INEG: 345 stack.push(stack.ipop().negate()); 346 break; 347 348 case InstructionConstants.OP_LNEG: 349 stack.push(stack.lpop().negate()); 350 break; 351 352 case InstructionConstants.OP_FNEG: 353 stack.push(stack.fpop().negate()); 354 break; 355 356 case InstructionConstants.OP_DNEG: 357 stack.push(stack.dpop().negate()); 358 break; 359 360 case InstructionConstants.OP_ISHL: 361 stack.push(stack.ipop().shiftLeftOf(stack.ipop())); 362 break; 363 364 case InstructionConstants.OP_LSHL: 365 stack.push(stack.ipop().shiftLeftOf(stack.lpop())); 366 break; 367 368 case InstructionConstants.OP_ISHR: 369 stack.push(stack.ipop().shiftRightOf(stack.ipop())); 370 break; 371 372 case InstructionConstants.OP_LSHR: 373 stack.push(stack.ipop().shiftRightOf(stack.lpop())); 374 break; 375 376 case InstructionConstants.OP_IUSHR: 377 stack.push(stack.ipop().unsignedShiftRightOf(stack.ipop())); 378 break; 379 380 case InstructionConstants.OP_LUSHR: 381 stack.push(stack.ipop().unsignedShiftRightOf(stack.lpop())); 382 break; 383 384 case InstructionConstants.OP_IAND: 385 stack.push(stack.ipop().and(stack.ipop())); 386 break; 387 388 case InstructionConstants.OP_LAND: 389 stack.push(stack.lpop().and(stack.lpop())); 390 break; 391 392 case InstructionConstants.OP_IOR: 393 stack.push(stack.ipop().or(stack.ipop())); 394 break; 395 396 case InstructionConstants.OP_LOR: 397 stack.push(stack.lpop().or(stack.lpop())); 398 break; 399 400 case InstructionConstants.OP_IXOR: 401 stack.push(stack.ipop().xor(stack.ipop())); 402 break; 403 404 case InstructionConstants.OP_LXOR: 405 stack.push(stack.lpop().xor(stack.lpop())); 406 break; 407 408 case InstructionConstants.OP_I2L: 409 stack.push(stack.ipop().convertToLong(valueFactory)); 410 break; 411 412 case InstructionConstants.OP_I2F: 413 stack.push(stack.ipop().convertToFloat(valueFactory)); 414 break; 415 416 case InstructionConstants.OP_I2D: 417 stack.push(stack.ipop().convertToDouble(valueFactory)); 418 break; 419 420 case InstructionConstants.OP_L2I: 421 stack.push(stack.lpop().convertToInteger(valueFactory)); 422 break; 423 424 case InstructionConstants.OP_L2F: 425 stack.push(stack.lpop().convertToFloat(valueFactory)); 426 break; 427 428 case InstructionConstants.OP_L2D: 429 stack.push(stack.lpop().convertToDouble(valueFactory)); 430 break; 431 432 case InstructionConstants.OP_F2I: 433 stack.push(stack.fpop().convertToInteger(valueFactory)); 434 break; 435 436 case InstructionConstants.OP_F2L: 437 stack.push(stack.fpop().convertToLong(valueFactory)); 438 break; 439 440 case InstructionConstants.OP_F2D: 441 stack.push(stack.fpop().convertToDouble(valueFactory)); 442 break; 443 444 case InstructionConstants.OP_D2I: 445 stack.push(stack.dpop().convertToInteger(valueFactory)); 446 break; 447 448 case InstructionConstants.OP_D2L: 449 stack.push(stack.dpop().convertToLong(valueFactory)); 450 break; 451 452 case InstructionConstants.OP_D2F: 453 stack.push(stack.dpop().convertToFloat(valueFactory)); 454 break; 455 456 case InstructionConstants.OP_I2B: 457 stack.push(stack.ipop().convertToByte(valueFactory)); 458 break; 459 460 case InstructionConstants.OP_I2C: 461 stack.push(stack.ipop().convertToCharacter(valueFactory)); 462 break; 463 464 case InstructionConstants.OP_I2S: 465 stack.push(stack.ipop().convertToShort(valueFactory)); 466 break; 467 468 case InstructionConstants.OP_LCMP: 469 471 LongValue longValue1 = stack.lpop(); 472 LongValue longValue2 = stack.lpop(); 473 stack.push(longValue2.compare(longValue1, valueFactory)); 474 break; 475 476 case InstructionConstants.OP_FCMPL: 477 FloatValue floatValue1 = stack.fpop(); 478 FloatValue floatValue2 = stack.fpop(); 479 stack.push(floatValue2.compare(floatValue1, valueFactory)); 480 break; 481 482 case InstructionConstants.OP_FCMPG: 483 stack.push(stack.fpop().compareReverse(stack.fpop(), valueFactory)); 484 break; 485 486 case InstructionConstants.OP_DCMPL: 487 DoubleValue doubleValue1 = stack.dpop(); 488 DoubleValue doubleValue2 = stack.dpop(); 489 stack.push(doubleValue2.compare(doubleValue1, valueFactory)); 490 break; 491 492 case InstructionConstants.OP_DCMPG: 493 stack.push(stack.dpop().compareReverse(stack.dpop(), valueFactory)); 494 break; 495 496 case InstructionConstants.OP_IRETURN: 497 invocationUnit.exitMethod(clazz, method, stack.ipop()); 498 branchUnit.returnFromMethod(); 499 break; 500 501 case InstructionConstants.OP_LRETURN: 502 invocationUnit.exitMethod(clazz, method, stack.lpop()); 503 branchUnit.returnFromMethod(); 504 break; 505 506 case InstructionConstants.OP_FRETURN: 507 invocationUnit.exitMethod(clazz, method, stack.fpop()); 508 branchUnit.returnFromMethod(); 509 break; 510 511 case InstructionConstants.OP_DRETURN: 512 invocationUnit.exitMethod(clazz, method, stack.dpop()); 513 branchUnit.returnFromMethod(); 514 break; 515 516 case InstructionConstants.OP_ARETURN: 517 invocationUnit.exitMethod(clazz, method, stack.apop()); 518 branchUnit.returnFromMethod(); 519 break; 520 521 case InstructionConstants.OP_RETURN: 522 branchUnit.returnFromMethod(); 523 break; 524 525 case InstructionConstants.OP_NEWARRAY: 526 IntegerValue arrayLength = stack.ipop(); 527 stack.push(valueFactory.createArrayReferenceValue(String.valueOf(InstructionUtil.internalTypeFromArrayType((byte)simpleInstruction.constant)), 528 null, 529 arrayLength)); 530 break; 531 532 case InstructionConstants.OP_ARRAYLENGTH: 533 stack.apop(); 534 stack.push(valueFactory.createIntegerValue()); 535 break; 536 537 case InstructionConstants.OP_ATHROW: 538 ReferenceValue exceptionReferenceValue = stack.apop(); 539 stack.clear(); 540 stack.push(exceptionReferenceValue); 541 branchUnit.throwException(); 542 break; 543 544 case InstructionConstants.OP_MONITORENTER: 545 case InstructionConstants.OP_MONITOREXIT: 546 stack.apop(); 547 break; 548 549 default: 550 throw new IllegalArgumentException ("Unknown simple instruction ["+simpleInstruction.opcode+"]"); 551 } 552 } 553 554 555 public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction) 556 { 557 int constantIndex = constantInstruction.constantIndex; 558 559 switch (constantInstruction.opcode) 560 { 561 case InstructionConstants.OP_LDC: 562 case InstructionConstants.OP_LDC_W: 563 case InstructionConstants.OP_LDC2_W: 564 stack.push(cpValue(clazz, constantIndex, true)); 565 break; 566 567 case InstructionConstants.OP_GETSTATIC: 568 case InstructionConstants.OP_PUTSTATIC: 569 case InstructionConstants.OP_GETFIELD: 570 case InstructionConstants.OP_PUTFIELD: 571 case InstructionConstants.OP_INVOKEVIRTUAL: 572 case InstructionConstants.OP_INVOKESPECIAL: 573 case InstructionConstants.OP_INVOKESTATIC: 574 case InstructionConstants.OP_INVOKEINTERFACE: 575 invocationUnit.invokeMember(clazz, method, codeAttribute, offset, constantInstruction, stack); 576 break; 577 578 case InstructionConstants.OP_NEW: 579 stack.push(cpValue(clazz, constantIndex).referenceValue()); 580 break; 581 582 case InstructionConstants.OP_ANEWARRAY: 583 { 584 ReferenceValue referenceValue = cpValue(clazz, constantIndex).referenceValue(); 585 586 stack.push(valueFactory.createArrayReferenceValue(referenceValue.internalType(), 587 referenceValue.getReferencedClass(), 588 stack.ipop())); 589 break; 590 } 591 592 case InstructionConstants.OP_CHECKCAST: 593 ReferenceValue castValue = stack.apop(); 595 ReferenceValue castResultValue = 596 castValue.isNull() == Value.ALWAYS ? castValue : 597 castValue.isNull() == Value.NEVER ? cpValue(clazz, constantIndex).referenceValue() : 598 cpValue(clazz, constantIndex).referenceValue().generalize(valueFactory.createReferenceValueNull()); 599 stack.push(castResultValue); 600 break; 601 602 case InstructionConstants.OP_INSTANCEOF: 603 { 604 ReferenceValue referenceValue = cpValue(clazz, constantIndex).referenceValue(); 605 606 int instanceOf = stack.apop().instanceOf(referenceValue.getType(), 607 referenceValue.getReferencedClass()); 608 609 stack.push(instanceOf == Value.NEVER ? valueFactory.createIntegerValue(0) : 610 instanceOf == Value.ALWAYS ? valueFactory.createIntegerValue(1) : 611 valueFactory.createIntegerValue()); 612 break; 613 } 614 615 case InstructionConstants.OP_MULTIANEWARRAY: 616 { 617 int dimensionCount = constantInstruction.constant; 618 for (int dimension = 0; dimension < dimensionCount; dimension++) 619 { 620 IntegerValue arrayLength = stack.ipop(); 622 } 623 624 stack.push(cpValue(clazz, constantIndex).referenceValue()); 625 break; 626 } 627 628 default: 629 throw new IllegalArgumentException ("Unknown constant pool instruction ["+constantInstruction.opcode+"]"); 630 } 631 } 632 633 634 public void visitVariableInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VariableInstruction variableInstruction) 635 { 636 int variableIndex = variableInstruction.variableIndex; 637 638 switch (variableInstruction.opcode) 639 { 640 case InstructionConstants.OP_ILOAD: 641 case InstructionConstants.OP_ILOAD_0: 642 case InstructionConstants.OP_ILOAD_1: 643 case InstructionConstants.OP_ILOAD_2: 644 case InstructionConstants.OP_ILOAD_3: 645 stack.push(variables.iload(variableIndex)); 646 break; 647 648 case InstructionConstants.OP_LLOAD: 649 case InstructionConstants.OP_LLOAD_0: 650 case InstructionConstants.OP_LLOAD_1: 651 case InstructionConstants.OP_LLOAD_2: 652 case InstructionConstants.OP_LLOAD_3: 653 stack.push(variables.lload(variableIndex)); 654 break; 655 656 case InstructionConstants.OP_FLOAD: 657 case InstructionConstants.OP_FLOAD_0: 658 case InstructionConstants.OP_FLOAD_1: 659 case InstructionConstants.OP_FLOAD_2: 660 case InstructionConstants.OP_FLOAD_3: 661 stack.push(variables.fload(variableIndex)); 662 break; 663 664 case InstructionConstants.OP_DLOAD: 665 case InstructionConstants.OP_DLOAD_0: 666 case InstructionConstants.OP_DLOAD_1: 667 case InstructionConstants.OP_DLOAD_2: 668 case InstructionConstants.OP_DLOAD_3: 669 stack.push(variables.dload(variableIndex)); 670 break; 671 672 case InstructionConstants.OP_ALOAD: 673 case InstructionConstants.OP_ALOAD_0: 674 case InstructionConstants.OP_ALOAD_1: 675 case InstructionConstants.OP_ALOAD_2: 676 case InstructionConstants.OP_ALOAD_3: 677 stack.push(variables.aload(variableIndex)); 678 break; 679 680 case InstructionConstants.OP_ISTORE: 681 case InstructionConstants.OP_ISTORE_0: 682 case InstructionConstants.OP_ISTORE_1: 683 case InstructionConstants.OP_ISTORE_2: 684 case InstructionConstants.OP_ISTORE_3: 685 variables.store(variableIndex, stack.ipop()); 686 break; 687 688 case InstructionConstants.OP_LSTORE: 689 case InstructionConstants.OP_LSTORE_0: 690 case InstructionConstants.OP_LSTORE_1: 691 case InstructionConstants.OP_LSTORE_2: 692 case InstructionConstants.OP_LSTORE_3: 693 variables.store(variableIndex, stack.lpop()); 694 break; 695 696 case InstructionConstants.OP_FSTORE: 697 case InstructionConstants.OP_FSTORE_0: 698 case InstructionConstants.OP_FSTORE_1: 699 case InstructionConstants.OP_FSTORE_2: 700 case InstructionConstants.OP_FSTORE_3: 701 variables.store(variableIndex, stack.fpop()); 702 break; 703 704 case InstructionConstants.OP_DSTORE: 705 case InstructionConstants.OP_DSTORE_0: 706 case InstructionConstants.OP_DSTORE_1: 707 case InstructionConstants.OP_DSTORE_2: 708 case InstructionConstants.OP_DSTORE_3: 709 variables.store(variableIndex, stack.dpop()); 710 break; 711 712 case InstructionConstants.OP_ASTORE: 713 case InstructionConstants.OP_ASTORE_0: 714 case InstructionConstants.OP_ASTORE_1: 715 case InstructionConstants.OP_ASTORE_2: 716 case InstructionConstants.OP_ASTORE_3: 717 variables.store(variableIndex, stack.pop()); 721 break; 722 723 case InstructionConstants.OP_IINC: 724 variables.store(variableIndex, 725 variables.iload(variableIndex).add( 726 valueFactory.createIntegerValue(variableInstruction.constant))); 727 break; 728 729 case InstructionConstants.OP_RET: 730 InstructionOffsetValue instructionOffsetValue = variables.oload(variableIndex); 734 branchUnit.branch(clazz, 735 codeAttribute, 736 offset, 737 instructionOffsetValue.instructionOffset(instructionOffsetValue.instructionOffsetCount()-1)); 738 break; 739 740 default: 741 throw new IllegalArgumentException ("Unknown variable instruction ["+variableInstruction.opcode+"]"); 742 } 743 } 744 745 746 public void visitBranchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, BranchInstruction branchInstruction) 747 { 748 int branchTarget = offset + branchInstruction.branchOffset; 749 750 switch (branchInstruction.opcode) 751 { 752 case InstructionConstants.OP_IFEQ: 753 branchUnit.branchConditionally(clazz, codeAttribute, offset, branchTarget, 754 stack.ipop().equal(valueFactory.createIntegerValue(0))); 755 break; 756 757 case InstructionConstants.OP_IFNE: 758 branchUnit.branchConditionally(clazz, codeAttribute, offset, branchTarget, 759 stack.ipop().notEqual(valueFactory.createIntegerValue(0))); 760 break; 761 762 case InstructionConstants.OP_IFLT: 763 branchUnit.branchConditionally(clazz, codeAttribute, offset, branchTarget, 764 stack.ipop().lessThan(valueFactory.createIntegerValue(0))); 765 break; 766 767 case InstructionConstants.OP_IFGE: 768 branchUnit.branchConditionally(clazz, codeAttribute, offset, branchTarget, 769 stack.ipop().greaterThanOrEqual(valueFactory.createIntegerValue(0))); 770 break; 771 772 case InstructionConstants.OP_IFGT: 773 branchUnit.branchConditionally(clazz, codeAttribute, offset, branchTarget, 774 stack.ipop().greaterThan(valueFactory.createIntegerValue(0))); 775 break; 776 777 case InstructionConstants.OP_IFLE: 778 branchUnit.branchConditionally(clazz, codeAttribute, offset, branchTarget, 779 stack.ipop().lessThanOrEqual(valueFactory.createIntegerValue(0))); 780 break; 781 782 783 case InstructionConstants.OP_IFICMPEQ: 784 branchUnit.branchConditionally(clazz, codeAttribute, offset, branchTarget, 785 stack.ipop().equal(stack.ipop())); 786 break; 787 788 case InstructionConstants.OP_IFICMPNE: 789 branchUnit.branchConditionally(clazz, codeAttribute, offset, branchTarget, 790 stack.ipop().notEqual(stack.ipop())); 791 break; 792 793 case InstructionConstants.OP_IFICMPLT: 794 branchUnit.branchConditionally(clazz, codeAttribute, offset, branchTarget, 796 stack.ipop().greaterThan(stack.ipop())); 797 break; 798 799 case InstructionConstants.OP_IFICMPGE: 800 branchUnit.branchConditionally(clazz, codeAttribute, offset, branchTarget, 802 stack.ipop().lessThanOrEqual(stack.ipop())); 803 break; 804 805 case InstructionConstants.OP_IFICMPGT: 806 branchUnit.branchConditionally(clazz, codeAttribute, offset, branchTarget, 808 stack.ipop().lessThan(stack.ipop())); 809 break; 810 811 case InstructionConstants.OP_IFICMPLE: 812 branchUnit.branchConditionally(clazz, codeAttribute, offset, branchTarget, 814 stack.ipop().greaterThanOrEqual(stack.ipop())); 815 break; 816 817 case InstructionConstants.OP_IFACMPEQ: 818 branchUnit.branchConditionally(clazz, codeAttribute, offset, branchTarget, 819 stack.apop().equal(stack.apop())); 820 break; 821 822 case InstructionConstants.OP_IFACMPNE: 823 branchUnit.branchConditionally(clazz, codeAttribute, offset, branchTarget, 824 stack.apop().notEqual(stack.apop())); 825 break; 826 827 case InstructionConstants.OP_GOTO: 828 case InstructionConstants.OP_GOTO_W: 829 branchUnit.branch(clazz, codeAttribute, offset, branchTarget); 830 break; 831 832 833 case InstructionConstants.OP_JSR: 834 case InstructionConstants.OP_JSR_W: 835 stack.push(new InstructionOffsetValue(offset + 836 branchInstruction.length(offset))); 837 branchUnit.branch(clazz, codeAttribute, offset, branchTarget); 838 break; 839 840 case InstructionConstants.OP_IFNULL: 841 branchUnit.branchConditionally(clazz, codeAttribute, offset, branchTarget, 842 stack.apop().isNull()); 843 break; 844 845 case InstructionConstants.OP_IFNONNULL: 846 branchUnit.branchConditionally(clazz, codeAttribute, offset, branchTarget, 847 stack.apop().isNotNull()); 848 break; 849 850 default: 851 throw new IllegalArgumentException ("Unknown branch instruction ["+branchInstruction.opcode+"]"); 852 } 853 } 854 855 856 public void visitTableSwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, TableSwitchInstruction tableSwitchInstruction) 857 { 858 IntegerValue indexValue = stack.ipop(); 859 860 branchUnit.branch(clazz, codeAttribute, 863 offset, 864 offset + tableSwitchInstruction.defaultOffset); 865 866 for (int index = 0; index < tableSwitchInstruction.jumpOffsets.length; index++) 867 { 868 int conditional = indexValue.equal(valueFactory.createIntegerValue( 869 tableSwitchInstruction.lowCase + index)); 870 branchUnit.branchConditionally(clazz, codeAttribute, 871 offset, 872 offset + tableSwitchInstruction.jumpOffsets[index], 873 conditional); 874 875 if (conditional == Value.ALWAYS) 877 { 878 break; 879 } 880 } 881 } 882 883 884 public void visitLookUpSwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, LookUpSwitchInstruction lookUpSwitchInstruction) 885 { 886 IntegerValue indexValue = stack.ipop(); 887 888 branchUnit.branch(clazz, codeAttribute, 891 offset, 892 offset + lookUpSwitchInstruction.defaultOffset); 893 894 for (int index = 0; index < lookUpSwitchInstruction.jumpOffsets.length; index++) 895 { 896 int conditional = indexValue.equal(valueFactory.createIntegerValue( 897 lookUpSwitchInstruction.cases[index])); 898 branchUnit.branchConditionally(clazz, codeAttribute, 899 offset, 900 offset + lookUpSwitchInstruction.jumpOffsets[index], 901 conditional); 902 903 if (conditional == Value.ALWAYS) 905 { 906 break; 907 } 908 } 909 } 910 911 912 914 public void visitIntegerConstant(Clazz clazz, IntegerConstant integerConstant) 915 { 916 cpValue = valueFactory.createIntegerValue(integerConstant.getValue()); 917 } 918 919 public void visitLongConstant(Clazz clazz, LongConstant longConstant) 920 { 921 cpValue = valueFactory.createLongValue(longConstant.getValue()); 922 } 923 924 public void visitFloatConstant(Clazz clazz, FloatConstant floatConstant) 925 { 926 cpValue = valueFactory.createFloatValue(floatConstant.getValue()); 927 } 928 929 public void visitDoubleConstant(Clazz clazz, DoubleConstant doubleConstant) 930 { 931 cpValue = valueFactory.createDoubleValue(doubleConstant.getValue()); 932 } 933 934 public void visitStringConstant(Clazz clazz, StringConstant stringConstant) 935 { 936 cpValue = valueFactory.createReferenceValue(ClassConstants.INTERNAL_NAME_JAVA_LANG_STRING, 937 null, 938 false); 939 } 940 941 public void visitClassConstant(Clazz clazz, ClassConstant classConstant) 942 { 943 cpValue = handleClassConstantAsClassValue ? 944 valueFactory.createReferenceValue(ClassConstants.INTERNAL_NAME_JAVA_LANG_CLASS, 945 null, 946 false) : 947 valueFactory.createReferenceValue(classConstant.getName(clazz), 948 classConstant.referencedClass, 949 false); 950 } 951 952 953 955 958 private Value cpValue(Clazz clazz, 959 int constantIndex) 960 { 961 return cpValue(clazz, constantIndex, false); 962 } 963 964 965 968 private Value cpValue(Clazz clazz, 969 int constantIndex, 970 boolean handleClassConstantAsClassValue) 971 { 972 this.handleClassConstantAsClassValue = handleClassConstantAsClassValue; 973 974 clazz.constantPoolEntryAccept(constantIndex, this); 976 977 return cpValue; 978 } 979 } 980
| Popular Tags
|