Mercurial > hg > graal-compiler
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 * @Specialization | |
89 * void doCached(int operand, @Local("operand") 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 * @Specialization(guards = "==(operand, cachedOperand)") | |
115 * void doCached(int operand, @Cached("operand") 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="doCached"</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 * @Specialization(guards = "==(operand, cachedOperand)") | |
143 * void doCached(int operand, @Cached("operand") int cachedOperand) { | |
144 * CompilerAsserts.compilationConstant(cachedOperand); | |
145 * ... | |
146 * } | |
147 * | |
148 * @Specialization(contains = "doCached") | |
149 * void doNormal(int operand) {...} | |
150 * | |
151 * Example executions with contains = "doCached": | |
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 = "doCached": | |
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 * @Specialization | |
176 * void s(int operand, @Cached("transformLocal(operand)") 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 * @Specialization | |
191 * void s(Object operand, @Cached("new()") 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 * @Specialization | |
212 * void s(int operand, @Local("create()") 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 } |