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

Tue, 02 Apr 2013 10:51:16 +0100

author
vromero
date
Tue, 02 Apr 2013 10:51:16 +0100
changeset 1670
29c6984a1673
parent 1521
71f35e4b93a5
child 1676
e9d986381414
permissions
-rw-r--r--

4965689: class literal code wastes a byte
Reviewed-by: jjg

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

mercurial