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;