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

Mon, 10 Dec 2012 16:21:26 +0000

author
vromero
date
Mon, 10 Dec 2012 16:21:26 +0000
changeset 1442
fcf89720ae71
parent 1374
c002fdee76fd
child 1444
170e486632d9
permissions
-rw-r--r--

8003967: detect and remove all mutable implicit static enum fields in langtools
Reviewed-by: jjg

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

mercurial