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
26package sun.tools.asm;
27
28import sun.tools.java.*;
29import java.util.Enumeration;
30import java.io.IOException;
31import 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 */
40public
41class 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}