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