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

changeset 1127
ca49d50318dc
parent 1109
3cdfa97e1be9
child 1138
7375d4979bd3
equal deleted inserted replaced
1126:11c184155128 1127:ca49d50318dc
45 import static com.sun.tools.javac.code.Kinds.*; 45 import static com.sun.tools.javac.code.Kinds.*;
46 import static com.sun.tools.javac.code.TypeTags.*; 46 import static com.sun.tools.javac.code.TypeTags.*;
47 import static com.sun.tools.javac.jvm.ByteCodes.*; 47 import static com.sun.tools.javac.jvm.ByteCodes.*;
48 import static com.sun.tools.javac.jvm.CRTFlags.*; 48 import static com.sun.tools.javac.jvm.CRTFlags.*;
49 import static com.sun.tools.javac.main.OptionName.*; 49 import static com.sun.tools.javac.main.OptionName.*;
50 import static com.sun.tools.javac.tree.JCTree.Tag.*;
51 import static com.sun.tools.javac.tree.JCTree.Tag.BLOCK;
50 52
51 /** This pass maps flat Java (i.e. without inner classes) to bytecodes. 53 /** This pass maps flat Java (i.e. without inner classes) to bytecodes.
52 * 54 *
53 * <p><b>This is NOT part of any supported API. 55 * <p><b>This is NOT part of any supported API.
54 * If you write code that depends on this, you do so at your own risk. 56 * If you write code that depends on this, you do so at your own risk.
431 * @param target The tree representing the structure that's aborted 433 * @param target The tree representing the structure that's aborted
432 * @param env The environment current at the non-local exit. 434 * @param env The environment current at the non-local exit.
433 */ 435 */
434 boolean hasFinally(JCTree target, Env<GenContext> env) { 436 boolean hasFinally(JCTree target, Env<GenContext> env) {
435 while (env.tree != target) { 437 while (env.tree != target) {
436 if (env.tree.getTag() == JCTree.TRY && env.info.finalize.hasFinalizer()) 438 if (env.tree.hasTag(TRY) && env.info.finalize.hasFinalizer())
437 return true; 439 return true;
438 env = env.next; 440 env = env.next;
439 } 441 }
440 return false; 442 return false;
441 } 443 }
458 // - clinitCode for class initializers 460 // - clinitCode for class initializers
459 // - methodDefs for method definitions 461 // - methodDefs for method definitions
460 for (List<JCTree> l = defs; l.nonEmpty(); l = l.tail) { 462 for (List<JCTree> l = defs; l.nonEmpty(); l = l.tail) {
461 JCTree def = l.head; 463 JCTree def = l.head;
462 switch (def.getTag()) { 464 switch (def.getTag()) {
463 case JCTree.BLOCK: 465 case BLOCK:
464 JCBlock block = (JCBlock)def; 466 JCBlock block = (JCBlock)def;
465 if ((block.flags & STATIC) != 0) 467 if ((block.flags & STATIC) != 0)
466 clinitCode.append(block); 468 clinitCode.append(block);
467 else 469 else
468 initCode.append(block); 470 initCode.append(block);
469 break; 471 break;
470 case JCTree.METHODDEF: 472 case METHODDEF:
471 methodDefs.append(def); 473 methodDefs.append(def);
472 break; 474 break;
473 case JCTree.VARDEF: 475 case VARDEF:
474 JCVariableDecl vdef = (JCVariableDecl) def; 476 JCVariableDecl vdef = (JCVariableDecl) def;
475 VarSymbol sym = vdef.sym; 477 VarSymbol sym = vdef.sym;
476 checkDimension(vdef.pos(), sym.type); 478 checkDimension(vdef.pos(), sym.type);
477 if (vdef.init != null) { 479 if (vdef.init != null) {
478 if ((sym.flags() & STATIC) == 0) { 480 if ((sym.flags() & STATIC) == 0) {
705 genStat(tree, env); 707 genStat(tree, env);
706 return; 708 return;
707 } 709 }
708 int startpc = code.curPc(); 710 int startpc = code.curPc();
709 genStat(tree, env); 711 genStat(tree, env);
710 if (tree.getTag() == JCTree.BLOCK) crtFlags |= CRT_BLOCK; 712 if (tree.hasTag(BLOCK)) crtFlags |= CRT_BLOCK;
711 code.crt.put(tree, crtFlags, startpc, code.curPc()); 713 code.crt.put(tree, crtFlags, startpc, code.curPc());
712 } 714 }
713 715
714 /** Derived visitor method: generate code for a statement. 716 /** Derived visitor method: generate code for a statement.
715 */ 717 */
716 public void genStat(JCTree tree, Env<GenContext> env) { 718 public void genStat(JCTree tree, Env<GenContext> env) {
717 if (code.isAlive()) { 719 if (code.isAlive()) {
718 code.statBegin(tree.pos); 720 code.statBegin(tree.pos);
719 genDef(tree, env); 721 genDef(tree, env);
720 } else if (env.info.isSwitch && tree.getTag() == JCTree.VARDEF) { 722 } else if (env.info.isSwitch && tree.hasTag(VARDEF)) {
721 // variables whose declarations are in a switch 723 // variables whose declarations are in a switch
722 // can be used even if the decl is unreachable. 724 // can be used even if the decl is unreachable.
723 code.newLocal(((JCVariableDecl) tree).sym); 725 code.newLocal(((JCVariableDecl) tree).sym);
724 } 726 }
725 } 727 }
782 * should contain a proper tree to generate 784 * should contain a proper tree to generate
783 * CharacterRangeTable branches for them. 785 * CharacterRangeTable branches for them.
784 */ 786 */
785 public CondItem genCond(JCTree _tree, boolean markBranches) { 787 public CondItem genCond(JCTree _tree, boolean markBranches) {
786 JCTree inner_tree = TreeInfo.skipParens(_tree); 788 JCTree inner_tree = TreeInfo.skipParens(_tree);
787 if (inner_tree.getTag() == JCTree.CONDEXPR) { 789 if (inner_tree.hasTag(CONDEXPR)) {
788 JCConditional tree = (JCConditional)inner_tree; 790 JCConditional tree = (JCConditional)inner_tree;
789 CondItem cond = genCond(tree.cond, CRT_FLOW_CONTROLLER); 791 CondItem cond = genCond(tree.cond, CRT_FLOW_CONTROLLER);
790 if (cond.isTrue()) { 792 if (cond.isTrue()) {
791 code.resolve(cond.trueJumps); 793 code.resolve(cond.trueJumps);
792 CondItem result = genCond(tree.truepart, CRT_FLOW_TARGET); 794 CondItem result = genCond(tree.truepart, CRT_FLOW_TARGET);
1031 public void visitBlock(JCBlock tree) { 1033 public void visitBlock(JCBlock tree) {
1032 int limit = code.nextreg; 1034 int limit = code.nextreg;
1033 Env<GenContext> localEnv = env.dup(tree, new GenContext()); 1035 Env<GenContext> localEnv = env.dup(tree, new GenContext());
1034 genStats(tree.stats, localEnv); 1036 genStats(tree.stats, localEnv);
1035 // End the scope of all block-local variables in variable info. 1037 // End the scope of all block-local variables in variable info.
1036 if (env.tree.getTag() != JCTree.METHODDEF) { 1038 if (!env.tree.hasTag(METHODDEF)) {
1037 code.statBegin(tree.endpos); 1039 code.statBegin(tree.endpos);
1038 code.endScopes(limit); 1040 code.endScopes(limit);
1039 code.pendingStatPos = Position.NOPOS; 1041 code.pendingStatPos = Position.NOPOS;
1040 } 1042 }
1041 } 1043 }
1626 1628
1627 public void visitExec(JCExpressionStatement tree) { 1629 public void visitExec(JCExpressionStatement tree) {
1628 // Optimize x++ to ++x and x-- to --x. 1630 // Optimize x++ to ++x and x-- to --x.
1629 JCExpression e = tree.expr; 1631 JCExpression e = tree.expr;
1630 switch (e.getTag()) { 1632 switch (e.getTag()) {
1631 case JCTree.POSTINC: 1633 case POSTINC:
1632 ((JCUnary) e).setTag(JCTree.PREINC); 1634 ((JCUnary) e).setTag(PREINC);
1633 break; 1635 break;
1634 case JCTree.POSTDEC: 1636 case POSTDEC:
1635 ((JCUnary) e).setTag(JCTree.PREDEC); 1637 ((JCUnary) e).setTag(PREDEC);
1636 break; 1638 break;
1637 } 1639 }
1638 genExpr(tree.expr, tree.expr.type).drop(); 1640 genExpr(tree.expr, tree.expr.type).drop();
1639 } 1641 }
1640 1642
1817 l = genExpr(tree.lhs, tree.lhs.type); 1819 l = genExpr(tree.lhs, tree.lhs.type);
1818 1820
1819 // If we have an increment of -32768 to +32767 of a local 1821 // If we have an increment of -32768 to +32767 of a local
1820 // int variable we can use an incr instruction instead of 1822 // int variable we can use an incr instruction instead of
1821 // proceeding further. 1823 // proceeding further.
1822 if ((tree.getTag() == JCTree.PLUS_ASG || tree.getTag() == JCTree.MINUS_ASG) && 1824 if ((tree.hasTag(PLUS_ASG) || tree.hasTag(MINUS_ASG)) &&
1823 l instanceof LocalItem && 1825 l instanceof LocalItem &&
1824 tree.lhs.type.tag <= INT && 1826 tree.lhs.type.tag <= INT &&
1825 tree.rhs.type.tag <= INT && 1827 tree.rhs.type.tag <= INT &&
1826 tree.rhs.type.constValue() != null) { 1828 tree.rhs.type.constValue() != null) {
1827 int ival = ((Number) tree.rhs.type.constValue()).intValue(); 1829 int ival = ((Number) tree.rhs.type.constValue()).intValue();
1828 if (tree.getTag() == JCTree.MINUS_ASG) ival = -ival; 1830 if (tree.hasTag(MINUS_ASG)) ival = -ival;
1829 ((LocalItem)l).incr(ival); 1831 ((LocalItem)l).incr(ival);
1830 result = l; 1832 result = l;
1831 return; 1833 return;
1832 } 1834 }
1833 // Otherwise, duplicate expression, load one copy 1835 // Otherwise, duplicate expression, load one copy
1839 result = items.makeAssignItem(l); 1841 result = items.makeAssignItem(l);
1840 } 1842 }
1841 1843
1842 public void visitUnary(JCUnary tree) { 1844 public void visitUnary(JCUnary tree) {
1843 OperatorSymbol operator = (OperatorSymbol)tree.operator; 1845 OperatorSymbol operator = (OperatorSymbol)tree.operator;
1844 if (tree.getTag() == JCTree.NOT) { 1846 if (tree.hasTag(NOT)) {
1845 CondItem od = genCond(tree.arg, false); 1847 CondItem od = genCond(tree.arg, false);
1846 result = od.negate(); 1848 result = od.negate();
1847 } else { 1849 } else {
1848 Item od = genExpr(tree.arg, operator.type.getParameterTypes().head); 1850 Item od = genExpr(tree.arg, operator.type.getParameterTypes().head);
1849 switch (tree.getTag()) { 1851 switch (tree.getTag()) {
1850 case JCTree.POS: 1852 case POS:
1851 result = od.load(); 1853 result = od.load();
1852 break; 1854 break;
1853 case JCTree.NEG: 1855 case NEG:
1854 result = od.load(); 1856 result = od.load();
1855 code.emitop0(operator.opcode); 1857 code.emitop0(operator.opcode);
1856 break; 1858 break;
1857 case JCTree.COMPL: 1859 case COMPL:
1858 result = od.load(); 1860 result = od.load();
1859 emitMinusOne(od.typecode); 1861 emitMinusOne(od.typecode);
1860 code.emitop0(operator.opcode); 1862 code.emitop0(operator.opcode);
1861 break; 1863 break;
1862 case JCTree.PREINC: case JCTree.PREDEC: 1864 case PREINC: case PREDEC:
1863 od.duplicate(); 1865 od.duplicate();
1864 if (od instanceof LocalItem && 1866 if (od instanceof LocalItem &&
1865 (operator.opcode == iadd || operator.opcode == isub)) { 1867 (operator.opcode == iadd || operator.opcode == isub)) {
1866 ((LocalItem)od).incr(tree.getTag() == JCTree.PREINC ? 1 : -1); 1868 ((LocalItem)od).incr(tree.hasTag(PREINC) ? 1 : -1);
1867 result = od; 1869 result = od;
1868 } else { 1870 } else {
1869 od.load(); 1871 od.load();
1870 code.emitop0(one(od.typecode)); 1872 code.emitop0(one(od.typecode));
1871 code.emitop0(operator.opcode); 1873 code.emitop0(operator.opcode);
1875 Code.truncate(od.typecode) == INTcode) 1877 Code.truncate(od.typecode) == INTcode)
1876 code.emitop0(int2byte + od.typecode - BYTEcode); 1878 code.emitop0(int2byte + od.typecode - BYTEcode);
1877 result = items.makeAssignItem(od); 1879 result = items.makeAssignItem(od);
1878 } 1880 }
1879 break; 1881 break;
1880 case JCTree.POSTINC: case JCTree.POSTDEC: 1882 case POSTINC: case POSTDEC:
1881 od.duplicate(); 1883 od.duplicate();
1882 if (od instanceof LocalItem && 1884 if (od instanceof LocalItem &&
1883 (operator.opcode == iadd || operator.opcode == isub)) { 1885 (operator.opcode == iadd || operator.opcode == isub)) {
1884 Item res = od.load(); 1886 Item res = od.load();
1885 ((LocalItem)od).incr(tree.getTag() == JCTree.POSTINC ? 1 : -1); 1887 ((LocalItem)od).incr(tree.hasTag(POSTINC) ? 1 : -1);
1886 result = res; 1888 result = res;
1887 } else { 1889 } else {
1888 Item res = od.load(); 1890 Item res = od.load();
1889 od.stash(od.typecode); 1891 od.stash(od.typecode);
1890 code.emitop0(one(od.typecode)); 1892 code.emitop0(one(od.typecode));
1896 code.emitop0(int2byte + od.typecode - BYTEcode); 1898 code.emitop0(int2byte + od.typecode - BYTEcode);
1897 od.store(); 1899 od.store();
1898 result = res; 1900 result = res;
1899 } 1901 }
1900 break; 1902 break;
1901 case JCTree.NULLCHK: 1903 case NULLCHK:
1902 result = od.load(); 1904 result = od.load();
1903 code.emitop0(dup); 1905 code.emitop0(dup);
1904 genNullCheck(tree.pos()); 1906 genNullCheck(tree.pos());
1905 break; 1907 break;
1906 default: 1908 default:
1924 // Append all strings to buffer. 1926 // Append all strings to buffer.
1925 appendStrings(tree); 1927 appendStrings(tree);
1926 // Convert buffer to string. 1928 // Convert buffer to string.
1927 bufferToString(tree.pos()); 1929 bufferToString(tree.pos());
1928 result = items.makeStackItem(syms.stringType); 1930 result = items.makeStackItem(syms.stringType);
1929 } else if (tree.getTag() == JCTree.AND) { 1931 } else if (tree.hasTag(AND)) {
1930 CondItem lcond = genCond(tree.lhs, CRT_FLOW_CONTROLLER); 1932 CondItem lcond = genCond(tree.lhs, CRT_FLOW_CONTROLLER);
1931 if (!lcond.isFalse()) { 1933 if (!lcond.isFalse()) {
1932 Chain falseJumps = lcond.jumpFalse(); 1934 Chain falseJumps = lcond.jumpFalse();
1933 code.resolve(lcond.trueJumps); 1935 code.resolve(lcond.trueJumps);
1934 CondItem rcond = genCond(tree.rhs, CRT_FLOW_TARGET); 1936 CondItem rcond = genCond(tree.rhs, CRT_FLOW_TARGET);
1938 Code.mergeChains(falseJumps, 1940 Code.mergeChains(falseJumps,
1939 rcond.falseJumps)); 1941 rcond.falseJumps));
1940 } else { 1942 } else {
1941 result = lcond; 1943 result = lcond;
1942 } 1944 }
1943 } else if (tree.getTag() == JCTree.OR) { 1945 } else if (tree.hasTag(OR)) {
1944 CondItem lcond = genCond(tree.lhs, CRT_FLOW_CONTROLLER); 1946 CondItem lcond = genCond(tree.lhs, CRT_FLOW_CONTROLLER);
1945 if (!lcond.isTrue()) { 1947 if (!lcond.isTrue()) {
1946 Chain trueJumps = lcond.jumpTrue(); 1948 Chain trueJumps = lcond.jumpTrue();
1947 code.resolve(lcond.falseJumps); 1949 code.resolve(lcond.falseJumps);
1948 CondItem rcond = genCond(tree.rhs, CRT_FLOW_TARGET); 1950 CondItem rcond = genCond(tree.rhs, CRT_FLOW_TARGET);
1995 1997
1996 /** Add all strings in tree to string buffer. 1998 /** Add all strings in tree to string buffer.
1997 */ 1999 */
1998 void appendStrings(JCTree tree) { 2000 void appendStrings(JCTree tree) {
1999 tree = TreeInfo.skipParens(tree); 2001 tree = TreeInfo.skipParens(tree);
2000 if (tree.getTag() == JCTree.PLUS && tree.type.constValue() == null) { 2002 if (tree.hasTag(PLUS) && tree.type.constValue() == null) {
2001 JCBinary op = (JCBinary) tree; 2003 JCBinary op = (JCBinary) tree;
2002 if (op.operator.kind == MTH && 2004 if (op.operator.kind == MTH &&
2003 ((OperatorSymbol) op.operator).opcode == string_add) { 2005 ((OperatorSymbol) op.operator).opcode == string_add) {
2004 appendStrings(op.lhs); 2006 appendStrings(op.lhs);
2005 appendStrings(op.rhs); 2007 appendStrings(op.rhs);
2238 nerrs++; 2240 nerrs++;
2239 } 2241 }
2240 if (nerrs != 0) { 2242 if (nerrs != 0) {
2241 // if errors, discard code 2243 // if errors, discard code
2242 for (List<JCTree> l = cdef.defs; l.nonEmpty(); l = l.tail) { 2244 for (List<JCTree> l = cdef.defs; l.nonEmpty(); l = l.tail) {
2243 if (l.head.getTag() == JCTree.METHODDEF) 2245 if (l.head.hasTag(METHODDEF))
2244 ((JCMethodDecl) l.head).sym.code = null; 2246 ((JCMethodDecl) l.head).sym.code = null;
2245 } 2247 }
2246 } 2248 }
2247 cdef.defs = List.nil(); // discard trees 2249 cdef.defs = List.nil(); // discard trees
2248 return nerrs == 0; 2250 return nerrs == 0;

mercurial