comparison graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/JavaTypeProfile.java @ 9760:c76b43ed5089

Added infrastructure for recording invoked methods in the profiling information.
author Christian Haeubl <haeubl@ssw.jku.at>
date Fri, 17 May 2013 15:38:22 +0200
parents 708aea0e5a25
children 828f342cb275
comparison
equal deleted inserted replaced
9759:580faa2ee288 9760:c76b43ed5089
20 * or visit www.oracle.com if you need additional information or have any 20 * or visit www.oracle.com if you need additional information or have any
21 * questions. 21 * questions.
22 */ 22 */
23 package com.oracle.graal.api.meta; 23 package com.oracle.graal.api.meta;
24 24
25 import java.io.*;
26 import java.util.*; 25 import java.util.*;
27 26
28 import com.oracle.graal.api.meta.ProfilingInfo.*; 27 import com.oracle.graal.api.meta.JavaTypeProfile.ProfiledType;
28 import com.oracle.graal.api.meta.ProfilingInfo.TriState;
29 29
30 /** 30 /**
31 * This profile object represents the type profile at a specific BCI. The precision of the supplied 31 * This profile object represents the type profile at a specific BCI. The precision of the supplied
32 * values may vary, but a runtime that provides this information should be aware that it will be 32 * values may vary, but a runtime that provides this information should be aware that it will be
33 * used to guide performance-critical decisions like speculative inlining, etc. 33 * used to guide performance-critical decisions like speculative inlining, etc.
34 */ 34 */
35 public final class JavaTypeProfile implements Serializable { 35 public final class JavaTypeProfile extends AbstractJavaProfile<ProfiledType, ResolvedJavaType> {
36 36
37 private static final long serialVersionUID = -6877016333706838441L; 37 private static final long serialVersionUID = -6877016333706838441L;
38 38 private static final ProfiledType[] EMPTY_ARRAY = new ProfiledType[0];
39 /**
40 * A profiled type that has a probability. Profiled types are naturally sorted in descending
41 * order of their probabilities.
42 */
43 public static final class ProfiledType implements Comparable<ProfiledType>, Serializable {
44
45 private static final long serialVersionUID = 7838575753661305744L;
46
47 public static final ProfiledType[] EMPTY_ARRAY = new ProfiledType[0];
48
49 private final ResolvedJavaType type;
50 private final double probability;
51
52 public ProfiledType(ResolvedJavaType type, double probability) {
53 assert type != null;
54 assert probability >= 0.0D && probability <= 1.0D;
55 this.type = type;
56 this.probability = probability;
57 }
58
59 /**
60 * Returns the type for this profile entry.
61 */
62 public ResolvedJavaType getType() {
63 return type;
64 }
65
66 /**
67 * Returns the estimated probability of {@link #getType()}.
68 *
69 * @return double value >= 0.0 and <= 1.0
70 */
71 public double getProbability() {
72 return probability;
73 }
74
75 @Override
76 public int compareTo(ProfiledType o) {
77 if (getProbability() > o.getProbability()) {
78 return -1;
79 } else if (getProbability() < o.getProbability()) {
80 return 1;
81 }
82 return 0;
83 }
84
85 @Override
86 public int hashCode() {
87 final int prime = 31;
88 int result = 1;
89 long temp;
90 temp = Double.doubleToLongBits(probability);
91 result = prime * result + (int) (temp ^ (temp >>> 32));
92 result = prime * result + type.hashCode();
93 return result;
94 }
95
96 @Override
97 public boolean equals(Object obj) {
98 if (this == obj) {
99 return true;
100 }
101 if (obj == null) {
102 return false;
103 }
104 if (getClass() != obj.getClass()) {
105 return false;
106 }
107 ProfiledType other = (ProfiledType) obj;
108 if (Double.doubleToLongBits(probability) != Double.doubleToLongBits(other.probability)) {
109 return false;
110 }
111 return type.equals(other.type);
112 }
113
114 @Override
115 public String toString() {
116 return "{" + type.getName() + ", " + probability + "}";
117 }
118 }
119 39
120 private final TriState nullSeen; 40 private final TriState nullSeen;
121 private final double notRecordedProbability;
122 private final ProfiledType[] ptypes;
123 41
124 /** 42 public JavaTypeProfile(TriState nullSeen, double notRecordedProbability, ProfiledType[] pitems) {
125 * Determines if an array of profiled types are sorted in descending order of their 43 super(notRecordedProbability, pitems);
126 * probabilities.
127 */
128 private static boolean isSorted(ProfiledType[] ptypes) {
129 for (int i = 1; i < ptypes.length; i++) {
130 if (ptypes[i - 1].getProbability() < ptypes[i].getProbability()) {
131 return false;
132 }
133 }
134 return true;
135 }
136
137 public JavaTypeProfile(TriState nullSeen, double notRecordedProbability, ProfiledType... ptypes) {
138 this.nullSeen = nullSeen; 44 this.nullSeen = nullSeen;
139 this.ptypes = ptypes;
140 assert notRecordedProbability != Double.NaN;
141 this.notRecordedProbability = notRecordedProbability;
142 assert isSorted(ptypes);
143 }
144
145 /**
146 * Returns the estimated probability of all types that could not be recorded due to profiling
147 * limitations.
148 *
149 * @return double value >= 0.0 and <= 1.0
150 */
151 public double getNotRecordedProbability() {
152 return notRecordedProbability;
153 } 45 }
154 46
155 /** 47 /**
156 * Returns whether a null value was at the type check. 48 * Returns whether a null value was at the type check.
157 */ 49 */
163 * A list of types for which the runtime has recorded probability information. Note that this 55 * A list of types for which the runtime has recorded probability information. Note that this
164 * includes both positive and negative types where a positive type is a subtype of the checked 56 * includes both positive and negative types where a positive type is a subtype of the checked
165 * type and a negative type is not. 57 * type and a negative type is not.
166 */ 58 */
167 public ProfiledType[] getTypes() { 59 public ProfiledType[] getTypes() {
168 return ptypes; 60 return getItems();
169 }
170
171 /**
172 * Searches for an entry of a given resolved Java type.
173 *
174 * @param type the type for which an entry should be searched
175 * @return the entry or null if no entry for this type can be found
176 */
177 public ProfiledType findEntry(ResolvedJavaType type) {
178 if (ptypes != null) {
179 for (ProfiledType pt : ptypes) {
180 if (pt.getType() == type) {
181 return pt;
182 }
183 }
184 }
185 return null;
186 }
187
188 @Override
189 public String toString() {
190 StringBuilder builder = new StringBuilder();
191 builder.append("JavaTypeProfile[");
192 builder.append(this.nullSeen);
193 builder.append(", ");
194 if (ptypes != null) {
195 for (ProfiledType pt : ptypes) {
196 builder.append(pt.toString());
197 builder.append(", ");
198 }
199 }
200 builder.append(this.notRecordedProbability);
201 builder.append("]");
202 return builder.toString();
203 } 61 }
204 62
205 public JavaTypeProfile restrict(JavaTypeProfile otherProfile) { 63 public JavaTypeProfile restrict(JavaTypeProfile otherProfile) {
206 if (otherProfile.getNotRecordedProbability() > 0.0) { 64 if (otherProfile.getNotRecordedProbability() > 0.0) {
207 // Not useful for restricting since there is an unknown set of types occuring. 65 // Not useful for restricting since there is an unknown set of types occuring.
212 // We are unrestricted, so the other profile is always a better estimate. 70 // We are unrestricted, so the other profile is always a better estimate.
213 return otherProfile; 71 return otherProfile;
214 } 72 }
215 73
216 ArrayList<ProfiledType> result = new ArrayList<>(); 74 ArrayList<ProfiledType> result = new ArrayList<>();
217 for (int i = 0; i < getTypes().length; i++) { 75 for (int i = 0; i < getItems().length; i++) {
218 ProfiledType ptype = getTypes()[i]; 76 ProfiledType ptype = getItems()[i];
219 ResolvedJavaType type = ptype.getType(); 77 ResolvedJavaType type = ptype.getItem();
220 if (otherProfile.isIncluded(type)) { 78 if (otherProfile.isIncluded(type)) {
221 result.add(ptype); 79 result.add(ptype);
222 } 80 }
223 } 81 }
224 82
225 TriState newNullSeen = (otherProfile.getNullSeen() == TriState.FALSE) ? TriState.FALSE : this.nullSeen; 83 TriState newNullSeen = (otherProfile.getNullSeen() == TriState.FALSE) ? TriState.FALSE : getNullSeen();
226 double newNotRecorded = this.notRecordedProbability; 84 double newNotRecorded = getNotRecordedProbability();
227 return createAdjustedProfile(result, newNullSeen, newNotRecorded); 85 return createAdjustedProfile(result, newNullSeen, newNotRecorded);
228 }
229
230 public boolean isIncluded(ResolvedJavaType type) {
231 if (this.getNotRecordedProbability() > 0.0) {
232 return true;
233 } else {
234 for (int i = 0; i < getTypes().length; i++) {
235 ProfiledType ptype = getTypes()[i];
236 ResolvedJavaType curType = ptype.getType();
237 if (curType == type) {
238 return true;
239 }
240 }
241 }
242 return false;
243 } 86 }
244 87
245 public JavaTypeProfile restrict(ResolvedJavaType declaredType, boolean nonNull) { 88 public JavaTypeProfile restrict(ResolvedJavaType declaredType, boolean nonNull) {
246 ArrayList<ProfiledType> result = new ArrayList<>(); 89 ArrayList<ProfiledType> result = new ArrayList<>();
247 for (int i = 0; i < getTypes().length; i++) { 90 for (int i = 0; i < getItems().length; i++) {
248 ProfiledType ptype = getTypes()[i]; 91 ProfiledType ptype = getItems()[i];
249 ResolvedJavaType type = ptype.getType(); 92 ResolvedJavaType type = ptype.getItem();
250 if (declaredType.isAssignableFrom(type)) { 93 if (declaredType.isAssignableFrom(type)) {
251 result.add(ptype); 94 result.add(ptype);
252 } 95 }
253 } 96 }
254 97
255 TriState newNullSeen = (nonNull) ? TriState.FALSE : this.nullSeen; 98 TriState newNullSeen = (nonNull) ? TriState.FALSE : getNullSeen();
256 double newNotRecorded = this.getNotRecordedProbability(); 99 double newNotRecorded = this.getNotRecordedProbability();
257 // Assume for the types not recorded, the incompatibility rate is the same. 100 // Assume for the types not recorded, the incompatibility rate is the same.
258 if (getTypes().length != 0) { 101 if (getItems().length != 0) {
259 newNotRecorded *= ((double) result.size() / (double) getTypes().length); 102 newNotRecorded *= ((double) result.size() / (double) getItems().length);
260 } 103 }
261 return createAdjustedProfile(result, newNullSeen, newNotRecorded); 104 return createAdjustedProfile(result, newNullSeen, newNotRecorded);
262 } 105 }
263 106
264 private JavaTypeProfile createAdjustedProfile(ArrayList<ProfiledType> result, TriState newNullSeen, double newNotRecorded) { 107 private JavaTypeProfile createAdjustedProfile(ArrayList<ProfiledType> result, TriState newNullSeen, double newNotRecorded) {
265 if (result.size() != this.getTypes().length || newNotRecorded != getNotRecordedProbability() || newNullSeen != this.nullSeen) { 108 if (result.size() != this.getItems().length || newNotRecorded != getNotRecordedProbability() || newNullSeen != getNullSeen()) {
266 if (result.size() == 0) { 109 if (result.size() == 0) {
267 return new JavaTypeProfile(newNullSeen, 1.0, ProfiledType.EMPTY_ARRAY); 110 return new JavaTypeProfile(newNullSeen, 1.0, EMPTY_ARRAY);
268 } 111 }
269 double probabilitySum = 0.0; 112 double probabilitySum = 0.0;
270 for (int i = 0; i < result.size(); i++) { 113 for (int i = 0; i < result.size(); i++) {
271 probabilitySum += result.get(i).getProbability(); 114 probabilitySum += result.get(i).getProbability();
272 } 115 }
275 double factor = 1.0 / probabilitySum; // Normalize to 1.0 118 double factor = 1.0 / probabilitySum; // Normalize to 1.0
276 assert factor > 1.0; 119 assert factor > 1.0;
277 ProfiledType[] newResult = new ProfiledType[result.size()]; 120 ProfiledType[] newResult = new ProfiledType[result.size()];
278 for (int i = 0; i < newResult.length; ++i) { 121 for (int i = 0; i < newResult.length; ++i) {
279 ProfiledType curType = result.get(i); 122 ProfiledType curType = result.get(i);
280 newResult[i] = new ProfiledType(curType.getType(), Math.min(1.0, curType.getProbability() * factor)); 123 newResult[i] = new ProfiledType(curType.getItem(), Math.min(1.0, curType.getProbability() * factor));
281 } 124 }
282 double newNotRecordedTypeProbability = Math.min(1.0, newNotRecorded * factor); 125 double newNotRecordedTypeProbability = Math.min(1.0, newNotRecorded * factor);
283 return new JavaTypeProfile(newNullSeen, newNotRecordedTypeProbability, newResult); 126 return new JavaTypeProfile(newNullSeen, newNotRecordedTypeProbability, newResult);
284 } 127 }
285 return this; 128 return this;
286 } 129 }
287 130
288 @Override 131 @Override
289 public boolean equals(Object other) { 132 public boolean equals(Object other) {
290 if (other == this) { 133 return super.equals(other) && nullSeen.equals(((JavaTypeProfile) other).nullSeen);
291 return true;
292 }
293 if (other instanceof JavaTypeProfile) {
294 JavaTypeProfile javaTypeProfile = (JavaTypeProfile) other;
295 if (javaTypeProfile.nullSeen != nullSeen) {
296 return false;
297 }
298 if (javaTypeProfile.notRecordedProbability != notRecordedProbability) {
299 return false;
300 }
301 if (javaTypeProfile.ptypes.length != ptypes.length) {
302 return false;
303 }
304
305 for (int i = 0; i < ptypes.length; ++i) {
306 if (!ptypes[i].equals(javaTypeProfile.ptypes[i])) {
307 return false;
308 }
309 }
310
311 return true;
312 }
313 return false;
314 } 134 }
315 135
316 @Override 136 @Override
317 public int hashCode() { 137 public int hashCode() {
318 return nullSeen.hashCode() + (int) Double.doubleToLongBits(notRecordedProbability) + ptypes.length * 13; 138 return nullSeen.hashCode() + super.hashCode();
139 }
140
141 public static class ProfiledType extends AbstractProfiledItem<ResolvedJavaType> {
142
143 private static final long serialVersionUID = 1481773321889860837L;
144
145 public ProfiledType(ResolvedJavaType item, double probability) {
146 super(item, probability);
147 }
148
149 /**
150 * Returns the type for this profile entry.
151 */
152 public ResolvedJavaType getType() {
153 return getItem();
154 }
155
156 @Override
157 public String toString() {
158 return "{" + item.getName() + ", " + probability + "}";
159 }
319 } 160 }
320 } 161 }