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

Thu, 04 Oct 2012 13:04:53 +0100

author
mcimadamore
date
Thu, 04 Oct 2012 13:04:53 +0100
changeset 1347
1408af4cd8b0
parent 1339
0e5899f09dab
child 1374
c002fdee76fd
permissions
-rw-r--r--

7177387: Add target-typing support in method context
Summary: Add support for deferred types and speculative attribution
Reviewed-by: jjg, dlsmith

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

mercurial