comparison graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/SpecializationNode.java @ 18761:a665483c3881

Truffle-DSL: new node layout implementation.
author Christian Humer <christian.humer@gmail.com>
date Mon, 29 Dec 2014 23:38:54 +0100
parents
children a720bf2e2f43
comparison
equal deleted inserted replaced
18760:6fa3999631d8 18761:a665483c3881
1 /*
2 * Copyright (c) 2014, 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.internal;
26
27 import java.lang.reflect.*;
28 import java.util.concurrent.*;
29
30 import com.oracle.truffle.api.*;
31 import com.oracle.truffle.api.dsl.*;
32 import com.oracle.truffle.api.dsl.internal.RewriteEvent.RewriteEvent0;
33 import com.oracle.truffle.api.dsl.internal.RewriteEvent.RewriteEvent1;
34 import com.oracle.truffle.api.dsl.internal.RewriteEvent.RewriteEvent2;
35 import com.oracle.truffle.api.dsl.internal.RewriteEvent.RewriteEvent3;
36 import com.oracle.truffle.api.dsl.internal.RewriteEvent.RewriteEvent4;
37 import com.oracle.truffle.api.dsl.internal.RewriteEvent.RewriteEventN;
38 import com.oracle.truffle.api.frame.*;
39 import com.oracle.truffle.api.nodes.*;
40 import com.oracle.truffle.api.nodes.NodeUtil.NodeClass;
41 import com.oracle.truffle.api.nodes.NodeUtil.NodeField;
42
43 /**
44 * Internal implementation dependent base class for generated specialized nodes.
45 */
46 @SuppressWarnings("unused")
47 @NodeInfo(cost = NodeCost.NONE)
48 public abstract class SpecializationNode extends Node {
49
50 @Child protected SpecializationNode next;
51
52 private final int index;
53
54 public SpecializationNode() {
55 this(-1);
56 }
57
58 public SpecializationNode(int index) {
59 this.index = index;
60 }
61
62 @Override
63 public final NodeCost getCost() {
64 return NodeCost.NONE;
65 }
66
67 public static Node updateRoot(Node node) {
68 updateRootImpl(((SpecializedNode) node).getSpecializationNode(), node);
69 return node;
70 }
71
72 private static void updateRootImpl(SpecializationNode start, Node node) {
73 NodeField[] fields = NodeClass.get(start.getClass()).getFields();
74 for (int i = fields.length - 1; i >= 0; i--) {
75 NodeField f = fields[i];
76 if (f.getName().equals("root")) {
77 f.putObject(start, node);
78 break;
79 }
80 }
81 if (start.next != null) {
82 updateRootImpl(start.next, node);
83 }
84 }
85
86 protected final SpecializationNode polymorphicMerge(SpecializationNode newNode) {
87 SpecializationNode merged = next.merge(newNode);
88 if (merged == newNode && !isSame(newNode) && count() <= 2) {
89 return removeSame(new RewriteEvent0(findParentNode(), "merged polymorphic to monomorphic"));
90 }
91 return merged;
92 }
93
94 public final NodeCost getNodeCost() {
95 switch (count()) {
96 case 0:
97 case 1:
98 return NodeCost.UNINITIALIZED;
99 case 2:
100 return NodeCost.MONOMORPHIC;
101 default:
102 return NodeCost.POLYMORPHIC;
103 }
104 }
105
106 protected abstract Node[] getSuppliedChildren();
107
108 protected SpecializationNode merge(SpecializationNode newNode) {
109 if (this.isSame(newNode)) {
110 return this;
111 }
112 return next != null ? next.merge(newNode) : newNode;
113 }
114
115 @Override
116 public final boolean equals(Object obj) {
117 if (obj instanceof SpecializationNode) {
118 return ((SpecializationNode) obj).isSame(this);
119 }
120 return super.equals(obj);
121 }
122
123 @Override
124 public final int hashCode() {
125 return index;
126 }
127
128 protected boolean isSame(SpecializationNode other) {
129 return getClass() == other.getClass();
130 }
131
132 private final int count() {
133 return next != null ? next.count() + 1 : 1;
134 }
135
136 protected final SpecializationNode removeSame(final CharSequence reason) {
137 return atomic(new Callable<SpecializationNode>() {
138 public SpecializationNode call() throws Exception {
139 return removeImpl(SpecializationNode.this, reason);
140 }
141 });
142 }
143
144 /** Find the topmost of the specialization chain. */
145 private final SpecializationNode findStart() {
146 SpecializationNode node = this;
147 Node parent = this.getParent();
148 while (parent instanceof SpecializationNode) {
149 SpecializationNode parentCast = ((SpecializationNode) parent);
150 if (parentCast.next != node) {
151 break;
152 }
153 node = parentCast;
154 parent = node.getParent();
155 }
156 return node;
157 }
158
159 private final Node findParentNode() {
160 return findStart().getParent();
161 }
162
163 private SpecializationNode removeImpl(SpecializationNode toRemove, CharSequence reason) {
164 SpecializationNode start = findStart();
165 SpecializationNode current = start;
166 while (current != null) {
167 if (current.isSame(toRemove)) {
168 current.replace(current.next, reason);
169 if (current == start) {
170 start = start.next;
171 }
172 }
173 current = current.next;
174 }
175 return start;
176 }
177
178 public Object acceptAndExecute(VirtualFrame frame) {
179 throw new UnsupportedOperationException();
180 }
181
182 public Object acceptAndExecute(VirtualFrame frame, Object o1) {
183 throw new UnsupportedOperationException();
184 }
185
186 public Object acceptAndExecute(VirtualFrame frame, Object o1, Object o2) {
187 throw new UnsupportedOperationException();
188 }
189
190 public Object acceptAndExecute(VirtualFrame frame, Object o1, Object o2, Object o3) {
191 throw new UnsupportedOperationException();
192 }
193
194 public Object acceptAndExecute(VirtualFrame frame, Object o1, Object o2, Object o3, Object o4) {
195 throw new UnsupportedOperationException();
196 }
197
198 public Object acceptAndExecute(VirtualFrame frame, Object... args) {
199 throw new UnsupportedOperationException();
200 }
201
202 protected SpecializationNode createFallback() {
203 return null;
204 }
205
206 protected SpecializationNode createPolymorphic() {
207 return null;
208 }
209
210 protected SpecializationNode createNext(VirtualFrame frame) {
211 throw new UnsupportedOperationException();
212 }
213
214 protected SpecializationNode createNext(VirtualFrame frame, Object o1) {
215 throw new UnsupportedOperationException();
216 }
217
218 protected SpecializationNode createNext(VirtualFrame frame, Object o1, Object o2) {
219 throw new UnsupportedOperationException();
220 }
221
222 protected SpecializationNode createNext(VirtualFrame frame, Object o1, Object o2, Object o3) {
223 throw new UnsupportedOperationException();
224 }
225
226 protected SpecializationNode createNext(VirtualFrame frame, Object o1, Object o2, Object o3, Object o4) {
227 throw new UnsupportedOperationException();
228 }
229
230 protected SpecializationNode createNext(VirtualFrame frame, Object... args) {
231 throw new UnsupportedOperationException();
232 }
233
234 protected final Object uninitialized(VirtualFrame frame) {
235 CompilerDirectives.transferToInterpreterAndInvalidate();
236 SpecializationNode nextSpecialization = createNext(frame);
237 if (nextSpecialization == null) {
238 nextSpecialization = createFallback();
239 }
240 if (nextSpecialization == null) {
241 return unsupported(frame);
242 }
243 return insertSpecialization(nextSpecialization, new RewriteEvent0(findParentNode(), "inserted new specialization")).acceptAndExecute(frame);
244 }
245
246 protected final Object uninitialized(VirtualFrame frame, Object o1) {
247 CompilerDirectives.transferToInterpreterAndInvalidate();
248 SpecializationNode nextSpecialization = createNext(frame, o1);
249 if (nextSpecialization == null) {
250 nextSpecialization = createFallback();
251 }
252 if (nextSpecialization == null) {
253 return unsupported(frame, o1);
254 }
255 return insertSpecialization(nextSpecialization, new RewriteEvent1(findParentNode(), "inserted new specialization", o1)).acceptAndExecute(frame, o1);
256 }
257
258 protected final Object uninitialized(VirtualFrame frame, Object o1, Object o2) {
259 CompilerDirectives.transferToInterpreterAndInvalidate();
260 SpecializationNode nextSpecialization = createNext(frame, o1, o2);
261 if (nextSpecialization == null) {
262 nextSpecialization = createFallback();
263 }
264 if (nextSpecialization == null) {
265 return unsupported(frame, o1, o2);
266 }
267 return insertSpecialization(nextSpecialization, new RewriteEvent2(findParentNode(), "inserted new specialization", o1, o2)).acceptAndExecute(frame, o1, o2);
268 }
269
270 protected final Object uninitialized(VirtualFrame frame, Object o1, Object o2, Object o3) {
271 CompilerDirectives.transferToInterpreterAndInvalidate();
272 SpecializationNode nextSpecialization = createNext(frame, o1, o2, o3);
273 if (nextSpecialization == null) {
274 nextSpecialization = createFallback();
275 }
276 if (nextSpecialization == null) {
277 return unsupported(frame, o1, o2, o3);
278 }
279 return insertSpecialization(nextSpecialization, new RewriteEvent3(findParentNode(), "inserted new specialization", o1, o2, o3)).acceptAndExecute(frame, o1, o2, o3);
280 }
281
282 protected final Object uninitialized(VirtualFrame frame, Object o1, Object o2, Object o3, Object o4) {
283 CompilerDirectives.transferToInterpreterAndInvalidate();
284 SpecializationNode nextSpecialization = createNext(frame, o1, o2, o3, o4);
285 if (nextSpecialization == null) {
286 nextSpecialization = createFallback();
287 }
288 if (nextSpecialization == null) {
289 return unsupported(frame, o1, o2, o3, o4);
290 }
291 return insertSpecialization(nextSpecialization, new RewriteEvent4(findParentNode(), "inserts new specialization", o1, o2, o3, o4)).acceptAndExecute(frame, o1, o2, o3, o4);
292 }
293
294 protected final Object uninitialized(VirtualFrame frame, Object... args) {
295 CompilerDirectives.transferToInterpreterAndInvalidate();
296 SpecializationNode nextSpecialization = createNext(frame, args);
297 if (nextSpecialization == null) {
298 nextSpecialization = createFallback();
299 }
300 if (nextSpecialization == null) {
301 unsupported(frame, args);
302 }
303 return insertSpecialization(nextSpecialization, new RewriteEventN(findParentNode(), "inserts new specialization", args)).acceptAndExecute(frame, args);
304 }
305
306 private boolean needsPolymorphic() {
307 return findStart().count() == 2;
308 }
309
310 protected final Object remove(String reason, VirtualFrame frame) {
311 return removeSame(new RewriteEvent0(findParentNode(), reason)).acceptAndExecute(frame);
312 }
313
314 protected final Object remove(String reason, VirtualFrame frame, Object o1) {
315 return removeSame(new RewriteEvent1(findParentNode(), reason, o1)).acceptAndExecute(frame, o1);
316 }
317
318 protected final Object remove(String reason, VirtualFrame frame, Object o1, Object o2) {
319 return removeSame(new RewriteEvent2(findParentNode(), reason, o1, o2)).acceptAndExecute(frame, o1, o2);
320 }
321
322 protected final Object remove(String reason, VirtualFrame frame, Object o1, Object o2, Object o3) {
323 return removeSame(new RewriteEvent3(findParentNode(), reason, o1, o2, o3)).acceptAndExecute(frame, o1, o2, o3);
324 }
325
326 protected final Object remove(String reason, VirtualFrame frame, Object o1, Object o2, Object o3, Object o4) {
327 return removeSame(new RewriteEvent4(findParentNode(), reason, o1, o2, o3, o4)).acceptAndExecute(frame, o1, o2, o3, o4);
328 }
329
330 protected final Object remove(String reason, VirtualFrame frame, Object... args) {
331 return removeSame(new RewriteEventN(findParentNode(), reason, args)).acceptAndExecute(frame, args);
332 }
333
334 protected Object unsupported(VirtualFrame frame) {
335 throw new UnsupportedSpecializationException(findParentNode(), getSuppliedChildren());
336 }
337
338 protected Object unsupported(VirtualFrame frame, Object o1) {
339 throw new UnsupportedSpecializationException(findParentNode(), getSuppliedChildren(), o1);
340 }
341
342 protected Object unsupported(VirtualFrame frame, Object o1, Object o2) {
343 throw new UnsupportedSpecializationException(findParentNode(), getSuppliedChildren(), o1, o2);
344 }
345
346 protected Object unsupported(VirtualFrame frame, Object o1, Object o2, Object o3) {
347 throw new UnsupportedSpecializationException(findParentNode(), getSuppliedChildren(), o1, o2, o3);
348 }
349
350 protected Object unsupported(VirtualFrame frame, Object o1, Object o2, Object o3, Object o4) {
351 throw new UnsupportedSpecializationException(findParentNode(), getSuppliedChildren(), o1, o2, o3, o4);
352 }
353
354 protected Object unsupported(VirtualFrame frame, Object... args) {
355 throw new UnsupportedSpecializationException(findParentNode(), getSuppliedChildren(), args);
356 }
357
358 private SpecializationNode insertSpecialization(final SpecializationNode generated, final CharSequence message) {
359 return atomic(new Callable<SpecializationNode>() {
360 public SpecializationNode call() {
361 return insert(generated, message);
362 }
363 });
364 }
365
366 private final SpecializationNode insert(final SpecializationNode generated, CharSequence message) {
367 SpecializationNode start = findStart();
368 if (start == this) {
369 // fast path for first insert
370 return insertBefore(this, generated, message);
371 } else {
372 return slowSortedInsert(start, generated, message);
373 }
374 }
375
376 private static <T> SpecializationNode slowSortedInsert(SpecializationNode start, final SpecializationNode generated, final CharSequence message) {
377 final SpecializationNode merged = start.merge(generated);
378 if (merged == generated) {
379 // new node
380 if (start.count() == 2) {
381 insertBefore(start, start.createPolymorphic(), "insert polymorphic");
382 }
383 SpecializationNode insertBefore = findInsertBeforeNode(generated.index, start);
384 return insertBefore(insertBefore, generated, message);
385 } else {
386 // existing node
387 merged.replace(merged, new RewriteEvent0(merged.findParentNode(), "merged specialization"));
388 return merged;
389 }
390 }
391
392 private static SpecializationNode findInsertBeforeNode(int generatedIndex, SpecializationNode start) {
393 SpecializationNode current = start;
394 while (current != null && current.index < generatedIndex) {
395 current = current.next;
396 }
397 return current;
398 }
399
400 private static <T> SpecializationNode insertBefore(SpecializationNode node, SpecializationNode insertBefore, CharSequence message) {
401 insertBefore.next = node;
402 return node.replace(insertBefore, message);
403 }
404
405 @Override
406 public final String toString() {
407 Class<?> clazz = getClass();
408 StringBuilder b = new StringBuilder();
409 b.append(clazz.getSimpleName());
410
411 appendFields(b, clazz);
412 if (next != null) {
413 b.append(" -> ").append(next.toString());
414 }
415 return b.toString();
416 }
417
418 private void appendFields(StringBuilder b, Class<?> clazz) {
419 Field[] fields = clazz.getDeclaredFields();
420 if (fields.length == 0) {
421 return;
422 }
423 b.append("(");
424 for (Field field : fields) {
425 if (Modifier.isStatic(field.getModifiers())) {
426 continue;
427 }
428 String name = field.getName();
429 if (name.equals("root")) {
430 continue;
431 }
432 b.append(field.getName());
433 try {
434 field.setAccessible(true);
435 b.append(field.get(this));
436 } catch (IllegalArgumentException e) {
437 b.append(e.toString());
438 } catch (IllegalAccessException e) {
439 b.append(e.toString());
440 }
441 }
442 b.append(")");
443 }
444
445 }