Mercurial > hg > graal-jvmci-8
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 } |