langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Items.java
changeset 25874 83c19f00452c
parent 19941 8b91e8eb2d20
equal deleted inserted replaced
25873:024ed9c9ed13 25874:83c19f00452c
       
     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  */
       
    25 
       
    26 package com.sun.tools.javac.jvm;
       
    27 
       
    28 import com.sun.tools.javac.code.*;
       
    29 import com.sun.tools.javac.code.Symbol.*;
       
    30 import com.sun.tools.javac.code.Type.*;
       
    31 import com.sun.tools.javac.jvm.Code.*;
       
    32 import com.sun.tools.javac.tree.JCTree;
       
    33 import com.sun.tools.javac.util.Assert;
       
    34 
       
    35 import static com.sun.tools.javac.jvm.ByteCodes.*;
       
    36 
       
    37 /** A helper class for code generation. Items are objects
       
    38  *  that stand for addressable entities in the bytecode. Each item
       
    39  *  supports a fixed protocol for loading the item on the stack, storing
       
    40  *  into it, converting it into a jump condition, and several others.
       
    41  *  There are many individual forms of items, such as local, static,
       
    42  *  indexed, or instance variables, values on the top of stack, the
       
    43  *  special values this or super, etc. Individual items are represented as
       
    44  *  inner classes in class Items.
       
    45  *
       
    46  *  <p><b>This is NOT part of any supported API.
       
    47  *  If you write code that depends on this, you do so at your own risk.
       
    48  *  This code and its internal interfaces are subject to change or
       
    49  *  deletion without notice.</b>
       
    50  */
       
    51 public class Items {
       
    52 
       
    53     /** The current constant pool.
       
    54      */
       
    55     Pool pool;
       
    56 
       
    57     /** The current code buffer.
       
    58      */
       
    59     Code code;
       
    60 
       
    61     /** The current symbol table.
       
    62      */
       
    63     Symtab syms;
       
    64 
       
    65     /** Type utilities. */
       
    66     Types types;
       
    67 
       
    68     /** Items that exist only once (flyweight pattern).
       
    69      */
       
    70     private final Item voidItem;
       
    71     private final Item thisItem;
       
    72     private final Item superItem;
       
    73     private final Item[] stackItem = new Item[TypeCodeCount];
       
    74 
       
    75     public Items(Pool pool, Code code, Symtab syms, Types types) {
       
    76         this.code = code;
       
    77         this.pool = pool;
       
    78         this.types = types;
       
    79         voidItem = new Item(VOIDcode) {
       
    80                 public String toString() { return "void"; }
       
    81             };
       
    82         thisItem = new SelfItem(false);
       
    83         superItem = new SelfItem(true);
       
    84         for (int i = 0; i < VOIDcode; i++) stackItem[i] = new StackItem(i);
       
    85         stackItem[VOIDcode] = voidItem;
       
    86         this.syms = syms;
       
    87     }
       
    88 
       
    89     /** Make a void item
       
    90      */
       
    91     Item makeVoidItem() {
       
    92         return voidItem;
       
    93     }
       
    94     /** Make an item representing `this'.
       
    95      */
       
    96     Item makeThisItem() {
       
    97         return thisItem;
       
    98     }
       
    99 
       
   100     /** Make an item representing `super'.
       
   101      */
       
   102     Item makeSuperItem() {
       
   103         return superItem;
       
   104     }
       
   105 
       
   106     /** Make an item representing a value on stack.
       
   107      *  @param type    The value's type.
       
   108      */
       
   109     Item makeStackItem(Type type) {
       
   110         return stackItem[Code.typecode(type)];
       
   111     }
       
   112 
       
   113     /** Make an item representing a dynamically invoked method.
       
   114      *  @param member   The represented symbol.
       
   115      */
       
   116     Item makeDynamicItem(Symbol member) {
       
   117         return new DynamicItem(member);
       
   118     }
       
   119 
       
   120     /** Make an item representing an indexed expression.
       
   121      *  @param type    The expression's type.
       
   122      */
       
   123     Item makeIndexedItem(Type type) {
       
   124         return new IndexedItem(type);
       
   125     }
       
   126 
       
   127     /** Make an item representing a local variable.
       
   128      *  @param v    The represented variable.
       
   129      */
       
   130     LocalItem makeLocalItem(VarSymbol v) {
       
   131         return new LocalItem(v.erasure(types), v.adr);
       
   132     }
       
   133 
       
   134     /** Make an item representing a local anonymous variable.
       
   135      *  @param type  The represented variable's type.
       
   136      *  @param reg   The represented variable's register.
       
   137      */
       
   138     private LocalItem makeLocalItem(Type type, int reg) {
       
   139         return new LocalItem(type, reg);
       
   140     }
       
   141 
       
   142     /** Make an item representing a static variable or method.
       
   143      *  @param member   The represented symbol.
       
   144      */
       
   145     Item makeStaticItem(Symbol member) {
       
   146         return new StaticItem(member);
       
   147     }
       
   148 
       
   149     /** Make an item representing an instance variable or method.
       
   150      *  @param member       The represented symbol.
       
   151      *  @param nonvirtual   Is the reference not virtual? (true for constructors
       
   152      *                      and private members).
       
   153      */
       
   154     Item makeMemberItem(Symbol member, boolean nonvirtual) {
       
   155         return new MemberItem(member, nonvirtual);
       
   156     }
       
   157 
       
   158     /** Make an item representing a literal.
       
   159      *  @param type     The literal's type.
       
   160      *  @param value    The literal's value.
       
   161      */
       
   162     Item makeImmediateItem(Type type, Object value) {
       
   163         return new ImmediateItem(type, value);
       
   164     }
       
   165 
       
   166     /** Make an item representing an assignment expression.
       
   167      *  @param lhs      The item representing the assignment's left hand side.
       
   168      */
       
   169     Item makeAssignItem(Item lhs) {
       
   170         return new AssignItem(lhs);
       
   171     }
       
   172 
       
   173     /** Make an item representing a conditional or unconditional jump.
       
   174      *  @param opcode      The jump's opcode.
       
   175      *  @param trueJumps   A chain encomassing all jumps that can be taken
       
   176      *                     if the condition evaluates to true.
       
   177      *  @param falseJumps  A chain encomassing all jumps that can be taken
       
   178      *                     if the condition evaluates to false.
       
   179      */
       
   180     CondItem makeCondItem(int opcode, Chain trueJumps, Chain falseJumps) {
       
   181         return new CondItem(opcode, trueJumps, falseJumps);
       
   182     }
       
   183 
       
   184     /** Make an item representing a conditional or unconditional jump.
       
   185      *  @param opcode      The jump's opcode.
       
   186      */
       
   187     CondItem makeCondItem(int opcode) {
       
   188         return makeCondItem(opcode, null, null);
       
   189     }
       
   190 
       
   191     /** The base class of all items, which implements default behavior.
       
   192      */
       
   193     abstract class Item {
       
   194 
       
   195         /** The type code of values represented by this item.
       
   196          */
       
   197         int typecode;
       
   198 
       
   199         Item(int typecode) {
       
   200             this.typecode = typecode;
       
   201         }
       
   202 
       
   203         /** Generate code to load this item onto stack.
       
   204          */
       
   205         Item load() {
       
   206             throw new AssertionError();
       
   207         }
       
   208 
       
   209         /** Generate code to store top of stack into this item.
       
   210          */
       
   211         void store() {
       
   212             throw new AssertionError("store unsupported: " + this);
       
   213         }
       
   214 
       
   215         /** Generate code to invoke method represented by this item.
       
   216          */
       
   217         Item invoke() {
       
   218             throw new AssertionError(this);
       
   219         }
       
   220 
       
   221         /** Generate code to use this item twice.
       
   222          */
       
   223         void duplicate() {}
       
   224 
       
   225         /** Generate code to avoid having to use this item.
       
   226          */
       
   227         void drop() {}
       
   228 
       
   229         /** Generate code to stash a copy of top of stack - of typecode toscode -
       
   230          *  under this item.
       
   231          */
       
   232         void stash(int toscode) {
       
   233             stackItem[toscode].duplicate();
       
   234         }
       
   235 
       
   236         /** Generate code to turn item into a testable condition.
       
   237          */
       
   238         CondItem mkCond() {
       
   239             load();
       
   240             return makeCondItem(ifne);
       
   241         }
       
   242 
       
   243         /** Generate code to coerce item to given type code.
       
   244          *  @param targetcode    The type code to coerce to.
       
   245          */
       
   246         Item coerce(int targetcode) {
       
   247             if (typecode == targetcode)
       
   248                 return this;
       
   249             else {
       
   250                 load();
       
   251                 int typecode1 = Code.truncate(typecode);
       
   252                 int targetcode1 = Code.truncate(targetcode);
       
   253                 if (typecode1 != targetcode1) {
       
   254                     int offset = targetcode1 > typecode1 ? targetcode1 - 1
       
   255                         : targetcode1;
       
   256                     code.emitop0(i2l + typecode1 * 3 + offset);
       
   257                 }
       
   258                 if (targetcode != targetcode1) {
       
   259                     code.emitop0(int2byte + targetcode - BYTEcode);
       
   260                 }
       
   261                 return stackItem[targetcode];
       
   262             }
       
   263         }
       
   264 
       
   265         /** Generate code to coerce item to given type.
       
   266          *  @param targettype    The type to coerce to.
       
   267          */
       
   268         Item coerce(Type targettype) {
       
   269             return coerce(Code.typecode(targettype));
       
   270         }
       
   271 
       
   272         /** Return the width of this item on stack as a number of words.
       
   273          */
       
   274         int width() {
       
   275             return 0;
       
   276         }
       
   277 
       
   278         public abstract String toString();
       
   279     }
       
   280 
       
   281     /** An item representing a value on stack.
       
   282      */
       
   283     class StackItem extends Item {
       
   284 
       
   285         StackItem(int typecode) {
       
   286             super(typecode);
       
   287         }
       
   288 
       
   289         Item load() {
       
   290             return this;
       
   291         }
       
   292 
       
   293         void duplicate() {
       
   294             code.emitop0(width() == 2 ? dup2 : dup);
       
   295         }
       
   296 
       
   297         void drop() {
       
   298             code.emitop0(width() == 2 ? pop2 : pop);
       
   299         }
       
   300 
       
   301         void stash(int toscode) {
       
   302             code.emitop0(
       
   303                 (width() == 2 ? dup_x2 : dup_x1) + 3 * (Code.width(toscode) - 1));
       
   304         }
       
   305 
       
   306         int width() {
       
   307             return Code.width(typecode);
       
   308         }
       
   309 
       
   310         public String toString() {
       
   311             return "stack(" + typecodeNames[typecode] + ")";
       
   312         }
       
   313     }
       
   314 
       
   315     /** An item representing an indexed expression.
       
   316      */
       
   317     class IndexedItem extends Item {
       
   318 
       
   319         IndexedItem(Type type) {
       
   320             super(Code.typecode(type));
       
   321         }
       
   322 
       
   323         Item load() {
       
   324             code.emitop0(iaload + typecode);
       
   325             return stackItem[typecode];
       
   326         }
       
   327 
       
   328         void store() {
       
   329             code.emitop0(iastore + typecode);
       
   330         }
       
   331 
       
   332         void duplicate() {
       
   333             code.emitop0(dup2);
       
   334         }
       
   335 
       
   336         void drop() {
       
   337             code.emitop0(pop2);
       
   338         }
       
   339 
       
   340         void stash(int toscode) {
       
   341             code.emitop0(dup_x2 + 3 * (Code.width(toscode) - 1));
       
   342         }
       
   343 
       
   344         int width() {
       
   345             return 2;
       
   346         }
       
   347 
       
   348         public String toString() {
       
   349             return "indexed(" + ByteCodes.typecodeNames[typecode] + ")";
       
   350         }
       
   351     }
       
   352 
       
   353     /** An item representing `this' or `super'.
       
   354      */
       
   355     class SelfItem extends Item {
       
   356 
       
   357         /** Flag which determines whether this item represents `this' or `super'.
       
   358          */
       
   359         boolean isSuper;
       
   360 
       
   361         SelfItem(boolean isSuper) {
       
   362             super(OBJECTcode);
       
   363             this.isSuper = isSuper;
       
   364         }
       
   365 
       
   366         Item load() {
       
   367             code.emitop0(aload_0);
       
   368             return stackItem[typecode];
       
   369         }
       
   370 
       
   371         public String toString() {
       
   372             return isSuper ? "super" : "this";
       
   373         }
       
   374     }
       
   375 
       
   376     /** An item representing a local variable.
       
   377      */
       
   378     class LocalItem extends Item {
       
   379 
       
   380         /** The variable's register.
       
   381          */
       
   382         int reg;
       
   383 
       
   384         /** The variable's type.
       
   385          */
       
   386         Type type;
       
   387 
       
   388         LocalItem(Type type, int reg) {
       
   389             super(Code.typecode(type));
       
   390             Assert.check(reg >= 0);
       
   391             this.type = type;
       
   392             this.reg = reg;
       
   393         }
       
   394 
       
   395         Item load() {
       
   396             if (reg <= 3)
       
   397                 code.emitop0(iload_0 + Code.truncate(typecode) * 4 + reg);
       
   398             else
       
   399                 code.emitop1w(iload + Code.truncate(typecode), reg);
       
   400             return stackItem[typecode];
       
   401         }
       
   402 
       
   403         void store() {
       
   404             if (reg <= 3)
       
   405                 code.emitop0(istore_0 + Code.truncate(typecode) * 4 + reg);
       
   406             else
       
   407                 code.emitop1w(istore + Code.truncate(typecode), reg);
       
   408             code.setDefined(reg);
       
   409         }
       
   410 
       
   411         void incr(int x) {
       
   412             if (typecode == INTcode && x >= -32768 && x <= 32767) {
       
   413                 code.emitop1w(iinc, reg, x);
       
   414             } else {
       
   415                 load();
       
   416                 if (x >= 0) {
       
   417                     makeImmediateItem(syms.intType, x).load();
       
   418                     code.emitop0(iadd);
       
   419                 } else {
       
   420                     makeImmediateItem(syms.intType, -x).load();
       
   421                     code.emitop0(isub);
       
   422                 }
       
   423                 makeStackItem(syms.intType).coerce(typecode);
       
   424                 store();
       
   425             }
       
   426         }
       
   427 
       
   428         public String toString() {
       
   429             return "localItem(type=" + type + "; reg=" + reg + ")";
       
   430         }
       
   431     }
       
   432 
       
   433     /** An item representing a static variable or method.
       
   434      */
       
   435     class StaticItem extends Item {
       
   436 
       
   437         /** The represented symbol.
       
   438          */
       
   439         Symbol member;
       
   440 
       
   441         StaticItem(Symbol member) {
       
   442             super(Code.typecode(member.erasure(types)));
       
   443             this.member = member;
       
   444         }
       
   445 
       
   446         Item load() {
       
   447             code.emitop2(getstatic, pool.put(member));
       
   448             return stackItem[typecode];
       
   449         }
       
   450 
       
   451         void store() {
       
   452             code.emitop2(putstatic, pool.put(member));
       
   453         }
       
   454 
       
   455         Item invoke() {
       
   456             MethodType mtype = (MethodType)member.erasure(types);
       
   457             int rescode = Code.typecode(mtype.restype);
       
   458             code.emitInvokestatic(pool.put(member), mtype);
       
   459             return stackItem[rescode];
       
   460         }
       
   461 
       
   462         public String toString() {
       
   463             return "static(" + member + ")";
       
   464         }
       
   465     }
       
   466 
       
   467     /** An item representing a dynamic call site.
       
   468      */
       
   469     class DynamicItem extends StaticItem {
       
   470         DynamicItem(Symbol member) {
       
   471             super(member);
       
   472         }
       
   473 
       
   474         Item load() {
       
   475             assert false;
       
   476             return null;
       
   477         }
       
   478 
       
   479         void store() {
       
   480             assert false;
       
   481         }
       
   482 
       
   483         Item invoke() {
       
   484             // assert target.hasNativeInvokeDynamic();
       
   485             MethodType mtype = (MethodType)member.erasure(types);
       
   486             int rescode = Code.typecode(mtype.restype);
       
   487             code.emitInvokedynamic(pool.put(member), mtype);
       
   488             return stackItem[rescode];
       
   489         }
       
   490 
       
   491         public String toString() {
       
   492             return "dynamic(" + member + ")";
       
   493         }
       
   494     }
       
   495 
       
   496     /** An item representing an instance variable or method.
       
   497      */
       
   498     class MemberItem extends Item {
       
   499 
       
   500         /** The represented symbol.
       
   501          */
       
   502         Symbol member;
       
   503 
       
   504         /** Flag that determines whether or not access is virtual.
       
   505          */
       
   506         boolean nonvirtual;
       
   507 
       
   508         MemberItem(Symbol member, boolean nonvirtual) {
       
   509             super(Code.typecode(member.erasure(types)));
       
   510             this.member = member;
       
   511             this.nonvirtual = nonvirtual;
       
   512         }
       
   513 
       
   514         Item load() {
       
   515             code.emitop2(getfield, pool.put(member));
       
   516             return stackItem[typecode];
       
   517         }
       
   518 
       
   519         void store() {
       
   520             code.emitop2(putfield, pool.put(member));
       
   521         }
       
   522 
       
   523         Item invoke() {
       
   524             MethodType mtype = (MethodType)member.externalType(types);
       
   525             int rescode = Code.typecode(mtype.restype);
       
   526             if ((member.owner.flags() & Flags.INTERFACE) != 0 && !nonvirtual) {
       
   527                 code.emitInvokeinterface(pool.put(member), mtype);
       
   528             } else if (nonvirtual) {
       
   529                 code.emitInvokespecial(pool.put(member), mtype);
       
   530             } else {
       
   531                 code.emitInvokevirtual(pool.put(member), mtype);
       
   532             }
       
   533             return stackItem[rescode];
       
   534         }
       
   535 
       
   536         void duplicate() {
       
   537             stackItem[OBJECTcode].duplicate();
       
   538         }
       
   539 
       
   540         void drop() {
       
   541             stackItem[OBJECTcode].drop();
       
   542         }
       
   543 
       
   544         void stash(int toscode) {
       
   545             stackItem[OBJECTcode].stash(toscode);
       
   546         }
       
   547 
       
   548         int width() {
       
   549             return 1;
       
   550         }
       
   551 
       
   552         public String toString() {
       
   553             return "member(" + member + (nonvirtual ? " nonvirtual)" : ")");
       
   554         }
       
   555     }
       
   556 
       
   557     /** An item representing a literal.
       
   558      */
       
   559     class ImmediateItem extends Item {
       
   560 
       
   561         /** The literal's value.
       
   562          */
       
   563         Object value;
       
   564 
       
   565         ImmediateItem(Type type, Object value) {
       
   566             super(Code.typecode(type));
       
   567             this.value = value;
       
   568         }
       
   569 
       
   570         private void ldc() {
       
   571             int idx = pool.put(value);
       
   572             if (typecode == LONGcode || typecode == DOUBLEcode) {
       
   573                 code.emitop2(ldc2w, idx);
       
   574             } else {
       
   575                 code.emitLdc(idx);
       
   576             }
       
   577         }
       
   578 
       
   579         Item load() {
       
   580             switch (typecode) {
       
   581             case INTcode: case BYTEcode: case SHORTcode: case CHARcode:
       
   582                 int ival = ((Number)value).intValue();
       
   583                 if (-1 <= ival && ival <= 5)
       
   584                     code.emitop0(iconst_0 + ival);
       
   585                 else if (Byte.MIN_VALUE <= ival && ival <= Byte.MAX_VALUE)
       
   586                     code.emitop1(bipush, ival);
       
   587                 else if (Short.MIN_VALUE <= ival && ival <= Short.MAX_VALUE)
       
   588                     code.emitop2(sipush, ival);
       
   589                 else
       
   590                     ldc();
       
   591                 break;
       
   592             case LONGcode:
       
   593                 long lval = ((Number)value).longValue();
       
   594                 if (lval == 0 || lval == 1)
       
   595                     code.emitop0(lconst_0 + (int)lval);
       
   596                 else
       
   597                     ldc();
       
   598                 break;
       
   599             case FLOATcode:
       
   600                 float fval = ((Number)value).floatValue();
       
   601                 if (isPosZero(fval) || fval == 1.0 || fval == 2.0)
       
   602                     code.emitop0(fconst_0 + (int)fval);
       
   603                 else {
       
   604                     ldc();
       
   605                 }
       
   606                 break;
       
   607             case DOUBLEcode:
       
   608                 double dval = ((Number)value).doubleValue();
       
   609                 if (isPosZero(dval) || dval == 1.0)
       
   610                     code.emitop0(dconst_0 + (int)dval);
       
   611                 else
       
   612                     ldc();
       
   613                 break;
       
   614             case OBJECTcode:
       
   615                 ldc();
       
   616                 break;
       
   617             default:
       
   618                 Assert.error();
       
   619             }
       
   620             return stackItem[typecode];
       
   621         }
       
   622         //where
       
   623             /** Return true iff float number is positive 0.
       
   624              */
       
   625             private boolean isPosZero(float x) {
       
   626                 return x == 0.0f && 1.0f / x > 0.0f;
       
   627             }
       
   628             /** Return true iff double number is positive 0.
       
   629              */
       
   630             private boolean isPosZero(double x) {
       
   631                 return x == 0.0d && 1.0d / x > 0.0d;
       
   632             }
       
   633 
       
   634         CondItem mkCond() {
       
   635             int ival = ((Number)value).intValue();
       
   636             return makeCondItem(ival != 0 ? goto_ : dontgoto);
       
   637         }
       
   638 
       
   639         Item coerce(int targetcode) {
       
   640             if (typecode == targetcode) {
       
   641                 return this;
       
   642             } else {
       
   643                 switch (targetcode) {
       
   644                 case INTcode:
       
   645                     if (Code.truncate(typecode) == INTcode)
       
   646                         return this;
       
   647                     else
       
   648                         return new ImmediateItem(
       
   649                             syms.intType,
       
   650                             ((Number)value).intValue());
       
   651                 case LONGcode:
       
   652                     return new ImmediateItem(
       
   653                         syms.longType,
       
   654                         ((Number)value).longValue());
       
   655                 case FLOATcode:
       
   656                     return new ImmediateItem(
       
   657                         syms.floatType,
       
   658                         ((Number)value).floatValue());
       
   659                 case DOUBLEcode:
       
   660                     return new ImmediateItem(
       
   661                         syms.doubleType,
       
   662                         ((Number)value).doubleValue());
       
   663                 case BYTEcode:
       
   664                     return new ImmediateItem(
       
   665                         syms.byteType,
       
   666                         (int)(byte)((Number)value).intValue());
       
   667                 case CHARcode:
       
   668                     return new ImmediateItem(
       
   669                         syms.charType,
       
   670                         (int)(char)((Number)value).intValue());
       
   671                 case SHORTcode:
       
   672                     return new ImmediateItem(
       
   673                         syms.shortType,
       
   674                         (int)(short)((Number)value).intValue());
       
   675                 default:
       
   676                     return super.coerce(targetcode);
       
   677                 }
       
   678             }
       
   679         }
       
   680 
       
   681         public String toString() {
       
   682             return "immediate(" + value + ")";
       
   683         }
       
   684     }
       
   685 
       
   686     /** An item representing an assignment expressions.
       
   687      */
       
   688     class AssignItem extends Item {
       
   689 
       
   690         /** The item representing the assignment's left hand side.
       
   691          */
       
   692         Item lhs;
       
   693 
       
   694         AssignItem(Item lhs) {
       
   695             super(lhs.typecode);
       
   696             this.lhs = lhs;
       
   697         }
       
   698 
       
   699         Item load() {
       
   700             lhs.stash(typecode);
       
   701             lhs.store();
       
   702             return stackItem[typecode];
       
   703         }
       
   704 
       
   705         void duplicate() {
       
   706             load().duplicate();
       
   707         }
       
   708 
       
   709         void drop() {
       
   710             lhs.store();
       
   711         }
       
   712 
       
   713         void stash(int toscode) {
       
   714             Assert.error();
       
   715         }
       
   716 
       
   717         int width() {
       
   718             return lhs.width() + Code.width(typecode);
       
   719         }
       
   720 
       
   721         public String toString() {
       
   722             return "assign(lhs = " + lhs + ")";
       
   723         }
       
   724     }
       
   725 
       
   726     /** An item representing a conditional or unconditional jump.
       
   727      */
       
   728     class CondItem extends Item {
       
   729 
       
   730         /** A chain encomassing all jumps that can be taken
       
   731          *  if the condition evaluates to true.
       
   732          */
       
   733         Chain trueJumps;
       
   734 
       
   735         /** A chain encomassing all jumps that can be taken
       
   736          *  if the condition evaluates to false.
       
   737          */
       
   738         Chain falseJumps;
       
   739 
       
   740         /** The jump's opcode.
       
   741          */
       
   742         int opcode;
       
   743 
       
   744         /*
       
   745          *  An abstract syntax tree of this item. It is needed
       
   746          *  for branch entries in 'CharacterRangeTable' attribute.
       
   747          */
       
   748         JCTree tree;
       
   749 
       
   750         CondItem(int opcode, Chain truejumps, Chain falsejumps) {
       
   751             super(BYTEcode);
       
   752             this.opcode = opcode;
       
   753             this.trueJumps = truejumps;
       
   754             this.falseJumps = falsejumps;
       
   755         }
       
   756 
       
   757         Item load() {
       
   758             Chain trueChain = null;
       
   759             Chain falseChain = jumpFalse();
       
   760             if (!isFalse()) {
       
   761                 code.resolve(trueJumps);
       
   762                 code.emitop0(iconst_1);
       
   763                 trueChain = code.branch(goto_);
       
   764             }
       
   765             if (falseChain != null) {
       
   766                 code.resolve(falseChain);
       
   767                 code.emitop0(iconst_0);
       
   768             }
       
   769             code.resolve(trueChain);
       
   770             return stackItem[typecode];
       
   771         }
       
   772 
       
   773         void duplicate() {
       
   774             load().duplicate();
       
   775         }
       
   776 
       
   777         void drop() {
       
   778             load().drop();
       
   779         }
       
   780 
       
   781         void stash(int toscode) {
       
   782             Assert.error();
       
   783         }
       
   784 
       
   785         CondItem mkCond() {
       
   786             return this;
       
   787         }
       
   788 
       
   789         Chain jumpTrue() {
       
   790             if (tree == null) return Code.mergeChains(trueJumps, code.branch(opcode));
       
   791             // we should proceed further in -Xjcov mode only
       
   792             int startpc = code.curCP();
       
   793             Chain c = Code.mergeChains(trueJumps, code.branch(opcode));
       
   794             code.crt.put(tree, CRTable.CRT_BRANCH_TRUE, startpc, code.curCP());
       
   795             return c;
       
   796         }
       
   797 
       
   798         Chain jumpFalse() {
       
   799             if (tree == null) return Code.mergeChains(falseJumps, code.branch(Code.negate(opcode)));
       
   800             // we should proceed further in -Xjcov mode only
       
   801             int startpc = code.curCP();
       
   802             Chain c = Code.mergeChains(falseJumps, code.branch(Code.negate(opcode)));
       
   803             code.crt.put(tree, CRTable.CRT_BRANCH_FALSE, startpc, code.curCP());
       
   804             return c;
       
   805         }
       
   806 
       
   807         CondItem negate() {
       
   808             CondItem c = new CondItem(Code.negate(opcode), falseJumps, trueJumps);
       
   809             c.tree = tree;
       
   810             return c;
       
   811         }
       
   812 
       
   813         int width() {
       
   814             // a CondItem doesn't have a size on the stack per se.
       
   815             throw new AssertionError();
       
   816         }
       
   817 
       
   818         boolean isTrue() {
       
   819             return falseJumps == null && opcode == goto_;
       
   820         }
       
   821 
       
   822         boolean isFalse() {
       
   823             return trueJumps == null && opcode == dontgoto;
       
   824         }
       
   825 
       
   826         public String toString() {
       
   827             return "cond(" + Code.mnem(opcode) + ")";
       
   828         }
       
   829     }
       
   830 }