comparison graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Specialization.java @ 19288:3a37116ef37f

Truffle-DSL: added @Cached annotation, added limit property and updated @Specialization javadoc.
author Christian Humer <christian.humer@gmail.com>
date Mon, 29 Dec 2014 18:32:03 +0100
parents ea9903f9684f
children 67ab244ab689
comparison
equal deleted inserted replaced
19287:19c6359c6191 19288:3a37116ef37f
1 /* 1 /*
2 * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. 2 * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 * 4 *
5 * This code is free software; you can redistribute it and/or modify it 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 6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this 7 * published by the Free Software Foundation. Oracle designates this
24 */ 24 */
25 package com.oracle.truffle.api.dsl; 25 package com.oracle.truffle.api.dsl;
26 26
27 import java.lang.annotation.*; 27 import java.lang.annotation.*;
28 28
29 import com.oracle.truffle.api.*;
30 import com.oracle.truffle.api.frame.*;
31 import com.oracle.truffle.api.nodes.*;
32
33 /**
34 * <p>
35 * Defines a method of a node subclass to represent one specialization of an operation. Multiple
36 * specializations can be defined in a node representing an operation. A specialization defines
37 * which kind of input is expected using the method signature and the annotation attributes. The
38 * specialized semantics of the operation are defined using the body of the annotated Java method. A
39 * specialization method must be declared in a class that is derived from {@link Node} that
40 * references a {@link TypeSystem}. At least one specialization must be defined per operation. If no
41 * specialization is valid for the given set of input values then an
42 * {@link UnsupportedSpecializationException} is thrown instead of invoking any specialization
43 * method.
44 * </p>
45 * <p>
46 * A specialization must have at least as many parameters as there are {@link NodeChild} annotations
47 * declared for the enclosing operation node. These parameters are declared in the same order as the
48 * {@link NodeChild} annotations (linear execution order). We call such parameters dynamic input
49 * parameters. Every specialization that is declared within an operation must have an equal number
50 * of dynamic input parameters.
51 * </p>
52 * <p>
53 * The supported kind of input values for a specialization are declared using guards. A
54 * specialization may provide declarative specifications for four kinds of guards:
55 * <ul>
56 * <li><b>Type guards</b> optimistically assume the type of an input value. A value that matches the
57 * type is cast to its expected type automatically. Type guards are modeled using the parameter type
58 * of the specialization method. Types used for type guards must be defined in the
59 * {@link TypeSystem}. If the type of the parameter is {@link Object} then no type guard is used for
60 * the dynamic input parameter.</li>
61 *
62 * <li><b>Expression guards</b> optimistically assume the return value of a user-defined expression
63 * to be <code>true</code>. Expression guards are modeled using Java expressions that return a
64 * <code>boolean</code> value. If the guard expression returns <code>false</code>, the
65 * specialization is no longer applicable and the operation is re-specialized. Guard expressions are
66 * declared using the {@link #guards()} attribute.</li>
67 *
68 * <li><b>Event guards</b> trigger re-specialization in case an exception is thrown in the
69 * specialization body. The {@link #rewriteOn()} attribute can be used to declare a list of such
70 * exceptions. Guards of this kind are useful to avoid calculating a value twice when it is used in
71 * the guard and its specialization.</li>
72 *
73 * <li><b>Assumption guards</b> optimistically assume that the state of an {@link Assumption}
74 * remains <code>true</code>. Assumptions can be assigned to specializations using the
75 * {@link #assumptions()} attribute.</li>
76 * </ul>
77 * </p>
78 * <p>
79 * The enclosing {@link Node} of a specialization method must have at least one <code>public</code>
80 * and non-<code>final</code> execute method. An execute method is a method that starts with
81 * 'execute'. If all execute methods declare the first parameter type as {@link Frame},
82 * {@link VirtualFrame} or {@link MaterializedFrame} then the same frame type can be used as
83 * optional first parameter of the specialization. This parameter does not count to the number of
84 * dynamic parameters.
85 * </p>
86 * <p>
87 * A specialization method may declare multiple parameters annotated with {@link Cached}. Cached
88 * parameters are initialized and stored once per specialization instantiation. For consistency
89 * between specialization declarations cached parameters must be declared last in a specialization
90 * method.
91 * </p>
92 * <p>
93 * If the operation is re-specialized or if it is executed for the first time then all declared
94 * specializations of the operation are tried in declaration order until the guards of the first
95 * specialization accepts the current input values. The new specialization is then added to the
96 * chain of current specialization instances which might consist of one (monomorph) or multiple
97 * instances (polymorph). If an assumption of an instantiated specialization is violated then
98 * re-specialization is triggered again.
99 * </p>
100 * <p>
101 * With guards in combination with cached parameters it is possible that multiple instances of the
102 * same specialization are created. The {@link #limit()} attribute can be used to limit the number
103 * of instantiations per specialization.
104 * </p>
105 *
106 * @see NodeChild
107 * @see ShortCircuit
108 * @see Fallback
109 * @see Cached
110 * @see TypeSystem
111 * @see TypeSystemReference
112 * @see UnsupportedSpecializationException
113 */
29 @Retention(RetentionPolicy.RUNTIME) 114 @Retention(RetentionPolicy.RUNTIME)
30 @Target({ElementType.METHOD}) 115 @Target({ElementType.METHOD})
31 public @interface Specialization { 116 public @interface Specialization {
32 117
33 /** 118 /**
34 * @deprecated do not use anymore. Will get removed in the next release. 119 * @deprecated do not use anymore. Will get removed in the next release.
35 */ 120 */
36 @Deprecated int DEFAULT_ORDER = -1; 121 @Deprecated int DEFAULT_ORDER = -1;
37 122
38 /** 123 /**
39 * The order has no effect anymore. The declaration order specialization methods is used
40 * instead.
41 *
42 * @deprecated use declaration order instead. Will get removed in the next release. 124 * @deprecated use declaration order instead. Will get removed in the next release.
43 */ 125 */
44 @Deprecated 126 @Deprecated
45 int order() default DEFAULT_ORDER; 127 int order() default DEFAULT_ORDER;
46 128
47 /** 129 /**
48 * Inserts this and all specializations that are declared after this specialization before a 130 * References a specialization of a super class by its method name where this specialization is
49 * specialization in the superclass. By default all specializations of the subclass are appended 131 * inserted before. The declaration order of a specialization is not usable for nodes where
50 * to the specializations of the superclass. 132 * specializations are partly declared in the super class and partly declared in a derived
133 * class. By default all specializations declared in the derived class are appended to those in
134 * the super class. This attribute can be used to override the default behavior.
51 */ 135 */
52 String insertBefore() default ""; 136 String insertBefore() default "";
53 137
138 /**
139 * <p>
140 * Declares an event guards that trigger re-specialization in case an exception is thrown in the
141 * specialization body. This attribute can be used to declare a list of such exceptions. Guards
142 * of this kind are useful to avoid calculating a value twice when it is used in the guard and
143 * its specialization.
144 * </p>
145 *
146 * <p>
147 * If an event guard exception is triggered then all instantiations of this specialization are
148 * removed. If one of theses exceptions is thrown once then no further instantiations of this
149 * specialization are going to be created for this node. A specialization that rewrites on an
150 * exception must ensure that no non-repeatable side-effect is caused until the rewrite is
151 * triggered.
152 * </p>
153 *
154 * <b>Example usage:</b>
155 *
156 * <pre>
157 * &#064;Specialization(rewriteOn = ArithmeticException.class)
158 * int doAddNoOverflow(int a, int b) {
159 * return ExactMath.addExact(a, b);
160 * }
161 *
162 * &#064;Specialization
163 * long doAddWithOverflow(int a, int b) {
164 * return a + b;
165 * }
166 * ...
167 *
168 * Example executions:
169 * execute(Integer.MAX_VALUE - 1, 1) => doAddNoOverflow(Integer.MAX_VALUE - 1, 1)
170 * execute(Integer.MAX_VALUE, 1) => doAddNoOverflow(Integer.MAX_VALUE, 1)
171 * => throws ArithmeticException
172 * => doAddWithOverflow(Integer.MAX_VALUE, 1)
173 * execute(Integer.MAX_VALUE - 1, 1) => doAddWithOverflow(Integer.MAX_VALUE - 1, 1)
174 * </pre>
175 *
176 * </p>
177 *
178 * @see ExactMath#addExact(int, int)
179 */
54 Class<? extends Throwable>[] rewriteOn() default {}; 180 Class<? extends Throwable>[] rewriteOn() default {};
55 181
56 /** 182 /**
57 * The contains attribute declares all specializations that are contained by this 183 * <p>
58 * specialization. A containing specialization must be strictly generic as the contained 184 * Declares other specializations of the same node to be contained by this specialization. Other
59 * specialization. 185 * specializations are references using their unique method name. If this specialization is
186 * instantiated then all contained specialization instances are removed and never instantiated
187 * again for this node instance. Therefore this specialization should handle strictly more
188 * inputs than which were handled by the contained specialization, otherwise the removal of the
189 * contained specialization will lead to unspecialized types of input values. The contains
190 * declaration is transitive for multiple involved specializations.
191 * </p>
192 * <b>Example usage:</b>
193 *
194 * <pre>
195 * &#064;Specialization(guards = "b == 2")
196 * void doDivPowerTwo(int a, int b) {
197 * return a >> 1;
198 * }
199 *
200 * &#064;Specialization(contains ="doDivPowerTwo", guards = "b > 0")
201 * void doDivPositive(int a, int b) {
202 * return a / b;
203 * }
204 * ...
205 *
206 * Example executions with contains="doDivPowerTwo":
207 * execute(4, 2) => doDivPowerTwo(4, 2)
208 * execute(9, 3) => doDivPositive(9, 3) // doDivPowerTwo instances get removed
209 * execute(4, 2) => doDivPositive(4, 2)
210 *
211 * Same executions without contains="doDivPowerTwo"
212 * execute(4, 2) => doDivPowerTwo(4, 2)
213 * execute(9, 3) => doDivPositive(9, 3)
214 * execute(4, 2) => doDivPowerTwo(4, 2)
215 * </pre>
216 *
217 * </p>
218 *
219 * @see #guards()
60 */ 220 */
61 String[] contains() default {}; 221 String[] contains() default {};
62 222
223 /**
224 * <p>
225 * Declares <code>boolean</code> expressions that define whether or not input values are
226 * applicable to this specialization instance. Guard expressions must always return the same
227 * result for each combination of the enclosing node instance and the bound input values.
228 * </p>
229 * <p>
230 * If a guard expression does not bind any dynamic input parameters then the DSL assumes that
231 * the result will not change for this node after specialization instantiation. The DSL asserts
232 * this assumption if assertions are enabled (-ea).
233 * </p>
234 * <p>
235 * Guard expressions are defined using a subset of Java. This subset includes field/parameter
236 * accesses, function calls, type exact infix comparisons (==, !=, <, <=, >, >=), logical
237 * negation (!), logical disjunction (||) and integer literals. The return type of guard
238 * expressions must be <code>boolean</code>. Bound elements without receivers are resolved using
239 * the following order:
240 * <ol>
241 * <li>Dynamic and cached parameters of the enclosing specialization.</li>
242 * <li>Fields defined using {@link NodeField} for the enclosing node.</li>
243 * <li>Non-private, static or virtual methods or fields of enclosing node.</li>
244 * <li>Non-private, static or virtual methods or fields of super types of the enclosing node.</li>
245 * <li>Public and static methods or fields imported using {@link ImportStatic}.</li>
246 * </ol>
247 * </p>
248 * <p>
249 * <b>Example usage:</b>
250 *
251 * <pre>
252 * static boolean acceptOperand(int operand) {
253 * assert operand <= 42;
254 * return operand & 1 == 1;
255 * }
256 *
257 * &#064;Specialization(guards = {"operand <= 42", "acceptOperand(operand)"})
258 * void doSpecialization(int operand) {...}
259 * </pre>
260 *
261 * </p>
262 *
263 * @see Cached
264 * @see ImportStatic
265 */
63 String[] guards() default {}; 266 String[] guards() default {};
64 267
65 /** 268 /**
66 * Defines the assumptions to check for this specialization. When the specialization method is 269 * <p>
67 * invoked it is guaranteed that these assumptions still hold. It is not guaranteed that they 270 * Declares assumption guards that optimistically assume that the state of an {@link Assumption}
68 * are checked before the {@link #guards()} methods. They may be checked before after or in 271 * remains valid. Assumption expressions are cached once per specialization instantiation. If
69 * between {@link #guards()}. To declare assumptions use the {@link NodeAssumptions} annotation 272 * one of the returned assumptions gets invalidated then the specialization instance is removed.
70 * at class level. 273 * An assumption expression may return different assumptions per specialization instance. The
274 * returned assumption instance must not be <code>null</code>.
275 * </p>
276 * <p>
277 * Assumption expressions are defined using a subset of Java. This subset includes
278 * field/parameter accesses, function calls, type exact infix comparisons (==, !=, <, <=, >,
279 * >=), logical negation (!), logical disjunction (||) and integer literals. The return type of
280 * the expression must be {@link Assumption}. Assumption expressions are not allowed to bind to
281 * dynamic parameter values of the specialization. Bound elements without receivers are resolved
282 * using the following order:
283 * <ol>
284 * <li>Cached parameters of the enclosing specialization.</li>
285 * <li>Fields defined using {@link NodeField} for the enclosing node.</li>
286 * <li>Non-private, static or virtual methods or fields of enclosing node.</li>
287 * <li>Non-private, static or virtual methods or fields of super types of the enclosing node.</li>
288 * <li>Public and static methods or fields imported using {@link ImportStatic}.</li>
289 * </ol>
290 * </p>
291 *
292 * <p>
293 * <b>Example usage:</b>
294 *
295 * <pre>
296 * static abstract class DynamicObject() {
297 * abstract Shape getShape();
298 * ...
299 * }
300 * static abstract class Shape() {
301 * abstract Assumption getUnmodifiedAssuption();
302 * ...
303 * }
304 *
305 * &#064;Specialization(guards = "operand.getShape() == cachedShape", assumptions = "cachedShape.getUnmodifiedAssumption()")
306 * void doAssumeUnmodifiedShape(DynamicObject operand, @Cached("operand.getShape()") Shape cachedShape) {...}
307 * </pre>
308 *
309 * </p>
310 *
311 * @see Cached
312 * @see ImportStatic
71 */ 313 */
72 String[] assumptions() default {}; 314 String[] assumptions() default {};
73 315
316 /**
317 * <p>
318 * Declares the expression that limits the number of specialization instantiations. The default
319 * limit for specialization instantiations is defined as <code>"3"</code>. If the limit is
320 * exceeded no more instantiations of the enclosing specialization method are created. Please
321 * note that the existing specialization instantiations are <b>not</b> removed from the
322 * specialization chain. You can use {@link #contains()} to remove unnecessary specializations
323 * instances.
324 * </p>
325 * <p>
326 * The limit expression is defined using a subset of Java. This subset includes field/parameter
327 * accesses, function calls, type exact infix comparisons (==, !=, <, <=, >, >=), logical
328 * negation (!), logical disjunction (||) and integer literals. The return type of the limit
329 * expression must be <code>int</code>. Limit expressions are not allowed to bind to dynamic
330 * parameter values of the specialization. Bound elements without receivers are resolved using
331 * the following order:
332 * <ol>
333 * <li>Cached parameters of the enclosing specialization.</li>
334 * <li>Fields defined using {@link NodeField} for the enclosing node.</li>
335 * <li>Non-private, static or virtual methods or fields of enclosing node.</li>
336 * <li>Non-private, static or virtual methods or fields of super types of the enclosing node.</li>
337 * <li>Public and static methods or fields imported using {@link ImportStatic}.</li>
338 * </ol>
339 * </p>
340 *
341 * <p>
342 * <b>Example usage:</b>
343 *
344 * <pre>
345 * static int getCacheLimit() {
346 * return Integer.parseInt(System.getProperty("language.cacheLimit"));
347 * }
348 *
349 * &#064;Specialization(guards = "operand == cachedOperand", limit = "getCacheLimit()")
350 * void doCached(Object operand, @Cached("operand") Object cachedOperand) {...}
351 * </pre>
352 *
353 * </p>
354 *
355 * @see #guards()
356 * @see #contains()
357 * @see Cached
358 * @see ImportStatic
359 */
360 String limit() default "";
361
74 } 362 }