src/utils/LogCompilation/src/com/sun/hotspot/tools/compiler/CallSite.java
branchhttp-client-branch
changeset 55973 4d9b002587db
parent 55972 3fe2ae6d97a4
parent 48202 309dbeb79657
child 55977 a31a16b95f6f
equal deleted inserted replaced
55972:3fe2ae6d97a4 55973:4d9b002587db
     1 /*
       
     2  * Copyright (c) 2009, 2015, 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.
       
     8  *
       
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    12  * version 2 for more details (a copy is included in the LICENSE file that
       
    13  * accompanied this code).
       
    14  *
       
    15  * You should have received a copy of the GNU General Public License version
       
    16  * 2 along with this work; if not, write to the Free Software Foundation,
       
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    18  *
       
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    20  * or visit www.oracle.com if you need additional information or have any
       
    21  * questions.
       
    22  *
       
    23  */
       
    24 
       
    25 package com.sun.hotspot.tools.compiler;
       
    26 
       
    27 import java.io.PrintStream;
       
    28 import java.util.ArrayDeque;
       
    29 import java.util.ArrayList;
       
    30 import java.util.List;
       
    31 
       
    32 /**
       
    33  * Representation of a compilation scope in a compilation log. This class is a
       
    34  * hybrid: its instances can represent original scopes of methods being
       
    35  * compiled, but are also used to represent call sites in given methods.
       
    36  */
       
    37 public class CallSite {
       
    38 
       
    39     /**
       
    40      * The index of the call in the caller. This will be 0 if this instance
       
    41      * represents a compilation root.
       
    42      */
       
    43     private int bci;
       
    44 
       
    45     /**
       
    46      * The method that is called at this call site. This will be {@code null}
       
    47      * if this instance represents a compilation root.
       
    48      */
       
    49     private Method method;
       
    50 
       
    51     /**
       
    52      * The invocation count for this call site.
       
    53      */
       
    54     private int count;
       
    55 
       
    56     /**
       
    57      * The receiver type of the call represented by this instance, if known.
       
    58      */
       
    59     private String receiver;
       
    60 
       
    61     /**
       
    62      * In case the {@linkplain receiver receiver type} of the call represented
       
    63      * by this instance is known, this is how often the type was encountered.
       
    64      */
       
    65     private int receiver_count;
       
    66 
       
    67     /**
       
    68      * The reason for a success or failure of an inlining operation at this
       
    69      * call site.
       
    70      */
       
    71     private String reason;
       
    72 
       
    73     /**
       
    74      * A list of all calls in this compilation scope.
       
    75      */
       
    76     private List<CallSite> calls;
       
    77 
       
    78     /**
       
    79      * Number of nodes in the graph at the end of parsing this compilation
       
    80      * scope.
       
    81      */
       
    82     private int endNodes;
       
    83 
       
    84     /**
       
    85      * Number of live nodes in the graph at the end of parsing this compilation
       
    86      * scope.
       
    87      */
       
    88     private int endLiveNodes;
       
    89 
       
    90     /**
       
    91      * Time in seconds since VM startup at which parsing this compilation scope
       
    92      * ended.
       
    93      */
       
    94     private double timeStamp;
       
    95 
       
    96     /**
       
    97      * The inline ID in case the call represented by this instance is inlined,
       
    98      * 0 otherwise.
       
    99      */
       
   100     private long inlineId;
       
   101 
       
   102     /**
       
   103      * List of uncommon traps in this compilation scope.
       
   104      */
       
   105     private List<UncommonTrap> traps;
       
   106 
       
   107     /**
       
   108      * Default constructor: used to create an instance that represents the top
       
   109      * scope of a compilation.
       
   110      */
       
   111     CallSite() {}
       
   112 
       
   113     /**
       
   114      * Constructor to create an instance that represents an actual method call.
       
   115      */
       
   116     CallSite(int bci, Method m) {
       
   117         this.bci = bci;
       
   118         this.method = m;
       
   119     }
       
   120 
       
   121     /**
       
   122      * Add a call site to the compilation scope represented by this instance.
       
   123      */
       
   124     void add(CallSite site) {
       
   125         if (getCalls() == null) {
       
   126             calls = new ArrayList<>();
       
   127         }
       
   128         getCalls().add(site);
       
   129     }
       
   130 
       
   131     /**
       
   132      * Return the last of the {@linkplain #getCalls() call sites} in this
       
   133      * compilation scope.
       
   134      */
       
   135     CallSite last() {
       
   136         return getCalls().get(getCalls().size() - 1);
       
   137     }
       
   138 
       
   139     /**
       
   140      * Return the last-but-one of the {@linkplain #getCalls() call sites} in
       
   141      * this compilation scope.
       
   142      */
       
   143     CallSite lastButOne() {
       
   144         return getCalls().get(getCalls().size() - 2);
       
   145     }
       
   146 
       
   147     public String toString() {
       
   148         StringBuilder sb = new StringBuilder();
       
   149         if (getReason() == null) {
       
   150             sb.append("  @ " + getBci() + " " + getMethod());
       
   151         } else {
       
   152             sb.append("- @ " + getBci() + " " + getMethod() + " " + getReason());
       
   153         }
       
   154         sb.append("\n");
       
   155         if (getCalls() != null) {
       
   156             for (CallSite site : getCalls()) {
       
   157                 sb.append(site);
       
   158                 sb.append("\n");
       
   159             }
       
   160         }
       
   161         return sb.toString();
       
   162     }
       
   163 
       
   164     public void print(PrintStream stream) {
       
   165         print(stream, 0, true, false);
       
   166     }
       
   167 
       
   168     void emit(PrintStream stream, int indent) {
       
   169         for (int i = 0; i < indent; i++) {
       
   170             stream.print(' ');
       
   171         }
       
   172     }
       
   173 
       
   174     public void print(PrintStream stream, int indent, boolean printInlining, boolean printUncommonTraps) {
       
   175         emit(stream, indent);
       
   176         String m = getMethod().getHolder() + "::" + getMethod().getName();
       
   177         if (getReason() == null) {
       
   178             stream.print("  @ " + getBci() + " " + m + " (" + getMethod().getBytes() + " bytes)");
       
   179         } else {
       
   180             stream.print("  @ " + getBci() + " " + m + " " + getReason());
       
   181         }
       
   182         stream.printf(" (end time: %6.4f", getTimeStamp());
       
   183         if (getEndNodes() > 0) {
       
   184             stream.printf(" nodes: %d live: %d", getEndNodes(), getEndLiveNodes());
       
   185         }
       
   186         stream.println(")");
       
   187 
       
   188         if (getReceiver() != null) {
       
   189             emit(stream, indent + 4);
       
   190             stream.println("type profile " + getMethod().getHolder() + " -> " + getReceiver() + " (" +
       
   191                     (getReceiverCount() * 100 / getCount()) + "%)");
       
   192         }
       
   193         if (printInlining && getCalls() != null) {
       
   194             for (CallSite site : getCalls()) {
       
   195                 site.print(stream, indent + 2, printInlining, printUncommonTraps);
       
   196             }
       
   197         }
       
   198         if (printUncommonTraps && getTraps() != null) {
       
   199             for (UncommonTrap site : getTraps()) {
       
   200                 site.print(stream, indent + 2);
       
   201             }
       
   202         }
       
   203     }
       
   204 
       
   205     public int getBci() {
       
   206         return bci;
       
   207     }
       
   208 
       
   209     public void setBci(int bci) {
       
   210         this.bci = bci;
       
   211     }
       
   212 
       
   213     public Method getMethod() {
       
   214         return method;
       
   215     }
       
   216 
       
   217     public void setMethod(Method method) {
       
   218         this.method = method;
       
   219     }
       
   220 
       
   221     public int getCount() {
       
   222         return count;
       
   223     }
       
   224 
       
   225     public void setCount(int count) {
       
   226         this.count = count;
       
   227     }
       
   228 
       
   229     public String getReceiver() {
       
   230         return receiver;
       
   231     }
       
   232 
       
   233     public void setReceiver(String receiver) {
       
   234         this.receiver = receiver;
       
   235     }
       
   236 
       
   237     public int getReceiverCount() {
       
   238         return receiver_count;
       
   239     }
       
   240 
       
   241     public void setReceiver_count(int receiver_count) {
       
   242         this.receiver_count = receiver_count;
       
   243     }
       
   244 
       
   245     public String getReason() {
       
   246         return reason;
       
   247     }
       
   248 
       
   249     public void setReason(String reason) {
       
   250         this.reason = reason;
       
   251     }
       
   252 
       
   253     public List<CallSite> getCalls() {
       
   254         return calls;
       
   255     }
       
   256 
       
   257     public List<UncommonTrap> getTraps() {
       
   258         return traps;
       
   259     }
       
   260 
       
   261     void add(UncommonTrap e) {
       
   262         if (traps == null) {
       
   263             traps = new ArrayList<UncommonTrap>();
       
   264         }
       
   265         traps.add(e);
       
   266     }
       
   267 
       
   268     void setEndNodes(int n) {
       
   269         endNodes = n;
       
   270     }
       
   271 
       
   272     public int getEndNodes() {
       
   273         return endNodes;
       
   274     }
       
   275 
       
   276     void setEndLiveNodes(int n) {
       
   277         endLiveNodes = n;
       
   278     }
       
   279 
       
   280     public int getEndLiveNodes() {
       
   281         return endLiveNodes;
       
   282     }
       
   283 
       
   284     void setTimeStamp(double time) {
       
   285         timeStamp = time;
       
   286     }
       
   287 
       
   288     public double getTimeStamp() {
       
   289         return timeStamp;
       
   290     }
       
   291 
       
   292     /**
       
   293      * Check whether this call site matches another. Every late inline call
       
   294      * site has a unique inline ID. If the call site we're looking for has one,
       
   295      * then use it; otherwise rely on method name and byte code index.
       
   296      */
       
   297     private boolean matches(CallSite other) {
       
   298         if (other.inlineId != 0) {
       
   299             return inlineId == other.inlineId;
       
   300         }
       
   301         return method.equals(other.method) && bci == other.bci;
       
   302     }
       
   303 
       
   304     /**
       
   305      * Locate a late inline call site: find, in this instance's
       
   306      * {@linkplain #calls call sites}, the one furthest down the given call
       
   307      * stack.
       
   308      *
       
   309      * Multiple chains of identical call sites with the same method name / bci
       
   310      * combination are possible, so we have to try them all until we find the
       
   311      * late inline call site that has a matching inline ID.
       
   312      *
       
   313      * @return a matching call site, or {@code null} if none was found.
       
   314      */
       
   315     public CallSite findCallSite(ArrayDeque<CallSite> sites) {
       
   316         if (calls == null) {
       
   317             return null;
       
   318         }
       
   319         CallSite site = sites.pop();
       
   320         for (CallSite c : calls) {
       
   321             if (c.matches(site)) {
       
   322                 if (!sites.isEmpty()) {
       
   323                     CallSite res = c.findCallSite(sites);
       
   324                     if (res != null) {
       
   325                         sites.push(site);
       
   326                         return res;
       
   327                     }
       
   328                 } else {
       
   329                     sites.push(site);
       
   330                     return c;
       
   331                 }
       
   332             }
       
   333         }
       
   334         sites.push(site);
       
   335         return null;
       
   336     }
       
   337 
       
   338     /**
       
   339      * Locate a late inline call site in the tree spanned by all this instance's
       
   340      * {@linkplain #calls call sites}, and return the sequence of call sites
       
   341      * (scopes) leading to that late inline call site.
       
   342      */
       
   343     public ArrayDeque<CallSite> findCallSite2(CallSite site) {
       
   344         if (calls == null) {
       
   345             return null;
       
   346         }
       
   347 
       
   348         for (CallSite c : calls) {
       
   349             if (c.matches(site)) {
       
   350                 ArrayDeque<CallSite> stack = new ArrayDeque<>();
       
   351                 stack.push(c);
       
   352                 return stack;
       
   353             } else {
       
   354                 ArrayDeque<CallSite> stack = c.findCallSite2(site);
       
   355                 if (stack != null) {
       
   356                     stack.push(c);
       
   357                     return stack;
       
   358                 }
       
   359             }
       
   360         }
       
   361         return null;
       
   362     }
       
   363 
       
   364     public long getInlineId() {
       
   365         return inlineId;
       
   366     }
       
   367 
       
   368     public void setInlineId(long inlineId) {
       
   369         this.inlineId = inlineId;
       
   370     }
       
   371 }