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

Print this page




 416      *  lying between, and including to two environments.
 417      *  @param from    the most deeply nested environment to mark
 418      *  @param to      the least deeply nested environment to mark
 419      */
 420     void endFinalizerGaps(Env<GenContext> from, Env<GenContext> to) {
 421         Env<GenContext> last = null;
 422         while (last != to) {
 423             endFinalizerGap(from);
 424             last = from;
 425             from = from.next;
 426         }
 427     }
 428 
 429     /** Do any of the structures aborted by a non-local exit have
 430      *  finalizers that require an empty stack?
 431      *  @param target      The tree representing the structure that's aborted
 432      *  @param env         The environment current at the non-local exit.
 433      */
 434     boolean hasFinally(JCTree target, Env<GenContext> env) {
 435         while (env.tree != target) {
 436             if (env.tree.getTag() == JCTree.TRY && env.info.finalize.hasFinalizer())
 437                 return true;
 438             env = env.next;
 439         }
 440         return false;
 441     }
 442 
 443 /* ************************************************************************
 444  * Normalizing class-members.
 445  *************************************************************************/
 446 
 447     /** Distribute member initializer code into constructors and <clinit>
 448      *  method.
 449      *  @param defs         The list of class member declarations.
 450      *  @param c            The enclosing class.
 451      */
 452     List<JCTree> normalizeDefs(List<JCTree> defs, ClassSymbol c) {
 453         ListBuffer<JCStatement> initCode = new ListBuffer<JCStatement>();
 454         ListBuffer<JCStatement> clinitCode = new ListBuffer<JCStatement>();
 455         ListBuffer<JCTree> methodDefs = new ListBuffer<JCTree>();
 456         // Sort definitions into three listbuffers:
 457         //  - initCode for instance initializers
 458         //  - clinitCode for class initializers
 459         //  - methodDefs for method definitions
 460         for (List<JCTree> l = defs; l.nonEmpty(); l = l.tail) {
 461             JCTree def = l.head;
 462             switch (def.getTag()) {
 463             case JCTree.BLOCK:
 464                 JCBlock block = (JCBlock)def;
 465                 if ((block.flags & STATIC) != 0)
 466                     clinitCode.append(block);
 467                 else
 468                     initCode.append(block);
 469                 break;
 470             case JCTree.METHODDEF:
 471                 methodDefs.append(def);
 472                 break;
 473             case JCTree.VARDEF:
 474                 JCVariableDecl vdef = (JCVariableDecl) def;
 475                 VarSymbol sym = vdef.sym;
 476                 checkDimension(vdef.pos(), sym.type);
 477                 if (vdef.init != null) {
 478                     if ((sym.flags() & STATIC) == 0) {
 479                         // Always initialize instance variables.
 480                         JCStatement init = make.at(vdef.pos()).
 481                             Assignment(sym, vdef.init);
 482                         initCode.append(init);
 483                         if (endPositions != null) {
 484                             Integer endPos = endPositions.remove(vdef);
 485                             if (endPos != null) endPositions.put(init, endPos);
 486                         }
 487                     } else if (sym.getConstValue() == null) {
 488                         // Initialize class (static) variables only if
 489                         // they are not compile-time constants.
 490                         JCStatement init = make.at(vdef.pos).
 491                             Assignment(sym, vdef.init);
 492                         clinitCode.append(init);
 493                         if (endPositions != null) {


 690     }
 691 
 692     /** Derived visitor method: check whether CharacterRangeTable
 693      *  should be emitted, if so, put a new entry into CRTable
 694      *  and call method to generate bytecode.
 695      *  If not, just call method to generate bytecode.
 696      *  @see    #genStat(Tree, Env)
 697      *
 698      *  @param  tree     The tree to be visited.
 699      *  @param  env      The environment to use.
 700      *  @param  crtFlags The CharacterRangeTable flags
 701      *                   indicating type of the entry.
 702      */
 703     public void genStat(JCTree tree, Env<GenContext> env, int crtFlags) {
 704         if (!genCrt) {
 705             genStat(tree, env);
 706             return;
 707         }
 708         int startpc = code.curPc();
 709         genStat(tree, env);
 710         if (tree.getTag() == JCTree.BLOCK) crtFlags |= CRT_BLOCK;
 711         code.crt.put(tree, crtFlags, startpc, code.curPc());
 712     }
 713 
 714     /** Derived visitor method: generate code for a statement.
 715      */
 716     public void genStat(JCTree tree, Env<GenContext> env) {
 717         if (code.isAlive()) {
 718             code.statBegin(tree.pos);
 719             genDef(tree, env);
 720         } else if (env.info.isSwitch && tree.getTag() == JCTree.VARDEF) {
 721             // variables whose declarations are in a switch
 722             // can be used even if the decl is unreachable.
 723             code.newLocal(((JCVariableDecl) tree).sym);
 724         }
 725     }
 726 
 727     /** Derived visitor method: check whether CharacterRangeTable
 728      *  should be emitted, if so, put a new entry into CRTable
 729      *  and call method to generate bytecode.
 730      *  If not, just call method to generate bytecode.
 731      *  @see    #genStats(List, Env)
 732      *
 733      *  @param  trees    The list of trees to be visited.
 734      *  @param  env      The environment to use.
 735      *  @param  crtFlags The CharacterRangeTable flags
 736      *                   indicating type of the entry.
 737      */
 738     public void genStats(List<JCStatement> trees, Env<GenContext> env, int crtFlags) {
 739         if (!genCrt) {
 740             genStats(trees, env);


 767      *                   indicating type of the entry.
 768      */
 769     public CondItem genCond(JCTree tree, int crtFlags) {
 770         if (!genCrt) return genCond(tree, false);
 771         int startpc = code.curPc();
 772         CondItem item = genCond(tree, (crtFlags & CRT_FLOW_CONTROLLER) != 0);
 773         code.crt.put(tree, crtFlags, startpc, code.curPc());
 774         return item;
 775     }
 776 
 777     /** Derived visitor method: generate code for a boolean
 778      *  expression in a control-flow context.
 779      *  @param _tree         The expression to be visited.
 780      *  @param markBranches The flag to indicate that the condition is
 781      *                      a flow controller so produced conditions
 782      *                      should contain a proper tree to generate
 783      *                      CharacterRangeTable branches for them.
 784      */
 785     public CondItem genCond(JCTree _tree, boolean markBranches) {
 786         JCTree inner_tree = TreeInfo.skipParens(_tree);
 787         if (inner_tree.getTag() == JCTree.CONDEXPR) {
 788             JCConditional tree = (JCConditional)inner_tree;
 789             CondItem cond = genCond(tree.cond, CRT_FLOW_CONTROLLER);
 790             if (cond.isTrue()) {
 791                 code.resolve(cond.trueJumps);
 792                 CondItem result = genCond(tree.truepart, CRT_FLOW_TARGET);
 793                 if (markBranches) result.tree = tree.truepart;
 794                 return result;
 795             }
 796             if (cond.isFalse()) {
 797                 code.resolve(cond.falseJumps);
 798                 CondItem result = genCond(tree.falsepart, CRT_FLOW_TARGET);
 799                 if (markBranches) result.tree = tree.falsepart;
 800                 return result;
 801             }
 802             Chain secondJumps = cond.jumpFalse();
 803             code.resolve(cond.trueJumps);
 804             CondItem first = genCond(tree.truepart, CRT_FLOW_TARGET);
 805             if (markBranches) first.tree = tree.truepart;
 806             Chain falseJumps = first.jumpFalse();
 807             code.resolve(first.trueJumps);


1016         VarSymbol v = tree.sym;
1017         code.newLocal(v);
1018         if (tree.init != null) {
1019             checkStringConstant(tree.init.pos(), v.getConstValue());
1020             if (v.getConstValue() == null || varDebugInfo) {
1021                 genExpr(tree.init, v.erasure(types)).load();
1022                 items.makeLocalItem(v).store();
1023             }
1024         }
1025         checkDimension(tree.pos(), v.type);
1026     }
1027 
1028     public void visitSkip(JCSkip tree) {
1029     }
1030 
1031     public void visitBlock(JCBlock tree) {
1032         int limit = code.nextreg;
1033         Env<GenContext> localEnv = env.dup(tree, new GenContext());
1034         genStats(tree.stats, localEnv);
1035         // End the scope of all block-local variables in variable info.
1036         if (env.tree.getTag() != JCTree.METHODDEF) {
1037             code.statBegin(tree.endpos);
1038             code.endScopes(limit);
1039             code.pendingStatPos = Position.NOPOS;
1040         }
1041     }
1042 
1043     public void visitDoLoop(JCDoWhileLoop tree) {
1044         genLoop(tree, tree.body, tree.cond, List.<JCExpressionStatement>nil(), false);
1045     }
1046 
1047     public void visitWhileLoop(JCWhileLoop tree) {
1048         genLoop(tree, tree.body, tree.cond, List.<JCExpressionStatement>nil(), true);
1049     }
1050 
1051     public void visitForLoop(JCForLoop tree) {
1052         int limit = code.nextreg;
1053         genStats(tree.init, env);
1054         genLoop(tree, tree.body, tree.cond, tree.step, true);
1055         code.endScopes(limit);
1056     }


1611                              CRT_FLOW_CONTROLLER);
1612         Chain elseChain = c.jumpFalse();
1613         if (!c.isFalse()) {
1614             code.resolve(c.trueJumps);
1615             genStat(tree.thenpart, env, CRT_STATEMENT | CRT_FLOW_TARGET);
1616             thenExit = code.branch(goto_);
1617         }
1618         if (elseChain != null) {
1619             code.resolve(elseChain);
1620             if (tree.elsepart != null)
1621                 genStat(tree.elsepart, env,CRT_STATEMENT | CRT_FLOW_TARGET);
1622         }
1623         code.resolve(thenExit);
1624         code.endScopes(limit);
1625     }
1626 
1627     public void visitExec(JCExpressionStatement tree) {
1628         // Optimize x++ to ++x and x-- to --x.
1629         JCExpression e = tree.expr;
1630         switch (e.getTag()) {
1631             case JCTree.POSTINC:
1632                 ((JCUnary) e).setTag(JCTree.PREINC);
1633                 break;
1634             case JCTree.POSTDEC:
1635                 ((JCUnary) e).setTag(JCTree.PREDEC);
1636                 break;
1637         }
1638         genExpr(tree.expr, tree.expr.type).drop();
1639     }
1640 
1641     public void visitBreak(JCBreak tree) {
1642         Env<GenContext> targetEnv = unwind(tree.target, env);
1643         Assert.check(code.state.stacksize == 0);
1644         targetEnv.info.addExit(code.branch(goto_));
1645         endFinalizerGaps(env, targetEnv);
1646     }
1647 
1648     public void visitContinue(JCContinue tree) {
1649         Env<GenContext> targetEnv = unwind(tree.target, env);
1650         Assert.check(code.state.stacksize == 0);
1651         targetEnv.info.addCont(code.branch(goto_));
1652         endFinalizerGaps(env, targetEnv);
1653     }
1654 
1655     public void visitReturn(JCReturn tree) {


1802             if (l.width() > 0) {
1803                 code.emitop0(dup_x1 + 3 * (l.width() - 1));
1804             }
1805 
1806             // Load first string and append to buffer.
1807             l.load();
1808             appendString(tree.lhs);
1809 
1810             // Append all other strings to buffer.
1811             appendStrings(tree.rhs);
1812 
1813             // Convert buffer to string.
1814             bufferToString(tree.pos());
1815         } else {
1816             // Generate code for first expression
1817             l = genExpr(tree.lhs, tree.lhs.type);
1818 
1819             // If we have an increment of -32768 to +32767 of a local
1820             // int variable we can use an incr instruction instead of
1821             // proceeding further.
1822             if ((tree.getTag() == JCTree.PLUS_ASG || tree.getTag() == JCTree.MINUS_ASG) &&
1823                 l instanceof LocalItem &&
1824                 tree.lhs.type.tag <= INT &&
1825                 tree.rhs.type.tag <= INT &&
1826                 tree.rhs.type.constValue() != null) {
1827                 int ival = ((Number) tree.rhs.type.constValue()).intValue();
1828                 if (tree.getTag() == JCTree.MINUS_ASG) ival = -ival;
1829                 ((LocalItem)l).incr(ival);
1830                 result = l;
1831                 return;
1832             }
1833             // Otherwise, duplicate expression, load one copy
1834             // and complete binary operation.
1835             l.duplicate();
1836             l.coerce(operator.type.getParameterTypes().head).load();
1837             completeBinop(tree.lhs, tree.rhs, operator).coerce(tree.lhs.type);
1838         }
1839         result = items.makeAssignItem(l);
1840     }
1841 
1842     public void visitUnary(JCUnary tree) {
1843         OperatorSymbol operator = (OperatorSymbol)tree.operator;
1844         if (tree.getTag() == JCTree.NOT) {
1845             CondItem od = genCond(tree.arg, false);
1846             result = od.negate();
1847         } else {
1848             Item od = genExpr(tree.arg, operator.type.getParameterTypes().head);
1849             switch (tree.getTag()) {
1850             case JCTree.POS:
1851                 result = od.load();
1852                 break;
1853             case JCTree.NEG:
1854                 result = od.load();
1855                 code.emitop0(operator.opcode);
1856                 break;
1857             case JCTree.COMPL:
1858                 result = od.load();
1859                 emitMinusOne(od.typecode);
1860                 code.emitop0(operator.opcode);
1861                 break;
1862             case JCTree.PREINC: case JCTree.PREDEC:
1863                 od.duplicate();
1864                 if (od instanceof LocalItem &&
1865                     (operator.opcode == iadd || operator.opcode == isub)) {
1866                     ((LocalItem)od).incr(tree.getTag() == JCTree.PREINC ? 1 : -1);
1867                     result = od;
1868                 } else {
1869                     od.load();
1870                     code.emitop0(one(od.typecode));
1871                     code.emitop0(operator.opcode);
1872                     // Perform narrowing primitive conversion if byte,
1873                     // char, or short.  Fix for 4304655.
1874                     if (od.typecode != INTcode &&
1875                         Code.truncate(od.typecode) == INTcode)
1876                       code.emitop0(int2byte + od.typecode - BYTEcode);
1877                     result = items.makeAssignItem(od);
1878                 }
1879                 break;
1880             case JCTree.POSTINC: case JCTree.POSTDEC:
1881                 od.duplicate();
1882                 if (od instanceof LocalItem &&
1883                     (operator.opcode == iadd || operator.opcode == isub)) {
1884                     Item res = od.load();
1885                     ((LocalItem)od).incr(tree.getTag() == JCTree.POSTINC ? 1 : -1);
1886                     result = res;
1887                 } else {
1888                     Item res = od.load();
1889                     od.stash(od.typecode);
1890                     code.emitop0(one(od.typecode));
1891                     code.emitop0(operator.opcode);
1892                     // Perform narrowing primitive conversion if byte,
1893                     // char, or short.  Fix for 4304655.
1894                     if (od.typecode != INTcode &&
1895                         Code.truncate(od.typecode) == INTcode)
1896                       code.emitop0(int2byte + od.typecode - BYTEcode);
1897                     od.store();
1898                     result = res;
1899                 }
1900                 break;
1901             case JCTree.NULLCHK:
1902                 result = od.load();
1903                 code.emitop0(dup);
1904                 genNullCheck(tree.pos());
1905                 break;
1906             default:
1907                 Assert.error();
1908             }
1909         }
1910     }
1911 
1912     /** Generate a null check from the object value at stack top. */
1913     private void genNullCheck(DiagnosticPosition pos) {
1914         callMethod(pos, syms.objectType, names.getClass,
1915                    List.<Type>nil(), false);
1916         code.emitop0(pop);
1917     }
1918 
1919     public void visitBinary(JCBinary tree) {
1920         OperatorSymbol operator = (OperatorSymbol)tree.operator;
1921         if (operator.opcode == string_add) {
1922             // Create a string buffer.
1923             makeStringBuffer(tree.pos());
1924             // Append all strings to buffer.
1925             appendStrings(tree);
1926             // Convert buffer to string.
1927             bufferToString(tree.pos());
1928             result = items.makeStackItem(syms.stringType);
1929         } else if (tree.getTag() == JCTree.AND) {
1930             CondItem lcond = genCond(tree.lhs, CRT_FLOW_CONTROLLER);
1931             if (!lcond.isFalse()) {
1932                 Chain falseJumps = lcond.jumpFalse();
1933                 code.resolve(lcond.trueJumps);
1934                 CondItem rcond = genCond(tree.rhs, CRT_FLOW_TARGET);
1935                 result = items.
1936                     makeCondItem(rcond.opcode,
1937                                  rcond.trueJumps,
1938                                  Code.mergeChains(falseJumps,
1939                                                   rcond.falseJumps));
1940             } else {
1941                 result = lcond;
1942             }
1943         } else if (tree.getTag() == JCTree.OR) {
1944             CondItem lcond = genCond(tree.lhs, CRT_FLOW_CONTROLLER);
1945             if (!lcond.isTrue()) {
1946                 Chain trueJumps = lcond.jumpTrue();
1947                 code.resolve(lcond.falseJumps);
1948                 CondItem rcond = genCond(tree.rhs, CRT_FLOW_TARGET);
1949                 result = items.
1950                     makeCondItem(rcond.opcode,
1951                                  Code.mergeChains(trueJumps, rcond.trueJumps),
1952                                  rcond.falseJumps);
1953             } else {
1954                 result = lcond;
1955             }
1956         } else {
1957             Item od = genExpr(tree.lhs, operator.type.getParameterTypes().head);
1958             od.load();
1959             result = completeBinop(tree.lhs, tree.rhs, operator);
1960         }
1961     }
1962 //where
1963         /** Make a new string buffer.


1980         }
1981         Symbol getStringBufferAppend(JCTree tree, Type t) {
1982             Assert.checkNull(t.constValue());
1983             Symbol method = stringBufferAppend.get(t);
1984             if (method == null) {
1985                 method = rs.resolveInternalMethod(tree.pos(),
1986                                                   attrEnv,
1987                                                   stringBufferType,
1988                                                   names.append,
1989                                                   List.of(t),
1990                                                   null);
1991                 stringBufferAppend.put(t, method);
1992             }
1993             return method;
1994         }
1995 
1996         /** Add all strings in tree to string buffer.
1997          */
1998         void appendStrings(JCTree tree) {
1999             tree = TreeInfo.skipParens(tree);
2000             if (tree.getTag() == JCTree.PLUS && tree.type.constValue() == null) {
2001                 JCBinary op = (JCBinary) tree;
2002                 if (op.operator.kind == MTH &&
2003                     ((OperatorSymbol) op.operator).opcode == string_add) {
2004                     appendStrings(op.lhs);
2005                     appendStrings(op.rhs);
2006                     return;
2007                 }
2008             }
2009             genExpr(tree, tree.type).load();
2010             appendString(tree);
2011         }
2012 
2013         /** Convert string buffer on tos to string.
2014          */
2015         void bufferToString(DiagnosticPosition pos) {
2016             callMethod(
2017                 pos,
2018                 stringBufferType,
2019                 names.toString,
2020                 List.<Type>nil(),


2223                 && !allowGenerics // no Miranda methods available with generics
2224                 )
2225                 implementInterfaceMethods(c);
2226             cdef.defs = normalizeDefs(cdef.defs, c);
2227             c.pool = pool;
2228             pool.reset();
2229             Env<GenContext> localEnv =
2230                 new Env<GenContext>(cdef, new GenContext());
2231             localEnv.toplevel = env.toplevel;
2232             localEnv.enclClass = cdef;
2233             for (List<JCTree> l = cdef.defs; l.nonEmpty(); l = l.tail) {
2234                 genDef(l.head, localEnv);
2235             }
2236             if (pool.numEntries() > Pool.MAX_ENTRIES) {
2237                 log.error(cdef.pos(), "limit.pool");
2238                 nerrs++;
2239             }
2240             if (nerrs != 0) {
2241                 // if errors, discard code
2242                 for (List<JCTree> l = cdef.defs; l.nonEmpty(); l = l.tail) {
2243                     if (l.head.getTag() == JCTree.METHODDEF)
2244                         ((JCMethodDecl) l.head).sym.code = null;
2245                 }
2246             }
2247             cdef.defs = List.nil(); // discard trees
2248             return nerrs == 0;
2249         } finally {
2250             // note: this method does NOT support recursion.
2251             attrEnv = null;
2252             this.env = null;
2253             toplevel = null;
2254             endPositions = null;
2255             nerrs = 0;
2256         }
2257     }
2258 
2259 /* ************************************************************************
2260  * Auxiliary classes
2261  *************************************************************************/
2262 
2263     /** An abstract class for finalizer generation.




 416      *  lying between, and including to two environments.
 417      *  @param from    the most deeply nested environment to mark
 418      *  @param to      the least deeply nested environment to mark
 419      */
 420     void endFinalizerGaps(Env<GenContext> from, Env<GenContext> to) {
 421         Env<GenContext> last = null;
 422         while (last != to) {
 423             endFinalizerGap(from);
 424             last = from;
 425             from = from.next;
 426         }
 427     }
 428 
 429     /** Do any of the structures aborted by a non-local exit have
 430      *  finalizers that require an empty stack?
 431      *  @param target      The tree representing the structure that's aborted
 432      *  @param env         The environment current at the non-local exit.
 433      */
 434     boolean hasFinally(JCTree target, Env<GenContext> env) {
 435         while (env.tree != target) {
 436             if (env.tree.getTag() == JCTree.Tag.TRY && env.info.finalize.hasFinalizer())
 437                 return true;
 438             env = env.next;
 439         }
 440         return false;
 441     }
 442 
 443 /* ************************************************************************
 444  * Normalizing class-members.
 445  *************************************************************************/
 446 
 447     /** Distribute member initializer code into constructors and <clinit>
 448      *  method.
 449      *  @param defs         The list of class member declarations.
 450      *  @param c            The enclosing class.
 451      */
 452     List<JCTree> normalizeDefs(List<JCTree> defs, ClassSymbol c) {
 453         ListBuffer<JCStatement> initCode = new ListBuffer<JCStatement>();
 454         ListBuffer<JCStatement> clinitCode = new ListBuffer<JCStatement>();
 455         ListBuffer<JCTree> methodDefs = new ListBuffer<JCTree>();
 456         // Sort definitions into three listbuffers:
 457         //  - initCode for instance initializers
 458         //  - clinitCode for class initializers
 459         //  - methodDefs for method definitions
 460         for (List<JCTree> l = defs; l.nonEmpty(); l = l.tail) {
 461             JCTree def = l.head;
 462             switch (def.getTag()) {
 463             case BLOCK:
 464                 JCBlock block = (JCBlock)def;
 465                 if ((block.flags & STATIC) != 0)
 466                     clinitCode.append(block);
 467                 else
 468                     initCode.append(block);
 469                 break;
 470             case METHODDEF:
 471                 methodDefs.append(def);
 472                 break;
 473             case VARDEF:
 474                 JCVariableDecl vdef = (JCVariableDecl) def;
 475                 VarSymbol sym = vdef.sym;
 476                 checkDimension(vdef.pos(), sym.type);
 477                 if (vdef.init != null) {
 478                     if ((sym.flags() & STATIC) == 0) {
 479                         // Always initialize instance variables.
 480                         JCStatement init = make.at(vdef.pos()).
 481                             Assignment(sym, vdef.init);
 482                         initCode.append(init);
 483                         if (endPositions != null) {
 484                             Integer endPos = endPositions.remove(vdef);
 485                             if (endPos != null) endPositions.put(init, endPos);
 486                         }
 487                     } else if (sym.getConstValue() == null) {
 488                         // Initialize class (static) variables only if
 489                         // they are not compile-time constants.
 490                         JCStatement init = make.at(vdef.pos).
 491                             Assignment(sym, vdef.init);
 492                         clinitCode.append(init);
 493                         if (endPositions != null) {


 690     }
 691 
 692     /** Derived visitor method: check whether CharacterRangeTable
 693      *  should be emitted, if so, put a new entry into CRTable
 694      *  and call method to generate bytecode.
 695      *  If not, just call method to generate bytecode.
 696      *  @see    #genStat(Tree, Env)
 697      *
 698      *  @param  tree     The tree to be visited.
 699      *  @param  env      The environment to use.
 700      *  @param  crtFlags The CharacterRangeTable flags
 701      *                   indicating type of the entry.
 702      */
 703     public void genStat(JCTree tree, Env<GenContext> env, int crtFlags) {
 704         if (!genCrt) {
 705             genStat(tree, env);
 706             return;
 707         }
 708         int startpc = code.curPc();
 709         genStat(tree, env);
 710         if (tree.getTag() == JCTree.Tag.BLOCK) crtFlags |= CRT_BLOCK;
 711         code.crt.put(tree, crtFlags, startpc, code.curPc());
 712     }
 713 
 714     /** Derived visitor method: generate code for a statement.
 715      */
 716     public void genStat(JCTree tree, Env<GenContext> env) {
 717         if (code.isAlive()) {
 718             code.statBegin(tree.pos);
 719             genDef(tree, env);
 720         } else if (env.info.isSwitch && tree.getTag() == JCTree.Tag.VARDEF) {
 721             // variables whose declarations are in a switch
 722             // can be used even if the decl is unreachable.
 723             code.newLocal(((JCVariableDecl) tree).sym);
 724         }
 725     }
 726 
 727     /** Derived visitor method: check whether CharacterRangeTable
 728      *  should be emitted, if so, put a new entry into CRTable
 729      *  and call method to generate bytecode.
 730      *  If not, just call method to generate bytecode.
 731      *  @see    #genStats(List, Env)
 732      *
 733      *  @param  trees    The list of trees to be visited.
 734      *  @param  env      The environment to use.
 735      *  @param  crtFlags The CharacterRangeTable flags
 736      *                   indicating type of the entry.
 737      */
 738     public void genStats(List<JCStatement> trees, Env<GenContext> env, int crtFlags) {
 739         if (!genCrt) {
 740             genStats(trees, env);


 767      *                   indicating type of the entry.
 768      */
 769     public CondItem genCond(JCTree tree, int crtFlags) {
 770         if (!genCrt) return genCond(tree, false);
 771         int startpc = code.curPc();
 772         CondItem item = genCond(tree, (crtFlags & CRT_FLOW_CONTROLLER) != 0);
 773         code.crt.put(tree, crtFlags, startpc, code.curPc());
 774         return item;
 775     }
 776 
 777     /** Derived visitor method: generate code for a boolean
 778      *  expression in a control-flow context.
 779      *  @param _tree         The expression to be visited.
 780      *  @param markBranches The flag to indicate that the condition is
 781      *                      a flow controller so produced conditions
 782      *                      should contain a proper tree to generate
 783      *                      CharacterRangeTable branches for them.
 784      */
 785     public CondItem genCond(JCTree _tree, boolean markBranches) {
 786         JCTree inner_tree = TreeInfo.skipParens(_tree);
 787         if (inner_tree.getTag() == JCTree.Tag.CONDEXPR) {
 788             JCConditional tree = (JCConditional)inner_tree;
 789             CondItem cond = genCond(tree.cond, CRT_FLOW_CONTROLLER);
 790             if (cond.isTrue()) {
 791                 code.resolve(cond.trueJumps);
 792                 CondItem result = genCond(tree.truepart, CRT_FLOW_TARGET);
 793                 if (markBranches) result.tree = tree.truepart;
 794                 return result;
 795             }
 796             if (cond.isFalse()) {
 797                 code.resolve(cond.falseJumps);
 798                 CondItem result = genCond(tree.falsepart, CRT_FLOW_TARGET);
 799                 if (markBranches) result.tree = tree.falsepart;
 800                 return result;
 801             }
 802             Chain secondJumps = cond.jumpFalse();
 803             code.resolve(cond.trueJumps);
 804             CondItem first = genCond(tree.truepart, CRT_FLOW_TARGET);
 805             if (markBranches) first.tree = tree.truepart;
 806             Chain falseJumps = first.jumpFalse();
 807             code.resolve(first.trueJumps);


1016         VarSymbol v = tree.sym;
1017         code.newLocal(v);
1018         if (tree.init != null) {
1019             checkStringConstant(tree.init.pos(), v.getConstValue());
1020             if (v.getConstValue() == null || varDebugInfo) {
1021                 genExpr(tree.init, v.erasure(types)).load();
1022                 items.makeLocalItem(v).store();
1023             }
1024         }
1025         checkDimension(tree.pos(), v.type);
1026     }
1027 
1028     public void visitSkip(JCSkip tree) {
1029     }
1030 
1031     public void visitBlock(JCBlock tree) {
1032         int limit = code.nextreg;
1033         Env<GenContext> localEnv = env.dup(tree, new GenContext());
1034         genStats(tree.stats, localEnv);
1035         // End the scope of all block-local variables in variable info.
1036         if (env.tree.getTag() != JCTree.Tag.METHODDEF) {
1037             code.statBegin(tree.endpos);
1038             code.endScopes(limit);
1039             code.pendingStatPos = Position.NOPOS;
1040         }
1041     }
1042 
1043     public void visitDoLoop(JCDoWhileLoop tree) {
1044         genLoop(tree, tree.body, tree.cond, List.<JCExpressionStatement>nil(), false);
1045     }
1046 
1047     public void visitWhileLoop(JCWhileLoop tree) {
1048         genLoop(tree, tree.body, tree.cond, List.<JCExpressionStatement>nil(), true);
1049     }
1050 
1051     public void visitForLoop(JCForLoop tree) {
1052         int limit = code.nextreg;
1053         genStats(tree.init, env);
1054         genLoop(tree, tree.body, tree.cond, tree.step, true);
1055         code.endScopes(limit);
1056     }


1611                              CRT_FLOW_CONTROLLER);
1612         Chain elseChain = c.jumpFalse();
1613         if (!c.isFalse()) {
1614             code.resolve(c.trueJumps);
1615             genStat(tree.thenpart, env, CRT_STATEMENT | CRT_FLOW_TARGET);
1616             thenExit = code.branch(goto_);
1617         }
1618         if (elseChain != null) {
1619             code.resolve(elseChain);
1620             if (tree.elsepart != null)
1621                 genStat(tree.elsepart, env,CRT_STATEMENT | CRT_FLOW_TARGET);
1622         }
1623         code.resolve(thenExit);
1624         code.endScopes(limit);
1625     }
1626 
1627     public void visitExec(JCExpressionStatement tree) {
1628         // Optimize x++ to ++x and x-- to --x.
1629         JCExpression e = tree.expr;
1630         switch (e.getTag()) {
1631             case POSTINC:
1632                 ((JCUnary) e).setTag(JCTree.Tag.PREINC);
1633                 break;
1634             case POSTDEC:
1635                 ((JCUnary) e).setTag(JCTree.Tag.PREDEC);
1636                 break;
1637         }
1638         genExpr(tree.expr, tree.expr.type).drop();
1639     }
1640 
1641     public void visitBreak(JCBreak tree) {
1642         Env<GenContext> targetEnv = unwind(tree.target, env);
1643         Assert.check(code.state.stacksize == 0);
1644         targetEnv.info.addExit(code.branch(goto_));
1645         endFinalizerGaps(env, targetEnv);
1646     }
1647 
1648     public void visitContinue(JCContinue tree) {
1649         Env<GenContext> targetEnv = unwind(tree.target, env);
1650         Assert.check(code.state.stacksize == 0);
1651         targetEnv.info.addCont(code.branch(goto_));
1652         endFinalizerGaps(env, targetEnv);
1653     }
1654 
1655     public void visitReturn(JCReturn tree) {


1802             if (l.width() > 0) {
1803                 code.emitop0(dup_x1 + 3 * (l.width() - 1));
1804             }
1805 
1806             // Load first string and append to buffer.
1807             l.load();
1808             appendString(tree.lhs);
1809 
1810             // Append all other strings to buffer.
1811             appendStrings(tree.rhs);
1812 
1813             // Convert buffer to string.
1814             bufferToString(tree.pos());
1815         } else {
1816             // Generate code for first expression
1817             l = genExpr(tree.lhs, tree.lhs.type);
1818 
1819             // If we have an increment of -32768 to +32767 of a local
1820             // int variable we can use an incr instruction instead of
1821             // proceeding further.
1822             if ((tree.getTag() == JCTree.Tag.PLUS_ASG || tree.getTag() == JCTree.Tag.MINUS_ASG) &&
1823                 l instanceof LocalItem &&
1824                 tree.lhs.type.tag <= INT &&
1825                 tree.rhs.type.tag <= INT &&
1826                 tree.rhs.type.constValue() != null) {
1827                 int ival = ((Number) tree.rhs.type.constValue()).intValue();
1828                 if (tree.getTag() == JCTree.Tag.MINUS_ASG) ival = -ival;
1829                 ((LocalItem)l).incr(ival);
1830                 result = l;
1831                 return;
1832             }
1833             // Otherwise, duplicate expression, load one copy
1834             // and complete binary operation.
1835             l.duplicate();
1836             l.coerce(operator.type.getParameterTypes().head).load();
1837             completeBinop(tree.lhs, tree.rhs, operator).coerce(tree.lhs.type);
1838         }
1839         result = items.makeAssignItem(l);
1840     }
1841 
1842     public void visitUnary(JCUnary tree) {
1843         OperatorSymbol operator = (OperatorSymbol)tree.operator;
1844         if (tree.getTag() == JCTree.Tag.NOT) {
1845             CondItem od = genCond(tree.arg, false);
1846             result = od.negate();
1847         } else {
1848             Item od = genExpr(tree.arg, operator.type.getParameterTypes().head);
1849             switch (tree.getTag()) {
1850             case POS:
1851                 result = od.load();
1852                 break;
1853             case NEG:
1854                 result = od.load();
1855                 code.emitop0(operator.opcode);
1856                 break;
1857             case COMPL:
1858                 result = od.load();
1859                 emitMinusOne(od.typecode);
1860                 code.emitop0(operator.opcode);
1861                 break;
1862             case PREINC: case PREDEC:
1863                 od.duplicate();
1864                 if (od instanceof LocalItem &&
1865                     (operator.opcode == iadd || operator.opcode == isub)) {
1866                     ((LocalItem)od).incr(tree.getTag() == JCTree.Tag.PREINC ? 1 : -1);
1867                     result = od;
1868                 } else {
1869                     od.load();
1870                     code.emitop0(one(od.typecode));
1871                     code.emitop0(operator.opcode);
1872                     // Perform narrowing primitive conversion if byte,
1873                     // char, or short.  Fix for 4304655.
1874                     if (od.typecode != INTcode &&
1875                         Code.truncate(od.typecode) == INTcode)
1876                       code.emitop0(int2byte + od.typecode - BYTEcode);
1877                     result = items.makeAssignItem(od);
1878                 }
1879                 break;
1880             case POSTINC: case POSTDEC:
1881                 od.duplicate();
1882                 if (od instanceof LocalItem &&
1883                     (operator.opcode == iadd || operator.opcode == isub)) {
1884                     Item res = od.load();
1885                     ((LocalItem)od).incr(tree.getTag() == JCTree.Tag.POSTINC ? 1 : -1);
1886                     result = res;
1887                 } else {
1888                     Item res = od.load();
1889                     od.stash(od.typecode);
1890                     code.emitop0(one(od.typecode));
1891                     code.emitop0(operator.opcode);
1892                     // Perform narrowing primitive conversion if byte,
1893                     // char, or short.  Fix for 4304655.
1894                     if (od.typecode != INTcode &&
1895                         Code.truncate(od.typecode) == INTcode)
1896                       code.emitop0(int2byte + od.typecode - BYTEcode);
1897                     od.store();
1898                     result = res;
1899                 }
1900                 break;
1901             case NULLCHK:
1902                 result = od.load();
1903                 code.emitop0(dup);
1904                 genNullCheck(tree.pos());
1905                 break;
1906             default:
1907                 Assert.error();
1908             }
1909         }
1910     }
1911 
1912     /** Generate a null check from the object value at stack top. */
1913     private void genNullCheck(DiagnosticPosition pos) {
1914         callMethod(pos, syms.objectType, names.getClass,
1915                    List.<Type>nil(), false);
1916         code.emitop0(pop);
1917     }
1918 
1919     public void visitBinary(JCBinary tree) {
1920         OperatorSymbol operator = (OperatorSymbol)tree.operator;
1921         if (operator.opcode == string_add) {
1922             // Create a string buffer.
1923             makeStringBuffer(tree.pos());
1924             // Append all strings to buffer.
1925             appendStrings(tree);
1926             // Convert buffer to string.
1927             bufferToString(tree.pos());
1928             result = items.makeStackItem(syms.stringType);
1929         } else if (tree.getTag() == JCTree.Tag.AND) {
1930             CondItem lcond = genCond(tree.lhs, CRT_FLOW_CONTROLLER);
1931             if (!lcond.isFalse()) {
1932                 Chain falseJumps = lcond.jumpFalse();
1933                 code.resolve(lcond.trueJumps);
1934                 CondItem rcond = genCond(tree.rhs, CRT_FLOW_TARGET);
1935                 result = items.
1936                     makeCondItem(rcond.opcode,
1937                                  rcond.trueJumps,
1938                                  Code.mergeChains(falseJumps,
1939                                                   rcond.falseJumps));
1940             } else {
1941                 result = lcond;
1942             }
1943         } else if (tree.getTag() == JCTree.Tag.OR) {
1944             CondItem lcond = genCond(tree.lhs, CRT_FLOW_CONTROLLER);
1945             if (!lcond.isTrue()) {
1946                 Chain trueJumps = lcond.jumpTrue();
1947                 code.resolve(lcond.falseJumps);
1948                 CondItem rcond = genCond(tree.rhs, CRT_FLOW_TARGET);
1949                 result = items.
1950                     makeCondItem(rcond.opcode,
1951                                  Code.mergeChains(trueJumps, rcond.trueJumps),
1952                                  rcond.falseJumps);
1953             } else {
1954                 result = lcond;
1955             }
1956         } else {
1957             Item od = genExpr(tree.lhs, operator.type.getParameterTypes().head);
1958             od.load();
1959             result = completeBinop(tree.lhs, tree.rhs, operator);
1960         }
1961     }
1962 //where
1963         /** Make a new string buffer.


1980         }
1981         Symbol getStringBufferAppend(JCTree tree, Type t) {
1982             Assert.checkNull(t.constValue());
1983             Symbol method = stringBufferAppend.get(t);
1984             if (method == null) {
1985                 method = rs.resolveInternalMethod(tree.pos(),
1986                                                   attrEnv,
1987                                                   stringBufferType,
1988                                                   names.append,
1989                                                   List.of(t),
1990                                                   null);
1991                 stringBufferAppend.put(t, method);
1992             }
1993             return method;
1994         }
1995 
1996         /** Add all strings in tree to string buffer.
1997          */
1998         void appendStrings(JCTree tree) {
1999             tree = TreeInfo.skipParens(tree);
2000             if (tree.getTag() == JCTree.Tag.PLUS && tree.type.constValue() == null) {
2001                 JCBinary op = (JCBinary) tree;
2002                 if (op.operator.kind == MTH &&
2003                     ((OperatorSymbol) op.operator).opcode == string_add) {
2004                     appendStrings(op.lhs);
2005                     appendStrings(op.rhs);
2006                     return;
2007                 }
2008             }
2009             genExpr(tree, tree.type).load();
2010             appendString(tree);
2011         }
2012 
2013         /** Convert string buffer on tos to string.
2014          */
2015         void bufferToString(DiagnosticPosition pos) {
2016             callMethod(
2017                 pos,
2018                 stringBufferType,
2019                 names.toString,
2020                 List.<Type>nil(),


2223                 && !allowGenerics // no Miranda methods available with generics
2224                 )
2225                 implementInterfaceMethods(c);
2226             cdef.defs = normalizeDefs(cdef.defs, c);
2227             c.pool = pool;
2228             pool.reset();
2229             Env<GenContext> localEnv =
2230                 new Env<GenContext>(cdef, new GenContext());
2231             localEnv.toplevel = env.toplevel;
2232             localEnv.enclClass = cdef;
2233             for (List<JCTree> l = cdef.defs; l.nonEmpty(); l = l.tail) {
2234                 genDef(l.head, localEnv);
2235             }
2236             if (pool.numEntries() > Pool.MAX_ENTRIES) {
2237                 log.error(cdef.pos(), "limit.pool");
2238                 nerrs++;
2239             }
2240             if (nerrs != 0) {
2241                 // if errors, discard code
2242                 for (List<JCTree> l = cdef.defs; l.nonEmpty(); l = l.tail) {
2243                     if (l.head.getTag() == JCTree.Tag.METHODDEF)
2244                         ((JCMethodDecl) l.head).sym.code = null;
2245                 }
2246             }
2247             cdef.defs = List.nil(); // discard trees
2248             return nerrs == 0;
2249         } finally {
2250             // note: this method does NOT support recursion.
2251             attrEnv = null;
2252             this.env = null;
2253             toplevel = null;
2254             endPositions = null;
2255             nerrs = 0;
2256         }
2257     }
2258 
2259 /* ************************************************************************
2260  * Auxiliary classes
2261  *************************************************************************/
2262 
2263     /** An abstract class for finalizer generation.