comparison truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/profiles/ValueProfile.java @ 22501:a63bda98cfdb

Extract profiles into separate package. Add isProfilingEnabled in TruffleRuntime to disable profiling in the default runtime; Add low overhead profiles for primitives; Add LoopConditionProfile; Profile footprint/threadsafety improvements; Make toString implementations more consistent; Greatly enhanced javadoc documentation for profiles; Deprecate old profiles
author Christian Humer <christian.humer@oracle.com>
date Wed, 16 Dec 2015 16:38:13 +0100
parents truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/utilities/ValueProfile.java@71c7a1ae8829
children
comparison
equal deleted inserted replaced
22500:fbe1eb7b4172 22501:a63bda98cfdb
1 /*
2 * Copyright (c) 2014, 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. 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 */
25 package com.oracle.truffle.api.profiles;
26
27 import java.util.Objects;
28
29 import com.oracle.truffle.api.CompilerDirectives;
30 import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
31 import com.oracle.truffle.api.Truffle;
32
33 /**
34 * <p>
35 * Specialized value profile to capture certain properties of <code>Object</code> runtime values.
36 * Value profiles require a runtime check in their initialized state to verify their profiled
37 * assumption. Value profiles are limited to capture monomorphic profiles only. This means that if
38 * two or more identities or classes are profiles within a single profile then the profile has no
39 * effect and no overhead after compilation. There are specialized versions of this profile with
40 * less interpreter footprint for {@link ConditionProfile boolean}, {@link ByteValueProfile byte},
41 * {@link IntValueProfile int}, {@link LongValueProfile long}, {@link FloatValueProfile float} and
42 * {@link DoubleValueProfile double} values.
43 * </p>
44 *
45 * <p>
46 * <b> Usage example: </b>
47 *
48 * <pre>
49 * class SampleNode extends Node {
50 *
51 * final ValueProfile profile = ValueProfile.create{Identity,Class}Profile();
52 *
53 * Object execute(Object input) {
54 * Object profiledValue = profile.profile(input);
55 * // compiler may know now more about profiledValue
56 * return profieldValue;
57 * }
58 * }
59 * </pre>
60 * <p>
61 *
62 *
63 * {@inheritDoc}
64 *
65 * @see #createIdentityProfile()
66 * @see #createClassProfile()
67 */
68 public abstract class ValueProfile extends Profile {
69
70 ValueProfile() {
71 }
72
73 public abstract <T> T profile(T value);
74
75 /**
76 * <p>
77 * Returns a value profile that profiles the exact class of a value. It will check the class of
78 * the profiled value and provide additional information to the compiler if only non-null values
79 * of exactly one concrete Java class are passed as a parameter to the
80 * {@link ValueProfile#profile} method. This can be beneficial if subsequent code can take
81 * advantage of knowing the concrete class of the value. The profile will degrade to the generic
82 * case if a null value or if at least two instances of two different Java classes are
83 * registered.
84 * </p>
85 *
86 * <p>
87 * <b>Compilation notes:</b> Value profiles require a runtime check in their initialized state
88 * to verify their profiled class. If two classes have been seen on a single profile instance
89 * then this profile will transition to a generic state with no overhead.
90 * </P>
91 *
92 * @see ValueProfile usage example
93 */
94 public static ValueProfile createClassProfile() {
95 if (Truffle.getRuntime().isProfilingEnabled()) {
96 return ExactClass.create();
97 } else {
98 return Disabled.INSTANCE;
99 }
100 }
101
102 /**
103 * <p>
104 * Returns a value profile that profiles the object identity of a value. A single instance can
105 * only profile one particular instance.
106 * </p>
107 *
108 * <p>
109 * <b>Compilation notes:</b> Identity profiles require a runtime check to verify their profiled
110 * object identity. If two identities have been seen on a single profile instance then this
111 * profile will transition to a generic state with no overhead.
112 * </p>
113 */
114 public static ValueProfile createIdentityProfile() {
115 if (Truffle.getRuntime().isProfilingEnabled()) {
116 return Identity.create();
117 } else {
118 return Disabled.INSTANCE;
119 }
120 }
121
122 /**
123 * <p>
124 * Returns a value profile that profiles the object equality of a value. A single instance can
125 * only profile one set of equal values.
126 * </p>
127 *
128 * <p>
129 * <b>Compilation notes:</b> Equality profiles inline the body of the equal method of the first
130 * profiled value in order to verify its assumption. Please take care that you do this only for
131 * equals implementations that your guest language actually has control over otherwise your
132 * compiled code might contain recursions or too much code. If two non equal objects have been
133 * seen on a single profile instance then this profile will transition to a generic state with
134 * no overhead.
135 * </p>
136 */
137 public static ValueProfile createEqualityProfile() {
138 if (Truffle.getRuntime().isProfilingEnabled()) {
139 return Equality.create();
140 } else {
141 return Disabled.INSTANCE;
142 }
143 }
144
145 static final class Disabled extends ValueProfile {
146
147 static final ValueProfile INSTANCE = new Disabled();
148
149 @Override
150 protected Object clone() {
151 return INSTANCE;
152 }
153
154 @Override
155 public <T> T profile(T value) {
156 return value;
157 }
158
159 @Override
160 public String toString() {
161 return toStringDisabled(ValueProfile.class);
162 }
163
164 }
165
166 static final class Equality extends ValueProfile {
167
168 private static final Object GENERIC = new Object();
169
170 @CompilationFinal protected Object cachedValue = null;
171
172 Equality() {
173 }
174
175 @Override
176 @SuppressWarnings("unchecked")
177 public <T> T profile(T newValue) {
178 // Field needs to be cached in local variable for thread safety and startup speed.
179 Object cached = this.cachedValue;
180 if (cached != GENERIC) {
181 if (cached != null && cached.equals(newValue)) {
182 return (T) cached;
183 } else {
184 CompilerDirectives.transferToInterpreterAndInvalidate();
185 if (cached == null && newValue != null) {
186 cachedValue = newValue;
187 } else {
188 cachedValue = GENERIC;
189 }
190 }
191 }
192 return newValue;
193 }
194
195 public boolean isGeneric() {
196 return getCachedValue() == GENERIC;
197 }
198
199 public boolean isUninitialized() {
200 return getCachedValue() == null;
201 }
202
203 public Object getCachedValue() {
204 return cachedValue;
205 }
206
207 @Override
208 public String toString() {
209 return toString(ValueProfile.class, isUninitialized(), isGeneric(), //
210 String.format("value == %s@%x", cachedValue != null ? cachedValue.getClass().getSimpleName() : "null", Objects.hash(cachedValue)));
211 }
212
213 /* Needed for lazy class loading. */
214 static ValueProfile create() {
215 return new Equality();
216 }
217
218 }
219
220 static final class Identity extends ValueProfile {
221
222 private static final Object UNINITIALIZED = new Object();
223 private static final Object GENERIC = new Object();
224
225 @CompilationFinal protected Object cachedValue = UNINITIALIZED;
226
227 Identity() {
228 }
229
230 @Override
231 @SuppressWarnings("unchecked")
232 public <T> T profile(T newValue) {
233 // Field needs to be cached in local variable for thread safety and startup speed.
234 Object cached = this.cachedValue;
235 if (cached != GENERIC) {
236 if (cached == newValue) {
237 return (T) cached;
238 } else {
239 CompilerDirectives.transferToInterpreterAndInvalidate();
240 if (cachedValue == UNINITIALIZED) {
241 cachedValue = newValue;
242 } else {
243 cachedValue = GENERIC;
244 }
245 }
246 }
247 return newValue;
248 }
249
250 public boolean isGeneric() {
251 return getCachedValue() == GENERIC;
252 }
253
254 public boolean isUninitialized() {
255 return getCachedValue() == UNINITIALIZED;
256 }
257
258 public Object getCachedValue() {
259 return cachedValue;
260 }
261
262 @Override
263 public String toString() {
264 return toString(ValueProfile.class, isUninitialized(), isGeneric(), //
265 String.format("value == %s@%x", cachedValue != null ? cachedValue.getClass().getSimpleName() : "null", Objects.hash(cachedValue)));
266 }
267
268 /* Needed for lazy class loading. */
269 static ValueProfile create() {
270 return new Identity();
271 }
272
273 }
274
275 static final class ExactClass extends ValueProfile {
276
277 @CompilationFinal protected Class<?> cachedClass;
278
279 ExactClass() {
280 }
281
282 public static ValueProfile create() {
283 return new ExactClass();
284 }
285
286 @SuppressWarnings("unchecked")
287 @Override
288 public <T> T profile(T value) {
289 // Field needs to be cached in local variable for thread safety and startup speed.
290 Class<?> clazz = cachedClass;
291 if (clazz != Object.class) {
292 if (clazz != null && value != null && clazz == value.getClass()) {
293 /*
294 * The cast is really only for the compiler relevant. It does not perform any
295 * useful action in the interpreter and only takes time.
296 */
297 if (CompilerDirectives.inInterpreter()) {
298 return value;
299 } else {
300 return (T) clazz.cast(value);
301 }
302 } else {
303 CompilerDirectives.transferToInterpreterAndInvalidate();
304 if (clazz == null && value != null) {
305 cachedClass = value.getClass();
306 } else {
307 cachedClass = Object.class;
308 }
309 }
310 }
311 return value;
312 }
313
314 boolean isGeneric() {
315 return cachedClass == Object.class;
316 }
317
318 boolean isUninitialized() {
319 return cachedClass == null;
320 }
321
322 Class<?> getCachedClass() {
323 return cachedClass;
324 }
325
326 @Override
327 public String toString() {
328 return toString(ValueProfile.class, cachedClass == null, cachedClass == Object.class, //
329 String.format("value.getClass() == %s.class", cachedClass != null ? cachedClass.getSimpleName() : "null"));
330 }
331
332 }
333
334 }