Skip to content

Commit ae1054d

Browse files
committed
Patch for AST inlining breaks capture semantics: SOM-st#5
1 parent e5fb96d commit ae1054d

File tree

8 files changed

+165
-10
lines changed

8 files changed

+165
-10
lines changed

src/som/compiler/Variable.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import static som.interpreter.SNodeFactory.createArgumentRead;
44
import static som.interpreter.SNodeFactory.createLocalVarRead;
5+
import static som.interpreter.SNodeFactory.createInlinedAsLocalArgumentVarRead;
56
import static som.interpreter.SNodeFactory.createSuperRead;
67
import static som.interpreter.SNodeFactory.createVariableWrite;
78
import static som.interpreter.SNodeFactory.createThisContext;
@@ -101,6 +102,16 @@ public ExpressionNode getReadNode(final int contextLevel,
101102
}
102103
return createLocalVarRead(this, contextLevel, source);
103104
}
105+
106+
public ExpressionNode getReadNodeForInlinedArgument(final int contextLevel,
107+
final SourceSection source) {
108+
transferToInterpreterAndInvalidate("Variable.getReadNode");
109+
isRead = true;
110+
if (contextLevel > 0) {
111+
isReadOutOfContext = true;
112+
}
113+
return createInlinedAsLocalArgumentVarRead(this, contextLevel, source);
114+
}
104115

