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

Fri, 03 May 2013 15:08:47 -0700

author
jjg
date
Fri, 03 May 2013 15:08:47 -0700
changeset 1723
a2889739cf21
parent 1713
2ca9e7d50136
child 1755
ddb4a2bfcd82
permissions
-rw-r--r--

8000407: remove @GenerateNativeHeader
Reviewed-by: vromero, darcy

     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         int prevPos = pendingStatPos;
   474         try {
   475             //disable line number generation (we could have used 'emit1', that
   476             //bypasses stackmap generation - which is needed for indy calls)
   477             pendingStatPos = Position.NOPOS;
   478             emitop(invokedynamic);
   479         } finally {
   480             pendingStatPos = prevPos;
   481         }
   482         if (!alive) return;
   483         emit2(desc);
   484         emit2(0);
   485         state.pop(argsize);
   486         state.push(mtype.getReturnType());
   487     }
   489     /** Emit an opcode with no operand field.
   490      */
   491     public void emitop0(int op) {
   492         emitop(op);
   493         if (!alive) return;
   494         switch (op) {
   495         case aaload: {
   496             state.pop(1);// index
   497             Type a = state.stack[state.stacksize-1];
   498             state.pop(1);
   499             //sometimes 'null type' is treated as a one-dimensional array type
   500             //see Gen.visitLiteral - we should handle this case accordingly
   501             Type stackType = a.hasTag(BOT) ?
   502                 syms.objectType :
   503                 types.erasure(types.elemtype(a));
   504             state.push(stackType); }
   505             break;
   506         case goto_:
   507             markDead();
   508             break;
   509         case nop:
   510         case ineg:
   511         case lneg:
   512         case fneg:
   513         case dneg:
   514             break;
   515         case aconst_null:
   516             state.push(syms.botType);
   517             break;
   518         case iconst_m1:
   519         case iconst_0:
   520         case iconst_1:
   521         case iconst_2:
   522         case iconst_3:
   523         case iconst_4:
   524         case iconst_5:
   525         case iload_0:
   526         case iload_1:
   527         case iload_2:
   528         case iload_3:
   529             state.push(syms.intType);
   530             break;
   531         case lconst_0:
   532         case lconst_1:
   533         case lload_0:
   534         case lload_1:
   535         case lload_2:
   536         case lload_3:
   537             state.push(syms.longType);
   538             break;
   539         case fconst_0:
   540         case fconst_1:
   541         case fconst_2:
   542         case fload_0:
   543         case fload_1:
   544         case fload_2:
   545         case fload_3:
   546             state.push(syms.floatType);
   547             break;
   548         case dconst_0:
   549         case dconst_1:
   550         case dload_0:
   551         case dload_1:
   552         case dload_2:
   553         case dload_3:
   554             state.push(syms.doubleType);
   555             break;
   556         case aload_0:
   557             state.push(lvar[0].sym.type);
   558             break;
   559         case aload_1:
   560             state.push(lvar[1].sym.type);
   561             break;
   562         case aload_2:
   563             state.push(lvar[2].sym.type);
   564             break;
   565         case aload_3:
   566             state.push(lvar[3].sym.type);
   567             break;
   568         case iaload:
   569         case baload:
   570         case caload:
   571         case saload:
   572             state.pop(2);
   573             state.push(syms.intType);
   574             break;
   575         case laload:
   576             state.pop(2);
   577             state.push(syms.longType);
   578             break;
   579         case faload:
   580             state.pop(2);
   581             state.push(syms.floatType);
   582             break;
   583         case daload:
   584             state.pop(2);
   585             state.push(syms.doubleType);
   586             break;
   587         case istore_0:
   588         case istore_1:
   589         case istore_2:
   590         case istore_3:
   591         case fstore_0:
   592         case fstore_1:
   593         case fstore_2:
   594         case fstore_3:
   595         case astore_0:
   596         case astore_1:
   597         case astore_2:
   598         case astore_3:
   599         case pop:
   600         case lshr:
   601         case lshl:
   602         case lushr:
   603             state.pop(1);
   604             break;
   605         case areturn:
   606         case ireturn:
   607         case freturn:
   608             Assert.check(state.nlocks == 0);
   609             state.pop(1);
   610             markDead();
   611             break;
   612         case athrow:
   613             state.pop(1);
   614             markDead();
   615             break;
   616         case lstore_0:
   617         case lstore_1:
   618         case lstore_2:
   619         case lstore_3:
   620         case dstore_0:
   621         case dstore_1:
   622         case dstore_2:
   623         case dstore_3:
   624         case pop2:
   625             state.pop(2);
   626             break;
   627         case lreturn:
   628         case dreturn:
   629             Assert.check(state.nlocks == 0);
   630             state.pop(2);
   631             markDead();
   632             break;
   633         case dup:
   634             state.push(state.stack[state.stacksize-1]);
   635             break;
   636         case return_:
   637             Assert.check(state.nlocks == 0);
   638             markDead();
   639             break;
   640         case arraylength:
   641             state.pop(1);
   642             state.push(syms.intType);
   643             break;
   644         case isub:
   645         case iadd:
   646         case imul:
   647         case idiv:
   648         case imod:
   649         case ishl:
   650         case ishr:
   651         case iushr:
   652         case iand:
   653         case ior:
   654         case ixor:
   655             state.pop(1);
   656             // state.pop(1);
   657             // state.push(syms.intType);
   658             break;
   659         case aastore:
   660             state.pop(3);
   661             break;
   662         case land:
   663         case lor:
   664         case lxor:
   665         case lmod:
   666         case ldiv:
   667         case lmul:
   668         case lsub:
   669         case ladd:
   670             state.pop(2);
   671             break;
   672         case lcmp:
   673             state.pop(4);
   674             state.push(syms.intType);
   675             break;
   676         case l2i:
   677             state.pop(2);
   678             state.push(syms.intType);
   679             break;
   680         case i2l:
   681             state.pop(1);
   682             state.push(syms.longType);
   683             break;
   684         case i2f:
   685             state.pop(1);
   686             state.push(syms.floatType);
   687             break;
   688         case i2d:
   689             state.pop(1);
   690             state.push(syms.doubleType);
   691             break;
   692         case l2f:
   693             state.pop(2);
   694             state.push(syms.floatType);
   695             break;
   696         case l2d:
   697             state.pop(2);
   698             state.push(syms.doubleType);
   699             break;
   700         case f2i:
   701             state.pop(1);
   702             state.push(syms.intType);
   703             break;
   704         case f2l:
   705             state.pop(1);
   706             state.push(syms.longType);
   707             break;
   708         case f2d:
   709             state.pop(1);
   710             state.push(syms.doubleType);
   711             break;
   712         case d2i:
   713             state.pop(2);
   714             state.push(syms.intType);
   715             break;
   716         case d2l:
   717             state.pop(2);
   718             state.push(syms.longType);
   719             break;
   720         case d2f:
   721             state.pop(2);
   722             state.push(syms.floatType);
   723             break;
   724         case tableswitch:
   725         case lookupswitch:
   726             state.pop(1);
   727             // the caller is responsible for patching up the state
   728             break;
   729         case dup_x1: {
   730             Type val1 = state.pop1();
   731             Type val2 = state.pop1();
   732             state.push(val1);
   733             state.push(val2);
   734             state.push(val1);
   735             break;
   736         }
   737         case bastore:
   738             state.pop(3);
   739             break;
   740         case int2byte:
   741         case int2char:
   742         case int2short:
   743             break;
   744         case fmul:
   745         case fadd:
   746         case fsub:
   747         case fdiv:
   748         case fmod:
   749             state.pop(1);
   750             break;
   751         case castore:
   752         case iastore:
   753         case fastore:
   754         case sastore:
   755             state.pop(3);
   756             break;
   757         case lastore:
   758         case dastore:
   759             state.pop(4);
   760             break;
   761         case dup2:
   762             if (state.stack[state.stacksize-1] != null) {
   763                 Type value1 = state.pop1();
   764                 Type value2 = state.pop1();
   765                 state.push(value2);
   766                 state.push(value1);
   767                 state.push(value2);
   768                 state.push(value1);
   769             } else {
   770                 Type value = state.pop2();
   771                 state.push(value);
   772                 state.push(value);
   773             }
   774             break;
   775         case dup2_x1:
   776             if (state.stack[state.stacksize-1] != null) {
   777                 Type value1 = state.pop1();
   778                 Type value2 = state.pop1();
   779                 Type value3 = state.pop1();
   780                 state.push(value2);
   781                 state.push(value1);
   782                 state.push(value3);
   783                 state.push(value2);
   784                 state.push(value1);
   785             } else {
   786                 Type value1 = state.pop2();
   787                 Type value2 = state.pop1();
   788                 state.push(value1);
   789                 state.push(value2);
   790                 state.push(value1);
   791             }
   792             break;
   793         case dup2_x2:
   794             if (state.stack[state.stacksize-1] != null) {
   795                 Type value1 = state.pop1();
   796                 Type value2 = state.pop1();
   797                 if (state.stack[state.stacksize-1] != null) {
   798                     // form 1
   799                     Type value3 = state.pop1();
   800                     Type value4 = state.pop1();
   801                     state.push(value2);
   802                     state.push(value1);
   803                     state.push(value4);
   804                     state.push(value3);
   805                     state.push(value2);
   806                     state.push(value1);
   807                 } else {
   808                     // form 3
   809                     Type value3 = state.pop2();
   810                     state.push(value2);
   811                     state.push(value1);
   812                     state.push(value3);
   813                     state.push(value2);
   814                     state.push(value1);
   815                 }
   816             } else {
   817                 Type value1 = state.pop2();
   818                 if (state.stack[state.stacksize-1] != null) {
   819                     // form 2
   820                     Type value2 = state.pop1();
   821                     Type value3 = state.pop1();
   822                     state.push(value1);
   823                     state.push(value3);
   824                     state.push(value2);
   825                     state.push(value1);
   826                 } else {
   827                     // form 4
   828                     Type value2 = state.pop2();
   829                     state.push(value1);
   830                     state.push(value2);
   831                     state.push(value1);
   832                 }
   833             }
   834             break;
   835         case dup_x2: {
   836             Type value1 = state.pop1();
   837             if (state.stack[state.stacksize-1] != null) {
   838                 // form 1
   839                 Type value2 = state.pop1();
   840                 Type value3 = state.pop1();
   841                 state.push(value1);
   842                 state.push(value3);
   843                 state.push(value2);
   844                 state.push(value1);
   845             } else {
   846                 // form 2
   847                 Type value2 = state.pop2();
   848                 state.push(value1);
   849                 state.push(value2);
   850                 state.push(value1);
   851             }
   852         }
   853             break;
   854         case fcmpl:
   855         case fcmpg:
   856             state.pop(2);
   857             state.push(syms.intType);
   858             break;
   859         case dcmpl:
   860         case dcmpg:
   861             state.pop(4);
   862             state.push(syms.intType);
   863             break;
   864         case swap: {
   865             Type value1 = state.pop1();
   866             Type value2 = state.pop1();
   867             state.push(value1);
   868             state.push(value2);
   869             break;
   870         }
   871         case dadd:
   872         case dsub:
   873         case dmul:
   874         case ddiv:
   875         case dmod:
   876             state.pop(2);
   877             break;
   878         case ret:
   879             markDead();
   880             break;
   881         case wide:
   882             // must be handled by the caller.
   883             return;
   884         case monitorenter:
   885         case monitorexit:
   886             state.pop(1);
   887             break;
   889         default:
   890             throw new AssertionError(mnem(op));
   891         }
   892         postop();
   893     }
   895     /** Emit an opcode with a one-byte operand field.
   896      */
   897     public void emitop1(int op, int od) {
   898         emitop(op);
   899         if (!alive) return;
   900         emit1(od);
   901         switch (op) {
   902         case bipush:
   903             state.push(syms.intType);
   904             break;
   905         case ldc1:
   906             state.push(typeForPool(pool.pool[od]));
   907             break;
   908         default:
   909             throw new AssertionError(mnem(op));
   910         }
   911         postop();
   912     }
   914     /** The type of a constant pool entry. */
   915     private Type typeForPool(Object o) {
   916         if (o instanceof Integer) return syms.intType;
   917         if (o instanceof Float) return syms.floatType;
   918         if (o instanceof String) return syms.stringType;
   919         if (o instanceof Long) return syms.longType;
   920         if (o instanceof Double) return syms.doubleType;
   921         if (o instanceof ClassSymbol) return syms.classType;
   922         if (o instanceof Type.ArrayType) return syms.classType;
   923         if (o instanceof Type.MethodType) return syms.methodTypeType;
   924         if (o instanceof UniqueType) return typeForPool(((UniqueType)o).type);
   925         if (o instanceof Pool.MethodHandle) return syms.methodHandleType;
   926         throw new AssertionError(o);
   927     }
   929     /** Emit an opcode with a one-byte operand field;
   930      *  widen if field does not fit in a byte.
   931      */
   932     public void emitop1w(int op, int od) {
   933         if (od > 0xFF) {
   934             emitop(wide);
   935             emitop(op);
   936             emit2(od);
   937         } else {
   938             emitop(op);
   939             emit1(od);
   940         }
   941         if (!alive) return;
   942         switch (op) {
   943         case iload:
   944             state.push(syms.intType);
   945             break;
   946         case lload:
   947             state.push(syms.longType);
   948             break;
   949         case fload:
   950             state.push(syms.floatType);
   951             break;
   952         case dload:
   953             state.push(syms.doubleType);
   954             break;
   955         case aload:
   956             state.push(lvar[od].sym.type);
   957             break;
   958         case lstore:
   959         case dstore:
   960             state.pop(2);
   961             break;
   962         case istore:
   963         case fstore:
   964         case astore:
   965             state.pop(1);
   966             break;
   967         case ret:
   968             markDead();
   969             break;
   970         default:
   971             throw new AssertionError(mnem(op));
   972         }
   973         postop();
   974     }
   976     /** Emit an opcode with two one-byte operand fields;
   977      *  widen if either field does not fit in a byte.
   978      */
   979     public void emitop1w(int op, int od1, int od2) {
   980         if (od1 > 0xFF || od2 < -128 || od2 > 127) {
   981             emitop(wide);
   982             emitop(op);
   983             emit2(od1);
   984             emit2(od2);
   985         } else {
   986             emitop(op);
   987             emit1(od1);
   988             emit1(od2);
   989         }
   990         if (!alive) return;
   991         switch (op) {
   992         case iinc:
   993             break;
   994         default:
   995             throw new AssertionError(mnem(op));
   996         }
   997     }
   999     /** Emit an opcode with a two-byte operand field.
  1000      */
  1001     public void emitop2(int op, int od) {
  1002         emitop(op);
  1003         if (!alive) return;
  1004         emit2(od);
  1005         switch (op) {
  1006         case getstatic:
  1007             state.push(((Symbol)(pool.pool[od])).erasure(types));
  1008             break;
  1009         case putstatic:
  1010             state.pop(((Symbol)(pool.pool[od])).erasure(types));
  1011             break;
  1012         case new_:
  1013             state.push(uninitializedObject(((Symbol)(pool.pool[od])).erasure(types), cp-3));
  1014             break;
  1015         case sipush:
  1016             state.push(syms.intType);
  1017             break;
  1018         case if_acmp_null:
  1019         case if_acmp_nonnull:
  1020         case ifeq:
  1021         case ifne:
  1022         case iflt:
  1023         case ifge:
  1024         case ifgt:
  1025         case ifle:
  1026             state.pop(1);
  1027             break;
  1028         case if_icmpeq:
  1029         case if_icmpne:
  1030         case if_icmplt:
  1031         case if_icmpge:
  1032         case if_icmpgt:
  1033         case if_icmple:
  1034         case if_acmpeq:
  1035         case if_acmpne:
  1036             state.pop(2);
  1037             break;
  1038         case goto_:
  1039             markDead();
  1040             break;
  1041         case putfield:
  1042             state.pop(((Symbol)(pool.pool[od])).erasure(types));
  1043             state.pop(1); // object ref
  1044             break;
  1045         case getfield:
  1046             state.pop(1); // object ref
  1047             state.push(((Symbol)(pool.pool[od])).erasure(types));
  1048             break;
  1049         case checkcast: {
  1050             state.pop(1); // object ref
  1051             Object o = pool.pool[od];
  1052             Type t = (o instanceof Symbol)
  1053                 ? ((Symbol)o).erasure(types)
  1054                 : types.erasure((((UniqueType)o).type));
  1055             state.push(t);
  1056             break; }
  1057         case ldc2w:
  1058             state.push(typeForPool(pool.pool[od]));
  1059             break;
  1060         case instanceof_:
  1061             state.pop(1);
  1062             state.push(syms.intType);
  1063             break;
  1064         case ldc2:
  1065             state.push(typeForPool(pool.pool[od]));
  1066             break;
  1067         case jsr:
  1068             break;
  1069         default:
  1070             throw new AssertionError(mnem(op));
  1072         // postop();
  1075     /** Emit an opcode with a four-byte operand field.
  1076      */
  1077     public void emitop4(int op, int od) {
  1078         emitop(op);
  1079         if (!alive) return;
  1080         emit4(od);
  1081         switch (op) {
  1082         case goto_w:
  1083             markDead();
  1084             break;
  1085         case jsr_w:
  1086             break;
  1087         default:
  1088             throw new AssertionError(mnem(op));
  1090         // postop();
  1093     /** Align code pointer to next `incr' boundary.
  1094      */
  1095     public void align(int incr) {
  1096         if (alive)
  1097             while (cp % incr != 0) emitop0(nop);
  1100     /** Place a byte into code at address pc.
  1101      *  Pre: {@literal pc + 1 <= cp }.
  1102      */
  1103     private void put1(int pc, int op) {
  1104         code[pc] = (byte)op;
  1107     /** Place two bytes into code at address pc.
  1108      *  Pre: {@literal pc + 2 <= cp }.
  1109      */
  1110     private void put2(int pc, int od) {
  1111         // pre: pc + 2 <= cp
  1112         put1(pc, od >> 8);
  1113         put1(pc+1, od);
  1116     /** Place four  bytes into code at address pc.
  1117      *  Pre: {@literal pc + 4 <= cp }.
  1118      */
  1119     public void put4(int pc, int od) {
  1120         // pre: pc + 4 <= cp
  1121         put1(pc  , od >> 24);
  1122         put1(pc+1, od >> 16);
  1123         put1(pc+2, od >> 8);
  1124         put1(pc+3, od);
  1127     /** Return code byte at position pc as an unsigned int.
  1128      */
  1129     private int get1(int pc) {
  1130         return code[pc] & 0xFF;
  1133     /** Return two code bytes at position pc as an unsigned int.
  1134      */
  1135     private int get2(int pc) {
  1136         return (get1(pc) << 8) | get1(pc+1);
  1139     /** Return four code bytes at position pc as an int.
  1140      */
  1141     public int get4(int pc) {
  1142         // pre: pc + 4 <= cp
  1143         return
  1144             (get1(pc) << 24) |
  1145             (get1(pc+1) << 16) |
  1146             (get1(pc+2) << 8) |
  1147             (get1(pc+3));
  1150     /** Is code generation currently enabled?
  1151      */
  1152     public boolean isAlive() {
  1153         return alive || pendingJumps != null;
  1156     /** Switch code generation on/off.
  1157      */
  1158     public void markDead() {
  1159         alive = false;
  1162     /** Declare an entry point; return current code pointer
  1163      */
  1164     public int entryPoint() {
  1165         int pc = curPc();
  1166         alive = true;
  1167         pendingStackMap = needStackMap;
  1168         return pc;
  1171     /** Declare an entry point with initial state;
  1172      *  return current code pointer
  1173      */
  1174     public int entryPoint(State state) {
  1175         int pc = curPc();
  1176         alive = true;
  1177         this.state = state.dup();
  1178         Assert.check(state.stacksize <= max_stack);
  1179         if (debugCode) System.err.println("entry point " + state);
  1180         pendingStackMap = needStackMap;
  1181         return pc;
  1184     /** Declare an entry point with initial state plus a pushed value;
  1185      *  return current code pointer
  1186      */
  1187     public int entryPoint(State state, Type pushed) {
  1188         int pc = curPc();
  1189         alive = true;
  1190         this.state = state.dup();
  1191         Assert.check(state.stacksize <= max_stack);
  1192         this.state.push(pushed);
  1193         if (debugCode) System.err.println("entry point " + state);
  1194         pendingStackMap = needStackMap;
  1195         return pc;
  1199 /**************************************************************************
  1200  * Stack map generation
  1201  *************************************************************************/
  1203     /** An entry in the stack map. */
  1204     static class StackMapFrame {
  1205         int pc;
  1206         Type[] locals;
  1207         Type[] stack;
  1210     /** A buffer of cldc stack map entries. */
  1211     StackMapFrame[] stackMapBuffer = null;
  1213     /** A buffer of compressed StackMapTable entries. */
  1214     StackMapTableFrame[] stackMapTableBuffer = null;
  1215     int stackMapBufferSize = 0;
  1217     /** The last PC at which we generated a stack map. */
  1218     int lastStackMapPC = -1;
  1220     /** The last stack map frame in StackMapTable. */
  1221     StackMapFrame lastFrame = null;
  1223     /** The stack map frame before the last one. */
  1224     StackMapFrame frameBeforeLast = null;
  1226     /** Emit a stack map entry.  */
  1227     public void emitStackMap() {
  1228         int pc = curPc();
  1229         if (!needStackMap) return;
  1233         switch (stackMap) {
  1234             case CLDC:
  1235                 emitCLDCStackMap(pc, getLocalsSize());
  1236                 break;
  1237             case JSR202:
  1238                 emitStackMapFrame(pc, getLocalsSize());
  1239                 break;
  1240             default:
  1241                 throw new AssertionError("Should have chosen a stackmap format");
  1243         // DEBUG code follows
  1244         if (debugCode) state.dump(pc);
  1247     private int getLocalsSize() {
  1248         int nextLocal = 0;
  1249         for (int i=max_locals-1; i>=0; i--) {
  1250             if (state.defined.isMember(i) && lvar[i] != null) {
  1251                 nextLocal = i + width(lvar[i].sym.erasure(types));
  1252                 break;
  1255         return nextLocal;
  1258     /** Emit a CLDC stack map frame. */
  1259     void emitCLDCStackMap(int pc, int localsSize) {
  1260         if (lastStackMapPC == pc) {
  1261             // drop existing stackmap at this offset
  1262             stackMapBuffer[--stackMapBufferSize] = null;
  1264         lastStackMapPC = pc;
  1266         if (stackMapBuffer == null) {
  1267             stackMapBuffer = new StackMapFrame[20];
  1268         } else {
  1269             stackMapBuffer = ArrayUtils.ensureCapacity(stackMapBuffer, stackMapBufferSize);
  1271         StackMapFrame frame =
  1272             stackMapBuffer[stackMapBufferSize++] = new StackMapFrame();
  1273         frame.pc = pc;
  1275         frame.locals = new Type[localsSize];
  1276         for (int i=0; i<localsSize; i++) {
  1277             if (state.defined.isMember(i) && lvar[i] != null) {
  1278                 Type vtype = lvar[i].sym.type;
  1279                 if (!(vtype instanceof UninitializedType))
  1280                     vtype = types.erasure(vtype);
  1281                 frame.locals[i] = vtype;
  1284         frame.stack = new Type[state.stacksize];
  1285         for (int i=0; i<state.stacksize; i++)
  1286             frame.stack[i] = state.stack[i];
  1289     void emitStackMapFrame(int pc, int localsSize) {
  1290         if (lastFrame == null) {
  1291             // first frame
  1292             lastFrame = getInitialFrame();
  1293         } else if (lastFrame.pc == pc) {
  1294             // drop existing stackmap at this offset
  1295             stackMapTableBuffer[--stackMapBufferSize] = null;
  1296             lastFrame = frameBeforeLast;
  1297             frameBeforeLast = null;
  1300         StackMapFrame frame = new StackMapFrame();
  1301         frame.pc = pc;
  1303         int localCount = 0;
  1304         Type[] locals = new Type[localsSize];
  1305         for (int i=0; i<localsSize; i++, localCount++) {
  1306             if (state.defined.isMember(i) && lvar[i] != null) {
  1307                 Type vtype = lvar[i].sym.type;
  1308                 if (!(vtype instanceof UninitializedType))
  1309                     vtype = types.erasure(vtype);
  1310                 locals[i] = vtype;
  1311                 if (width(vtype) > 1) i++;
  1314         frame.locals = new Type[localCount];
  1315         for (int i=0, j=0; i<localsSize; i++, j++) {
  1316             Assert.check(j < localCount);
  1317             frame.locals[j] = locals[i];
  1318             if (width(locals[i]) > 1) i++;
  1321         int stackCount = 0;
  1322         for (int i=0; i<state.stacksize; i++) {
  1323             if (state.stack[i] != null) {
  1324                 stackCount++;
  1327         frame.stack = new Type[stackCount];
  1328         stackCount = 0;
  1329         for (int i=0; i<state.stacksize; i++) {
  1330             if (state.stack[i] != null) {
  1331                 frame.stack[stackCount++] = types.erasure(state.stack[i]);
  1335         if (stackMapTableBuffer == null) {
  1336             stackMapTableBuffer = new StackMapTableFrame[20];
  1337         } else {
  1338             stackMapTableBuffer = ArrayUtils.ensureCapacity(
  1339                                     stackMapTableBuffer,
  1340                                     stackMapBufferSize);
  1342         stackMapTableBuffer[stackMapBufferSize++] =
  1343                 StackMapTableFrame.getInstance(frame, lastFrame.pc, lastFrame.locals, types);
  1345         frameBeforeLast = lastFrame;
  1346         lastFrame = frame;
  1349     StackMapFrame getInitialFrame() {
  1350         StackMapFrame frame = new StackMapFrame();
  1351         List<Type> arg_types = ((MethodType)meth.externalType(types)).argtypes;
  1352         int len = arg_types.length();
  1353         int count = 0;
  1354         if (!meth.isStatic()) {
  1355             Type thisType = meth.owner.type;
  1356             frame.locals = new Type[len+1];
  1357             if (meth.isConstructor() && thisType != syms.objectType) {
  1358                 frame.locals[count++] = UninitializedType.uninitializedThis(thisType);
  1359             } else {
  1360                 frame.locals[count++] = types.erasure(thisType);
  1362         } else {
  1363             frame.locals = new Type[len];
  1365         for (Type arg_type : arg_types) {
  1366             frame.locals[count++] = types.erasure(arg_type);
  1368         frame.pc = -1;
  1369         frame.stack = null;
  1370         return frame;
  1374 /**************************************************************************
  1375  * Operations having to do with jumps
  1376  *************************************************************************/
  1378     /** A chain represents a list of unresolved jumps. Jump locations
  1379      *  are sorted in decreasing order.
  1380      */
  1381     public static class Chain {
  1383         /** The position of the jump instruction.
  1384          */
  1385         public final int pc;
  1387         /** The machine state after the jump instruction.
  1388          *  Invariant: all elements of a chain list have the same stacksize
  1389          *  and compatible stack and register contents.
  1390          */
  1391         Code.State state;
  1393         /** The next jump in the list.
  1394          */
  1395         public final Chain next;
  1397         /** Construct a chain from its jump position, stacksize, previous
  1398          *  chain, and machine state.
  1399          */
  1400         public Chain(int pc, Chain next, Code.State state) {
  1401             this.pc = pc;
  1402             this.next = next;
  1403             this.state = state;
  1407     /** Negate a branch opcode.
  1408      */
  1409     public static int negate(int opcode) {
  1410         if (opcode == if_acmp_null) return if_acmp_nonnull;
  1411         else if (opcode == if_acmp_nonnull) return if_acmp_null;
  1412         else return ((opcode + 1) ^ 1) - 1;
  1415     /** Emit a jump instruction.
  1416      *  Return code pointer of instruction to be patched.
  1417      */
  1418     public int emitJump(int opcode) {
  1419         if (fatcode) {
  1420             if (opcode == goto_ || opcode == jsr) {
  1421                 emitop4(opcode + goto_w - goto_, 0);
  1422             } else {
  1423                 emitop2(negate(opcode), 8);
  1424                 emitop4(goto_w, 0);
  1425                 alive = true;
  1426                 pendingStackMap = needStackMap;
  1428             return cp - 5;
  1429         } else {
  1430             emitop2(opcode, 0);
  1431             return cp - 3;
  1435     /** Emit a branch with given opcode; return its chain.
  1436      *  branch differs from jump in that jsr is treated as no-op.
  1437      */
  1438     public Chain branch(int opcode) {
  1439         Chain result = null;
  1440         if (opcode == goto_) {
  1441             result = pendingJumps;
  1442             pendingJumps = null;
  1444         if (opcode != dontgoto && isAlive()) {
  1445             result = new Chain(emitJump(opcode),
  1446                                result,
  1447                                state.dup());
  1448             fixedPc = fatcode;
  1449             if (opcode == goto_) alive = false;
  1451         return result;
  1454     /** Resolve chain to point to given target.
  1455      */
  1456     public void resolve(Chain chain, int target) {
  1457         boolean changed = false;
  1458         State newState = state;
  1459         for (; chain != null; chain = chain.next) {
  1460             Assert.check(state != chain.state
  1461                     && (target > chain.pc || state.stacksize == 0));
  1462             if (target >= cp) {
  1463                 target = cp;
  1464             } else if (get1(target) == goto_) {
  1465                 if (fatcode) target = target + get4(target + 1);
  1466                 else target = target + get2(target + 1);
  1468             if (get1(chain.pc) == goto_ &&
  1469                 chain.pc + 3 == target && target == cp && !fixedPc) {
  1470                 // If goto the next instruction, the jump is not needed:
  1471                 // compact the code.
  1472                 cp = cp - 3;
  1473                 target = target - 3;
  1474                 if (chain.next == null) {
  1475                     // This is the only jump to the target. Exit the loop
  1476                     // without setting new state. The code is reachable
  1477                     // from the instruction before goto_.
  1478                     alive = true;
  1479                     break;
  1481             } else {
  1482                 if (fatcode)
  1483                     put4(chain.pc + 1, target - chain.pc);
  1484                 else if (target - chain.pc < Short.MIN_VALUE ||
  1485                          target - chain.pc > Short.MAX_VALUE)
  1486                     fatcode = true;
  1487                 else
  1488                     put2(chain.pc + 1, target - chain.pc);
  1489                 Assert.check(!alive ||
  1490                     chain.state.stacksize == newState.stacksize &&
  1491                     chain.state.nlocks == newState.nlocks);
  1493             fixedPc = true;
  1494             if (cp == target) {
  1495                 changed = true;
  1496                 if (debugCode)
  1497                     System.err.println("resolving chain state=" + chain.state);
  1498                 if (alive) {
  1499                     newState = chain.state.join(newState);
  1500                 } else {
  1501                     newState = chain.state;
  1502                     alive = true;
  1506         Assert.check(!changed || state != newState);
  1507         if (state != newState) {
  1508             setDefined(newState.defined);
  1509             state = newState;
  1510             pendingStackMap = needStackMap;
  1514     /** Resolve chain to point to current code pointer.
  1515      */
  1516     public void resolve(Chain chain) {
  1517         Assert.check(
  1518             !alive ||
  1519             chain==null ||
  1520             state.stacksize == chain.state.stacksize &&
  1521             state.nlocks == chain.state.nlocks);
  1522         pendingJumps = mergeChains(chain, pendingJumps);
  1525     /** Resolve any pending jumps.
  1526      */
  1527     public void resolvePending() {
  1528         Chain x = pendingJumps;
  1529         pendingJumps = null;
  1530         resolve(x, cp);
  1533     /** Merge the jumps in of two chains into one.
  1534      */
  1535     public static Chain mergeChains(Chain chain1, Chain chain2) {
  1536         // recursive merge sort
  1537         if (chain2 == null) return chain1;
  1538         if (chain1 == null) return chain2;
  1539         Assert.check(
  1540             chain1.state.stacksize == chain2.state.stacksize &&
  1541             chain1.state.nlocks == chain2.state.nlocks);
  1542         if (chain1.pc < chain2.pc)
  1543             return new Chain(
  1544                 chain2.pc,
  1545                 mergeChains(chain1, chain2.next),
  1546                 chain2.state);
  1547         return new Chain(
  1548                 chain1.pc,
  1549                 mergeChains(chain1.next, chain2),
  1550                 chain1.state);
  1554 /* **************************************************************************
  1555  * Catch clauses
  1556  ****************************************************************************/
  1558     /** Add a catch clause to code.
  1559      */
  1560     public void addCatch(
  1561         char startPc, char endPc, char handlerPc, char catchType) {
  1562             catchInfo.append(new char[]{startPc, endPc, handlerPc, catchType});
  1566     public void compressCatchTable() {
  1567         ListBuffer<char[]> compressedCatchInfo = ListBuffer.lb();
  1568         List<Integer> handlerPcs = List.nil();
  1569         for (char[] catchEntry : catchInfo) {
  1570             handlerPcs = handlerPcs.prepend((int)catchEntry[2]);
  1572         for (char[] catchEntry : catchInfo) {
  1573             int startpc = catchEntry[0];
  1574             int endpc = catchEntry[1];
  1575             if (startpc == endpc ||
  1576                     (startpc == (endpc - 1) &&
  1577                     handlerPcs.contains(startpc))) {
  1578                 continue;
  1579             } else {
  1580                 compressedCatchInfo.append(catchEntry);
  1583         catchInfo = compressedCatchInfo;
  1587 /* **************************************************************************
  1588  * Line numbers
  1589  ****************************************************************************/
  1591     /** Add a line number entry.
  1592      */
  1593     public void addLineNumber(char startPc, char lineNumber) {
  1594         if (lineDebugInfo) {
  1595             if (lineInfo.nonEmpty() && lineInfo.head[0] == startPc)
  1596                 lineInfo = lineInfo.tail;
  1597             if (lineInfo.isEmpty() || lineInfo.head[1] != lineNumber)
  1598                 lineInfo = lineInfo.prepend(new char[]{startPc, lineNumber});
  1602     /** Mark beginning of statement.
  1603      */
  1604     public void statBegin(int pos) {
  1605         if (pos != Position.NOPOS) {
  1606             pendingStatPos = pos;
  1610     /** Force stat begin eagerly
  1611      */
  1612     public void markStatBegin() {
  1613         if (alive && lineDebugInfo) {
  1614             int line = lineMap.getLineNumber(pendingStatPos);
  1615             char cp1 = (char)cp;
  1616             char line1 = (char)line;
  1617             if (cp1 == cp && line1 == line)
  1618                 addLineNumber(cp1, line1);
  1620         pendingStatPos = Position.NOPOS;
  1624 /* **************************************************************************
  1625  * Simulated VM machine state
  1626  ****************************************************************************/
  1628     class State implements Cloneable {
  1629         /** The set of registers containing values. */
  1630         Bits defined;
  1632         /** The (types of the) contents of the machine stack. */
  1633         Type[] stack;
  1635         /** The first stack position currently unused. */
  1636         int stacksize;
  1638         /** The numbers of registers containing locked monitors. */
  1639         int[] locks;
  1640         int nlocks;
  1642         State() {
  1643             defined = new Bits();
  1644             stack = new Type[16];
  1647         State dup() {
  1648             try {
  1649                 State state = (State)super.clone();
  1650                 state.defined = new Bits(defined);
  1651                 state.stack = stack.clone();
  1652                 if (locks != null) state.locks = locks.clone();
  1653                 if (debugCode) {
  1654                     System.err.println("duping state " + this);
  1655                     dump();
  1657                 return state;
  1658             } catch (CloneNotSupportedException ex) {
  1659                 throw new AssertionError(ex);
  1663         void lock(int register) {
  1664             if (locks == null) {
  1665                 locks = new int[20];
  1666             } else {
  1667                 locks = ArrayUtils.ensureCapacity(locks, nlocks);
  1669             locks[nlocks] = register;
  1670             nlocks++;
  1673         void unlock(int register) {
  1674             nlocks--;
  1675             Assert.check(locks[nlocks] == register);
  1676             locks[nlocks] = -1;
  1679         void push(Type t) {
  1680             if (debugCode) System.err.println("   pushing " + t);
  1681             switch (t.getTag()) {
  1682             case VOID:
  1683                 return;
  1684             case BYTE:
  1685             case CHAR:
  1686             case SHORT:
  1687             case BOOLEAN:
  1688                 t = syms.intType;
  1689                 break;
  1690             default:
  1691                 break;
  1693             stack = ArrayUtils.ensureCapacity(stack, stacksize+2);
  1694             stack[stacksize++] = t;
  1695             switch (width(t)) {
  1696             case 1:
  1697                 break;
  1698             case 2:
  1699                 stack[stacksize++] = null;
  1700                 break;
  1701             default:
  1702                 throw new AssertionError(t);
  1704             if (stacksize > max_stack)
  1705                 max_stack = stacksize;
  1708         Type pop1() {
  1709             if (debugCode) System.err.println("   popping " + 1);
  1710             stacksize--;
  1711             Type result = stack[stacksize];
  1712             stack[stacksize] = null;
  1713             Assert.check(result != null && width(result) == 1);
  1714             return result;
  1717         Type peek() {
  1718             return stack[stacksize-1];
  1721         Type pop2() {
  1722             if (debugCode) System.err.println("   popping " + 2);
  1723             stacksize -= 2;
  1724             Type result = stack[stacksize];
  1725             stack[stacksize] = null;
  1726             Assert.check(stack[stacksize+1] == null
  1727                     && result != null && width(result) == 2);
  1728             return result;
  1731         void pop(int n) {
  1732             if (debugCode) System.err.println("   popping " + n);
  1733             while (n > 0) {
  1734                 stack[--stacksize] = null;
  1735                 n--;
  1739         void pop(Type t) {
  1740             pop(width(t));
  1743         /** Force the top of the stack to be treated as this supertype
  1744          *  of its current type. */
  1745         void forceStackTop(Type t) {
  1746             if (!alive) return;
  1747             switch (t.getTag()) {
  1748             case CLASS:
  1749             case ARRAY:
  1750                 int width = width(t);
  1751                 Type old = stack[stacksize-width];
  1752                 Assert.check(types.isSubtype(types.erasure(old),
  1753                                        types.erasure(t)));
  1754                 stack[stacksize-width] = t;
  1755                 break;
  1756             default:
  1760         void markInitialized(UninitializedType old) {
  1761             Type newtype = old.initializedType();
  1762             for (int i=0; i<stacksize; i++)
  1763                 if (stack[i] == old) stack[i] = newtype;
  1764             for (int i=0; i<lvar.length; i++) {
  1765                 LocalVar lv = lvar[i];
  1766                 if (lv != null && lv.sym.type == old) {
  1767                     VarSymbol sym = lv.sym;
  1768                     sym = sym.clone(sym.owner);
  1769                     sym.type = newtype;
  1770                     LocalVar newlv = lvar[i] = new LocalVar(sym);
  1771                     // should the following be initialized to cp?
  1772                     newlv.start_pc = lv.start_pc;
  1777         State join(State other) {
  1778             defined.andSet(other.defined);
  1779             Assert.check(stacksize == other.stacksize
  1780                     && nlocks == other.nlocks);
  1781             for (int i=0; i<stacksize; ) {
  1782                 Type t = stack[i];
  1783                 Type tother = other.stack[i];
  1784                 Type result =
  1785                     t==tother ? t :
  1786                     types.isSubtype(t, tother) ? tother :
  1787                     types.isSubtype(tother, t) ? t :
  1788                     error();
  1789                 int w = width(result);
  1790                 stack[i] = result;
  1791                 if (w == 2) Assert.checkNull(stack[i+1]);
  1792                 i += w;
  1794             return this;
  1797         Type error() {
  1798             throw new AssertionError("inconsistent stack types at join point");
  1801         void dump() {
  1802             dump(-1);
  1805         void dump(int pc) {
  1806             System.err.print("stackMap for " + meth.owner + "." + meth);
  1807             if (pc == -1)
  1808                 System.out.println();
  1809             else
  1810                 System.out.println(" at " + pc);
  1811             System.err.println(" stack (from bottom):");
  1812             for (int i=0; i<stacksize; i++)
  1813                 System.err.println("  " + i + ": " + stack[i]);
  1815             int lastLocal = 0;
  1816             for (int i=max_locals-1; i>=0; i--) {
  1817                 if (defined.isMember(i)) {
  1818                     lastLocal = i;
  1819                     break;
  1822             if (lastLocal >= 0)
  1823                 System.err.println(" locals:");
  1824             for (int i=0; i<=lastLocal; i++) {
  1825                 System.err.print("  " + i + ": ");
  1826                 if (defined.isMember(i)) {
  1827                     LocalVar var = lvar[i];
  1828                     if (var == null) {
  1829                         System.err.println("(none)");
  1830                     } else if (var.sym == null)
  1831                         System.err.println("UNKNOWN!");
  1832                     else
  1833                         System.err.println("" + var.sym + " of type " +
  1834                                            var.sym.erasure(types));
  1835                 } else {
  1836                     System.err.println("undefined");
  1839             if (nlocks != 0) {
  1840                 System.err.print(" locks:");
  1841                 for (int i=0; i<nlocks; i++) {
  1842                     System.err.print(" " + locks[i]);
  1844                 System.err.println();
  1849     static final Type jsrReturnValue = new Type(INT, null);
  1852 /* **************************************************************************
  1853  * Local variables
  1854  ****************************************************************************/
  1856     /** A live range of a local variable. */
  1857     static class LocalVar {
  1858         final VarSymbol sym;
  1859         final char reg;
  1860         char start_pc = Character.MAX_VALUE;
  1861         char length = Character.MAX_VALUE;
  1862         LocalVar(VarSymbol v) {
  1863             this.sym = v;
  1864             this.reg = (char)v.adr;
  1866         public LocalVar dup() {
  1867             return new LocalVar(sym);
  1869         public String toString() {
  1870             return "" + sym + " in register " + ((int)reg) + " starts at pc=" + ((int)start_pc) + " length=" + ((int)length);
  1872     };
  1874     /** Local variables, indexed by register. */
  1875     LocalVar[] lvar;
  1877     /** Add a new local variable. */
  1878     private void addLocalVar(VarSymbol v) {
  1879         int adr = v.adr;
  1880         lvar = ArrayUtils.ensureCapacity(lvar, adr+1);
  1881         Assert.checkNull(lvar[adr]);
  1882         if (pendingJumps != null) resolvePending();
  1883         lvar[adr] = new LocalVar(v);
  1884         state.defined.excl(adr);
  1887     /** Set the current variable defined state. */
  1888     public void setDefined(Bits newDefined) {
  1889         if (alive && newDefined != state.defined) {
  1890             Bits diff = new Bits(state.defined).xorSet(newDefined);
  1891             for (int adr = diff.nextBit(0);
  1892                  adr >= 0;
  1893                  adr = diff.nextBit(adr+1)) {
  1894                 if (adr >= nextreg)
  1895                     state.defined.excl(adr);
  1896                 else if (state.defined.isMember(adr))
  1897                     setUndefined(adr);
  1898                 else
  1899                     setDefined(adr);
  1904     /** Mark a register as being (possibly) defined. */
  1905     public void setDefined(int adr) {
  1906         LocalVar v = lvar[adr];
  1907         if (v == null) {
  1908             state.defined.excl(adr);
  1909         } else {
  1910             state.defined.incl(adr);
  1911             if (cp < Character.MAX_VALUE) {
  1912                 if (v.start_pc == Character.MAX_VALUE)
  1913                     v.start_pc = (char)cp;
  1918     /** Mark a register as being undefined. */
  1919     public void setUndefined(int adr) {
  1920         state.defined.excl(adr);
  1921         if (adr < lvar.length &&
  1922             lvar[adr] != null &&
  1923             lvar[adr].start_pc != Character.MAX_VALUE) {
  1924             LocalVar v = lvar[adr];
  1925             char length = (char)(curPc() - v.start_pc);
  1926             if (length > 0 && length < Character.MAX_VALUE) {
  1927                 lvar[adr] = v.dup();
  1928                 v.length = length;
  1929                 putVar(v);
  1930             } else {
  1931                 v.start_pc = Character.MAX_VALUE;
  1936     /** End the scope of a variable. */
  1937     private void endScope(int adr) {
  1938         LocalVar v = lvar[adr];
  1939         if (v != null) {
  1940             lvar[adr] = null;
  1941             if (v.start_pc != Character.MAX_VALUE) {
  1942                 char length = (char)(curPc() - v.start_pc);
  1943                 if (length < Character.MAX_VALUE) {
  1944                     v.length = length;
  1945                     putVar(v);
  1946                     fillLocalVarPosition(v);
  1950         state.defined.excl(adr);
  1953     private void fillLocalVarPosition(LocalVar lv) {
  1954         if (lv == null || lv.sym == null
  1955                 || lv.sym.annotations.isTypesEmpty())
  1956             return;
  1957         for (Attribute.TypeCompound ta : lv.sym.getRawTypeAttributes()) {
  1958             TypeAnnotationPosition p = ta.position;
  1959             p.lvarOffset = new int[] { (int)lv.start_pc };
  1960             p.lvarLength = new int[] { (int)lv.length };
  1961             p.lvarIndex = new int[] { (int)lv.reg };
  1962             p.isValidOffset = true;
  1966     // Method to be called after compressCatchTable to
  1967     // fill in the exception table index for type
  1968     // annotations on exception parameters.
  1969     public void fillExceptionParameterPositions() {
  1970         for (int i = 0; i < varBufferSize; ++i) {
  1971             LocalVar lv = varBuffer[i];
  1972             if (lv == null || lv.sym == null
  1973                     || lv.sym.annotations.isTypesEmpty()
  1974                     || !lv.sym.isExceptionParameter())
  1975                 return;
  1977             int exidx = findExceptionIndex(lv);
  1979             for (Attribute.TypeCompound ta : lv.sym.getRawTypeAttributes()) {
  1980                 TypeAnnotationPosition p = ta.position;
  1981                 p.exception_index = exidx;
  1986     private int findExceptionIndex(LocalVar lv) {
  1987         List<char[]> iter = catchInfo.toList();
  1988         int len = catchInfo.length();
  1989         for (int i = 0; i < len; ++i) {
  1990             char[] catchEntry = iter.head;
  1991             iter = iter.tail;
  1992             char handlerpc = catchEntry[2];
  1993             if (lv.start_pc == handlerpc + 1) {
  1994                 return i;
  1997         return -1;
  2000     /** Put a live variable range into the buffer to be output to the
  2001      *  class file.
  2002      */
  2003     void putVar(LocalVar var) {
  2004         // Keep local variables if
  2005         // 1) we need them for debug information
  2006         // 2) it is an exception type and it contains type annotations
  2007         if (!varDebugInfo &&
  2008                 (!var.sym.isExceptionParameter() ||
  2009                 var.sym.annotations.isTypesEmpty())) return;
  2010         if ((var.sym.flags() & Flags.SYNTHETIC) != 0) return;
  2011         if (varBuffer == null)
  2012             varBuffer = new LocalVar[20];
  2013         else
  2014             varBuffer = ArrayUtils.ensureCapacity(varBuffer, varBufferSize);
  2015         varBuffer[varBufferSize++] = var;
  2018     /** Previously live local variables, to be put into the variable table. */
  2019     LocalVar[] varBuffer;
  2020     int varBufferSize;
  2022     /** Create a new local variable address and return it.
  2023      */
  2024     private int newLocal(int typecode) {
  2025         int reg = nextreg;
  2026         int w = width(typecode);
  2027         nextreg = reg + w;
  2028         if (nextreg > max_locals) max_locals = nextreg;
  2029         return reg;
  2032     private int newLocal(Type type) {
  2033         return newLocal(typecode(type));
  2036     public int newLocal(VarSymbol v) {
  2037         int reg = v.adr = newLocal(v.erasure(types));
  2038         addLocalVar(v);
  2039         return reg;
  2042     /** Start a set of fresh registers.
  2043      */
  2044     public void newRegSegment() {
  2045         nextreg = max_locals;
  2048     /** End scopes of all variables with registers &ge; first.
  2049      */
  2050     public void endScopes(int first) {
  2051         int prevNextReg = nextreg;
  2052         nextreg = first;
  2053         for (int i = nextreg; i < prevNextReg; i++) endScope(i);
  2056 /**************************************************************************
  2057  * static tables
  2058  *************************************************************************/
  2060     public static String mnem(int opcode) {
  2061         return Mneumonics.mnem[opcode];
  2064     private static class Mneumonics {
  2065         private final static String[] mnem = new String[ByteCodeCount];
  2066         static {
  2067             mnem[nop] = "nop";
  2068             mnem[aconst_null] = "aconst_null";
  2069             mnem[iconst_m1] = "iconst_m1";
  2070             mnem[iconst_0] = "iconst_0";
  2071             mnem[iconst_1] = "iconst_1";
  2072             mnem[iconst_2] = "iconst_2";
  2073             mnem[iconst_3] = "iconst_3";
  2074             mnem[iconst_4] = "iconst_4";
  2075             mnem[iconst_5] = "iconst_5";
  2076             mnem[lconst_0] = "lconst_0";
  2077             mnem[lconst_1] = "lconst_1";
  2078             mnem[fconst_0] = "fconst_0";
  2079             mnem[fconst_1] = "fconst_1";
  2080             mnem[fconst_2] = "fconst_2";
  2081             mnem[dconst_0] = "dconst_0";
  2082             mnem[dconst_1] = "dconst_1";
  2083             mnem[bipush] = "bipush";
  2084             mnem[sipush] = "sipush";
  2085             mnem[ldc1] = "ldc1";
  2086             mnem[ldc2] = "ldc2";
  2087             mnem[ldc2w] = "ldc2w";
  2088             mnem[iload] = "iload";
  2089             mnem[lload] = "lload";
  2090             mnem[fload] = "fload";
  2091             mnem[dload] = "dload";
  2092             mnem[aload] = "aload";
  2093             mnem[iload_0] = "iload_0";
  2094             mnem[lload_0] = "lload_0";
  2095             mnem[fload_0] = "fload_0";
  2096             mnem[dload_0] = "dload_0";
  2097             mnem[aload_0] = "aload_0";
  2098             mnem[iload_1] = "iload_1";
  2099             mnem[lload_1] = "lload_1";
  2100             mnem[fload_1] = "fload_1";
  2101             mnem[dload_1] = "dload_1";
  2102             mnem[aload_1] = "aload_1";
  2103             mnem[iload_2] = "iload_2";
  2104             mnem[lload_2] = "lload_2";
  2105             mnem[fload_2] = "fload_2";
  2106             mnem[dload_2] = "dload_2";
  2107             mnem[aload_2] = "aload_2";
  2108             mnem[iload_3] = "iload_3";
  2109             mnem[lload_3] = "lload_3";
  2110             mnem[fload_3] = "fload_3";
  2111             mnem[dload_3] = "dload_3";
  2112             mnem[aload_3] = "aload_3";
  2113             mnem[iaload] = "iaload";
  2114             mnem[laload] = "laload";
  2115             mnem[faload] = "faload";
  2116             mnem[daload] = "daload";
  2117             mnem[aaload] = "aaload";
  2118             mnem[baload] = "baload";
  2119             mnem[caload] = "caload";
  2120             mnem[saload] = "saload";
  2121             mnem[istore] = "istore";
  2122             mnem[lstore] = "lstore";
  2123             mnem[fstore] = "fstore";
  2124             mnem[dstore] = "dstore";
  2125             mnem[astore] = "astore";
  2126             mnem[istore_0] = "istore_0";
  2127             mnem[lstore_0] = "lstore_0";
  2128             mnem[fstore_0] = "fstore_0";
  2129             mnem[dstore_0] = "dstore_0";
  2130             mnem[astore_0] = "astore_0";
  2131             mnem[istore_1] = "istore_1";
  2132             mnem[lstore_1] = "lstore_1";
  2133             mnem[fstore_1] = "fstore_1";
  2134             mnem[dstore_1] = "dstore_1";
  2135             mnem[astore_1] = "astore_1";
  2136             mnem[istore_2] = "istore_2";
  2137             mnem[lstore_2] = "lstore_2";
  2138             mnem[fstore_2] = "fstore_2";
  2139             mnem[dstore_2] = "dstore_2";
  2140             mnem[astore_2] = "astore_2";
  2141             mnem[istore_3] = "istore_3";
  2142             mnem[lstore_3] = "lstore_3";
  2143             mnem[fstore_3] = "fstore_3";
  2144             mnem[dstore_3] = "dstore_3";
  2145             mnem[astore_3] = "astore_3";
  2146             mnem[iastore] = "iastore";
  2147             mnem[lastore] = "lastore";
  2148             mnem[fastore] = "fastore";
  2149             mnem[dastore] = "dastore";
  2150             mnem[aastore] = "aastore";
  2151             mnem[bastore] = "bastore";
  2152             mnem[castore] = "castore";
  2153             mnem[sastore] = "sastore";
  2154             mnem[pop] = "pop";
  2155             mnem[pop2] = "pop2";
  2156             mnem[dup] = "dup";
  2157             mnem[dup_x1] = "dup_x1";
  2158             mnem[dup_x2] = "dup_x2";
  2159             mnem[dup2] = "dup2";
  2160             mnem[dup2_x1] = "dup2_x1";
  2161             mnem[dup2_x2] = "dup2_x2";
  2162             mnem[swap] = "swap";
  2163             mnem[iadd] = "iadd";
  2164             mnem[ladd] = "ladd";
  2165             mnem[fadd] = "fadd";
  2166             mnem[dadd] = "dadd";
  2167             mnem[isub] = "isub";
  2168             mnem[lsub] = "lsub";
  2169             mnem[fsub] = "fsub";
  2170             mnem[dsub] = "dsub";
  2171             mnem[imul] = "imul";
  2172             mnem[lmul] = "lmul";
  2173             mnem[fmul] = "fmul";
  2174             mnem[dmul] = "dmul";
  2175             mnem[idiv] = "idiv";
  2176             mnem[ldiv] = "ldiv";
  2177             mnem[fdiv] = "fdiv";
  2178             mnem[ddiv] = "ddiv";
  2179             mnem[imod] = "imod";
  2180             mnem[lmod] = "lmod";
  2181             mnem[fmod] = "fmod";
  2182             mnem[dmod] = "dmod";
  2183             mnem[ineg] = "ineg";
  2184             mnem[lneg] = "lneg";
  2185             mnem[fneg] = "fneg";
  2186             mnem[dneg] = "dneg";
  2187             mnem[ishl] = "ishl";
  2188             mnem[lshl] = "lshl";
  2189             mnem[ishr] = "ishr";
  2190             mnem[lshr] = "lshr";
  2191             mnem[iushr] = "iushr";
  2192             mnem[lushr] = "lushr";
  2193             mnem[iand] = "iand";
  2194             mnem[land] = "land";
  2195             mnem[ior] = "ior";
  2196             mnem[lor] = "lor";
  2197             mnem[ixor] = "ixor";
  2198             mnem[lxor] = "lxor";
  2199             mnem[iinc] = "iinc";
  2200             mnem[i2l] = "i2l";
  2201             mnem[i2f] = "i2f";
  2202             mnem[i2d] = "i2d";
  2203             mnem[l2i] = "l2i";
  2204             mnem[l2f] = "l2f";
  2205             mnem[l2d] = "l2d";
  2206             mnem[f2i] = "f2i";
  2207             mnem[f2l] = "f2l";
  2208             mnem[f2d] = "f2d";
  2209             mnem[d2i] = "d2i";
  2210             mnem[d2l] = "d2l";
  2211             mnem[d2f] = "d2f";
  2212             mnem[int2byte] = "int2byte";
  2213             mnem[int2char] = "int2char";
  2214             mnem[int2short] = "int2short";
  2215             mnem[lcmp] = "lcmp";
  2216             mnem[fcmpl] = "fcmpl";
  2217             mnem[fcmpg] = "fcmpg";
  2218             mnem[dcmpl] = "dcmpl";
  2219             mnem[dcmpg] = "dcmpg";
  2220             mnem[ifeq] = "ifeq";
  2221             mnem[ifne] = "ifne";
  2222             mnem[iflt] = "iflt";
  2223             mnem[ifge] = "ifge";
  2224             mnem[ifgt] = "ifgt";
  2225             mnem[ifle] = "ifle";
  2226             mnem[if_icmpeq] = "if_icmpeq";
  2227             mnem[if_icmpne] = "if_icmpne";
  2228             mnem[if_icmplt] = "if_icmplt";
  2229             mnem[if_icmpge] = "if_icmpge";
  2230             mnem[if_icmpgt] = "if_icmpgt";
  2231             mnem[if_icmple] = "if_icmple";
  2232             mnem[if_acmpeq] = "if_acmpeq";
  2233             mnem[if_acmpne] = "if_acmpne";
  2234             mnem[goto_] = "goto_";
  2235             mnem[jsr] = "jsr";
  2236             mnem[ret] = "ret";
  2237             mnem[tableswitch] = "tableswitch";
  2238             mnem[lookupswitch] = "lookupswitch";
  2239             mnem[ireturn] = "ireturn";
  2240             mnem[lreturn] = "lreturn";
  2241             mnem[freturn] = "freturn";
  2242             mnem[dreturn] = "dreturn";
  2243             mnem[areturn] = "areturn";
  2244             mnem[return_] = "return_";
  2245             mnem[getstatic] = "getstatic";
  2246             mnem[putstatic] = "putstatic";
  2247             mnem[getfield] = "getfield";
  2248             mnem[putfield] = "putfield";
  2249             mnem[invokevirtual] = "invokevirtual";
  2250             mnem[invokespecial] = "invokespecial";
  2251             mnem[invokestatic] = "invokestatic";
  2252             mnem[invokeinterface] = "invokeinterface";
  2253             mnem[invokedynamic] = "invokedynamic";
  2254             mnem[new_] = "new_";
  2255             mnem[newarray] = "newarray";
  2256             mnem[anewarray] = "anewarray";
  2257             mnem[arraylength] = "arraylength";
  2258             mnem[athrow] = "athrow";
  2259             mnem[checkcast] = "checkcast";
  2260             mnem[instanceof_] = "instanceof_";
  2261             mnem[monitorenter] = "monitorenter";
  2262             mnem[monitorexit] = "monitorexit";
  2263             mnem[wide] = "wide";
  2264             mnem[multianewarray] = "multianewarray";
  2265             mnem[if_acmp_null] = "if_acmp_null";
  2266             mnem[if_acmp_nonnull] = "if_acmp_nonnull";
  2267             mnem[goto_w] = "goto_w";
  2268             mnem[jsr_w] = "jsr_w";
  2269             mnem[breakpoint] = "breakpoint";

mercurial