src/share/classes/com/sun/tools/javac/jvm/Code.java

Sun, 17 Feb 2013 16:44:55 -0500

author
dholmes
date
Sun, 17 Feb 2013 16:44:55 -0500
changeset 1571
af8417e590f4
parent 1521
71f35e4b93a5
child 1670
29c6984a1673
permissions
-rw-r--r--

Merge

     1 /*
     2  * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle in the LICENSE file that accompanied this code.
    10  *
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    14  * version 2 for more details (a copy is included in the LICENSE file that
    15  * accompanied this code).
    16  *
    17  * You should have received a copy of the GNU General Public License version
    18  * 2 along with this work; if not, write to the Free Software Foundation,
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    20  *
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    24  */
    26 package com.sun.tools.javac.jvm;
    28 import com.sun.tools.javac.code.*;
    29 import com.sun.tools.javac.code.Symbol.*;
    30 import com.sun.tools.javac.code.Types.UniqueType;
    31 import com.sun.tools.javac.util.*;
    32 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
    34 import static com.sun.tools.javac.code.TypeTag.BOT;
    35 import static com.sun.tools.javac.code.TypeTag.INT;
    36 import static com.sun.tools.javac.jvm.ByteCodes.*;
    37 import static com.sun.tools.javac.jvm.UninitializedType.*;
    38 import static com.sun.tools.javac.jvm.ClassWriter.StackMapTableFrame;
    40 /** An internal structure that corresponds to the code attribute of
    41  *  methods in a classfile. The class also provides some utility operations to
    42  *  generate bytecode instructions.
    43  *
    44  *  <p><b>This is NOT part of any supported API.
    45  *  If you write code that depends on this, you do so at your own risk.
    46  *  This code and its internal interfaces are subject to change or
    47  *  deletion without notice.</b>
    48  */
    49 public class Code {
    51     public final boolean debugCode;
    52     public final boolean needStackMap;
    54     public enum StackMapFormat {
    55         NONE,
    56         CLDC {
    57             Name getAttributeName(Names names) {
    58                 return names.StackMap;
    59             }
    60         },
    61         JSR202 {
    62             Name getAttributeName(Names names) {
    63                 return names.StackMapTable;
    64             }
    65         };
    66         Name getAttributeName(Names names) {
    67             return names.empty;
    68         }
    69     }
    71     final Types types;
    72     final Symtab syms;
    74 /*---------- classfile fields: --------------- */
    76     /** The maximum stack size.
    77      */
    78     public int max_stack = 0;
    80     /** The maximum number of local variable slots.
    81      */
    82     public int max_locals = 0;
    84     /** The code buffer.
    85      */
    86     public byte[] code = new byte[64];
    88     /** the current code pointer.
    89      */
    90     public int cp = 0;
    92     /** Check the code against VM spec limits; if
    93      *  problems report them and return true.
    94      */
    95     public boolean checkLimits(DiagnosticPosition pos, Log log) {
    96         if (cp > ClassFile.MAX_CODE) {
    97             log.error(pos, "limit.code");
    98             return true;
    99         }
   100         if (max_locals > ClassFile.MAX_LOCALS) {
   101             log.error(pos, "limit.locals");
   102             return true;
   103         }
   104         if (max_stack > ClassFile.MAX_STACK) {
   105             log.error(pos, "limit.stack");
   106             return true;
   107         }
   108         return false;
   109     }
   111     /** A buffer for expression catch data. Each enter is a vector
   112      *  of four unsigned shorts.
   113      */
   114     ListBuffer<char[]> catchInfo = new ListBuffer<char[]>();
   116     /** A buffer for line number information. Each entry is a vector
   117      *  of two unsigned shorts.
   118      */
   119     List<char[]> lineInfo = List.nil(); // handled in stack fashion
   121     /** The CharacterRangeTable
   122      */
   123     public CRTable crt;
   125 /*---------- internal fields: --------------- */
   127     /** Are we generating code with jumps &ge; 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));
  1053         // postop();
  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));
  1071         // postop();
  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);
  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;
  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);
  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);
  1108     /** Return code byte at position pc as an unsigned int.
  1109      */
  1110     private int get1(int pc) {
  1111         return code[pc] & 0xFF;
  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);
  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));
  1131     /** Is code generation currently enabled?
  1132      */
  1133     public boolean isAlive() {
  1134         return alive || pendingJumps != null;
  1137     /** Switch code generation on/off.
  1138      */
  1139     public void markDead() {
  1140         alive = false;
  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;
  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;
  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;
  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;
  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");
  1224         // DEBUG code follows
  1225         if (debugCode) state.dump(pc);
  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;
  1236         return nextLocal;
  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;
  1245         lastStackMapPC = pc;
  1247         if (stackMapBuffer == null) {
  1248             stackMapBuffer = new StackMapFrame[20];
  1249         } else {
  1250             stackMapBuffer = ArrayUtils.ensureCapacity(stackMapBuffer, stackMapBufferSize);
  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;
  1265         frame.stack = new Type[state.stacksize];
  1266         for (int i=0; i<state.stacksize; i++)
  1267             frame.stack[i] = state.stack[i];
  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;
  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++;
  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++;
  1302         int stackCount = 0;
  1303         for (int i=0; i<state.stacksize; i++) {
  1304             if (state.stack[i] != null) {
  1305                 stackCount++;
  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]);
  1316         if (stackMapTableBuffer == null) {
  1317             stackMapTableBuffer = new StackMapTableFrame[20];
  1318         } else {
  1319             stackMapTableBuffer = ArrayUtils.ensureCapacity(
  1320                                     stackMapTableBuffer,
  1321                                     stackMapBufferSize);
  1323         stackMapTableBuffer[stackMapBufferSize++] =
  1324                 StackMapTableFrame.getInstance(frame, lastFrame.pc, lastFrame.locals, types);
  1326         frameBeforeLast = lastFrame;
  1327         lastFrame = frame;
  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);
  1343         } else {
  1344             frame.locals = new Type[len];
  1346         for (Type arg_type : arg_types) {
  1347             frame.locals[count++] = types.erasure(arg_type);
  1349         frame.pc = -1;
  1350         frame.stack = null;
  1351         return frame;
  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;
  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;
  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;
  1409             return cp - 5;
  1410         } else {
  1411             emitop2(opcode, 0);
  1412             return cp - 3;
  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;
  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;
  1432         return result;
  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);
  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;
  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);
  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;
  1487         Assert.check(!changed || state != newState);
  1488         if (state != newState) {
  1489             setDefined(newState.defined);
  1490             state = newState;
  1491             pendingStackMap = needStackMap;
  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);
  1506     /** Resolve any pending jumps.
  1507      */
  1508     public void resolvePending() {
  1509         Chain x = pendingJumps;
  1510         pendingJumps = null;
  1511         resolve(x, cp);
  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);
  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});
  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]);
  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);
  1564         catchInfo = compressedCatchInfo;
  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});
  1583     /** Mark beginning of statement.
  1584      */
  1585     public void statBegin(int pos) {
  1586         if (pos != Position.NOPOS) {
  1587             pendingStatPos = pos;
  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);
  1601         pendingStatPos = Position.NOPOS;
  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];
  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();
  1638                 return state;
  1639             } catch (CloneNotSupportedException ex) {
  1640                 throw new AssertionError(ex);
  1644         void lock(int register) {
  1645             if (locks == null) {
  1646                 locks = new int[20];
  1647             } else {
  1648                 locks = ArrayUtils.ensureCapacity(locks, nlocks);
  1650             locks[nlocks] = register;
  1651             nlocks++;
  1654         void unlock(int register) {
  1655             nlocks--;
  1656             Assert.check(locks[nlocks] == register);
  1657             locks[nlocks] = -1;
  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;
  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);
  1685             if (stacksize > max_stack)
  1686                 max_stack = stacksize;
  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;
  1698         Type peek() {
  1699             return stack[stacksize-1];
  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;
  1712         void pop(int n) {
  1713             if (debugCode) System.err.println("   popping " + n);
  1714             while (n > 0) {
  1715                 stack[--stacksize] = null;
  1716                 n--;
  1720         void pop(Type t) {
  1721             pop(width(t));
  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:
  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;
  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;
  1775             return this;
  1778         Type error() {
  1779             throw new AssertionError("inconsistent stack types at join point");
  1782         void dump() {
  1783             dump(-1);
  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;
  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");
  1820             if (nlocks != 0) {
  1821                 System.err.print(" locks:");
  1822                 for (int i=0; i<nlocks; i++) {
  1823                     System.err.print(" " + locks[i]);
  1825                 System.err.println();
  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;
  1847         public LocalVar dup() {
  1848             return new LocalVar(sym);
  1850         public String toString() {
  1851             return "" + sym + " in register " + ((int)reg) + " starts at pc=" + ((int)start_pc) + " length=" + ((int)length);
  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);
  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);
  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;
  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;
  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                     fillLocalVarPosition(v);
  1931         state.defined.excl(adr);
  1934     private void fillLocalVarPosition(LocalVar lv) {
  1935         if (lv == null || lv.sym == null
  1936                 || lv.sym.annotations.isTypesEmpty())
  1937             return;
  1938         for (Attribute.TypeCompound ta : lv.sym.getRawTypeAttributes()) {
  1939             TypeAnnotationPosition p = ta.position;
  1940             p.lvarOffset = new int[] { (int)lv.start_pc };
  1941             p.lvarLength = new int[] { (int)lv.length };
  1942             p.lvarIndex = new int[] { (int)lv.reg };
  1943             p.isValidOffset = true;
  1947     // Method to be called after compressCatchTable to
  1948     // fill in the exception table index for type
  1949     // annotations on exception parameters.
  1950     public void fillExceptionParameterPositions() {
  1951         for (int i = 0; i < varBufferSize; ++i) {
  1952             LocalVar lv = varBuffer[i];
  1953             if (lv == null || lv.sym == null
  1954                     || lv.sym.annotations.isTypesEmpty()
  1955                     || !lv.sym.isExceptionParameter())
  1956                 return;
  1958             int exidx = findExceptionIndex(lv);
  1960             for (Attribute.TypeCompound ta : lv.sym.getRawTypeAttributes()) {
  1961                 TypeAnnotationPosition p = ta.position;
  1962                 p.exception_index = exidx;
  1967     private int findExceptionIndex(LocalVar lv) {
  1968         List<char[]> iter = catchInfo.toList();
  1969         int len = catchInfo.length();
  1970         for (int i = 0; i < len; ++i) {
  1971             char[] catchEntry = iter.head;
  1972             iter = iter.tail;
  1973             char handlerpc = catchEntry[2];
  1974             if (lv.start_pc == handlerpc + 1) {
  1975                 return i;
  1978         return -1;
  1981     /** Put a live variable range into the buffer to be output to the
  1982      *  class file.
  1983      */
  1984     void putVar(LocalVar var) {
  1985         // Keep local variables if
  1986         // 1) we need them for debug information
  1987         // 2) it is an exception type and it contains type annotations
  1988         if (!varDebugInfo &&
  1989                 (!var.sym.isExceptionParameter() ||
  1990                 var.sym.annotations.isTypesEmpty())) return;
  1991         if ((var.sym.flags() & Flags.SYNTHETIC) != 0) return;
  1992         if (varBuffer == null)
  1993             varBuffer = new LocalVar[20];
  1994         else
  1995             varBuffer = ArrayUtils.ensureCapacity(varBuffer, varBufferSize);
  1996         varBuffer[varBufferSize++] = var;
  1999     /** Previously live local variables, to be put into the variable table. */
  2000     LocalVar[] varBuffer;
  2001     int varBufferSize;
  2003     /** Create a new local variable address and return it.
  2004      */
  2005     private int newLocal(int typecode) {
  2006         int reg = nextreg;
  2007         int w = width(typecode);
  2008         nextreg = reg + w;
  2009         if (nextreg > max_locals) max_locals = nextreg;
  2010         return reg;
  2013     private int newLocal(Type type) {
  2014         return newLocal(typecode(type));
  2017     public int newLocal(VarSymbol v) {
  2018         int reg = v.adr = newLocal(v.erasure(types));
  2019         addLocalVar(v);
  2020         return reg;
  2023     /** Start a set of fresh registers.
  2024      */
  2025     public void newRegSegment() {
  2026         nextreg = max_locals;
  2029     /** End scopes of all variables with registers &ge; first.
  2030      */
  2031     public void endScopes(int first) {
  2032         int prevNextReg = nextreg;
  2033         nextreg = first;
  2034         for (int i = nextreg; i < prevNextReg; i++) endScope(i);
  2037 /**************************************************************************
  2038  * static tables
  2039  *************************************************************************/
  2041     public static String mnem(int opcode) {
  2042         return Mneumonics.mnem[opcode];
  2045     private static class Mneumonics {
  2046         private final static String[] mnem = new String[ByteCodeCount];
  2047         static {
  2048             mnem[nop] = "nop";
  2049             mnem[aconst_null] = "aconst_null";
  2050             mnem[iconst_m1] = "iconst_m1";
  2051             mnem[iconst_0] = "iconst_0";
  2052             mnem[iconst_1] = "iconst_1";
  2053             mnem[iconst_2] = "iconst_2";
  2054             mnem[iconst_3] = "iconst_3";
  2055             mnem[iconst_4] = "iconst_4";
  2056             mnem[iconst_5] = "iconst_5";
  2057             mnem[lconst_0] = "lconst_0";
  2058             mnem[lconst_1] = "lconst_1";
  2059             mnem[fconst_0] = "fconst_0";
  2060             mnem[fconst_1] = "fconst_1";
  2061             mnem[fconst_2] = "fconst_2";
  2062             mnem[dconst_0] = "dconst_0";
  2063             mnem[dconst_1] = "dconst_1";
  2064             mnem[bipush] = "bipush";
  2065             mnem[sipush] = "sipush";
  2066             mnem[ldc1] = "ldc1";
  2067             mnem[ldc2] = "ldc2";
  2068             mnem[ldc2w] = "ldc2w";
  2069             mnem[iload] = "iload";
  2070             mnem[lload] = "lload";
  2071             mnem[fload] = "fload";
  2072             mnem[dload] = "dload";
  2073             mnem[aload] = "aload";
  2074             mnem[iload_0] = "iload_0";
  2075             mnem[lload_0] = "lload_0";
  2076             mnem[fload_0] = "fload_0";
  2077             mnem[dload_0] = "dload_0";
  2078             mnem[aload_0] = "aload_0";
  2079             mnem[iload_1] = "iload_1";
  2080             mnem[lload_1] = "lload_1";
  2081             mnem[fload_1] = "fload_1";
  2082             mnem[dload_1] = "dload_1";
  2083             mnem[aload_1] = "aload_1";
  2084             mnem[iload_2] = "iload_2";
  2085             mnem[lload_2] = "lload_2";
  2086             mnem[fload_2] = "fload_2";
  2087             mnem[dload_2] = "dload_2";
  2088             mnem[aload_2] = "aload_2";
  2089             mnem[iload_3] = "iload_3";
  2090             mnem[lload_3] = "lload_3";
  2091             mnem[fload_3] = "fload_3";
  2092             mnem[dload_3] = "dload_3";
  2093             mnem[aload_3] = "aload_3";
  2094             mnem[iaload] = "iaload";
  2095             mnem[laload] = "laload";
  2096             mnem[faload] = "faload";
  2097             mnem[daload] = "daload";
  2098             mnem[aaload] = "aaload";
  2099             mnem[baload] = "baload";
  2100             mnem[caload] = "caload";
  2101             mnem[saload] = "saload";
  2102             mnem[istore] = "istore";
  2103             mnem[lstore] = "lstore";
  2104             mnem[fstore] = "fstore";
  2105             mnem[dstore] = "dstore";
  2106             mnem[astore] = "astore";
  2107             mnem[istore_0] = "istore_0";
  2108             mnem[lstore_0] = "lstore_0";
  2109             mnem[fstore_0] = "fstore_0";
  2110             mnem[dstore_0] = "dstore_0";
  2111             mnem[astore_0] = "astore_0";
  2112             mnem[istore_1] = "istore_1";
  2113             mnem[lstore_1] = "lstore_1";
  2114             mnem[fstore_1] = "fstore_1";
  2115             mnem[dstore_1] = "dstore_1";
  2116             mnem[astore_1] = "astore_1";
  2117             mnem[istore_2] = "istore_2";
  2118             mnem[lstore_2] = "lstore_2";
  2119             mnem[fstore_2] = "fstore_2";
  2120             mnem[dstore_2] = "dstore_2";
  2121             mnem[astore_2] = "astore_2";
  2122             mnem[istore_3] = "istore_3";
  2123             mnem[lstore_3] = "lstore_3";
  2124             mnem[fstore_3] = "fstore_3";
  2125             mnem[dstore_3] = "dstore_3";
  2126             mnem[astore_3] = "astore_3";
  2127             mnem[iastore] = "iastore";
  2128             mnem[lastore] = "lastore";
  2129             mnem[fastore] = "fastore";
  2130             mnem[dastore] = "dastore";
  2131             mnem[aastore] = "aastore";
  2132             mnem[bastore] = "bastore";
  2133             mnem[castore] = "castore";
  2134             mnem[sastore] = "sastore";
  2135             mnem[pop] = "pop";
  2136             mnem[pop2] = "pop2";
  2137             mnem[dup] = "dup";
  2138             mnem[dup_x1] = "dup_x1";
  2139             mnem[dup_x2] = "dup_x2";
  2140             mnem[dup2] = "dup2";
  2141             mnem[dup2_x1] = "dup2_x1";
  2142             mnem[dup2_x2] = "dup2_x2";
  2143             mnem[swap] = "swap";
  2144             mnem[iadd] = "iadd";
  2145             mnem[ladd] = "ladd";
  2146             mnem[fadd] = "fadd";
  2147             mnem[dadd] = "dadd";
  2148             mnem[isub] = "isub";
  2149             mnem[lsub] = "lsub";
  2150             mnem[fsub] = "fsub";
  2151             mnem[dsub] = "dsub";
  2152             mnem[imul] = "imul";
  2153             mnem[lmul] = "lmul";
  2154             mnem[fmul] = "fmul";
  2155             mnem[dmul] = "dmul";
  2156             mnem[idiv] = "idiv";
  2157             mnem[ldiv] = "ldiv";
  2158             mnem[fdiv] = "fdiv";
  2159             mnem[ddiv] = "ddiv";
  2160             mnem[imod] = "imod";
  2161             mnem[lmod] = "lmod";
  2162             mnem[fmod] = "fmod";
  2163             mnem[dmod] = "dmod";
  2164             mnem[ineg] = "ineg";
  2165             mnem[lneg] = "lneg";
  2166             mnem[fneg] = "fneg";
  2167             mnem[dneg] = "dneg";
  2168             mnem[ishl] = "ishl";
  2169             mnem[lshl] = "lshl";
  2170             mnem[ishr] = "ishr";
  2171             mnem[lshr] = "lshr";
  2172             mnem[iushr] = "iushr";
  2173             mnem[lushr] = "lushr";
  2174             mnem[iand] = "iand";
  2175             mnem[land] = "land";
  2176             mnem[ior] = "ior";
  2177             mnem[lor] = "lor";
  2178             mnem[ixor] = "ixor";
  2179             mnem[lxor] = "lxor";
  2180             mnem[iinc] = "iinc";
  2181             mnem[i2l] = "i2l";
  2182             mnem[i2f] = "i2f";
  2183             mnem[i2d] = "i2d";
  2184             mnem[l2i] = "l2i";
  2185             mnem[l2f] = "l2f";
  2186             mnem[l2d] = "l2d";
  2187             mnem[f2i] = "f2i";
  2188             mnem[f2l] = "f2l";
  2189             mnem[f2d] = "f2d";
  2190             mnem[d2i] = "d2i";
  2191             mnem[d2l] = "d2l";
  2192             mnem[d2f] = "d2f";
  2193             mnem[int2byte] = "int2byte";
  2194             mnem[int2char] = "int2char";
  2195             mnem[int2short] = "int2short";
  2196             mnem[lcmp] = "lcmp";
  2197             mnem[fcmpl] = "fcmpl";
  2198             mnem[fcmpg] = "fcmpg";
  2199             mnem[dcmpl] = "dcmpl";
  2200             mnem[dcmpg] = "dcmpg";
  2201             mnem[ifeq] = "ifeq";
  2202             mnem[ifne] = "ifne";
  2203             mnem[iflt] = "iflt";
  2204             mnem[ifge] = "ifge";
  2205             mnem[ifgt] = "ifgt";
  2206             mnem[ifle] = "ifle";
  2207             mnem[if_icmpeq] = "if_icmpeq";
  2208             mnem[if_icmpne] = "if_icmpne";
  2209             mnem[if_icmplt] = "if_icmplt";
  2210             mnem[if_icmpge] = "if_icmpge";
  2211             mnem[if_icmpgt] = "if_icmpgt";
  2212             mnem[if_icmple] = "if_icmple";
  2213             mnem[if_acmpeq] = "if_acmpeq";
  2214             mnem[if_acmpne] = "if_acmpne";
  2215             mnem[goto_] = "goto_";
  2216             mnem[jsr] = "jsr";
  2217             mnem[ret] = "ret";
  2218             mnem[tableswitch] = "tableswitch";
  2219             mnem[lookupswitch] = "lookupswitch";
  2220             mnem[ireturn] = "ireturn";
  2221             mnem[lreturn] = "lreturn";
  2222             mnem[freturn] = "freturn";
  2223             mnem[dreturn] = "dreturn";
  2224             mnem[areturn] = "areturn";
  2225             mnem[return_] = "return_";
  2226             mnem[getstatic] = "getstatic";
  2227             mnem[putstatic] = "putstatic";
  2228             mnem[getfield] = "getfield";
  2229             mnem[putfield] = "putfield";
  2230             mnem[invokevirtual] = "invokevirtual";
  2231             mnem[invokespecial] = "invokespecial";
  2232             mnem[invokestatic] = "invokestatic";
  2233             mnem[invokeinterface] = "invokeinterface";
  2234             mnem[invokedynamic] = "invokedynamic";
  2235             mnem[new_] = "new_";
  2236             mnem[newarray] = "newarray";
  2237             mnem[anewarray] = "anewarray";
  2238             mnem[arraylength] = "arraylength";
  2239             mnem[athrow] = "athrow";
  2240             mnem[checkcast] = "checkcast";
  2241             mnem[instanceof_] = "instanceof_";
  2242             mnem[monitorenter] = "monitorenter";
  2243             mnem[monitorexit] = "monitorexit";
  2244             mnem[wide] = "wide";
  2245             mnem[multianewarray] = "multianewarray";
  2246             mnem[if_acmp_null] = "if_acmp_null";
  2247             mnem[if_acmp_nonnull] = "if_acmp_nonnull";
  2248             mnem[goto_w] = "goto_w";
  2249             mnem[jsr_w] = "jsr_w";
  2250             mnem[breakpoint] = "breakpoint";

mercurial