comparison truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/profiles/ConditionProfile.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/ConditionProfile.java@dc83cc1f94f2
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 com.oracle.truffle.api.CompilerDirectives;
28 import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
29 import com.oracle.truffle.api.Truffle;
30
31 /**
32 * <p>
33 * ConditionProfiles are useful to profile the outcome of conditions.
34 * </p>
35 *
36 * <p>
37 * <b> Usage example: </b>
38 *
39 * <pre>
40 * class AbsoluteNode extends Node {
41 *
42 * final ConditionProfile greaterZeroProfile = ConditionProfile.create{Binary,Counting}Profile();
43 *
44 * void execute(int value) {
45 * if (greaterZeroProfile.profile(value >= 0)) {
46 * return value;
47 * } else {
48 * return -value;
49 * }
50 * }
51 * }
52 * </pre>
53 *
54 * {@inheritDoc}
55 *
56 * @see #createBinaryProfile()
57 * @see #createCountingProfile()
58 * @see LoopConditionProfile
59 */
60 public abstract class ConditionProfile extends Profile {
61
62 ConditionProfile() {
63 }
64
65 public abstract boolean profile(boolean value);
66
67 /**
68 * Returns a {@link ConditionProfile} that speculates on conditions to be never
69 * <code>true</code> or to be never <code>false</code>. Additionally to a binary profile this
70 * method returns a condition profile that also counts the number of times the condition was
71 * true and false. This information is reported to the underlying optimization system using
72 * {@link CompilerDirectives#injectBranchProbability(double, boolean)}. Condition profiles are
73 * intended to be used as part of if conditions.
74 *
75 * @see ConditionProfile
76 * @see #createBinaryProfile()
77 */
78 public static ConditionProfile createCountingProfile() {
79 if (Truffle.getRuntime().isProfilingEnabled()) {
80 return Counting.create();
81 } else {
82 return Disabled.INSTANCE;
83 }
84 }
85
86 /**
87 * Returns a {@link ConditionProfile} that speculates on conditions to be never
88 * <code>true</code> or to be never <code>false</code>. Condition profiles are intended to be
89 * used as part of if conditions.
90 *
91 * @see ConditionProfile
92 * @see ConditionProfile#createCountingProfile()
93 */
94 public static ConditionProfile createBinaryProfile() {
95 if (Truffle.getRuntime().isProfilingEnabled()) {
96 return Binary.create();
97 } else {
98 return Disabled.INSTANCE;
99 }
100 }
101
102 static final class Disabled extends ConditionProfile {
103
104 static final ConditionProfile INSTANCE = new Disabled();
105
106 @Override
107 protected Object clone() {
108 return INSTANCE;
109 }
110
111 @Override
112 public boolean profile(boolean value) {
113 return value;
114 }
115
116 @Override
117 public String toString() {
118 return toStringDisabled(ConditionProfile.class);
119 }
120
121 }
122
123 static final class Counting extends ConditionProfile {
124
125 @CompilationFinal private int trueCount;
126 @CompilationFinal private int falseCount;
127
128 Counting() {
129 /* package protected constructor */
130 }
131
132 @Override
133 public boolean profile(boolean value) {
134 if (CompilerDirectives.inInterpreter()) {
135 if (value) {
136 // local required to guarantee no overflow in multi-threaded environments
137 int t = trueCount;
138 if (t < Integer.MAX_VALUE) {
139 trueCount = t + 1;
140 }
141 } else {
142 // local required to guarantee no overflow in multi-threaded environments
143 int f = falseCount;
144 if (f < Integer.MAX_VALUE) {
145 falseCount = f + 1;
146 }
147 }
148 // no branch probability calculation in the interpreter
149 return value;
150 } else {
151 // use trueCount and falseCount as locals for compilation speed
152 int t = trueCount;
153 int f = falseCount;
154 if (value) {
155 if (t == 0) {
156 CompilerDirectives.transferToInterpreterAndInvalidate();
157 t = 1;
158 }
159 } else {
160 if (f == 0) {
161 CompilerDirectives.transferToInterpreterAndInvalidate();
162 f = 1;
163 }
164 }
165 return CompilerDirectives.injectBranchProbability((double) t / (double) (t + f), value);
166 }
167 }
168
169 int getTrueCount() {
170 return trueCount;
171 }
172
173 int getFalseCount() {
174 return falseCount;
175 }
176
177 @Override
178 public String toString() {
179 int t = trueCount;
180 int f = falseCount;
181 return toString(ConditionProfile.class, trueCount == 0 && falseCount == 0, false, //
182 String.format("trueProbability=%s (trueCount=%s, falseCount=%s)", (double) t / (double) (t + f), t, f));
183 }
184
185 /* Needed for lazy class loading. */
186 static ConditionProfile create() {
187 return new Counting();
188 }
189 }
190
191 /**
192 * Utility class to speculate on conditions to be never true or to be never false. Condition
193 * profiles are intended to be used as part of if conditions.
194 *
195 * @see ConditionProfile#createBinaryProfile()
196 */
197 static final class Binary extends ConditionProfile {
198
199 @CompilationFinal private boolean wasTrue;
200 @CompilationFinal private boolean wasFalse;
201
202 Binary() {
203 /* package protected constructor */
204 }
205
206 @Override
207 public boolean profile(boolean value) {
208 if (value) {
209 if (!wasTrue) {
210 CompilerDirectives.transferToInterpreterAndInvalidate();
211 wasTrue = true;
212 }
213 return true;
214 } else {
215 if (!wasFalse) {
216 CompilerDirectives.transferToInterpreterAndInvalidate();
217 wasFalse = true;
218 }
219 return false;
220 }
221 }
222
223 boolean wasTrue() {
224 return wasTrue;
225 }
226
227 boolean wasFalse() {
228 return wasFalse;
229 }
230
231 @Override
232 public String toString() {
233 return String.format("%s(wasTrue=%s, wasFalse=%s)@%x", getClass().getSimpleName(), wasTrue, wasFalse, hashCode());
234 }
235
236 /* Needed for lazy class loading. */
237 static ConditionProfile create() {
238 return new Binary();
239 }
240 }
241
242 }