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

Fri, 29 Apr 2011 16:05:02 +0100

author
mcimadamore
date
Fri, 29 Apr 2011 16:05:02 +0100
changeset 989
4c03383f6529
parent 816
7c537f4298fb
child 1109
3cdfa97e1be9
permissions
-rw-r--r--

7040104: javac NPE on Object a[]; Object o = (a=null)[0];
Summary: When a null literal is found on top of stack, if expected type is 1-dimension array no checkcast is emitted
Reviewed-by: jjg

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

mercurial