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)); |
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; |