Skip to content

Commit 1edba86

Browse files
committed
First support for inlining
Signed-off-by: Stefan Marr <git@stefan-marr.de>
1 parent 851549a commit 1edba86

File tree

3 files changed

+165
-22
lines changed

3 files changed

+165
-22
lines changed

src/som/compiler/MethodGenerationContext.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,8 @@ public Method assemble(final Universe universe, final ExpressionNode expressions
115115

116116
som.interpreter.nodes.Method truffleMethod =
117117
new som.interpreter.nodes.Method(expressions,
118-
selfSlot, argSlots, localSlots, nonLocalReturnMarker, universe);
118+
selfSlot, argSlots, localSlots, nonLocalReturnMarker, universe,
119+
frameDescriptor);
119120

120121
assignSourceSectionToMethod(expressions, truffleMethod);
121122

src/som/interpreter/nodes/MessageNode.java

Lines changed: 147 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -21,22 +21,26 @@
2121
*/
2222
package som.interpreter.nodes;
2323

24-
import com.oracle.truffle.api.CompilerDirectives;
25-
import com.oracle.truffle.api.frame.VirtualFrame;
26-
import com.oracle.truffle.api.nodes.NodeInfo;
27-
import com.oracle.truffle.api.nodes.NodeInfo.Kind;
28-
2924
import som.interpreter.nodes.VariableNode.SuperReadNode;
3025
import som.vm.Universe;
3126
import som.vmobjects.Class;
3227
import som.vmobjects.Invokable;
3328
import som.vmobjects.Object;
3429
import som.vmobjects.Symbol;
3530

