Wed, 23 Oct 2013 23:20:32 -0400
8006732: support correct bytecode storage of type annotations in multicatch
Summary: Fix issue with annotations being added before attribution, which causes multicatch not to work right and several tests to fail.
Reviewed-by: jfranck, jjg
1 /*
2 * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
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 // N.B. this format is under consideration by the JSR 292 EG
487 int argsize = width(mtype.getParameterTypes());
488 int prevPos = pendingStatPos;
489 try {
490 //disable line number generation (we could have used 'emit1', that
491 //bypasses stackmap generation - which is needed for indy calls)
492 pendingStatPos = Position.NOPOS;
493 emitop(invokedynamic);
494 } finally {
495 pendingStatPos = prevPos;
496 }
497 if (!alive) return;
498 emit2(desc);
499 emit2(0);
500 state.pop(argsize);
501 state.push(mtype.getReturnType());
502 }
504 /** Emit an opcode with no operand field.
505 */
506 public void emitop0(int op) {
507 emitop(op);
508 if (!alive) return;
509 switch (op) {
510 case aaload: {
511 state.pop(1);// index
512 Type a = state.stack[state.stacksize-1];
513 state.pop(1);
514 //sometimes 'null type' is treated as a one-dimensional array type
515 //see Gen.visitLiteral - we should handle this case accordingly
516 Type stackType = a.hasTag(BOT) ?
517 syms.objectType :
518 types.erasure(types.elemtype(a));
519 state.push(stackType); }
520 break;
521 case goto_:
522 markDead();
523 break;
524 case nop:
525 case ineg:
526 case lneg:
527 case fneg:
528 case dneg:
529 break;
530 case aconst_null:
531 state.push(syms.botType);
532 break;
533 case iconst_m1:
534 case iconst_0:
535 case iconst_1:
536 case iconst_2:
537 case iconst_3:
538 case iconst_4:
539 case iconst_5:
540 case iload_0:
541 case iload_1:
542 case iload_2:
543 case iload_3:
544 state.push(syms.intType);
545 break;
546 case lconst_0:
547 case lconst_1:
548 case lload_0:
549 case lload_1:
550 case lload_2:
551 case lload_3:
552 state.push(syms.longType);
553 break;
554 case fconst_0:
555 case fconst_1:
556 case fconst_2:
557 case fload_0:
558 case fload_1:
559 case fload_2:
560 case fload_3:
561 state.push(syms.floatType);
562 break;
563 case dconst_0:
564 case dconst_1:
565 case dload_0:
566 case dload_1:
567 case dload_2:
568 case dload_3:
569 state.push(syms.doubleType);
570 break;
571 case aload_0:
572 state.push(lvar[0].sym.type);
573 break;
574 case aload_1:
575 state.push(lvar[1].sym.type);
576 break;
577 case aload_2:
578 state.push(lvar[2].sym.type);
579 break;
580 case aload_3:
581 state.push(lvar[3].sym.type);
582 break;
583 case iaload:
584 case baload:
585 case caload:
586 case saload:
587 state.pop(2);
588 state.push(syms.intType);
589 break;
590 case laload:
591 state.pop(2);
592 state.push(syms.longType);
593 break;
594 case faload:
595 state.pop(2);
596 state.push(syms.floatType);
597 break;
598 case daload:
599 state.pop(2);
600 state.push(syms.doubleType);
601 break;
602 case istore_0:
603 case istore_1:
604 case istore_2:
605 case istore_3:
606 case fstore_0:
607 case fstore_1:
608 case fstore_2:
609 case fstore_3:
610 case astore_0:
611 case astore_1:
612 case astore_2:
613 case astore_3:
614 case pop:
615 case lshr:
616 case lshl:
617 case lushr:
618 state.pop(1);
619 break;
620 case areturn:
621 case ireturn:
622 case freturn:
623 Assert.check(state.nlocks == 0);
624 state.pop(1);
625 markDead();
626 break;
627 case athrow:
628 state.pop(1);
629 markDead();
630 break;
631 case lstore_0:
632 case lstore_1:
633 case lstore_2:
634 case lstore_3:
635 case dstore_0:
636 case dstore_1:
637 case dstore_2:
638 case dstore_3:
639 case pop2:
640 state.pop(2);
641 break;
642 case lreturn:
643 case dreturn:
644 Assert.check(state.nlocks == 0);
645 state.pop(2);
646 markDead();
647 break;
648 case dup:
649 state.push(state.stack[state.stacksize-1]);
650 break;
651 case return_:
652 Assert.check(state.nlocks == 0);
653 markDead();
654 break;
655 case arraylength:
656 state.pop(1);
657 state.push(syms.intType);
658 break;
659 case isub:
660 case iadd:
661 case imul:
662 case idiv:
663 case imod:
664 case ishl:
665 case ishr:
666 case iushr:
667 case iand:
668 case ior:
669 case ixor:
670 state.pop(1);
671 // state.pop(1);
672 // state.push(syms.intType);
673 break;
674 case aastore:
675 state.pop(3);
676 break;
677 case land:
678 case lor:
679 case lxor:
680 case lmod:
681 case ldiv:
682 case lmul:
683 case lsub:
684 case ladd:
685 state.pop(2);
686 break;
687 case lcmp:
688 state.pop(4);
689 state.push(syms.intType);
690 break;
691 case l2i:
692 state.pop(2);
693 state.push(syms.intType);
694 break;
695 case i2l:
696 state.pop(1);
697 state.push(syms.longType);
698 break;
699 case i2f:
700 state.pop(1);
701 state.push(syms.floatType);
702 break;
703 case i2d:
704 state.pop(1);
705 state.push(syms.doubleType);
706 break;
707 case l2f:
708 state.pop(2);
709 state.push(syms.floatType);
710 break;
711 case l2d:
712 state.pop(2);
713 state.push(syms.doubleType);
714 break;
715 case f2i:
716 state.pop(1);
717 state.push(syms.intType);
718 break;
719 case f2l:
720 state.pop(1);
721 state.push(syms.longType);
722 break;
723 case f2d:
724 state.pop(1);
725 state.push(syms.doubleType);
726 break;
727 case d2i:
728 state.pop(2);
729 state.push(syms.intType);
730 break;
731 case d2l:
732 state.pop(2);
733 state.push(syms.longType);
734 break;
735 case d2f:
736 state.pop(2);
737 state.push(syms.floatType);
738 break;
739 case tableswitch:
740 case lookupswitch:
741 state.pop(1);
742 // the caller is responsible for patching up the state
743 break;
744 case dup_x1: {
745 Type val1 = state.pop1();
746 Type val2 = state.pop1();
747 state.push(val1);
748 state.push(val2);
749 state.push(val1);
750 break;
751 }
752 case bastore:
753 state.pop(3);
754 break;
755 case int2byte:
756 case int2char:
757 case int2short:
758 break;
759 case fmul:
760 case fadd:
761 case fsub:
762 case fdiv:
763 case fmod:
764 state.pop(1);
765 break;
766 case castore:
767 case iastore:
768 case fastore:
769 case sastore:
770 state.pop(3);
771 break;
772 case lastore:
773 case dastore:
774 state.pop(4);
775 break;
776 case dup2:
777 if (state.stack[state.stacksize-1] != null) {
778 Type value1 = state.pop1();
779 Type value2 = state.pop1();
780 state.push(value2);
781 state.push(value1);
782 state.push(value2);
783 state.push(value1);
784 } else {
785 Type value = state.pop2();
786 state.push(value);
787 state.push(value);
788 }
789 break;
790 case dup2_x1:
791 if (state.stack[state.stacksize-1] != null) {
792 Type value1 = state.pop1();
793 Type value2 = state.pop1();
794 Type value3 = state.pop1();
795 state.push(value2);
796 state.push(value1);
797 state.push(value3);
798 state.push(value2);
799 state.push(value1);
800 } else {
801 Type value1 = state.pop2();
802 Type value2 = state.pop1();
803 state.push(value1);
804 state.push(value2);
805 state.push(value1);
806 }
807 break;
808 case dup2_x2:
809 if (state.stack[state.stacksize-1] != null) {
810 Type value1 = state.pop1();
811 Type value2 = state.pop1();
812 if (state.stack[state.stacksize-1] != null) {
813 // form 1
814 Type value3 = state.pop1();
815 Type value4 = state.pop1();
816 state.push(value2);
817 state.push(value1);
818 state.push(value4);
819 state.push(value3);
820 state.push(value2);
821 state.push(value1);
822 } else {
823 // form 3
824 Type value3 = state.pop2();
825 state.push(value2);
826 state.push(value1);
827 state.push(value3);
828 state.push(value2);
829 state.push(value1);
830 }
831 } else {
832 Type value1 = state.pop2();
833 if (state.stack[state.stacksize-1] != null) {
834 // form 2
835 Type value2 = state.pop1();
836 Type value3 = state.pop1();
837 state.push(value1);
838 state.push(value3);
839 state.push(value2);
840 state.push(value1);
841 } else {
842 // form 4
843 Type value2 = state.pop2();
844 state.push(value1);
845 state.push(value2);
846 state.push(value1);
847 }
848 }
849 break;
850 case dup_x2: {
851 Type value1 = state.pop1();
852 if (state.stack[state.stacksize-1] != null) {
853 // form 1
854 Type value2 = state.pop1();
855 Type value3 = state.pop1();
856 state.push(value1);
857 state.push(value3);
858 state.push(value2);
859 state.push(value1);
860 } else {
861 // form 2
862 Type value2 = state.pop2();
863 state.push(value1);
864 state.push(value2);
865 state.push(value1);
866 }
867 }
868 break;
869 case fcmpl:
870 case fcmpg:
871 state.pop(2);
872 state.push(syms.intType);
873 break;
874 case dcmpl:
875 case dcmpg:
876 state.pop(4);
877 state.push(syms.intType);
878 break;
879 case swap: {
880 Type value1 = state.pop1();
881 Type value2 = state.pop1();
882 state.push(value1);
883 state.push(value2);
884 break;
885 }
886 case dadd:
887 case dsub:
888 case dmul:
889 case ddiv:
890 case dmod:
891 state.pop(2);
892 break;
893 case ret:
894 markDead();
895 break;
896 case wide:
897 // must be handled by the caller.
898 return;
899 case monitorenter:
900 case monitorexit:
901 state.pop(1);
902 break;
904 default:
905 throw new AssertionError(mnem(op));
906 }
907 postop();
908 }
910 /** Emit an opcode with a one-byte operand field.
911 */
912 public void emitop1(int op, int od) {
913 emitop(op);
914 if (!alive) return;
915 emit1(od);
916 switch (op) {
917 case bipush:
918 state.push(syms.intType);
919 break;
920 case ldc1:
921 state.push(typeForPool(pool.pool[od]));
922 break;
923 default:
924 throw new AssertionError(mnem(op));
925 }
926 postop();
927 }
929 /** The type of a constant pool entry. */
930 private Type typeForPool(Object o) {
931 if (o instanceof Integer) return syms.intType;
932 if (o instanceof Float) return syms.floatType;
933 if (o instanceof String) return syms.stringType;
934 if (o instanceof Long) return syms.longType;
935 if (o instanceof Double) return syms.doubleType;
936 if (o instanceof ClassSymbol) return syms.classType;
937 if (o instanceof Pool.MethodHandle) return syms.methodHandleType;
938 if (o instanceof UniqueType) return typeForPool(((UniqueType)o).type);
939 if (o instanceof Type) {
940 Type ty = ((Type)o).unannotatedType();
942 if (ty instanceof Type.ArrayType) return syms.classType;
943 if (ty instanceof Type.MethodType) return syms.methodTypeType;
944 }
945 throw new AssertionError("Invalid type of constant pool entry: " + o.getClass());
946 }
948 /** Emit an opcode with a one-byte operand field;
949 * widen if field does not fit in a byte.
950 */
951 public void emitop1w(int op, int od) {
952 if (od > 0xFF) {
953 emitop(wide);
954 emitop(op);
955 emit2(od);
956 } else {
957 emitop(op);
958 emit1(od);
959 }
960 if (!alive) return;
961 switch (op) {
962 case iload:
963 state.push(syms.intType);
964 break;
965 case lload:
966 state.push(syms.longType);
967 break;
968 case fload:
969 state.push(syms.floatType);
970 break;
971 case dload:
972 state.push(syms.doubleType);
973 break;
974 case aload:
975 state.push(lvar[od].sym.type);
976 break;
977 case lstore:
978 case dstore:
979 state.pop(2);
980 break;
981 case istore:
982 case fstore:
983 case astore:
984 state.pop(1);
985 break;
986 case ret:
987 markDead();
988 break;
989 default:
990 throw new AssertionError(mnem(op));
991 }
992 postop();
993 }
995 /** Emit an opcode with two one-byte operand fields;
996 * widen if either field does not fit in a byte.
997 */
998 public void emitop1w(int op, int od1, int od2) {
999 if (od1 > 0xFF || od2 < -128 || od2 > 127) {
1000 emitop(wide);
1001 emitop(op);
1002 emit2(od1);
1003 emit2(od2);
1004 } else {
1005 emitop(op);
1006 emit1(od1);
1007 emit1(od2);
1008 }
1009 if (!alive) return;
1010 switch (op) {
1011 case iinc:
1012 break;
1013 default:
1014 throw new AssertionError(mnem(op));
1015 }
1016 }
1018 /** Emit an opcode with a two-byte operand field.
1019 */
1020 public void emitop2(int op, int od) {
1021 emitop(op);
1022 if (!alive) return;
1023 emit2(od);
1024 switch (op) {
1025 case getstatic:
1026 state.push(((Symbol)(pool.pool[od])).erasure(types));
1027 break;
1028 case putstatic:
1029 state.pop(((Symbol)(pool.pool[od])).erasure(types));
1030 break;
1031 case new_:
1032 Symbol sym;
1033 if (pool.pool[od] instanceof UniqueType) {
1034 // Required by change in Gen.makeRef to allow
1035 // annotated types.
1036 // TODO: is this needed anywhere else?
1037 sym = ((UniqueType)(pool.pool[od])).type.tsym;
1038 } else {
1039 sym = (Symbol)(pool.pool[od]);
1040 }
1041 state.push(uninitializedObject(sym.erasure(types), cp-3));
1042 break;
1043 case sipush:
1044 state.push(syms.intType);
1045 break;
1046 case if_acmp_null:
1047 case if_acmp_nonnull:
1048 case ifeq:
1049 case ifne:
1050 case iflt:
1051 case ifge:
1052 case ifgt:
1053 case ifle:
1054 state.pop(1);
1055 break;
1056 case if_icmpeq:
1057 case if_icmpne:
1058 case if_icmplt:
1059 case if_icmpge:
1060 case if_icmpgt:
1061 case if_icmple:
1062 case if_acmpeq:
1063 case if_acmpne:
1064 state.pop(2);
1065 break;
1066 case goto_:
1067 markDead();
1068 break;
1069 case putfield:
1070 state.pop(((Symbol)(pool.pool[od])).erasure(types));
1071 state.pop(1); // object ref
1072 break;
1073 case getfield:
1074 state.pop(1); // object ref
1075 state.push(((Symbol)(pool.pool[od])).erasure(types));
1076 break;
1077 case checkcast: {
1078 state.pop(1); // object ref
1079 Object o = pool.pool[od];
1080 Type t = (o instanceof Symbol)
1081 ? ((Symbol)o).erasure(types)
1082 : types.erasure((((UniqueType)o).type));
1083 state.push(t);
1084 break; }
1085 case ldc2w:
1086 state.push(typeForPool(pool.pool[od]));
1087 break;
1088 case instanceof_:
1089 state.pop(1);
1090 state.push(syms.intType);
1091 break;
1092 case ldc2:
1093 state.push(typeForPool(pool.pool[od]));
1094 break;
1095 case jsr:
1096 break;
1097 default:
1098 throw new AssertionError(mnem(op));
1099 }
1100 // postop();
1101 }
1103 /** Emit an opcode with a four-byte operand field.
1104 */
1105 public void emitop4(int op, int od) {
1106 emitop(op);
1107 if (!alive) return;
1108 emit4(od);
1109 switch (op) {
1110 case goto_w:
1111 markDead();
1112 break;
1113 case jsr_w:
1114 break;
1115 default:
1116 throw new AssertionError(mnem(op));
1117 }
1118 // postop();
1119 }
1121 /** Align code pointer to next `incr' boundary.
1122 */
1123 public void align(int incr) {
1124 if (alive)
1125 while (cp % incr != 0) emitop0(nop);
1126 }
1128 /** Place a byte into code at address pc.
1129 * Pre: {@literal pc + 1 <= cp }.
1130 */
1131 private void put1(int pc, int op) {
1132 code[pc] = (byte)op;
1133 }
1135 /** Place two bytes into code at address pc.
1136 * Pre: {@literal pc + 2 <= cp }.
1137 */
1138 private void put2(int pc, int od) {
1139 // pre: pc + 2 <= cp
1140 put1(pc, od >> 8);
1141 put1(pc+1, od);
1142 }
1144 /** Place four bytes into code at address pc.
1145 * Pre: {@literal pc + 4 <= cp }.
1146 */
1147 public void put4(int pc, int od) {
1148 // pre: pc + 4 <= cp
1149 put1(pc , od >> 24);
1150 put1(pc+1, od >> 16);
1151 put1(pc+2, od >> 8);
1152 put1(pc+3, od);
1153 }
1155 /** Return code byte at position pc as an unsigned int.
1156 */
1157 private int get1(int pc) {
1158 return code[pc] & 0xFF;
1159 }
1161 /** Return two code bytes at position pc as an unsigned int.
1162 */
1163 private int get2(int pc) {
1164 return (get1(pc) << 8) | get1(pc+1);
1165 }
1167 /** Return four code bytes at position pc as an int.
1168 */
1169 public int get4(int pc) {
1170 // pre: pc + 4 <= cp
1171 return
1172 (get1(pc) << 24) |
1173 (get1(pc+1) << 16) |
1174 (get1(pc+2) << 8) |
1175 (get1(pc+3));
1176 }
1178 /** Is code generation currently enabled?
1179 */
1180 public boolean isAlive() {
1181 return alive || pendingJumps != null;
1182 }
1184 /** Switch code generation on/off.
1185 */
1186 public void markDead() {
1187 alive = false;
1188 }
1190 /** Declare an entry point; return current code pointer
1191 */
1192 public int entryPoint() {
1193 int pc = curCP();
1194 alive = true;
1195 pendingStackMap = needStackMap;
1196 return pc;
1197 }
1199 /** Declare an entry point with initial state;
1200 * return current code pointer
1201 */
1202 public int entryPoint(State state) {
1203 int pc = curCP();
1204 alive = true;
1205 this.state = state.dup();
1206 Assert.check(state.stacksize <= max_stack);
1207 if (debugCode) System.err.println("entry point " + state);
1208 pendingStackMap = needStackMap;
1209 return pc;
1210 }
1212 /** Declare an entry point with initial state plus a pushed value;
1213 * return current code pointer
1214 */
1215 public int entryPoint(State state, Type pushed) {
1216 int pc = curCP();
1217 alive = true;
1218 this.state = state.dup();
1219 Assert.check(state.stacksize <= max_stack);
1220 this.state.push(pushed);
1221 if (debugCode) System.err.println("entry point " + state);
1222 pendingStackMap = needStackMap;
1223 return pc;
1224 }
1227 /**************************************************************************
1228 * Stack map generation
1229 *************************************************************************/
1231 /** An entry in the stack map. */
1232 static class StackMapFrame {
1233 int pc;
1234 Type[] locals;
1235 Type[] stack;
1236 }
1238 /** A buffer of cldc stack map entries. */
1239 StackMapFrame[] stackMapBuffer = null;
1241 /** A buffer of compressed StackMapTable entries. */
1242 StackMapTableFrame[] stackMapTableBuffer = null;
1243 int stackMapBufferSize = 0;
1245 /** The last PC at which we generated a stack map. */
1246 int lastStackMapPC = -1;
1248 /** The last stack map frame in StackMapTable. */
1249 StackMapFrame lastFrame = null;
1251 /** The stack map frame before the last one. */
1252 StackMapFrame frameBeforeLast = null;
1254 /** Emit a stack map entry. */
1255 public void emitStackMap() {
1256 int pc = curCP();
1257 if (!needStackMap) return;
1261 switch (stackMap) {
1262 case CLDC:
1263 emitCLDCStackMap(pc, getLocalsSize());
1264 break;
1265 case JSR202:
1266 emitStackMapFrame(pc, getLocalsSize());
1267 break;
1268 default:
1269 throw new AssertionError("Should have chosen a stackmap format");
1270 }
1271 // DEBUG code follows
1272 if (debugCode) state.dump(pc);
1273 }
1275 private int getLocalsSize() {
1276 int nextLocal = 0;
1277 for (int i=max_locals-1; i>=0; i--) {
1278 if (state.defined.isMember(i) && lvar[i] != null) {
1279 nextLocal = i + width(lvar[i].sym.erasure(types));
1280 break;
1281 }
1282 }
1283 return nextLocal;
1284 }
1286 /** Emit a CLDC stack map frame. */
1287 void emitCLDCStackMap(int pc, int localsSize) {
1288 if (lastStackMapPC == pc) {
1289 // drop existing stackmap at this offset
1290 stackMapBuffer[--stackMapBufferSize] = null;
1291 }
1292 lastStackMapPC = pc;
1294 if (stackMapBuffer == null) {
1295 stackMapBuffer = new StackMapFrame[20];
1296 } else {
1297 stackMapBuffer = ArrayUtils.ensureCapacity(stackMapBuffer, stackMapBufferSize);
1298 }
1299 StackMapFrame frame =
1300 stackMapBuffer[stackMapBufferSize++] = new StackMapFrame();
1301 frame.pc = pc;
1303 frame.locals = new Type[localsSize];
1304 for (int i=0; i<localsSize; i++) {
1305 if (state.defined.isMember(i) && lvar[i] != null) {
1306 Type vtype = lvar[i].sym.type;
1307 if (!(vtype instanceof UninitializedType))
1308 vtype = types.erasure(vtype);
1309 frame.locals[i] = vtype;
1310 }
1311 }
1312 frame.stack = new Type[state.stacksize];
1313 for (int i=0; i<state.stacksize; i++)
1314 frame.stack[i] = state.stack[i];
1315 }
1317 void emitStackMapFrame(int pc, int localsSize) {
1318 if (lastFrame == null) {
1319 // first frame
1320 lastFrame = getInitialFrame();
1321 } else if (lastFrame.pc == pc) {
1322 // drop existing stackmap at this offset
1323 stackMapTableBuffer[--stackMapBufferSize] = null;
1324 lastFrame = frameBeforeLast;
1325 frameBeforeLast = null;
1326 }
1328 StackMapFrame frame = new StackMapFrame();
1329 frame.pc = pc;
1331 int localCount = 0;
1332 Type[] locals = new Type[localsSize];
1333 for (int i=0; i<localsSize; i++, localCount++) {
1334 if (state.defined.isMember(i) && lvar[i] != null) {
1335 Type vtype = lvar[i].sym.type;
1336 if (!(vtype instanceof UninitializedType))
1337 vtype = types.erasure(vtype);
1338 locals[i] = vtype;
1339 if (width(vtype) > 1) i++;
1340 }
1341 }
1342 frame.locals = new Type[localCount];
1343 for (int i=0, j=0; i<localsSize; i++, j++) {
1344 Assert.check(j < localCount);
1345 frame.locals[j] = locals[i];
1346 if (width(locals[i]) > 1) i++;
1347 }
1349 int stackCount = 0;
1350 for (int i=0; i<state.stacksize; i++) {
1351 if (state.stack[i] != null) {
1352 stackCount++;
1353 }
1354 }
1355 frame.stack = new Type[stackCount];
1356 stackCount = 0;
1357 for (int i=0; i<state.stacksize; i++) {
1358 if (state.stack[i] != null) {
1359 frame.stack[stackCount++] = types.erasure(state.stack[i]);
1360 }
1361 }
1363 if (stackMapTableBuffer == null) {
1364 stackMapTableBuffer = new StackMapTableFrame[20];
1365 } else {
1366 stackMapTableBuffer = ArrayUtils.ensureCapacity(
1367 stackMapTableBuffer,
1368 stackMapBufferSize);
1369 }
1370 stackMapTableBuffer[stackMapBufferSize++] =
1371 StackMapTableFrame.getInstance(frame, lastFrame.pc, lastFrame.locals, types);
1373 frameBeforeLast = lastFrame;
1374 lastFrame = frame;
1375 }
1377 StackMapFrame getInitialFrame() {
1378 StackMapFrame frame = new StackMapFrame();
1379 List<Type> arg_types = ((MethodType)meth.externalType(types)).argtypes;
1380 int len = arg_types.length();
1381 int count = 0;
1382 if (!meth.isStatic()) {
1383 Type thisType = meth.owner.type;
1384 frame.locals = new Type[len+1];
1385 if (meth.isConstructor() && thisType != syms.objectType) {
1386 frame.locals[count++] = UninitializedType.uninitializedThis(thisType);
1387 } else {
1388 frame.locals[count++] = types.erasure(thisType);
1389 }
1390 } else {
1391 frame.locals = new Type[len];
1392 }
1393 for (Type arg_type : arg_types) {
1394 frame.locals[count++] = types.erasure(arg_type);
1395 }
1396 frame.pc = -1;
1397 frame.stack = null;
1398 return frame;
1399 }
1402 /**************************************************************************
1403 * Operations having to do with jumps
1404 *************************************************************************/
1406 /** A chain represents a list of unresolved jumps. Jump locations
1407 * are sorted in decreasing order.
1408 */
1409 public static class Chain {
1411 /** The position of the jump instruction.
1412 */
1413 public final int pc;
1415 /** The machine state after the jump instruction.
1416 * Invariant: all elements of a chain list have the same stacksize
1417 * and compatible stack and register contents.
1418 */
1419 Code.State state;
1421 /** The next jump in the list.
1422 */
1423 public final Chain next;
1425 /** Construct a chain from its jump position, stacksize, previous
1426 * chain, and machine state.
1427 */
1428 public Chain(int pc, Chain next, Code.State state) {
1429 this.pc = pc;
1430 this.next = next;
1431 this.state = state;
1432 }
1433 }
1435 /** Negate a branch opcode.
1436 */
1437 public static int negate(int opcode) {
1438 if (opcode == if_acmp_null) return if_acmp_nonnull;
1439 else if (opcode == if_acmp_nonnull) return if_acmp_null;
1440 else return ((opcode + 1) ^ 1) - 1;
1441 }
1443 /** Emit a jump instruction.
1444 * Return code pointer of instruction to be patched.
1445 */
1446 public int emitJump(int opcode) {
1447 if (fatcode) {
1448 if (opcode == goto_ || opcode == jsr) {
1449 emitop4(opcode + goto_w - goto_, 0);
1450 } else {
1451 emitop2(negate(opcode), 8);
1452 emitop4(goto_w, 0);
1453 alive = true;
1454 pendingStackMap = needStackMap;
1455 }
1456 return cp - 5;
1457 } else {
1458 emitop2(opcode, 0);
1459 return cp - 3;
1460 }
1461 }
1463 /** Emit a branch with given opcode; return its chain.
1464 * branch differs from jump in that jsr is treated as no-op.
1465 */
1466 public Chain branch(int opcode) {
1467 Chain result = null;
1468 if (opcode == goto_) {
1469 result = pendingJumps;
1470 pendingJumps = null;
1471 }
1472 if (opcode != dontgoto && isAlive()) {
1473 result = new Chain(emitJump(opcode),
1474 result,
1475 state.dup());
1476 fixedPc = fatcode;
1477 if (opcode == goto_) alive = false;
1478 }
1479 return result;
1480 }
1482 /** Resolve chain to point to given target.
1483 */
1484 public void resolve(Chain chain, int target) {
1485 boolean changed = false;
1486 State newState = state;
1487 for (; chain != null; chain = chain.next) {
1488 Assert.check(state != chain.state
1489 && (target > chain.pc || state.stacksize == 0));
1490 if (target >= cp) {
1491 target = cp;
1492 } else if (get1(target) == goto_) {
1493 if (fatcode) target = target + get4(target + 1);
1494 else target = target + get2(target + 1);
1495 }
1496 if (get1(chain.pc) == goto_ &&
1497 chain.pc + 3 == target && target == cp && !fixedPc) {
1498 // If goto the next instruction, the jump is not needed:
1499 // compact the code.
1500 if (varDebugInfo) {
1501 adjustAliveRanges(cp, -3);
1502 }
1503 cp = cp - 3;
1504 target = target - 3;
1505 if (chain.next == null) {
1506 // This is the only jump to the target. Exit the loop
1507 // without setting new state. The code is reachable
1508 // from the instruction before goto_.
1509 alive = true;
1510 break;
1511 }
1512 } else {
1513 if (fatcode)
1514 put4(chain.pc + 1, target - chain.pc);
1515 else if (target - chain.pc < Short.MIN_VALUE ||
1516 target - chain.pc > Short.MAX_VALUE)
1517 fatcode = true;
1518 else
1519 put2(chain.pc + 1, target - chain.pc);
1520 Assert.check(!alive ||
1521 chain.state.stacksize == newState.stacksize &&
1522 chain.state.nlocks == newState.nlocks);
1523 }
1524 fixedPc = true;
1525 if (cp == target) {
1526 changed = true;
1527 if (debugCode)
1528 System.err.println("resolving chain state=" + chain.state);
1529 if (alive) {
1530 newState = chain.state.join(newState);
1531 } else {
1532 newState = chain.state;
1533 alive = true;
1534 }
1535 }
1536 }
1537 Assert.check(!changed || state != newState);
1538 if (state != newState) {
1539 setDefined(newState.defined);
1540 state = newState;
1541 pendingStackMap = needStackMap;
1542 }
1543 }
1545 /** Resolve chain to point to current code pointer.
1546 */
1547 public void resolve(Chain chain) {
1548 Assert.check(
1549 !alive ||
1550 chain==null ||
1551 state.stacksize == chain.state.stacksize &&
1552 state.nlocks == chain.state.nlocks);
1553 pendingJumps = mergeChains(chain, pendingJumps);
1554 }
1556 /** Resolve any pending jumps.
1557 */
1558 public void resolvePending() {
1559 Chain x = pendingJumps;
1560 pendingJumps = null;
1561 resolve(x, cp);
1562 }
1564 /** Merge the jumps in of two chains into one.
1565 */
1566 public static Chain mergeChains(Chain chain1, Chain chain2) {
1567 // recursive merge sort
1568 if (chain2 == null) return chain1;
1569 if (chain1 == null) return chain2;
1570 Assert.check(
1571 chain1.state.stacksize == chain2.state.stacksize &&
1572 chain1.state.nlocks == chain2.state.nlocks);
1573 if (chain1.pc < chain2.pc)
1574 return new Chain(
1575 chain2.pc,
1576 mergeChains(chain1, chain2.next),
1577 chain2.state);
1578 return new Chain(
1579 chain1.pc,
1580 mergeChains(chain1.next, chain2),
1581 chain1.state);
1582 }
1585 /* **************************************************************************
1586 * Catch clauses
1587 ****************************************************************************/
1589 /** Add a catch clause to code.
1590 */
1591 public void addCatch(
1592 char startPc, char endPc, char handlerPc, char catchType) {
1593 catchInfo.append(new char[]{startPc, endPc, handlerPc, catchType});
1594 }
1597 public void compressCatchTable() {
1598 ListBuffer<char[]> compressedCatchInfo = new ListBuffer<>();
1599 List<Integer> handlerPcs = List.nil();
1600 for (char[] catchEntry : catchInfo) {
1601 handlerPcs = handlerPcs.prepend((int)catchEntry[2]);
1602 }
1603 for (char[] catchEntry : catchInfo) {
1604 int startpc = catchEntry[0];
1605 int endpc = catchEntry[1];
1606 if (startpc == endpc ||
1607 (startpc == (endpc - 1) &&
1608 handlerPcs.contains(startpc))) {
1609 continue;
1610 } else {
1611 compressedCatchInfo.append(catchEntry);
1612 }
1613 }
1614 catchInfo = compressedCatchInfo;
1615 }
1618 /* **************************************************************************
1619 * Line numbers
1620 ****************************************************************************/
1622 /** Add a line number entry.
1623 */
1624 public void addLineNumber(char startPc, char lineNumber) {
1625 if (lineDebugInfo) {
1626 if (lineInfo.nonEmpty() && lineInfo.head[0] == startPc)
1627 lineInfo = lineInfo.tail;
1628 if (lineInfo.isEmpty() || lineInfo.head[1] != lineNumber)
1629 lineInfo = lineInfo.prepend(new char[]{startPc, lineNumber});
1630 }
1631 }
1633 /** Mark beginning of statement.
1634 */
1635 public void statBegin(int pos) {
1636 if (pos != Position.NOPOS) {
1637 pendingStatPos = pos;
1638 }
1639 }
1641 /** Force stat begin eagerly
1642 */
1643 public void markStatBegin() {
1644 if (alive && lineDebugInfo) {
1645 int line = lineMap.getLineNumber(pendingStatPos);
1646 char cp1 = (char)cp;
1647 char line1 = (char)line;
1648 if (cp1 == cp && line1 == line)
1649 addLineNumber(cp1, line1);
1650 }
1651 pendingStatPos = Position.NOPOS;
1652 }
1655 /* **************************************************************************
1656 * Simulated VM machine state
1657 ****************************************************************************/
1659 class State implements Cloneable {
1660 /** The set of registers containing values. */
1661 Bits defined;
1663 /** The (types of the) contents of the machine stack. */
1664 Type[] stack;
1666 /** The first stack position currently unused. */
1667 int stacksize;
1669 /** The numbers of registers containing locked monitors. */
1670 int[] locks;
1671 int nlocks;
1673 State() {
1674 defined = new Bits();
1675 stack = new Type[16];
1676 }
1678 State dup() {
1679 try {
1680 State state = (State)super.clone();
1681 state.defined = new Bits(defined);
1682 state.stack = stack.clone();
1683 if (locks != null) state.locks = locks.clone();
1684 if (debugCode) {
1685 System.err.println("duping state " + this);
1686 dump();
1687 }
1688 return state;
1689 } catch (CloneNotSupportedException ex) {
1690 throw new AssertionError(ex);
1691 }
1692 }
1694 void lock(int register) {
1695 if (locks == null) {
1696 locks = new int[20];
1697 } else {
1698 locks = ArrayUtils.ensureCapacity(locks, nlocks);
1699 }
1700 locks[nlocks] = register;
1701 nlocks++;
1702 }
1704 void unlock(int register) {
1705 nlocks--;
1706 Assert.check(locks[nlocks] == register);
1707 locks[nlocks] = -1;
1708 }
1710 void push(Type t) {
1711 if (debugCode) System.err.println(" pushing " + t);
1712 switch (t.getTag()) {
1713 case VOID:
1714 return;
1715 case BYTE:
1716 case CHAR:
1717 case SHORT:
1718 case BOOLEAN:
1719 t = syms.intType;
1720 break;
1721 default:
1722 break;
1723 }
1724 stack = ArrayUtils.ensureCapacity(stack, stacksize+2);
1725 stack[stacksize++] = t;
1726 switch (width(t)) {
1727 case 1:
1728 break;
1729 case 2:
1730 stack[stacksize++] = null;
1731 break;
1732 default:
1733 throw new AssertionError(t);
1734 }
1735 if (stacksize > max_stack)
1736 max_stack = stacksize;
1737 }
1739 Type pop1() {
1740 if (debugCode) System.err.println(" popping " + 1);
1741 stacksize--;
1742 Type result = stack[stacksize];
1743 stack[stacksize] = null;
1744 Assert.check(result != null && width(result) == 1);
1745 return result;
1746 }
1748 Type peek() {
1749 return stack[stacksize-1];
1750 }
1752 Type pop2() {
1753 if (debugCode) System.err.println(" popping " + 2);
1754 stacksize -= 2;
1755 Type result = stack[stacksize];
1756 stack[stacksize] = null;
1757 Assert.check(stack[stacksize+1] == null
1758 && result != null && width(result) == 2);
1759 return result;
1760 }
1762 void pop(int n) {
1763 if (debugCode) System.err.println(" popping " + n);
1764 while (n > 0) {
1765 stack[--stacksize] = null;
1766 n--;
1767 }
1768 }
1770 void pop(Type t) {
1771 pop(width(t));
1772 }
1774 /** Force the top of the stack to be treated as this supertype
1775 * of its current type. */
1776 void forceStackTop(Type t) {
1777 if (!alive) return;
1778 switch (t.getTag()) {
1779 case CLASS:
1780 case ARRAY:
1781 int width = width(t);
1782 Type old = stack[stacksize-width];
1783 Assert.check(types.isSubtype(types.erasure(old),
1784 types.erasure(t)));
1785 stack[stacksize-width] = t;
1786 break;
1787 default:
1788 }
1789 }
1791 void markInitialized(UninitializedType old) {
1792 Type newtype = old.initializedType();
1793 for (int i=0; i<stacksize; i++)
1794 if (stack[i] == old) stack[i] = newtype;
1795 for (int i=0; i<lvar.length; i++) {
1796 LocalVar lv = lvar[i];
1797 if (lv != null && lv.sym.type == old) {
1798 VarSymbol sym = lv.sym;
1799 sym = sym.clone(sym.owner);
1800 sym.type = newtype;
1801 LocalVar newlv = lvar[i] = new LocalVar(sym);
1802 newlv.aliveRanges = lv.aliveRanges;
1803 }
1804 }
1805 }
1807 State join(State other) {
1808 defined.andSet(other.defined);
1809 Assert.check(stacksize == other.stacksize
1810 && nlocks == other.nlocks);
1811 for (int i=0; i<stacksize; ) {
1812 Type t = stack[i];
1813 Type tother = other.stack[i];
1814 Type result =
1815 t==tother ? t :
1816 types.isSubtype(t, tother) ? tother :
1817 types.isSubtype(tother, t) ? t :
1818 error();
1819 int w = width(result);
1820 stack[i] = result;
1821 if (w == 2) Assert.checkNull(stack[i+1]);
1822 i += w;
1823 }
1824 return this;
1825 }
1827 Type error() {
1828 throw new AssertionError("inconsistent stack types at join point");
1829 }
1831 void dump() {
1832 dump(-1);
1833 }
1835 void dump(int pc) {
1836 System.err.print("stackMap for " + meth.owner + "." + meth);
1837 if (pc == -1)
1838 System.out.println();
1839 else
1840 System.out.println(" at " + pc);
1841 System.err.println(" stack (from bottom):");
1842 for (int i=0; i<stacksize; i++)
1843 System.err.println(" " + i + ": " + stack[i]);
1845 int lastLocal = 0;
1846 for (int i=max_locals-1; i>=0; i--) {
1847 if (defined.isMember(i)) {
1848 lastLocal = i;
1849 break;
1850 }
1851 }
1852 if (lastLocal >= 0)
1853 System.err.println(" locals:");
1854 for (int i=0; i<=lastLocal; i++) {
1855 System.err.print(" " + i + ": ");
1856 if (defined.isMember(i)) {
1857 LocalVar var = lvar[i];
1858 if (var == null) {
1859 System.err.println("(none)");
1860 } else if (var.sym == null)
1861 System.err.println("UNKNOWN!");
1862 else
1863 System.err.println("" + var.sym + " of type " +
1864 var.sym.erasure(types));
1865 } else {
1866 System.err.println("undefined");
1867 }
1868 }
1869 if (nlocks != 0) {
1870 System.err.print(" locks:");
1871 for (int i=0; i<nlocks; i++) {
1872 System.err.print(" " + locks[i]);
1873 }
1874 System.err.println();
1875 }
1876 }
1877 }
1879 static final Type jsrReturnValue = new JCPrimitiveType(INT, null);
1882 /* **************************************************************************
1883 * Local variables
1884 ****************************************************************************/
1886 /** A live range of a local variable. */
1887 static class LocalVar {
1888 final VarSymbol sym;
1889 final char reg;
1891 class Range {
1892 char start_pc = Character.MAX_VALUE;
1893 char length = Character.MAX_VALUE;
1895 Range() {}
1897 Range(char start) {
1898 this.start_pc = start;
1899 }
1901 Range(char start, char length) {
1902 this.start_pc = start;
1903 this.length = length;
1904 }
1906 boolean closed() {
1907 return start_pc != Character.MAX_VALUE && length != Character.MAX_VALUE;
1908 }
1910 @Override
1911 public String toString() {
1912 int currentStartPC = start_pc;
1913 int currentLength = length;
1914 return "startpc = " + currentStartPC + " length " + currentLength;
1915 }
1916 }
1918 java.util.List<Range> aliveRanges = new java.util.ArrayList<>();
1920 LocalVar(VarSymbol v) {
1921 this.sym = v;
1922 this.reg = (char)v.adr;
1923 }
1924 public LocalVar dup() {
1925 return new LocalVar(sym);
1926 }
1928 Range firstRange() {
1929 return aliveRanges.isEmpty() ? null : aliveRanges.get(0);
1930 }
1932 Range lastRange() {
1933 return aliveRanges.isEmpty() ? null : aliveRanges.get(aliveRanges.size() - 1);
1934 }
1936 @Override
1937 public String toString() {
1938 if (aliveRanges == null) {
1939 return "empty local var";
1940 }
1941 StringBuilder sb = new StringBuilder().append(sym)
1942 .append(" in register ").append((int)reg).append(" \n");
1943 for (Range r : aliveRanges) {
1944 sb.append(" starts at pc=").append(Integer.toString(((int)r.start_pc)))
1945 .append(" length=").append(Integer.toString(((int)r.length)))
1946 .append("\n");
1947 }
1948 return sb.toString();
1949 }
1951 public void openRange(char start) {
1952 if (!hasOpenRange()) {
1953 aliveRanges.add(new Range(start));
1954 }
1955 }
1957 public void closeRange(char end) {
1958 if (isLastRangeInitialized()) {
1959 Range range = lastRange();
1960 if (range != null) {
1961 if (range.length == Character.MAX_VALUE) {
1962 range.length = end;
1963 }
1964 }
1965 } else {
1966 if (!aliveRanges.isEmpty()) {
1967 aliveRanges.remove(aliveRanges.size() - 1);
1968 }
1969 }
1970 }
1972 public boolean hasOpenRange() {
1973 if (aliveRanges.isEmpty()) {
1974 return false;
1975 }
1976 Range range = lastRange();
1977 return range.length == Character.MAX_VALUE;
1978 }
1980 public boolean isLastRangeInitialized() {
1981 if (aliveRanges.isEmpty()) {
1982 return false;
1983 }
1984 Range range = lastRange();
1985 return range.start_pc != Character.MAX_VALUE;
1986 }
1988 public Range getWidestRange() {
1989 if (aliveRanges.isEmpty()) {
1990 return new Range();
1991 } else {
1992 Range firstRange = firstRange();
1993 Range lastRange = lastRange();
1994 char length = (char)(lastRange.length + (lastRange.start_pc - firstRange.start_pc));
1995 return new Range(firstRange.start_pc, length);
1996 }
1997 }
1999 };
2001 /** Local variables, indexed by register. */
2002 LocalVar[] lvar;
2004 /** Add a new local variable. */
2005 private void addLocalVar(VarSymbol v) {
2006 int adr = v.adr;
2007 lvar = ArrayUtils.ensureCapacity(lvar, adr+1);
2008 Assert.checkNull(lvar[adr]);
2009 if (pendingJumps != null) {
2010 resolvePending();
2011 }
2012 lvar[adr] = new LocalVar(v);
2013 state.defined.excl(adr);
2014 }
2017 public void closeAliveRanges(JCTree tree) {
2018 closeAliveRanges(tree, cp);
2019 }
2021 public void closeAliveRanges(JCTree tree, int closingCP) {
2022 List<VarSymbol> locals = lvtRanges.getVars(meth, tree);
2023 for (LocalVar localVar: lvar) {
2024 for (VarSymbol aliveLocal : locals) {
2025 if (localVar == null) {
2026 return;
2027 }
2028 if (localVar.sym == aliveLocal && localVar.lastRange() != null) {
2029 char length = (char)(closingCP - localVar.lastRange().start_pc);
2030 if (length > 0 && length < Character.MAX_VALUE) {
2031 localVar.closeRange(length);
2032 }
2033 }
2034 }
2035 }
2036 }
2038 void adjustAliveRanges(int oldCP, int delta) {
2039 for (LocalVar localVar: lvar) {
2040 if (localVar == null) {
2041 return;
2042 }
2043 for (LocalVar.Range range: localVar.aliveRanges) {
2044 if (range.closed() && range.start_pc + range.length >= oldCP) {
2045 range.length += delta;
2046 }
2047 }
2048 }
2049 }
2051 /**
2052 * Calculates the size of the LocalVariableTable.
2053 */
2054 public int getLVTSize() {
2055 int result = varBufferSize;
2056 for (int i = 0; i < varBufferSize; i++) {
2057 LocalVar var = varBuffer[i];
2058 result += var.aliveRanges.size() - 1;
2059 }
2060 return result;
2061 }
2063 /** Set the current variable defined state. */
2064 public void setDefined(Bits newDefined) {
2065 if (alive && newDefined != state.defined) {
2066 Bits diff = new Bits(state.defined).xorSet(newDefined);
2067 for (int adr = diff.nextBit(0);
2068 adr >= 0;
2069 adr = diff.nextBit(adr+1)) {
2070 if (adr >= nextreg)
2071 state.defined.excl(adr);
2072 else if (state.defined.isMember(adr))
2073 setUndefined(adr);
2074 else
2075 setDefined(adr);
2076 }
2077 }
2078 }
2080 /** Mark a register as being (possibly) defined. */
2081 public void setDefined(int adr) {
2082 LocalVar v = lvar[adr];
2083 if (v == null) {
2084 state.defined.excl(adr);
2085 } else {
2086 state.defined.incl(adr);
2087 if (cp < Character.MAX_VALUE) {
2088 v.openRange((char)cp);
2089 }
2090 }
2091 }
2093 /** Mark a register as being undefined. */
2094 public void setUndefined(int adr) {
2095 state.defined.excl(adr);
2096 if (adr < lvar.length &&
2097 lvar[adr] != null &&
2098 lvar[adr].isLastRangeInitialized()) {
2099 LocalVar v = lvar[adr];
2100 char length = (char)(curCP() - v.lastRange().start_pc);
2101 if (length > 0 && length < Character.MAX_VALUE) {
2102 lvar[adr] = v.dup();
2103 v.closeRange(length);
2104 putVar(v);
2105 } else {
2106 v.lastRange().start_pc = Character.MAX_VALUE;
2107 }
2108 }
2109 }
2111 /** End the scope of a variable. */
2112 private void endScope(int adr) {
2113 LocalVar v = lvar[adr];
2114 if (v != null) {
2115 lvar[adr] = null;
2116 if (v.isLastRangeInitialized()) {
2117 char length = (char)(curCP() - v.lastRange().start_pc);
2118 if (length < Character.MAX_VALUE) {
2119 v.closeRange(length);
2120 putVar(v);
2121 fillLocalVarPosition(v);
2122 }
2123 }
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 if (!varDebugInfo &&
2196 (!var.sym.isExceptionParameter() ||
2197 var.sym.hasTypeAnnotations())) 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 }