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

Wed, 27 Apr 2016 01:34:52 +0800

author
aoqi
date
Wed, 27 Apr 2016 01:34:52 +0800
changeset 0
959103a6100f
child 2525
2eb010b6cb22
permissions
-rw-r--r--

Initial load
http://hg.openjdk.java.net/jdk8u/jdk8u/langtools/
changeset: 2573:53ca196be1ae
tag: jdk8u25-b17

     1 /*
     2  * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle in the LICENSE file that accompanied this code.
    10  *
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    14  * version 2 for more details (a copy is included in the LICENSE file that
    15  * accompanied this code).
    16  *
    17  * You should have received a copy of the GNU General Public License version
    18  * 2 along with this work; if not, write to the Free Software Foundation,
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    20  *
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    24  */
    26 package com.sun.tools.javac.jvm;
    28 import java.util.*;
    30 import com.sun.tools.javac.tree.*;
    31 import com.sun.tools.javac.util.*;
    32 import com.sun.tools.javac.util.List;
    33 import com.sun.tools.javac.tree.JCTree.*;
    34 import com.sun.tools.javac.tree.EndPosTable;
    36 /** This class contains the CharacterRangeTable for some method
    37  *  and the hashtable for mapping trees or lists of trees to their
    38  *  ending positions.
    39  *
    40  *  <p><b>This is NOT part of any supported API.
    41  *  If you write code that depends on this, you do so at your own risk.
    42  *  This code and its internal interfaces are subject to change or
    43  *  deletion without notice.</b>
    44  */
    45 public class CRTable
    46 implements CRTFlags {
    48     private final boolean crtDebug = false;
    50     /** The list of CRTable entries.
    51      */
    52     private ListBuffer<CRTEntry> entries = new ListBuffer<CRTEntry>();
    54     /** The hashtable for source positions.
    55      */
    56     private Map<Object,SourceRange> positions = new HashMap<Object,SourceRange>();
    58     /** The object for ending positions stored in the parser.
    59      */
    60     private EndPosTable endPosTable;
    62     /** The tree of the method this table is intended for.
    63      *  We should traverse this tree to get source ranges.
    64      */
    65     JCTree.JCMethodDecl methodTree;
    67     /** Constructor
    68      */
    69     public CRTable(JCTree.JCMethodDecl tree, EndPosTable endPosTable) {
    70         this.methodTree = tree;
    71         this.endPosTable = endPosTable;
    72     }
    74     /** Create a new CRTEntry and add it to the entries.
    75      *  @param tree     The tree or the list of trees for which
    76      *                  we are storing the code pointers.
    77      *  @param flags    The set of flags designating type of the entry.
    78      *  @param startPc  The starting code position.
    79      *  @param endPc    The ending code position.
    80      */
    81     public void put(Object tree, int flags, int startPc, int endPc) {
    82         entries.append(new CRTEntry(tree, flags, startPc, endPc));
    83     }
    85     /** Compute source positions and write CRT to the databuf.
    86      *  @param databuf  The buffer to write bytecodes to.
    87      */
    88     public int writeCRT(ByteBuffer databuf, Position.LineMap lineMap, Log log) {
    90         int crtEntries = 0;
    92         // compute source positions for the method
    93         new SourceComputer().csp(methodTree);
    95         for (List<CRTEntry> l = entries.toList(); l.nonEmpty(); l = l.tail) {
    97             CRTEntry entry = l.head;
    99             // eliminate entries that do not produce bytecodes:
   100             // for example, empty blocks and statements
   101             if (entry.startPc == entry.endPc)
   102                 continue;
   104             SourceRange pos = positions.get(entry.tree);
   105             Assert.checkNonNull(pos, "CRT: tree source positions are undefined");
   106             if ((pos.startPos == Position.NOPOS) || (pos.endPos == Position.NOPOS))
   107                 continue;
   109             if (crtDebug) {
   110                 System.out.println("Tree: " + entry.tree + ", type:" + getTypes(entry.flags));
   111                 System.out.print("Start: pos = " + pos.startPos + ", pc = " + entry.startPc);
   112             }
   114             // encode startPos into line/column representation
   115             int startPos = encodePosition(pos.startPos, lineMap, log);
   116             if (startPos == Position.NOPOS)
   117                 continue;
   119             if (crtDebug) {
   120                 System.out.print("End:   pos = " + pos.endPos + ", pc = " + (entry.endPc - 1));
   121             }
   123             // encode endPos into line/column representation
   124             int endPos = encodePosition(pos.endPos, lineMap, log);
   125             if (endPos == Position.NOPOS)
   126                 continue;
   128             // write attribute
   129             databuf.appendChar(entry.startPc);
   130             // 'endPc - 1' because endPc actually points to start of the next command
   131             databuf.appendChar(entry.endPc - 1);
   132             databuf.appendInt(startPos);
   133             databuf.appendInt(endPos);
   134             databuf.appendChar(entry.flags);
   136             crtEntries++;
   137         }
   139         return crtEntries;
   140     }
   142     /** Return the number of the entries.
   143      */
   144     public int length() {
   145         return entries.length();
   146     }
   148     /** Return string describing flags enabled.
   149      */
   150     private String getTypes(int flags) {
   151         String types = "";
   152         if ((flags & CRT_STATEMENT)       != 0) types += " CRT_STATEMENT";
   153         if ((flags & CRT_BLOCK)           != 0) types += " CRT_BLOCK";
   154         if ((flags & CRT_ASSIGNMENT)      != 0) types += " CRT_ASSIGNMENT";
   155         if ((flags & CRT_FLOW_CONTROLLER) != 0) types += " CRT_FLOW_CONTROLLER";
   156         if ((flags & CRT_FLOW_TARGET)     != 0) types += " CRT_FLOW_TARGET";
   157         if ((flags & CRT_INVOKE)          != 0) types += " CRT_INVOKE";
   158         if ((flags & CRT_CREATE)          != 0) types += " CRT_CREATE";
   159         if ((flags & CRT_BRANCH_TRUE)     != 0) types += " CRT_BRANCH_TRUE";
   160         if ((flags & CRT_BRANCH_FALSE)    != 0) types += " CRT_BRANCH_FALSE";
   161         return types;
   162     }
   164     /** Source file positions in CRT are integers in the format:
   165      *  {@literal line-number << LINESHIFT + column-number }
   166      */
   167      private int encodePosition(int pos, Position.LineMap lineMap, Log log) {
   168          int line = lineMap.getLineNumber(pos);
   169          int col = lineMap.getColumnNumber(pos);
   170          int new_pos = Position.encodePosition(line, col);
   171          if (crtDebug) {
   172              System.out.println(", line = " + line + ", column = " + col +
   173                                 ", new_pos = " + new_pos);
   174          }
   175          if (new_pos == Position.NOPOS)
   176              log.warning(pos, "position.overflow", line);
   178         return new_pos;
   179      }
   181 /* ************************************************************************
   182  * Traversal methods
   183  *************************************************************************/
   185     /**
   186      *  This class contains methods to compute source positions for trees.
   187      *  Extends Tree.Visitor to traverse the abstract syntax tree.
   188      */
   189     class SourceComputer extends JCTree.Visitor {
   191         /** The result of the tree traversal methods.
   192          */
   193         SourceRange result;
   195         /** Visitor method: compute source positions for a single node.
   196          */
   197         public SourceRange csp(JCTree tree) {
   198             if (tree == null) return null;
   199             tree.accept(this);
   200             if (result != null) {
   201                 positions.put(tree, result);
   202             }
   203             return result;
   204         }
   206         /** Visitor method: compute source positions for a list of nodes.
   207          */
   208         public SourceRange csp(List<? extends JCTree> trees) {
   209             if ((trees == null) || !(trees.nonEmpty())) return null;
   210             SourceRange list_sr = new SourceRange();
   211             for (List<? extends JCTree> l = trees; l.nonEmpty(); l = l.tail) {
   212                 list_sr.mergeWith(csp(l.head));
   213             }
   214             positions.put(trees, list_sr);
   215             return list_sr;
   216         }
   218         /**  Visitor method: compute source positions for
   219          *    a list of case blocks of switch statements.
   220          */
   221         public SourceRange cspCases(List<JCCase> trees) {
   222             if ((trees == null) || !(trees.nonEmpty())) return null;
   223             SourceRange list_sr = new SourceRange();
   224             for (List<JCCase> l = trees; l.nonEmpty(); l = l.tail) {
   225                 list_sr.mergeWith(csp(l.head));
   226             }
   227             positions.put(trees, list_sr);
   228             return list_sr;
   229         }
   231         /**  Visitor method: compute source positions for
   232          *   a list of catch clauses in try statements.
   233          */
   234         public SourceRange cspCatchers(List<JCCatch> trees) {
   235             if ((trees == null) || !(trees.nonEmpty())) return null;
   236             SourceRange list_sr = new SourceRange();
   237             for (List<JCCatch> l = trees; l.nonEmpty(); l = l.tail) {
   238                 list_sr.mergeWith(csp(l.head));
   239             }
   240             positions.put(trees, list_sr);
   241             return list_sr;
   242         }
   244         public void visitMethodDef(JCMethodDecl tree) {
   245             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   246             sr.mergeWith(csp(tree.body));
   247             result = sr;
   248         }
   250         public void visitVarDef(JCVariableDecl tree) {
   251             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   252             csp(tree.vartype);
   253             sr.mergeWith(csp(tree.init));
   254             result = sr;
   255         }
   257         public void visitSkip(JCSkip tree) {
   258             // endPos is the same as startPos for the empty statement
   259             SourceRange sr = new SourceRange(startPos(tree), startPos(tree));
   260             result = sr;
   261         }
   263         public void visitBlock(JCBlock tree) {
   264             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   265             csp(tree.stats);    // doesn't compare because block's ending position is defined
   266             result = sr;
   267         }
   269         public void visitDoLoop(JCDoWhileLoop tree) {
   270             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   271             sr.mergeWith(csp(tree.body));
   272             sr.mergeWith(csp(tree.cond));
   273             result = sr;
   274         }
   276         public void visitWhileLoop(JCWhileLoop tree) {
   277             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   278             sr.mergeWith(csp(tree.cond));
   279             sr.mergeWith(csp(tree.body));
   280             result = sr;
   281         }
   283         public void visitForLoop(JCForLoop tree) {
   284             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   285             sr.mergeWith(csp(tree.init));
   286             sr.mergeWith(csp(tree.cond));
   287             sr.mergeWith(csp(tree.step));
   288             sr.mergeWith(csp(tree.body));
   289             result = sr;
   290         }
   292         public void visitForeachLoop(JCEnhancedForLoop tree) {
   293             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   294             sr.mergeWith(csp(tree.var));
   295             sr.mergeWith(csp(tree.expr));
   296             sr.mergeWith(csp(tree.body));
   297             result = sr;
   298         }
   300         public void visitLabelled(JCLabeledStatement tree) {
   301             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   302             sr.mergeWith(csp(tree.body));
   303             result = sr;
   304         }
   306         public void visitSwitch(JCSwitch tree) {
   307             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   308             sr.mergeWith(csp(tree.selector));
   309             sr.mergeWith(cspCases(tree.cases));
   310             result = sr;
   311         }
   313         public void visitCase(JCCase tree) {
   314             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   315             sr.mergeWith(csp(tree.pat));
   316             sr.mergeWith(csp(tree.stats));
   317             result = sr;
   318         }
   320         public void visitSynchronized(JCSynchronized tree) {
   321             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   322             sr.mergeWith(csp(tree.lock));
   323             sr.mergeWith(csp(tree.body));
   324             result = sr;
   325         }
   327         public void visitTry(JCTry tree) {
   328             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   329             sr.mergeWith(csp(tree.resources));
   330             sr.mergeWith(csp(tree.body));
   331             sr.mergeWith(cspCatchers(tree.catchers));
   332             sr.mergeWith(csp(tree.finalizer));
   333             result = sr;
   334         }
   336         public void visitCatch(JCCatch tree) {
   337             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   338             sr.mergeWith(csp(tree.param));
   339             sr.mergeWith(csp(tree.body));
   340             result = sr;
   341         }
   343         public void visitConditional(JCConditional tree) {
   344             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   345             sr.mergeWith(csp(tree.cond));
   346             sr.mergeWith(csp(tree.truepart));
   347             sr.mergeWith(csp(tree.falsepart));
   348             result = sr;
   349         }
   351         public void visitIf(JCIf tree) {
   352             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   353             sr.mergeWith(csp(tree.cond));
   354             sr.mergeWith(csp(tree.thenpart));
   355             sr.mergeWith(csp(tree.elsepart));
   356             result = sr;
   357         }
   359         public void visitExec(JCExpressionStatement tree) {
   360             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   361             sr.mergeWith(csp(tree.expr));
   362             result = sr;
   363         }
   365         public void visitBreak(JCBreak tree) {
   366             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   367             result = sr;
   368         }
   370         public void visitContinue(JCContinue tree) {
   371             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   372             result = sr;
   373         }
   375         public void visitReturn(JCReturn tree) {
   376             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   377             sr.mergeWith(csp(tree.expr));
   378             result = sr;
   379         }
   381         public void visitThrow(JCThrow tree) {
   382             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   383             sr.mergeWith(csp(tree.expr));
   384             result = sr;
   385         }
   387         public void visitAssert(JCAssert tree) {
   388             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   389             sr.mergeWith(csp(tree.cond));
   390             sr.mergeWith(csp(tree.detail));
   391             result = sr;
   392         }
   394         public void visitApply(JCMethodInvocation tree) {
   395             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   396             sr.mergeWith(csp(tree.meth));
   397             sr.mergeWith(csp(tree.args));
   398             result = sr;
   399         }
   401         public void visitNewClass(JCNewClass tree) {
   402             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   403             sr.mergeWith(csp(tree.encl));
   404             sr.mergeWith(csp(tree.clazz));
   405             sr.mergeWith(csp(tree.args));
   406             sr.mergeWith(csp(tree.def));
   407             result = sr;
   408         }
   410         public void visitNewArray(JCNewArray tree) {
   411             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   412             sr.mergeWith(csp(tree.elemtype));
   413             sr.mergeWith(csp(tree.dims));
   414             sr.mergeWith(csp(tree.elems));
   415             result = sr;
   416         }
   418         public void visitParens(JCParens tree) {
   419             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   420             sr.mergeWith(csp(tree.expr));
   421             result = sr;
   422         }
   424         public void visitAssign(JCAssign tree) {
   425             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   426             sr.mergeWith(csp(tree.lhs));
   427             sr.mergeWith(csp(tree.rhs));
   428             result = sr;
   429         }
   431         public void visitAssignop(JCAssignOp tree) {
   432             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   433             sr.mergeWith(csp(tree.lhs));
   434             sr.mergeWith(csp(tree.rhs));
   435             result = sr;
   436         }
   438         public void visitUnary(JCUnary tree) {
   439             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   440             sr.mergeWith(csp(tree.arg));
   441             result = sr;
   442         }
   444         public void visitBinary(JCBinary tree) {
   445             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   446             sr.mergeWith(csp(tree.lhs));
   447             sr.mergeWith(csp(tree.rhs));
   448             result = sr;
   449         }
   451         public void visitTypeCast(JCTypeCast tree) {
   452             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   453             sr.mergeWith(csp(tree.clazz));
   454             sr.mergeWith(csp(tree.expr));
   455             result = sr;
   456         }
   458         public void visitTypeTest(JCInstanceOf tree) {
   459             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   460             sr.mergeWith(csp(tree.expr));
   461             sr.mergeWith(csp(tree.clazz));
   462             result = sr;
   463         }
   465         public void visitIndexed(JCArrayAccess tree) {
   466             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   467             sr.mergeWith(csp(tree.indexed));
   468             sr.mergeWith(csp(tree.index));
   469             result = sr;
   470         }
   472         public void visitSelect(JCFieldAccess tree) {
   473             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   474             sr.mergeWith(csp(tree.selected));
   475             result = sr;
   476         }
   478         public void visitIdent(JCIdent tree) {
   479             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   480             result = sr;
   481         }
   483         public void visitLiteral(JCLiteral tree) {
   484             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   485             result = sr;
   486         }
   488         public void visitTypeIdent(JCPrimitiveTypeTree tree) {
   489             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   490             result = sr;
   491         }
   493         public void visitTypeArray(JCArrayTypeTree tree) {
   494             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   495             sr.mergeWith(csp(tree.elemtype));
   496             result = sr;
   497         }
   499         public void visitTypeApply(JCTypeApply tree) {
   500             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   501             sr.mergeWith(csp(tree.clazz));
   502             sr.mergeWith(csp(tree.arguments));
   503             result = sr;
   504         }
   506         @Override
   507         public void visitLetExpr(LetExpr tree) {
   508             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   509             sr.mergeWith(csp(tree.defs));
   510             sr.mergeWith(csp(tree.expr));
   511             result = sr;
   512         }
   514         public void visitTypeParameter(JCTypeParameter tree) {
   515             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   516             sr.mergeWith(csp(tree.bounds));
   517             result = sr;
   518         }
   520         public void visitWildcard(JCWildcard tree) {
   521             result = null;
   522         }
   524         public void visitErroneous(JCErroneous tree) {
   525             result = null;
   526         }
   528         public void visitTree(JCTree tree) {
   529             Assert.error();
   530         }
   532         /** The start position of given tree.
   533          */
   534         public int startPos(JCTree tree) {
   535             if (tree == null) return Position.NOPOS;
   536             return TreeInfo.getStartPos(tree);
   537         }
   539         /** The end position of given tree, if it has
   540          *  defined endpos, NOPOS otherwise.
   541          */
   542         public int endPos(JCTree tree) {
   543             if (tree == null) return Position.NOPOS;
   544             return TreeInfo.getEndPos(tree, endPosTable);
   545         }
   546     }
   548     /** This class contains a CharacterRangeTableEntry.
   549      */
   550     static class CRTEntry {
   552         /** A tree or a list of trees to obtain source positions.
   553          */
   554         Object tree;
   556         /** The flags described in the CharacterRangeTable spec.
   557          */
   558         int flags;
   560         /** The starting code position of this entry.
   561          */
   562         int startPc;
   564         /** The ending code position of this entry.
   565          */
   566         int endPc;
   568         /** Constructor */
   569         CRTEntry(Object tree, int flags, int startPc, int endPc) {
   570             this.tree = tree;
   571             this.flags = flags;
   572             this.startPc = startPc;
   573             this.endPc = endPc;
   574         }
   575     }
   578     /** This class contains source positions
   579      *  for some tree or list of trees.
   580      */
   581     static class SourceRange {
   583         /** The starting source position.
   584          */
   585         int startPos;
   587         /** The ending source position.
   588          */
   589         int endPos;
   591         /** Constructor */
   592         SourceRange() {
   593             startPos = Position.NOPOS;
   594             endPos = Position.NOPOS;
   595         }
   597         /** Constructor */
   598         SourceRange(int startPos, int endPos) {
   599             this.startPos = startPos;
   600             this.endPos = endPos;
   601         }
   603         /** Compare the starting and the ending positions
   604          *  of the source range and combines them assigning
   605          *  the widest range to this.
   606          */
   607         SourceRange mergeWith(SourceRange sr) {
   608             if (sr == null) return this;
   609             if (startPos == Position.NOPOS)
   610                 startPos = sr.startPos;
   611             else if (sr.startPos != Position.NOPOS)
   612                 startPos = (startPos < sr.startPos ? startPos : sr.startPos);
   613             if (endPos == Position.NOPOS)
   614                 endPos = sr.endPos;
   615             else if (sr.endPos != Position.NOPOS)
   616                 endPos = (endPos > sr.endPos ? endPos : sr.endPos);
   617             return this;
   618         }
   619     }
   621 }

mercurial