1 19 20 package jode.bytecode; 21 22 26 public final class Instruction implements Opcodes{ 27 33 private int opcode; 35 39 private int shortData; 40 43 private int addr; 44 58 private Object objData; 59 65 private Object succs; 66 70 private Instruction[] preds; 71 74 Instruction nextByAddr; 75 79 Instruction prevByAddr; 80 81 87 private Object tmpInfo; 88 89 public Instruction(int opcode) { 90 this.opcode = opcode; 91 } 92 93 105 public final int getOpcode() { 106 return opcode; 107 } 108 109 120 public final int getAddr() { 121 return addr; 122 } 123 124 public final int getNextAddr() { 125 return nextByAddr.addr; 126 } 127 128 135 public final int getLength() { 136 return getNextAddr() - addr; 137 } 138 139 final void setAddr(int addr) { 140 this.addr = addr; 141 } 142 143 public final boolean hasLocalSlot() { 144 return opcode == opc_iinc || opcode == opc_ret 145 || opcode >= opc_iload && opcode <= opc_aload 146 || opcode >= opc_istore && opcode <= opc_astore; 147 } 148 149 public final int getLocalSlot() 150 152 { 153 return shortData; 154 } 155 156 public final void setLocalSlot(int slot) 157 159 { 160 shortData = slot; 161 } 162 163 173 public final int getIncrement() 174 177 { 178 179 return ((Short ) objData).shortValue(); 180 } 181 182 192 public final void setIncrement(int incr) 193 195 { 196 197 objData = new Short ((short) incr); 198 } 199 200 203 public final int getDimensions() 204 206 { 207 return shortData; 208 } 209 210 213 public final void setDimensions(int dims) 214 216 { 217 shortData = dims; 218 } 219 220 public final Object getConstant() 221 223 { 224 return objData; 225 } 226 227 public final void setConstant(Object constant) 228 230 { 231 objData = constant; 232 } 233 234 public final Reference getReference() 235 237 { 238 return (Reference) objData; 239 } 240 241 public final void setReference(Reference ref) 242 244 { 245 objData = ref; 246 } 247 248 public final String getClazzType() 249 254 { 255 return (String ) objData; 256 } 257 258 public final void setClazzType(String type) 259 264 { 265 objData = type; 266 } 267 268 public final int[] getValues() 269 271 { 272 return (int[]) objData; 273 } 274 275 public final void setValues(int[] values) 276 278 { 279 objData = values; 280 } 281 282 public final boolean doesAlwaysJump() { 283 switch (opcode) { 284 case opc_ret: 285 case opc_goto: 286 case opc_jsr: 287 case opc_tableswitch: 288 case opc_lookupswitch: 289 case opc_ireturn: 290 case opc_lreturn: 291 case opc_freturn: 292 case opc_dreturn: 293 case opc_areturn: 294 case opc_return: 295 case opc_athrow: 296 return true; 297 default: 298 return false; 299 } 300 } 301 302 public final Instruction[] getPreds() { 303 return preds; 304 } 305 306 310 public boolean hasSuccs() { 311 return succs != null; 312 } 313 314 319 public final Instruction[] getSuccs() { 320 if (succs instanceof Instruction) 321 return new Instruction[] { (Instruction) succs }; 322 return (Instruction[]) succs; 323 } 324 325 331 public final Instruction getSingleSucc() { 332 return (Instruction) succs; 333 } 334 335 public final Instruction getPrevByAddr() { 336 if (prevByAddr.opcode == opc_impdep1) 337 return null; 338 return prevByAddr; 339 } 340 341 public final Instruction getNextByAddr() { 342 if (nextByAddr.opcode == opc_impdep1) 343 return null; 344 return nextByAddr; 345 } 346 347 public final Object getTmpInfo() { 348 return tmpInfo; 349 } 350 351 public final void setTmpInfo(Object info) { 352 tmpInfo = info; 353 } 354 355 356 358 final void removeSuccs() { 359 if (succs == null) 360 return; 361 if (succs instanceof Instruction[]) { 362 Instruction[] ss = (Instruction[]) succs; 363 for (int i = 0; i < ss.length; i++) 364 if (ss[i] != null) 365 ss[i].removePredecessor(this); 366 } else 367 ((Instruction) succs).removePredecessor(this); 368 succs = null; 369 } 370 371 374 private final void promoteSuccs(Instruction from, Instruction to) { 375 if (succs == from) 376 succs = to; 377 else if (succs instanceof Instruction[]) { 378 Instruction[] ss = (Instruction[]) succs; 379 for (int i = 0; i < ss.length; i++) 380 if (ss[i] == from) 381 ss[i] = to; 382 } 383 } 384 385 389 public final void setSuccs(Object newSuccs) { 390 if (succs == newSuccs) 391 return; 392 removeSuccs(); 393 if (newSuccs == null) 394 return; 395 if (newSuccs instanceof Instruction[]) { 396 Instruction[] ns = (Instruction[]) newSuccs; 397 switch (ns.length) { 398 case 0: 399 break; 400 case 1: 401 succs = ns[0]; 402 ns[0].addPredecessor(this); 403 break; 404 default: 405 succs = ns; 406 for (int i = 0; i < ns.length; i++) 407 ns[i].addPredecessor(this); 408 break; 409 } 410 } else { 411 succs = newSuccs; 412 ((Instruction) newSuccs).addPredecessor(this); 413 } 414 } 415 416 void addPredecessor(Instruction pred) { 417 if (preds == null) { 418 preds = new Instruction[] { pred }; 419 return; 420 } 421 int predsLength = preds.length; 422 Instruction[] newPreds = new Instruction[predsLength+1]; 423 System.arraycopy(preds, 0, newPreds, 0, predsLength); 424 newPreds[predsLength] = pred; 425 preds = newPreds; 426 } 427 428 void removePredecessor(Instruction pred) { 429 430 int predLength = preds.length; 431 if (predLength == 1) { 432 if (preds[0] != pred) 433 throw new jode.AssertError 434 ("removing not existing predecessor"); 435 preds = null; 436 } else { 437 Instruction[] newPreds = new Instruction[predLength-1]; 438 int j; 439 for (j = 0; preds[j] != pred; j++) 440 newPreds[j] = preds[j]; 441 System.arraycopy(preds, j+1, newPreds, j, predLength - j - 1); 442 preds = newPreds; 443 } 444 } 445 446 448 461 public final void replaceInstruction(Instruction newInstr, 462 BytecodeInfo codeinfo) { 463 464 removeSuccs(); 465 466 newInstr.addr = addr; 467 nextByAddr.prevByAddr = newInstr; 468 newInstr.nextByAddr = nextByAddr; 469 prevByAddr.nextByAddr = newInstr; 470 newInstr.prevByAddr = prevByAddr; 471 prevByAddr = null; 472 nextByAddr = null; 473 474 475 if (preds != null) { 476 for (int j=0; j < preds.length; j++) 477 preds[j].promoteSuccs(this, newInstr); 478 newInstr.preds = preds; 479 preds = null; 480 } 481 482 483 Handler[] handlers = codeinfo.getExceptionHandlers(); 484 for (int i=0; i< handlers.length; i++) { 485 if (handlers[i].start == this) 486 handlers[i].start = newInstr; 487 if (handlers[i].end == this) 488 handlers[i].end = newInstr; 489 if (handlers[i].catcher == this) 490 handlers[i].catcher = newInstr; 491 } 492 493 494 LocalVariableInfo[] lvt = codeinfo.getLocalVariableTable(); 495 if (lvt != null) { 496 for (int i=0; i< lvt.length; i++) { 497 if (lvt[i].start == this) 498 lvt[i].start = newInstr; 499 if (lvt[i].end == this) 500 lvt[i].end = newInstr; 501 } 502 } 503 LineNumber[] lnt = codeinfo.getLineNumberTable(); 504 if (lnt != null) { 505 for (int i=0; i< lnt.length; i++) { 506 if (lnt[i].start == this) 507 lnt[i].start = newInstr; 508 } 509 } 510 } 511 512 void appendInstruction(Instruction newInstr, BytecodeInfo codeinfo) { 513 newInstr.addr = nextByAddr.addr; 514 515 newInstr.nextByAddr = nextByAddr; 516 nextByAddr.prevByAddr = newInstr; 517 newInstr.prevByAddr = this; 518 nextByAddr = newInstr; 519 520 521 Handler[] handlers = codeinfo.getExceptionHandlers(); 522 if (handlers != null) { 523 for (int i=0; i< handlers.length; i++) { 524 if (handlers[i].end == this) 525 handlers[i].end = newInstr; 526 } 527 } 528 } 529 530 533 void removeInstruction(BytecodeInfo codeinfo) { 534 535 536 prevByAddr.nextByAddr = nextByAddr; 537 nextByAddr.prevByAddr = prevByAddr; 538 539 540 removeSuccs(); 541 542 543 if (preds != null) { 544 for (int j=0; j < preds.length; j++) 545 preds[j].promoteSuccs(this, nextByAddr); 546 if (nextByAddr.preds == null) 547 nextByAddr.preds = preds; 548 else { 549 Instruction[] newPreds = new Instruction 550 [nextByAddr.preds.length + preds.length]; 551 System.arraycopy(nextByAddr.preds, 0, newPreds, 0, 552 nextByAddr.preds.length); 553 System.arraycopy(preds, 0, newPreds, nextByAddr.preds.length, 554 preds.length); 555 nextByAddr.preds = newPreds; 556 } 557 preds = null; 558 } 559 560 561 Handler[] handlers = codeinfo.getExceptionHandlers(); 562 for (int i=0; i< handlers.length; i++) { 563 if (handlers[i].start == this && handlers[i].end == this) { 564 566 Handler[] newHandlers = new Handler[handlers.length - 1]; 567 System.arraycopy(handlers, 0, newHandlers, 0, i); 568 System.arraycopy(handlers, i+1, newHandlers, i, 569 handlers.length - (i+1)); 570 handlers = newHandlers; 571 codeinfo.setExceptionHandlers(newHandlers); 572 i--; 573 } else { 574 if (handlers[i].start == this) 575 handlers[i].start = nextByAddr; 576 if (handlers[i].end == this) 577 handlers[i].end = prevByAddr; 578 if (handlers[i].catcher == this) 579 handlers[i].catcher = nextByAddr; 580 } 581 } 582 583 584 LocalVariableInfo[] lvt = codeinfo.getLocalVariableTable(); 585 if (lvt != null) { 586 for (int i=0; i< lvt.length; i++) { 587 if (lvt[i].start == this && lvt[i].end == this) { 588 591 LocalVariableInfo[] newLVT = 592 new LocalVariableInfo[lvt.length - 1]; 593 System.arraycopy(lvt, 0, newLVT, 0, i); 594 System.arraycopy(lvt, i+1, newLVT, i, 595 newLVT.length - i); 596 lvt = newLVT; 597 codeinfo.setLocalVariableTable(newLVT); 598 i--; 599 } else { 600 if (lvt[i].start == this) 601 lvt[i].start = nextByAddr; 602 if (lvt[i].end == this) 603 lvt[i].end = prevByAddr; 604 } 605 } 606 } 607 LineNumber[] lnt = codeinfo.getLineNumberTable(); 608 if (lnt != null) { 609 for (int i=0; i< lnt.length; i++) { 610 if (lnt[i].start == this) { 611 if (nextByAddr.opcode == opc_impdep1 612 || (i+1 < lnt.length 613 && lnt[i+1].start == nextByAddr)) { 614 616 LineNumber[] newLNT = 617 new LineNumber[lnt.length - 1]; 618 System.arraycopy(lnt, 0, newLNT, 0, i); 619 System.arraycopy(lnt, i+1, newLNT, i, 620 newLNT.length - i); 621 lnt = newLNT; 622 codeinfo.setLineNumberTable(newLNT); 623 i--; 624 } else 625 lnt[i].start = nextByAddr; 626 } 627 } 628 } 629 630 prevByAddr = null; 631 nextByAddr = null; 632 } 633 634 public int compareTo(Instruction instr) { 635 if (addr != instr.addr) 636 return addr - instr.addr; 637 if (this == instr) 638 return 0; 639 do { 640 instr = instr.nextByAddr; 641 if (instr.addr > addr) 642 return -1; 643 } while (instr != this); 644 return 1; 645 } 646 647 655 public void getStackPopPush(int[] poppush) 656 658 { 659 byte delta = (byte) stackDelta.charAt(opcode); 660 if (delta < 0x40) { 661 poppush[0] = delta & 7; 662 poppush[1] = delta >> 3; 663 } else { 664 switch (opcode) { 665 case opc_invokevirtual: 666 case opc_invokespecial: 667 case opc_invokestatic: 668 case opc_invokeinterface: { 669 Reference ref = getReference(); 670 String typeSig = ref.getType(); 671 poppush[0] = opcode != opc_invokestatic ? 1 : 0; 672 poppush[0] += TypeSignature.getArgumentSize(typeSig); 673 poppush[1] = TypeSignature.getReturnSize(typeSig); 674 break; 675 } 676 677 case opc_putfield: 678 case opc_putstatic: { 679 Reference ref = getReference(); 680 poppush[1] = 0; 681 poppush[0] = TypeSignature.getTypeSize(ref.getType()); 682 if (opcode == opc_putfield) 683 poppush[0]++; 684 break; 685 } 686 case opc_getstatic: 687 case opc_getfield: { 688 Reference ref = getReference(); 689 poppush[1] = TypeSignature.getTypeSize(ref.getType()); 690 poppush[0] = opcode == opc_getfield ? 1 : 0; 691 break; 692 } 693 694 case opc_multianewarray: { 695 poppush[1] = 1; 696 poppush[0] = getDimensions(); 697 break; 698 } 699 default: 700 throw new jode.AssertError("Unknown Opcode: "+opcode); 701 } 702 } 703 } 704 705 public Instruction findMatchingPop() { 706 int poppush[] = new int[2]; 707 getStackPopPush(poppush); 708 709 int count = poppush[1]; 710 Instruction instr = this; 711 while (true) { 712 if (instr.succs != null || instr.doesAlwaysJump()) 713 return null; 714 instr = instr.nextByAddr; 715 if (instr.preds != null) 716 return null; 717 718 instr.getStackPopPush(poppush); 719 if (count == poppush[0]) 720 return instr; 721 count += poppush[1] - poppush[0]; 722 } 723 } 724 725 public Instruction findMatchingPush() { 726 int count = 0; 727 Instruction instr = this; 728 int poppush[] = new int[2]; 729 while (true) { 730 if (instr.preds != null) 731 return null; 732 instr = instr.prevByAddr; 733 if (instr == null || instr.succs != null || instr.doesAlwaysJump()) 734 return null; 735 736 instr.getStackPopPush(poppush); 737 if (count < poppush[1]) { 738 return count == 0 ? instr : null; 739 } 740 count += poppush[0] - poppush[1]; 741 } 742 } 743 744 public String getDescription() { 745 StringBuffer result = new StringBuffer (String.valueOf(addr)) 746 .append('_').append(Integer.toHexString(hashCode())) 747 .append(": ").append(opcodeString[opcode]); 748 if (opcode != opc_lookupswitch) { 749 if (hasLocalSlot()) 750 result.append(' ').append(getLocalSlot()); 751 if (succs != null) 752 result.append(' ').append(((Instruction) succs).addr); 753 if (objData != null) 754 result.append(' ').append(objData); 755 if (opcode == opc_multianewarray) 756 result.append(' ').append(getDimensions()); 757 } else { 758 int[] values = getValues(); 759 Instruction[] succs = getSuccs(); 760 for (int i=0; i < values.length; i++) { 761 result.append(' ').append(values[i]).append("->") 762 .append(((Instruction) succs[i]).addr); 763 } 764 result.append(' ').append("default: ") 765 .append(((Instruction) succs[values.length]).addr); 766 } 767 return result.toString(); 768 } 769 770 public String toString() { 771 return "" + addr + "_" + Integer.toHexString(hashCode()); 772 } 773 774 private final static String stackDelta = 775 "\000\010\010\010\010\010\010\010\010\020\020\010\010\010\020\020\010\010\010\010\020\010\020\010\020\010\010\010\010\010\020\020\020\020\010\010\010\010\020\020\020\020\010\010\010\010\012\022\012\022\012\012\012\012\001\002\001\002\001\001\001\001\001\002\002\002\002\001\001\001\001\002\002\002\002\001\001\001\001\003\004\003\004\003\003\003\003\001\002\021\032\043\042\053\064\022\012\024\012\024\012\024\012\024\012\024\012\024\012\024\012\024\012\024\012\024\011\022\011\022\012\023\012\023\012\023\012\024\012\024\012\024\000\021\011\021\012\012\022\011\021\021\012\022\012\011\011\011\014\012\012\014\014\001\001\001\001\001\001\002\002\002\002\002\002\002\002\000\010\000\001\001\001\002\001\002\001\000\100\100\100\100\100\100\100\100\177\010\011\011\011\001\011\011\001\001\177\100\001\001\000\010"; 776 777 830 } 831 | Popular Tags |