Mercurial > hg > graal-jvmci-8
comparison graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/CallNode.java @ 13983:f46cab39a9a2
Truffle: Updated inlining API. Pushed inlining implementation to the Truffle runtime.
author | Christian Humer <christian.humer@gmail.com> |
---|---|
date | Thu, 20 Feb 2014 01:21:49 +0100 |
parents | e86d32f4803f |
children | c5411233cdf8 |
comparison
equal
deleted
inserted
replaced
13977:39076a984c33 | 13983:f46cab39a9a2 |
---|---|
24 */ | 24 */ |
25 package com.oracle.truffle.api.nodes; | 25 package com.oracle.truffle.api.nodes; |
26 | 26 |
27 import com.oracle.truffle.api.*; | 27 import com.oracle.truffle.api.*; |
28 import com.oracle.truffle.api.frame.*; | 28 import com.oracle.truffle.api.frame.*; |
29 import com.oracle.truffle.api.impl.*; | |
30 | 29 |
31 /** | 30 /** |
32 * This node represents a call to a static {@link CallTarget}. This node should be used whenever a | 31 * This node represents a call to a static {@link CallTarget}. This node should be used whenever a |
33 * {@link CallTarget} is considered constant at a certain location in the tree. This enables the | 32 * {@link CallTarget} is considered constant at a certain location in the tree. This enables the |
34 * Truffle runtime to perform inlining or other optimizations for this call-site. | 33 * Truffle runtime to perform inlining or other optimizations for this call-site. This class is |
34 * intended to be implemented by truffle runtime implementors and not by guest languague | |
35 * implementors. | |
35 * | 36 * |
36 * @see #create(CallTarget) to create a CallNode instance. | 37 * @see #create(CallTarget) to create a CallNode instance. |
37 */ | 38 */ |
38 public abstract class CallNode extends Node { | 39 public abstract class CallNode extends Node { |
39 | 40 |
40 protected final CallTarget callTarget; | 41 protected final CallTarget callTarget; |
41 | 42 |
42 private CallNode(CallTarget callTarget) { | 43 protected CallNode(CallTarget callTarget) { |
43 this.callTarget = callTarget; | 44 this.callTarget = callTarget; |
44 } | 45 } |
45 | 46 |
46 /** | 47 /** |
47 * @return the constant {@link CallTarget} that is associated with this {@link CallNode}. | 48 * @return the constant {@link CallTarget} that is associated with this {@link CallNode}. |
57 * @param arguments the arguments that should be passed to the callee | 58 * @param arguments the arguments that should be passed to the callee |
58 * @return the return result of the call | 59 * @return the return result of the call |
59 */ | 60 */ |
60 public abstract Object call(PackedFrame caller, Arguments arguments); | 61 public abstract Object call(PackedFrame caller, Arguments arguments); |
61 | 62 |
62 /** | |
63 * Returns <code>true</code> if the {@link CallTarget} contained in this {@link CallNode} can be | |
64 * inlined. A {@link CallTarget} is considered inlinable if it was created using | |
65 * {@link TruffleRuntime#createCallTarget(RootNode)} and if the enclosed {@link RootNode} | |
66 * returns <code>true</code> for {@link RootNode#isInlinable()}. | |
67 */ | |
68 public abstract boolean isInlinable(); | 63 public abstract boolean isInlinable(); |
69 | 64 |
70 /** | 65 /** |
71 * @return true if this {@link CallNode} was already inlined. | 66 * @return true if this {@link CallNode} was already inlined. |
72 */ | 67 */ |
73 public abstract boolean isInlined(); | 68 public abstract boolean isInlined(); |
74 | 69 |
75 /** | 70 public abstract void inline(); |
76 * Enforces an inlining optimization on this {@link CallNode} instance. If not performed | |
77 * manually the Truffle runtime may perform inlining using an heuristic to optimize the | |
78 * performance of the execution. It is recommended to implement an version of | |
79 * {@link RootNode#inline()} that adapts the inlining for possible guest language specific | |
80 * behavior. If the this {@link CallNode} is not inlinable or is already inlined | |
81 * <code>false</code> is returned. | |
82 * | |
83 * @return <code>true</code> if the inlining operation was successful. | |
84 */ | |
85 public abstract boolean inline(); | |
86 | 71 |
87 /** | 72 public abstract boolean isSplittable(); |
88 * Returns the inlined root node if the call node was inlined. If the {@link CallNode} was not | 73 |
89 * inlined <code>null</code> is returned. | 74 public abstract boolean split(); |
90 * | 75 |
91 * @return the inlined root node returned by {@link RootNode#inline()} | 76 public abstract CallTarget getSplitCallTarget(); |
92 */ | 77 |
93 public RootNode getInlinedRoot() { | 78 public abstract RootNode getInlinedRoot(); |
94 return null; | |
95 } | |
96 | 79 |
97 /** | 80 /** |
98 * Creates a new {@link CallNode} using a {@link CallTarget}. | 81 * Creates a new {@link CallNode} using a {@link CallTarget}. |
99 * | 82 * |
100 * @param target the {@link CallTarget} to call | 83 * @param target the {@link CallTarget} to call |
101 * @return a call node that calls the provided target | 84 * @return a call node that calls the provided target |
85 * @deprecated use {@link TruffleRuntime#createCallNode(CallTarget)} instead | |
102 */ | 86 */ |
87 @Deprecated | |
103 public static CallNode create(CallTarget target) { | 88 public static CallNode create(CallTarget target) { |
104 if (isInlinable(target)) { | 89 return Truffle.getRuntime().createCallNode(target); |
105 return new InlinableCallNode((RootCallTarget) target); | |
106 } else { | |
107 return new DefaultCallNode(target); | |
108 } | |
109 } | 90 } |
110 | 91 |
111 /** | 92 protected final void installParentInlinedCall() { |
112 * Warning: this is internal API and may change without notice. | 93 getInlinedRoot().addParentInlinedCall(this); |
113 */ | |
114 public interface CompilerCallView { | |
115 | |
116 int getCallCount(); | |
117 | |
118 void resetCallCount(); | |
119 | |
120 void store(Object value); | |
121 | |
122 Object load(); | |
123 } | |
124 | |
125 /** | |
126 * Warning: this is internal API and may change without notice. | |
127 */ | |
128 public CompilerCallView getCompilerCallView() { | |
129 return null; | |
130 } | |
131 | |
132 private static boolean isInlinable(CallTarget callTarget) { | |
133 if (callTarget instanceof RootCallTarget) { | |
134 return (((RootCallTarget) callTarget).getRootNode()).isInlinable(); | |
135 } | |
136 return false; | |
137 } | |
138 | |
139 @Override | |
140 public String toString() { | |
141 return getParent() != null ? getParent().toString() : super.toString(); | |
142 } | |
143 | |
144 static final class DefaultCallNode extends CallNode { | |
145 | |
146 public DefaultCallNode(CallTarget target) { | |
147 super(target); | |
148 } | |
149 | |
150 @Override | |
151 public Object call(PackedFrame caller, Arguments arguments) { | |
152 return callTarget.call(caller, arguments); | |
153 } | |
154 | |
155 @Override | |
156 public boolean inline() { | |
157 return false; | |
158 } | |
159 | |
160 @Override | |
161 public boolean isInlinable() { | |
162 return false; | |
163 } | |
164 | |
165 @Override | |
166 public boolean isInlined() { | |
167 return false; | |
168 } | |
169 | |
170 } | |
171 | |
172 static final class InlinableCallNode extends CallNode implements CompilerCallView { | |
173 | |
174 private int callCount; | |
175 | |
176 public InlinableCallNode(RootCallTarget target) { | |
177 super(target); | |
178 } | |
179 | |
180 @Override | |
181 public Object call(PackedFrame parentFrame, Arguments arguments) { | |
182 if (CompilerDirectives.inInterpreter()) { | |
183 callCount++; | |
184 } | |
185 return callTarget.call(parentFrame, arguments); | |
186 } | |
187 | |
188 @Override | |
189 public boolean inline() { | |
190 DefaultCallTarget defaultTarget = (DefaultCallTarget) getCallTarget(); | |
191 RootNode originalRootNode = defaultTarget.getRootNode(); | |
192 if (originalRootNode.isInlinable()) { | |
193 RootNode inlinedRootNode = defaultTarget.getRootNode().inline(); | |
194 inlinedRootNode.setCallTarget(callTarget); | |
195 inlinedRootNode.setParentInlinedCall(this); | |
196 replace(new InlinedCallNode(defaultTarget, inlinedRootNode)); | |
197 return true; | |
198 } | |
199 return false; | |
200 } | |
201 | |
202 @Override | |
203 public boolean isInlined() { | |
204 return false; | |
205 } | |
206 | |
207 @Override | |
208 public boolean isInlinable() { | |
209 return true; | |
210 } | |
211 | |
212 @Override | |
213 public CompilerCallView getCompilerCallView() { | |
214 return this; | |
215 } | |
216 | |
217 /* Truffle internal API. */ | |
218 public int getCallCount() { | |
219 return callCount; | |
220 } | |
221 | |
222 /* Truffle internal API. */ | |
223 public void resetCallCount() { | |
224 callCount = 0; | |
225 } | |
226 | |
227 private Object storedCompilerInfo; | |
228 | |
229 public void store(Object value) { | |
230 this.storedCompilerInfo = value; | |
231 } | |
232 | |
233 public Object load() { | |
234 return storedCompilerInfo; | |
235 } | |
236 | |
237 } | |
238 | |
239 static final class InlinedCallNode extends CallNode { | |
240 | |
241 private final RootNode inlinedRoot; | |
242 | |
243 public InlinedCallNode(DefaultCallTarget callTarget, RootNode inlinedRoot) { | |
244 super(callTarget); | |
245 this.inlinedRoot = inlinedRoot; | |
246 } | |
247 | |
248 @Override | |
249 public Object call(PackedFrame caller, Arguments arguments) { | |
250 return inlinedRoot.execute(Truffle.getRuntime().createVirtualFrame(caller, arguments, inlinedRoot.getFrameDescriptor())); | |
251 } | |
252 | |
253 @Override | |
254 public InlinedCallNode copy() { | |
255 return new InlinedCallNode((DefaultCallTarget) getCallTarget(), NodeUtil.cloneNode(inlinedRoot)); | |
256 } | |
257 | |
258 @Override | |
259 public RootNode getInlinedRoot() { | |
260 return inlinedRoot; | |
261 } | |
262 | |
263 @Override | |
264 public boolean inline() { | |
265 return false; | |
266 } | |
267 | |
268 @Override | |
269 public boolean isInlinable() { | |
270 return true; | |
271 } | |
272 | |
273 @Override | |
274 public boolean isInlined() { | |
275 return true; | |
276 } | |
277 | |
278 } | 94 } |
279 | 95 |
280 } | 96 } |