Mercurial > hg > graal-compiler
comparison graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/CallNode.java @ 13804:3840d61e0e68
Merge.
author | Christian Humer <christian.humer@gmail.com> |
---|---|
date | Tue, 28 Jan 2014 12:52:57 +0100 |
parents | e076c87ab175 |
children | 641f22b1c6b8 |
comparison
equal
deleted
inserted
replaced
13803:e076c87ab175 | 13804:3840d61e0e68 |
---|---|
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.*; | 29 import com.oracle.truffle.api.impl.*; |
30 | 30 |
31 /** | 31 /** |
32 * This node represents a call to a constant {@link CallTarget} in the Truffle AST. This node should | 32 * This node represents a call to a static {@link CallTarget}. This node should be used whenever a |
33 * be used whenever a {@link CallTarget} is considered constant at a certain location. This enables | 33 * {@link CallTarget} is considered constant at a certain location in the tree. This enables the |
34 * the Truffle runtime to perform inlining or other optimizations for this call-site. | 34 * Truffle runtime to perform inlining or other optimizations for this call-site. |
35 * | 35 * |
36 * @see #create(CallTarget) to create a CallNode instance. | 36 * @see #create(CallTarget) to create a CallNode instance. |
37 */ | 37 */ |
38 public abstract class CallNode extends Node { | 38 public abstract class CallNode extends Node { |
39 | 39 |
42 private CallNode(CallTarget callTarget) { | 42 private CallNode(CallTarget callTarget) { |
43 this.callTarget = callTarget; | 43 this.callTarget = callTarget; |
44 } | 44 } |
45 | 45 |
46 /** | 46 /** |
47 * Returns the constant {@link CallTarget} that is associated with this {@link CallNode}. | 47 * @return the constant {@link CallTarget} that is associated with this {@link CallNode}. |
48 */ | 48 */ |
49 public CallTarget getCallTarget() { | 49 public CallTarget getCallTarget() { |
50 return callTarget; | 50 return callTarget; |
51 } | 51 } |
52 | 52 |
58 * @return the return result of the call | 58 * @return the return result of the call |
59 */ | 59 */ |
60 public abstract Object call(PackedFrame caller, Arguments arguments); | 60 public abstract Object call(PackedFrame caller, Arguments arguments); |
61 | 61 |
62 /** | 62 /** |
63 * Returns <code>true</code> if this {@link CallNode} can be inlined. A {@link CallTarget} is | 63 * Returns <code>true</code> if the {@link CallTarget} contained in this {@link CallNode} can be |
64 * considered inlinable if it was created using | 64 * inlined. A {@link CallTarget} is considered inlinable if it was created using |
65 * {@link TruffleRuntime#createCallTarget(RootNode)} and if the enclosed {@link RootNode} | 65 * {@link TruffleRuntime#createCallTarget(RootNode)} and if the enclosed {@link RootNode} |
66 * returns <code>true</code> for {@link RootNode#isInlinable()}. | 66 * returns <code>true</code> for {@link RootNode#isInlinable()}. |
67 */ | 67 */ |
68 public boolean isInlinable() { | 68 public abstract boolean isInlinable(); |
69 return false; | 69 |
70 } | 70 /** |
71 | 71 * @return true if this {@link CallNode} was already inlined. |
72 /** | 72 */ |
73 * Returns true if this {@link CallNode} was already inlined. | 73 public abstract boolean isInlined(); |
74 */ | |
75 public boolean isInlined() { | |
76 return false; | |
77 } | |
78 | 74 |
79 /** | 75 /** |
80 * Enforces an inlining optimization on this {@link CallNode} instance. If not performed | 76 * Enforces an inlining optimization on this {@link CallNode} instance. If not performed |
81 * manually the Truffle runtime may perform inlining using an heuristic to optimize the | 77 * manually the Truffle runtime may perform inlining using an heuristic to optimize the |
82 * performance of the execution. It is recommended to implement an optimized version of | 78 * performance of the execution. It is recommended to implement an version of |
83 * {@link RootNode#inline()}. | 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. | |
84 * | 82 * |
85 * @return true if the inlining operation was successful. | 83 * @return <code>true</code> if the inlining operation was successful. |
86 * @throws IllegalStateException if {@link #isInlinable()} is false. | 84 */ |
87 */ | 85 public abstract boolean inline(); |
88 public boolean inline() { | 86 |
89 CompilerDirectives.transferToInterpreter(); | 87 /** |
90 if (!isInlinable()) { | 88 * Creates a new {@link CallNode} using a {@link CallTarget}. |
91 throw new IllegalStateException("Invoked inline on a non inlinable CallNode."); | |
92 } | |
93 assert !isInlined(); | |
94 return false; | |
95 } | |
96 | |
97 /** | |
98 * Creates a new {@link CallNode} using a constant {@link CallTarget}. | |
99 * | 89 * |
100 * @param target the {@link CallTarget} the {@link CallNode} should call | 90 * @param target the {@link CallTarget} to call |
101 * @return a call node that calls the provided target | 91 * @return a call node that calls the provided target |
102 */ | 92 */ |
103 public static CallNode create(CallTarget target) { | 93 public static CallNode create(CallTarget target) { |
104 if (isInlinable(target)) { | 94 if (isInlinable(target)) { |
105 return new InlinableCallNode(target); | 95 return new InlinableCallNode(target); |
110 | 100 |
111 /** | 101 /** |
112 * Warning: this is internal API and may change without notice. | 102 * Warning: this is internal API and may change without notice. |
113 */ | 103 */ |
114 public static int internalGetCallCount(CallNode callNode) { | 104 public static int internalGetCallCount(CallNode callNode) { |
115 if (callNode.isInlinable()) { | 105 if (callNode.isInlinable() && !callNode.isInlined()) { |
116 return ((InlinableCallNode) callNode).getCallCount(); | 106 return ((InlinableCallNode) callNode).getCallCount(); |
117 } | 107 } |
118 throw new UnsupportedOperationException(); | 108 throw new UnsupportedOperationException(); |
119 } | 109 } |
120 | 110 |
121 /** | 111 /** |
122 * Warning: this is internal API and may change without notice. | 112 * Warning: this is internal API and may change without notice. |
123 */ | 113 */ |
124 public static void internalResetCallCount(CallNode callNode) { | 114 public static void internalResetCallCount(CallNode callNode) { |
125 if (callNode.isInlinable()) { | 115 if (callNode.isInlinable() && !callNode.isInlined()) { |
126 ((InlinableCallNode) callNode).resetCallCount(); | 116 ((InlinableCallNode) callNode).resetCallCount(); |
127 return; | 117 return; |
128 } | 118 } |
129 throw new UnsupportedOperationException(); | 119 throw new UnsupportedOperationException(); |
130 } | 120 } |
143 } | 133 } |
144 | 134 |
145 @Override | 135 @Override |
146 public Object call(PackedFrame caller, Arguments arguments) { | 136 public Object call(PackedFrame caller, Arguments arguments) { |
147 return callTarget.call(caller, arguments); | 137 return callTarget.call(caller, arguments); |
138 } | |
139 | |
140 @Override | |
141 public boolean inline() { | |
142 return false; | |
143 } | |
144 | |
145 @Override | |
146 public boolean isInlinable() { | |
147 return false; | |
148 } | |
149 | |
150 @Override | |
151 public boolean isInlined() { | |
152 return false; | |
148 } | 153 } |
149 | 154 |
150 } | 155 } |
151 | 156 |
152 static final class InlinableCallNode extends CallNode { | 157 static final class InlinableCallNode extends CallNode { |
165 return callTarget.call(parentFrame, arguments); | 170 return callTarget.call(parentFrame, arguments); |
166 } | 171 } |
167 | 172 |
168 @Override | 173 @Override |
169 public boolean inline() { | 174 public boolean inline() { |
170 super.inline(); | |
171 DefaultCallTarget defaultTarget = (DefaultCallTarget) getCallTarget(); | 175 DefaultCallTarget defaultTarget = (DefaultCallTarget) getCallTarget(); |
172 RootNode originalRootNode = defaultTarget.getRootNode(); | 176 RootNode originalRootNode = defaultTarget.getRootNode(); |
173 boolean inlined = false; | 177 boolean inlined = false; |
174 if (originalRootNode.isInlinable()) { | 178 if (originalRootNode.isInlinable()) { |
175 RootNode inlinedRootNode = defaultTarget.getRootNode().inline(); | 179 RootNode inlinedRootNode = defaultTarget.getRootNode().inline(); |
178 } | 182 } |
179 return inlined; | 183 return inlined; |
180 } | 184 } |
181 | 185 |
182 @Override | 186 @Override |
187 public boolean isInlined() { | |
188 return false; | |
189 } | |
190 | |
191 @Override | |
183 public boolean isInlinable() { | 192 public boolean isInlinable() { |
184 return true; | 193 return true; |
185 } | 194 } |
186 | 195 |
187 /* Truffle internal API. */ | 196 /* Truffle internal API. */ |
214 public InlinedCallNode copy() { | 223 public InlinedCallNode copy() { |
215 return new InlinedCallNode((DefaultCallTarget) getCallTarget(), NodeUtil.cloneNode(inlinedRoot)); | 224 return new InlinedCallNode((DefaultCallTarget) getCallTarget(), NodeUtil.cloneNode(inlinedRoot)); |
216 } | 225 } |
217 | 226 |
218 @Override | 227 @Override |
228 public boolean inline() { | |
229 return false; | |
230 } | |
231 | |
232 @Override | |
219 public boolean isInlinable() { | 233 public boolean isInlinable() { |
220 return false; | 234 return true; |
221 } | 235 } |
222 | 236 |
223 @Override | 237 @Override |
224 public boolean isInlined() { | 238 public boolean isInlined() { |
225 return true; | 239 return true; |