comparison graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/FunctionCallNode.java @ 13803:e076c87ab175

Truffle: refactored inlining interfaces to a more compact CallNode.
author Christian Humer <christian.humer@gmail.com>
date Fri, 24 Jan 2014 15:55:41 +0100
parents graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/CallNode.java@c2ed2ce2cfe0
children 3840d61e0e68
comparison
equal deleted inserted replaced
13750:a03cb658e68e 13803:e076c87ab175
1 /*
2 * Copyright (c) 2012, 2012, 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.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23 package com.oracle.truffle.sl.nodes;
24
25 import com.oracle.truffle.api.*;
26 import com.oracle.truffle.api.frame.*;
27 import com.oracle.truffle.api.impl.*;
28 import com.oracle.truffle.api.nodes.*;
29 import com.oracle.truffle.sl.runtime.*;
30
31 public abstract class FunctionCallNode extends TypedNode {
32
33 private static final int INLINE_CACHE_SIZE = 2;
34
35 @Child protected TypedNode functionNode;
36 @Child protected ArgumentsNode argumentsNode;
37
38 public FunctionCallNode(TypedNode functionNode, ArgumentsNode argumentsNode) {
39 this.functionNode = adoptChild(functionNode);
40 this.argumentsNode = adoptChild(argumentsNode);
41 }
42
43 @Override
44 public final Object executeGeneric(VirtualFrame frame) {
45 CallTarget function;
46 try {
47 function = functionNode.executeCallTarget(frame);
48 } catch (UnexpectedResultException e) {
49 throw new UnsupportedOperationException("Call to " + e.getMessage() + " not supported.");
50 }
51 Object[] arguments = argumentsNode.executeArray(frame);
52 return executeCall(frame, function, new SLArguments(arguments));
53 }
54
55 public abstract Object executeCall(VirtualFrame frame, CallTarget function, SLArguments arguments);
56
57 public static FunctionCallNode create(TypedNode function, TypedNode[] arguments) {
58 return new UninitializedCallNode(function, new ArgumentsNode(arguments), 0);
59 }
60
61 private static final class UninitializedCallNode extends FunctionCallNode {
62
63 protected final int depth;
64
65 UninitializedCallNode(TypedNode function, ArgumentsNode args, int depth) {
66 super(function, args);
67 this.depth = depth;
68 }
69
70 UninitializedCallNode(UninitializedCallNode copy) {
71 super(null, null);
72 this.depth = copy.depth + 1;
73 }
74
75 @Override
76 public Object executeCall(VirtualFrame frame, CallTarget function, SLArguments arguments) {
77 CompilerDirectives.transferToInterpreter();
78 return specialize(function).executeCall(frame, function, arguments);
79 }
80
81 private FunctionCallNode specialize(CallTarget function) {
82 CompilerAsserts.neverPartOfCompilation();
83 if (depth < INLINE_CACHE_SIZE) {
84 return replace(new CachedCallNode(functionNode, argumentsNode, function, new UninitializedCallNode(this)));
85 } else {
86 FunctionCallNode topMost = (FunctionCallNode) NodeUtil.getNthParent(this, depth);
87 return topMost.replace(new GenericCallNode(topMost.functionNode, topMost.argumentsNode));
88 }
89 }
90
91 }
92
93 private static final class CachedCallNode extends FunctionCallNode {
94
95 protected final CallTarget cachedFunction;
96
97 @Child protected CallNode callNode;
98 @Child protected FunctionCallNode nextNode;
99
100 public CachedCallNode(TypedNode function, ArgumentsNode arguments, CallTarget cachedFunction, FunctionCallNode next) {
101 super(function, arguments);
102 this.cachedFunction = cachedFunction;
103 this.callNode = adoptChild(CallNode.create(cachedFunction));
104 this.nextNode = adoptChild(next);
105
106 // inline usually known functions that should always be inlined
107 if (findSLFunctionRoot(cachedFunction).isInlineImmediatly()) {
108 if (callNode.isInlinable() && !callNode.isInlined()) {
109 callNode.inline();
110 }
111 }
112 }
113
114 @Override
115 public Object executeCall(VirtualFrame frame, CallTarget function, SLArguments arguments) {
116 if (this.cachedFunction == function) {
117 return callNode.call(frame.pack(), arguments);
118 }
119 return nextNode.executeCall(frame, function, arguments);
120 }
121
122 private static FunctionRootNode findSLFunctionRoot(CallTarget target) {
123 return (FunctionRootNode) ((DefaultCallTarget) target).getRootNode();
124 }
125
126 }
127
128 private static final class GenericCallNode extends FunctionCallNode {
129
130 GenericCallNode(TypedNode functionNode, ArgumentsNode arguments) {
131 super(functionNode, arguments);
132 }
133
134 @Override
135 public Object executeCall(VirtualFrame frame, CallTarget function, SLArguments arguments) {
136 return function.call(frame.pack(), arguments);
137 }
138 }
139
140 }