Wed, 27 Apr 2016 01:34:52 +0800
Initial load
http://hg.openjdk.java.net/jdk8u/jdk8u/langtools/
changeset: 2573:53ca196be1ae
tag: jdk8u25-b17
1 /*
2 * Copyright (c) 1999, 2014, 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 */
26 package com.sun.tools.javac.jvm;
28 import com.sun.tools.javac.code.*;
29 import com.sun.tools.javac.code.Symbol.*;
30 import com.sun.tools.javac.code.Types.UniqueType;
31 import com.sun.tools.javac.tree.JCTree;
32 import com.sun.tools.javac.util.*;
33 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
35 import static com.sun.tools.javac.code.TypeTag.BOT;
36 import static com.sun.tools.javac.code.TypeTag.INT;
37 import static com.sun.tools.javac.jvm.ByteCodes.*;
38 import static com.sun.tools.javac.jvm.UninitializedType.*;
39 import static com.sun.tools.javac.jvm.ClassWriter.StackMapTableFrame;
41 /** An internal structure that corresponds to the code attribute of
42 * methods in a classfile. The class also provides some utility operations to
43 * generate bytecode instructions.
44 *
45 * <p><b>This is NOT part of any supported API.
46 * If you write code that depends on this, you do so at your own risk.
47 * This code and its internal interfaces are subject to change or
48 * deletion without notice.</b>
49 */
50 public class Code {
52 public final boolean debugCode;
53 public final boolean needStackMap;
55 public enum StackMapFormat {
56 NONE,
57 CLDC {
58 Name getAttributeName(Names names) {
59 return names.StackMap;
60 }
61 },
62 JSR202 {
63 Name getAttributeName(Names names) {
64 return names.StackMapTable;
65 }
66 };
67 Name getAttributeName(Names names) {
68 return names.empty;
69 }
70 }
72 final Types types;
73 final Symtab syms;
75 /*---------- classfile fields: --------------- */
77 /** The maximum stack size.
78 */
79 public int max_stack = 0;
81 /** The maximum number of local variable slots.
82 */
83 public int max_locals = 0;
85 /** The code buffer.
86 */
87 public byte[] code = new byte[64];
89 /** the current code pointer.
90 */
91 public int cp = 0;
93 /** Check the code against VM spec limits; if
94 * problems report them and return true.
95 */
96 public boolean checkLimits(DiagnosticPosition pos, Log log) {
97 if (cp > ClassFile.MAX_CODE) {
98 log.error(pos, "limit.code");
99 return true;
100 }
101 if (max_locals > ClassFile.MAX_LOCALS) {
102 log.error(pos, "limit.locals");
103 return true;
104 }
105 if (max_stack > ClassFile.MAX_STACK) {
106 log.error(pos, "limit.stack");
107 return true;
108 }
109 return false;
110 }
112 /** A buffer for expression catch data. Each enter is a vector
113 * of four unsigned shorts.
114 */
115 ListBuffer<char[]> catchInfo = new ListBuffer<char[]>();
117 /** A buffer for line number information. Each entry is a vector
118 * of two unsigned shorts.
119 */
120 List<char[]> lineInfo = List.nil(); // handled in stack fashion
122 /** The CharacterRangeTable
123 */
124 public CRTable crt;
126 /*---------- internal fields: --------------- */
128 /** Are we generating code with jumps ≥ 32K?
129 */
130 public boolean fatcode;
132 /** Code generation enabled?
133 */
134 private boolean alive = true;
136 /** The current machine state (registers and stack).
137 */
138 State state;
140 /** Is it forbidden to compactify code, because something is
141 * pointing to current location?
142 */
143 private boolean fixedPc = false;
145 /** The next available register.
146 */
147 public int nextreg = 0;
149 /** A chain for jumps to be resolved before the next opcode is emitted.
150 * We do this lazily to avoid jumps to jumps.
151 */
152 Chain pendingJumps = null;
154 /** The position of the currently statement, if we are at the
155 * start of this statement, NOPOS otherwise.
156 * We need this to emit line numbers lazily, which we need to do
157 * because of jump-to-jump optimization.
158 */
159 int pendingStatPos = Position.NOPOS;
161 /** Set true when a stackMap is needed at the current PC. */
162 boolean pendingStackMap = false;
164 /** The stack map format to be generated. */
165 StackMapFormat stackMap;
167 /** Switch: emit variable debug info.
168 */
169 boolean varDebugInfo;
171 /** Switch: emit line number info.
172 */
173 boolean lineDebugInfo;
175 /** Emit line number info if map supplied
176 */
177 Position.LineMap lineMap;
179 /** The constant pool of the current class.
180 */
181 final Pool pool;
183 final MethodSymbol meth;
185 final LVTRanges lvtRanges;
187 /** Construct a code object, given the settings of the fatcode,
188 * debugging info switches and the CharacterRangeTable.
189 */
190 public Code(MethodSymbol meth,
191 boolean fatcode,
192 Position.LineMap lineMap,
193 boolean varDebugInfo,
194 StackMapFormat stackMap,
195 boolean debugCode,
196 CRTable crt,
197 Symtab syms,
198 Types types,
199 Pool pool,
200 LVTRanges lvtRanges) {
201 this.meth = meth;
202 this.fatcode = fatcode;
203 this.lineMap = lineMap;
204 this.lineDebugInfo = lineMap != null;
205 this.varDebugInfo = varDebugInfo;
206 this.crt = crt;
207 this.syms = syms;
208 this.types = types;
209 this.debugCode = debugCode;
210 this.stackMap = stackMap;
211 switch (stackMap) {
212 case CLDC:
213 case JSR202:
214 this.needStackMap = true;
215 break;
216 default:
217 this.needStackMap = false;
218 }
219 state = new State();
220 lvar = new LocalVar[20];
221 this.pool = pool;
222 this.lvtRanges = lvtRanges;
223 }
226 /* **************************************************************************
227 * Typecodes & related stuff
228 ****************************************************************************/
230 /** Given a type, return its type code (used implicitly in the
231 * JVM architecture).
232 */
233 public static int typecode(Type type) {
234 switch (type.getTag()) {
235 case BYTE: return BYTEcode;
236 case SHORT: return SHORTcode;
237 case CHAR: return CHARcode;
238 case INT: return INTcode;
239 case LONG: return LONGcode;
240 case FLOAT: return FLOATcode;
241 case DOUBLE: return DOUBLEcode;
242 case BOOLEAN: return BYTEcode;
243 case VOID: return VOIDcode;
244 case CLASS:
245 case ARRAY:
246 case METHOD:
247 case BOT:
248 case TYPEVAR:
249 case UNINITIALIZED_THIS:
250 case UNINITIALIZED_OBJECT:
251 return OBJECTcode;
252 default: throw new AssertionError("typecode " + type.getTag());
253 }
254 }
256 /** Collapse type code for subtypes of int to INTcode.
257 */
258 public static int truncate(int tc) {
259 switch (tc) {
260 case BYTEcode: case SHORTcode: case CHARcode: return INTcode;
261 default: return tc;
262 }
263 }
265 /** The width in bytes of objects of the type.
266 */
267 public static int width(int typecode) {
268 switch (typecode) {
269 case LONGcode: case DOUBLEcode: return 2;
270 case VOIDcode: return 0;
271 default: return 1;
272 }
273 }
275 public static int width(Type type) {
276 return type == null ? 1 : width(typecode(type));
277 }
279 /** The total width taken up by a vector of objects.
280 */
281 public static int width(List<Type> types) {
282 int w = 0;
283 for (List<Type> l = types; l.nonEmpty(); l = l.tail)
284 w = w + width(l.head);
285 return w;
286 }
288 /** Given a type, return its code for allocating arrays of that type.
289 */
290 public static int arraycode(Type type) {
291 switch (type.getTag()) {
292 case BYTE: return 8;
293 case BOOLEAN: return 4;
294 case SHORT: return 9;
295 case CHAR: return 5;
296 case INT: return 10;
297 case LONG: return 11;
298 case FLOAT: return 6;
299 case DOUBLE: return 7;
300 case CLASS: return 0;
301 case ARRAY: return 1;
302 default: throw new AssertionError("arraycode " + type);
303 }
304 }
307 /* **************************************************************************
308 * Emit code
309 ****************************************************************************/
311 /** The current output code pointer.
312 */
313 public int curCP() {
314 /*
315 * This method has side-effects because calling it can indirectly provoke
316 * extra code generation, like goto instructions, depending on the context
317 * where it's called.
318 * Use with care or even better avoid using it.
319 */
320 if (pendingJumps != null) {
321 resolvePending();
322 }
323 if (pendingStatPos != Position.NOPOS) {
324 markStatBegin();
325 }
326 fixedPc = true;
327 return cp;
328 }
330 /** Emit a byte of code.
331 */
332 private void emit1(int od) {
333 if (!alive) return;
334 code = ArrayUtils.ensureCapacity(code, cp);
335 code[cp++] = (byte)od;
336 }
338 /** Emit two bytes of code.
339 */
340 private void emit2(int od) {
341 if (!alive) return;
342 if (cp + 2 > code.length) {
343 emit1(od >> 8);
344 emit1(od);
345 } else {
346 code[cp++] = (byte)(od >> 8);
347 code[cp++] = (byte)od;
348 }
349 }
351 /** Emit four bytes of code.
352 */
353 public void emit4(int od) {
354 if (!alive) return;
355 if (cp + 4 > code.length) {
356 emit1(od >> 24);
357 emit1(od >> 16);
358 emit1(od >> 8);
359 emit1(od);
360 } else {
361 code[cp++] = (byte)(od >> 24);
362 code[cp++] = (byte)(od >> 16);
363 code[cp++] = (byte)(od >> 8);
364 code[cp++] = (byte)od;
365 }
366 }
368 /** Emit an opcode.
369 */
370 private void emitop(int op) {
371 if (pendingJumps != null) resolvePending();
372 if (alive) {
373 if (pendingStatPos != Position.NOPOS)
374 markStatBegin();
375 if (pendingStackMap) {
376 pendingStackMap = false;
377 emitStackMap();
378 }
379 if (debugCode)
380 System.err.println("emit@" + cp + " stack=" +
381 state.stacksize + ": " +
382 mnem(op));
383 emit1(op);
384 }
385 }
387 void postop() {
388 Assert.check(alive || state.stacksize == 0);
389 }
391 /** Emit a ldc (or ldc_w) instruction, taking into account operand size
392 */
393 public void emitLdc(int od) {
394 if (od <= 255) {
395 emitop1(ldc1, od);
396 }
397 else {
398 emitop2(ldc2, od);
399 }
400 }
402 /** Emit a multinewarray instruction.
403 */
404 public void emitMultianewarray(int ndims, int type, Type arrayType) {
405 emitop(multianewarray);
406 if (!alive) return;
407 emit2(type);
408 emit1(ndims);
409 state.pop(ndims);
410 state.push(arrayType);
411 }
413 /** Emit newarray.
414 */
415 public void emitNewarray(int elemcode, Type arrayType) {
416 emitop(newarray);
417 if (!alive) return;
418 emit1(elemcode);
419 state.pop(1); // count
420 state.push(arrayType);
421 }
423 /** Emit anewarray.
424 */
425 public void emitAnewarray(int od, Type arrayType) {
426 emitop(anewarray);
427 if (!alive) return;
428 emit2(od);
429 state.pop(1);
430 state.push(arrayType);
431 }
433 /** Emit an invokeinterface instruction.
434 */
435 public void emitInvokeinterface(int meth, Type mtype) {
436 int argsize = width(mtype.getParameterTypes());
437 emitop(invokeinterface);
438 if (!alive) return;
439 emit2(meth);
440 emit1(argsize + 1);
441 emit1(0);
442 state.pop(argsize + 1);
443 state.push(mtype.getReturnType());
444 }
446 /** Emit an invokespecial instruction.
447 */
448 public void emitInvokespecial(int meth, Type mtype) {
449 int argsize = width(mtype.getParameterTypes());
450 emitop(invokespecial);
451 if (!alive) return;
452 emit2(meth);
453 Symbol sym = (Symbol)pool.pool[meth];
454 state.pop(argsize);
455 if (sym.isConstructor())
456 state.markInitialized((UninitializedType)state.peek());
457 state.pop(1);
458 state.push(mtype.getReturnType());
459 }
461 /** Emit an invokestatic instruction.
462 */
463 public void emitInvokestatic(int meth, Type mtype) {
464 int argsize = width(mtype.getParameterTypes());
465 emitop(invokestatic);
466 if (!alive) return;
467 emit2(meth);
468 state.pop(argsize);
469 state.push(mtype.getReturnType());
470 }
472 /** Emit an invokevirtual instruction.
473 */
474 public void emitInvokevirtual(int meth, Type mtype) {
475 int argsize = width(mtype.getParameterTypes());
476 emitop(invokevirtual);
477 if (!alive) return;
478 emit2(meth);
479 state.pop(argsize + 1);
480 state.push(mtype.getReturnType());
481 }
483 /** Emit an invokedynamic instruction.
484 */
485 public void emitInvokedynamic(int desc, Type mtype) {
486 int argsize = width(mtype.getParameterTypes());
487 emitop(invokedynamic);
488 if (!alive) return;
489 emit2(desc);
490 emit2(0);
491 state.pop(argsize);
492 state.push(mtype.getReturnType());
493 }
495 /** Emit an opcode with no operand field.
496 */
497 public void emitop0(int op) {
498 emitop(op);
499 if (!alive) return;
500 switch (op) {
501 case aaload: {
502 state.pop(1);// index
503 Type a = state.stack[state.stacksize-1];
504 state.pop(1);
505 //sometimes 'null type' is treated as a one-dimensional array type
506 //see Gen.visitLiteral - we should handle this case accordingly
507 Type stackType = a.hasTag(BOT) ?
508 syms.objectType :
509 types.erasure(types.elemtype(a));
510 state.push(stackType); }
511 break;
512 case goto_:
513 markDead();
514 break;
515 case nop:
516 case ineg:
517 case lneg:
518 case fneg:
519 case dneg:
520 break;
521 case aconst_null:
522 state.push(syms.botType);
523 break;
524 case iconst_m1:
525 case iconst_0:
526 case iconst_1:
527 case iconst_2:
528 case iconst_3:
529 case iconst_4:
530 case iconst_5:
531 case iload_0:
532 case iload_1:
533 case iload_2:
534 case iload_3:
535 state.push(syms.intType);
536 break;
537 case lconst_0:
538 case lconst_1:
539 case lload_0:
540 case lload_1:
541 case lload_2:
542 case lload_3:
543 state.push(syms.longType);
544 break;
545 case fconst_0:
546 case fconst_1:
547 case fconst_2:
548 case fload_0:
549 case fload_1:
550 case fload_2:
551 case fload_3:
552 state.push(syms.floatType);
553 break;
554 case dconst_0:
555 case dconst_1:
556 case dload_0:
557 case dload_1:
558 case dload_2:
559 case dload_3:
560 state.push(syms.doubleType);
561 break;
562 case aload_0:
563 state.push(lvar[0].sym.type);
564 break;
565 case aload_1:
566 state.push(lvar[1].sym.type);
567 break;
568 case aload_2:
569 state.push(lvar[2].sym.type);
570 break;
571 case aload_3:
572 state.push(lvar[3].sym.type);
573 break;
574 case iaload:
575 case baload:
576 case caload:
577 case saload:
578 state.pop(2);
579 state.push(syms.intType);
580 break;
581 case laload:
582 state.pop(2);
583 state.push(syms.longType);
584 break;
585 case faload:
586 state.pop(2);
587 state.push(syms.floatType);
588 break;
589 case daload:
590 state.pop(2);
591 state.push(syms.doubleType);
592 break;
593 case istore_0:
594 case istore_1:
595 case istore_2:
596 case istore_3:
597 case fstore_0:
598 case fstore_1:
599 case fstore_2:
600 case fstore_3:
601 case astore_0:
602 case astore_1:
603 case astore_2:
604 case astore_3:
605 case pop:
606 case lshr:
607 case lshl:
608 case lushr:
609 state.pop(1);
610 break;
611 case areturn:
612 case ireturn:
613 case freturn:
614 Assert.check(state.nlocks == 0);
615 state.pop(1);
616 markDead();
617 break;
618 case athrow:
619 state.pop(1);
620 markDead();
621 break;
622 case lstore_0:
623 case lstore_1:
624 case lstore_2:
625 case lstore_3:
626 case dstore_0:
627 case dstore_1:
628 case dstore_2:
629 case dstore_3:
630 case pop2:
631 state.pop(2);
632 break;
633 case lreturn:
634 case dreturn:
635 Assert.check(state.nlocks == 0);
636 state.pop(2);
637 markDead();
638 break;
639 case dup:
640 state.push(state.stack[state.stacksize-1]);
641 break;
642 case return_:
643 Assert.check(state.nlocks == 0);
644 markDead();
645 break;
646 case arraylength:
647 state.pop(1);
648 state.push(syms.intType);
649 break;
650 case isub:
651 case iadd:
652 case imul:
653 case idiv:
654 case imod:
655 case ishl:
656 case ishr:
657 case iushr:
658 case iand:
659 case ior:
660 case ixor:
661 state.pop(1);
662 // state.pop(1);
663 // state.push(syms.intType);
664 break;
665 case aastore:
666 state.pop(3);
667 break;
668 case land:
669 case lor:
670 case lxor:
671 case lmod:
672 case ldiv:
673 case lmul:
674 case lsub:
675 case ladd:
676 state.pop(2);
677 break;
678 case lcmp:
679 state.pop(4);
680 state.push(syms.intType);
681 break;
682 case l2i:
683 state.pop(2);
684 state.push(syms.intType);
685 break;
686 case i2l:
687 state.pop(1);
688 state.push(syms.longType);
689 break;
690 case i2f:
691 state.pop(1);
692 state.push(syms.floatType);
693 break;
694 case i2d:
695 state.pop(1);
696 state.push(syms.doubleType);
697 break;
698 case l2f:
699 state.pop(2);
700 state.push(syms.floatType);
701 break;
702 case l2d:
703 state.pop(2);
704 state.push(syms.doubleType);
705 break;
706 case f2i:
707 state.pop(1);
708 state.push(syms.intType);
709 break;
710 case f2l:
711 state.pop(1);
712 state.push(syms.longType);
713 break;
714 case f2d:
715 state.pop(1);
716 state.push(syms.doubleType);
717 break;
718 case d2i:
719 state.pop(2);
720 state.push(syms.intType);
721 break;
722 case d2l:
723 state.pop(2);
724 state.push(syms.longType);
725 break;
726 case d2f:
727 state.pop(2);
728 state.push(syms.floatType);
729 break;
730 case tableswitch:
731 case lookupswitch:
732 state.pop(1);
733 // the caller is responsible for patching up the state
734 break;
735 case dup_x1: {
736 Type val1 = state.pop1();
737 Type val2 = state.pop1();
738 state.push(val1);
739 state.push(val2);
740 state.push(val1);
741 break;
742 }
743 case bastore:
744 state.pop(3);
745 break;
746 case int2byte:
747 case int2char:
748 case int2short:
749 break;
750 case fmul:
751 case fadd:
752 case fsub:
753 case fdiv:
754 case fmod:
755 state.pop(1);
756 break;
757 case castore:
758 case iastore:
759 case fastore:
760 case sastore:
761 state.pop(3);
762 break;
763 case lastore:
764 case dastore:
765 state.pop(4);
766 break;
767 case dup2:
768 if (state.stack[state.stacksize-1] != null) {
769 Type value1 = state.pop1();
770 Type value2 = state.pop1();
771 state.push(value2);
772 state.push(value1);
773 state.push(value2);
774 state.push(value1);
775 } else {
776 Type value = state.pop2();
777 state.push(value);
778 state.push(value);
779 }
780 break;
781 case dup2_x1:
782 if (state.stack[state.stacksize-1] != null) {
783 Type value1 = state.pop1();
784 Type value2 = state.pop1();
785 Type value3 = state.pop1();
786 state.push(value2);
787 state.push(value1);
788 state.push(value3);
789 state.push(value2);
790 state.push(value1);
791 } else {
792 Type value1 = state.pop2();
793 Type value2 = state.pop1();
794 state.push(value1);
795 state.push(value2);
796 state.push(value1);
797 }
798 break;
799 case dup2_x2:
800 if (state.stack[state.stacksize-1] != null) {
801 Type value1 = state.pop1();
802 Type value2 = state.pop1();
803 if (state.stack[state.stacksize-1] != null) {
804 // form 1
805 Type value3 = state.pop1();
806 Type value4 = state.pop1();
807 state.push(value2);
808 state.push(value1);
809 state.push(value4);
810 state.push(value3);
811 state.push(value2);
812 state.push(value1);
813 } else {
814 // form 3
815 Type value3 = state.pop2();
816 state.push(value2);
817 state.push(value1);
818 state.push(value3);
819 state.push(value2);
820 state.push(value1);
821 }
822 } else {
823 Type value1 = state.pop2();
824 if (state.stack[state.stacksize-1] != null) {
825 // form 2
826 Type value2 = state.pop1();
827 Type value3 = state.pop1();
828 state.push(value1);
829 state.push(value3);
830 state.push(value2);
831 state.push(value1);
832 } else {
833 // form 4
834 Type value2 = state.pop2();
835 state.push(value1);
836 state.push(value2);
837 state.push(value1);
838 }
839 }
840 break;
841 case dup_x2: {
842 Type value1 = state.pop1();
843 if (state.stack[state.stacksize-1] != null) {
844 // form 1
845 Type value2 = state.pop1();
846 Type value3 = state.pop1();
847 state.push(value1);
848 state.push(value3);
849 state.push(value2);
850 state.push(value1);
851 } else {
852 // form 2
853 Type value2 = state.pop2();
854 state.push(value1);
855 state.push(value2);
856 state.push(value1);
857 }
858 }
859 break;
860 case fcmpl:
861 case fcmpg:
862 state.pop(2);
863 state.push(syms.intType);
864 break;
865 case dcmpl:
866 case dcmpg:
867 state.pop(4);
868 state.push(syms.intType);
869 break;
870 case swap: {
871 Type value1 = state.pop1();
872 Type value2 = state.pop1();
873 state.push(value1);
874 state.push(value2);
875 break;
876 }
877 case dadd:
878 case dsub:
879 case dmul:
880 case ddiv:
881 case dmod:
882 state.pop(2);
883 break;
884 case ret:
885 markDead();
886 break;
887 case wide:
888 // must be handled by the caller.
889 return;
890 case monitorenter:
891 case monitorexit:
892 state.pop(1);
893 break;
895 default:
896 throw new AssertionError(mnem(op));
897 }
898 postop();
899 }
901 /** Emit an opcode with a one-byte operand field.
902 */
903 public void emitop1(int op, int od) {
904 emitop(op);
905 if (!alive) return;
906 emit1(od);
907 switch (op) {
908 case bipush:
909 state.push(syms.intType);
910 break;
911 case ldc1:
912 state.push(typeForPool(pool.pool[od]));
913 break;
914 default:
915 throw new AssertionError(mnem(op));
916 }
917 postop();
918 }
920 /** The type of a constant pool entry. */
921 private Type typeForPool(Object o) {
922 if (o instanceof Integer) return syms.intType;
923 if (o instanceof Float) return syms.floatType;
924 if (o instanceof String) return syms.stringType;
925 if (o instanceof Long) return syms.longType;
926 if (o instanceof Double) return syms.doubleType;
927 if (o instanceof ClassSymbol) return syms.classType;
928 if (o instanceof Pool.MethodHandle) return syms.methodHandleType;
929 if (o instanceof UniqueType) return typeForPool(((UniqueType)o).type);
930 if (o instanceof Type) {
931 Type ty = ((Type)o).unannotatedType();
933 if (ty instanceof Type.ArrayType) return syms.classType;
934 if (ty instanceof Type.MethodType) return syms.methodTypeType;
935 }
936 throw new AssertionError("Invalid type of constant pool entry: " + o.getClass());
937 }
939 /** Emit an opcode with a one-byte operand field;
940 * widen if field does not fit in a byte.
941 */
942 public void emitop1w(int op, int od) {
943 if (od > 0xFF) {
944 emitop(wide);
945 emitop(op);
946 emit2(od);
947 } else {
948 emitop(op);
949 emit1(od);
950 }
951 if (!alive) return;
952 switch (op) {
953 case iload:
954 state.push(syms.intType);
955 break;
956 case lload:
957 state.push(syms.longType);
958 break;
959 case fload:
960 state.push(syms.floatType);
961 break;
962 case dload:
963 state.push(syms.doubleType);
964 break;
965 case aload:
966 state.push(lvar[od].sym.type);
967 break;
968 case lstore:
969 case dstore:
970 state.pop(2);
971 break;
972 case istore:
973 case fstore:
974 case astore:
975 state.pop(1);
976 break;
977 case ret:
978 markDead();
979 break;
980 default:
981 throw new AssertionError(mnem(op));
982 }
983 postop();
984 }
986 /** Emit an opcode with two one-byte operand fields;
987 * widen if either field does not fit in a byte.
988 */
989 public void emitop1w(int op, int od1, int od2) {
990 if (od1 > 0xFF || od2 < -128 || od2 > 127) {
991 emitop(wide);
992 emitop(op);
993 emit2(od1);
994 emit2(od2);
995 } else {
996 emitop(op);
997 emit1(od1);
998 emit1(od2);
999 }
1000 if (!alive) return;
1001 switch (op) {
1002 case iinc:
1003 break;
1004 default:
1005 throw new AssertionError(mnem(op));
1006 }
1007 }
1009 /** Emit an opcode with a two-byte operand field.
1010 */
1011 public void emitop2(int op, int od) {
1012 emitop(op);
1013 if (!alive) return;
1014 emit2(od);
1015 switch (op) {
1016 case getstatic:
1017 state.push(((Symbol)(pool.pool[od])).erasure(types));
1018 break;
1019 case putstatic:
1020 state.pop(((Symbol)(pool.pool[od])).erasure(types));
1021 break;
1022 case new_:
1023 Symbol sym;
1024 if (pool.pool[od] instanceof UniqueType) {
1025 // Required by change in Gen.makeRef to allow
1026 // annotated types.
1027 // TODO: is this needed anywhere else?
1028 sym = ((UniqueType)(pool.pool[od])).type.tsym;
1029 } else {
1030 sym = (Symbol)(pool.pool[od]);
1031 }
1032 state.push(uninitializedObject(sym.erasure(types), cp-3));
1033 break;
1034 case sipush:
1035 state.push(syms.intType);
1036 break;
1037 case if_acmp_null:
1038 case if_acmp_nonnull:
1039 case ifeq:
1040 case ifne:
1041 case iflt:
1042 case ifge:
1043 case ifgt:
1044 case ifle:
1045 state.pop(1);
1046 break;
1047 case if_icmpeq:
1048 case if_icmpne:
1049 case if_icmplt:
1050 case if_icmpge:
1051 case if_icmpgt:
1052 case if_icmple:
1053 case if_acmpeq:
1054 case if_acmpne:
1055 state.pop(2);
1056 break;
1057 case goto_:
1058 markDead();
1059 break;
1060 case putfield:
1061 state.pop(((Symbol)(pool.pool[od])).erasure(types));
1062 state.pop(1); // object ref
1063 break;
1064 case getfield:
1065 state.pop(1); // object ref
1066 state.push(((Symbol)(pool.pool[od])).erasure(types));
1067 break;
1068 case checkcast: {
1069 state.pop(1); // object ref
1070 Object o = pool.pool[od];
1071 Type t = (o instanceof Symbol)
1072 ? ((Symbol)o).erasure(types)
1073 : types.erasure((((UniqueType)o).type));
1074 state.push(t);
1075 break; }
1076 case ldc2w:
1077 state.push(typeForPool(pool.pool[od]));
1078 break;
1079 case instanceof_:
1080 state.pop(1);
1081 state.push(syms.intType);
1082 break;
1083 case ldc2:
1084 state.push(typeForPool(pool.pool[od]));
1085 break;
1086 case jsr:
1087 break;
1088 default:
1089 throw new AssertionError(mnem(op));
1090 }
1091 // postop();
1092 }
1094 /** Emit an opcode with a four-byte operand field.
1095 */
1096 public void emitop4(int op, int od) {
1097 emitop(op);
1098 if (!alive) return;
1099 emit4(od);
1100 switch (op) {
1101 case goto_w:
1102 markDead();
1103 break;
1104 case jsr_w:
1105 break;
1106 default:
1107 throw new AssertionError(mnem(op));
1108 }
1109 // postop();
1110 }
1112 /** Align code pointer to next `incr' boundary.
1113 */
1114 public void align(int incr) {
1115 if (alive)
1116 while (cp % incr != 0) emitop0(nop);
1117 }
1119 /** Place a byte into code at address pc.
1120 * Pre: {@literal pc + 1 <= cp }.
1121 */
1122 private void put1(int pc, int op) {
1123 code[pc] = (byte)op;
1124 }
1126 /** Place two bytes into code at address pc.
1127 * Pre: {@literal pc + 2 <= cp }.
1128 */
1129 private void put2(int pc, int od) {
1130 // pre: pc + 2 <= cp
1131 put1(pc, od >> 8);
1132 put1(pc+1, od);
1133 }
1135 /** Place four bytes into code at address pc.
1136 * Pre: {@literal pc + 4 <= cp }.
1137 */
1138 public void put4(int pc, int od) {
1139 // pre: pc + 4 <= cp
1140 put1(pc , od >> 24);
1141 put1(pc+1, od >> 16);
1142 put1(pc+2, od >> 8);
1143 put1(pc+3, od);
1144 }
1146 /** Return code byte at position pc as an unsigned int.
1147 */
1148 private int get1(int pc) {
1149 return code[pc] & 0xFF;
1150 }
1152 /** Return two code bytes at position pc as an unsigned int.
1153 */
1154 private int get2(int pc) {
1155 return (get1(pc) << 8) | get1(pc+1);
1156 }
1158 /** Return four code bytes at position pc as an int.
1159 */
1160 public int get4(int pc) {
1161 // pre: pc + 4 <= cp
1162 return
1163 (get1(pc) << 24) |
1164 (get1(pc+1) << 16) |
1165 (get1(pc+2) << 8) |
1166 (get1(pc+3));
1167 }
1169 /** Is code generation currently enabled?
1170 */
1171 public boolean isAlive() {
1172 return alive || pendingJumps != null;
1173 }
1175 /** Switch code generation on/off.
1176 */
1177 public void markDead() {
1178 alive = false;
1179 }
1181 /** Declare an entry point; return current code pointer
1182 */
1183 public int entryPoint() {
1184 int pc = curCP();
1185 alive = true;
1186 pendingStackMap = needStackMap;
1187 return pc;
1188 }
1190 /** Declare an entry point with initial state;
1191 * return current code pointer
1192 */
1193 public int entryPoint(State state) {
1194 int pc = curCP();
1195 alive = true;
1196 this.state = state.dup();
1197 Assert.check(state.stacksize <= max_stack);
1198 if (debugCode) System.err.println("entry point " + state);
1199 pendingStackMap = needStackMap;
1200 return pc;
1201 }
1203 /** Declare an entry point with initial state plus a pushed value;
1204 * return current code pointer
1205 */
1206 public int entryPoint(State state, Type pushed) {
1207 int pc = curCP();
1208 alive = true;
1209 this.state = state.dup();
1210 Assert.check(state.stacksize <= max_stack);
1211 this.state.push(pushed);
1212 if (debugCode) System.err.println("entry point " + state);
1213 pendingStackMap = needStackMap;
1214 return pc;
1215 }
1218 /**************************************************************************
1219 * Stack map generation
1220 *************************************************************************/
1222 /** An entry in the stack map. */
1223 static class StackMapFrame {
1224 int pc;
1225 Type[] locals;
1226 Type[] stack;
1227 }
1229 /** A buffer of cldc stack map entries. */
1230 StackMapFrame[] stackMapBuffer = null;
1232 /** A buffer of compressed StackMapTable entries. */
1233 StackMapTableFrame[] stackMapTableBuffer = null;
1234 int stackMapBufferSize = 0;
1236 /** The last PC at which we generated a stack map. */
1237 int lastStackMapPC = -1;
1239 /** The last stack map frame in StackMapTable. */
1240 StackMapFrame lastFrame = null;
1242 /** The stack map frame before the last one. */
1243 StackMapFrame frameBeforeLast = null;
1245 /** Emit a stack map entry. */
1246 public void emitStackMap() {
1247 int pc = curCP();
1248 if (!needStackMap) return;
1252 switch (stackMap) {
1253 case CLDC:
1254 emitCLDCStackMap(pc, getLocalsSize());
1255 break;
1256 case JSR202:
1257 emitStackMapFrame(pc, getLocalsSize());
1258 break;
1259 default:
1260 throw new AssertionError("Should have chosen a stackmap format");
1261 }
1262 // DEBUG code follows
1263 if (debugCode) state.dump(pc);
1264 }
1266 private int getLocalsSize() {
1267 int nextLocal = 0;
1268 for (int i=max_locals-1; i>=0; i--) {
1269 if (state.defined.isMember(i) && lvar[i] != null) {
1270 nextLocal = i + width(lvar[i].sym.erasure(types));
1271 break;
1272 }
1273 }
1274 return nextLocal;
1275 }
1277 /** Emit a CLDC stack map frame. */
1278 void emitCLDCStackMap(int pc, int localsSize) {
1279 if (lastStackMapPC == pc) {
1280 // drop existing stackmap at this offset
1281 stackMapBuffer[--stackMapBufferSize] = null;
1282 }
1283 lastStackMapPC = pc;
1285 if (stackMapBuffer == null) {
1286 stackMapBuffer = new StackMapFrame[20];
1287 } else {
1288 stackMapBuffer = ArrayUtils.ensureCapacity(stackMapBuffer, stackMapBufferSize);
1289 }
1290 StackMapFrame frame =
1291 stackMapBuffer[stackMapBufferSize++] = new StackMapFrame();
1292 frame.pc = pc;
1294 frame.locals = new Type[localsSize];
1295 for (int i=0; i<localsSize; i++) {
1296 if (state.defined.isMember(i) && lvar[i] != null) {
1297 Type vtype = lvar[i].sym.type;
1298 if (!(vtype instanceof UninitializedType))
1299 vtype = types.erasure(vtype);
1300 frame.locals[i] = vtype;
1301 }
1302 }
1303 frame.stack = new Type[state.stacksize];
1304 for (int i=0; i<state.stacksize; i++)
1305 frame.stack[i] = state.stack[i];
1306 }
1308 void emitStackMapFrame(int pc, int localsSize) {
1309 if (lastFrame == null) {
1310 // first frame
1311 lastFrame = getInitialFrame();
1312 } else if (lastFrame.pc == pc) {
1313 // drop existing stackmap at this offset
1314 stackMapTableBuffer[--stackMapBufferSize] = null;
1315 lastFrame = frameBeforeLast;
1316 frameBeforeLast = null;
1317 }
1319 StackMapFrame frame = new StackMapFrame();
1320 frame.pc = pc;
1322 int localCount = 0;
1323 Type[] locals = new Type[localsSize];
1324 for (int i=0; i<localsSize; i++, localCount++) {
1325 if (state.defined.isMember(i) && lvar[i] != null) {
1326 Type vtype = lvar[i].sym.type;
1327 if (!(vtype instanceof UninitializedType))
1328 vtype = types.erasure(vtype);
1329 locals[i] = vtype;
1330 if (width(vtype) > 1) i++;
1331 }
1332 }
1333 frame.locals = new Type[localCount];
1334 for (int i=0, j=0; i<localsSize; i++, j++) {
1335 Assert.check(j < localCount);
1336 frame.locals[j] = locals[i];
1337 if (width(locals[i]) > 1) i++;
1338 }
1340 int stackCount = 0;
1341 for (int i=0; i<state.stacksize; i++) {
1342 if (state.stack[i] != null) {
1343 stackCount++;
1344 }
1345 }
1346 frame.stack = new Type[stackCount];
1347 stackCount = 0;
1348 for (int i=0; i<state.stacksize; i++) {
1349 if (state.stack[i] != null) {
1350 frame.stack[stackCount++] = types.erasure(state.stack[i]);
1351 }
1352 }
1354 if (stackMapTableBuffer == null) {
1355 stackMapTableBuffer = new StackMapTableFrame[20];
1356 } else {
1357 stackMapTableBuffer = ArrayUtils.ensureCapacity(
1358 stackMapTableBuffer,
1359 stackMapBufferSize);
1360 }
1361 stackMapTableBuffer[stackMapBufferSize++] =
1362 StackMapTableFrame.getInstance(frame, lastFrame.pc, lastFrame.locals, types);
1364 frameBeforeLast = lastFrame;
1365 lastFrame = frame;
1366 }
1368 StackMapFrame getInitialFrame() {
1369 StackMapFrame frame = new StackMapFrame();
1370 List<Type> arg_types = ((MethodType)meth.externalType(types)).argtypes;
1371 int len = arg_types.length();
1372 int count = 0;
1373 if (!meth.isStatic()) {
1374 Type thisType = meth.owner.type;
1375 frame.locals = new Type[len+1];
1376 if (meth.isConstructor() && thisType != syms.objectType) {
1377 frame.locals[count++] = UninitializedType.uninitializedThis(thisType);
1378 } else {
1379 frame.locals[count++] = types.erasure(thisType);
1380 }
1381 } else {
1382 frame.locals = new Type[len];
1383 }
1384 for (Type arg_type : arg_types) {
1385 frame.locals[count++] = types.erasure(arg_type);
1386 }
1387 frame.pc = -1;
1388 frame.stack = null;
1389 return frame;
1390 }
1393 /**************************************************************************
1394 * Operations having to do with jumps
1395 *************************************************************************/
1397 /** A chain represents a list of unresolved jumps. Jump locations
1398 * are sorted in decreasing order.
1399 */
1400 public static class Chain {
1402 /** The position of the jump instruction.
1403 */
1404 public final int pc;
1406 /** The machine state after the jump instruction.
1407 * Invariant: all elements of a chain list have the same stacksize
1408 * and compatible stack and register contents.
1409 */
1410 Code.State state;
1412 /** The next jump in the list.
1413 */
1414 public final Chain next;
1416 /** Construct a chain from its jump position, stacksize, previous
1417 * chain, and machine state.
1418 */
1419 public Chain(int pc, Chain next, Code.State state) {
1420 this.pc = pc;
1421 this.next = next;
1422 this.state = state;
1423 }
1424 }
1426 /** Negate a branch opcode.
1427 */
1428 public static int negate(int opcode) {
1429 if (opcode == if_acmp_null) return if_acmp_nonnull;
1430 else if (opcode == if_acmp_nonnull) return if_acmp_null;
1431 else return ((opcode + 1) ^ 1) - 1;
1432 }
1434 /** Emit a jump instruction.
1435 * Return code pointer of instruction to be patched.
1436 */
1437 public int emitJump(int opcode) {
1438 if (fatcode) {
1439 if (opcode == goto_ || opcode == jsr) {
1440 emitop4(opcode + goto_w - goto_, 0);
1441 } else {
1442 emitop2(negate(opcode), 8);
1443 emitop4(goto_w, 0);
1444 alive = true;
1445 pendingStackMap = needStackMap;
1446 }
1447 return cp - 5;
1448 } else {
1449 emitop2(opcode, 0);
1450 return cp - 3;
1451 }
1452 }
1454 /** Emit a branch with given opcode; return its chain.
1455 * branch differs from jump in that jsr is treated as no-op.
1456 */
1457 public Chain branch(int opcode) {
1458 Chain result = null;
1459 if (opcode == goto_) {
1460 result = pendingJumps;
1461 pendingJumps = null;
1462 }
1463 if (opcode != dontgoto && isAlive()) {
1464 result = new Chain(emitJump(opcode),
1465 result,
1466 state.dup());
1467 fixedPc = fatcode;
1468 if (opcode == goto_) alive = false;
1469 }
1470 return result;
1471 }
1473 /** Resolve chain to point to given target.
1474 */
1475 public void resolve(Chain chain, int target) {
1476 boolean changed = false;
1477 State newState = state;
1478 for (; chain != null; chain = chain.next) {
1479 Assert.check(state != chain.state
1480 && (target > chain.pc || state.stacksize == 0));
1481 if (target >= cp) {
1482 target = cp;
1483 } else if (get1(target) == goto_) {
1484 if (fatcode) target = target + get4(target + 1);
1485 else target = target + get2(target + 1);
1486 }
1487 if (get1(chain.pc) == goto_ &&
1488 chain.pc + 3 == target && target == cp && !fixedPc) {
1489 // If goto the next instruction, the jump is not needed:
1490 // compact the code.
1491 if (varDebugInfo) {
1492 adjustAliveRanges(cp, -3);
1493 }
1494 cp = cp - 3;
1495 target = target - 3;
1496 if (chain.next == null) {
1497 // This is the only jump to the target. Exit the loop
1498 // without setting new state. The code is reachable
1499 // from the instruction before goto_.
1500 alive = true;
1501 break;
1502 }
1503 } else {
1504 if (fatcode)
1505 put4(chain.pc + 1, target - chain.pc);
1506 else if (target - chain.pc < Short.MIN_VALUE ||
1507 target - chain.pc > Short.MAX_VALUE)
1508 fatcode = true;
1509 else
1510 put2(chain.pc + 1, target - chain.pc);
1511 Assert.check(!alive ||
1512 chain.state.stacksize == newState.stacksize &&
1513 chain.state.nlocks == newState.nlocks);
1514 }
1515 fixedPc = true;
1516 if (cp == target) {
1517 changed = true;
1518 if (debugCode)
1519 System.err.println("resolving chain state=" + chain.state);
1520 if (alive) {
1521 newState = chain.state.join(newState);
1522 } else {
1523 newState = chain.state;
1524 alive = true;
1525 }
1526 }
1527 }
1528 Assert.check(!changed || state != newState);
1529 if (state != newState) {
1530 setDefined(newState.defined);
1531 state = newState;
1532 pendingStackMap = needStackMap;
1533 }
1534 }
1536 /** Resolve chain to point to current code pointer.
1537 */
1538 public void resolve(Chain chain) {
1539 Assert.check(
1540 !alive ||
1541 chain==null ||
1542 state.stacksize == chain.state.stacksize &&
1543 state.nlocks == chain.state.nlocks);
1544 pendingJumps = mergeChains(chain, pendingJumps);
1545 }
1547 /** Resolve any pending jumps.
1548 */
1549 public void resolvePending() {
1550 Chain x = pendingJumps;
1551 pendingJumps = null;
1552 resolve(x, cp);
1553 }
1555 /** Merge the jumps in of two chains into one.
1556 */
1557 public static Chain mergeChains(Chain chain1, Chain chain2) {
1558 // recursive merge sort
1559 if (chain2 == null) return chain1;
1560 if (chain1 == null) return chain2;
1561 Assert.check(
1562 chain1.state.stacksize == chain2.state.stacksize &&
1563 chain1.state.nlocks == chain2.state.nlocks);
1564 if (chain1.pc < chain2.pc)
1565 return new Chain(
1566 chain2.pc,
1567 mergeChains(chain1, chain2.next),
1568 chain2.state);
1569 return new Chain(
1570 chain1.pc,
1571 mergeChains(chain1.next, chain2),
1572 chain1.state);
1573 }
1576 /* **************************************************************************
1577 * Catch clauses
1578 ****************************************************************************/
1580 /** Add a catch clause to code.
1581 */
1582 public void addCatch(
1583 char startPc, char endPc, char handlerPc, char catchType) {
1584 catchInfo.append(new char[]{startPc, endPc, handlerPc, catchType});
1585 }
1588 public void compressCatchTable() {
1589 ListBuffer<char[]> compressedCatchInfo = new ListBuffer<>();
1590 List<Integer> handlerPcs = List.nil();
1591 for (char[] catchEntry : catchInfo) {
1592 handlerPcs = handlerPcs.prepend((int)catchEntry[2]);
1593 }
1594 for (char[] catchEntry : catchInfo) {
1595 int startpc = catchEntry[0];
1596 int endpc = catchEntry[1];
1597 if (startpc == endpc ||
1598 (startpc == (endpc - 1) &&
1599 handlerPcs.contains(startpc))) {
1600 continue;
1601 } else {
1602 compressedCatchInfo.append(catchEntry);
1603 }
1604 }
1605 catchInfo = compressedCatchInfo;
1606 }
1609 /* **************************************************************************
1610 * Line numbers
1611 ****************************************************************************/
1613 /** Add a line number entry.
1614 */
1615 public void addLineNumber(char startPc, char lineNumber) {
1616 if (lineDebugInfo) {
1617 if (lineInfo.nonEmpty() && lineInfo.head[0] == startPc)
1618 lineInfo = lineInfo.tail;
1619 if (lineInfo.isEmpty() || lineInfo.head[1] != lineNumber)
1620 lineInfo = lineInfo.prepend(new char[]{startPc, lineNumber});
1621 }
1622 }
1624 /** Mark beginning of statement.
1625 */
1626 public void statBegin(int pos) {
1627 if (pos != Position.NOPOS) {
1628 pendingStatPos = pos;
1629 }
1630 }
1632 /** Force stat begin eagerly
1633 */
1634 public void markStatBegin() {
1635 if (alive && lineDebugInfo) {
1636 int line = lineMap.getLineNumber(pendingStatPos);
1637 char cp1 = (char)cp;
1638 char line1 = (char)line;
1639 if (cp1 == cp && line1 == line)
1640 addLineNumber(cp1, line1);
1641 }
1642 pendingStatPos = Position.NOPOS;
1643 }
1646 /* **************************************************************************
1647 * Simulated VM machine state
1648 ****************************************************************************/
1650 class State implements Cloneable {
1651 /** The set of registers containing values. */
1652 Bits defined;
1654 /** The (types of the) contents of the machine stack. */
1655 Type[] stack;
1657 /** The first stack position currently unused. */
1658 int stacksize;
1660 /** The numbers of registers containing locked monitors. */
1661 int[] locks;
1662 int nlocks;
1664 State() {
1665 defined = new Bits();
1666 stack = new Type[16];
1667 }
1669 State dup() {
1670 try {
1671 State state = (State)super.clone();
1672 state.defined = new Bits(defined);
1673 state.stack = stack.clone();
1674 if (locks != null) state.locks = locks.clone();
1675 if (debugCode) {
1676 System.err.println("duping state " + this);
1677 dump();
1678 }
1679 return state;
1680 } catch (CloneNotSupportedException ex) {
1681 throw new AssertionError(ex);
1682 }
1683 }
1685 void lock(int register) {
1686 if (locks == null) {
1687 locks = new int[20];
1688 } else {
1689 locks = ArrayUtils.ensureCapacity(locks, nlocks);
1690 }
1691 locks[nlocks] = register;
1692 nlocks++;
1693 }
1695 void unlock(int register) {
1696 nlocks--;
1697 Assert.check(locks[nlocks] == register);
1698 locks[nlocks] = -1;
1699 }
1701 void push(Type t) {
1702 if (debugCode) System.err.println(" pushing " + t);
1703 switch (t.getTag()) {
1704 case VOID:
1705 return;
1706 case BYTE:
1707 case CHAR:
1708 case SHORT:
1709 case BOOLEAN:
1710 t = syms.intType;
1711 break;
1712 default:
1713 break;
1714 }
1715 stack = ArrayUtils.ensureCapacity(stack, stacksize+2);
1716 stack[stacksize++] = t;
1717 switch (width(t)) {
1718 case 1:
1719 break;
1720 case 2:
1721 stack[stacksize++] = null;
1722 break;
1723 default:
1724 throw new AssertionError(t);
1725 }
1726 if (stacksize > max_stack)
1727 max_stack = stacksize;
1728 }
1730 Type pop1() {
1731 if (debugCode) System.err.println(" popping " + 1);
1732 stacksize--;
1733 Type result = stack[stacksize];
1734 stack[stacksize] = null;
1735 Assert.check(result != null && width(result) == 1);
1736 return result;
1737 }
1739 Type peek() {
1740 return stack[stacksize-1];
1741 }
1743 Type pop2() {
1744 if (debugCode) System.err.println(" popping " + 2);
1745 stacksize -= 2;
1746 Type result = stack[stacksize];
1747 stack[stacksize] = null;
1748 Assert.check(stack[stacksize+1] == null
1749 && result != null && width(result) == 2);
1750 return result;
1751 }
1753 void pop(int n) {
1754 if (debugCode) System.err.println(" popping " + n);
1755 while (n > 0) {
1756 stack[--stacksize] = null;
1757 n--;
1758 }
1759 }
1761 void pop(Type t) {
1762 pop(width(t));
1763 }
1765 /** Force the top of the stack to be treated as this supertype
1766 * of its current type. */
1767 void forceStackTop(Type t) {
1768 if (!alive) return;
1769 switch (t.getTag()) {
1770 case CLASS:
1771 case ARRAY:
1772 int width = width(t);
1773 Type old = stack[stacksize-width];
1774 Assert.check(types.isSubtype(types.erasure(old),
1775 types.erasure(t)));
1776 stack[stacksize-width] = t;
1777 break;
1778 default:
1779 }
1780 }
1782 void markInitialized(UninitializedType old) {
1783 Type newtype = old.initializedType();
1784 for (int i=0; i<stacksize; i++) {
1785 if (stack[i] == old) stack[i] = newtype;
1786 }
1787 for (int i=0; i<lvar.length; i++) {
1788 LocalVar lv = lvar[i];
1789 if (lv != null && lv.sym.type == old) {
1790 VarSymbol sym = lv.sym;
1791 sym = sym.clone(sym.owner);
1792 sym.type = newtype;
1793 LocalVar newlv = lvar[i] = new LocalVar(sym);
1794 newlv.aliveRanges = lv.aliveRanges;
1795 }
1796 }
1797 }
1799 State join(State other) {
1800 defined.andSet(other.defined);
1801 Assert.check(stacksize == other.stacksize
1802 && nlocks == other.nlocks);
1803 for (int i=0; i<stacksize; ) {
1804 Type t = stack[i];
1805 Type tother = other.stack[i];
1806 Type result =
1807 t==tother ? t :
1808 types.isSubtype(t, tother) ? tother :
1809 types.isSubtype(tother, t) ? t :
1810 error();
1811 int w = width(result);
1812 stack[i] = result;
1813 if (w == 2) Assert.checkNull(stack[i+1]);
1814 i += w;
1815 }
1816 return this;
1817 }
1819 Type error() {
1820 throw new AssertionError("inconsistent stack types at join point");
1821 }
1823 void dump() {
1824 dump(-1);
1825 }
1827 void dump(int pc) {
1828 System.err.print("stackMap for " + meth.owner + "." + meth);
1829 if (pc == -1)
1830 System.out.println();
1831 else
1832 System.out.println(" at " + pc);
1833 System.err.println(" stack (from bottom):");
1834 for (int i=0; i<stacksize; i++)
1835 System.err.println(" " + i + ": " + stack[i]);
1837 int lastLocal = 0;
1838 for (int i=max_locals-1; i>=0; i--) {
1839 if (defined.isMember(i)) {
1840 lastLocal = i;
1841 break;
1842 }
1843 }
1844 if (lastLocal >= 0)
1845 System.err.println(" locals:");
1846 for (int i=0; i<=lastLocal; i++) {
1847 System.err.print(" " + i + ": ");
1848 if (defined.isMember(i)) {
1849 LocalVar var = lvar[i];
1850 if (var == null) {
1851 System.err.println("(none)");
1852 } else if (var.sym == null)
1853 System.err.println("UNKNOWN!");
1854 else
1855 System.err.println("" + var.sym + " of type " +
1856 var.sym.erasure(types));
1857 } else {
1858 System.err.println("undefined");
1859 }
1860 }
1861 if (nlocks != 0) {
1862 System.err.print(" locks:");
1863 for (int i=0; i<nlocks; i++) {
1864 System.err.print(" " + locks[i]);
1865 }
1866 System.err.println();
1867 }
1868 }
1869 }
1871 static final Type jsrReturnValue = new JCPrimitiveType(INT, null);
1874 /* **************************************************************************
1875 * Local variables
1876 ****************************************************************************/
1878 /** A live range of a local variable. */
1879 static class LocalVar {
1880 final VarSymbol sym;
1881 final char reg;
1883 class Range {
1884 char start_pc = Character.MAX_VALUE;
1885 char length = Character.MAX_VALUE;
1887 Range() {}
1889 Range(char start) {
1890 this.start_pc = start;
1891 }
1893 Range(char start, char length) {
1894 this.start_pc = start;
1895 this.length = length;
1896 }
1898 boolean closed() {
1899 return start_pc != Character.MAX_VALUE && length != Character.MAX_VALUE;
1900 }
1902 @Override
1903 public String toString() {
1904 int currentStartPC = start_pc;
1905 int currentLength = length;
1906 return "startpc = " + currentStartPC + " length " + currentLength;
1907 }
1908 }
1910 java.util.List<Range> aliveRanges = new java.util.ArrayList<>();
1912 LocalVar(VarSymbol v) {
1913 this.sym = v;
1914 this.reg = (char)v.adr;
1915 }
1916 public LocalVar dup() {
1917 return new LocalVar(sym);
1918 }
1920 Range firstRange() {
1921 return aliveRanges.isEmpty() ? null : aliveRanges.get(0);
1922 }
1924 Range lastRange() {
1925 return aliveRanges.isEmpty() ? null : aliveRanges.get(aliveRanges.size() - 1);
1926 }
1928 void removeLastRange() {
1929 Range lastRange = lastRange();
1930 if (lastRange != null) {
1931 aliveRanges.remove(lastRange);
1932 }
1933 }
1935 @Override
1936 public String toString() {
1937 if (aliveRanges == null) {
1938 return "empty local var";
1939 }
1940 StringBuilder sb = new StringBuilder().append(sym)
1941 .append(" in register ").append((int)reg).append(" \n");
1942 for (Range r : aliveRanges) {
1943 sb.append(" starts at pc=").append(Integer.toString(((int)r.start_pc)))
1944 .append(" length=").append(Integer.toString(((int)r.length)))
1945 .append("\n");
1946 }
1947 return sb.toString();
1948 }
1950 public void openRange(char start) {
1951 if (!hasOpenRange()) {
1952 aliveRanges.add(new Range(start));
1953 }
1954 }
1956 public void closeRange(char end) {
1957 if (isLastRangeInitialized()) {
1958 Range range = lastRange();
1959 if (range != null) {
1960 if (range.length == Character.MAX_VALUE) {
1961 range.length = end;
1962 }
1963 }
1964 } else {
1965 removeLastRange();
1966 }
1967 }
1969 public boolean hasOpenRange() {
1970 if (aliveRanges.isEmpty()) {
1971 return false;
1972 }
1973 return lastRange().length == Character.MAX_VALUE;
1974 }
1976 public boolean isLastRangeInitialized() {
1977 if (aliveRanges.isEmpty()) {
1978 return false;
1979 }
1980 return lastRange().start_pc != Character.MAX_VALUE;
1981 }
1983 public Range getWidestRange() {
1984 if (aliveRanges.isEmpty()) {
1985 return new Range();
1986 } else {
1987 Range firstRange = firstRange();
1988 Range lastRange = lastRange();
1989 char length = (char)(lastRange.length + (lastRange.start_pc - firstRange.start_pc));
1990 return new Range(firstRange.start_pc, length);
1991 }
1992 }
1994 };
1996 /** Local variables, indexed by register. */
1997 LocalVar[] lvar;
1999 /** Add a new local variable. */
2000 private void addLocalVar(VarSymbol v) {
2001 int adr = v.adr;
2002 lvar = ArrayUtils.ensureCapacity(lvar, adr+1);
2003 Assert.checkNull(lvar[adr]);
2004 if (pendingJumps != null) {
2005 resolvePending();
2006 }
2007 lvar[adr] = new LocalVar(v);
2008 state.defined.excl(adr);
2009 }
2012 public void closeAliveRanges(JCTree tree) {
2013 closeAliveRanges(tree, cp);
2014 }
2016 public void closeAliveRanges(JCTree tree, int closingCP) {
2017 List<VarSymbol> locals = lvtRanges.getVars(meth, tree);
2018 for (LocalVar localVar: lvar) {
2019 for (VarSymbol aliveLocal : locals) {
2020 if (localVar == null) {
2021 return;
2022 }
2023 if (localVar.sym == aliveLocal && localVar.lastRange() != null) {
2024 char length = (char)(closingCP - localVar.lastRange().start_pc);
2025 if (length > 0 && length < Character.MAX_VALUE) {
2026 localVar.closeRange(length);
2027 }
2028 }
2029 }
2030 }
2031 }
2033 void adjustAliveRanges(int oldCP, int delta) {
2034 for (LocalVar localVar: lvar) {
2035 if (localVar == null) {
2036 return;
2037 }
2038 for (LocalVar.Range range: localVar.aliveRanges) {
2039 if (range.closed() && range.start_pc + range.length >= oldCP) {
2040 range.length += delta;
2041 }
2042 }
2043 }
2044 }
2046 /**
2047 * Calculates the size of the LocalVariableTable.
2048 */
2049 public int getLVTSize() {
2050 int result = varBufferSize;
2051 for (int i = 0; i < varBufferSize; i++) {
2052 LocalVar var = varBuffer[i];
2053 result += var.aliveRanges.size() - 1;
2054 }
2055 return result;
2056 }
2058 /** Set the current variable defined state. */
2059 public void setDefined(Bits newDefined) {
2060 if (alive && newDefined != state.defined) {
2061 Bits diff = new Bits(state.defined).xorSet(newDefined);
2062 for (int adr = diff.nextBit(0);
2063 adr >= 0;
2064 adr = diff.nextBit(adr+1)) {
2065 if (adr >= nextreg)
2066 state.defined.excl(adr);
2067 else if (state.defined.isMember(adr))
2068 setUndefined(adr);
2069 else
2070 setDefined(adr);
2071 }
2072 }
2073 }
2075 /** Mark a register as being (possibly) defined. */
2076 public void setDefined(int adr) {
2077 LocalVar v = lvar[adr];
2078 if (v == null) {
2079 state.defined.excl(adr);
2080 } else {
2081 state.defined.incl(adr);
2082 if (cp < Character.MAX_VALUE) {
2083 v.openRange((char)cp);
2084 }
2085 }
2086 }
2088 /** Mark a register as being undefined. */
2089 public void setUndefined(int adr) {
2090 state.defined.excl(adr);
2091 if (adr < lvar.length &&
2092 lvar[adr] != null &&
2093 lvar[adr].isLastRangeInitialized()) {
2094 LocalVar v = lvar[adr];
2095 char length = (char)(curCP() - v.lastRange().start_pc);
2096 if (length > 0 && length < Character.MAX_VALUE) {
2097 lvar[adr] = v.dup();
2098 v.closeRange(length);
2099 putVar(v);
2100 } else {
2101 v.removeLastRange();
2102 }
2103 }
2104 }
2106 /** End the scope of a variable. */
2107 private void endScope(int adr) {
2108 LocalVar v = lvar[adr];
2109 if (v != null) {
2110 if (v.isLastRangeInitialized()) {
2111 char length = (char)(curCP() - v.lastRange().start_pc);
2112 if (length < Character.MAX_VALUE) {
2113 v.closeRange(length);
2114 putVar(v);
2115 fillLocalVarPosition(v);
2116 }
2117 }
2118 /** the call to curCP() can implicitly adjust the current cp, if so
2119 * the alive range of local variables may be modified. Thus we need
2120 * all of them. For this reason assigning null to the given address
2121 * should be the last action to do.
2122 */
2123 lvar[adr] = null;
2124 }
2125 state.defined.excl(adr);
2126 }
2128 private void fillLocalVarPosition(LocalVar lv) {
2129 if (lv == null || lv.sym == null || !lv.sym.hasTypeAnnotations())
2130 return;
2131 for (Attribute.TypeCompound ta : lv.sym.getRawTypeAttributes()) {
2132 TypeAnnotationPosition p = ta.position;
2133 LocalVar.Range widestRange = lv.getWidestRange();
2134 p.lvarOffset = new int[] { (int)widestRange.start_pc };
2135 p.lvarLength = new int[] { (int)widestRange.length };
2136 p.lvarIndex = new int[] { (int)lv.reg };
2137 p.isValidOffset = true;
2138 }
2139 }
2141 // Method to be called after compressCatchTable to
2142 // fill in the exception table index for type
2143 // annotations on exception parameters.
2144 public void fillExceptionParameterPositions() {
2145 for (int i = 0; i < varBufferSize; ++i) {
2146 LocalVar lv = varBuffer[i];
2147 if (lv == null || lv.sym == null
2148 || !lv.sym.hasTypeAnnotations()
2149 || !lv.sym.isExceptionParameter())
2150 continue;
2152 for (Attribute.TypeCompound ta : lv.sym.getRawTypeAttributes()) {
2153 TypeAnnotationPosition p = ta.position;
2154 // At this point p.type_index contains the catch type index.
2155 // Use that index to determine the exception table index.
2156 // We can afterwards discard the type_index.
2157 // A TA position is shared for all type annotations in the
2158 // same location; updating one is enough.
2159 // Use -666 as a marker that the exception_index was already updated.
2160 if (p.type_index != -666) {
2161 p.exception_index = findExceptionIndex(p.type_index);
2162 p.type_index = -666;
2163 }
2164 }
2165 }
2166 }
2168 private int findExceptionIndex(int catchType) {
2169 if (catchType == Integer.MIN_VALUE) {
2170 // We didn't set the catch type index correctly.
2171 // This shouldn't happen.
2172 // TODO: issue error?
2173 return -1;
2174 }
2175 List<char[]> iter = catchInfo.toList();
2176 int len = catchInfo.length();
2177 for (int i = 0; i < len; ++i) {
2178 char[] catchEntry = iter.head;
2179 iter = iter.tail;
2180 char ct = catchEntry[3];
2181 if (catchType == ct) {
2182 return i;
2183 }
2184 }
2185 return -1;
2186 }
2188 /** Put a live variable range into the buffer to be output to the
2189 * class file.
2190 */
2191 void putVar(LocalVar var) {
2192 // Keep local variables if
2193 // 1) we need them for debug information
2194 // 2) it is an exception type and it contains type annotations
2195 boolean keepLocalVariables = varDebugInfo ||
2196 (var.sym.isExceptionParameter() && var.sym.hasTypeAnnotations());
2197 if (!keepLocalVariables) return;
2198 if ((var.sym.flags() & Flags.SYNTHETIC) != 0) return;
2199 if (varBuffer == null)
2200 varBuffer = new LocalVar[20];
2201 else
2202 varBuffer = ArrayUtils.ensureCapacity(varBuffer, varBufferSize);
2203 varBuffer[varBufferSize++] = var;
2204 }
2206 /** Previously live local variables, to be put into the variable table. */
2207 LocalVar[] varBuffer;
2208 int varBufferSize;
2210 /** Create a new local variable address and return it.
2211 */
2212 private int newLocal(int typecode) {
2213 int reg = nextreg;
2214 int w = width(typecode);
2215 nextreg = reg + w;
2216 if (nextreg > max_locals) max_locals = nextreg;
2217 return reg;
2218 }
2220 private int newLocal(Type type) {
2221 return newLocal(typecode(type));
2222 }
2224 public int newLocal(VarSymbol v) {
2225 int reg = v.adr = newLocal(v.erasure(types));
2226 addLocalVar(v);
2227 return reg;
2228 }
2230 /** Start a set of fresh registers.
2231 */
2232 public void newRegSegment() {
2233 nextreg = max_locals;
2234 }
2236 /** End scopes of all variables with registers ≥ first.
2237 */
2238 public void endScopes(int first) {
2239 int prevNextReg = nextreg;
2240 nextreg = first;
2241 for (int i = nextreg; i < prevNextReg; i++) endScope(i);
2242 }
2244 /**************************************************************************
2245 * static tables
2246 *************************************************************************/
2248 public static String mnem(int opcode) {
2249 return Mneumonics.mnem[opcode];
2250 }
2252 private static class Mneumonics {
2253 private final static String[] mnem = new String[ByteCodeCount];
2254 static {
2255 mnem[nop] = "nop";
2256 mnem[aconst_null] = "aconst_null";
2257 mnem[iconst_m1] = "iconst_m1";
2258 mnem[iconst_0] = "iconst_0";
2259 mnem[iconst_1] = "iconst_1";
2260 mnem[iconst_2] = "iconst_2";
2261 mnem[iconst_3] = "iconst_3";
2262 mnem[iconst_4] = "iconst_4";
2263 mnem[iconst_5] = "iconst_5";
2264 mnem[lconst_0] = "lconst_0";
2265 mnem[lconst_1] = "lconst_1";
2266 mnem[fconst_0] = "fconst_0";
2267 mnem[fconst_1] = "fconst_1";
2268 mnem[fconst_2] = "fconst_2";
2269 mnem[dconst_0] = "dconst_0";
2270 mnem[dconst_1] = "dconst_1";
2271 mnem[bipush] = "bipush";
2272 mnem[sipush] = "sipush";
2273 mnem[ldc1] = "ldc1";
2274 mnem[ldc2] = "ldc2";
2275 mnem[ldc2w] = "ldc2w";
2276 mnem[iload] = "iload";
2277 mnem[lload] = "lload";
2278 mnem[fload] = "fload";
2279 mnem[dload] = "dload";
2280 mnem[aload] = "aload";
2281 mnem[iload_0] = "iload_0";
2282 mnem[lload_0] = "lload_0";
2283 mnem[fload_0] = "fload_0";
2284 mnem[dload_0] = "dload_0";
2285 mnem[aload_0] = "aload_0";
2286 mnem[iload_1] = "iload_1";
2287 mnem[lload_1] = "lload_1";
2288 mnem[fload_1] = "fload_1";
2289 mnem[dload_1] = "dload_1";
2290 mnem[aload_1] = "aload_1";
2291 mnem[iload_2] = "iload_2";
2292 mnem[lload_2] = "lload_2";
2293 mnem[fload_2] = "fload_2";
2294 mnem[dload_2] = "dload_2";
2295 mnem[aload_2] = "aload_2";
2296 mnem[iload_3] = "iload_3";
2297 mnem[lload_3] = "lload_3";
2298 mnem[fload_3] = "fload_3";
2299 mnem[dload_3] = "dload_3";
2300 mnem[aload_3] = "aload_3";
2301 mnem[iaload] = "iaload";
2302 mnem[laload] = "laload";
2303 mnem[faload] = "faload";
2304 mnem[daload] = "daload";
2305 mnem[aaload] = "aaload";
2306 mnem[baload] = "baload";
2307 mnem[caload] = "caload";
2308 mnem[saload] = "saload";
2309 mnem[istore] = "istore";
2310 mnem[lstore] = "lstore";
2311 mnem[fstore] = "fstore";
2312 mnem[dstore] = "dstore";
2313 mnem[astore] = "astore";
2314 mnem[istore_0] = "istore_0";
2315 mnem[lstore_0] = "lstore_0";
2316 mnem[fstore_0] = "fstore_0";
2317 mnem[dstore_0] = "dstore_0";
2318 mnem[astore_0] = "astore_0";
2319 mnem[istore_1] = "istore_1";
2320 mnem[lstore_1] = "lstore_1";
2321 mnem[fstore_1] = "fstore_1";
2322 mnem[dstore_1] = "dstore_1";
2323 mnem[astore_1] = "astore_1";
2324 mnem[istore_2] = "istore_2";
2325 mnem[lstore_2] = "lstore_2";
2326 mnem[fstore_2] = "fstore_2";
2327 mnem[dstore_2] = "dstore_2";
2328 mnem[astore_2] = "astore_2";
2329 mnem[istore_3] = "istore_3";
2330 mnem[lstore_3] = "lstore_3";
2331 mnem[fstore_3] = "fstore_3";
2332 mnem[dstore_3] = "dstore_3";
2333 mnem[astore_3] = "astore_3";
2334 mnem[iastore] = "iastore";
2335 mnem[lastore] = "lastore";
2336 mnem[fastore] = "fastore";
2337 mnem[dastore] = "dastore";
2338 mnem[aastore] = "aastore";
2339 mnem[bastore] = "bastore";
2340 mnem[castore] = "castore";
2341 mnem[sastore] = "sastore";
2342 mnem[pop] = "pop";
2343 mnem[pop2] = "pop2";
2344 mnem[dup] = "dup";
2345 mnem[dup_x1] = "dup_x1";
2346 mnem[dup_x2] = "dup_x2";
2347 mnem[dup2] = "dup2";
2348 mnem[dup2_x1] = "dup2_x1";
2349 mnem[dup2_x2] = "dup2_x2";
2350 mnem[swap] = "swap";
2351 mnem[iadd] = "iadd";
2352 mnem[ladd] = "ladd";
2353 mnem[fadd] = "fadd";
2354 mnem[dadd] = "dadd";
2355 mnem[isub] = "isub";
2356 mnem[lsub] = "lsub";
2357 mnem[fsub] = "fsub";
2358 mnem[dsub] = "dsub";
2359 mnem[imul] = "imul";
2360 mnem[lmul] = "lmul";
2361 mnem[fmul] = "fmul";
2362 mnem[dmul] = "dmul";
2363 mnem[idiv] = "idiv";
2364 mnem[ldiv] = "ldiv";
2365 mnem[fdiv] = "fdiv";
2366 mnem[ddiv] = "ddiv";
2367 mnem[imod] = "imod";
2368 mnem[lmod] = "lmod";
2369 mnem[fmod] = "fmod";
2370 mnem[dmod] = "dmod";
2371 mnem[ineg] = "ineg";
2372 mnem[lneg] = "lneg";
2373 mnem[fneg] = "fneg";
2374 mnem[dneg] = "dneg";
2375 mnem[ishl] = "ishl";
2376 mnem[lshl] = "lshl";
2377 mnem[ishr] = "ishr";
2378 mnem[lshr] = "lshr";
2379 mnem[iushr] = "iushr";
2380 mnem[lushr] = "lushr";
2381 mnem[iand] = "iand";
2382 mnem[land] = "land";
2383 mnem[ior] = "ior";
2384 mnem[lor] = "lor";
2385 mnem[ixor] = "ixor";
2386 mnem[lxor] = "lxor";
2387 mnem[iinc] = "iinc";
2388 mnem[i2l] = "i2l";
2389 mnem[i2f] = "i2f";
2390 mnem[i2d] = "i2d";
2391 mnem[l2i] = "l2i";
2392 mnem[l2f] = "l2f";
2393 mnem[l2d] = "l2d";
2394 mnem[f2i] = "f2i";
2395 mnem[f2l] = "f2l";
2396 mnem[f2d] = "f2d";
2397 mnem[d2i] = "d2i";
2398 mnem[d2l] = "d2l";
2399 mnem[d2f] = "d2f";
2400 mnem[int2byte] = "int2byte";
2401 mnem[int2char] = "int2char";
2402 mnem[int2short] = "int2short";
2403 mnem[lcmp] = "lcmp";
2404 mnem[fcmpl] = "fcmpl";
2405 mnem[fcmpg] = "fcmpg";
2406 mnem[dcmpl] = "dcmpl";
2407 mnem[dcmpg] = "dcmpg";
2408 mnem[ifeq] = "ifeq";
2409 mnem[ifne] = "ifne";
2410 mnem[iflt] = "iflt";
2411 mnem[ifge] = "ifge";
2412 mnem[ifgt] = "ifgt";
2413 mnem[ifle] = "ifle";
2414 mnem[if_icmpeq] = "if_icmpeq";
2415 mnem[if_icmpne] = "if_icmpne";
2416 mnem[if_icmplt] = "if_icmplt";
2417 mnem[if_icmpge] = "if_icmpge";
2418 mnem[if_icmpgt] = "if_icmpgt";
2419 mnem[if_icmple] = "if_icmple";
2420 mnem[if_acmpeq] = "if_acmpeq";
2421 mnem[if_acmpne] = "if_acmpne";
2422 mnem[goto_] = "goto_";
2423 mnem[jsr] = "jsr";
2424 mnem[ret] = "ret";
2425 mnem[tableswitch] = "tableswitch";
2426 mnem[lookupswitch] = "lookupswitch";
2427 mnem[ireturn] = "ireturn";
2428 mnem[lreturn] = "lreturn";
2429 mnem[freturn] = "freturn";
2430 mnem[dreturn] = "dreturn";
2431 mnem[areturn] = "areturn";
2432 mnem[return_] = "return_";
2433 mnem[getstatic] = "getstatic";
2434 mnem[putstatic] = "putstatic";
2435 mnem[getfield] = "getfield";
2436 mnem[putfield] = "putfield";
2437 mnem[invokevirtual] = "invokevirtual";
2438 mnem[invokespecial] = "invokespecial";
2439 mnem[invokestatic] = "invokestatic";
2440 mnem[invokeinterface] = "invokeinterface";
2441 mnem[invokedynamic] = "invokedynamic";
2442 mnem[new_] = "new_";
2443 mnem[newarray] = "newarray";
2444 mnem[anewarray] = "anewarray";
2445 mnem[arraylength] = "arraylength";
2446 mnem[athrow] = "athrow";
2447 mnem[checkcast] = "checkcast";
2448 mnem[instanceof_] = "instanceof_";
2449 mnem[monitorenter] = "monitorenter";
2450 mnem[monitorexit] = "monitorexit";
2451 mnem[wide] = "wide";
2452 mnem[multianewarray] = "multianewarray";
2453 mnem[if_acmp_null] = "if_acmp_null";
2454 mnem[if_acmp_nonnull] = "if_acmp_nonnull";
2455 mnem[goto_w] = "goto_w";
2456 mnem[jsr_w] = "jsr_w";
2457 mnem[breakpoint] = "breakpoint";
2458 }
2459 }
2460 }