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.
|