History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/sun/tools/asm/Instruction.java (1 of 18352 files). Show all

Unified · Split

java/pkg/sun/tools/asm/Instruction.java+831−0
@@ -0,0 +1,831 @@
1+/*
2+ * Copyright (c) 1994, 2003, 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+ */
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+ */
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+ */
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+ */
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+ */
122+ public int getOpcode() {
123+ return pc;
124+ }
125+
126+ public Object getValue() {
127+ return value;
128+ }
129+
130+ public void setValue(Object value) {
131+ this.value = value;
132+ }
133+
134+
135+ /**
136+ * Optimize
137+ */
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 = new Integer(((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 e = sw.tab.keys() ; e.hasMoreElements() ; ) {
278+ Integer k = (Integer)e.nextElement();
279+ Label lbl = (Label)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+ */
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 e = ((TryData)value).catches.elements() ; e.hasMoreElements() ;) {
393+ CatchData cd = (CatchData)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+ */
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+ */
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+ void write(DataOutputStream out, ConstantPool tab) throws IOException {
645+ switch (opc) {
646+ case opc_try: case opc_label: case opc_dead:
647+ break;
648+
649+ case opc_bipush: case opc_newarray:
650+ case opc_iload: case opc_lload: case opc_fload:
651+ case opc_dload: case opc_aload: case opc_ret:
652+ out.writeByte(opc);
653+ out.writeByte(((Number)value).intValue());
654+ break;
655+
656+ case opc_iload + 256: case opc_lload + 256:
657+ case opc_fload + 256: case opc_dload + 256:
658+ case opc_aload + 256: case opc_ret + 256:
659+ out.writeByte(opc_wide);
660+ out.writeByte(opc - 256);
661+ out.writeShort(((Number)value).intValue());
662+ break;
663+
664+ case opc_istore: case opc_lstore: case opc_fstore:
665+ case opc_dstore: case opc_astore:
666+ out.writeByte(opc);
667+ out.writeByte((value instanceof Number) ?
668+ ((Number)value).intValue() : ((LocalVariable)value).slot);
669+ break;
670+
671+ case opc_istore + 256: case opc_lstore + 256:
672+ case opc_fstore + 256: case opc_dstore + 256:
673+ case opc_astore + 256:
674+ out.writeByte(opc_wide);
675+ out.writeByte(opc - 256);
676+ out.writeShort((value instanceof Number) ?
677+ ((Number)value).intValue() : ((LocalVariable)value).slot);
678+ break;
679+
680+ case opc_sipush:
681+ out.writeByte(opc);
682+ out.writeShort(((Number)value).intValue());
683+ break;
684+
685+ case opc_ldc:
686+ out.writeByte(opc);
687+ out.writeByte(tab.index(value));
688+ break;
689+
690+ case opc_ldc_w: case opc_ldc2_w:
691+ case opc_new: case opc_putstatic:
692+ case opc_getstatic: case opc_putfield:
693+ case opc_getfield: case opc_invokevirtual:
694+ case opc_invokespecial: case opc_invokestatic:
695+ case opc_instanceof: case opc_checkcast:
696+ out.writeByte(opc);
697+ out.writeShort(tab.index(value));
698+ break;
699+
700+ case opc_iinc:
701+ out.writeByte(opc);
702+ out.writeByte(((int[])value)[0]); // register
703+ out.writeByte(((int[])value)[1]); // increment
704+ break;
705+
706+ case opc_iinc + 256:
707+ out.writeByte(opc_wide);
708+ out.writeByte(opc - 256);
709+ out.writeShort(((int[])value)[0]); // register
710+ out.writeShort(((int[])value)[1]); // increment
711+ break;
712+
713+ case opc_anewarray:
714+ out.writeByte(opc);
715+ out.writeShort(tab.index(value));
716+ break;
717+
718+ case opc_multianewarray:
719+ out.writeByte(opc);
720+ out.writeShort(tab.index(((ArrayData)value).type));
721+ out.writeByte(((ArrayData)value).nargs);
722+ break;
723+
724+ case opc_invokeinterface:
725+ out.writeByte(opc);
726+ out.writeShort(tab.index(value));
727+ out.writeByte(((MemberDefinition)value).getType().stackSize() + 1);
728+ out.writeByte(0);
729+ break;
730+
731+ case opc_goto: case opc_jsr: case opc_ifeq:
732+ case opc_ifne: case opc_ifgt: case opc_ifge:
733+ case opc_iflt: case opc_ifle: case opc_ifnull:
734+ case opc_ifnonnull: case opc_if_acmpeq: case opc_if_acmpne:
735+ case opc_if_icmpeq: case opc_if_icmpne: case opc_if_icmpgt:
736+ case opc_if_icmpge: case opc_if_icmplt: case opc_if_icmple:
737+ out.writeByte(opc);
738+ out.writeShort(((Instruction)value).pc - pc);
739+ break;
740+
741+ case opc_goto_w:
742+ case opc_jsr_w:
743+ out.writeByte(opc);
744+ out.writeLong(((Instruction)value).pc - pc);
745+ break;
746+
747+ case opc_tableswitch: {
748+ SwitchData sw = (SwitchData)value;
749+ out.writeByte(opc);
750+ for(int n = 1 ; ((pc + n) % 4) != 0 ; n++) {
751+ out.writeByte(0);
752+ }
753+ out.writeInt(sw.defaultLabel.pc - pc);
754+ out.writeInt(sw.minValue);
755+ out.writeInt(sw.maxValue);
756+ for (int n = sw.minValue ; n <= sw.maxValue ; n++) {
757+ Label lbl = sw.get(n);
758+ int target_pc = (lbl != null) ? lbl.pc : sw.defaultLabel.pc;
759+ out.writeInt(target_pc - pc);
760+ }
761+ break;
762+ }
763+
764+ case opc_lookupswitch: {
765+ SwitchData sw = (SwitchData)value;
766+ out.writeByte(opc);
767+ int n = pc + 1;
768+ for(; (n % 4) != 0 ; n++) {
769+ out.writeByte(0);
770+ }
771+ out.writeInt(sw.defaultLabel.pc - pc);
772+ out.writeInt(sw.tab.size());
773+ for (Enumeration e = sw.sortedKeys(); e.hasMoreElements() ; ) {
774+ Integer v = (Integer)e.nextElement();
775+ out.writeInt(v.intValue());
776+ out.writeInt(sw.get(v).pc - pc);
777+ }
778+ break;
779+ }
780+
781+ case opc_nop:
782+ if (value != null) {
783+ if (value instanceof Integer)
784+ out.writeByte(((Integer)value).intValue());
785+ else
786+ out.writeShort(tab.index(value));
787+ return;
788+ }
789+ // fall through
790+
791+ default:
792+ out.writeByte(opc);
793+ break;
794+ }
795+ }
796+
797+ /**
798+ * toString
799+ */
800+ public String toString() {
801+ String prefix = (where >> WHEREOFFSETBITS) + ":\t";
802+ switch (opc) {
803+ case opc_try:
804+ return prefix + "try " + ((TryData)value).getEndLabel().hashCode();
805+
806+ case opc_dead:
807+ return prefix + "dead";
808+
809+ case opc_iinc: {
810+ int register = ((int[])value)[0];
811+ int increment = ((int[])value)[1];
812+ return prefix + opcNames[opc] + " " + register + ", " + increment;
813+ }
814+
815+ default:
816+ if (value != null) {
817+ if (value instanceof Label) {
818+ return prefix + opcNames[opc] + " " + value.toString();
819+ } else if (value instanceof Instruction) {
820+ return prefix + opcNames[opc] + " " + value.hashCode();
821+ } else if (value instanceof String) {
822+ return prefix + opcNames[opc] + " \"" + value + "\"";
823+ } else {
824+ return prefix + opcNames[opc] + " " + value;
825+ }
826+ } else {
827+ return prefix + opcNames[opc];
828+ }
829+ }
830+ }
831+}