comparison graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/Cached.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
children 67ab244ab689
comparison
equal deleted inserted replaced
19287:19c6359c6191 19288:3a37116ef37f
1 /*
2 * Copyright (c) 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.dsl;
26
27 import java.lang.annotation.*;
28
29 import com.oracle.truffle.api.*;
30 import com.oracle.truffle.api.nodes.*;
31 import com.oracle.truffle.api.utilities.*;
32
33 /**
34 * <p>
35 * A parameter annotated with {@link Cached} in a {@link Specialization} refers to a <b>cached</b>
36 * value of a specialization instance. A cached parameter value is initialized once using the
37 * initializer expression at specialization instantiation. For each call of the specialization
38 * method the cached value is provided by using the annotated parameter from the method body. Cache
39 * initializers are potentially executed before guard expressions declared in
40 * {@link Specialization#guards()}.
41 * </p>
42 * <p>
43 * A typical specialization may define multiple dynamic and multiple cached parameters. Dynamic
44 * parameter values are typically provided by executing child nodes of the operation. Cached
45 * parameters are initialized and stored once per specialization instantiation. Cached parameters
46 * are always constant at compile time. You may verify this by invoking
47 * {@link CompilerAsserts#compilationConstant(Object)} on any cached parameter. For consistency
48 * between specialization declarations cached parameters must be declared last in a specialization
49 * method.
50 * </p>
51 * <p>
52 * The initializer expression of a cached parameter is defined using a subset of Java. This subset
53 * includes field/parameter accesses, function calls, type exact infix comparisons (==, !=, <, <=,
54 * >, >=) and integer literals. The return type of the initializer expression must be assignable to
55 * the parameter type. If the annotated parameter type is derived from {@link Node} then the
56 * {@link Node} instance is allowed to use the {@link Node#replace(Node)} method to replace itself.
57 * Bound elements without receivers are resolved using the following order:
58 * <ol>
59 * <li>Dynamic and cached parameters of the enclosing specialization.</li>
60 * <li>Fields defined using {@link NodeField} for the enclosing node.</li>
61 * <li>Public constructors of the type of the annotated parameter using the <code>new</code> keyword
62 * as method name.</li>
63 * <li>Public and static methods or fields of the type of the annotated parameter.</li>
64 * <li>Non-private, static or virtual methods or fields of enclosing node.</li>
65 * <li>Non-private, static or virtual methods or fields of super types of the enclosing node.</li>
66 * <li>Public and static methods or fields imported using {@link ImportStatic}.</li>
67 * </ol>
68 *
69 * The following examples explain the intended use of the {@link Cached} annotation. All of the
70 * examples have to be enclosed in the following node declaration:
71 * </p>
72 *
73 * <pre>
74 * @NodeChild("operand")
75 * abstract TestNode extends Node {
76 * abstract void execute(Object operandValue);
77 * // ... example here ...
78 * }
79 * </pre>
80 *
81 * <ol>
82 * <li>
83 * This example defines one dynamic and one cached parameter. The operand parameter is representing
84 * the dynamic value of the operand while the cachedOperand is initialized once at first execution
85 * of the specialization (specialization instantiation time).
86 *
87 * <pre>
88 * &#064;Specialization
89 * void doCached(int operand, @Local(&quot;operand&quot;) int cachedOperand) {
90 * CompilerAsserts.compilationConstant(cachedOperand);
91 * ...
92 * }
93 *
94 * Example executions:
95 * execute(1) => doCached(1, 1) // new instantiation, localOperand is bound to 1
96 * execute(0) => doCached(0, 1)
97 * execute(2) => doCached(2, 1)
98 *
99 * </pre>
100 *
101 * </li>
102 * <li>
103 * We extend the previous example by a guard for the cachedOperand value to be equal to the dynamic
104 * operand value. This specifies that the specialization is instantiated for each individual operand
105 * value that is provided. There are a lot of individual <code>int</code> values and for each
106 * individual <code>int</code> value a new specialization would get instantiated. The
107 * {@link Specialization#limit()} property defines a limit for the number of specializations that
108 * can get instantiated. If the specialization instantiation limit is reached then no further
109 * specializations are instantiated. Like for other specializations if there are no more
110 * specializations defined an {@link UnsupportedSpecializationException} is thrown. The default
111 * specialization instantiation limit is <code>3</code>.
112 *
113 * <pre>
114 * &#064;Specialization(guards = &quot;==(operand, cachedOperand)&quot;)
115 * void doCached(int operand, @Cached(&quot;operand&quot;) int cachedOperand) {
116 * CompilerAsserts.compilationConstant(cachedOperand);
117 * ...
118 * }
119 *
120 * Example executions:
121 * execute(0) => doCached(0, 0) // new instantiation, cachedOperand is bound to 0
122 * execute(1) => doCached(1, 1) // new instantiation, cachedOperand is bound to 1
123 * execute(1) => doCached(1, 1)
124 * execute(2) => doCached(2, 2) // new instantiation, cachedOperand is bound to 2
125 * execute(3) => throws UnsupportedSpecializationException // instantiation limit overflows
126 *
127 * </pre>
128 *
129 * </li>
130 * <li>
131 * To handle the limit overflow we extend our example by an additional specialization named
132 * <code>doNormal</code>. This specialization has the same type restrictions but does not have local
133 * state nor the operand identity guard. It is also declared after <code>doCached</code> therefore
134 * it is only instantiated if the limit of the <code>doCached</code> specialization has been
135 * reached. In other words <code>doNormal</code> is more generic than <code>doCached</code> . The
136 * <code>doNormal</code> specialization uses <code>contains=&quot;doCached&quot;</code> to specify
137 * that all instantiations of <code>doCached</code> get removed if <code>doNormal</code> is
138 * instantiated. Alternatively if the <code>contains</code> relation is omitted then all
139 * <code>doCached</code> instances remain but no new instances are created.
140 *
141 * <pre>
142 * &#064;Specialization(guards = &quot;==(operand, cachedOperand)&quot;)
143 * void doCached(int operand, @Cached(&quot;operand&quot;) int cachedOperand) {
144 * CompilerAsserts.compilationConstant(cachedOperand);
145 * ...
146 * }
147 *
148 * &#064;Specialization(contains = &quot;doCached&quot;)
149 * void doNormal(int operand) {...}
150 *
151 * Example executions with contains = &quot;doCached&quot;:
152 * execute(0) => doCached(0, 0) // new instantiation, cachedOperand is bound to 0
153 * execute(1) => doCached(1, 1) // new instantiation, cachedOperand is bound to 1
154 * execute(1) => doCached(1, 1)
155 * execute(2) => doCached(2, 2) // new instantiation, cachedOperand is bound to 2
156 * execute(3) => doNormal(3) // new instantiation of doNormal due to limit overflow; doCached gets removed.
157 * execute(1) => doNormal(1)
158 *
159 * Example executions without contains = &quot;doCached&quot;:
160 * execute(0) => doCached(0, 0) // new instantiation, cachedOperand is bound to 0
161 * execute(1) => doCached(1, 1) // new instantiation, cachedOperand is bound to 1
162 * execute(1) => doCached(1, 1)
163 * execute(2) => doCached(2, 2) // new instantiation, cachedOperand is bound to 2
164 * execute(3) => doNormal(3) // new instantiation of doNormal due to limit overflow
165 * execute(1) => doCached(1, 1)
166 *
167 * </pre>
168 *
169 * </li>
170 * <li>
171 * This next example shows how methods from the enclosing node can be used to initialize cached
172 * parameters. Please note that the visibility of transformLocal must not be <code>private</code>.
173 *
174 * <pre>
175 * &#064;Specialization
176 * void s(int operand, @Cached(&quot;transformLocal(operand)&quot;) int cachedOperand) {
177 * }
178 *
179 * int transformLocal(int operand) {
180 * return operand & 0x42;
181 * }
182 *
183 * </li>
184 * </pre>
185 * <li>
186 * The <code>new</code> keyword can be used to initialize a cached parameter using a constructor of
187 * the parameter type.
188 *
189 * <pre>
190 * &#064;Specialization
191 * void s(Object operand, @Cached(&quot;new()&quot;) OtherNode someNode) {
192 * someNode.execute(operand);
193 * }
194 *
195 * static class OtherNode extends Node {
196 *
197 * public String execute(Object value) {
198 * throw new UnsupportedOperationException();
199 * }
200 * }
201 *
202 * </pre>
203 *
204 * </li>
205 * <li>
206 * Java types without public constructor but with a static factory methods can be initialized by
207 * just referencing its static factory method and its parameters. In this case
208 * {@link BranchProfile#create()} is used to instantiate the {@link BranchProfile} instance.
209 *
210 * <pre>
211 * &#064;Specialization
212 * void s(int operand, @Local(&quot;create()&quot;) BranchProfile profile) {
213 * }
214 * </pre>
215 *
216 * </li>
217 * </ol>
218 *
219 * @see Specialization#guards()
220 * @see Specialization#contains()
221 * @see Specialization#limit()
222 * @see ImportStatic
223 */
224 @Retention(RetentionPolicy.RUNTIME)
225 @Target({ElementType.PARAMETER})
226 public @interface Cached {
227
228 /**
229 * Defines the initializer expression of the cached parameter value.
230 *
231 * @see Cached
232 */
233 String value();
234
235 }