105116
public FrameSlot getSlot() {
106117
return slot;

src/som/interpreter/InlinerForLexicallyEmbeddedMethods.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,10 @@ public ExpressionNode getReplacementForLocalArgument(final int argumentIndex,
9090
public ExpressionNode getReplacementForNonLocalArgument(final int contextLevel,
9191
final int argumentIndex, final SourceSection source) {
9292
assert contextLevel > 0;
93-
return blockArguments[argumentIndex - 1].getReadNode(contextLevel, source);
93+
return blockArguments[argumentIndex - 1].getReadNodeForInlinedArgument(contextLevel, source);
94+
}
95+
96+
public Local[] getBlockArguments(){
97+
return blockArguments;
9498
}
9599
}

src/som/interpreter/SNodeFactory.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import som.interpreter.nodes.MessageSendNode;
2323
import som.interpreter.nodes.MessageSendNode.AbstractMessageSendNode;
2424
import som.interpreter.nodes.MessageSendNode.CascadeMessageSendNode;
25+
import som.interpreter.nodes.NonLocalVariableNodeFactory.NonLocalArgumentVariableEmbeddedinBlockReadNodeUninitializedNodeGen;
2526
import som.interpreter.nodes.ReturnNonLocalNode;
2627
import som.interpreter.nodes.ReturnNonLocalNode.CatchNonLocalReturnNode;
2728
import som.interpreter.nodes.SequenceNode;
@@ -68,6 +69,12 @@ public static ContextualNode createLocalVarRead(final Local variable,
6869
final int contextLevel, final SourceSection source) {
6970
return new UninitializedVariableReadNode(variable, contextLevel, source);
7071
}
72+
73+
public static ContextualNode createInlinedAsLocalArgumentVarRead(final Local variable,
74+
final int contextLevel, final SourceSection source) {
75+
return NonLocalArgumentVariableEmbeddedinBlockReadNodeUninitializedNodeGen.create(
76+
contextLevel, variable.getSlot(), source);
77+
}
7178

7279
public static ExpressionNode createArgumentRead(final Argument variable,
7380
final int contextLevel, final SourceSection source) {

src/som/interpreter/nodes/ContextualNode.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
public abstract class ContextualNode extends ExpressionWithTagsNode {
3737

3838
protected final int contextLevel;
39-
private final ValueProfile frameType;
39+
protected final ValueProfile frameType;
4040

4141
public ContextualNode(final int contextLevel, final SourceSection source) {
4242
super(source);
@@ -53,18 +53,21 @@ public final boolean accessesOuterContext() {
5353
}
5454

5555
@ExplodeLoop
56-
protected final MaterializedFrame determineContext(final VirtualFrame frame) {
56+
protected SBlock determineSelf(final VirtualFrame frame) {
5757
SBlock self = (SBlock) SArguments.rcvr(frame);
5858
int i = contextLevel - 1;
5959

6060
while (i > 0) {
6161
self = (SBlock) self.getOuterSelf();
6262
i--;
6363
}
64-
64+
return self;
65+
}
66+
67+
protected MaterializedFrame determineContext(final VirtualFrame frame) {
6568
// Graal needs help here to see that this is always a MaterializedFrame
6669
// so, we record explicitly a class profile
67-
return frameType.profile(self.getContext());
70+
return frameType.profile(determineSelf(frame).getContext());
6871
}
6972

7073
@Override

src/som/interpreter/nodes/NonLocalVariableNode.java

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,15 @@
33
import static som.interpreter.TruffleCompiler.transferToInterpreter;
44
import som.interpreter.InlinerAdaptToEmbeddedOuterContext;
55
import som.interpreter.InlinerForLexicallyEmbeddedMethods;
6+
import som.interpreter.nodes.NonLocalVariableNodeFactory.NonLocalArgumentVariableEmbeddedinBlockReadNodeGen;
67
import som.vm.constants.Nil;
78

89
import com.oracle.truffle.api.dsl.NodeChild;
910
import com.oracle.truffle.api.dsl.Specialization;
1011
import com.oracle.truffle.api.frame.FrameSlot;
1112
import com.oracle.truffle.api.frame.FrameSlotKind;
1213
import com.oracle.truffle.api.frame.FrameSlotTypeException;
14+
import com.oracle.truffle.api.frame.MaterializedFrame;
1315
import com.oracle.truffle.api.frame.VirtualFrame;
1416
import com.oracle.truffle.api.object.DynamicObject;
1517
import com.oracle.truffle.api.source.SourceSection;
@@ -95,7 +97,38 @@ protected final boolean isUninitialized(final VirtualFrame frame) {
9597
return slot.getKind() == FrameSlotKind.Illegal;
9698
}
9799
}
98-
100+
101+
public abstract static class NonLocalArgumentVariableEmbeddedinBlockReadNodeUninitialized extends NonLocalArgumentVariableEmbeddedinBlockReadNode {
102+
public NonLocalArgumentVariableEmbeddedinBlockReadNodeUninitialized(final int contextLevel,
103+
final FrameSlot slot, final SourceSection source) {
104+
super(contextLevel, slot, source);
105+
}
106+
107+
/*Needed because there is a mismatch in the slot index the first time the node is executed*/
108+
@Specialization(guards = "1 == 1", insertBefore="doNil")
109+
public final Object doGeneric(final VirtualFrame frame) {
110+
FrameSlot updatedSlot = this.determineContext(frame).getFrameDescriptor().
111+
findOrAddFrameSlot(slot.getIdentifier(), slot.getKind());
112+
return replace(NonLocalArgumentVariableEmbeddedinBlockReadNodeGen.
113+
create(contextLevel, updatedSlot, this.sourceSection)).executeGeneric(frame);
114+
}
115+
116+
}
117+
118+
public abstract static class NonLocalArgumentVariableEmbeddedinBlockReadNode extends NonLocalVariableReadNode {
119+
public NonLocalArgumentVariableEmbeddedinBlockReadNode(final int contextLevel,
120+
final FrameSlot slot, final SourceSection source) {
121+
super(contextLevel, slot, source);
122+
}
123+
124+
@Override
125+
protected final MaterializedFrame determineContext(final VirtualFrame frame) {
126+
// Graal needs help here to see that this is always a MaterializedFrame
127+
// so, we record explicitly a class profile
128+
return frameType.profile(determineSelf(frame).getEmbeddedContext());
129+
}
130+
}
131+
99132
@NodeChild(value = "exp", type = ExpressionNode.class)
100133
public abstract static class NonLocalVariableWriteNode extends NonLocalVariableNode {
101134

src/som/interpreter/nodes/literals/BlockNode.java

Lines changed: 81 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,12 @@
1313
import som.vmobjects.MethodLayoutImpl;
1414
import som.vmobjects.SBlock;
1515
import som.vmobjects.SInvokable;
16+
1617
import com.oracle.truffle.api.CompilerDirectives;
1718
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
19+
import com.oracle.truffle.api.frame.FrameDescriptor;
20+
import com.oracle.truffle.api.frame.FrameSlot;
21+
import com.oracle.truffle.api.frame.FrameSlotTypeException;
1822
import com.oracle.truffle.api.frame.VirtualFrame;
1923
import com.oracle.truffle.api.object.DynamicObject;
2024
import com.oracle.truffle.api.source.SourceSection;
@@ -70,7 +74,7 @@ public void replaceWithLexicallyEmbeddedNode(
7074
final InlinerForLexicallyEmbeddedMethods inliner) {
7175
Invokable adapted = ((Method) InvokableLayoutImpl.INSTANCE.getInvokable(blockMethod)).
7276
cloneAndAdaptToEmbeddedOuterContext(inliner);
73-
replaceAdapted(adapted);
77+
replaceAdaptedForEmbeddedOuter(adapted, inliner.getBlockArguments());
7478
}
7579

7680
@Override
@@ -82,15 +86,28 @@ public void replaceWithCopyAdaptedToEmbeddedOuterContext(
8286
}
8387

8488
private void replaceAdapted(final Invokable adaptedForContext) {
85-
DynamicObject adapted = Universe.newMethod(
89+
DynamicObject adapted = methodForInvokable(adaptedForContext);
90+
replace(createNode(adapted));
91+
}
92+
93+
private DynamicObject methodForInvokable(final Invokable adaptedForContext){
94+
return Universe.newMethod(
8695
MethodLayoutImpl.INSTANCE.getSignature(blockMethod), adaptedForContext, false,
8796
MethodLayoutImpl.INSTANCE.getEmbeddedBlocks(blockMethod));
88-
replace(createNode(adapted));
97+
}
98+
99+
private void replaceAdaptedForEmbeddedOuter(final Invokable adaptedForContext, Local[] blockArguments) {
100+
DynamicObject adapted = methodForInvokable(adaptedForContext);
101+
replace(createNodeForEmbeddedOuter(adapted, blockArguments));
89102
}
90103

91104
protected BlockNode createNode(final DynamicObject adapted) {
92105
return new BlockNode(adapted, getSourceSection());
93106
}
107+
108+
protected BlockNode createNodeForEmbeddedOuter(final DynamicObject adapted, final Local[] blockArguments){
109+
return createNode(adapted);
110+
}
94111

95112
@Override
96113
public ExpressionNode inline(final MethodGenerationContext mgenc,
@@ -100,7 +117,7 @@ public ExpressionNode inline(final MethodGenerationContext mgenc,
100117
return InvokableLayoutImpl.INSTANCE.getInvokable(blockMethod).inline(mgenc, blockArguments);
101118
}
102119

103-
public static final class BlockNodeWithContext extends BlockNode {
120+
public static class BlockNodeWithContext extends BlockNode {
104121

105122
public BlockNodeWithContext(final DynamicObject blockMethod,
106123
final SourceSection source) {
@@ -124,5 +141,65 @@ public SBlock executeSBlock(final VirtualFrame frame) {
124141
protected BlockNode createNode(final DynamicObject adapted) {
125142
return new BlockNodeWithContext(adapted, getSourceSection());
126143
}
144+
145+
@Override
146+
protected BlockNode createNodeForEmbeddedOuter(final DynamicObject adapted, final Local[] blockArguments){
147+
return new BlockNodeWithContextForInlinedScope(adapted, getSourceSection(), blockArguments);
148+
}
127149
}
150+
151+
public static final class BlockNodeWithContextForInlinedScope extends BlockNodeWithContext {
152+
private final Local[] inlinedAsLocalBlockArguments;
153+
154+
public BlockNodeWithContextForInlinedScope(final DynamicObject blockMethod,
155+
final SourceSection source, final Local[] blockArguments) {
156+
super(blockMethod, source);
157+
this.inlinedAsLocalBlockArguments = blockArguments;
158+
}
159+
160+
@Override
161+
public SBlock executeSBlock(final VirtualFrame frame) {
162+
if (blockClass == null) {
163+
CompilerDirectives.transferToInterpreter();
164+
setBlockClass();
165+
}
166+
FrameDescriptor descriptor = new FrameDescriptor();
167+
VirtualFrame blockArgumentsEmbeddedFrame = Universe.getCurrent().getTruffleRuntime().createVirtualFrame(null, descriptor);
168+
try {
169+
for (Local local: inlinedAsLocalBlockArguments){
170+
FrameSlot slot = blockArgumentsEmbeddedFrame.getFrameDescriptor().addFrameSlot(local.getSlotIdentifier(), local.getSlot().getKind());
171+
switch(local.getSlot().getKind()){
172+
case Long:
173+
blockArgumentsEmbeddedFrame.setLong(slot, frame.getLong(local.getSlot()));
174+
break;
175+
case Boolean:
176+
assert false;
177+
break;
178+
case Byte:
179+
assert false;
180+
break;
181+
case Double:
182+
assert false;
183+
break;
184+
case Float:
185+
assert false;
186+
break;
187+
case Int:
188+
assert false;
189+
break;
190+
case Object:
191+
assert false;
192+
break;
193+
default:
194+
assert false;
195+
break;
196+
}
197+
}
198+
} catch (FrameSlotTypeException e) {
199+
// Should never enter here!
200+
}
201+
return Universe.newBlock(blockMethod, blockClass, frame.materialize(), blockArgumentsEmbeddedFrame.materialize());
202+
}
203+
}
204+
128205
}

src/som/vm/Universe.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,11 @@ public static SBlock newBlock(final DynamicObject method,
257257
final DynamicObject blockClass, final MaterializedFrame context) {
258258
return new SBlock(method, blockClass, context);
259259
}
260+
261+
public static SBlock newBlock(final DynamicObject method,
262+
final DynamicObject blockClass, final MaterializedFrame context, final MaterializedFrame embeddedContext) {
263+
return new SBlock(method, blockClass, context, embeddedContext);
264+
}
260265

261266
@TruffleBoundary
262267
public static DynamicObject newMethod(final SSymbol signature,

src/som/vmobjects/SBlock.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,15 @@ public SBlock(final DynamicObject blockMethod, final DynamicObject blockClass,
4444
this.method = blockMethod;
4545
this.context = context;
4646
this.blockClass = blockClass;
47+
this.blockFixedArguments = null;
48+
}
49+
50+
public SBlock(final DynamicObject blockMethod, final DynamicObject blockClass,
51+
final MaterializedFrame context, final MaterializedFrame embeddedContext) {
52+
this.method = blockMethod;
53+
this.context = context;
54+
this.blockClass = blockClass;
55+
this.blockFixedArguments = embeddedContext;
4756
}
4857

4958
public final DynamicObject getMethod() {
@@ -54,6 +63,11 @@ public final MaterializedFrame getContext() {
5463
assert context != null;
5564
return context;
5665
}
66+
67+
public final MaterializedFrame getEmbeddedContext() {
68+
assert blockFixedArguments != null;
69+
return blockFixedArguments;
70+
}
5771

5872
@Override
5973
public DynamicObject getSOMClass() {
@@ -100,4 +114,5 @@ private static String computeSignatureString(final int numberOfArguments) {
100114
private final DynamicObject blockClass;
101115
private final DynamicObject method;
102116
private final MaterializedFrame context;
117+
private final MaterializedFrame blockFixedArguments;
103118
}

0 commit comments

Comments
 (0)