< prev index next >

src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java

Print this page
rev 3498 : More review cleanups


   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 java.util.*;
  29 
  30 import com.sun.tools.javac.util.*;
  31 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
  32 import com.sun.tools.javac.util.List;
  33 import com.sun.tools.javac.code.*;
  34 import com.sun.tools.javac.code.Attribute.TypeCompound;
  35 import com.sun.tools.javac.code.Symbol.VarSymbol;
  36 import com.sun.tools.javac.comp.*;
  37 import com.sun.tools.javac.tree.*;
  38 
  39 import com.sun.tools.javac.code.Symbol.*;
  40 import com.sun.tools.javac.code.Type.*;
  41 import com.sun.tools.javac.jvm.Code.*;
  42 import com.sun.tools.javac.jvm.Items.*;
  43 import com.sun.tools.javac.tree.EndPosTable;
  44 import com.sun.tools.javac.tree.JCTree.*;
  45 
  46 import static com.sun.tools.javac.code.Flags.*;
  47 import static com.sun.tools.javac.code.Kinds.Kind.*;
  48 import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE;
  49 import static com.sun.tools.javac.code.TypeTag.*;
  50 import static com.sun.tools.javac.jvm.ByteCodes.*;
  51 import static com.sun.tools.javac.jvm.CRTFlags.*;
  52 import static com.sun.tools.javac.main.Option.*;
  53 import static com.sun.tools.javac.tree.JCTree.Tag.*;
  54 
  55 /** This pass maps flat Java (i.e. without inner classes) to bytecodes.
  56  *
  57  *  <p><b>This is NOT part of any supported API.
  58  *  If you write code that depends on this, you do so at your own risk.
  59  *  This code and its internal interfaces are subject to change or
  60  *  deletion without notice.</b>
  61  */
  62 public class Gen extends JCTree.Visitor {
  63     protected static final Context.Key<Gen> genKey = new Context.Key<>();
  64 
  65     private final Log log;
  66     private final Symtab syms;
  67     private final Check chk;
  68     private final Resolve rs;
  69     private final TreeMaker make;
  70     private final Names names;
  71     private final Target target;
  72     private final Map<Type,Symbol> stringBufferAppend;
  73     private Name accessDollar;
  74     private final Types types;
  75     private final Lower lower;
  76     private final Flow flow;
  77     private final Annotate annotate;

  78 
  79     /** Format of stackmap tables to be generated. */
  80     private final Code.StackMapFormat stackMap;
  81 
  82     /** A type that serves as the expected type for all method expressions.
  83      */
  84     private final Type methodType;
  85 
  86     public static Gen instance(Context context) {
  87         Gen instance = context.get(genKey);
  88         if (instance == null)
  89             instance = new Gen(context);
  90         return instance;
  91     }
  92 
  93     /** Constant pool, reset by genClass.
  94      */
  95     private Pool pool;
  96 
  97     protected Gen(Context context) {
  98         context.put(genKey, this);
  99 
 100         names = Names.instance(context);
 101         log = Log.instance(context);
 102         syms = Symtab.instance(context);
 103         chk = Check.instance(context);
 104         rs = Resolve.instance(context);
 105         make = TreeMaker.instance(context);
 106         target = Target.instance(context);
 107         types = Types.instance(context);


 108         methodType = new MethodType(null, null, null, syms.methodClass);
 109         stringBufferAppend = new HashMap<>();
 110         accessDollar = names.
 111             fromString("access" + target.syntheticNameChar());
 112         flow = Flow.instance(context);
 113         lower = Lower.instance(context);
 114 
 115         Options options = Options.instance(context);
 116         lineDebugInfo =
 117             options.isUnset(G_CUSTOM) ||
 118             options.isSet(G_CUSTOM, "lines");
 119         varDebugInfo =
 120             options.isUnset(G_CUSTOM)
 121             ? options.isSet(G)
 122             : options.isSet(G_CUSTOM, "vars");
 123         genCrt = options.isSet(XJCOV);
 124         debugCode = options.isSet("debugcode");
 125         allowInvokedynamic = target.hasInvokedynamic() || options.isSet("invokedynamic");
 126         allowBetterNullChecks = target.hasObjects();
 127         pool = new Pool(types);
 128 
 129         // ignore cldc because we cannot have both stackmap formats


 736             code.resolve(cond.trueJumps);
 737             CondItem first = genCond(tree.truepart, CRT_FLOW_TARGET);
 738             if (markBranches) first.tree = tree.truepart;
 739             Chain falseJumps = first.jumpFalse();
 740             code.resolve(first.trueJumps);
 741             Chain trueJumps = code.branch(goto_);
 742             code.resolve(secondJumps);
 743             CondItem second = genCond(tree.falsepart, CRT_FLOW_TARGET);
 744             CondItem result = items.makeCondItem(second.opcode,
 745                                       Code.mergeChains(trueJumps, second.trueJumps),
 746                                       Code.mergeChains(falseJumps, second.falseJumps));
 747             if (markBranches) result.tree = tree.falsepart;
 748             return result;
 749         } else {
 750             CondItem result = genExpr(_tree, syms.booleanType).mkCond();
 751             if (markBranches) result.tree = _tree;
 752             return result;
 753         }
 754     }
 755 












 756     /** Visitor class for expressions which might be constant expressions.
 757      *  This class is a subset of TreeScanner. Intended to visit trees pruned by
 758      *  Lower as long as constant expressions looking for references to any
 759      *  ClassSymbol. Any such reference will be added to the constant pool so
 760      *  automated tools can detect class dependencies better.
 761      */
 762     class ClassReferenceVisitor extends JCTree.Visitor {
 763 
 764         @Override
 765         public void visitTree(JCTree tree) {}
 766 
 767         @Override
 768         public void visitBinary(JCBinary tree) {
 769             tree.lhs.accept(this);
 770             tree.rhs.accept(this);
 771         }
 772 
 773         @Override
 774         public void visitSelect(JCFieldAccess tree) {
 775             if (tree.selected.type.hasTag(CLASS)) {


1878         result = genExpr(tree.expr, tree.expr.type);
1879     }
1880 
1881     public void visitAssign(JCAssign tree) {
1882         Item l = genExpr(tree.lhs, tree.lhs.type);
1883         genExpr(tree.rhs, tree.lhs.type).load();
1884         if (tree.rhs.type.hasTag(BOT)) {
1885             /* This is just a case of widening reference conversion that per 5.1.5 simply calls
1886                for "regarding a reference as having some other type in a manner that can be proved
1887                correct at compile time."
1888             */
1889             code.state.forceStackTop(tree.lhs.type);
1890         }
1891         result = items.makeAssignItem(l);
1892     }
1893 
1894     public void visitAssignop(JCAssignOp tree) {
1895         OperatorSymbol operator = (OperatorSymbol) tree.operator;
1896         Item l;
1897         if (operator.opcode == string_add) {
1898             // Generate code to make a string buffer
1899             makeStringBuffer(tree.pos());
1900 
1901             // Generate code for first string, possibly save one
1902             // copy under buffer
1903             l = genExpr(tree.lhs, tree.lhs.type);
1904             if (l.width() > 0) {
1905                 code.emitop0(dup_x1 + 3 * (l.width() - 1));
1906             }
1907 
1908             // Load first string and append to buffer.
1909             l.load();
1910             appendString(tree.lhs);
1911 
1912             // Append all other strings to buffer.
1913             appendStrings(tree.rhs);
1914 
1915             // Convert buffer to string.
1916             bufferToString(tree.pos());
1917         } else {
1918             // Generate code for first expression
1919             l = genExpr(tree.lhs, tree.lhs.type);
1920 
1921             // If we have an increment of -32768 to +32767 of a local
1922             // int variable we can use an incr instruction instead of
1923             // proceeding further.
1924             if ((tree.hasTag(PLUS_ASG) || tree.hasTag(MINUS_ASG)) &&
1925                 l instanceof LocalItem &&
1926                 tree.lhs.type.getTag().isSubRangeOf(INT) &&
1927                 tree.rhs.type.getTag().isSubRangeOf(INT) &&
1928                 tree.rhs.type.constValue() != null) {
1929                 int ival = ((Number) tree.rhs.type.constValue()).intValue();
1930                 if (tree.hasTag(MINUS_ASG)) ival = -ival;
1931                 ((LocalItem)l).incr(ival);
1932                 result = l;
1933                 return;
1934             }
1935             // Otherwise, duplicate expression, load one copy
1936             // and complete binary operation.


2009                 Assert.error();
2010             }
2011         }
2012     }
2013 
2014     /** Generate a null check from the object value at stack top. */
2015     private void genNullCheck(DiagnosticPosition pos) {
2016         if (allowBetterNullChecks) {
2017             callMethod(pos, syms.objectsType, names.requireNonNull,
2018                     List.of(syms.objectType), true);
2019         } else {
2020             callMethod(pos, syms.objectType, names.getClass,
2021                     List.<Type>nil(), false);
2022         }
2023         code.emitop0(pop);
2024     }
2025 
2026     public void visitBinary(JCBinary tree) {
2027         OperatorSymbol operator = (OperatorSymbol)tree.operator;
2028         if (operator.opcode == string_add) {
2029             // Create a string buffer.
2030             makeStringBuffer(tree.pos());
2031             // Append all strings to buffer.
2032             appendStrings(tree);
2033             // Convert buffer to string.
2034             bufferToString(tree.pos());
2035             result = items.makeStackItem(syms.stringType);
2036         } else if (tree.hasTag(AND)) {
2037             CondItem lcond = genCond(tree.lhs, CRT_FLOW_CONTROLLER);
2038             if (!lcond.isFalse()) {
2039                 Chain falseJumps = lcond.jumpFalse();
2040                 code.resolve(lcond.trueJumps);
2041                 CondItem rcond = genCond(tree.rhs, CRT_FLOW_TARGET);
2042                 result = items.
2043                     makeCondItem(rcond.opcode,
2044                                  rcond.trueJumps,
2045                                  Code.mergeChains(falseJumps,
2046                                                   rcond.falseJumps));
2047             } else {
2048                 result = lcond;
2049             }
2050         } else if (tree.hasTag(OR)) {
2051             CondItem lcond = genCond(tree.lhs, CRT_FLOW_CONTROLLER);
2052             if (!lcond.isTrue()) {
2053                 Chain trueJumps = lcond.jumpTrue();
2054                 code.resolve(lcond.falseJumps);
2055                 CondItem rcond = genCond(tree.rhs, CRT_FLOW_TARGET);
2056                 result = items.
2057                     makeCondItem(rcond.opcode,
2058                                  Code.mergeChains(trueJumps, rcond.trueJumps),
2059                                  rcond.falseJumps);
2060             } else {
2061                 result = lcond;
2062             }
2063         } else {
2064             Item od = genExpr(tree.lhs, operator.type.getParameterTypes().head);
2065             od.load();
2066             result = completeBinop(tree.lhs, tree.rhs, operator);
2067         }
2068     }
2069 //where
2070         /** Make a new string buffer.
2071          */
2072         void makeStringBuffer(DiagnosticPosition pos) {
2073             code.emitop2(new_, makeRef(pos, syms.stringBuilderType));
2074             code.emitop0(dup);
2075             callMethod(
2076                     pos, syms.stringBuilderType, names.init, List.<Type>nil(), false);
2077         }
2078 
2079         /** Append value (on tos) to string buffer (on tos - 1).
2080          */
2081         void appendString(JCTree tree) {
2082             Type t = tree.type.baseType();
2083             if (!t.isPrimitive() && t.tsym != syms.stringType.tsym) {
2084                 t = syms.objectType;
2085             }
2086             items.makeMemberItem(getStringBufferAppend(tree, t), false).invoke();
2087         }
2088         Symbol getStringBufferAppend(JCTree tree, Type t) {
2089             Assert.checkNull(t.constValue());
2090             Symbol method = stringBufferAppend.get(t);
2091             if (method == null) {
2092                 method = rs.resolveInternalMethod(tree.pos(),
2093                                                   attrEnv,
2094                                                   syms.stringBuilderType,
2095                                                   names.append,
2096                                                   List.of(t),
2097                                                   null);
2098                 stringBufferAppend.put(t, method);
2099             }
2100             return method;
2101         }
2102 
2103         /** Add all strings in tree to string buffer.
2104          */
2105         void appendStrings(JCTree tree) {
2106             tree = TreeInfo.skipParens(tree);
2107             if (tree.hasTag(PLUS) && tree.type.constValue() == null) {
2108                 JCBinary op = (JCBinary) tree;
2109                 if (op.operator.kind == MTH &&
2110                     ((OperatorSymbol) op.operator).opcode == string_add) {
2111                     appendStrings(op.lhs);
2112                     appendStrings(op.rhs);
2113                     return;
2114                 }
2115             }
2116             genExpr(tree, tree.type).load();
2117             appendString(tree);
2118         }
2119 
2120         /** Convert string buffer on tos to string.
2121          */
2122         void bufferToString(DiagnosticPosition pos) {
2123             callMethod(
2124                     pos,
2125                     syms.stringBuilderType,
2126                     names.toString,
2127                     List.<Type>nil(),
2128                     false);
2129         }
2130 
2131         /** Complete generating code for operation, with left operand
2132          *  already on stack.
2133          *  @param lhs       The tree representing the left operand.
2134          *  @param rhs       The tree representing the right operand.
2135          *  @param operator  The operator symbol.
2136          */
2137         Item completeBinop(JCTree lhs, JCTree rhs, OperatorSymbol operator) {
2138             MethodType optype = (MethodType)operator.type;
2139             int opcode = operator.opcode;
2140             if (opcode >= if_icmpeq && opcode <= if_icmple &&
2141                 rhs.type.constValue() instanceof Number &&
2142                 ((Number) rhs.type.constValue()).intValue() == 0) {
2143                 opcode = opcode + (ifeq - if_icmpeq);
2144             } else if (opcode >= if_acmpeq && opcode <= if_acmpne &&
2145                        TreeInfo.isNull(rhs)) {
2146                 opcode = opcode + (if_acmp_null - if_acmpeq);
2147             } else {
2148                 // The expected type of the right operand is
2149                 // the second parameter type of the operator, except for




   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.util.*;
  29 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
  30 import com.sun.tools.javac.util.List;
  31 import com.sun.tools.javac.code.*;
  32 import com.sun.tools.javac.code.Attribute.TypeCompound;
  33 import com.sun.tools.javac.code.Symbol.VarSymbol;
  34 import com.sun.tools.javac.comp.*;
  35 import com.sun.tools.javac.tree.*;
  36 
  37 import com.sun.tools.javac.code.Symbol.*;
  38 import com.sun.tools.javac.code.Type.*;
  39 import com.sun.tools.javac.jvm.Code.*;
  40 import com.sun.tools.javac.jvm.Items.*;
  41 import com.sun.tools.javac.tree.EndPosTable;
  42 import com.sun.tools.javac.tree.JCTree.*;
  43 
  44 import static com.sun.tools.javac.code.Flags.*;
  45 import static com.sun.tools.javac.code.Kinds.Kind.*;

  46 import static com.sun.tools.javac.code.TypeTag.*;
  47 import static com.sun.tools.javac.jvm.ByteCodes.*;
  48 import static com.sun.tools.javac.jvm.CRTFlags.*;
  49 import static com.sun.tools.javac.main.Option.*;
  50 import static com.sun.tools.javac.tree.JCTree.Tag.*;
  51 
  52 /** This pass maps flat Java (i.e. without inner classes) to bytecodes.
  53  *
  54  *  <p><b>This is NOT part of any supported API.
  55  *  If you write code that depends on this, you do so at your own risk.
  56  *  This code and its internal interfaces are subject to change or
  57  *  deletion without notice.</b>
  58  */
  59 public class Gen extends JCTree.Visitor {
  60     protected static final Context.Key<Gen> genKey = new Context.Key<>();
  61 
  62     private final Log log;
  63     private final Symtab syms;
  64     private final Check chk;
  65     private final Resolve rs;
  66     private final TreeMaker make;
  67     private final Names names;
  68     private final Target target;

  69     private Name accessDollar;
  70     private final Types types;
  71     private final Lower lower;
  72     private final Flow flow;
  73     private final Annotate annotate;
  74     private final StringConcat concat;
  75 
  76     /** Format of stackmap tables to be generated. */
  77     private final Code.StackMapFormat stackMap;
  78 
  79     /** A type that serves as the expected type for all method expressions.
  80      */
  81     private final Type methodType;
  82 
  83     public static Gen instance(Context context) {
  84         Gen instance = context.get(genKey);
  85         if (instance == null)
  86             instance = new Gen(context);
  87         return instance;
  88     }
  89 
  90     /** Constant pool, reset by genClass.
  91      */
  92     private Pool pool;
  93 
  94     protected Gen(Context context) {
  95         context.put(genKey, this);
  96 
  97         names = Names.instance(context);
  98         log = Log.instance(context);
  99         syms = Symtab.instance(context);
 100         chk = Check.instance(context);
 101         rs = Resolve.instance(context);
 102         make = TreeMaker.instance(context);
 103         target = Target.instance(context);
 104         types = Types.instance(context);
 105         concat = StringConcat.instance(context);
 106 
 107         methodType = new MethodType(null, null, null, syms.methodClass);

 108         accessDollar = names.
 109             fromString("access" + target.syntheticNameChar());
 110         flow = Flow.instance(context);
 111         lower = Lower.instance(context);
 112 
 113         Options options = Options.instance(context);
 114         lineDebugInfo =
 115             options.isUnset(G_CUSTOM) ||
 116             options.isSet(G_CUSTOM, "lines");
 117         varDebugInfo =
 118             options.isUnset(G_CUSTOM)
 119             ? options.isSet(G)
 120             : options.isSet(G_CUSTOM, "vars");
 121         genCrt = options.isSet(XJCOV);
 122         debugCode = options.isSet("debugcode");
 123         allowInvokedynamic = target.hasInvokedynamic() || options.isSet("invokedynamic");
 124         allowBetterNullChecks = target.hasObjects();
 125         pool = new Pool(types);
 126 
 127         // ignore cldc because we cannot have both stackmap formats


 734             code.resolve(cond.trueJumps);
 735             CondItem first = genCond(tree.truepart, CRT_FLOW_TARGET);
 736             if (markBranches) first.tree = tree.truepart;
 737             Chain falseJumps = first.jumpFalse();
 738             code.resolve(first.trueJumps);
 739             Chain trueJumps = code.branch(goto_);
 740             code.resolve(secondJumps);
 741             CondItem second = genCond(tree.falsepart, CRT_FLOW_TARGET);
 742             CondItem result = items.makeCondItem(second.opcode,
 743                                       Code.mergeChains(trueJumps, second.trueJumps),
 744                                       Code.mergeChains(falseJumps, second.falseJumps));
 745             if (markBranches) result.tree = tree.falsepart;
 746             return result;
 747         } else {
 748             CondItem result = genExpr(_tree, syms.booleanType).mkCond();
 749             if (markBranches) result.tree = _tree;
 750             return result;
 751         }
 752     }
 753 
 754     public Code getCode() {
 755         return code;
 756     }
 757 
 758     public Items getItems() {
 759         return items;
 760     }
 761 
 762     public Env<AttrContext> getAttrEnv() {
 763         return attrEnv;
 764     }
 765 
 766     /** Visitor class for expressions which might be constant expressions.
 767      *  This class is a subset of TreeScanner. Intended to visit trees pruned by
 768      *  Lower as long as constant expressions looking for references to any
 769      *  ClassSymbol. Any such reference will be added to the constant pool so
 770      *  automated tools can detect class dependencies better.
 771      */
 772     class ClassReferenceVisitor extends JCTree.Visitor {
 773 
 774         @Override
 775         public void visitTree(JCTree tree) {}
 776 
 777         @Override
 778         public void visitBinary(JCBinary tree) {
 779             tree.lhs.accept(this);
 780             tree.rhs.accept(this);
 781         }
 782 
 783         @Override
 784         public void visitSelect(JCFieldAccess tree) {
 785             if (tree.selected.type.hasTag(CLASS)) {


1888         result = genExpr(tree.expr, tree.expr.type);
1889     }
1890 
1891     public void visitAssign(JCAssign tree) {
1892         Item l = genExpr(tree.lhs, tree.lhs.type);
1893         genExpr(tree.rhs, tree.lhs.type).load();
1894         if (tree.rhs.type.hasTag(BOT)) {
1895             /* This is just a case of widening reference conversion that per 5.1.5 simply calls
1896                for "regarding a reference as having some other type in a manner that can be proved
1897                correct at compile time."
1898             */
1899             code.state.forceStackTop(tree.lhs.type);
1900         }
1901         result = items.makeAssignItem(l);
1902     }
1903 
1904     public void visitAssignop(JCAssignOp tree) {
1905         OperatorSymbol operator = (OperatorSymbol) tree.operator;
1906         Item l;
1907         if (operator.opcode == string_add) {
1908             l = concat.makeConcat(tree);


















1909         } else {
1910             // Generate code for first expression
1911             l = genExpr(tree.lhs, tree.lhs.type);
1912 
1913             // If we have an increment of -32768 to +32767 of a local
1914             // int variable we can use an incr instruction instead of
1915             // proceeding further.
1916             if ((tree.hasTag(PLUS_ASG) || tree.hasTag(MINUS_ASG)) &&
1917                 l instanceof LocalItem &&
1918                 tree.lhs.type.getTag().isSubRangeOf(INT) &&
1919                 tree.rhs.type.getTag().isSubRangeOf(INT) &&
1920                 tree.rhs.type.constValue() != null) {
1921                 int ival = ((Number) tree.rhs.type.constValue()).intValue();
1922                 if (tree.hasTag(MINUS_ASG)) ival = -ival;
1923                 ((LocalItem)l).incr(ival);
1924                 result = l;
1925                 return;
1926             }
1927             // Otherwise, duplicate expression, load one copy
1928             // and complete binary operation.


2001                 Assert.error();
2002             }
2003         }
2004     }
2005 
2006     /** Generate a null check from the object value at stack top. */
2007     private void genNullCheck(DiagnosticPosition pos) {
2008         if (allowBetterNullChecks) {
2009             callMethod(pos, syms.objectsType, names.requireNonNull,
2010                     List.of(syms.objectType), true);
2011         } else {
2012             callMethod(pos, syms.objectType, names.getClass,
2013                     List.<Type>nil(), false);
2014         }
2015         code.emitop0(pop);
2016     }
2017 
2018     public void visitBinary(JCBinary tree) {
2019         OperatorSymbol operator = (OperatorSymbol)tree.operator;
2020         if (operator.opcode == string_add) {
2021             result = concat.makeConcat(tree);






2022         } else if (tree.hasTag(AND)) {
2023             CondItem lcond = genCond(tree.lhs, CRT_FLOW_CONTROLLER);
2024             if (!lcond.isFalse()) {
2025                 Chain falseJumps = lcond.jumpFalse();
2026                 code.resolve(lcond.trueJumps);
2027                 CondItem rcond = genCond(tree.rhs, CRT_FLOW_TARGET);
2028                 result = items.
2029                     makeCondItem(rcond.opcode,
2030                                  rcond.trueJumps,
2031                                  Code.mergeChains(falseJumps,
2032                                                   rcond.falseJumps));
2033             } else {
2034                 result = lcond;
2035             }
2036         } else if (tree.hasTag(OR)) {
2037             CondItem lcond = genCond(tree.lhs, CRT_FLOW_CONTROLLER);
2038             if (!lcond.isTrue()) {
2039                 Chain trueJumps = lcond.jumpTrue();
2040                 code.resolve(lcond.falseJumps);
2041                 CondItem rcond = genCond(tree.rhs, CRT_FLOW_TARGET);
2042                 result = items.
2043                     makeCondItem(rcond.opcode,
2044                                  Code.mergeChains(trueJumps, rcond.trueJumps),
2045                                  rcond.falseJumps);
2046             } else {
2047                 result = lcond;
2048             }
2049         } else {
2050             Item od = genExpr(tree.lhs, operator.type.getParameterTypes().head);
2051             od.load();
2052             result = completeBinop(tree.lhs, tree.rhs, operator);
2053         }
2054     }









2055 



















































2056 
2057         /** Complete generating code for operation, with left operand
2058          *  already on stack.
2059          *  @param lhs       The tree representing the left operand.
2060          *  @param rhs       The tree representing the right operand.
2061          *  @param operator  The operator symbol.
2062          */
2063         Item completeBinop(JCTree lhs, JCTree rhs, OperatorSymbol operator) {
2064             MethodType optype = (MethodType)operator.type;
2065             int opcode = operator.opcode;
2066             if (opcode >= if_icmpeq && opcode <= if_icmple &&
2067                 rhs.type.constValue() instanceof Number &&
2068                 ((Number) rhs.type.constValue()).intValue() == 0) {
2069                 opcode = opcode + (ifeq - if_icmpeq);
2070             } else if (opcode >= if_acmpeq && opcode <= if_acmpne &&
2071                        TreeInfo.isNull(rhs)) {
2072                 opcode = opcode + (if_acmp_null - if_acmpeq);
2073             } else {
2074                 // The expected type of the right operand is
2075                 // the second parameter type of the operator, except for


< prev index next >