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