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