1 /* 2 * Copyright (c) 2009, 2013, 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 public class CallSite { 33 34 private int bci; 35 private Method method; 36 private int count; 37 private String receiver; 38 private int receiver_count; 39 private String reason; 40 private List<CallSite> calls; 41 private int endNodes; 42 private int endLiveNodes; 43 private double timeStamp; 44 private long inlineId; 45 46 CallSite() { 47 } 48 49 CallSite(int bci, Method m) { 50 this.bci = bci; 51 this.method = m; 52 } 53 54 void add(CallSite site) { 55 if (getCalls() == null) { 56 setCalls(new ArrayList<CallSite>()); 57 } 58 getCalls().add(site); 59 } 60 61 CallSite last() { 62 return last(-1); 63 } 64 65 CallSite last(int fromEnd) { 66 return getCalls().get(getCalls().size() + fromEnd); 67 } 68 69 public String toString() { 70 StringBuilder sb = new StringBuilder(); 71 if (getReason() == null) { 72 sb.append(" @ " + getBci() + " " + getMethod()); 73 } else { 74 sb.append("- @ " + getBci() + " " + getMethod() + " " + getReason()); 75 } 76 sb.append("\n"); 77 if (getCalls() != null) { 78 for (CallSite site : getCalls()) { 79 sb.append(site); 80 sb.append("\n"); 81 } 82 } 83 return sb.toString(); 84 } 85 86 public void print(PrintStream stream) { 87 print(stream, 0); 88 } 89 90 void emit(PrintStream stream, int indent) { 91 for (int i = 0; i < indent; i++) { 92 stream.print(' '); 93 } 94 } 95 private static boolean compat = true; 96 97 public void print(PrintStream stream, int indent) { 98 emit(stream, indent); 99 String m = getMethod().getHolder() + "::" + getMethod().getName(); 100 if (getReason() == null) { 101 stream.print(" @ " + getBci() + " " + m + " (" + getMethod().getBytes() + " bytes)"); 102 103 } else { 104 if (isCompat()) { 105 stream.print(" @ " + getBci() + " " + m + " " + getReason()); 106 } else { 107 stream.print("- @ " + getBci() + " " + m + 108 " (" + getMethod().getBytes() + " bytes) " + getReason()); 109 } 110 } 111 stream.printf(" (end time: %6.4f", getTimeStamp()); 112 if (getEndNodes() > 0) { 113 stream.printf(" nodes: %d live: %d", getEndNodes(), getEndLiveNodes()); 114 } 115 stream.println(")"); 116 117 if (getReceiver() != null) { 118 emit(stream, indent + 4); 119 // stream.println("type profile " + method.holder + " -> " + receiver + " (" + 120 // receiver_count + "/" + count + "," + (receiver_count * 100 / count) + "%)"); 121 stream.println("type profile " + getMethod().getHolder() + " -> " + getReceiver() + " (" + 122 (getReceiverCount() * 100 / getCount()) + "%)"); 123 } 124 if (getCalls() != null) { 125 for (CallSite site : getCalls()) { 126 site.print(stream, indent + 2); 127 } 128 } 129 } 130 131 public int getBci() { 132 return bci; 133 } 134 135 public void setBci(int bci) { 136 this.bci = bci; 137 } 138 139 public Method getMethod() { 140 return method; 141 } 142 143 public void setMethod(Method method) { 144 this.method = method; 145 } 146 147 public int getCount() { 148 return count; 149 } 150 151 public void setCount(int count) { 152 this.count = count; 153 } 154 155 public String getReceiver() { 156 return receiver; 157 } 158 159 public void setReceiver(String receiver) { 160 this.receiver = receiver; 161 } 162 163 public int getReceiverCount() { 164 return receiver_count; 165 } 166 167 public void setReceiver_count(int receiver_count) { 168 this.receiver_count = receiver_count; 169 } 170 171 public String getReason() { 172 return reason; 173 } 174 175 public void setReason(String reason) { 176 this.reason = reason; 177 } 178 179 public List<CallSite> getCalls() { 180 return calls; 181 } 182 183 public void setCalls(List<CallSite> calls) { 184 this.calls = calls; 185 } 186 187 public static boolean isCompat() { 188 return compat; 189 } 190 191 public static void setCompat(boolean aCompat) { 192 compat = aCompat; 193 } 194 195 void setEndNodes(int n) { 196 endNodes = n; 197 } 198 199 public int getEndNodes() { 200 return endNodes; 201 } 202 203 void setEndLiveNodes(int n) { 204 endLiveNodes = n; 205 } 206 207 public int getEndLiveNodes() { 208 return endLiveNodes; 209 } 210 211 void setTimeStamp(double time) { 212 timeStamp = time; 213 } 214 215 public double getTimeStamp() { 216 return timeStamp; 217 } 218 219 private boolean matches(CallSite other) { 220 // Every late inline call site has a unique inline id. If the 221 // call site we're looking for has one then use it other rely 222 // on method name and bci. 223 if (other.inlineId != 0) { 224 return inlineId == other.inlineId; 225 } 226 return method.equals(other.method) && bci == other.bci; 227 } 228 229 public CallSite findCallSite(ArrayDeque<CallSite> sites) { 230 // Locate a late inline call site. Multiple chains of 231 // identical call sites with the same method name/bci are 232 // possible so we have to try them all until we find the late 233 // inline call site that has a matching inline id. 234 if (calls == null) { 235 return null; 236 } 237 CallSite site = sites.pop(); 238 for (CallSite c : calls) { 239 if (c.matches(site)) { 240 if (!sites.isEmpty()) { 241 CallSite res = c.findCallSite(sites); 242 if (res != null) { 243 sites.push(site); 244 return res; 245 } 246 } else { 247 sites.push(site); 248 return c; 249 } 250 } 251 } 252 sites.push(site); 253 return null; 254 } 255 256 public ArrayDeque<CallSite> findCallSite2(CallSite site) { 257 if (calls == null) { 258 return null; 259 } 260 261 for (CallSite c : calls) { 262 if (c.matches(site)) { 263 ArrayDeque<CallSite> stack = new ArrayDeque<CallSite>(); 264 stack.push(c); 265 return stack; 266 } else { 267 ArrayDeque<CallSite> stack = c.findCallSite2(site); 268 if (stack != null) { 269 stack.push(c); 270 return stack; 271 } 272 } 273 } 274 return null; 275 } 276 277 public long getInlineId() { 278 return inlineId; 279 } 280 281 public void setInlineId(long inlineId) { 282 this.inlineId = inlineId; 283 } 284 }