31+
import com.oracle.truffle.api.CallTarget;
32+
import com.oracle.truffle.api.CompilerDirectives;
33+
import com.oracle.truffle.api.frame.VirtualFrame;
34+
import com.oracle.truffle.api.nodes.FrameFactory;
35+
import com.oracle.truffle.api.nodes.InlinableCallSite;
36+
import com.oracle.truffle.api.nodes.InlinedCallSite;
37+
import com.oracle.truffle.api.nodes.Node;
38+
39+
// TODO: I need to add a check that the invokable has not changed
40+
3641
// @NodeChildren({
3742
// @NodeChild(value = "receiver", type = ExpressionNode.class),
3843
// @NodeChild(value = "arguments", type = ExpressionNode[].class)})
39-
@NodeInfo(kind = Kind.UNINITIALIZED)
4044
public class MessageNode extends ExpressionNode {
4145

4246
@Child protected final ExpressionNode receiver;
@@ -116,8 +120,10 @@ public Object executeGeneric(VirtualFrame frame) {
116120
CompilerDirectives.transferToInterpreter();
117121

118122
// First let's rewrite this node
119-
MonomorpicMessageNode mono = new MonomorpicMessageNode(receiver, arguments, selector, universe, rcvrClass, invokable);
120-
this.replace(mono, "Let's assume it is a monomorphic send site.");
123+
MonomorpicMessageNode mono = new MonomorpicMessageNode(receiver,
124+
arguments, selector, universe, rcvrClass, invokable);
125+
126+
replace(mono, "Let's assume it is a monomorphic send site.");
121127

122128
// Then execute the invokable, because it can exit this method with
123129
// control flow exceptions (non-local returns), which would leave node
@@ -128,23 +134,29 @@ public Object executeGeneric(VirtualFrame frame) {
128134
}
129135
}
130136

131-
@NodeInfo(kind = Kind.SPECIALIZED)
132-
public static class MonomorpicMessageNode extends MessageNode {
137+
public static class MonomorpicMessageNode extends MessageNode
138+
implements InlinableCallSite {
133139

134140
private final Class rcvrClass;
135141
private final Invokable invokable;
136142

143+
private int callCount;
144+
137145
public MonomorpicMessageNode(final ExpressionNode receiver,
138146
final ExpressionNode[] arguments, final Symbol selector,
139147
final Universe universe, final Class rcvrClass,
140148
final Invokable invokable) {
141149
super(receiver, arguments, selector, universe);
142150
this.rcvrClass = rcvrClass;
143151
this.invokable = invokable;
152+
153+
callCount = 0;
144154
}
145155

146156
@Override
147157
public Object executeGeneric(VirtualFrame frame) {
158+
callCount++;
159+
148160
// evaluate all the expressions: first determine receiver
149161
Object rcvr = receiver.executeGeneric(frame);
150162

@@ -160,13 +172,134 @@ public Object executeGeneric(VirtualFrame frame) {
160172
// So, it might just be a polymorphic send site.
161173
PolymorpicMessageNode poly = new PolymorpicMessageNode(receiver,
162174
arguments, selector, universe, rcvrClass, invokable, currentRcvrClass);
163-
this.replace(poly, "It is not a monomorpic send.");
175+
176+
replace(poly, "It is not a monomorpic send.");
164177
return doFullSend(frame, rcvr, args, currentRcvrClass);
165178
}
166179
}
180+
181+
@Override
182+
public int getCallCount() {
183+
return callCount;
184+
}
185+
186+
@Override
187+
public void resetCallCount() {
188+
callCount = 0;
189+
}
190+
191+
@Override
192+
public CallTarget getCallTarget() {
193+
return invokable.getCallTarget();
194+
}
195+
196+
@Override
197+
public Node getInlineTree() {
198+
if (invokable.isPrimitive()) {
199+
return this;
200+
} else {
201+
return invokable.getTruffleInvokable();
202+
}
203+
}
204+
205+
private InlinedMonomorphicMessageNode newInlinedNode(
206+
final FrameFactory frameFactory,
207+
final Method method) {
208+
return new InlinedMonomorphicMessageNode(receiver, arguments, selector,
209+
universe, rcvrClass, invokable, method.methodCloneForInlining(),
210+
frameFactory, method);
211+
}
212+
213+
@Override
214+
public boolean inline(FrameFactory factory) {
215+
Method method = invokable.getTruffleInvokable();
216+
if (method == null) {
217+
return false;
218+
}
219+
220+
InlinedMonomorphicMessageNode inlinedNode = newInlinedNode(factory,
221+
method);
222+
223+
replace(inlinedNode, "Node got inlined");
224+
225+
return true;
226+
}
227+
}
228+
229+
public static class InlinedMonomorphicMessageNode extends MessageNode
230+
implements InlinedCallSite {
231+
232+
private final Class rcvrClass;
233+
private final Invokable invokable;
234+
235+
@Child private final ExpressionNode methodBody;
236+
237+
private final FrameFactory frameFactory;
238+
private final Method inlinedMethod;
239+
240+
public InlinedMonomorphicMessageNode(final ExpressionNode receiver,
241+
final ExpressionNode[] arguments, final Symbol selector,
242+
final Universe universe, final Class rcvrClass,
243+
final Invokable invokable, final ExpressionNode methodBody,
244+
final FrameFactory frameFactory,
245+
final Method inlinedMethod) {
246+
super(receiver, arguments, selector, universe);
247+
this.rcvrClass = rcvrClass;
248+
this.invokable = invokable;
249+
250+
this.methodBody = adoptChild(methodBody);
251+
252+
this.frameFactory = frameFactory;
253+
this.inlinedMethod = inlinedMethod;
254+
}
255+
256+
@Override
257+
public Object executeGeneric(VirtualFrame frame) {
258+
// evaluate all the expressions: first determine receiver
259+
Object rcvr = receiver.executeGeneric(frame);
260+
261+
// then determine the arguments
262+
Object[] args = determineArguments(frame);
263+
264+
Class currentRcvrClass = classOfReceiver(rcvr, receiver);
265+
266+
if (currentRcvrClass == rcvrClass) {
267+
return executeInlined(frame, rcvr, args);
268+
} else {
269+
return generalizeNode(frame, rcvr, args, currentRcvrClass);
270+
}
271+
}
272+
273+
private Object executeInlined(final VirtualFrame caller, final Object rcvr,
274+
final Object[] args) {
275+
// CompilerDirectives.transferToInterpreter();
276+
final VirtualFrame frame = frameFactory.create(
277+
inlinedMethod.getFrameDescriptor(), caller.pack(),
278+
new Arguments(rcvr, args));
279+
280+
final FrameOnStackMarker marker = Method.initializeFrame(inlinedMethod,
281+
frame.materialize());
282+
283+
return Method.messageSendExecution(marker, frame, methodBody);
284+
}
285+
286+
private Object generalizeNode(final VirtualFrame frame, final Object rcvr,
287+
final Object[] args, final Class currentRcvrClass) {
288+
CompilerDirectives.transferToInterpreter();
289+
// So, it might just be a polymorphic send site.
290+
PolymorpicMessageNode poly = new PolymorpicMessageNode(receiver,
291+
arguments, selector, universe, rcvrClass, invokable, currentRcvrClass);
292+
293+
replace(poly, "It is not a monomorpic send.");
294+
return doFullSend(frame, rcvr, args, currentRcvrClass);
295+
}
296+
297+
@Override
298+
public CallTarget getCallTarget() {
299+
return invokable.getCallTarget();
300+
}
167301
}
168302

169-
@NodeInfo(kind = Kind.SPECIALIZED)
170303
public static class PolymorpicMessageNode extends MessageNode {
171304
private static final int CACHE_SIZE = 8;
172305

@@ -216,13 +349,13 @@ public Object executeGeneric(VirtualFrame frame) {
216349
CompilerDirectives.transferToInterpreter();
217350
// So, it might just be a megamorphic send site.
218351
MegamorphicMessageNode mega = new MegamorphicMessageNode(receiver, arguments, selector, universe);
219-
this.replace(mega, "It is not a polymorpic send.");
352+
353+
replace(mega, "It is not a polymorpic send.");
220354
return doFullSend(frame, rcvr, args, currentRcvrClass);
221355
}
222356
}
223357
}
224358

225-
@NodeInfo(kind = Kind.GENERIC)
226359
public static class MegamorphicMessageNode extends MessageNode {
227360

228361
public MegamorphicMessageNode(final ExpressionNode receiver,

src/som/interpreter/nodes/Method.java

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
2727
import com.oracle.truffle.api.SourceSection;
28+
import com.oracle.truffle.api.frame.FrameDescriptor;
2829
import com.oracle.truffle.api.frame.FrameSlot;
2930
import com.oracle.truffle.api.frame.FrameSlotTypeException;
3031
import com.oracle.truffle.api.frame.MaterializedFrame;
@@ -43,22 +44,22 @@ public class Method extends RootNode {
4344
private final FrameSlot nonLocalReturnMarker;
4445
private final Universe universe;
4546

46-
//private final FrameDescriptor frameDescriptor;
47+
private final FrameDescriptor frameDescriptor;
4748

4849
public Method(final ExpressionNode expressions,
4950
final FrameSlot selfSlot,
5051
final FrameSlot[] argumentSlots,
5152
final FrameSlot[] temporarySlots,
5253
final FrameSlot nonLocalReturnMarker,
53-
final Universe universe) {
54-
//, final FrameDescriptor frameDescriptor) {
54+
final Universe universe,
55+
final FrameDescriptor frameDescriptor) {
5556
this.expressionOrSequence = adoptChild(expressions);
5657
this.selfSlot = selfSlot;
5758
this.argumentSlots = argumentSlots;
5859
this.temporarySlots = temporarySlots;
5960
this.nonLocalReturnMarker = nonLocalReturnMarker;
6061
this.universe = universe;
61-
//this.frameDescriptor = frameDescriptor;
62+
this.frameDescriptor = frameDescriptor;
6263
}
6364

6465
@Override
@@ -67,10 +68,10 @@ public Object execute(VirtualFrame frame) {
6768
return messageSendExecution(marker, frame, expressionOrSequence);
6869
}
6970

70-
private static Object messageSendExecution(final FrameOnStackMarker marker,
71+
public static som.vmobjects.Object messageSendExecution(final FrameOnStackMarker marker,
7172
final VirtualFrame frame,
7273
final ExpressionNode expr) {
73-
Object result;
74+
som.vmobjects.Object result;
7475
boolean restart;
7576

7677
do {
@@ -95,7 +96,7 @@ private static Object messageSendExecution(final FrameOnStackMarker marker,
9596
}
9697

9798
@ExplodeLoop
98-
private static FrameOnStackMarker initializeFrame(final Method method,
99+
public static FrameOnStackMarker initializeFrame(final Method method,
99100
final MaterializedFrame frame) {
100101
try {
101102
frame.setObject(method.selfSlot, frame.getArguments(Arguments.class).self);
@@ -125,4 +126,12 @@ public String toString() {
125126
final String location = getSourceSection().toString();
126127
return "Method " + name + ":" + location + "@" + Integer.toHexString(hashCode());
127128
}
129+
130+
public FrameDescriptor getFrameDescriptor() {
131+
return frameDescriptor;
132+
}
133+
134+
public ExpressionNode methodCloneForInlining() {
135+
return expressionOrSequence.cloneForInlining();
136+
}
128137
}

0 commit comments

Comments
 (0)