1 24 25 package org.aspectj.compiler.base.bcg; 26 27 import org.aspectj.compiler.base.bcg.pool.*; 28 29 import java.io.OutputStream ; 30 import java.io.DataOutputStream ; 31 import java.io.PrintStream ; 32 import java.io.IOException ; 33 34 import java.util.HashSet ; 35 import java.util.Set ; 36 import java.util.Arrays ; 37 import java.util.List ; 38 import java.util.Map ; 39 import java.util.HashMap ; 40 import java.util.Stack ; 41 import java.util.ArrayList ; 42 import java.util.Iterator ; 43 import java.util.ListIterator ; 44 45 import org.aspectj.compiler.base.JavaCompiler; 47 import org.aspectj.compiler.base.ast.ControlContext; 48 import org.aspectj.compiler.base.ast.VarDec; 49 import org.aspectj.compiler.base.ast.LabeledStmt; 50 import org.aspectj.compiler.base.ast.WindingStmt; 51 import org.aspectj.compiler.base.ast.Stmt; 52 import org.aspectj.compiler.base.ast.Type; 53 import org.aspectj.compiler.base.ast.ArrayType; 54 import org.aspectj.compiler.base.ast.RefType; 55 import org.aspectj.compiler.base.ast.NameType; 56 import org.aspectj.compiler.base.ast.SourceLocation; 57 58 66 public final class CodeBuilder { 67 68 71 private boolean isResolvedFlag = false; 72 public boolean isResolved() { return isResolvedFlag; } 73 74 77 ConstantPool pool; 78 ClassfileBuilder cfb; 79 Attributes attributes; 80 CodeBuilder(ClassfileBuilder cfb) { 81 this.cfb = cfb; 82 this.pool = cfb.pool; 83 this.attributes = new Attributes(pool); 84 } 85 86 public JavaCompiler getCompiler() { return cfb.getCompiler(); } 87 88 int maxFrame; 89 public void setMaxFrame(int maxFrame) { 90 this.maxFrame = maxFrame; 91 } 92 int maxStack = 0; 93 int stackSize = 0; 94 95 List starts = new ArrayList (); 96 List ends = new ArrayList (); 97 List handlers = new ArrayList (); 98 List names = new ArrayList (); 99 100 List codes = new ArrayList (); 101 Code[] codea; 102 103 List labels = new ArrayList (); 104 105 108 public int getStackSize() { 109 return stackSize; 110 } 111 public void pushStack(int delta) { 112 stackSize += delta; 113 stackInvariant(); 114 } 115 public void adjustStack(int delta) { 116 pushStack(delta); 117 } 118 public void popStack(int delta) { 119 stackSize -= delta; 120 } 121 public void setStackSize(int ss) { 122 stackSize = ss; 123 stackInvariant(); 124 } 125 public void clearStack() { 126 stackSize = 0; 127 } 128 private void stackInvariant() { 129 if (stackSize > maxStack) maxStack = stackSize; 130 } 131 132 135 private ControlContext context = new ControlContext(); 136 private Map breakLabels = new HashMap (); 137 private Map continueLabels = new HashMap (); 138 private Map windingLabels = new HashMap (); 139 140 public void enterNonWindingContext(Stmt s, Label b, Label c) { 141 context.enter(s); 142 breakLabels.put(s, b); 143 if (c != null) continueLabels.put(s, c); 144 } 145 public void enterWindingContext(Stmt s, Label w) { 146 context.enter(s); 147 windingLabels.put(s, w); 148 } 149 public void leaveContext() { context.exit(); } 150 151 public void doBreak(String label) { 152 Stmt target = context.getBreakTarget(label); 153 doJsrUntil(target); 154 emitJump((Label)breakLabels.get(target)); 155 } 156 public void doContinue(String label) { 157 Stmt target = context.getContinueTarget(label); 158 doJsrUntil(target); 159 emitJump((Label)continueLabels.get(target)); 160 } 161 private void doJsrUntil(Stmt target) { 162 for (Iterator i = context.getWindsUntil(target); i.hasNext(); ) { 163 emitJSR((Label)windingLabels.get(i.next())); 164 } 165 } 166 public void doReturn(Type t) { 167 for (Iterator i = context.getWindsUntil(null); i.hasNext(); ) { 168 WindingStmt w = (WindingStmt) i.next(); 169 int rvl = w.getRetValLoc(); 170 t.emitStore(this, rvl); 171 emitJSR((Label)windingLabels.get(w)); 172 t.emitLoad(this, rvl); 173 } 174 t.emitReturn(this); 175 } 176 177 180 188 193 private Stack localVarStack = new Stack (); 194 195 public void enterBlock() { 196 localVarStack.push(null); 198 localVarStack.push(null); 199 } 200 201 public void enterVar(VarDec v) { 202 Label start = genAnchor(); 204 emitLabel(start); 205 localVarStack.push(v); 206 localVarStack.push(start); 207 } 208 209 public void exitBlock() { 210 Label start = (Label) localVarStack.pop(); 212 VarDec v = (VarDec) localVarStack.pop(); 213 for (; v != null; 214 start = (Label) localVarStack.pop(), 215 v = (VarDec) localVarStack.pop()) { 216 Label end = genAnchor(); 218 emitLabel(end); 219 localVars = new LocalVar(start, end, 220 pool.addUtf8(v.getBytecodeId()), 221 pool.addUtf8(v.getDescriptor()), 222 v.getFrameLoc(), 223 localVars); 224 } 225 } 226 227 230 private static final class LocalVar { 231 Label start; 232 Label end; 233 Constant name; 234 Constant descriptor; 235 int index; 236 LocalVar next; 237 LocalVar(Label start, 238 Label end, 239 Constant name, 240 Constant descriptor, 241 int index, 242 LocalVar next) { 243 this.start = start; 244 this.end = end; 245 this.name = name; 246 this.descriptor = descriptor; 247 this.index = index; 248 this.next = next; 249 } 250 public String toString() { 251 return "(" + start + " " + end + " " + name + " " + descriptor + " " 252 + index + "):" + next; 253 } 254 } 255 256 private LocalVar localVars = null; 257 258 void createLocalAttribute() { 259 int size = 0; 263 for (LocalVar in = localVars; in != null; in = in.next) { 264 size++; 265 } 266 if (size == 0) return; 267 Label[] starts = new Label[size]; 269 Label[] ends = new Label[size]; 270 Constant[] names = new Constant[size]; 271 Constant[] descriptors = new Constant[size]; 272 int[] indices = new int[size]; 273 LocalVar lvs = localVars; 275 int i = 0; 276 for (; lvs != null; i++, lvs = lvs.next) { 277 starts[i] = lvs.start; 278 ends[i] = lvs.end; 279 names[i] = lvs.name; 280 descriptors[i] = lvs.descriptor; 281 indices[i] = lvs.index; 282 } 283 attributes.addLocalVariableTableAttribute(starts, ends, names, 285 descriptors, indices); 286 } 287 288 291 private static final class LineNumber { 292 ClassfileBuilder.SourceFile fileInfo; 293 Label pc; 294 int line; 295 LineNumber next; 296 LineNumber(ClassfileBuilder.SourceFile fileInfo, Label pc, int line, LineNumber next) { 297 this.fileInfo = fileInfo; 298 this.pc = pc; 299 this.line = line; 300 this.next = next; 301 } 302 } 303 304 LineNumber lineNumbers = null; 305 306 public void enterLocation(SourceLocation loc) { 307 ClassfileBuilder.SourceFile fileInfo = cfb.getSourceFile(loc); 309 if (fileInfo == null) return; int currLine = loc.getBeginLine(); 311 if (lineNumbers != null) { 312 if (currLine == -1) return; if (currLine == lineNumbers.line && fileInfo == lineNumbers.fileInfo) return; 314 } 315 Label pc = genAnchor(); 316 emitLabel(pc); 317 lineNumbers = new LineNumber(fileInfo, pc, currLine, lineNumbers); 318 } 319 320 void createLineAttribute() { 321 int endPc = getEndPc(); 324 int size = 0; 325 LineNumber in = lineNumbers; 326 LineNumber out = null; 327 while (in != null) { 329 if (in.pc.getPc() >= endPc) { 330 in = in.next; 331 } else { 332 in.line += in.fileInfo.offset; 334 LineNumber temp = in.next; 335 in.next = out; 336 out = in; 337 in = temp; 338 size++; 339 } 340 } 341 Label[] pcs = new Label[size]; 343 int[] lines = new int[size]; 344 for (int i = 0; i < size; i++, out = out.next) { 346 pcs[i] = out.pc; 347 lines[i] = out.line; 348 } 349 attributes.addLineNumberTableAttribute(pcs, lines); 351 } 352 353 356 public void addHandler(Label start, Label end, Label handler, NameType exn) { 357 starts.add(start); 358 ends.add(end); 359 handlers.add(handler); 360 names.add((exn == null) ? null : pool.addClass(exn)); 361 } 362 363 void compressExceptionTable() { 364 Iterator i = starts.iterator(); 365 Iterator j = ends.iterator(); 366 Iterator k = handlers.iterator(); 367 Iterator l = names.iterator(); 368 for (; i.hasNext(); ) { 369 if (((Label)i.next()).getPc() == ((Label)j.next()).getPc()) { 370 k.next(); 371 l.next(); 372 i.remove(); 373 j.remove(); 374 k.remove(); 375 l.remove(); 376 } 377 } 378 } 379 380 void writeExceptionTableTo(DataOutputStream stream) throws IOException { 381 stream.writeShort((short)starts.size()); 382 Iterator i = starts.iterator(); 383 Iterator j = ends.iterator(); 384 Iterator k = handlers.iterator(); 385 Iterator l = names.iterator(); 386 for (; i.hasNext(); ) { 387 stream.writeShort(((Label)i.next()).getPc()); 388 stream.writeShort(((Label)j.next()).getPc()); 389 stream.writeShort(((Label)k.next()).getPc()); 390 Constant name = (Constant)l.next(); 391 if (name == null) { 392 stream.writeShort(0); 393 } else { 394 name.writeIndex(stream); 395 } 396 } 397 } 398 399 402 JumpCode prevJump = null; 403 404 public void emitLabel(Label l) { 405 if (isResolved()) throw new RuntimeException ("already resolved"); 406 labels.add(l); 407 if (prevJump != null) { 408 if (prevJump.getDest() == l) { 409 labels.addAll(prevJump.getLabels()); 410 codes.remove(codes.size() - 1); 411 if (! codes.isEmpty() 412 && (codes.get(codes.size() - 1) instanceof JumpCode)) { 413 prevJump = (JumpCode) codes.get(codes.size() - 1); 414 } else { 415 prevJump = null; 416 } 417 } 418 } 419 } 420 421 public Label genLabel() { 422 return new Label(false); 423 } 424 public Label genAnchor() { 425 return new Label(true); 426 } 427 428 429 432 private void addCode(Code c, int stackDelta) { 433 addCode(c); 434 adjustStack(stackDelta); 435 } 436 private void addCode(Code c) { 437 if (isResolved()) { 438 throw new RuntimeException ("already resolved"); 439 } 440 for (Iterator i = labels.iterator(); i.hasNext(); ) { 441 ((Label) i.next()).setTarget(c); 442 } 443 c.index = codes.size(); 444 labels.clear(); 445 codes.add(c); 446 prevJump = null; 447 } 448 449 452 public void resolve() { 453 if (isResolved()) { 454 throw new RuntimeException ("already resolved"); 455 } 456 if (! pool.isResolved()) { 457 throw new RuntimeException ("pool not resolved yet"); 458 } 459 460 addCode(new SentinelCode()); 461 int len = codes.size(); 462 Code[] a = new Code[len]; 463 for (int i = 0; i < len; i++) { 464 a[i] = (Code) codes.get(i); 465 } 466 codea = a; 467 codes = null; 468 469 keelbackwards(); 470 471 int pc = 0; 472 try { 473 for (int i = 0; i < len; i++) { 474 if (DEBUG) System.err.print("(" + i + ") pc " + pc); 475 Code c = a[i]; 476 pc = c.resolveBest(pc); 477 if (DEBUG) System.err.println(" -> " + pc); 478 } 479 480 DataOutputStream sink = new DataOutputStream (new OutputStream () { 485 public void write(int b) {} 486 }); 487 try { 488 for (int i = 0; i < len; i++) { 489 a[i].writeTo(sink); 490 } 491 } catch (IOException e) {} 492 } catch (TooWideJumpException e) { 493 pc = 0; 494 for (int i = 0; i < len; i++) { 495 Code c = a[i]; 496 pc = c.resolveWorst(pc); 497 } 498 } 499 endPc = pc; 500 if (DEBUG) { 501 System.err.println(">>>>"); 502 display(0, false); 503 System.err.println(); 504 505 for (int i = 0; i < len; i++) { 506 Code c = a[i]; 507 for (Iterator ii = c.getLabels().iterator(); ii.hasNext(); ) { 508 if (((Label) ii.next()).getTarget() != c) { 509 System.err.println("hi"); 510 } 511 } 512 } 513 } 514 isResolvedFlag = true; 515 516 createLineAttribute(); 517 createLocalAttribute(); 518 compressExceptionTable(); 519 } 520 521 private int endPc; 522 int getEndPc() { 523 if (! isResolvedFlag) throw new RuntimeException ("not yet resolved"); 524 return endPc; 525 } 526 527 static class TooWideJumpException extends RuntimeException {} 528 529 static final boolean DEBUG = false; 531 private void keelbackwards() { 532 if (DEBUG) { 533 isResolvedFlag = true; 534 System.err.println("---"); 535 display(0, false); 536 System.err.println(); 537 System.err.println(">>>"); 538 } 539 Code[] a = codea; 540 Code next; 542 Code curr = a[a.length - 1]; 543 for (int i = a.length - 2; i >= 0; i--) { 544 next = curr; 545 curr = a[i]; 546 curr.resolve(next.getRealNext()); 547 if (curr.jumps()) { 548 next.notifyNonLive(); 549 } 550 } 551 if (DEBUG) { 552 display(0, false); 553 System.err.println(); 554 } 555 } 556 557 int getByteSize() { 558 return 2 + 2 + getCodeByteSize() 559 + getExnTableByteSize() 560 + attributes.getByteSize(); 561 } 562 private int getCodeByteSize() { 563 return 4 + getEndPc(); 564 } 565 private int getExnTableByteSize() { 566 return 2 + (8 * starts.size()); 567 } 568 569 void writeTo(DataOutputStream stream) throws IOException { 570 if (! isResolved()) { 571 throw new RuntimeException ("not yet resolved"); 572 } 573 stream.writeShort((short) maxStack); 574 stream.writeShort((short) maxFrame); 575 writeCodeTo(stream); 576 writeExceptionTableTo(stream); 577 attributes.writeTo(stream); 578 } 579 580 private void writeCodeTo(DataOutputStream stream) throws IOException { 581 stream.writeInt(getEndPc()); 582 Code[] a = codea; 583 for (int i = 0, len = a.length; i < len; i++) { 584 a[i].writeTo(stream); 585 } 586 } 587 588 591 593 public void emitJump(Label dest) { 594 JumpCode c = new JumpCode(dest); 595 addCode(c); 596 prevJump = c; 597 } 598 599 public void emitJSR(Label dest) { 600 addCode(new JsrCode(dest)); 601 } 602 603 public void emitRET(int n) { 604 addCode(new FrameCode(RET, n), 0); 605 } 606 607 609 public void emitSwitch(int[] keys, Label[] cases, Label defaultCase) { 610 long min = keys[0]; 611 long max = keys[keys.length - 1]; 612 613 if ((1 + 1 + max - min + 1) <= 615 (1 + keys.length * 2)) { Label[] realCases = new Label[(int)(max - min + 1)]; 617 for (int kv = (int)min, ki = 0, ci = 0, oi = 0; kv <= (int)max; kv++, oi++) { 618 if (kv == keys[ki]) { 619 realCases[oi] = cases[ci++]; 620 ki++; 621 } else { 622 realCases[oi] = defaultCase; 623 } 624 } 625 addCode(new TableSwitchCode((int)min, (int)max, realCases, defaultCase), -1); 626 627 } else { 628 addCode(new LookupSwitchCode(keys, cases, defaultCase), -1); 629 } 630 } 631 632 634 public void emitINVOKESTATIC(NameType nameType, String name, 635 String descriptor, int stackDelta) { 636 addCode(new PoolCode(INVOKESTATIC, 637 pool.addMethodRef(nameType, name, descriptor)), 638 stackDelta); 639 } 640 public void emitINVOKESPECIAL(NameType nameType, String name, 641 String descriptor, int stackDelta) { 642 addCode(new PoolCode(INVOKESPECIAL, 643 pool.addMethodRef(nameType, 644 name, descriptor)), 645 stackDelta); 646 } 647 public void emitINVOKEINTERFACE(NameType nameType, String name, 648 String descriptor, int stackDelta, int arglen) { 649 addCode(new InvokeInterfaceCode(pool.addInterfaceMethodRef(nameType, 650 name, 651 descriptor), 652 arglen), 653 stackDelta); 654 } 655 public void emitINVOKEVIRTUAL(NameType nameType, String name, 656 String descriptor, int stackDelta) { 657 addCode(new PoolCode(INVOKEVIRTUAL, 658 pool.addMethodRef(nameType, 659 name, descriptor)), 660 stackDelta); 661 } 662 public void emitGETSTATIC(NameType nameType, String name, 663 String descriptor, int stackDelta) { 664 addCode(new PoolCode(GETSTATIC, 665 pool.addFieldRef(nameType, 666 name, descriptor)), 667 stackDelta); 668 } 669 public void emitPUTSTATIC(NameType nameType, String name, 670 String descriptor, int stackDelta) { 671 addCode(new PoolCode(PUTSTATIC, 672 pool.addFieldRef(nameType, 673 name, descriptor)), 674 stackDelta); 675 } 676 public void emitGETFIELD(NameType nameType, String name, 677 String descriptor, int stackDelta) { 678 addCode(new PoolCode(GETFIELD, 679 pool.addFieldRef(nameType, 680 name, descriptor)), 681 stackDelta); 682 } 683 public void emitPUTFIELD(NameType nameType, String name, 684 String descriptor, int stackDelta) { 685 addCode(new PoolCode(PUTFIELD, 686 pool.addFieldRef(nameType, 687 name, descriptor)), 688 stackDelta); 689 } 690 691 693 public void emitNEW(NameType nameType) { 694 addCode(new PoolCode(NEW, pool.addClass(nameType)), 1); 695 } 696 public void emitCHECKCAST(RefType refType) { 697 addCode(new PoolCode(CHECKCAST, pool.addClass(refType))); 698 } 699 public void emitINSTANCEOF(RefType refType) { 700 addCode(new PoolCode(INSTANCEOF, pool.addClass(refType)), 0); 701 } 702 703 public void emitIAND() { addCode(new BasicCode(IAND), -1); } 705 public void emitLAND() { addCode(new BasicCode(LAND), -2); } 706 public void emitNULL() { addCode(new BasicCode(ACONST_NULL), 1); } 707 public void emitI2L() { addCode(new BasicCode(I2L), 1); } 708 public void emitI2F() { addCode(new BasicCode(I2F), 0); } 709 public void emitI2D() { addCode(new BasicCode(I2D), 1); } 710 public void emitL2I() { addCode(new BasicCode(L2I), -1); } 711 public void emitL2F() { addCode(new BasicCode(L2F), -1); } 712 public void emitL2D() { addCode(new BasicCode(L2D), 0); } 713 public void emitF2I() { addCode(new BasicCode(F2I), 0); } 714 public void emitF2L() { addCode(new BasicCode(F2L), 1); } 715 public void emitF2D() { addCode(new BasicCode(F2D), 1); } 716 public void emitD2I() { addCode(new BasicCode(D2I), -1); } 717 public void emitD2L() { addCode(new BasicCode(D2L), 0); } 718 public void emitD2F() { addCode(new BasicCode(D2F), -1); } 719 public void emitI2B() { addCode(new BasicCode(I2B), 0); } 720 public void emitI2C() { addCode(new BasicCode(I2C), 0); } 721 public void emitI2S() { addCode(new BasicCode(I2S), 0); } 722 public void emitPOP() { addCode(new BasicCode(POP), -1); } 723 public void emitPOP2() { addCode(new BasicCode(POP2), -2); } 724 public void emitLCMP () { addCode(new BasicCode(LCMP), -3); } 725 public void emitFCMPL() { addCode(new BasicCode(FCMPL), -1); } 726 public void emitFCMPG() { addCode(new BasicCode(FCMPG), -1); } 727 public void emitDCMPL() { addCode(new BasicCode(DCMPL), -3); } 728 public void emitDCMPG() { addCode(new BasicCode(DCMPG), -3); } 729 public void emitNOP() { addCode(new BasicCode(NOP), 0); } 730 public void emitACONST_NULL() { addCode(new BasicCode(ACONST_NULL), 1); } 731 public void emitIALOAD() { addCode(new BasicCode(IALOAD), -1); } 732 public void emitLALOAD() { addCode(new BasicCode(LALOAD), 0); } 733 public void emitFALOAD() { addCode(new BasicCode(FALOAD), -1); } 734 public void emitDALOAD() { addCode(new BasicCode(DALOAD), 0); } 735 public void emitAALOAD() { addCode(new BasicCode(AALOAD), -1); } 736 public void emitBALOAD() { addCode(new BasicCode(BALOAD), -1); } 737 public void emitCALOAD() { addCode(new BasicCode(CALOAD), -1); } 738 public void emitSALOAD() { addCode(new BasicCode(SALOAD), -1); } 739 public void emitIASTORE() { addCode(new BasicCode(IASTORE), -3); } 740 public void emitLASTORE() { addCode(new BasicCode(LASTORE), -4); } 741 public void emitFASTORE() { addCode(new BasicCode(FASTORE), -3); } 742 public void emitDASTORE() { addCode(new BasicCode(DASTORE), -4); } 743 public void emitAASTORE() { addCode(new BasicCode(AASTORE), -3); } 744 public void emitBASTORE() { addCode(new BasicCode(BASTORE), -3); } 745 public void emitCASTORE() { addCode(new BasicCode(CASTORE), -3); } 746 public void emitSASTORE() { addCode(new BasicCode(SASTORE), -3); } 747 public void emitSWAP() { addCode(new BasicCode(SWAP), 0); } 748 public void emitIADD() { addCode(new BasicCode(IADD), -1); } 749 public void emitLADD() { addCode(new BasicCode(LADD), -2); } 750 public void emitFADD() { addCode(new BasicCode(FADD), -1); } 751 public void emitDADD() { addCode(new BasicCode(DADD), -2); } 752 public void emitISUB() { addCode(new BasicCode(ISUB), -1); } 753 public void emitLSUB() { addCode(new BasicCode(LSUB), -2); } 754 public void emitFSUB() { addCode(new BasicCode(FSUB), -1); } 755 public void emitDSUB() { addCode(new BasicCode(DSUB), -2); } 756 public void emitIMUL() { addCode(new BasicCode(IMUL), -1); } 757 public void emitLMUL() { addCode(new BasicCode(LMUL), -2); } 758 public void emitFMUL() { addCode(new BasicCode(FMUL), -1); } 759 public void emitDMUL() { addCode(new BasicCode(DMUL), -2); } 760 public void emitIDIV() { addCode(new BasicCode(IDIV), -1); } 761 public void emitLDIV() { addCode(new BasicCode(LDIV), -2); } 762 public void emitFDIV() { addCode(new BasicCode(FDIV), -1); } 763 public void emitDDIV() { addCode(new BasicCode(DDIV), -2); } 764 public void emitIREM() { addCode(new BasicCode(IREM), -1); } 765 public void emitLREM() { addCode(new BasicCode(LREM), -2); } 766 public void emitFREM() { addCode(new BasicCode(FREM), -1); } 767 public void emitDREM() { addCode(new BasicCode(DREM), -2); } 768 public void emitINEG() { addCode(new BasicCode(INEG), 0); } 769 public void emitLNEG() { addCode(new BasicCode(LNEG), 0); } 770 public void emitFNEG() { addCode(new BasicCode(FNEG), 0); } 771 public void emitDNEG() { addCode(new BasicCode(DNEG), 0); } 772 public void emitISHL() { addCode(new BasicCode(ISHL), -1); } 773 public void emitLSHL() { addCode(new BasicCode(LSHL), -1); } 774 public void emitISHR() { addCode(new BasicCode(ISHR), -1); } 775 public void emitLSHR() { addCode(new BasicCode(LSHR), -1); } 776 public void emitIUSHR() { addCode(new BasicCode(IUSHR), -1); } 777 public void emitLUSHR() { addCode(new BasicCode(LUSHR), -1); } 778 public void emitIOR() { addCode(new BasicCode(IOR), -1); } 779 public void emitLOR() { addCode(new BasicCode(LOR), -2); } 780 public void emitIXOR() { addCode(new BasicCode(IXOR), -1); } 781 public void emitLXOR() { addCode(new BasicCode(LXOR), -2); } 782 public void emitIRETURN() { addCode(new ReturnCode(IRETURN), -1); } 783 public void emitLRETURN() { addCode(new ReturnCode(LRETURN), -2); } 784 public void emitFRETURN() { addCode(new ReturnCode(FRETURN), -1); } 785 public void emitDRETURN() { addCode(new ReturnCode(DRETURN), -2); } 786 public void emitARETURN() { addCode(new ReturnCode(ARETURN), -1); } 787 public void emitRETURN() { addCode(new ReturnCode(RETURN), 0); } 788 public void emitARRAYLENGTH() { addCode(new BasicCode(ARRAYLENGTH), 0); } 789 public void emitATHROW() { addCode(new BasicCode(ATHROW), -1); } 790 public void emitMONITORENTER(){ addCode(new BasicCode(MONITORENTER),-1); } 791 public void emitMONITOREXIT() { addCode(new BasicCode(MONITOREXIT), -1); } 792 public void emitDUP() { addCode(new BasicCode(DUP), 1); } 793 public void emitDUP_X1() { addCode(new BasicCode(DUP_X1), 1); } 794 public void emitDUP_X2() { addCode(new BasicCode(DUP_X2), 1); } 795 public void emitDUP2() { addCode(new BasicCode(DUP2), 2); } 796 public void emitDUP2_X1() { addCode(new BasicCode(DUP2_X1), 2); } 797 public void emitDUP2_X2() { addCode(new BasicCode(DUP2_X2), 2); } 798 799 801 public void emitIFEQ(Label tdest, Label fdest) { 802 addCode(new BranchCode(IFEQ, IFNE, tdest, fdest), -1); 803 } 804 public void emitIFNE(Label tdest, Label fdest) { 805 addCode(new BranchCode(IFNE, IFEQ, tdest, fdest), -1); 806 } 807 public void emitIFLT(Label tdest, Label fdest) { 808 addCode(new BranchCode(IFLT, IFGE, tdest, fdest), -1); 809 } 810 public void emitIFGE(Label tdest, Label fdest) { 811 addCode(new BranchCode(IFGE, IFLT, tdest, fdest), -1); 812 } 813 public void emitIFGT(Label tdest, Label fdest) { 814 addCode(new BranchCode(IFGT, IFLE, tdest, fdest), -1); 815 } 816 public void emitIFLE(Label tdest, Label fdest) { 817 addCode(new BranchCode(IFLE, IFGT, tdest, fdest), -1); 818 } 819 820 public void emitIF_ICMPEQ(Label tdest, Label fdest) { 821 addCode(new BranchCode(IF_ICMPEQ, IF_ICMPNE, tdest, fdest), -2); 822 } 823 public void emitIF_ICMPNE(Label tdest, Label fdest) { 824 addCode(new BranchCode(IF_ICMPNE, IF_ICMPEQ, tdest, fdest), -2); 825 } 826 public void emitIF_ICMPLT(Label tdest, Label fdest) { 827 addCode(new BranchCode(IF_ICMPLT, IF_ICMPGE, tdest, fdest), -2); 828 } 829 public void emitIF_ICMPGE(Label tdest, Label fdest) { 830 addCode(new BranchCode(IF_ICMPGE, IF_ICMPLT, tdest, fdest), -2); 831 } 832 public void emitIF_ICMPGT(Label tdest, Label fdest) { 833 addCode(new BranchCode(IF_ICMPGT, IF_ICMPLE, tdest, fdest), -2); 834 } 835 public void emitIF_ICMPLE(Label tdest, Label fdest) { 836 addCode(new BranchCode(IF_ICMPLE, IF_ICMPGT, tdest, fdest), -2); 837 } 838 839 public void emitIF_ACMPEQ(Label tdest, Label fdest) { 840 addCode(new BranchCode(IF_ACMPEQ, IF_ACMPNE, tdest, fdest), -2); 841 } 842 public void emitIF_ACMPNE(Label tdest, Label fdest) { 843 addCode(new BranchCode(IF_ACMPNE, IF_ACMPEQ, tdest, fdest), -2); 844 } 845 public void emitIFNULL(Label tdest, Label fdest) { 846 addCode(new BranchCode(IFNULL, IFNONNULL, tdest, fdest), -1); 847 } 848 public void emitIFNONNULL(Label tdest, Label fdest) { 849 addCode(new BranchCode(IFNONNULL, IFNULL, tdest, fdest), -1); 850 } 851 852 854 public void emitIntConstant(int val) { 855 Code code; 856 switch (val) { 857 case -1: code = new BasicCode(ICONST_M1); break; 858 case 0: code = new BasicCode(ICONST_0); break; 859 case 1: code = new BasicCode(ICONST_1); break; 860 case 2: code = new BasicCode(ICONST_2); break; 861 case 3: code = new BasicCode(ICONST_3); break; 862 case 4: code = new BasicCode(ICONST_4); break; 863 case 5: code = new BasicCode(ICONST_5); break; 864 default: 865 if (Asserts.isByte(val)) { 866 code = new ByteCode(BIPUSH, (byte)val); 867 } else if (Asserts.isShort(val)) { 868 code = new ShortCode(SIPUSH, (short)val); 869 } else { 870 code = new LDCCode(pool.addInt(val)); 871 } 872 break; 873 } 874 addCode(code, 1); 875 } 876 877 public void emitLongConstant(long val) { 878 Code code; 879 if (val == 0L) code = new BasicCode(LCONST_0); 880 else if (val == 1L) code = new BasicCode(LCONST_1); 881 else code = new PoolCode(LDC2_W, pool.addLong(val)); 882 addCode(code, 2); 883 } 884 885 public void emitFloatConstant(float val) { 886 Code code; 887 if (val == 0.0f) { 888 if ((1 / val) > 0) { 889 code = new BasicCode(FCONST_0); 890 } else { 891 code = new LDCCode(pool.addFloat(val)); 892 } 893 } 894 else if (val == 1.0f) code = new BasicCode(FCONST_1); 895 else if (val == 2.0f) code = new BasicCode(FCONST_2); 896 else code = new LDCCode(pool.addFloat(val)); 897 addCode(code, 1); 898 } 899 900 public void emitDoubleConstant(double val) { 901 Code code; 902 if (val == 0.0D) { 903 if ((1 / val) > 0) { 904 code = new BasicCode(DCONST_0); 905 } else { 906 code = new PoolCode(LDC2_W, pool.addDouble(val)); 907 } 908 } 909 else if (val == 1.0D) code = new BasicCode(DCONST_1); 910 else code = new PoolCode(LDC2_W, pool.addDouble(val)); 911 addCode(code, 2); 912 } 913 914 public void emitStringConstant(String val) { 915 addCode(new LDCCode(pool.addString(val)), 1); 916 } 917 918 920 public void emitNEWARRAY(int tyIndex) { 921 addCode(new ByteCode(NEWARRAY, (byte)tyIndex), 0); 922 } 923 924 public void emitANEWARRAY(RefType componentType) { 925 addCode(new PoolCode(ANEWARRAY, pool.addClass(componentType)), 0); 926 } 927 928 public void emitMULTIANEWARRAY(ArrayType arrayType, int dimCount) { 929 addCode(new PoolByteCode(MULTIANEWARRAY, 930 pool.addClass(arrayType), 931 (byte)dimCount), 932 -(dimCount - 1)); 933 } 934 935 937 private final byte[] aloads = { ALOAD_0, ALOAD_1, ALOAD_2, ALOAD_3, ALOAD }; 938 private final byte[] iloads = { ILOAD_0, ILOAD_1, ILOAD_2, ILOAD_3, ILOAD }; 939 private final byte[] lloads = { LLOAD_0, LLOAD_1, LLOAD_2, LLOAD_3, LLOAD }; 940 private final byte[] floads = { FLOAD_0, FLOAD_1, FLOAD_2, FLOAD_3, FLOAD }; 941 private final byte[] dloads = { DLOAD_0, DLOAD_1, DLOAD_2, DLOAD_3, DLOAD }; 942 943 private final byte[] astores = { ASTORE_0, ASTORE_1, ASTORE_2, ASTORE_3, ASTORE }; 944 private final byte[] istores = { ISTORE_0, ISTORE_1, ISTORE_2, ISTORE_3, ISTORE }; 945 private final byte[] lstores = { LSTORE_0, LSTORE_1, LSTORE_2, LSTORE_3, LSTORE }; 946 private final byte[] fstores = { FSTORE_0, FSTORE_1, FSTORE_2, FSTORE_3, FSTORE }; 947 private final byte[] dstores = { DSTORE_0, DSTORE_1, DSTORE_2, DSTORE_3, DSTORE }; 948 949 public void emitALOAD(int n) { emitFrameCode(aloads, n, 1); } 950 public void emitILOAD(int n) { emitFrameCode(iloads, n, 1); } 951 public void emitLLOAD(int n) { emitFrameCode(lloads, n, 2); } 952 public void emitFLOAD(int n) { emitFrameCode(floads, n, 1); } 953 public void emitDLOAD(int n) { emitFrameCode(dloads, n, 2); } 954 955 public void emitASTORE(int n) { emitFrameCode(astores, n, -1); } 956 public void emitISTORE(int n) { emitFrameCode(istores, n, -1); } 957 public void emitLSTORE(int n) { emitFrameCode(lstores, n, -2); } 958 public void emitFSTORE(int n) { emitFrameCode(fstores, n, -1); } 959 public void emitDSTORE(int n) { emitFrameCode(dstores, n, -2); } 960 961 public void emitFrameCode(byte[] insts, int n, int delta) { 962 if (n <= 3) addCode(new BasicCode(insts[n]), delta); 963 else addCode(new FrameCode(insts[4], n), delta); 964 } 965 966 968 public void emitIINC(int n, int incr) { 969 addCode(new IncCode(n, incr), 0); 970 } 971 972 976 public String toString() { 977 return "(st/fr " + maxStack + " " + maxFrame + ") " + 978 attributes; 979 } 980 981 public void emitStackSize() { 982 addCode(new BasicCode(NOP)); 983 addCode(new ByteCode(BIPUSH, (byte)getStackSize())); 984 addCode(new BasicCode(POP)); 985 addCode(new BasicCode(NOP)); 986 } 987 988 int labelCount = 0; 989 public void displayInstructions(int indent) { 990 List codes = (isResolved()) 991 ? Arrays.asList(codea) 992 : this.codes; 993 for (int i = 0, len = codes.size() - 1; i < len; i++) { 994 Code c = (Code) codes.get(i); 995 if (! c.isActive()) continue; 996 between(indent, false); 997 if (DEBUG) System.err.print("(" + i + ") "); 998 if (c.getLabels().size() != 0) { 999 if (DEBUG) { 1000 for (Iterator ii = c.getLabels().iterator(); ii.hasNext(); ) { 1001 System.err.print(ii.next() + " "); 1002 } 1003 } else { 1004 String s = c.getLabels().get(0) + " "; 1005 System.err.print(s); 1006 for (int p = 4 - s.length(); p > 0; p--) { 1007 System.err.print(" "); 1008 } 1009 } 1010 } else { 1011 System.err.print(" "); 1012 } 1013 System.err.print(c); 1014 } 1015 for (int i = 0, len = starts.size(); i < len; i++) { 1016 between(indent, false); 1017 String name = (names.get(i) == null) 1018 ? "any" 1019 : names.get(i).toString(); 1020 System.err.print("(throwing " + name 1021 + " from " + starts.get(i) 1022 + " to " + ends.get(i) 1023 + " goto " + handlers.get(i) + ")"); 1024 } 1025 } 1026 1027 public void display(int indent, boolean inline) { 1028 System.err.print("(stack " + maxStack + ") (locals " + maxFrame + ")"); 1029 between(indent, inline); 1030 attributes.display(indent, inline); 1031 if (! inline) { 1032 displayInstructions(indent); 1033 } 1034 } 1035 1036 static void between(int indent, boolean inline) { 1037 if (inline) { 1038 System.err.print(" "); 1039 } else { 1040 System.err.println(); 1041 for (int s=indent; s >= 0; s--) System.err.print(" "); 1042 } 1043 } 1044 1045 1049 static class SentinelCode extends Code { 1050 int resolveBest(int pc) { setPc(pc); return pc; } 1051 void writeTo(DataOutputStream stream) {} 1052 public String toString() { return "SENTINEL"; } 1053 boolean isActive() { return false; } 1054 } 1055 1056 static class BranchCode extends Code { 1057 byte tcode, fcode; 1058 Label tdest, fdest; 1059 BranchCode(byte tcode, byte fcode, Label tdest, Label fdest) { 1060 this.tcode = tcode; this.tdest = tdest; 1061 this.fcode = fcode; this.fdest = fdest; 1062 } 1063 1064 boolean oneArmed; 1065 boolean arm; 1066 void resolve(Code next) { 1067 if (tdest.getTarget() == next) { 1068 oneArmed = true; 1069 arm = false; 1070 } else if (fdest.getTarget() == next) { 1071 oneArmed = true; 1072 arm = true; 1073 } else { 1074 oneArmed = false; 1075 } 1076 } 1077 1078 boolean jumps() { return true; } 1079 1080 boolean small = true; 1081 int resolveBest(int pc) { this.pc = pc; return pc + (oneArmed ? 3 : 6); } 1082 int resolveWorst(int pc) { small = false; this.pc = pc; return pc + (oneArmed ? 8 : 13); } 1083 1084 void writeTo(DataOutputStream stream) throws IOException { 1085 if (small) { 1086 if (! oneArmed) { 1087 stream.writeByte(tcode); 1088 tdest.writeRelativeShort(pc, stream); 1089 stream.writeByte(GOTO); 1090 fdest.writeRelativeShort(pc + 3, stream); 1091 } else if (arm) { 1092 stream.writeByte(tcode); 1094 tdest.writeRelativeShort(pc, stream); 1095 } else { 1096 stream.writeByte(fcode); 1097 fdest.writeRelativeShort(pc, stream); 1098 } 1099 } else { 1100 if (! oneArmed) { 1101 stream.writeByte(tcode); 1102 stream.writeShort(8); 1103 stream.writeByte(GOTO_W); 1104 fdest.writeRelativeInt(pc + 3, stream); 1105 stream.writeByte(GOTO_W); 1106 tdest.writeRelativeInt(pc + 8, stream); 1107 } else if (arm) { 1108 stream.writeByte(fcode); 1110 stream.writeShort(8); 1111 stream.writeByte(GOTO_W); 1112 tdest.writeRelativeInt(pc + 3, stream); 1113 } else { 1114 stream.writeByte(tcode); 1115 stream.writeShort(8); 1116 stream.writeByte(GOTO_W); 1117 fdest.writeRelativeInt(pc + 3, stream); 1118 } 1119 } 1120 } 1121 1122 public String toString() { 1123 if (! oneArmed) { 1124 return debugString(tcode) + " " + tdest + " else " + fdest; 1125 } else if (arm) { 1126 return debugString(tcode) + " " + tdest + " "; 1127 } else { 1128 return debugString(fcode) + " " + fdest + " "; 1129 } 1130 } 1131 } 1132 1133 static class JumpCode extends Code { 1134 boolean active = true; 1135 boolean isActive() { return active; } 1136 Label dest; 1137 JumpCode(Label dest) { this.dest = dest; } 1138 Label getDest() { return dest; } 1139 void setDest(Label dest) { this.dest = dest; } 1140 1141 boolean small = true; 1142 int resolveBest(int pc) { this.pc = pc; return (active) ? (pc + 3) : pc; } 1143 int resolveWorst(int pc) { 1144 small = false; this.pc = pc; 1145 return (active) ? (pc + 5) : pc; 1146 } 1147 void writeTo(DataOutputStream stream) throws IOException { 1148 if (! active) return; 1149 if (small) { 1150 stream.writeByte(GOTO); 1151 dest.writeRelativeShort(pc, stream); 1152 } else { 1153 stream.writeByte(GOTO_W); 1154 dest.writeRelativeInt(pc, stream); 1155 } 1156 } 1157 public String toString() { 1158 return "GOTO " + dest; 1159 } 1160 boolean jumps() { return active; } 1161 1162 void notifyNonLive() { 1163 active = false; 1164 } 1165 Code getRealNext() { 1166 return (active) ? this : dest.getTarget(); 1167 } 1168 void resolve(Code next) { 1169 Code target = dest.getTarget(); 1170 if (target != this) { 1171 for (Iterator i = getLabels().iterator(); i.hasNext(); ) { 1172 Label l = (Label) i.next(); 1173 if (! l.isAnchored()) { 1174 i.remove(); 1175 l.setTarget(target); 1176 } 1177 } 1178 } 1179 if (next == target) { 1180 active = false; 1181 } 1182 } 1183 } 1184 1185 static class JsrCode extends Code { 1186 Label dest; 1187 JsrCode(Label dest) { this.dest = dest; } 1188 Label getDest() { return dest; } 1189 1190 int resolveBest(int pc) { this.pc = pc; return pc + 3; } 1191 int resolveWorst(int pc) { small = false; this.pc = pc; return pc + 5; } 1192 1193 boolean small = true; 1194 void writeTo(DataOutputStream stream) throws IOException { 1195 if (small) { 1196 stream.writeByte(JSR); 1197 dest.writeRelativeShort(pc, stream); 1198 } else { 1199 stream.writeByte(JSR_W); 1200 dest.writeRelativeInt(pc, stream); 1201 } 1202 } 1203 1204 public String toString() { 1205 return "JSR " + dest; 1206 } 1207 } 1208 1209 static class IncCode extends Code { 1210 int loc, val; 1211 int size; 1212 IncCode(int loc, int val) { 1213 this.loc = loc; this.val = val; 1214 size = (Asserts.isUByte(loc) && Asserts.isByte(val)) ? 3 : 6; 1215 } 1216 int resolveBest(int pc) { this.pc = pc; return pc + size; } 1217 1218 void writeTo(DataOutputStream stream) throws IOException { 1219 if (size == 6) { 1220 stream.writeByte(WIDE); 1221 stream.writeByte(IINC); 1222 stream.writeShort(loc); 1223 stream.writeShort(val); 1224 } else { 1225 stream.writeByte(IINC); 1226 stream.writeByte(loc); 1227 stream.writeByte(val); 1228 1229 } 1230 } 1231 public String toString() { 1232 return ((size == 6) ? "WIDE IINC " : "IINC ") 1233 + loc + " " + val; 1234 } 1235 } 1236 1237 static class FrameCode extends Code { 1238 byte code; 1239 int loc; 1240 int size; 1241 FrameCode(byte code, int loc) { 1242 this.code = code; this.loc = loc; 1243 size = Asserts.isUByte(loc) ? 2 : 4; 1244 } 1245 int resolveBest(int pc) { this.pc = pc; return pc + size; } 1246 1247 void writeTo(DataOutputStream stream) throws IOException { 1248 if (size == 4) { 1249 stream.writeByte(WIDE); 1250 stream.writeByte(code); 1251 stream.writeShort(loc); 1252 } else { 1253 stream.writeByte(code); 1254 stream.writeByte(loc); 1255 } 1256 } 1257 public String toString() { 1258 return ((size == 4) ? "WIDE " : "") 1259 + debugString(code) + " " + loc; 1260 } 1261 } 1262 1263 static class BasicCode extends Code { 1264 byte code; 1265 BasicCode(byte code) { this.code = code; } 1266 1267 int resolveBest(int pc) { this.pc = pc; return pc + 1; } 1268 void writeTo(DataOutputStream stream) throws IOException { 1269 stream.writeByte(code); 1270 } 1271 public String toString() { 1272 return debugString(code); 1273 } 1274 } 1275 1276 static class ReturnCode extends BasicCode { 1277 ReturnCode(byte code) { super(code); } 1278 boolean jumps() { return true; } 1279 } 1280 1281 static class ByteCode extends Code { 1282 byte code; 1283 byte data; 1284 ByteCode(byte code, byte data) { 1285 this.code = code; this.data = data; 1286 } 1287 1288 int resolveBest(int pc) { this.pc = pc; return pc + 2; } 1289 void writeTo(DataOutputStream stream) throws IOException { 1290 stream.writeByte(code); 1291 stream.writeByte(data); 1292 } 1293 public String toString() { 1294 return debugString(code) + " " + data; 1295 } 1296 } 1297 1298 static class ShortCode extends Code { 1299 byte code; 1300 short data; 1301 ShortCode(byte code, short data) { 1302 this.code = code; this.data = data; 1303 } 1304 1305 int resolveBest(int pc) { this.pc = pc; return pc + 3; } 1306 void writeTo(DataOutputStream stream) throws IOException { 1307 stream.writeByte(code); 1308 stream.writeShort(data); 1309 } 1310 public String toString() { 1311 return debugString(code) + " " + data; 1312 } 1313 } 1314 1315 static class PoolCode extends Code { 1316 byte code; 1317 Constant constant; 1318 PoolCode(byte code, Constant constant) { 1319 this.code = code; this.constant = constant; 1320 } 1321 int resolveBest(int pc) { 1322 this.pc = pc; 1323 return pc + 3; 1324 } 1325 void writeTo(DataOutputStream stream) throws IOException { 1326 stream.writeByte(code); 1327 constant.writeIndex(stream); 1328 } 1329 public String toString() { 1330 return debugString(code) + " " + constant; 1331 } 1332 } 1333 1334 static class InvokeInterfaceCode extends Code { 1335 Constant constant; 1336 int arglen; 1337 InvokeInterfaceCode(Constant constant, int arglen) { 1338 this.constant = constant; 1339 this.arglen = arglen; 1340 } 1341 int resolveBest(int pc) { 1342 this.pc = pc; 1343 return pc + 5; 1344 } 1345 void writeTo(DataOutputStream stream) throws IOException { 1346 stream.writeByte(INVOKEINTERFACE); 1347 constant.writeIndex(stream); 1348 stream.writeByte((byte)arglen); 1349 stream.writeByte(0); 1350 } 1351 public String toString() { 1352 return "INVOKEINTERFACE (args " + arglen + ") " + constant; 1353 } 1354 } 1355 1356 static class LDCCode extends Code { 1357 Constant constant; 1358 LDCCode(Constant constant) { 1359 this.constant = constant; 1360 constant.makePopular(); } 1362 int resolveBest(int pc) { 1363 this.pc = pc; return pc + (Asserts.isUByte(constant.getIndex()) ? 2 : 3); 1364 } 1365 void writeTo(DataOutputStream stream) throws IOException { 1366 if (Asserts.isUByte(constant.getIndex())) { 1367 stream.writeByte(LDC); 1368 constant.writeBriefIndex(stream); 1369 } else { 1370 stream.writeByte(LDC_W); 1371 constant.writeIndex(stream); 1372 } 1373 } 1374 public String toString() { 1375 return "LDC " + constant + (Asserts.isUByte(constant.getIndex()) ? "" : " (!!WIDE!!)"); 1376 } 1377 } 1378 1379 static class PoolByteCode extends Code { byte code; 1381 Constant constant; 1382 byte data; 1383 PoolByteCode(byte code, Constant constant, byte data) { 1384 this.code = code; this.constant = constant; this.data = data; 1385 } 1386 int resolveBest(int pc) { this.pc = pc; return pc + 4; } 1387 void writeTo(DataOutputStream stream) throws IOException { 1388 stream.writeByte(code); 1389 constant.writeIndex(stream); 1390 stream.writeByte(data); 1391 } 1392 public String toString() { 1393 return debugString(code) + " " + constant + " " + data; 1394 } 1395 } 1396 1397 public static class TableSwitchCode extends Code { 1398 int padBytes = 0; 1399 int min; 1400 int max; 1401 Label[] cases; 1402 Label defaultCase; 1403 TableSwitchCode(int min, int max, Label[] cases, Label defaultCase) { 1404 this.min = min; this.max = max; 1405 this.cases = cases; this.defaultCase = defaultCase; 1406 } 1407 int resolveBest(int pc) { 1408 this.pc = pc; 1409 padBytes = (-pc) % 4 + 3; 1410 return pc + 1 + padBytes + 4 + 4 + 4 + (4 * cases.length); 1411 } 1412 void writeTo(DataOutputStream stream) throws IOException { 1413 stream.writeByte(TABLESWITCH); 1414 for (int i = padBytes; i > 0; i--) { 1415 stream.writeByte(0); 1416 } 1417 defaultCase.writeRelativeInt(pc, stream); 1418 stream.writeInt(min); 1419 stream.writeInt(max); 1420 for (int i = 0; i < cases.length; i++) { 1421 cases[i].writeRelativeInt(pc, stream); 1422 } 1423 } 1424 public String toString() { 1425 return "tableswitch"; 1426 } 1427 1428 boolean jumps() { return true; } 1429 } 1430 1431 public static class LookupSwitchCode extends Code { 1432 int padBytes = 0; 1433 int[] keys; 1434 Label[] cases; 1435 Label defaultCase; 1436 LookupSwitchCode(int[] keys, Label[] cases, Label defaultCase) { 1437 this.keys = keys; this.cases = cases; 1438 this.defaultCase = defaultCase; 1439 } 1440 int resolveBest(int pc) { 1441 this.pc = pc; 1442 padBytes = (-pc) % 4 + 3; 1443 return pc + 1 + padBytes + 4 + 4 + (8 * cases.length); 1444 } 1445 void writeTo(DataOutputStream stream) throws IOException { 1446 stream.writeByte(LOOKUPSWITCH); 1447 for (int i = padBytes; i > 0; i--) { 1448 stream.writeByte(0); 1449 } 1450 defaultCase.writeRelativeInt(pc, stream); 1451 stream.writeInt(cases.length); 1452 for (int i = 0; i < cases.length; i++) { 1453 stream.writeInt(keys[i]); 1454 cases[i].writeRelativeInt(pc, stream); 1455 } 1456 } 1457 public String toString() { 1458 return "lookupswitch"; 1459 } 1460 boolean jumps() { return true; } 1461 } 1462 1463 1466 protected static final byte NOP = (byte) 0x00; 1468 protected static final byte ACONST_NULL = (byte) 0x01; 1469 protected static final byte ICONST_M1 = (byte) 0x02; 1470 protected static final byte ICONST_0 = (byte) 0x03; 1471 protected static final byte ICONST_1 = (byte) 0x04; 1472 protected static final byte ICONST_2 = (byte) 0x05; 1473 protected static final byte ICONST_3 = (byte) 0x06; 1474 protected static final byte ICONST_4 = (byte) 0x07; 1475 protected static final byte ICONST_5 = (byte) 0x08; 1476 protected static final byte LCONST_0 = (byte) 0x09; 1477 protected static final byte LCONST_1 = (byte) 0x0a; 1478 protected static final byte FCONST_0 = (byte) 0x0b; 1479 protected static final byte FCONST_1 = (byte) 0x0c; 1480 protected static final byte FCONST_2 = (byte) 0x0d; 1481 protected static final byte DCONST_0 = (byte) 0x0e; 1482 protected static final byte DCONST_1 = (byte) 0x0f; 1483 protected static final byte ILOAD_0 = (byte) 0x1a; 1484 protected static final byte ILOAD_1 = (byte) 0x1b; 1485 protected static final byte ILOAD_2 = (byte) 0x1c; 1486 protected static final byte ILOAD_3 = (byte) 0x1d; 1487 protected static final byte LLOAD_0 = (byte) 0x1e; 1488 protected static final byte LLOAD_1 = (byte) 0x1f; 1489 protected static final byte LLOAD_2 = (byte) 0x20; 1490 protected static final byte LLOAD_3 = (byte) 0x21; 1491 protected static final byte FLOAD_0 = (byte) 0x22; 1492 protected static final byte FLOAD_1 = (byte) 0x23; 1493 protected static final byte FLOAD_2 = (byte) 0x24; 1494 protected static final byte FLOAD_3 = (byte) 0x25; 1495 protected static final byte DLOAD_0 = (byte) 0x26; 1496 protected static final byte DLOAD_1 = (byte) 0x27; 1497 protected static final byte DLOAD_2 = (byte) 0x28; 1498 protected static final byte DLOAD_3 = (byte) 0x29; 1499 protected static final byte ALOAD_0 = (byte) 0x2a; 1500 protected static final byte ALOAD_1 = (byte) 0x2b; 1501 protected static final byte ALOAD_2 = (byte) 0x2c; 1502 protected static final byte ALOAD_3 = (byte) 0x2d; 1503 protected static final byte IALOAD = (byte) 0x2e; 1504 protected static final byte LALOAD = (byte) 0x2f; 1505 protected static final byte FALOAD = (byte) 0x30; 1506 protected static final byte DALOAD = (byte) 0x31; 1507 protected static final byte AALOAD = (byte) 0x32; 1508 protected static final byte BALOAD = (byte) 0x33; 1509 protected static final byte CALOAD = (byte) 0x34; 1510 protected static final byte SALOAD = (byte) 0x35; 1511 protected static final byte ISTORE_0 = (byte) 0x3b; 1512 protected static final byte ISTORE_1 = (byte) 0x3c; 1513 protected static final byte ISTORE_2 = (byte) 0x3d; 1514 protected static final byte ISTORE_3 = (byte) 0x3e; 1515 protected static final byte LSTORE_0 = (byte) 0x3f; 1516 protected static final byte LSTORE_1 = (byte) 0x40; 1517 protected static final byte LSTORE_2 = (byte) 0x41; 1518 protected static final byte LSTORE_3 = (byte) 0x42; 1519 protected static final byte FSTORE_0 = (byte) 0x43; 1520 protected static final byte FSTORE_1 = (byte) 0x44; 1521 protected static final byte FSTORE_2 = (byte) 0x45; 1522 protected static final byte FSTORE_3 = (byte) 0x46; 1523 protected static final byte DSTORE_0 = (byte) 0x47; 1524 protected static final byte DSTORE_1 = (byte) 0x48; 1525 protected static final byte DSTORE_2 = (byte) 0x49; 1526 protected static final byte DSTORE_3 = (byte) 0x4a; 1527 protected static final byte ASTORE_0 = (byte) 0x4b; 1528 protected static final byte ASTORE_1 = (byte) 0x4c; 1529 protected static final byte ASTORE_2 = (byte) 0x4d; 1530 protected static final byte ASTORE_3 = (byte) 0x4e; 1531 protected static final byte IASTORE = (byte) 0x4f; 1532 protected static final byte LASTORE = (byte) 0x50; 1533 protected static final byte FASTORE = (byte) 0x51; 1534 protected static final byte DASTORE = (byte) 0x52; 1535 protected static final byte AASTORE = (byte) 0x53; 1536 protected static final byte BASTORE = (byte) 0x54; 1537 protected static final byte CASTORE = (byte) 0x55; 1538 protected static final byte SASTORE = (byte) 0x56; 1539 protected static final byte POP = (byte) 0x57; 1540 protected static final byte POP2 = (byte) 0x58; 1541 protected static final byte DUP = (byte) 0x59; 1542 protected static final byte DUP_X1 = (byte) 0x5a; 1543 protected static final byte DUP_X2 = (byte) 0x5b; 1544 protected static final byte DUP2 = (byte) 0x5c; 1545 protected static final byte DUP2_X1 = (byte) 0x5d; 1546 protected static final byte DUP2_X2 = (byte) 0x5e; 1547 protected static final byte SWAP = (byte) 0x5f; 1548 protected static final byte IADD = (byte) 0x60; 1549 protected static final byte LADD = (byte) 0x61; 1550 protected static final byte FADD = (byte) 0x62; 1551 protected static final byte DADD = (byte) 0x63; 1552 protected static final byte ISUB = (byte) 0x64; 1553 protected static final byte LSUB = (byte) 0x65; 1554 protected static final byte FSUB = (byte) 0x66; 1555 protected static final byte DSUB = (byte) 0x67; 1556 protected static final byte IMUL = (byte) 0x68; 1557 protected static final byte LMUL = (byte) 0x69; 1558 protected static final byte FMUL = (byte) 0x6a; 1559 protected static final byte DMUL = (byte) 0x6b; 1560 protected static final byte IDIV = (byte) 0x6c; 1561 protected static final byte LDIV = (byte) 0x6d; 1562 protected static final byte FDIV = (byte) 0x6e; 1563 protected static final byte DDIV = (byte) 0x6f; 1564 protected static final byte IREM = (byte) 0x70; 1565 protected static final byte LREM = (byte) 0x71; 1566 protected static final byte FREM = (byte) 0x72; 1567 protected static final byte DREM = (byte) 0x73; 1568 protected static final byte INEG = (byte) 0x74; 1569 protected static final byte LNEG = (byte) 0x75; 1570 protected static final byte FNEG = (byte) 0x76; 1571 protected static final byte DNEG = (byte) 0x77; 1572 protected static final byte ISHL = (byte) 0x78; 1573 protected static final byte LSHL = (byte) 0x79; 1574 protected static final byte ISHR = (byte) 0x7a; 1575 protected static final byte LSHR = (byte) 0x7b; 1576 protected static final byte IUSHR = (byte) 0x7c; 1577 protected static final byte LUSHR = (byte) 0x7d; 1578 protected static final byte IAND = (byte) 0x7e; 1579 protected static final byte LAND = (byte) 0x7f; 1580 protected static final byte IOR = (byte) 0x80; 1581 protected static final byte LOR = (byte) 0x81; 1582 protected static final byte IXOR = (byte) 0x82; 1583 protected static final byte LXOR = (byte) 0x83; 1584 protected static final byte I2L = (byte) 0x85; 1585 protected static final byte I2F = (byte) 0x86; 1586 protected static final byte I2D = (byte) 0x87; 1587 protected static final byte L2I = (byte) 0x88; 1588 protected static final byte L2F = (byte) 0x89; 1589 protected static final byte L2D = (byte) 0x8a; 1590 protected static final byte F2I = (byte) 0x8b; 1591 protected static final byte F2L = (byte) 0x8c; 1592 protected static final byte F2D = (byte) 0x8d; 1593 protected static final byte D2I = (byte) 0x8e; 1594 protected static final byte D2L = (byte) 0x8f; 1595 protected static final byte D2F = (byte) 0x90; 1596 protected static final byte I2B = (byte) 0x91; 1597 protected static final byte I2C = (byte) 0x92; 1598 protected static final byte I2S = (byte) 0x93; 1599 protected static final byte LCMP = (byte) 0x94; 1600 protected static final byte FCMPL = (byte) 0x95; 1601 protected static final byte FCMPG = (byte) 0x96; 1602 protected static final byte DCMPL = (byte) 0x97; 1603 protected static final byte DCMPG = (byte) 0x98; 1604 protected static final byte IRETURN = (byte) 0xac; 1605 protected static final byte LRETURN = (byte) 0xad; 1606 protected static final byte FRETURN = (byte) 0xae; 1607 protected static final byte DRETURN = (byte) 0xaf; 1608 protected static final byte ARETURN = (byte) 0xb0; 1609 protected static final byte RETURN = (byte) 0xb1; 1610 protected static final byte ARRAYLENGTH = (byte) 0xbe; 1611 protected static final byte ATHROW = (byte) 0xbf; 1612 protected static final byte MONITORENTER = (byte) 0xc2; 1613 protected static final byte MONITOREXIT = (byte) 0xc3; 1614 protected static final byte BIPUSH = (byte) 0x10; 1616 protected static final byte NEWARRAY = (byte) 0xbc; 1617 protected static final byte ILOAD = (byte) 0x15; 1619 protected static final byte LLOAD = (byte) 0x16; 1620 protected static final byte FLOAD = (byte) 0x17; 1621 protected static final byte DLOAD = (byte) 0x18; 1622 protected static final byte ALOAD = (byte) 0x19; 1623 protected static final byte ISTORE = (byte) 0x36; 1624 protected static final byte LSTORE = (byte) 0x37; 1625 protected static final byte FSTORE = (byte) 0x38; 1626 protected static final byte DSTORE = (byte) 0x39; 1627 protected static final byte ASTORE = (byte) 0x3a; 1628 protected static final byte RET = (byte) 0xa9; 1629 protected static final byte SIPUSH = (byte) 0x11; 1631 protected static final byte LDC = (byte) 0x12; 1633 protected static final byte LDC_W = (byte) 0x13; 1634 protected static final byte LDC2_W = (byte) 0x14; 1635 protected static final byte GETSTATIC = (byte) 0xb2; 1636 protected static final byte PUTSTATIC = (byte) 0xb3; 1637 protected static final byte GETFIELD = (byte) 0xb4; 1638 protected static final byte PUTFIELD = (byte) 0xb5; 1639 protected static final byte INVOKEVIRTUAL = (byte) 0xb6; 1640 protected static final byte INVOKESPECIAL = (byte) 0xb7; 1641 protected static final byte INVOKESTATIC = (byte) 0xb8; 1642 protected static final byte INVOKEINTERFACE = (byte) 0xb9; 1643 protected static final byte ANEWARRAY = (byte) 0xbd; 1644 protected static final byte NEW = (byte) 0xbb; 1645 protected static final byte CHECKCAST = (byte) 0xc0; 1646 protected static final byte INSTANCEOF = (byte) 0xc1; 1647 protected static final byte MULTIANEWARRAY = (byte) 0xc5; 1649 protected static final byte IFEQ = (byte) 0x99; 1651 protected static final byte IFNE = (byte) 0x9a; 1652 protected static final byte IFLT = (byte) 0x9b; 1653 protected static final byte IFGE = (byte) 0x9c; 1654 protected static final byte IFGT = (byte) 0x9d; 1655 protected static final byte IFLE = (byte) 0x9e; 1656 protected static final byte IF_ICMPEQ = (byte) 0x9f; 1657 protected static final byte IF_ICMPNE = (byte) 0xa0; 1658 protected static final byte IF_ICMPLT = (byte) 0xa1; 1659 protected static final byte IF_ICMPGE = (byte) 0xa2; 1660 protected static final byte IF_ICMPGT = (byte) 0xa3; 1661 protected static final byte IF_ICMPLE = (byte) 0xa4; 1662 protected static final byte IF_ACMPEQ = (byte) 0xa5; 1663 protected static final byte IF_ACMPNE = (byte) 0xa6; 1664 protected static final byte IFNULL = (byte) 0xc6; 1665 protected static final byte IFNONNULL = (byte) 0xc7; 1666 protected static final byte GOTO = (byte) 0xa7; 1668 protected static final byte JSR = (byte) 0xa8; 1669 protected static final byte GOTO_W = (byte) 0xc8; 1670 protected static final byte JSR_W = (byte) 0xc9; 1671 protected static final byte TABLESWITCH = (byte) 0xaa; 1673 protected static final byte LOOKUPSWITCH = (byte) 0xab; 1674 protected static final byte IINC = (byte) 0x84; 1676 protected static final byte WIDE = (byte) 0xc4; 1678 protected static final byte XXXUNUSEDXXX1 = (byte) 0xba; 1679 protected static final byte BREAKPOINT = (byte) 0xca; 1680 protected static final byte IMPDEP1 = (byte) 0xfe; 1681 protected static final byte IMPDEP2 = (byte) 0xff; 1682 1683 1686 private static String debugString(byte b) { 1689 switch (b) { 1690 case NOP: return "NOP"; 1691 case ACONST_NULL: return "ACONST_NULL"; 1692 case ICONST_M1: return "ICONST_M1"; 1693 case ICONST_0: return "ICONST_0"; 1694 case ICONST_1: return "ICONST_1"; 1695 case ICONST_2: return "ICONST_2"; 1696 case ICONST_3: return "ICONST_3"; 1697 case ICONST_4: return "ICONST_4"; 1698 case ICONST_5: return "ICONST_5"; 1699 case LCONST_0: return "LCONST_0"; 1700 case LCONST_1: return "LCONST_1"; 1701 case FCONST_0: return "FCONST_0"; 1702 case FCONST_1: return "FCONST_1"; 1703 case FCONST_2: return "FCONST_2"; 1704 case DCONST_0: return "DCONST_0"; 1705 case DCONST_1: return "DCONST_1"; 1706 case ILOAD_0: return "ILOAD_0"; 1707 case ILOAD_1: return "ILOAD_1"; 1708 case ILOAD_2: return "ILOAD_2"; 1709 case ILOAD_3: return "ILOAD_3"; 1710 case LLOAD_0: return "LLOAD_0"; 1711 case LLOAD_1: return "LLOAD_1"; 1712 case LLOAD_2: return "LLOAD_2"; 1713 case LLOAD_3: return "LLOAD_3"; 1714 case FLOAD_0: return "FLOAD_0"; 1715 case FLOAD_1: return "FLOAD_1"; 1716 case FLOAD_2: return "FLOAD_2"; 1717 case FLOAD_3: return "FLOAD_3"; 1718 case DLOAD_0: return "DLOAD_0"; 1719 case DLOAD_1: return "DLOAD_1"; 1720 case DLOAD_2: return "DLOAD_2"; 1721 case DLOAD_3: return "DLOAD_3"; 1722 case ALOAD_0: return "ALOAD_0"; 1723 case ALOAD_1: return "ALOAD_1"; 1724 case ALOAD_2: return "ALOAD_2"; 1725 case ALOAD_3: return "ALOAD_3"; 1726 case IALOAD: return "IALOAD"; 1727 case LALOAD: return "LALOAD"; 1728 case FALOAD: return "FALOAD"; 1729 case DALOAD: return "DALOAD"; 1730 case AALOAD: return "AALOAD"; 1731 case BALOAD: return "BALOAD"; 1732 case CALOAD: return "CALOAD"; 1733 case SALOAD: return "SALOAD"; 1734 case ISTORE_0: return "ISTORE_0"; 1735 case ISTORE_1: return "ISTORE_1"; 1736 case ISTORE_2: return "ISTORE_2"; 1737 case ISTORE_3: return "ISTORE_3"; 1738 case LSTORE_0: return "LSTORE_0"; 1739 case LSTORE_1: return "LSTORE_1"; 1740 case LSTORE_2: return "LSTORE_2"; 1741 case LSTORE_3: return "LSTORE_3"; 1742 case FSTORE_0: return "FSTORE_0"; 1743 case FSTORE_1: return "FSTORE_1"; 1744 case FSTORE_2: return "FSTORE_2"; 1745 case FSTORE_3: return "FSTORE_3"; 1746 case DSTORE_0: return "DSTORE_0"; 1747 case DSTORE_1: return "DSTORE_1"; 1748 case DSTORE_2: return "DSTORE_2"; 1749 case DSTORE_3: return "DSTORE_3"; 1750 case ASTORE_0: return "ASTORE_0"; 1751 case ASTORE_1: return "ASTORE_1"; 1752 case ASTORE_2: return "ASTORE_2"; 1753 case ASTORE_3: return "ASTORE_3"; 1754 case IASTORE: return "IASTORE"; 1755 case LASTORE: return "LASTORE"; 1756 case FASTORE: return "FASTORE"; 1757 case DASTORE: return "DASTORE"; 1758 case AASTORE: return "AASTORE"; 1759 case BASTORE: return "BASTORE"; 1760 case CASTORE: return "CASTORE"; 1761 case SASTORE: return "SASTORE"; 1762 case POP: return "POP"; 1763 case POP2: return "POP2"; 1764 case DUP: return "DUP"; 1765 case DUP_X1: return "DUP_X1"; 1766 case DUP_X2: return "DUP_X2"; 1767 case DUP2: return "DUP2"; 1768 case DUP2_X1: return "DUP2_X1"; 1769 case DUP2_X2: return "DUP2_X2"; 1770 case SWAP: return "SWAP"; 1771 case IADD: return "IADD"; 1772 case LADD: return "LADD"; 1773 case FADD: return "FADD"; 1774 case DADD: return "DADD"; 1775 case ISUB: return "ISUB"; 1776 case LSUB: return "LSUB"; 1777 case FSUB: return "FSUB"; 1778 case DSUB: return "DSUB"; 1779 case IMUL: return "IMUL"; 1780 case LMUL: return "LMUL"; 1781 case FMUL: return "FMUL"; 1782 case DMUL: return "DMUL"; 1783 case IDIV: return "IDIV"; 1784 case LDIV: return "LDIV"; 1785 case FDIV: return "FDIV"; 1786 case DDIV: return "DDIV"; 1787 case IREM: return "IREM"; 1788 case LREM: return "LREM"; 1789 case FREM: return "FREM"; 1790 case DREM: return "DREM"; 1791 case INEG: return "INEG"; 1792 case LNEG: return "LNEG"; 1793 case FNEG: return "FNEG"; 1794 case DNEG: return "DNEG"; 1795 case ISHL: return "ISHL"; 1796 case LSHL: return "LSHL"; 1797 case ISHR: return "ISHR"; 1798 case LSHR: return "LSHR"; 1799 case IUSHR: return "IUSHR"; 1800 case LUSHR: return "LUSHR"; 1801 case IAND: return "IAND"; 1802 case LAND: return "LAND"; 1803 case IOR: return "IOR"; 1804 case LOR: return "LOR"; 1805 case IXOR: return "IXOR"; 1806 case LXOR: return "LXOR"; 1807 case I2L: return "I2L"; 1808 case I2F: return "I2F"; 1809 case I2D: return "I2D"; 1810 case L2I: return "L2I"; 1811 case L2F: return "L2F"; 1812 case L2D: return "L2D"; 1813 case F2I: return "F2I"; 1814 case F2L: return "F2L"; 1815 case F2D: return "F2D"; 1816 case D2I: return "D2I"; 1817 case D2L: return "D2L"; 1818 case D2F: return "D2F"; 1819 case I2B: return "I2B"; 1820 case I2C: return "I2C"; 1821 case I2S: return "I2S"; 1822 case LCMP: return "LCMP"; 1823 case FCMPL: return "FCMPL"; 1824 case FCMPG: return "FCMPG"; 1825 case DCMPL: return "DCMPL"; 1826 case DCMPG: return "DCMPG"; 1827 case IRETURN: return "IRETURN"; 1828 case LRETURN: return "LRETURN"; 1829 case FRETURN: return "FRETURN"; 1830 case DRETURN: return "DRETURN"; 1831 case ARETURN: return "ARETURN"; 1832 case RETURN: return "RETURN"; 1833 case ARRAYLENGTH: return "ARRAYLENGTH"; 1834 case ATHROW: return "ATHROW"; 1835 case MONITORENTER: return "MONITORENTER"; 1836 case MONITOREXIT: return "MONITOREXIT"; 1837 case BIPUSH: return "BIPUSH"; 1838 case NEWARRAY: return "NEWARRAY"; 1839 case ILOAD: return "ILOAD"; 1840 case LLOAD: return "LLOAD"; 1841 case FLOAD: return "FLOAD"; 1842 case DLOAD: return "DLOAD"; 1843 case ALOAD: return "ALOAD"; 1844 case ISTORE: return "ISTORE"; 1845 case LSTORE: return "LSTORE"; 1846 case FSTORE: return "FSTORE"; 1847 case DSTORE: return "DSTORE"; 1848 case ASTORE: return "ASTORE"; 1849 case RET: return "RET"; 1850 case SIPUSH: return "SIPUSH"; 1851 case LDC: return "LDC"; 1852 case LDC_W: return "LDC_W"; 1853 case LDC2_W: return "LDC2_W"; 1854 case GETSTATIC: return "GETSTATIC"; 1855 case PUTSTATIC: return "PUTSTATIC"; 1856 case GETFIELD: return "GETFIELD"; 1857 case PUTFIELD: return "PUTFIELD"; 1858 case INVOKEVIRTUAL: return "INVOKEVIRTUAL"; 1859 case INVOKESPECIAL: return "INVOKESPECIAL"; 1860 case INVOKESTATIC: return "INVOKESTATIC"; 1861 case INVOKEINTERFACE: return "INVOKEINTERFACE"; 1862 case ANEWARRAY: return "ANEWARRAY"; 1863 case NEW: return "NEW"; 1864 case CHECKCAST: return "CHECKCAST"; 1865 case INSTANCEOF: return "INSTANCEOF"; 1866 case MULTIANEWARRAY: return "MULTIANEWARRAY"; 1867 case IFEQ: return "IFEQ"; 1868 case IFNE: return "IFNE"; 1869 case IFLT: return "IFLT"; 1870 case IFGE: return "IFGE"; 1871 case IFGT: return "IFGT"; 1872 case IFLE: return "IFLE"; 1873 case IF_ICMPEQ: return "IF_ICMPEQ"; 1874 case IF_ICMPNE: return "IF_ICMPNE"; 1875 case IF_ICMPLT: return "IF_ICMPLT"; 1876 case IF_ICMPGE: return "IF_ICMPGE"; 1877 case IF_ICMPGT: return "IF_ICMPGT"; 1878 case IF_ICMPLE: return "IF_ICMPLE"; 1879 case IF_ACMPEQ: return "IF_ACMPEQ"; 1880 case IF_ACMPNE: return "IF_ACMPNE"; 1881 case IFNULL: return "IFNULL"; 1882 case IFNONNULL: return "IFNONNULL"; 1883 case GOTO: return "GOTO"; 1884 case JSR: return "JSR"; 1885 case GOTO_W: return "GOTO_W"; 1886 case JSR_W: return "JSR_W"; 1887 case TABLESWITCH: return "TABLESWITCH"; 1888 case LOOKUPSWITCH: return "LOOKUPSWITCH"; 1889 case IINC: return "IINC"; 1890 case WIDE: return "WIDE"; 1891 case XXXUNUSEDXXX1: return "XXXUNUSEDXXX1"; 1892 case BREAKPOINT: return "BREAKPOINT"; 1893 case IMPDEP1: return "IMPDEP1"; 1894 case IMPDEP2: return "IMPDEP2"; 1895 default: throw new RuntimeException ("weird bytecode"); 1896 } 1897 } 1898} 1899 | Popular Tags |