KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > jode > bytecode > Instruction


1 /* Instruction Copyright (C) 1999-2002 Jochen Hoenicke.
2  *
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU Lesser General Public License as published by
5  * the Free Software Foundation; either version 2, or (at your option)
6  * any later version.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU Lesser General Public License
14  * along with this program; see the file COPYING.LESSER. If not, write to
15  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
16  *
17  * $Id: Instruction.java,v 1.9.2.1 2002/05/28 17:34:00 hoenicke Exp $
18  */

19
20 package jode.bytecode;
21
22 /**
23  * This class represents an instruction in the byte code.
24  *
25  */

26 public final class Instruction implements Opcodes{
27     /**
28      * The opcode of the instruction. We map some opcodes, e.g.
29      * <pre>
30      * iload_[0-3] -> iload, ldc_w -> ldc, wide iinc -> iinc.
31      * </pre>
32      */

33     // a byte would be enough, but then we would need an unsigned convert.
34
private int opcode;
35     /**
36      * If this opcode uses a local this gives the slot. For multianewarray
37      * this gives the dimension.
38      */

39     private int shortData;
40     /**
41      * The address of this opcode.
42      */

43     private int addr;
44     /**
45      * Optional object data for this opcode. There are four different
46      * usages of this field:
47      * <dl>
48      * <dt>opc_ldc / opc_ldc2_w</dt>
49      * <dd>The constant of type Integer/Long/Float/Double/String. </dd>
50      * <dt>opc_invokexxx / opc_xxxfield / opc_xxxstatic</dt>
51      * <dd>The field/method Reference</dd>
52      * <dt>opc_new / opc_checkcast / opc_instanceof / opc_multianewarray</dt>
53      * <dd>The typesignature of the class/array</dd>
54      * <dt>opc_lookupswitch</dt>
55      * <dd>The array of values of type int[]</dd>
56      * </dl>
57      */

58     private Object JavaDoc objData;
59     /**
60      * The successors of this opcodes, where flow may lead to
61      * (except that nextByAddr is implicit if !alwaysJump). The
62      * value null means no successor, if there is one succesor, this
63      * is of type Instruction, otherwise, this is an array of Instruction.
64      */

65     private Object JavaDoc succs;
66     /**
67      * The predecessors of this opcode, orthogonal to the succs array.
68      * This must be null or a non empty array.
69      */

70     private Instruction[] preds;
71     /**
72      * The next instruction in code order.
73      */

74     Instruction nextByAddr;
75     /**
76      * The previous instruction in code order, useful when changing
77      * the order.
78      */

79     Instruction prevByAddr;
80
81     /**
82      * You can use this field to add some info to each instruction.
83      * After using, you must set it to null again.
84      * @XXX Do we really need this. Every field here can quickly take
85      * half a megabyte!
86      */

87     private Object JavaDoc tmpInfo;
88
89     public Instruction(int opcode) {
90     this.opcode = opcode;
91     }
92
93     /**
94      * Returns the opcode of the instruction. We map some opcodes:
95      * <pre>
96      * [iflda]load_x -&gt; [iflda]load
97      * [iflda]store_x -&gt; [iflda]store
98      * [ifa]const_xx, ldc_w -&gt; ldc
99      * [dl]const_xx -&gt; ldc2_w
100      * wide opcode -&gt; opcode
101      * tableswitch -&gt; lookupswitch
102      * [a]newarray -&gt; multianewarray
103      * </pre>
104      */

105     public final int getOpcode() {
106     return opcode;
107     }
108
109     /**
110      * Returns the address of this opcode. As long as you don't remove
111      * or insert instructions, you can be sure, that the addresses of the
112      * opcodes are unique, and that
113      * <pre>
114      * instr.getAddr() + instr.getLength() == instr.getNextByAddr().getAddr()
115      * <pre>
116      *
117      * If you insert/remove Instructions, you should be aware that the
118      * above property is not guaranteed anymore.
119      */

120     public final int getAddr() {
121     return addr;
122     }
123
124     public final int getNextAddr() {
125     return nextByAddr.addr;
126     }
127
128     /**
129      * Returns the length of this opcode. See getAddr() for some
130      * notes. Note that the length doesn't necessarily reflect the
131      * real length, when this bytecode is written again, since the
132      * length of an ldc instruction depends on the number of entries
133      * in constant pool, and the order they are allocated.
134      */

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     /*{ require { hasLocalSlot()
151                   :: "Instruction has no slot" } }*/

152     {
153     return shortData;
154     }
155
156     public final void setLocalSlot(int slot)
157     /*{ require { hasLocalSlot()
158                   :: "Instruction has no slot" } }*/

159     {
160     shortData = slot;
161     }
162
163     /**
164      * Optional integer data for this opcode. There are various uses
165      * for this:
166      * <dl>
167      * <dt>opc_iinc</dt>
168      * <dd>The value by which the constant is increased/decreased. (short)</dd>
169      * <dt>opc_multianewarray</dt>
170      * <dd>The number of dimensions (1..255)</dd>
171      * </dl>
172      */

173     public final int getIncrement()
174     /*{ require { opcode == opc_iinc || opcode == opc_multianewarray
175                   || opcode == opc_tableswitch
176                   :: "Instruction has no int data" } }*/

177     {
178     /* shortData already used for local slot */
179     return ((Short JavaDoc) objData).shortValue();
180     }
181
182     /**
183      * Optional integer data for this opcode. There are various uses
184      * for this:
185      * <dl>
186      * <dt>opc_iinc</dt>
187      * <dd>The value by which the constant is increased/decreased. (short)</dd>
188      * <dt>opc_multianewarray</dt>
189      * <dd>The number of dimensions (1..255)</dd>
190      * </dl>
191      */

192     public final void setIncrement(int incr)
193     /*{ require { opcode == opc_iinc || opcode == opc_multianewarray
194                   :: "Instruction has no int data" } }*/

195     {
196     /* shortData already used for local slot */
197     objData = new Short JavaDoc((short) incr);
198     }
199
200     /**
201      *
202      */

203     public final int getDimensions()
204     /*{ require { opcode == opc_multianewarray
205                   :: "Instruction has no dimensions" } }*/

206     {
207     return shortData;
208     }
209
210     /**
211      *
212      */

213     public final void setDimensions(int dims)
214     /*{ require { opcode == opc_multianewarray
215                   :: "Instruction has no dimensions" } }*/

216     {
217     shortData = dims;
218     }
219
220     public final Object JavaDoc getConstant()
221     /*{ require { opcode == opc_ldc || opcode == opc_ldc2_w
222                   :: "Instruction has no constant" } }*/

223     {
224     return objData;
225     }
226
227     public final void setConstant(Object JavaDoc constant)
228     /*{ require { opcode == opc_ldc || opcode == opc_ldc2_w
229                   :: "Instruction has no constant" } }*/

230     {
231     objData = constant;
232     }
233
234     public final Reference getReference()
235     /*{ require { opcode >= opc_getstatic && opcode <= opc_invokeinterface
236                   :: "Instruction has no reference" } }*/

237     {
238     return (Reference) objData;
239     }
240
241     public final void setReference(Reference ref)
242     /*{ require { opcode >= opc_getstatic && opcode <= opc_invokeinterface
243                   :: "Instruction has no reference" } }*/

244     {
245     objData = ref;
246     }
247
248     public final String JavaDoc getClazzType()
249     /*{ require { opcode == opc_new
250                   || opcode == opc_checkcast
251                   || opcode == opc_instanceof
252                   || opcode == opc_multianewarray
253           :: "Instruction has no typesig" } }*/

254     {
255     return (String JavaDoc) objData;
256     }
257
258     public final void setClazzType(String JavaDoc type)
259     /*{ require { opcode == opc_new
260                   || opcode == opc_checkcast
261                   || opcode == opc_instanceof
262                   || opcode == opc_multianewarray
263           :: "Instruction has no typesig" } }*/

264     {
265     objData = type;
266     }
267
268     public final int[] getValues()
269     /*{ require { opcode == opc_lookupswitch
270                   :: "Instruction has no values" } }*/

271     {
272     return (int[]) objData;
273     }
274
275     public final void setValues(int[] values)
276     /*{ require { opcode == opc_lookupswitch
277                   :: "Instruction has no values" } }*/

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     /**
307      * Returns true if this opcode has successors, other than the implicit
308      * getNextByAddr().
309      */

310     public boolean hasSuccs() {
311     return succs != null;
312     }
313
314     /**
315      * Returns the successors of this opcodes, where flow may lead to
316      * (except that nextByAddr is implicit if !alwaysJump). The
317      * value null means that there is no successor.
318      */

319     public final Instruction[] getSuccs() {
320     if (succs instanceof Instruction)
321         return new Instruction[] { (Instruction) succs };
322     return (Instruction[]) succs;
323     }
324
325     /**
326      * Returns the single successor of this opcodes. This gives the
327      * target of a goto, jsr, or if opcode.
328      * @return null if there is no successor, otherwise the successor.
329      * @exception ClassCastException if this has more than one succ.
330      */

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 JavaDoc getTmpInfo() {
348     return tmpInfo;
349     }
350
351     public final void setTmpInfo(Object JavaDoc info) {
352     tmpInfo = info;
353     }
354
355
356     // INTERNAL FUNCTIONS TO KEEP PREDS AND SUCCS CONSISTENT
357

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     /**
372      * @param to may be null
373      */

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     /**
386      * @exception ClassCastException if newSuccs is neither an Instruction
387      * nor an array of instructions.
388      */

389     public final void setSuccs(Object JavaDoc 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     /* Hopefully it doesn't matter if this is slow */
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     // ADDING, REMOVING AND REPLACING INSTRUCTIONS
447

448     /**
449      * Replaces the opcode of this instruction. You should only use the
450      * mapped opcodes:
451      * <pre>
452      * [iflda]load_x -&gt; [iflda]load
453      * [iflda]store_x -&gt; [iflda]store
454      * [ifa]const_xx, ldc_w -&gt; ldc
455      * [dl]const_xx -&gt; ldc2_w
456      * wide opcode -&gt; opcode
457      * tableswitch -&gt; lookupswitch
458      * [a]newarray -&gt; multianewarray
459      * </pre>
460      */

461     public final void replaceInstruction(Instruction newInstr,
462                      BytecodeInfo codeinfo) {
463     /* remove predecessors of successors */
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     /* promote the successors of the predecessors to newInstr */
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     /* adjust exception handlers */
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     /* adjust local variable table and line number table */
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     /* adjust exception handlers end */
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     /**
531      * Removes this instruction (as if it would be replaced by a nop).
532      */

533     void removeInstruction(BytecodeInfo codeinfo) {
534
535     /* remove from chained list and adjust addr / length */
536     prevByAddr.nextByAddr = nextByAddr;
537     nextByAddr.prevByAddr = prevByAddr;
538
539     /* remove predecessors of successors */
540     removeSuccs();
541
542     /* promote the predecessors to next instruction */
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     /* adjust exception handlers */
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         /* Remove the handler.
565          * This is very seldom, so we can make it slow */

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     /* adjust local variable table and line number table */
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             /* Remove the local variable info.
589              * This is very seldom, so we can make it slow
590              */

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             /* Remove the line number.
615              * This is very seldom, so we can make it slow */

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     /**
648      * This returns the number of stack entries this instruction
649      * pushes and pops from the stack. The result fills the given
650      * array.
651      *
652      * @param poppush an array of two ints. The first element will
653      * get the number of pops, the second the number of pushes.
654      */

655     public void getStackPopPush(int[] poppush)
656     /*{ require { poppush != null && poppush.length == 2
657         :: "poppush must be an array of two ints" } } */

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 JavaDoc 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 JavaDoc getDescription() {
745     StringBuffer JavaDoc result = new StringBuffer JavaDoc(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 JavaDoc toString() {
771         return "" + addr + "_" + Integer.toHexString(hashCode());
772     }
773
774     private final static String JavaDoc 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     /* stackDelta contains \100 if stack count of opcode is variable
778      * \177 if opcode is illegal, or 8*stack_push + stack_pop otherwise
779      * The above values are extracted from following list with:
780      * perl -ne'/"(.*)"/ and print $1'
781      *
782      * "\000" // nop
783      * "\010\010\010\010\010\010\010\010" // aconst_null, iconst_m?[0-5]
784      * "\020\020\010\010\010\020\020" // [lfd]const_[0-2]
785      * "\010\010\010\010\020" // sipush bipush ldcx
786      * "\010\020\010\020\010" // [ilfda]load
787      * "\010\010\010\010"
788      * "\020\020\020\020"
789      * "\010\010\010\010"
790      * "\020\020\020\020"
791      * "\010\010\010\010"
792      * "\012\022\012\022\012\012\012\012" // [ilfdabcs]aload
793      * "\001\002\001\002\001" // [ilfda]store
794      * "\001\001\001\001"
795      * "\002\002\002\002"
796      * "\001\001\001\001"
797      * "\002\002\002\002"
798      * "\001\001\001\001"
799      * "\003\004\003\004\003\003\003\003" // [ilfdabcs]astore
800      * "\001\002" // pop
801      * "\021\032\043\042\053\064" // dup2?(_x[12])?
802      * "\022" // swap
803      * "\012\024\012\024" // [ilfd]add
804      * "\012\024\012\024" // [ilfd]sub
805      * "\012\024\012\024" // [ilfd]mul
806      * "\012\024\012\024" // [ilfd]div
807      * "\012\024\012\024" // [ilfd]rem
808      * "\011\022\011\022" // [ilfd]neg
809      * "\012\023\012\023\012\023" // [il]u?sh[lr]
810      * "\012\024\012\024\012\024" // [il](and|or|xor)
811      * "\000" // opc_iinc
812      * "\021\011\021" // i2[lfd]
813      * "\012\012\022" // l2[ifd]
814      * "\011\021\021" // f2[ild]
815      * "\012\022\012" // d2[ilf]
816      * "\011\011\011" // i2[bcs]
817      * "\014\012\012\014\014" // [lfd]cmp.?
818      * "\001\001\001\001\001\001" // if..
819      * "\002\002\002\002\002\002" // if_icmp..
820      * "\002\002" // if_acmp..
821      * "\000\010\000\001\001" // goto,jsr,ret, .*switch
822      * "\001\002\001\002\001\000" // [ilfda]?return
823      * "\100\100\100\100" // (get/put)(static|field)
824      * "\100\100\100\100" // invoke.*
825      * "\177\010\011\011\011" // 186 - 190
826      * "\001\011\011\001\001" // 191 - 195
827      * "\177\100\001\001" // 196 - 199
828      * "\000\010" // goto_w, jsr_w
829      */

830 }
831
Popular Tags