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

Tue, 28 Dec 2010 15:54:52 -0800

author
ohair
date
Tue, 28 Dec 2010 15:54:52 -0800
changeset 798
4868a36f6fd8
parent 609
13354e1abba7
child 816
7c537f4298fb
permissions
-rw-r--r--

6962318: Update copyright year
Reviewed-by: xdono

     1 /*
     2  * Copyright (c) 2001, 2010, 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.*;
    35 /** This class contains the CharacterRangeTable for some method
    36  *  and the hashtable for mapping trees or lists of trees to their
    37  *  ending positions.
    38  *
    39  *  <p><b>This is NOT part of any supported API.
    40  *  If you write code that depends on this, you do so at your own risk.
    41  *  This code and its internal interfaces are subject to change or
    42  *  deletion without notice.</b>
    43  */
    44 public class CRTable
    45 implements CRTFlags {
    47     private final boolean crtDebug = false;
    49     /** The list of CRTable entries.
    50      */
    51     private ListBuffer<CRTEntry> entries = new ListBuffer<CRTEntry>();
    53     /** The hashtable for source positions.
    54      */
    55     private Map<Object,SourceRange> positions = new HashMap<Object,SourceRange>();
    57     /** The hashtable for ending positions stored in the parser.
    58      */
    59     private Map<JCTree, Integer> endPositions;
    61     /** The tree of the method this table is intended for.
    62      *  We should traverse this tree to get source ranges.
    63      */
    64     JCTree.JCMethodDecl methodTree;
    66     /** Constructor
    67      */
    68     public CRTable(JCTree.JCMethodDecl tree, Map<JCTree, Integer> endPositions) {
    69         this.methodTree = tree;
    70         this.endPositions = endPositions;
    71     }
    73     /** Create a new CRTEntry and add it to the entries.
    74      *  @param tree     The tree or the list of trees for which
    75      *                  we are storing the code pointers.
    76      *  @param flags    The set of flags designating type of the entry.
    77      *  @param startPc  The starting code position.
    78      *  @param endPc    The ending code position.
    79      */
    80     public void put(Object tree, int flags, int startPc, int endPc) {
    81         entries.append(new CRTEntry(tree, flags, startPc, endPc));
    82     }
    84     /** Compute source positions and write CRT to the databuf.
    85      *  @param databuf  The buffer to write bytecodes to.
    86      */
    87     public int writeCRT(ByteBuffer databuf, Position.LineMap lineMap, Log log) {
    89         int crtEntries = 0;
    91         // compute source positions for the method
    92         new SourceComputer().csp(methodTree);
    94         for (List<CRTEntry> l = entries.toList(); l.nonEmpty(); l = l.tail) {
    96             CRTEntry entry = l.head;
    98             // eliminate entries that do not produce bytecodes:
    99             // for example, empty blocks and statements
   100             if (entry.startPc == entry.endPc)
   101                 continue;
   103             SourceRange pos = positions.get(entry.tree);
   104             assert pos != null : "CRT: tree source positions are undefined";
   105             if ((pos.startPos == Position.NOPOS) || (pos.endPos == Position.NOPOS))
   106                 continue;
   108             if (crtDebug) {
   109                 System.out.println("Tree: " + entry.tree + ", type:" + getTypes(entry.flags));
   110                 System.out.print("Start: pos = " + pos.startPos + ", pc = " + entry.startPc);
   111             }
   113             // encode startPos into line/column representation
   114             int startPos = encodePosition(pos.startPos, lineMap, log);
   115             if (startPos == Position.NOPOS)
   116                 continue;
   118             if (crtDebug) {
   119                 System.out.print("End:   pos = " + pos.endPos + ", pc = " + (entry.endPc - 1));
   120             }
   122             // encode endPos into line/column representation
   123             int endPos = encodePosition(pos.endPos, lineMap, log);
   124             if (endPos == Position.NOPOS)
   125                 continue;
   127             // write attribute
   128             databuf.appendChar(entry.startPc);
   129             // 'endPc - 1' because endPc actually points to start of the next command
   130             databuf.appendChar(entry.endPc - 1);
   131             databuf.appendInt(startPos);
   132             databuf.appendInt(endPos);
   133             databuf.appendChar(entry.flags);
   135             crtEntries++;
   136         }
   138         return crtEntries;
   139     }
   141     /** Return the number of the entries.
   142      */
   143     public int length() {
   144         return entries.length();
   145     }
   147     /** Return string describing flags enabled.
   148      */
   149     private String getTypes(int flags) {
   150         String types = "";
   151         if ((flags & CRT_STATEMENT)       != 0) types += " CRT_STATEMENT";
   152         if ((flags & CRT_BLOCK)           != 0) types += " CRT_BLOCK";
   153         if ((flags & CRT_ASSIGNMENT)      != 0) types += " CRT_ASSIGNMENT";
   154         if ((flags & CRT_FLOW_CONTROLLER) != 0) types += " CRT_FLOW_CONTROLLER";
   155         if ((flags & CRT_FLOW_TARGET)     != 0) types += " CRT_FLOW_TARGET";
   156         if ((flags & CRT_INVOKE)          != 0) types += " CRT_INVOKE";
   157         if ((flags & CRT_CREATE)          != 0) types += " CRT_CREATE";
   158         if ((flags & CRT_BRANCH_TRUE)     != 0) types += " CRT_BRANCH_TRUE";
   159         if ((flags & CRT_BRANCH_FALSE)    != 0) types += " CRT_BRANCH_FALSE";
   160         return types;
   161     }
   163     /** Source file positions in CRT are integers in the format:
   164      *  line-number << LINESHIFT + column-number
   165      */
   166      private int encodePosition(int pos, Position.LineMap lineMap, Log log) {
   167          int line = lineMap.getLineNumber(pos);
   168          int col = lineMap.getColumnNumber(pos);
   169          int new_pos = Position.encodePosition(line, col);
   170          if (crtDebug) {
   171              System.out.println(", line = " + line + ", column = " + col +
   172                                 ", new_pos = " + new_pos);
   173          }
   174          if (new_pos == Position.NOPOS)
   175              log.warning(pos, "position.overflow", line);
   177         return new_pos;
   178      }
   180 /* ************************************************************************
   181  * Traversal methods
   182  *************************************************************************/
   184     /**
   185      *  This class contains methods to compute source positions for trees.
   186      *  Extends Tree.Visitor to traverse the abstract syntax tree.
   187      */
   188     class SourceComputer extends JCTree.Visitor {
   190         /** The result of the tree traversal methods.
   191          */
   192         SourceRange result;
   194         /** Visitor method: compute source positions for a single node.
   195          */
   196         public SourceRange csp(JCTree tree) {
   197             if (tree == null) return null;
   198             tree.accept(this);
   199             if (result != null) {
   200                 positions.put(tree, result);
   201             }
   202             return result;
   203         }
   205         /** Visitor method: compute source positions for a list of nodes.
   206          */
   207         public SourceRange csp(List<? extends JCTree> trees) {
   208             if ((trees == null) || !(trees.nonEmpty())) return null;
   209             SourceRange list_sr = new SourceRange();
   210             for (List<? extends JCTree> l = trees; l.nonEmpty(); l = l.tail) {
   211                 list_sr.mergeWith(csp(l.head));
   212             }
   213             positions.put(trees, list_sr);
   214             return list_sr;
   215         }
   217         /**  Visitor method: compute source positions for
   218          *    a list of case blocks of switch statements.
   219          */
   220         public SourceRange cspCases(List<JCCase> trees) {
   221             if ((trees == null) || !(trees.nonEmpty())) return null;
   222             SourceRange list_sr = new SourceRange();
   223             for (List<JCCase> l = trees; l.nonEmpty(); l = l.tail) {
   224                 list_sr.mergeWith(csp(l.head));
   225             }
   226             positions.put(trees, list_sr);
   227             return list_sr;
   228         }
   230         /**  Visitor method: compute source positions for
   231          *   a list of catch clauses in try statements.
   232          */
   233         public SourceRange cspCatchers(List<JCCatch> trees) {
   234             if ((trees == null) || !(trees.nonEmpty())) return null;
   235             SourceRange list_sr = new SourceRange();
   236             for (List<JCCatch> l = trees; l.nonEmpty(); l = l.tail) {
   237                 list_sr.mergeWith(csp(l.head));
   238             }
   239             positions.put(trees, list_sr);
   240             return list_sr;
   241         }
   243         public void visitMethodDef(JCMethodDecl tree) {
   244             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   245             sr.mergeWith(csp(tree.body));
   246             result = sr;
   247         }
   249         public void visitVarDef(JCVariableDecl tree) {
   250             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   251             csp(tree.vartype);
   252             sr.mergeWith(csp(tree.init));
   253             result = sr;
   254         }
   256         public void visitSkip(JCSkip tree) {
   257             // endPos is the same as startPos for the empty statement
   258             SourceRange sr = new SourceRange(startPos(tree), startPos(tree));
   259             result = sr;
   260         }
   262         public void visitBlock(JCBlock tree) {
   263             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   264             csp(tree.stats);    // doesn't compare because block's ending position is defined
   265             result = sr;
   266         }
   268         public void visitDoLoop(JCDoWhileLoop tree) {
   269             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   270             sr.mergeWith(csp(tree.body));
   271             sr.mergeWith(csp(tree.cond));
   272             result = sr;
   273         }
   275         public void visitWhileLoop(JCWhileLoop tree) {
   276             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   277             sr.mergeWith(csp(tree.cond));
   278             sr.mergeWith(csp(tree.body));
   279             result = sr;
   280         }
   282         public void visitForLoop(JCForLoop tree) {
   283             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   284             sr.mergeWith(csp(tree.init));
   285             sr.mergeWith(csp(tree.cond));
   286             sr.mergeWith(csp(tree.step));
   287             sr.mergeWith(csp(tree.body));
   288             result = sr;
   289         }
   291         public void visitForeachLoop(JCEnhancedForLoop tree) {
   292             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   293             sr.mergeWith(csp(tree.var));
   294             sr.mergeWith(csp(tree.expr));
   295             sr.mergeWith(csp(tree.body));
   296             result = sr;
   297         }
   299         public void visitLabelled(JCLabeledStatement tree) {
   300             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   301             sr.mergeWith(csp(tree.body));
   302             result = sr;
   303         }
   305         public void visitSwitch(JCSwitch tree) {
   306             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   307             sr.mergeWith(csp(tree.selector));
   308             sr.mergeWith(cspCases(tree.cases));
   309             result = sr;
   310         }
   312         public void visitCase(JCCase tree) {
   313             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   314             sr.mergeWith(csp(tree.pat));
   315             sr.mergeWith(csp(tree.stats));
   316             result = sr;
   317         }
   319         public void visitSynchronized(JCSynchronized tree) {
   320             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   321             sr.mergeWith(csp(tree.lock));
   322             sr.mergeWith(csp(tree.body));
   323             result = sr;
   324         }
   326         public void visitTry(JCTry tree) {
   327             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   328             sr.mergeWith(csp(tree.resources));
   329             sr.mergeWith(csp(tree.body));
   330             sr.mergeWith(cspCatchers(tree.catchers));
   331             sr.mergeWith(csp(tree.finalizer));
   332             result = sr;
   333         }
   335         public void visitCatch(JCCatch tree) {
   336             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   337             sr.mergeWith(csp(tree.param));
   338             sr.mergeWith(csp(tree.body));
   339             result = sr;
   340         }
   342         public void visitConditional(JCConditional tree) {
   343             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   344             sr.mergeWith(csp(tree.cond));
   345             sr.mergeWith(csp(tree.truepart));
   346             sr.mergeWith(csp(tree.falsepart));
   347             result = sr;
   348         }
   350         public void visitIf(JCIf tree) {
   351             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   352             sr.mergeWith(csp(tree.cond));
   353             sr.mergeWith(csp(tree.thenpart));
   354             sr.mergeWith(csp(tree.elsepart));
   355             result = sr;
   356         }
   358         public void visitExec(JCExpressionStatement tree) {
   359             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   360             sr.mergeWith(csp(tree.expr));
   361             result = sr;
   362         }
   364         public void visitBreak(JCBreak tree) {
   365             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   366             result = sr;
   367         }
   369         public void visitContinue(JCContinue tree) {
   370             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   371             result = sr;
   372         }
   374         public void visitReturn(JCReturn tree) {
   375             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   376             sr.mergeWith(csp(tree.expr));
   377             result = sr;
   378         }
   380         public void visitThrow(JCThrow tree) {
   381             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   382             sr.mergeWith(csp(tree.expr));
   383             result = sr;
   384         }
   386         public void visitAssert(JCAssert tree) {
   387             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   388             sr.mergeWith(csp(tree.cond));
   389             sr.mergeWith(csp(tree.detail));
   390             result = sr;
   391         }
   393         public void visitApply(JCMethodInvocation tree) {
   394             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   395             sr.mergeWith(csp(tree.meth));
   396             sr.mergeWith(csp(tree.args));
   397             result = sr;
   398         }
   400         public void visitNewClass(JCNewClass tree) {
   401             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   402             sr.mergeWith(csp(tree.encl));
   403             sr.mergeWith(csp(tree.clazz));
   404             sr.mergeWith(csp(tree.args));
   405             sr.mergeWith(csp(tree.def));
   406             result = sr;
   407         }
   409         public void visitNewArray(JCNewArray tree) {
   410             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   411             sr.mergeWith(csp(tree.elemtype));
   412             sr.mergeWith(csp(tree.dims));
   413             sr.mergeWith(csp(tree.elems));
   414             result = sr;
   415         }
   417         public void visitParens(JCParens tree) {
   418             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   419             sr.mergeWith(csp(tree.expr));
   420             result = sr;
   421         }
   423         public void visitAssign(JCAssign tree) {
   424             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   425             sr.mergeWith(csp(tree.lhs));
   426             sr.mergeWith(csp(tree.rhs));
   427             result = sr;
   428         }
   430         public void visitAssignop(JCAssignOp tree) {
   431             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   432             sr.mergeWith(csp(tree.lhs));
   433             sr.mergeWith(csp(tree.rhs));
   434             result = sr;
   435         }
   437         public void visitUnary(JCUnary tree) {
   438             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   439             sr.mergeWith(csp(tree.arg));
   440             result = sr;
   441         }
   443         public void visitBinary(JCBinary tree) {
   444             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   445             sr.mergeWith(csp(tree.lhs));
   446             sr.mergeWith(csp(tree.rhs));
   447             result = sr;
   448         }
   450         public void visitTypeCast(JCTypeCast tree) {
   451             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   452             sr.mergeWith(csp(tree.clazz));
   453             sr.mergeWith(csp(tree.expr));
   454             result = sr;
   455         }
   457         public void visitTypeTest(JCInstanceOf tree) {
   458             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   459             sr.mergeWith(csp(tree.expr));
   460             sr.mergeWith(csp(tree.clazz));
   461             result = sr;
   462         }
   464         public void visitIndexed(JCArrayAccess tree) {
   465             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   466             sr.mergeWith(csp(tree.indexed));
   467             sr.mergeWith(csp(tree.index));
   468             result = sr;
   469         }
   471         public void visitSelect(JCFieldAccess tree) {
   472             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   473             sr.mergeWith(csp(tree.selected));
   474             result = sr;
   475         }
   477         public void visitIdent(JCIdent tree) {
   478             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   479             result = sr;
   480         }
   482         public void visitLiteral(JCLiteral tree) {
   483             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   484             result = sr;
   485         }
   487         public void visitTypeIdent(JCPrimitiveTypeTree tree) {
   488             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   489             result = sr;
   490         }
   492         public void visitTypeArray(JCArrayTypeTree tree) {
   493             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   494             sr.mergeWith(csp(tree.elemtype));
   495             result = sr;
   496         }
   498         public void visitTypeApply(JCTypeApply tree) {
   499             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   500             sr.mergeWith(csp(tree.clazz));
   501             sr.mergeWith(csp(tree.arguments));
   502             result = sr;
   503         }
   505         public void visitTypeParameter(JCTypeParameter tree) {
   506             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
   507             sr.mergeWith(csp(tree.bounds));
   508             result = sr;
   509         }
   511         public void visitWildcard(JCWildcard tree) {
   512             result = null;
   513         }
   515         public void visitErroneous(JCErroneous tree) {
   516             result = null;
   517         }
   519         public void visitTree(JCTree tree) {
   520             assert false;
   521         }
   523         /** The start position of given tree.
   524          */
   525         public int startPos(JCTree tree) {
   526             if (tree == null) return Position.NOPOS;
   527             return tree.pos;
   528         }
   530         /** The end position of given tree, if it has
   531          *  defined endpos, NOPOS otherwise.
   532          */
   533         public int endPos(JCTree tree) {
   534             if (tree == null) return Position.NOPOS;
   535             if (tree.getTag() == JCTree.BLOCK)
   536                 return ((JCBlock) tree).endpos;
   537             Integer endpos = endPositions.get(tree);
   538             if (endpos != null)
   539                 return endpos.intValue();
   540             return Position.NOPOS;
   541         }
   542     }
   544     /** This class contains a CharacterRangeTableEntry.
   545      */
   546     static class CRTEntry {
   548         /** A tree or a list of trees to obtain source positions.
   549          */
   550         Object tree;
   552         /** The flags described in the CharacterRangeTable spec.
   553          */
   554         int flags;
   556         /** The starting code position of this entry.
   557          */
   558         int startPc;
   560         /** The ending code position of this entry.
   561          */
   562         int endPc;
   564         /** Constructor */
   565         CRTEntry(Object tree, int flags, int startPc, int endPc) {
   566             this.tree = tree;
   567             this.flags = flags;
   568             this.startPc = startPc;
   569             this.endPc = endPc;
   570         }
   571     }
   574     /** This class contains source positions
   575      *  for some tree or list of trees.
   576      */
   577     static class SourceRange {
   579         /** The starting source position.
   580          */
   581         int startPos;
   583         /** The ending source position.
   584          */
   585         int endPos;
   587         /** Constructor */
   588         SourceRange() {
   589             startPos = Position.NOPOS;
   590             endPos = Position.NOPOS;
   591         }
   593         /** Constructor */
   594         SourceRange(int startPos, int endPos) {
   595             this.startPos = startPos;
   596             this.endPos = endPos;
   597         }
   599         /** Compare the starting and the ending positions
   600          *  of the source range and combines them assigning
   601          *  the widest range to this.
   602          */
   603         SourceRange mergeWith(SourceRange sr) {
   604             if (sr == null) return this;
   605             if (startPos == Position.NOPOS)
   606                 startPos = sr.startPos;
   607             else if (sr.startPos != Position.NOPOS)
   608                 startPos = (startPos < sr.startPos ? startPos : sr.startPos);
   609             if (endPos == Position.NOPOS)
   610                 endPos = sr.endPos;
   611             else if (sr.endPos != Position.NOPOS)
   612                 endPos = (endPos > sr.endPos ? endPos : sr.endPos);
   613             return this;
   614         }
   615     }
   617 }

mercurial