Mon, 21 Jan 2013 20:15:16 +0000
8005851: Remove support for synchronized interface methods
Summary: Synchronized default methods are no longer supported
Reviewed-by: jjg
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.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 multinewarray instruction.
377 */
378 public void emitMultianewarray(int ndims, int type, Type arrayType) {
379 emitop(multianewarray);
380 if (!alive) return;
381 emit2(type);
382 emit1(ndims);
383 state.pop(ndims);
384 state.push(arrayType);
385 }
387 /** Emit newarray.
388 */
389 public void emitNewarray(int elemcode, Type arrayType) {
390 emitop(newarray);
391 if (!alive) return;
392 emit1(elemcode);
393 state.pop(1); // count
394 state.push(arrayType);
395 }
397 /** Emit anewarray.
398 */
399 public void emitAnewarray(int od, Type arrayType) {
400 emitop(anewarray);
401 if (!alive) return;
402 emit2(od);
403 state.pop(1);
404 state.push(arrayType);
405 }
407 /** Emit an invokeinterface instruction.
408 */
409 public void emitInvokeinterface(int meth, Type mtype) {
410 int argsize = width(mtype.getParameterTypes());
411 emitop(invokeinterface);
412 if (!alive) return;
413 emit2(meth);
414 emit1(argsize + 1);
415 emit1(0);
416 state.pop(argsize + 1);
417 state.push(mtype.getReturnType());
418 }
420 /** Emit an invokespecial instruction.
421 */
422 public void emitInvokespecial(int meth, Type mtype) {
423 int argsize = width(mtype.getParameterTypes());
424 emitop(invokespecial);
425 if (!alive) return;
426 emit2(meth);
427 Symbol sym = (Symbol)pool.pool[meth];
428 state.pop(argsize);
429 if (sym.isConstructor())
430 state.markInitialized((UninitializedType)state.peek());
431 state.pop(1);
432 state.push(mtype.getReturnType());
433 }
435 /** Emit an invokestatic instruction.
436 */
437 public void emitInvokestatic(int meth, Type mtype) {
438 int argsize = width(mtype.getParameterTypes());
439 emitop(invokestatic);
440 if (!alive) return;
441 emit2(meth);
442 state.pop(argsize);
443 state.push(mtype.getReturnType());
444 }
446 /** Emit an invokevirtual instruction.
447 */
448 public void emitInvokevirtual(int meth, Type mtype) {
449 int argsize = width(mtype.getParameterTypes());
450 emitop(invokevirtual);
451 if (!alive) return;
452 emit2(meth);
453 state.pop(argsize + 1);
454 state.push(mtype.getReturnType());
455 }
457 /** Emit an invokedynamic instruction.
458 */
459 public void emitInvokedynamic(int desc, Type mtype) {
460 // N.B. this format is under consideration by the JSR 292 EG
461 int argsize = width(mtype.getParameterTypes());
462 emitop(invokedynamic);
463 if (!alive) return;
464 emit2(desc);
465 emit2(0);
466 state.pop(argsize);
467 state.push(mtype.getReturnType());
468 }
470 /** Emit an opcode with no operand field.
471 */
472 public void emitop0(int op) {
473 emitop(op);
474 if (!alive) return;
475 switch (op) {
476 case aaload: {
477 state.pop(1);// index
478 Type a = state.stack[state.stacksize-1];
479 state.pop(1);
480 //sometimes 'null type' is treated as a one-dimensional array type
481 //see Gen.visitLiteral - we should handle this case accordingly
482 Type stackType = a.hasTag(BOT) ?
483 syms.objectType :
484 types.erasure(types.elemtype(a));
485 state.push(stackType); }
486 break;
487 case goto_:
488 markDead();
489 break;
490 case nop:
491 case ineg:
492 case lneg:
493 case fneg:
494 case dneg:
495 break;
496 case aconst_null:
497 state.push(syms.botType);
498 break;
499 case iconst_m1:
500 case iconst_0:
501 case iconst_1:
502 case iconst_2:
503 case iconst_3:
504 case iconst_4:
505 case iconst_5:
506 case iload_0:
507 case iload_1:
508 case iload_2:
509 case iload_3:
510 state.push(syms.intType);
511 break;
512 case lconst_0:
513 case lconst_1:
514 case lload_0:
515 case lload_1:
516 case lload_2:
517 case lload_3:
518 state.push(syms.longType);
519 break;
520 case fconst_0:
521 case fconst_1:
522 case fconst_2:
523 case fload_0:
524 case fload_1:
525 case fload_2:
526 case fload_3:
527 state.push(syms.floatType);
528 break;
529 case dconst_0:
530 case dconst_1:
531 case dload_0:
532 case dload_1:
533 case dload_2:
534 case dload_3:
535 state.push(syms.doubleType);
536 break;
537 case aload_0:
538 state.push(lvar[0].sym.type);
539 break;
540 case aload_1:
541 state.push(lvar[1].sym.type);
542 break;
543 case aload_2:
544 state.push(lvar[2].sym.type);
545 break;
546 case aload_3:
547 state.push(lvar[3].sym.type);
548 break;
549 case iaload:
550 case baload:
551 case caload:
552 case saload:
553 state.pop(2);
554 state.push(syms.intType);
555 break;
556 case laload:
557 state.pop(2);
558 state.push(syms.longType);
559 break;
560 case faload:
561 state.pop(2);
562 state.push(syms.floatType);
563 break;
564 case daload:
565 state.pop(2);
566 state.push(syms.doubleType);
567 break;
568 case istore_0:
569 case istore_1:
570 case istore_2:
571 case istore_3:
572 case fstore_0:
573 case fstore_1:
574 case fstore_2:
575 case fstore_3:
576 case astore_0:
577 case astore_1:
578 case astore_2:
579 case astore_3:
580 case pop:
581 case lshr:
582 case lshl:
583 case lushr:
584 state.pop(1);
585 break;
586 case areturn:
587 case ireturn:
588 case freturn:
589 Assert.check(state.nlocks == 0);
590 state.pop(1);
591 markDead();
592 break;
593 case athrow:
594 state.pop(1);
595 markDead();
596 break;
597 case lstore_0:
598 case lstore_1:
599 case lstore_2:
600 case lstore_3:
601 case dstore_0:
602 case dstore_1:
603 case dstore_2:
604 case dstore_3:
605 case pop2:
606 state.pop(2);
607 break;
608 case lreturn:
609 case dreturn:
610 Assert.check(state.nlocks == 0);
611 state.pop(2);
612 markDead();
613 break;
614 case dup:
615 state.push(state.stack[state.stacksize-1]);
616 break;
617 case return_:
618 Assert.check(state.nlocks == 0);
619 markDead();
620 break;
621 case arraylength:
622 state.pop(1);
623 state.push(syms.intType);
624 break;
625 case isub:
626 case iadd:
627 case imul:
628 case idiv:
629 case imod:
630 case ishl:
631 case ishr:
632 case iushr:
633 case iand:
634 case ior:
635 case ixor:
636 state.pop(1);
637 // state.pop(1);
638 // state.push(syms.intType);
639 break;
640 case aastore:
641 state.pop(3);
642 break;
643 case land:
644 case lor:
645 case lxor:
646 case lmod:
647 case ldiv:
648 case lmul:
649 case lsub:
650 case ladd:
651 state.pop(2);
652 break;
653 case lcmp:
654 state.pop(4);
655 state.push(syms.intType);
656 break;
657 case l2i:
658 state.pop(2);
659 state.push(syms.intType);
660 break;
661 case i2l:
662 state.pop(1);
663 state.push(syms.longType);
664 break;
665 case i2f:
666 state.pop(1);
667 state.push(syms.floatType);
668 break;
669 case i2d:
670 state.pop(1);
671 state.push(syms.doubleType);
672 break;
673 case l2f:
674 state.pop(2);
675 state.push(syms.floatType);
676 break;
677 case l2d:
678 state.pop(2);
679 state.push(syms.doubleType);
680 break;
681 case f2i:
682 state.pop(1);
683 state.push(syms.intType);
684 break;
685 case f2l:
686 state.pop(1);
687 state.push(syms.longType);
688 break;
689 case f2d:
690 state.pop(1);
691 state.push(syms.doubleType);
692 break;
693 case d2i:
694 state.pop(2);
695 state.push(syms.intType);
696 break;
697 case d2l:
698 state.pop(2);
699 state.push(syms.longType);
700 break;
701 case d2f:
702 state.pop(2);
703 state.push(syms.floatType);
704 break;
705 case tableswitch:
706 case lookupswitch:
707 state.pop(1);
708 // the caller is responsible for patching up the state
709 break;
710 case dup_x1: {
711 Type val1 = state.pop1();
712 Type val2 = state.pop1();
713 state.push(val1);
714 state.push(val2);
715 state.push(val1);
716 break;
717 }
718 case bastore:
719 state.pop(3);
720 break;
721 case int2byte:
722 case int2char:
723 case int2short:
724 break;
725 case fmul:
726 case fadd:
727 case fsub:
728 case fdiv:
729 case fmod:
730 state.pop(1);
731 break;
732 case castore:
733 case iastore:
734 case fastore:
735 case sastore:
736 state.pop(3);
737 break;
738 case lastore:
739 case dastore:
740 state.pop(4);
741 break;
742 case dup2:
743 if (state.stack[state.stacksize-1] != null) {
744 Type value1 = state.pop1();
745 Type value2 = state.pop1();
746 state.push(value2);
747 state.push(value1);
748 state.push(value2);
749 state.push(value1);
750 } else {
751 Type value = state.pop2();
752 state.push(value);
753 state.push(value);
754 }
755 break;
756 case dup2_x1:
757 if (state.stack[state.stacksize-1] != null) {
758 Type value1 = state.pop1();
759 Type value2 = state.pop1();
760 Type value3 = state.pop1();
761 state.push(value2);
762 state.push(value1);
763 state.push(value3);
764 state.push(value2);
765 state.push(value1);
766 } else {
767 Type value1 = state.pop2();
768 Type value2 = state.pop1();
769 state.push(value1);
770 state.push(value2);
771 state.push(value1);
772 }
773 break;
774 case dup2_x2:
775 if (state.stack[state.stacksize-1] != null) {
776 Type value1 = state.pop1();
777 Type value2 = state.pop1();
778 if (state.stack[state.stacksize-1] != null) {
779 // form 1
780 Type value3 = state.pop1();
781 Type value4 = state.pop1();
782 state.push(value2);
783 state.push(value1);
784 state.push(value4);
785 state.push(value3);
786 state.push(value2);
787 state.push(value1);
788 } else {
789 // form 3
790 Type value3 = state.pop2();
791 state.push(value2);
792 state.push(value1);
793 state.push(value3);
794 state.push(value2);
795 state.push(value1);
796 }
797 } else {
798 Type value1 = state.pop2();
799 if (state.stack[state.stacksize-1] != null) {
800 // form 2
801 Type value2 = state.pop1();
802 Type value3 = state.pop1();
803 state.push(value1);
804 state.push(value3);
805 state.push(value2);
806 state.push(value1);
807 } else {
808 // form 4
809 Type value2 = state.pop2();
810 state.push(value1);
811 state.push(value2);
812 state.push(value1);
813 }
814 }
815 break;
816 case dup_x2: {
817 Type value1 = state.pop1();
818 if (state.stack[state.stacksize-1] != null) {
819 // form 1
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 2
828 Type value2 = state.pop2();
829 state.push(value1);
830 state.push(value2);
831 state.push(value1);
832 }
833 }
834 break;
835 case fcmpl:
836 case fcmpg:
837 state.pop(2);
838 state.push(syms.intType);
839 break;
840 case dcmpl:
841 case dcmpg:
842 state.pop(4);
843 state.push(syms.intType);
844 break;
845 case swap: {
846 Type value1 = state.pop1();
847 Type value2 = state.pop1();
848 state.push(value1);
849 state.push(value2);
850 break;
851 }
852 case dadd:
853 case dsub:
854 case dmul:
855 case ddiv:
856 case dmod:
857 state.pop(2);
858 break;
859 case ret:
860 markDead();
861 break;
862 case wide:
863 // must be handled by the caller.
864 return;
865 case monitorenter:
866 case monitorexit:
867 state.pop(1);
868 break;
870 default:
871 throw new AssertionError(mnem(op));
872 }
873 postop();
874 }
876 /** Emit an opcode with a one-byte operand field.
877 */
878 public void emitop1(int op, int od) {
879 emitop(op);
880 if (!alive) return;
881 emit1(od);
882 switch (op) {
883 case bipush:
884 state.push(syms.intType);
885 break;
886 case ldc1:
887 state.push(typeForPool(pool.pool[od]));
888 break;
889 default:
890 throw new AssertionError(mnem(op));
891 }
892 postop();
893 }
895 /** The type of a constant pool entry. */
896 private Type typeForPool(Object o) {
897 if (o instanceof Integer) return syms.intType;
898 if (o instanceof Float) return syms.floatType;
899 if (o instanceof String) return syms.stringType;
900 if (o instanceof Long) return syms.longType;
901 if (o instanceof Double) return syms.doubleType;
902 if (o instanceof ClassSymbol) return syms.classType;
903 if (o instanceof Type.ArrayType) return syms.classType;
904 if (o instanceof Type.MethodType) return syms.methodTypeType;
905 if (o instanceof UniqueType) return typeForPool(((UniqueType)o).type);
906 if (o instanceof Pool.MethodHandle) return syms.methodHandleType;
907 throw new AssertionError(o);
908 }
910 /** Emit an opcode with a one-byte operand field;
911 * widen if field does not fit in a byte.
912 */
913 public void emitop1w(int op, int od) {
914 if (od > 0xFF) {
915 emitop(wide);
916 emitop(op);
917 emit2(od);
918 } else {
919 emitop(op);
920 emit1(od);
921 }
922 if (!alive) return;
923 switch (op) {
924 case iload:
925 state.push(syms.intType);
926 break;
927 case lload:
928 state.push(syms.longType);
929 break;
930 case fload:
931 state.push(syms.floatType);
932 break;
933 case dload:
934 state.push(syms.doubleType);
935 break;
936 case aload:
937 state.push(lvar[od].sym.type);
938 break;
939 case lstore:
940 case dstore:
941 state.pop(2);
942 break;
943 case istore:
944 case fstore:
945 case astore:
946 state.pop(1);
947 break;
948 case ret:
949 markDead();
950 break;
951 default:
952 throw new AssertionError(mnem(op));
953 }
954 postop();
955 }
957 /** Emit an opcode with two one-byte operand fields;
958 * widen if either field does not fit in a byte.
959 */
960 public void emitop1w(int op, int od1, int od2) {
961 if (od1 > 0xFF || od2 < -128 || od2 > 127) {
962 emitop(wide);
963 emitop(op);
964 emit2(od1);
965 emit2(od2);
966 } else {
967 emitop(op);
968 emit1(od1);
969 emit1(od2);
970 }
971 if (!alive) return;
972 switch (op) {
973 case iinc:
974 break;
975 default:
976 throw new AssertionError(mnem(op));
977 }
978 }
980 /** Emit an opcode with a two-byte operand field.
981 */
982 public void emitop2(int op, int od) {
983 emitop(op);
984 if (!alive) return;
985 emit2(od);
986 switch (op) {
987 case getstatic:
988 state.push(((Symbol)(pool.pool[od])).erasure(types));
989 break;
990 case putstatic:
991 state.pop(((Symbol)(pool.pool[od])).erasure(types));
992 break;
993 case new_:
994 state.push(uninitializedObject(((Symbol)(pool.pool[od])).erasure(types), cp-3));
995 break;
996 case sipush:
997 state.push(syms.intType);
998 break;
999 case if_acmp_null:
1000 case if_acmp_nonnull:
1001 case ifeq:
1002 case ifne:
1003 case iflt:
1004 case ifge:
1005 case ifgt:
1006 case ifle:
1007 state.pop(1);
1008 break;
1009 case if_icmpeq:
1010 case if_icmpne:
1011 case if_icmplt:
1012 case if_icmpge:
1013 case if_icmpgt:
1014 case if_icmple:
1015 case if_acmpeq:
1016 case if_acmpne:
1017 state.pop(2);
1018 break;
1019 case goto_:
1020 markDead();
1021 break;
1022 case putfield:
1023 state.pop(((Symbol)(pool.pool[od])).erasure(types));
1024 state.pop(1); // object ref
1025 break;
1026 case getfield:
1027 state.pop(1); // object ref
1028 state.push(((Symbol)(pool.pool[od])).erasure(types));
1029 break;
1030 case checkcast: {
1031 state.pop(1); // object ref
1032 Object o = pool.pool[od];
1033 Type t = (o instanceof Symbol)
1034 ? ((Symbol)o).erasure(types)
1035 : types.erasure((((UniqueType)o).type));
1036 state.push(t);
1037 break; }
1038 case ldc2w:
1039 state.push(typeForPool(pool.pool[od]));
1040 break;
1041 case instanceof_:
1042 state.pop(1);
1043 state.push(syms.intType);
1044 break;
1045 case ldc2:
1046 state.push(typeForPool(pool.pool[od]));
1047 break;
1048 case jsr:
1049 break;
1050 default:
1051 throw new AssertionError(mnem(op));
1052 }
1053 // postop();
1054 }
1056 /** Emit an opcode with a four-byte operand field.
1057 */
1058 public void emitop4(int op, int od) {
1059 emitop(op);
1060 if (!alive) return;
1061 emit4(od);
1062 switch (op) {
1063 case goto_w:
1064 markDead();
1065 break;
1066 case jsr_w:
1067 break;
1068 default:
1069 throw new AssertionError(mnem(op));
1070 }
1071 // postop();
1072 }
1074 /** Align code pointer to next `incr' boundary.
1075 */
1076 public void align(int incr) {
1077 if (alive)
1078 while (cp % incr != 0) emitop0(nop);
1079 }
1081 /** Place a byte into code at address pc.
1082 * Pre: {@literal pc + 1 <= cp }.
1083 */
1084 private void put1(int pc, int op) {
1085 code[pc] = (byte)op;
1086 }
1088 /** Place two bytes into code at address pc.
1089 * Pre: {@literal pc + 2 <= cp }.
1090 */
1091 private void put2(int pc, int od) {
1092 // pre: pc + 2 <= cp
1093 put1(pc, od >> 8);
1094 put1(pc+1, od);
1095 }
1097 /** Place four bytes into code at address pc.
1098 * Pre: {@literal pc + 4 <= cp }.
1099 */
1100 public void put4(int pc, int od) {
1101 // pre: pc + 4 <= cp
1102 put1(pc , od >> 24);
1103 put1(pc+1, od >> 16);
1104 put1(pc+2, od >> 8);
1105 put1(pc+3, od);
1106 }
1108 /** Return code byte at position pc as an unsigned int.
1109 */
1110 private int get1(int pc) {
1111 return code[pc] & 0xFF;
1112 }
1114 /** Return two code bytes at position pc as an unsigned int.
1115 */
1116 private int get2(int pc) {
1117 return (get1(pc) << 8) | get1(pc+1);
1118 }
1120 /** Return four code bytes at position pc as an int.
1121 */
1122 public int get4(int pc) {
1123 // pre: pc + 4 <= cp
1124 return
1125 (get1(pc) << 24) |
1126 (get1(pc+1) << 16) |
1127 (get1(pc+2) << 8) |
1128 (get1(pc+3));
1129 }
1131 /** Is code generation currently enabled?
1132 */
1133 public boolean isAlive() {
1134 return alive || pendingJumps != null;
1135 }
1137 /** Switch code generation on/off.
1138 */
1139 public void markDead() {
1140 alive = false;
1141 }
1143 /** Declare an entry point; return current code pointer
1144 */
1145 public int entryPoint() {
1146 int pc = curPc();
1147 alive = true;
1148 pendingStackMap = needStackMap;
1149 return pc;
1150 }
1152 /** Declare an entry point with initial state;
1153 * return current code pointer
1154 */
1155 public int entryPoint(State state) {
1156 int pc = curPc();
1157 alive = true;
1158 this.state = state.dup();
1159 Assert.check(state.stacksize <= max_stack);
1160 if (debugCode) System.err.println("entry point " + state);
1161 pendingStackMap = needStackMap;
1162 return pc;
1163 }
1165 /** Declare an entry point with initial state plus a pushed value;
1166 * return current code pointer
1167 */
1168 public int entryPoint(State state, Type pushed) {
1169 int pc = curPc();
1170 alive = true;
1171 this.state = state.dup();
1172 Assert.check(state.stacksize <= max_stack);
1173 this.state.push(pushed);
1174 if (debugCode) System.err.println("entry point " + state);
1175 pendingStackMap = needStackMap;
1176 return pc;
1177 }
1180 /**************************************************************************
1181 * Stack map generation
1182 *************************************************************************/
1184 /** An entry in the stack map. */
1185 static class StackMapFrame {
1186 int pc;
1187 Type[] locals;
1188 Type[] stack;
1189 }
1191 /** A buffer of cldc stack map entries. */
1192 StackMapFrame[] stackMapBuffer = null;
1194 /** A buffer of compressed StackMapTable entries. */
1195 StackMapTableFrame[] stackMapTableBuffer = null;
1196 int stackMapBufferSize = 0;
1198 /** The last PC at which we generated a stack map. */
1199 int lastStackMapPC = -1;
1201 /** The last stack map frame in StackMapTable. */
1202 StackMapFrame lastFrame = null;
1204 /** The stack map frame before the last one. */
1205 StackMapFrame frameBeforeLast = null;
1207 /** Emit a stack map entry. */
1208 public void emitStackMap() {
1209 int pc = curPc();
1210 if (!needStackMap) return;
1214 switch (stackMap) {
1215 case CLDC:
1216 emitCLDCStackMap(pc, getLocalsSize());
1217 break;
1218 case JSR202:
1219 emitStackMapFrame(pc, getLocalsSize());
1220 break;
1221 default:
1222 throw new AssertionError("Should have chosen a stackmap format");
1223 }
1224 // DEBUG code follows
1225 if (debugCode) state.dump(pc);
1226 }
1228 private int getLocalsSize() {
1229 int nextLocal = 0;
1230 for (int i=max_locals-1; i>=0; i--) {
1231 if (state.defined.isMember(i) && lvar[i] != null) {
1232 nextLocal = i + width(lvar[i].sym.erasure(types));
1233 break;
1234 }
1235 }
1236 return nextLocal;
1237 }
1239 /** Emit a CLDC stack map frame. */
1240 void emitCLDCStackMap(int pc, int localsSize) {
1241 if (lastStackMapPC == pc) {
1242 // drop existing stackmap at this offset
1243 stackMapBuffer[--stackMapBufferSize] = null;
1244 }
1245 lastStackMapPC = pc;
1247 if (stackMapBuffer == null) {
1248 stackMapBuffer = new StackMapFrame[20];
1249 } else {
1250 stackMapBuffer = ArrayUtils.ensureCapacity(stackMapBuffer, stackMapBufferSize);
1251 }
1252 StackMapFrame frame =
1253 stackMapBuffer[stackMapBufferSize++] = new StackMapFrame();
1254 frame.pc = pc;
1256 frame.locals = new Type[localsSize];
1257 for (int i=0; i<localsSize; i++) {
1258 if (state.defined.isMember(i) && lvar[i] != null) {
1259 Type vtype = lvar[i].sym.type;
1260 if (!(vtype instanceof UninitializedType))
1261 vtype = types.erasure(vtype);
1262 frame.locals[i] = vtype;
1263 }
1264 }
1265 frame.stack = new Type[state.stacksize];
1266 for (int i=0; i<state.stacksize; i++)
1267 frame.stack[i] = state.stack[i];
1268 }
1270 void emitStackMapFrame(int pc, int localsSize) {
1271 if (lastFrame == null) {
1272 // first frame
1273 lastFrame = getInitialFrame();
1274 } else if (lastFrame.pc == pc) {
1275 // drop existing stackmap at this offset
1276 stackMapTableBuffer[--stackMapBufferSize] = null;
1277 lastFrame = frameBeforeLast;
1278 frameBeforeLast = null;
1279 }
1281 StackMapFrame frame = new StackMapFrame();
1282 frame.pc = pc;
1284 int localCount = 0;
1285 Type[] locals = new Type[localsSize];
1286 for (int i=0; i<localsSize; i++, localCount++) {
1287 if (state.defined.isMember(i) && lvar[i] != null) {
1288 Type vtype = lvar[i].sym.type;
1289 if (!(vtype instanceof UninitializedType))
1290 vtype = types.erasure(vtype);
1291 locals[i] = vtype;
1292 if (width(vtype) > 1) i++;
1293 }
1294 }
1295 frame.locals = new Type[localCount];
1296 for (int i=0, j=0; i<localsSize; i++, j++) {
1297 Assert.check(j < localCount);
1298 frame.locals[j] = locals[i];
1299 if (width(locals[i]) > 1) i++;
1300 }
1302 int stackCount = 0;
1303 for (int i=0; i<state.stacksize; i++) {
1304 if (state.stack[i] != null) {
1305 stackCount++;
1306 }
1307 }
1308 frame.stack = new Type[stackCount];
1309 stackCount = 0;
1310 for (int i=0; i<state.stacksize; i++) {
1311 if (state.stack[i] != null) {
1312 frame.stack[stackCount++] = types.erasure(state.stack[i]);
1313 }
1314 }
1316 if (stackMapTableBuffer == null) {
1317 stackMapTableBuffer = new StackMapTableFrame[20];
1318 } else {
1319 stackMapTableBuffer = ArrayUtils.ensureCapacity(
1320 stackMapTableBuffer,
1321 stackMapBufferSize);
1322 }
1323 stackMapTableBuffer[stackMapBufferSize++] =
1324 StackMapTableFrame.getInstance(frame, lastFrame.pc, lastFrame.locals, types);
1326 frameBeforeLast = lastFrame;
1327 lastFrame = frame;
1328 }
1330 StackMapFrame getInitialFrame() {
1331 StackMapFrame frame = new StackMapFrame();
1332 List<Type> arg_types = ((MethodType)meth.externalType(types)).argtypes;
1333 int len = arg_types.length();
1334 int count = 0;
1335 if (!meth.isStatic()) {
1336 Type thisType = meth.owner.type;
1337 frame.locals = new Type[len+1];
1338 if (meth.isConstructor() && thisType != syms.objectType) {
1339 frame.locals[count++] = UninitializedType.uninitializedThis(thisType);
1340 } else {
1341 frame.locals[count++] = types.erasure(thisType);
1342 }
1343 } else {
1344 frame.locals = new Type[len];
1345 }
1346 for (Type arg_type : arg_types) {
1347 frame.locals[count++] = types.erasure(arg_type);
1348 }
1349 frame.pc = -1;
1350 frame.stack = null;
1351 return frame;
1352 }
1355 /**************************************************************************
1356 * Operations having to do with jumps
1357 *************************************************************************/
1359 /** A chain represents a list of unresolved jumps. Jump locations
1360 * are sorted in decreasing order.
1361 */
1362 public static class Chain {
1364 /** The position of the jump instruction.
1365 */
1366 public final int pc;
1368 /** The machine state after the jump instruction.
1369 * Invariant: all elements of a chain list have the same stacksize
1370 * and compatible stack and register contents.
1371 */
1372 Code.State state;
1374 /** The next jump in the list.
1375 */
1376 public final Chain next;
1378 /** Construct a chain from its jump position, stacksize, previous
1379 * chain, and machine state.
1380 */
1381 public Chain(int pc, Chain next, Code.State state) {
1382 this.pc = pc;
1383 this.next = next;
1384 this.state = state;
1385 }
1386 }
1388 /** Negate a branch opcode.
1389 */
1390 public static int negate(int opcode) {
1391 if (opcode == if_acmp_null) return if_acmp_nonnull;
1392 else if (opcode == if_acmp_nonnull) return if_acmp_null;
1393 else return ((opcode + 1) ^ 1) - 1;
1394 }
1396 /** Emit a jump instruction.
1397 * Return code pointer of instruction to be patched.
1398 */
1399 public int emitJump(int opcode) {
1400 if (fatcode) {
1401 if (opcode == goto_ || opcode == jsr) {
1402 emitop4(opcode + goto_w - goto_, 0);
1403 } else {
1404 emitop2(negate(opcode), 8);
1405 emitop4(goto_w, 0);
1406 alive = true;
1407 pendingStackMap = needStackMap;
1408 }
1409 return cp - 5;
1410 } else {
1411 emitop2(opcode, 0);
1412 return cp - 3;
1413 }
1414 }
1416 /** Emit a branch with given opcode; return its chain.
1417 * branch differs from jump in that jsr is treated as no-op.
1418 */
1419 public Chain branch(int opcode) {
1420 Chain result = null;
1421 if (opcode == goto_) {
1422 result = pendingJumps;
1423 pendingJumps = null;
1424 }
1425 if (opcode != dontgoto && isAlive()) {
1426 result = new Chain(emitJump(opcode),
1427 result,
1428 state.dup());
1429 fixedPc = fatcode;
1430 if (opcode == goto_) alive = false;
1431 }
1432 return result;
1433 }
1435 /** Resolve chain to point to given target.
1436 */
1437 public void resolve(Chain chain, int target) {
1438 boolean changed = false;
1439 State newState = state;
1440 for (; chain != null; chain = chain.next) {
1441 Assert.check(state != chain.state
1442 && (target > chain.pc || state.stacksize == 0));
1443 if (target >= cp) {
1444 target = cp;
1445 } else if (get1(target) == goto_) {
1446 if (fatcode) target = target + get4(target + 1);
1447 else target = target + get2(target + 1);
1448 }
1449 if (get1(chain.pc) == goto_ &&
1450 chain.pc + 3 == target && target == cp && !fixedPc) {
1451 // If goto the next instruction, the jump is not needed:
1452 // compact the code.
1453 cp = cp - 3;
1454 target = target - 3;
1455 if (chain.next == null) {
1456 // This is the only jump to the target. Exit the loop
1457 // without setting new state. The code is reachable
1458 // from the instruction before goto_.
1459 alive = true;
1460 break;
1461 }
1462 } else {
1463 if (fatcode)
1464 put4(chain.pc + 1, target - chain.pc);
1465 else if (target - chain.pc < Short.MIN_VALUE ||
1466 target - chain.pc > Short.MAX_VALUE)
1467 fatcode = true;
1468 else
1469 put2(chain.pc + 1, target - chain.pc);
1470 Assert.check(!alive ||
1471 chain.state.stacksize == newState.stacksize &&
1472 chain.state.nlocks == newState.nlocks);
1473 }
1474 fixedPc = true;
1475 if (cp == target) {
1476 changed = true;
1477 if (debugCode)
1478 System.err.println("resolving chain state=" + chain.state);
1479 if (alive) {
1480 newState = chain.state.join(newState);
1481 } else {
1482 newState = chain.state;
1483 alive = true;
1484 }
1485 }
1486 }
1487 Assert.check(!changed || state != newState);
1488 if (state != newState) {
1489 setDefined(newState.defined);
1490 state = newState;
1491 pendingStackMap = needStackMap;
1492 }
1493 }
1495 /** Resolve chain to point to current code pointer.
1496 */
1497 public void resolve(Chain chain) {
1498 Assert.check(
1499 !alive ||
1500 chain==null ||
1501 state.stacksize == chain.state.stacksize &&
1502 state.nlocks == chain.state.nlocks);
1503 pendingJumps = mergeChains(chain, pendingJumps);
1504 }
1506 /** Resolve any pending jumps.
1507 */
1508 public void resolvePending() {
1509 Chain x = pendingJumps;
1510 pendingJumps = null;
1511 resolve(x, cp);
1512 }
1514 /** Merge the jumps in of two chains into one.
1515 */
1516 public static Chain mergeChains(Chain chain1, Chain chain2) {
1517 // recursive merge sort
1518 if (chain2 == null) return chain1;
1519 if (chain1 == null) return chain2;
1520 Assert.check(
1521 chain1.state.stacksize == chain2.state.stacksize &&
1522 chain1.state.nlocks == chain2.state.nlocks);
1523 if (chain1.pc < chain2.pc)
1524 return new Chain(
1525 chain2.pc,
1526 mergeChains(chain1, chain2.next),
1527 chain2.state);
1528 return new Chain(
1529 chain1.pc,
1530 mergeChains(chain1.next, chain2),
1531 chain1.state);
1532 }
1535 /* **************************************************************************
1536 * Catch clauses
1537 ****************************************************************************/
1539 /** Add a catch clause to code.
1540 */
1541 public void addCatch(
1542 char startPc, char endPc, char handlerPc, char catchType) {
1543 catchInfo.append(new char[]{startPc, endPc, handlerPc, catchType});
1544 }
1547 public void compressCatchTable() {
1548 ListBuffer<char[]> compressedCatchInfo = ListBuffer.lb();
1549 List<Integer> handlerPcs = List.nil();
1550 for (char[] catchEntry : catchInfo) {
1551 handlerPcs = handlerPcs.prepend((int)catchEntry[2]);
1552 }
1553 for (char[] catchEntry : catchInfo) {
1554 int startpc = catchEntry[0];
1555 int endpc = catchEntry[1];
1556 if (startpc == endpc ||
1557 (startpc == (endpc - 1) &&
1558 handlerPcs.contains(startpc))) {
1559 continue;
1560 } else {
1561 compressedCatchInfo.append(catchEntry);
1562 }
1563 }
1564 catchInfo = compressedCatchInfo;
1565 }
1568 /* **************************************************************************
1569 * Line numbers
1570 ****************************************************************************/
1572 /** Add a line number entry.
1573 */
1574 public void addLineNumber(char startPc, char lineNumber) {
1575 if (lineDebugInfo) {
1576 if (lineInfo.nonEmpty() && lineInfo.head[0] == startPc)
1577 lineInfo = lineInfo.tail;
1578 if (lineInfo.isEmpty() || lineInfo.head[1] != lineNumber)
1579 lineInfo = lineInfo.prepend(new char[]{startPc, lineNumber});
1580 }
1581 }
1583 /** Mark beginning of statement.
1584 */
1585 public void statBegin(int pos) {
1586 if (pos != Position.NOPOS) {
1587 pendingStatPos = pos;
1588 }
1589 }
1591 /** Force stat begin eagerly
1592 */
1593 public void markStatBegin() {
1594 if (alive && lineDebugInfo) {
1595 int line = lineMap.getLineNumber(pendingStatPos);
1596 char cp1 = (char)cp;
1597 char line1 = (char)line;
1598 if (cp1 == cp && line1 == line)
1599 addLineNumber(cp1, line1);
1600 }
1601 pendingStatPos = Position.NOPOS;
1602 }
1605 /* **************************************************************************
1606 * Simulated VM machine state
1607 ****************************************************************************/
1609 class State implements Cloneable {
1610 /** The set of registers containing values. */
1611 Bits defined;
1613 /** The (types of the) contents of the machine stack. */
1614 Type[] stack;
1616 /** The first stack position currently unused. */
1617 int stacksize;
1619 /** The numbers of registers containing locked monitors. */
1620 int[] locks;
1621 int nlocks;
1623 State() {
1624 defined = new Bits();
1625 stack = new Type[16];
1626 }
1628 State dup() {
1629 try {
1630 State state = (State)super.clone();
1631 state.defined = defined.dup();
1632 state.stack = stack.clone();
1633 if (locks != null) state.locks = locks.clone();
1634 if (debugCode) {
1635 System.err.println("duping state " + this);
1636 dump();
1637 }
1638 return state;
1639 } catch (CloneNotSupportedException ex) {
1640 throw new AssertionError(ex);
1641 }
1642 }
1644 void lock(int register) {
1645 if (locks == null) {
1646 locks = new int[20];
1647 } else {
1648 locks = ArrayUtils.ensureCapacity(locks, nlocks);
1649 }
1650 locks[nlocks] = register;
1651 nlocks++;
1652 }
1654 void unlock(int register) {
1655 nlocks--;
1656 Assert.check(locks[nlocks] == register);
1657 locks[nlocks] = -1;
1658 }
1660 void push(Type t) {
1661 if (debugCode) System.err.println(" pushing " + t);
1662 switch (t.getTag()) {
1663 case VOID:
1664 return;
1665 case BYTE:
1666 case CHAR:
1667 case SHORT:
1668 case BOOLEAN:
1669 t = syms.intType;
1670 break;
1671 default:
1672 break;
1673 }
1674 stack = ArrayUtils.ensureCapacity(stack, stacksize+2);
1675 stack[stacksize++] = t;
1676 switch (width(t)) {
1677 case 1:
1678 break;
1679 case 2:
1680 stack[stacksize++] = null;
1681 break;
1682 default:
1683 throw new AssertionError(t);
1684 }
1685 if (stacksize > max_stack)
1686 max_stack = stacksize;
1687 }
1689 Type pop1() {
1690 if (debugCode) System.err.println(" popping " + 1);
1691 stacksize--;
1692 Type result = stack[stacksize];
1693 stack[stacksize] = null;
1694 Assert.check(result != null && width(result) == 1);
1695 return result;
1696 }
1698 Type peek() {
1699 return stack[stacksize-1];
1700 }
1702 Type pop2() {
1703 if (debugCode) System.err.println(" popping " + 2);
1704 stacksize -= 2;
1705 Type result = stack[stacksize];
1706 stack[stacksize] = null;
1707 Assert.check(stack[stacksize+1] == null
1708 && result != null && width(result) == 2);
1709 return result;
1710 }
1712 void pop(int n) {
1713 if (debugCode) System.err.println(" popping " + n);
1714 while (n > 0) {
1715 stack[--stacksize] = null;
1716 n--;
1717 }
1718 }
1720 void pop(Type t) {
1721 pop(width(t));
1722 }
1724 /** Force the top of the stack to be treated as this supertype
1725 * of its current type. */
1726 void forceStackTop(Type t) {
1727 if (!alive) return;
1728 switch (t.getTag()) {
1729 case CLASS:
1730 case ARRAY:
1731 int width = width(t);
1732 Type old = stack[stacksize-width];
1733 Assert.check(types.isSubtype(types.erasure(old),
1734 types.erasure(t)));
1735 stack[stacksize-width] = t;
1736 break;
1737 default:
1738 }
1739 }
1741 void markInitialized(UninitializedType old) {
1742 Type newtype = old.initializedType();
1743 for (int i=0; i<stacksize; i++)
1744 if (stack[i] == old) stack[i] = newtype;
1745 for (int i=0; i<lvar.length; i++) {
1746 LocalVar lv = lvar[i];
1747 if (lv != null && lv.sym.type == old) {
1748 VarSymbol sym = lv.sym;
1749 sym = sym.clone(sym.owner);
1750 sym.type = newtype;
1751 LocalVar newlv = lvar[i] = new LocalVar(sym);
1752 // should the following be initialized to cp?
1753 newlv.start_pc = lv.start_pc;
1754 }
1755 }
1756 }
1758 State join(State other) {
1759 defined = defined.andSet(other.defined);
1760 Assert.check(stacksize == other.stacksize
1761 && nlocks == other.nlocks);
1762 for (int i=0; i<stacksize; ) {
1763 Type t = stack[i];
1764 Type tother = other.stack[i];
1765 Type result =
1766 t==tother ? t :
1767 types.isSubtype(t, tother) ? tother :
1768 types.isSubtype(tother, t) ? t :
1769 error();
1770 int w = width(result);
1771 stack[i] = result;
1772 if (w == 2) Assert.checkNull(stack[i+1]);
1773 i += w;
1774 }
1775 return this;
1776 }
1778 Type error() {
1779 throw new AssertionError("inconsistent stack types at join point");
1780 }
1782 void dump() {
1783 dump(-1);
1784 }
1786 void dump(int pc) {
1787 System.err.print("stackMap for " + meth.owner + "." + meth);
1788 if (pc == -1)
1789 System.out.println();
1790 else
1791 System.out.println(" at " + pc);
1792 System.err.println(" stack (from bottom):");
1793 for (int i=0; i<stacksize; i++)
1794 System.err.println(" " + i + ": " + stack[i]);
1796 int lastLocal = 0;
1797 for (int i=max_locals-1; i>=0; i--) {
1798 if (defined.isMember(i)) {
1799 lastLocal = i;
1800 break;
1801 }
1802 }
1803 if (lastLocal >= 0)
1804 System.err.println(" locals:");
1805 for (int i=0; i<=lastLocal; i++) {
1806 System.err.print(" " + i + ": ");
1807 if (defined.isMember(i)) {
1808 LocalVar var = lvar[i];
1809 if (var == null) {
1810 System.err.println("(none)");
1811 } else if (var.sym == null)
1812 System.err.println("UNKNOWN!");
1813 else
1814 System.err.println("" + var.sym + " of type " +
1815 var.sym.erasure(types));
1816 } else {
1817 System.err.println("undefined");
1818 }
1819 }
1820 if (nlocks != 0) {
1821 System.err.print(" locks:");
1822 for (int i=0; i<nlocks; i++) {
1823 System.err.print(" " + locks[i]);
1824 }
1825 System.err.println();
1826 }
1827 }
1828 }
1830 static final Type jsrReturnValue = new Type(INT, null);
1833 /* **************************************************************************
1834 * Local variables
1835 ****************************************************************************/
1837 /** A live range of a local variable. */
1838 static class LocalVar {
1839 final VarSymbol sym;
1840 final char reg;
1841 char start_pc = Character.MAX_VALUE;
1842 char length = Character.MAX_VALUE;
1843 LocalVar(VarSymbol v) {
1844 this.sym = v;
1845 this.reg = (char)v.adr;
1846 }
1847 public LocalVar dup() {
1848 return new LocalVar(sym);
1849 }
1850 public String toString() {
1851 return "" + sym + " in register " + ((int)reg) + " starts at pc=" + ((int)start_pc) + " length=" + ((int)length);
1852 }
1853 };
1855 /** Local variables, indexed by register. */
1856 LocalVar[] lvar;
1858 /** Add a new local variable. */
1859 private void addLocalVar(VarSymbol v) {
1860 int adr = v.adr;
1861 lvar = ArrayUtils.ensureCapacity(lvar, adr+1);
1862 Assert.checkNull(lvar[adr]);
1863 if (pendingJumps != null) resolvePending();
1864 lvar[adr] = new LocalVar(v);
1865 state.defined.excl(adr);
1866 }
1868 /** Set the current variable defined state. */
1869 public void setDefined(Bits newDefined) {
1870 if (alive && newDefined != state.defined) {
1871 Bits diff = state.defined.dup().xorSet(newDefined);
1872 for (int adr = diff.nextBit(0);
1873 adr >= 0;
1874 adr = diff.nextBit(adr+1)) {
1875 if (adr >= nextreg)
1876 state.defined.excl(adr);
1877 else if (state.defined.isMember(adr))
1878 setUndefined(adr);
1879 else
1880 setDefined(adr);
1881 }
1882 }
1883 }
1885 /** Mark a register as being (possibly) defined. */
1886 public void setDefined(int adr) {
1887 LocalVar v = lvar[adr];
1888 if (v == null) {
1889 state.defined.excl(adr);
1890 } else {
1891 state.defined.incl(adr);
1892 if (cp < Character.MAX_VALUE) {
1893 if (v.start_pc == Character.MAX_VALUE)
1894 v.start_pc = (char)cp;
1895 }
1896 }
1897 }
1899 /** Mark a register as being undefined. */
1900 public void setUndefined(int adr) {
1901 state.defined.excl(adr);
1902 if (adr < lvar.length &&
1903 lvar[adr] != null &&
1904 lvar[adr].start_pc != Character.MAX_VALUE) {
1905 LocalVar v = lvar[adr];
1906 char length = (char)(curPc() - v.start_pc);
1907 if (length > 0 && length < Character.MAX_VALUE) {
1908 lvar[adr] = v.dup();
1909 v.length = length;
1910 putVar(v);
1911 } else {
1912 v.start_pc = Character.MAX_VALUE;
1913 }
1914 }
1915 }
1917 /** End the scope of a variable. */
1918 private void endScope(int adr) {
1919 LocalVar v = lvar[adr];
1920 if (v != null) {
1921 lvar[adr] = null;
1922 if (v.start_pc != Character.MAX_VALUE) {
1923 char length = (char)(curPc() - v.start_pc);
1924 if (length < Character.MAX_VALUE) {
1925 v.length = length;
1926 putVar(v);
1927 }
1928 }
1929 }
1930 state.defined.excl(adr);
1931 }
1933 /** Put a live variable range into the buffer to be output to the
1934 * class file.
1935 */
1936 void putVar(LocalVar var) {
1937 if (!varDebugInfo) return;
1938 if ((var.sym.flags() & Flags.SYNTHETIC) != 0) return;
1939 if (varBuffer == null)
1940 varBuffer = new LocalVar[20];
1941 else
1942 varBuffer = ArrayUtils.ensureCapacity(varBuffer, varBufferSize);
1943 varBuffer[varBufferSize++] = var;
1944 }
1946 /** Previously live local variables, to be put into the variable table. */
1947 LocalVar[] varBuffer;
1948 int varBufferSize;
1950 /** Create a new local variable address and return it.
1951 */
1952 private int newLocal(int typecode) {
1953 int reg = nextreg;
1954 int w = width(typecode);
1955 nextreg = reg + w;
1956 if (nextreg > max_locals) max_locals = nextreg;
1957 return reg;
1958 }
1960 private int newLocal(Type type) {
1961 return newLocal(typecode(type));
1962 }
1964 public int newLocal(VarSymbol v) {
1965 int reg = v.adr = newLocal(v.erasure(types));
1966 addLocalVar(v);
1967 return reg;
1968 }
1970 /** Start a set of fresh registers.
1971 */
1972 public void newRegSegment() {
1973 nextreg = max_locals;
1974 }
1976 /** End scopes of all variables with registers ≥ first.
1977 */
1978 public void endScopes(int first) {
1979 int prevNextReg = nextreg;
1980 nextreg = first;
1981 for (int i = nextreg; i < prevNextReg; i++) endScope(i);
1982 }
1984 /**************************************************************************
1985 * static tables
1986 *************************************************************************/
1988 public static String mnem(int opcode) {
1989 return Mneumonics.mnem[opcode];
1990 }
1992 private static class Mneumonics {
1993 private final static String[] mnem = new String[ByteCodeCount];
1994 static {
1995 mnem[nop] = "nop";
1996 mnem[aconst_null] = "aconst_null";
1997 mnem[iconst_m1] = "iconst_m1";
1998 mnem[iconst_0] = "iconst_0";
1999 mnem[iconst_1] = "iconst_1";
2000 mnem[iconst_2] = "iconst_2";
2001 mnem[iconst_3] = "iconst_3";
2002 mnem[iconst_4] = "iconst_4";
2003 mnem[iconst_5] = "iconst_5";
2004 mnem[lconst_0] = "lconst_0";
2005 mnem[lconst_1] = "lconst_1";
2006 mnem[fconst_0] = "fconst_0";
2007 mnem[fconst_1] = "fconst_1";
2008 mnem[fconst_2] = "fconst_2";
2009 mnem[dconst_0] = "dconst_0";
2010 mnem[dconst_1] = "dconst_1";
2011 mnem[bipush] = "bipush";
2012 mnem[sipush] = "sipush";
2013 mnem[ldc1] = "ldc1";
2014 mnem[ldc2] = "ldc2";
2015 mnem[ldc2w] = "ldc2w";
2016 mnem[iload] = "iload";
2017 mnem[lload] = "lload";
2018 mnem[fload] = "fload";
2019 mnem[dload] = "dload";
2020 mnem[aload] = "aload";
2021 mnem[iload_0] = "iload_0";
2022 mnem[lload_0] = "lload_0";
2023 mnem[fload_0] = "fload_0";
2024 mnem[dload_0] = "dload_0";
2025 mnem[aload_0] = "aload_0";
2026 mnem[iload_1] = "iload_1";
2027 mnem[lload_1] = "lload_1";
2028 mnem[fload_1] = "fload_1";
2029 mnem[dload_1] = "dload_1";
2030 mnem[aload_1] = "aload_1";
2031 mnem[iload_2] = "iload_2";
2032 mnem[lload_2] = "lload_2";
2033 mnem[fload_2] = "fload_2";
2034 mnem[dload_2] = "dload_2";
2035 mnem[aload_2] = "aload_2";
2036 mnem[iload_3] = "iload_3";
2037 mnem[lload_3] = "lload_3";
2038 mnem[fload_3] = "fload_3";
2039 mnem[dload_3] = "dload_3";
2040 mnem[aload_3] = "aload_3";
2041 mnem[iaload] = "iaload";
2042 mnem[laload] = "laload";
2043 mnem[faload] = "faload";
2044 mnem[daload] = "daload";
2045 mnem[aaload] = "aaload";
2046 mnem[baload] = "baload";
2047 mnem[caload] = "caload";
2048 mnem[saload] = "saload";
2049 mnem[istore] = "istore";
2050 mnem[lstore] = "lstore";
2051 mnem[fstore] = "fstore";
2052 mnem[dstore] = "dstore";
2053 mnem[astore] = "astore";
2054 mnem[istore_0] = "istore_0";
2055 mnem[lstore_0] = "lstore_0";
2056 mnem[fstore_0] = "fstore_0";
2057 mnem[dstore_0] = "dstore_0";
2058 mnem[astore_0] = "astore_0";
2059 mnem[istore_1] = "istore_1";
2060 mnem[lstore_1] = "lstore_1";
2061 mnem[fstore_1] = "fstore_1";
2062 mnem[dstore_1] = "dstore_1";
2063 mnem[astore_1] = "astore_1";
2064 mnem[istore_2] = "istore_2";
2065 mnem[lstore_2] = "lstore_2";
2066 mnem[fstore_2] = "fstore_2";
2067 mnem[dstore_2] = "dstore_2";
2068 mnem[astore_2] = "astore_2";
2069 mnem[istore_3] = "istore_3";
2070 mnem[lstore_3] = "lstore_3";
2071 mnem[fstore_3] = "fstore_3";
2072 mnem[dstore_3] = "dstore_3";
2073 mnem[astore_3] = "astore_3";
2074 mnem[iastore] = "iastore";
2075 mnem[lastore] = "lastore";
2076 mnem[fastore] = "fastore";
2077 mnem[dastore] = "dastore";
2078 mnem[aastore] = "aastore";
2079 mnem[bastore] = "bastore";
2080 mnem[castore] = "castore";
2081 mnem[sastore] = "sastore";
2082 mnem[pop] = "pop";
2083 mnem[pop2] = "pop2";
2084 mnem[dup] = "dup";
2085 mnem[dup_x1] = "dup_x1";
2086 mnem[dup_x2] = "dup_x2";
2087 mnem[dup2] = "dup2";
2088 mnem[dup2_x1] = "dup2_x1";
2089 mnem[dup2_x2] = "dup2_x2";
2090 mnem[swap] = "swap";
2091 mnem[iadd] = "iadd";
2092 mnem[ladd] = "ladd";
2093 mnem[fadd] = "fadd";
2094 mnem[dadd] = "dadd";
2095 mnem[isub] = "isub";
2096 mnem[lsub] = "lsub";
2097 mnem[fsub] = "fsub";
2098 mnem[dsub] = "dsub";
2099 mnem[imul] = "imul";
2100 mnem[lmul] = "lmul";
2101 mnem[fmul] = "fmul";
2102 mnem[dmul] = "dmul";
2103 mnem[idiv] = "idiv";
2104 mnem[ldiv] = "ldiv";
2105 mnem[fdiv] = "fdiv";
2106 mnem[ddiv] = "ddiv";
2107 mnem[imod] = "imod";
2108 mnem[lmod] = "lmod";
2109 mnem[fmod] = "fmod";
2110 mnem[dmod] = "dmod";
2111 mnem[ineg] = "ineg";
2112 mnem[lneg] = "lneg";
2113 mnem[fneg] = "fneg";
2114 mnem[dneg] = "dneg";
2115 mnem[ishl] = "ishl";
2116 mnem[lshl] = "lshl";
2117 mnem[ishr] = "ishr";
2118 mnem[lshr] = "lshr";
2119 mnem[iushr] = "iushr";
2120 mnem[lushr] = "lushr";
2121 mnem[iand] = "iand";
2122 mnem[land] = "land";
2123 mnem[ior] = "ior";
2124 mnem[lor] = "lor";
2125 mnem[ixor] = "ixor";
2126 mnem[lxor] = "lxor";
2127 mnem[iinc] = "iinc";
2128 mnem[i2l] = "i2l";
2129 mnem[i2f] = "i2f";
2130 mnem[i2d] = "i2d";
2131 mnem[l2i] = "l2i";
2132 mnem[l2f] = "l2f";
2133 mnem[l2d] = "l2d";
2134 mnem[f2i] = "f2i";
2135 mnem[f2l] = "f2l";
2136 mnem[f2d] = "f2d";
2137 mnem[d2i] = "d2i";
2138 mnem[d2l] = "d2l";
2139 mnem[d2f] = "d2f";
2140 mnem[int2byte] = "int2byte";
2141 mnem[int2char] = "int2char";
2142 mnem[int2short] = "int2short";
2143 mnem[lcmp] = "lcmp";
2144 mnem[fcmpl] = "fcmpl";
2145 mnem[fcmpg] = "fcmpg";
2146 mnem[dcmpl] = "dcmpl";
2147 mnem[dcmpg] = "dcmpg";
2148 mnem[ifeq] = "ifeq";
2149 mnem[ifne] = "ifne";
2150 mnem[iflt] = "iflt";
2151 mnem[ifge] = "ifge";
2152 mnem[ifgt] = "ifgt";
2153 mnem[ifle] = "ifle";
2154 mnem[if_icmpeq] = "if_icmpeq";
2155 mnem[if_icmpne] = "if_icmpne";
2156 mnem[if_icmplt] = "if_icmplt";
2157 mnem[if_icmpge] = "if_icmpge";
2158 mnem[if_icmpgt] = "if_icmpgt";
2159 mnem[if_icmple] = "if_icmple";
2160 mnem[if_acmpeq] = "if_acmpeq";
2161 mnem[if_acmpne] = "if_acmpne";
2162 mnem[goto_] = "goto_";
2163 mnem[jsr] = "jsr";
2164 mnem[ret] = "ret";
2165 mnem[tableswitch] = "tableswitch";
2166 mnem[lookupswitch] = "lookupswitch";
2167 mnem[ireturn] = "ireturn";
2168 mnem[lreturn] = "lreturn";
2169 mnem[freturn] = "freturn";
2170 mnem[dreturn] = "dreturn";
2171 mnem[areturn] = "areturn";
2172 mnem[return_] = "return_";
2173 mnem[getstatic] = "getstatic";
2174 mnem[putstatic] = "putstatic";
2175 mnem[getfield] = "getfield";
2176 mnem[putfield] = "putfield";
2177 mnem[invokevirtual] = "invokevirtual";
2178 mnem[invokespecial] = "invokespecial";
2179 mnem[invokestatic] = "invokestatic";
2180 mnem[invokeinterface] = "invokeinterface";
2181 mnem[invokedynamic] = "invokedynamic";
2182 mnem[new_] = "new_";
2183 mnem[newarray] = "newarray";
2184 mnem[anewarray] = "anewarray";
2185 mnem[arraylength] = "arraylength";
2186 mnem[athrow] = "athrow";
2187 mnem[checkcast] = "checkcast";
2188 mnem[instanceof_] = "instanceof_";
2189 mnem[monitorenter] = "monitorenter";
2190 mnem[monitorexit] = "monitorexit";
2191 mnem[wide] = "wide";
2192 mnem[multianewarray] = "multianewarray";
2193 mnem[if_acmp_null] = "if_acmp_null";
2194 mnem[if_acmp_nonnull] = "if_acmp_nonnull";
2195 mnem[goto_w] = "goto_w";
2196 mnem[jsr_w] = "jsr_w";
2197 mnem[breakpoint] = "breakpoint";
2198 }
2199 }
2200 }