langtools/src/share/classes/com/sun/tools/javac/jvm/Gen.java
changeset 10950 e87b50888909
parent 10811 4d4ed480210e
child 11055 ec1418effa77
equal deleted inserted replaced
10949:42f7cc0468dd 10950:e87b50888909
    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;