1 /*
2  * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 package sun.tools.asm;
27 
28 import sun.tools.java.*;
29 import java.util.Enumeration;
30 import java.io.IOException;
31 import java.io.DataOutputStream;
32 
33 /**
34  * An Java instruction
35  *
36  * WARNING: The contents of this source file are not part of any
37  * supported API.  Code that depends on them does so at its own risk:
38  * they are subject to change or removal without notice.
39  */
40 public
41 class Instruction implements Constants {
42     long where;
43     int pc;
44     int opc;
45     Object value;
46     Instruction next;
47 //JCOV
48     boolean flagCondInverted;        /* if true, the condition  is reversed
49                                    relatively of source code */
50     boolean flagNoCovered = false; /* if true, the command will
51                                    ignored for coverage */
52 
53 
54     /**
55      * Constructor
56      */
Instruction(long where, int opc, Object value, boolean flagCondInverted)57     public Instruction(long where, int opc, Object value, boolean flagCondInverted) {
58         this.where = where;
59         this.opc = opc;
60         this.value = value;
61         this.flagCondInverted = flagCondInverted;
62     }
63 
64     /**
65      * Constructor
66      */
Instruction(boolean flagNoCovered, long where, int opc, Object value)67     public Instruction(boolean flagNoCovered, long where, int opc, Object value) {
68         this.where = where;
69         this.opc = opc;
70         this.value = value;
71         this.flagNoCovered = flagNoCovered;
72     }
73 
74     /**
75      * Constructor
76      */
Instruction(long where, int opc, boolean flagNoCovered)77     public Instruction(long where, int opc, boolean flagNoCovered) {
78         this.where = where;
79         this.opc = opc;
80         this.flagNoCovered = flagNoCovered;
81     }
82 //end JCOV
83 
84     /**
85      * Constructor
86      */
Instruction(long where, int opc, Object value)87     public Instruction(long where, int opc, Object value) {
88         this.where = where;
89         this.opc = opc;
90         this.value = value;
91     }
92 
93     /**
94      * When deciding between a lookupswitch and a tableswitch, this
95      * value is used in determining how much size increase is
96      * acceptable.
97      */
98     public static final double SWITCHRATIO;
99 
100     static {
101         // Set SWITCHRATIO from the property javac.switchratio
102         // if it exists and is reasonable.  Otherwise, set
103         // SWITCHRATIO to 1.5, meaning that we will accept a 1.5x
104         // blowup (for the instruction) to use a tableswitch instead
105         // of a lookupswitch.
106         double ratio = 1.5;
107         String valStr = System.getProperty("javac.switchratio");
108         if (valStr != null) {
109             try {
110                 double temp = Double.valueOf(valStr).doubleValue();
111                 if (!(Double.isNaN(temp) || temp < 0.0)) {
112                     ratio = temp;
113                 }
114             } catch (NumberFormatException ee) {}
115         }
116         SWITCHRATIO = ratio;
117     }
118 
119     /**
120      * Accessor
121      */
getOpcode()122     public int getOpcode() {
123         return pc;
124      }
125 
getValue()126     public Object getValue() {
127         return value;
128      }
129 
setValue(Object value)130     public void setValue(Object value) {
131         this.value = value;
132      }
133 
134 
135     /**
136      * Optimize
137      */
optimize(Environment env)138     void optimize(Environment env) {
139         switch (opc) {
140           case opc_istore: case opc_lstore: case opc_fstore:
141           case opc_dstore: case opc_astore:
142             // Don't keep the LocalVariable info around, unless we
143             // are actually going to generate a local variable table.
144             if ((value instanceof LocalVariable) && !env.debug_vars()) {
145                 value = ((LocalVariable)value).slot;
146             }
147             break;
148 
149           case opc_goto: {
150             Label lbl = (Label)value;
151             value = lbl = lbl.getDestination();
152             if (lbl == next) {
153                 // goto to the next instruction, obsolete
154                 opc = opc_dead;
155                 break;
156             }
157 
158             // We optimize
159             //
160             //          goto Tag
161             //          ...
162             //    Tag:
163             //          return
164             //
165             // except when we're generating debuggable code.  When
166             // we're generating debuggable code, we leave it alone,
167             // in order to provide better stepping behavior.  Consider
168             // a method the end of which looks like this:
169             //
170             //          ...
171             //          break;
172             //      }   // end of loop
173             //  }   // end of method
174             //
175             // If we optimize the goto away, we'll be left with a
176             // single instruction (return) and the need to ascribe that
177             // instruction to two source lines (the break statement and
178             // the method's right curly).  Can't get there from here.
179             // Depending on which line-number ascription we choose, the
180             // stepping user will step directly from the break statement
181             // back into the caller of the method (case 1) or from the
182             // statement that precedes the break statement to the method's
183             // right curly (case 2).  Similarly, he'll be able to set a
184             // breakpoint on the break statement (case 1) or the method's
185             // right curly (case 2), but not on both.  Neither case 1 nor
186             // case 2 is desirable.  .We want him to see both the break
187             // statement and the method's right curly when stepping,
188             // and we want him to be able to set a breakpoint on either or
189             // both.  So we suppress the optimization when generating
190             // debuggable code.
191             // (Above notes from brucek@eng in JDK1.0.2, copied here
192             //  by kelly.ohair@eng for JDK1.1)
193             //
194             // With the changes to allow -O and -g at the same time,
195             // I've changed the condition to be whether optimization is
196             // on instead of the debugging flag being off.
197             //     - david.stoutamire@eng for 1.2
198 
199             if (lbl.next != null && env.opt()) {
200                 switch (lbl.next.opc) {
201                   case opc_return:  case opc_ireturn: case opc_lreturn:
202                   case opc_freturn: case opc_dreturn: case opc_areturn:
203                     // goto to return
204                     opc = lbl.next.opc;
205                     value = lbl.next.value;
206                     break;
207                 }
208             }
209             break;
210           }
211 
212           case opc_ifeq:   case opc_ifne:   case opc_ifgt:
213           case opc_ifge:   case opc_iflt:   case opc_ifle:
214           case opc_ifnull: case opc_ifnonnull:
215             value = ((Label)value).getDestination();
216             if (value == next) {
217                 // branch to next instruction, obsolete
218                 opc = opc_pop;
219                 break;
220             }
221             if ((next.opc == opc_goto) && (value == next.next)) {
222                 // Conditional branch over goto, invert
223                 // Note that you can't invert all conditions, condition
224                 // results for float/double compares are not invertable.
225                 switch (opc) {
226                   case opc_ifeq:      opc = opc_ifne; break;
227                   case opc_ifne:      opc = opc_ifeq; break;
228                   case opc_iflt:      opc = opc_ifge; break;
229                   case opc_ifle:      opc = opc_ifgt; break;
230                   case opc_ifgt:      opc = opc_ifle; break;
231                   case opc_ifge:      opc = opc_iflt; break;
232                   case opc_ifnull:    opc = opc_ifnonnull; break;
233                   case opc_ifnonnull: opc = opc_ifnull; break;
234                 }
235 //JCOV
236                 flagCondInverted = !flagCondInverted;
237 //end JCOV
238                 value = next.value;
239                 next.opc = opc_dead;
240             }
241             break;
242 
243           case opc_if_acmpeq:   case opc_if_acmpne:
244           case opc_if_icmpeq:   case opc_if_icmpne:
245           case opc_if_icmpgt:   case opc_if_icmpge:
246           case opc_if_icmplt:   case opc_if_icmple:
247             value = ((Label)value).getDestination();
248             if (value == next) {
249                 // branch to next instruction, obsolete
250                 opc = opc_pop2;
251                 break;
252             }
253             if ((next.opc == opc_goto) && (value == next.next)) {
254                 // Conditional branch over goto, invert
255                 switch (opc) {
256                   case opc_if_acmpeq: opc = opc_if_acmpne; break;
257                   case opc_if_acmpne: opc = opc_if_acmpeq; break;
258                   case opc_if_icmpeq: opc = opc_if_icmpne; break;
259                   case opc_if_icmpne: opc = opc_if_icmpeq; break;
260                   case opc_if_icmpgt: opc = opc_if_icmple; break;
261                   case opc_if_icmpge: opc = opc_if_icmplt; break;
262                   case opc_if_icmplt: opc = opc_if_icmpge; break;
263                   case opc_if_icmple: opc = opc_if_icmpgt; break;
264                 }
265 //JCOV
266                 flagCondInverted = !flagCondInverted;
267 //end JCOV
268                 value = next.value;
269                 next.opc = opc_dead;
270             }
271             break;
272 
273           case opc_tableswitch:
274           case opc_lookupswitch: {
275             SwitchData sw = (SwitchData)value;
276             sw.defaultLabel = sw.defaultLabel.getDestination();
277             for (Enumeration<Integer> e = sw.tab.keys() ; e.hasMoreElements() ; ) {
278                 Integer k = e.nextElement();
279                 Label lbl = sw.tab.get(k);
280                 sw.tab.put(k, lbl.getDestination());
281             }
282 
283             // Compute the approximate sizes of a tableswitch and a
284             // lookupswitch.  Decide which one we want to generate.
285 
286             long range = (long)sw.maxValue - (long)sw.minValue + 1;
287             long entries = sw.tab.size();
288 
289             long tableSize = 4 + range;
290             long lookupSize = 3 + 2 * entries;
291 
292             if (tableSize <= lookupSize * SWITCHRATIO) {
293                 opc = opc_tableswitch;
294             } else {
295                 opc = opc_lookupswitch;
296             }
297             break;
298           }
299 
300         }
301     }
302 
303     /**
304      * Collect constants into the constant table
305      */
collect(ConstantPool tab)306     void collect(ConstantPool tab) {
307         switch (opc) {
308           case opc_istore:      case opc_lstore:        case opc_fstore:
309           case opc_dstore:      case opc_astore:
310             if (value instanceof LocalVariable) {
311                 MemberDefinition field = ((LocalVariable)value).field;
312                 tab.put(field.getName().toString());
313                 tab.put(field.getType().getTypeSignature());
314             }
315             return;
316 
317           case opc_new:                 case opc_putfield:
318           case opc_putstatic:           case opc_getfield:
319           case opc_getstatic:           case opc_invokevirtual:
320           case opc_invokespecial:       case opc_invokestatic:
321           case opc_invokeinterface:     case opc_instanceof:
322           case opc_checkcast:
323             tab.put(value);
324             return;
325 
326           case opc_anewarray:
327             tab.put(value);
328             return;
329 
330           case opc_multianewarray:
331             tab.put(((ArrayData)value).type);
332             return;
333 
334           case opc_ldc:
335           case opc_ldc_w:
336             if (value instanceof Integer) {
337                 int v = ((Integer)value).intValue();
338                 if ((v >= -1) && (v <= 5)) {
339                     opc = opc_iconst_0 + v;
340                     return;
341                 } else if ((v >= -(1 << 7)) && (v < (1 << 7))) {
342                     opc = opc_bipush;
343                     return;
344                 } else if ((v >= -(1 << 15)) && (v < (1 << 15))) {
345                     opc = opc_sipush;
346                     return;
347                 }
348             } else if (value instanceof Float) {
349                 float v = ((Float)value).floatValue();
350                 if (v == 0) {
351                     if (Float.floatToIntBits(v) == 0) {
352                         opc = opc_fconst_0;
353                         return;
354                     }
355                 } else if (v == 1) {
356                     opc = opc_fconst_1;
357                     return;
358                 } else if (v == 2) {
359                     opc = opc_fconst_2;
360                     return;
361                 }
362             }
363             tab.put(value);
364             return;
365 
366           case opc_ldc2_w:
367             if (value instanceof Long) {
368                 long v = ((Long)value).longValue();
369                 if (v == 0) {
370                     opc = opc_lconst_0;
371                     return;
372                 } else if (v == 1) {
373                     opc = opc_lconst_1;
374                     return;
375                 }
376             } else if (value instanceof Double) {
377                 double v = ((Double)value).doubleValue();
378                 if (v == 0) {
379                     if (Double.doubleToLongBits(v) == 0) {
380                         opc = opc_dconst_0;
381                         return;
382                     }
383                 } else if (v == 1) {
384                     opc = opc_dconst_1;
385                     return;
386                 }
387             }
388             tab.put(value);
389             return;
390 
391           case opc_try:
392             for (Enumeration<CatchData> e = ((TryData)value).catches.elements() ; e.hasMoreElements() ;) {
393                 CatchData cd = e.nextElement();
394                 if (cd.getType() != null) {
395                     tab.put(cd.getType());
396                 }
397             }
398             return;
399 
400           case opc_nop:
401             if ((value != null) && (value instanceof ClassDeclaration))
402                 tab.put(value);
403                 return;
404         }
405     }
406 
407     /**
408      * Balance the stack
409      */
balance()410     int balance() {
411         switch (opc) {
412           case opc_dead:        case opc_label:         case opc_iinc:
413           case opc_arraylength: case opc_laload:        case opc_daload:
414           case opc_nop:         case opc_ineg:          case opc_fneg:
415           case opc_lneg:        case opc_dneg:          case opc_i2f:
416           case opc_f2i:         case opc_l2d:           case opc_d2l:
417           case opc_i2b:         case opc_i2c:           case opc_i2s:
418           case opc_jsr:         case opc_goto:          case opc_jsr_w:
419           case opc_goto_w:      case opc_return:        case opc_ret:
420           case opc_instanceof:  case opc_checkcast:     case opc_newarray:
421           case opc_anewarray:   case opc_try:           case opc_swap:
422             return 0;
423 
424           case opc_ldc:         case opc_ldc_w:         case opc_bipush:
425           case opc_sipush:      case opc_aconst_null:   case opc_iconst_m1:
426           case opc_iconst_0:    case opc_iconst_1:      case opc_iconst_2:
427           case opc_iconst_3:    case opc_iconst_4:      case opc_iconst_5:
428           case opc_fconst_0:    case opc_fconst_1:      case opc_fconst_2:
429           case opc_iload:       case opc_fload:         case opc_aload:
430           case opc_dup:         case opc_dup_x1:        case opc_dup_x2:
431           case opc_i2l:         case opc_i2d:           case opc_f2l:
432           case opc_f2d:         case opc_new:
433             return 1;
434 
435           case opc_lload:       case opc_dload:         case opc_dup2:
436           case opc_dup2_x1:     case opc_dup2_x2:       case opc_ldc2_w:
437           case opc_lconst_0:    case opc_lconst_1:      case opc_dconst_0:
438           case opc_dconst_1:
439             return 2;
440 
441           case opc_istore:      case opc_fstore:        case opc_astore:
442           case opc_iaload:      case opc_faload:        case opc_aaload:
443           case opc_baload:      case opc_caload:        case opc_saload:
444           case opc_pop:         case opc_iadd:          case opc_fadd:
445           case opc_isub:        case opc_fsub:          case opc_imul:
446           case opc_fmul:        case opc_idiv:          case opc_fdiv:
447           case opc_irem:        case opc_frem:          case opc_ishl:
448           case opc_ishr:        case opc_iushr:         case opc_lshl:
449           case opc_lshr:        case opc_lushr:         case opc_iand:
450           case opc_ior:         case opc_ixor:          case opc_l2i:
451           case opc_l2f:         case opc_d2i:           case opc_d2f:
452           case opc_ifeq:        case opc_ifne:          case opc_iflt:
453           case opc_ifle:        case opc_ifgt:          case opc_ifge:
454           case opc_ifnull:      case opc_ifnonnull:     case opc_fcmpl:
455           case opc_fcmpg:       case opc_ireturn:       case opc_freturn:
456           case opc_areturn:     case opc_tableswitch:   case opc_lookupswitch:
457           case opc_athrow:      case opc_monitorenter:  case opc_monitorexit:
458             return -1;
459 
460           case opc_lstore:      case opc_dstore:        case opc_pop2:
461           case opc_ladd:        case opc_dadd:          case opc_lsub:
462           case opc_dsub:        case opc_lmul:          case opc_dmul:
463           case opc_ldiv:        case opc_ddiv:          case opc_lrem:
464           case opc_drem:        case opc_land:          case opc_lor:
465           case opc_lxor:        case opc_if_acmpeq:     case opc_if_acmpne:
466           case opc_if_icmpeq:   case opc_if_icmpne:     case opc_if_icmplt:
467           case opc_if_icmple:   case opc_if_icmpgt:     case opc_if_icmpge:
468           case opc_lreturn:     case opc_dreturn:
469             return -2;
470 
471           case opc_iastore:     case opc_fastore:       case opc_aastore:
472           case opc_bastore:     case opc_castore:       case opc_sastore:
473           case opc_lcmp:        case opc_dcmpl:         case opc_dcmpg:
474             return -3;
475 
476           case opc_lastore:     case opc_dastore:
477             return -4;
478 
479           case opc_multianewarray:
480             return 1 - ((ArrayData)value).nargs;
481 
482           case opc_getfield:
483             return ((MemberDefinition)value).getType().stackSize() - 1;
484 
485           case opc_putfield:
486             return -1 - ((MemberDefinition)value).getType().stackSize();
487 
488           case opc_getstatic:
489             return ((MemberDefinition)value).getType().stackSize();
490 
491           case opc_putstatic:
492             return -((MemberDefinition)value).getType().stackSize();
493 
494           case opc_invokevirtual:
495           case opc_invokespecial:
496           case opc_invokeinterface:
497             return ((MemberDefinition)value).getType().getReturnType().stackSize() -
498                    (((MemberDefinition)value).getType().stackSize() + 1);
499 
500           case opc_invokestatic:
501             return ((MemberDefinition)value).getType().getReturnType().stackSize() -
502                    (((MemberDefinition)value).getType().stackSize());
503         }
504         throw new CompilerError("invalid opcode: " + toString());
505     }
506 
507     /**
508      * Return the size of the instruction
509      */
size(ConstantPool tab)510     int size(ConstantPool tab) {
511         switch (opc) {
512           case opc_try:         case opc_label:         case opc_dead:
513             return 0;
514 
515           case opc_bipush:      case opc_newarray:
516             return 2;
517 
518           case opc_sipush:      case opc_goto:          case opc_jsr:
519           case opc_ifeq:        case opc_ifne:          case opc_ifgt:
520           case opc_ifge:        case opc_iflt:          case opc_ifle:
521           case opc_ifnull:      case opc_ifnonnull:     case opc_if_acmpeq:
522           case opc_if_acmpne:   case opc_if_icmpeq:     case opc_if_icmpne:
523           case opc_if_icmpgt:   case opc_if_icmpge:     case opc_if_icmplt:
524           case opc_if_icmple:
525             return 3;
526 
527           case opc_ldc:
528           case opc_ldc_w:
529             if (tab.index(value) < 256) {
530                 opc = opc_ldc;
531                 return 2;
532             } else {
533                 opc = opc_ldc_w;
534                 return 3;
535             }
536 
537           case opc_iload:       case opc_lload:         case opc_fload:
538           case opc_dload:       case opc_aload: {
539             int v = ((Number)value).intValue();
540             if (v < 4) {
541                 if (v < 0) {
542                     throw new CompilerError("invalid slot: " + toString()
543                         + "\nThis error possibly resulted from poorly constructed class paths.");
544                 }
545                 opc = opc_iload_0 + (opc - opc_iload) * 4 + v;
546                 return 1;
547             } else if (v <= 255) {
548                 return 2;
549             } else {
550                 opc += 256;     // indicate wide variant
551                 return 4;
552             }
553           }
554 
555            case opc_iinc: {
556                int register = ((int[])value)[0];
557                int increment = ((int[])value)[1];
558                if (register < 0) {
559                    throw new CompilerError("invalid slot: " + toString());
560                }
561                if (register <= 255 && (((byte)increment) == increment)) {
562                    return 3;
563                } else {
564                    opc += 256;          // indicate wide variant
565                    return 6;
566                }
567            }
568 
569           case opc_istore:      case opc_lstore:        case opc_fstore:
570           case opc_dstore:      case opc_astore: {
571             int v = (value instanceof Number) ?
572                 ((Number)value).intValue() : ((LocalVariable)value).slot;
573             if (v < 4) {
574                 if (v < 0) {
575                     throw new CompilerError("invalid slot: " + toString());
576                 }
577                 opc = opc_istore_0 + (opc - opc_istore) * 4 + v;
578                 return 1;
579             } else if (v <= 255) {
580                 return 2;
581             } else {
582                 opc += 256;     // indicate wide variant
583                 return 4;
584             }
585           }
586 
587           case opc_ret: {
588               int v = ((Number)value).intValue();
589               if (v <= 255) {
590                   if (v < 0) {
591                       throw new CompilerError("invalid slot: " + toString());
592                   }
593                   return 2;
594               } else {
595                   opc += 256;   // indicate wide variant
596                   return 4;
597               }
598           }
599 
600           case opc_ldc2_w:              case opc_new:
601           case opc_putstatic:           case opc_getstatic:
602           case opc_putfield:            case opc_getfield:
603           case opc_invokevirtual:       case opc_invokespecial:
604           case opc_invokestatic:        case opc_instanceof:
605           case opc_checkcast:           case opc_anewarray:
606             return 3;
607 
608           case opc_multianewarray:
609             return 4;
610 
611           case opc_invokeinterface:
612           case opc_goto_w:
613           case opc_jsr_w:
614             return 5;
615 
616           case opc_tableswitch: {
617             SwitchData sw = (SwitchData)value;
618             int n = 1;
619             for(; ((pc + n) % 4) != 0 ; n++);
620             return n + 16 + (sw.maxValue - sw.minValue) * 4;
621           }
622 
623           case opc_lookupswitch: {
624             SwitchData sw = (SwitchData)value;
625             int n = 1;
626             for(; ((pc + n) % 4) != 0 ; n++);
627             return n + 8 + sw.tab.size() * 8;
628           }
629 
630           case opc_nop:
631             if ((value != null) && !(value instanceof Integer))
632                 return 2;
633             else
634                 return 1;
635         }
636 
637         // most opcodes are only 1 byte long
638         return 1;
639     }
640 
641     /**
642      * Generate code
643      */
644     @SuppressWarnings("fallthrough")
write(DataOutputStream out, ConstantPool tab)645     void write(DataOutputStream out, ConstantPool tab) throws IOException {
646         switch (opc) {
647           case opc_try:         case opc_label:         case opc_dead:
648             break;
649 
650           case opc_bipush:      case opc_newarray:
651           case opc_iload:       case opc_lload:         case opc_fload:
652           case opc_dload:       case opc_aload:         case opc_ret:
653             out.writeByte(opc);
654             out.writeByte(((Number)value).intValue());
655             break;
656 
657           case opc_iload + 256:         case opc_lload + 256:
658           case opc_fload + 256:         case opc_dload + 256:
659           case opc_aload + 256:         case opc_ret   + 256:
660             out.writeByte(opc_wide);
661             out.writeByte(opc - 256);
662             out.writeShort(((Number)value).intValue());
663             break;
664 
665           case opc_istore:      case opc_lstore:        case opc_fstore:
666           case opc_dstore:      case opc_astore:
667             out.writeByte(opc);
668             out.writeByte((value instanceof Number) ?
669                           ((Number)value).intValue() : ((LocalVariable)value).slot);
670             break;
671 
672           case opc_istore + 256:        case opc_lstore + 256:
673           case opc_fstore + 256:        case opc_dstore + 256:
674           case opc_astore + 256:
675             out.writeByte(opc_wide);
676             out.writeByte(opc - 256);
677             out.writeShort((value instanceof Number) ?
678                       ((Number)value).intValue() : ((LocalVariable)value).slot);
679             break;
680 
681           case opc_sipush:
682             out.writeByte(opc);
683             out.writeShort(((Number)value).intValue());
684             break;
685 
686           case opc_ldc:
687             out.writeByte(opc);
688             out.writeByte(tab.index(value));
689             break;
690 
691           case opc_ldc_w:               case opc_ldc2_w:
692           case opc_new:                 case opc_putstatic:
693           case opc_getstatic:           case opc_putfield:
694           case opc_getfield:            case opc_invokevirtual:
695           case opc_invokespecial:       case opc_invokestatic:
696           case opc_instanceof:          case opc_checkcast:
697             out.writeByte(opc);
698             out.writeShort(tab.index(value));
699             break;
700 
701           case opc_iinc:
702             out.writeByte(opc);
703             out.writeByte(((int[])value)[0]); // register
704             out.writeByte(((int[])value)[1]); // increment
705             break;
706 
707           case opc_iinc + 256:
708             out.writeByte(opc_wide);
709             out.writeByte(opc - 256);
710             out.writeShort(((int[])value)[0]); // register
711             out.writeShort(((int[])value)[1]); // increment
712             break;
713 
714           case opc_anewarray:
715             out.writeByte(opc);
716             out.writeShort(tab.index(value));
717             break;
718 
719           case opc_multianewarray:
720             out.writeByte(opc);
721             out.writeShort(tab.index(((ArrayData)value).type));
722             out.writeByte(((ArrayData)value).nargs);
723             break;
724 
725           case opc_invokeinterface:
726             out.writeByte(opc);
727             out.writeShort(tab.index(value));
728             out.writeByte(((MemberDefinition)value).getType().stackSize() + 1);
729             out.writeByte(0);
730             break;
731 
732           case opc_goto:        case opc_jsr:           case opc_ifeq:
733           case opc_ifne:        case opc_ifgt:          case opc_ifge:
734           case opc_iflt:        case opc_ifle:          case opc_ifnull:
735           case opc_ifnonnull:   case opc_if_acmpeq:     case opc_if_acmpne:
736           case opc_if_icmpeq:   case opc_if_icmpne:     case opc_if_icmpgt:
737           case opc_if_icmpge:   case opc_if_icmplt:     case opc_if_icmple:
738             out.writeByte(opc);
739             out.writeShort(((Instruction)value).pc - pc);
740             break;
741 
742           case opc_goto_w:
743           case opc_jsr_w:
744             out.writeByte(opc);
745             out.writeLong(((Instruction)value).pc - pc);
746             break;
747 
748           case opc_tableswitch: {
749             SwitchData sw = (SwitchData)value;
750             out.writeByte(opc);
751             for(int n = 1 ; ((pc + n) % 4) != 0 ; n++) {
752                 out.writeByte(0);
753             }
754             out.writeInt(sw.defaultLabel.pc - pc);
755             out.writeInt(sw.minValue);
756             out.writeInt(sw.maxValue);
757             for (int n = sw.minValue ; n <= sw.maxValue ; n++) {
758                 Label lbl = sw.get(n);
759                 int target_pc = (lbl != null) ? lbl.pc : sw.defaultLabel.pc;
760                 out.writeInt(target_pc - pc);
761             }
762             break;
763           }
764 
765           case opc_lookupswitch: {
766             SwitchData sw = (SwitchData)value;
767             out.writeByte(opc);
768             int n = pc + 1;
769             for(; (n % 4) != 0 ; n++) {
770                 out.writeByte(0);
771             }
772             out.writeInt(sw.defaultLabel.pc - pc);
773             out.writeInt(sw.tab.size());
774             for (Enumeration<Integer> e = sw.sortedKeys(); e.hasMoreElements() ; ) {
775                 Integer v = e.nextElement();
776                 out.writeInt(v.intValue());
777                 out.writeInt(sw.get(v).pc - pc);
778             }
779             break;
780           }
781 
782           case opc_nop:
783             if (value != null) {
784                 if (value instanceof Integer)
785                     out.writeByte(((Integer)value).intValue());
786                 else
787                     out.writeShort(tab.index(value));
788                 return;
789             }
790             // fall through
791 
792           default:
793             out.writeByte(opc);
794             break;
795         }
796     }
797 
798     /**
799      * toString
800      */
toString()801     public String toString() {
802         String prefix = (where >> WHEREOFFSETBITS) + ":\t";
803         switch (opc) {
804           case opc_try:
805             return prefix + "try " + ((TryData)value).getEndLabel().hashCode();
806 
807           case opc_dead:
808             return prefix + "dead";
809 
810           case opc_iinc: {
811             int register = ((int[])value)[0];
812             int increment = ((int[])value)[1];
813             return prefix + opcNames[opc] + " " + register + ", " + increment;
814           }
815 
816           default:
817             if (value != null) {
818                 if (value instanceof Label) {
819                     return prefix + opcNames[opc] + " " + value.toString();
820                 } else if (value instanceof Instruction) {
821                     return prefix + opcNames[opc] + " " + value.hashCode();
822                 } else if (value instanceof String) {
823                     return prefix + opcNames[opc] + " \"" + value + "\"";
824                 } else {
825                     return prefix + opcNames[opc] + " " + value;
826                 }
827             } else {
828               return prefix + opcNames[opc];
829             }
830         }
831     }
832 }
833