1 package alt.jiapi.reflect; 2 3 import java.util.Iterator ; 4 import java.util.List ; 5 import java.util.LinkedList ; 6 7 import alt.jiapi.file.ConstantPool; 8 import alt.jiapi.reflect.instruction.CPInstruction; 9 import alt.jiapi.reflect.instruction.Opcodes; 10 11 16 public class InstructionList { 17 18 private JiapiMethod declaringMethod; 19 ConstantPool constantPool; 20 List instructions; 21 22 private boolean modified = false; 24 26 public InstructionList() { 27 this.constantPool = new ConstantPool(); 28 this.instructions = new LinkedList (); 29 } 30 31 38 InstructionList(byte[] byteCode, ConstantPool cp) { 39 this.constantPool = cp; 40 41 InstructionFactory factory = new InstructionFactory(cp); 42 instructions = factory.createInstructionList(byteCode); 43 } 44 45 46 47 52 private InstructionList(ConstantPool cp, List instructions) { 53 this.constantPool = cp; 54 this.instructions = instructions; 55 } 56 57 58 63 InstructionList(ConstantPool cp) { 64 this.constantPool = cp; 65 this.instructions = new LinkedList (); 66 } 67 68 69 72 public InstructionList createEmptyList() { 73 return new InstructionList(constantPool); 74 } 75 76 85 public byte[] getBytes() { 86 Iterator i = instructions.iterator(); 88 int bSize = 0; 89 while(i.hasNext()) { 90 bSize += ((Instruction)i.next()).length(); 91 } 92 93 byte[] bytes = new byte[bSize]; 95 int bIdx = 0; 96 i = instructions.iterator(); 97 while(i.hasNext()) { 98 Instruction ins = (Instruction)i.next(); 99 byte[] iBytes = ins.getBytes(); 100 101 for (int j = 0; j < iBytes.length; j++) { 102 bytes[bIdx] = iBytes[j]; 103 bIdx++; 104 } 105 } 106 107 this.modified = false; 109 110 return bytes; 111 } 112 113 114 117 public void add(Instruction i) { 118 modified = true; 119 i.setAttribute("synthetic"); 120 121 if (i instanceof CPInstruction) { 122 CPInstruction cpIns = (CPInstruction)i; 123 ConstantPool cp = cpIns.getConstantPool(); 124 125 if (!constantPool.equals(cp)) { 126 cpIns.replaceConstantPool(constantPool); 127 } 128 } 129 130 instructions.add(i); 131 } 132 133 138 public void add(InstructionList il) { 139 modified = true; 140 if (il.size() == 0) { 141 return; 142 } 143 144 for (int i = 0; i < il.size(); i++) { 145 add(il.get(i)); 146 } 147 } 148 149 155 public boolean insert(int idx, Instruction i) { 156 modified = true; 157 i.setAttribute("synthetic"); 158 159 if (i instanceof CPInstruction) { 160 CPInstruction cpIns = (CPInstruction)i; 161 ConstantPool cp = cpIns.getConstantPool(); 162 163 if (!constantPool.equals(cp)) { 164 cpIns.replaceConstantPool(constantPool); 165 } 166 } 167 168 169 return instructions.subList(0, idx).add(i); 170 } 171 172 178 public boolean insert(int idx, InstructionList il) { 179 modified = true; 180 181 if (il.size() == 0) { 182 return true; 183 } 184 185 for (int i = 0; i < il.size(); i++) { 193 insert(idx + i, il.get(i)); 194 } 195 197 198 return true; 199 } 200 201 202 210 public Instruction get(int i) { 211 Instruction ins = (Instruction)instructions.get(i); 212 213 if (ins instanceof TargetInstruction) { 214 return ((TargetInstruction)ins).getTarget(); 215 } 216 217 return ins; 218 } 219 220 221 227 public void replace(int idx, Instruction i) { 228 if (i == null) { 229 throw new NullPointerException ("Instruction may not be null"); 231 } 232 233 instructions.set(idx, i); 236 } 237 238 public void replace(InstructionList il) { 239 replace(0, size(), il); 240 } 241 242 263 public void replace(int start, int end, InstructionList il) { 264 InstructionList __il = createView(start, end); 265 int su1 = __il.stackUsage(); 266 int su2 = il.stackUsage(); 267 268 if (su1 != su2) { 269 System.out.println("Replacing "); 270 print(__il); 271 System.out.println("with"); 272 print(il); 273 274 throw new IllegalArgumentException ("Cannot replace instruction list; stack usages differ: " + su1 + "(this list), " + su2 + " (other list)"); 275 } 276 277 278 Instruction first = (Instruction)__il.instructions.get(0); 279 if (first instanceof TargetInstruction) { 280 TargetInstruction tIns = (TargetInstruction)first; 283 tIns.setTarget((Instruction)il.get(0)); 284 il.instructions.set(0, tIns); 285 } 286 287 for (int i = 1; i < __il.size(); i++) { 290 if (__il.instructions.get(i) instanceof TargetInstruction) { 291 throw new IllegalArgumentException ("Cannot replace instructions since there are at least one 'target' instruction in it"); 292 } 293 } 294 295 __il.clear(); 297 __il.add(il); 298 } 299 300 301 306 public int stackUsage() { 307 int su = 0; 308 for (int i = 0; i < size(); i++) { 309 su += get(i).stackUsage(); 310 } 311 312 return su; 313 } 314 315 320 public int size() { 321 return instructions.size(); 322 } 323 324 325 332 public int indexOf(Instruction ins) { 333 return instructions.indexOf(ins); 334 } 335 336 337 338 345 public int indexOf(byte opcode) { 346 return indexOf(new byte[]{opcode}, 0); 347 } 348 349 356 public int indexOf(byte opcode, int fromIndex) { 357 return indexOf(new byte[]{opcode}, fromIndex); 358 } 359 360 367 public int indexOf(byte[] opcodes, int fromIndex) { 368 for (int i = fromIndex; i < instructions.size(); i++) { 369 Instruction ins = (Instruction)instructions.get(i); 370 short opCode = ins.getOpcode(); 371 372 for (int j = 0; j < opcodes.length; j++) { 373 if (opcodes[j] == opCode) { 374 return i; 375 } 376 } 377 } 378 379 return -1; 380 } 381 382 383 int offset(Instruction i) { 384 return offset(0, i); 385 } 386 387 int offset(int start, Instruction ins) { 388 int offset = 0; 389 for (int i = start; i < instructions.size(); i++) { 390 if (instructions.get(i).equals(ins)) { 391 return offset; 392 } 393 394 offset += ((Instruction)instructions.get(i)).length(); 395 } 396 397 throw new JiapiRuntimeException("Isntruction not found; " + ins); 398 } 399 400 406 Instruction instructionAtOffset(short offset) { 407 Iterator i = instructions.iterator(); 408 409 while(i.hasNext()) { 410 Instruction ins = (Instruction)i.next(); 411 if (ins.getOffset() == offset) { 412 return ins; 413 } 414 415 if (ins.getOffset() > offset) { 416 break; 417 } 418 } 419 420 return null; 421 } 422 423 424 public String toString() { 425 if (instructions.size() == 0) { 426 return "<empty>"; 427 } 428 429 StringBuffer sb = new StringBuffer (); 430 Iterator i = instructions.iterator(); 431 int offset = 0; 432 int count = 0; 433 while(i.hasNext()) { 434 Instruction ins = (Instruction)i.next(); 435 sb.append(" #"); 436 sb.append(count); 437 if (count < 10) { 438 sb.append(' '); 439 } 440 if (count < 100) { 441 if (size() >= 100) { 442 sb.append(' '); 443 } 444 } 445 446 sb.append(" ("); 447 sb.append(offset); 448 sb.append(") "); 449 450 sb.append(ins.toString()); 451 if (i.hasNext()) { 452 sb.append('\n'); 453 } 454 455 count++; 456 offset += ins.length(); 457 } 458 459 return sb.toString(); 460 } 461 462 463 private boolean isModified() { 464 return modified; 465 } 466 467 470 public void clear() { 471 instructions.clear(); 472 } 473 474 478 public InstructionFactory getInstructionFactory() { 479 return new InstructionFactory(constantPool); 480 } 481 482 485 public JiapiMethod getDeclaringMethod() { 486 return declaringMethod; 487 } 488 489 void setDeclaringMethod(JiapiMethod jm) { 491 this.declaringMethod = jm; 492 } 493 494 495 501 public InstructionList createView(int start) { 502 return createView(0, instructions.size()); 503 } 504 505 506 512 public InstructionList createView(int start, int end) { 513 InstructionList il = 514 new InstructionList(constantPool,instructions.subList(start, end)); 515 il.setDeclaringMethod(declaringMethod); 516 517 return il; 518 } 519 520 521 524 void updateOffsets() { 525 short offset = 0; 526 Iterator i = instructions.iterator(); 527 528 while(i.hasNext()) { 529 Instruction ins = (Instruction)i.next(); 530 ins.setOffset(offset); 531 532 offset += ins.length(); 536 } 537 } 538 539 540 private void print(InstructionList il) { 541 for (int i = 0; i < il.size(); i++) { 542 Instruction ins = il.get(i); 543 System.out.println(" #" + (i) + " " + ins + ", stack-usage: " + 544 ins.stackUsage()); 545 } 546 } 547 548 549 561 private Instruction changeLocalVars(Instruction ins) { 562 568 int maxLocals = getDeclaringMethod().getMaxLocals(); 573 578 InstructionFactory factory = new InstructionFactory(); 579 switch(ins.getOpcode()) { 580 case Opcodes.ALOAD_0: 582 return factory.aload(maxLocals); 583 case Opcodes.ALOAD_1: 584 return factory.aload(maxLocals + 1); 585 case Opcodes.ALOAD_2: 586 return factory.aload(maxLocals + 2); 587 case Opcodes.ALOAD_3: 588 return factory.aload(maxLocals + 3); 589 case Opcodes.ALOAD: 590 ins.getBytes()[1] += (byte)maxLocals; 594 break; 595 case Opcodes.ASTORE_0: 596 return factory.astore(maxLocals); 597 case Opcodes.ASTORE_1: 598 return factory.astore(maxLocals + 1); 599 case Opcodes.ASTORE_2: 600 return factory.astore(maxLocals + 2); 601 case Opcodes.ASTORE_3: 602 return factory.astore(maxLocals + 3); 603 case Opcodes.ASTORE: 604 ins.getBytes()[1] += (byte)maxLocals; 608 break; 609 610 case Opcodes.ILOAD_0: 612 return factory.iload(maxLocals); 613 case Opcodes.ILOAD_1: 614 return factory.iload(maxLocals + 1); 615 case Opcodes.ILOAD_2: 616 return factory.iload(maxLocals + 2); 617 case Opcodes.ILOAD_3: 618 return factory.iload(maxLocals + 3); 619 case Opcodes.ILOAD: 620 ins.getBytes()[1] += (byte)maxLocals; 624 break; 625 case Opcodes.ISTORE_0: 626 return factory.istore(maxLocals); 627 case Opcodes.ISTORE_1: 628 return factory.istore(maxLocals + 1); 629 case Opcodes.ISTORE_2: 630 return factory.istore(maxLocals + 2); 631 case Opcodes.ISTORE_3: 632 return factory.istore(maxLocals + 3); 633 case Opcodes.ISTORE: 634 ins.getBytes()[1] += (byte)maxLocals; 638 break; 639 640 case Opcodes.DLOAD_0: 642 return factory.dload(maxLocals); 643 case Opcodes.DLOAD_1: 644 return factory.dload(maxLocals + 1); 645 case Opcodes.DLOAD_2: 646 return factory.dload(maxLocals + 2); 647 case Opcodes.DLOAD_3: 648 return factory.dload(maxLocals + 3); 649 case Opcodes.DLOAD: 650 ins.getBytes()[1] += (byte)maxLocals; 654 break; 655 case Opcodes.DSTORE_0: 656 return factory.dstore(maxLocals); 657 case Opcodes.DSTORE_1: 658 return factory.dstore(maxLocals + 1); 659 case Opcodes.DSTORE_2: 660 return factory.dstore(maxLocals + 2); 661 case Opcodes.DSTORE_3: 662 return factory.dstore(maxLocals + 3); 663 case Opcodes.DSTORE: 664 ins.getBytes()[1] += (byte)maxLocals; 668 break; 669 670 case Opcodes.LLOAD_0: 672 return factory.lload(maxLocals); 673 case Opcodes.LLOAD_1: 674 return factory.lload(maxLocals + 1); 675 case Opcodes.LLOAD_2: 676 return factory.lload(maxLocals + 2); 677 case Opcodes.LLOAD_3: 678 return factory.lload(maxLocals + 3); 679 case Opcodes.LLOAD: 680 ins.getBytes()[1] += (byte)maxLocals; 684 break; 685 case Opcodes.LSTORE_0: 686 return factory.lstore(maxLocals); 687 case Opcodes.LSTORE_1: 688 return factory.lstore(maxLocals + 1); 689 case Opcodes.LSTORE_2: 690 return factory.lstore(maxLocals + 2); 691 case Opcodes.LSTORE_3: 692 return factory.lstore(maxLocals + 3); 693 case Opcodes.LSTORE: 694 ins.getBytes()[1] += (byte)maxLocals; 698 break; 699 700 case Opcodes.FLOAD_0: 702 return factory.fload(maxLocals); 703 case Opcodes.FLOAD_1: 704 return factory.fload(maxLocals + 1); 705 case Opcodes.FLOAD_2: 706 return factory.fload(maxLocals + 2); 707 case Opcodes.FLOAD_3: 708 return factory.fload(maxLocals + 3); 709 case Opcodes.FLOAD: 710 ins.getBytes()[1] += (byte)maxLocals; 714 break; 715 case Opcodes.FSTORE_0: 716 return factory.fstore(maxLocals); 717 case Opcodes.FSTORE_1: 718 return factory.fstore(maxLocals + 1); 719 case Opcodes.FSTORE_2: 720 return factory.fstore(maxLocals + 2); 721 case Opcodes.FSTORE_3: 722 return factory.fstore(maxLocals + 3); 723 case Opcodes.FSTORE: 724 ins.getBytes()[1] += (byte)maxLocals; 728 break; 729 730 } 731 732 return ins; 733 } 734 } 735 | Popular Tags |