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