Skip to content

Commit e1a47e4

Browse files
committed
Propagate loop count throughout the lexical context
This should make sure that the method containing a loop gets compiled properly, and not just a block that contains a loop. Signed-off-by: Stefan Marr <git@stefan-marr.de>
1 parent 0105ead commit e1a47e4

File tree

8 files changed

+71
-22
lines changed

8 files changed

+71
-22
lines changed

src/som/compiler/MethodGenerationContext.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,13 +190,22 @@ public SMethod assemble(final Universe universe, ExpressionNode methodBody) {
190190
new som.interpreter.Method(getSourceSectionForMethod(sourceSection),
191191
frameDescriptor, methodBody, universe, getLexicalContext());
192192

193+
setOuterMethodInLexicalScopes(truffleMethod);
194+
193195
SMethod meth = (SMethod) universe.newMethod(signature, truffleMethod, false,
194196
embeddedBlockMethods.toArray(new SMethod[0]));
195197

196198
// return the method - the holder field is to be set later on!
197199
return meth;
198200
}
199201

202+
private void setOuterMethodInLexicalScopes(final som.interpreter.Method method) {
203+
for (SMethod m : embeddedBlockMethods) {
204+
som.interpreter.Method blockMethod = (som.interpreter.Method) m.getInvokable();
205+
blockMethod.setOuterContextMethod(method);
206+
}
207+
}
208+
200209
private SourceSection getSourceSectionForMethod(final SourceSection ssBody) {
201210
SourceSection ssMethod = ssBody.getSource().createSection(
202211
holderGenc.getName().getString() + ">>" + signature.toString(),

src/som/interpreter/Invokable.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,8 @@ public final boolean isSplittable() {
4343
public final RootCallTarget createCallTarget() {
4444
return Truffle.getRuntime().createCallTarget(this);
4545
}
46+
47+
public abstract void propagateLoopCountThroughoutLexicalScope(final long count);
48+
49+
public abstract boolean isBlock();
4650
}

src/som/interpreter/LexicalContext.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
11
package som.interpreter;
22

3+
import com.oracle.truffle.api.CompilerAsserts;
4+
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
35
import com.oracle.truffle.api.frame.FrameDescriptor;
46

57

68
public final class LexicalContext {
79
private final FrameDescriptor frameDescriptor;
810
private final LexicalContext lexicalContext;
11+
@CompilationFinal private Method outerMethod;
912

10-
public LexicalContext(final FrameDescriptor frameDescriptor, final LexicalContext outerContext) {
13+
public LexicalContext(final FrameDescriptor frameDescriptor,
14+
final LexicalContext outerContext) {
1115
this.frameDescriptor = frameDescriptor;
1216
this.lexicalContext = outerContext;
1317
}
@@ -19,4 +23,14 @@ public FrameDescriptor getFrameDescriptor() {
1923
public LexicalContext getOuterContext() {
2024
return lexicalContext;
2125
}
26+
27+
public Method getOuterMethod() {
28+
return outerMethod;
29+
}
30+
31+
public void setOuterMethod(final Method method) {
32+
CompilerAsserts.neverPartOfCompilation();
33+
assert outerMethod == null; // should not have been set before
34+
outerMethod = method;
35+
}
2236
}

src/som/interpreter/Method.java

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,29 @@ public Invokable cloneWithNewLexicalContext(final LexicalContext outerContext) {
5959
outerContext);
6060
ExpressionNode inlinedBody = Inliner.doInline(getUninitializedBody(),
6161
inlinedContext);
62-
return new Method(getSourceSection(), inlinedFrameDescriptor, inlinedBody,
62+
Method clone = new Method(getSourceSection(), inlinedFrameDescriptor, inlinedBody,
6363
universe, outerContext);
64+
inlinedContext.setOuterMethod(clone);
65+
return clone;
66+
}
67+
68+
@Override
69+
public boolean isBlock() {
70+
return outerContext != null;
71+
}
72+
73+
public void setOuterContextMethod(final Method method) {
74+
outerContext.setOuterMethod(method);
75+
}
76+
77+
@Override
78+
public void propagateLoopCountThroughoutLexicalScope(final long count) {
79+
assert count >= 0;
80+
81+
if (outerContext != null) {
82+
outerContext.getOuterMethod().propagateLoopCountThroughoutLexicalScope(count);
83+
}
84+
reportLoopCount((count > Integer.MAX_VALUE) ? Integer.MAX_VALUE : (int) count);
6485
}
6586

6687
@Override

src/som/interpreter/Primitive.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,19 @@ public RootNode split() {
2828
return cloneWithNewLexicalContext(null);
2929
}
3030

31+
@Override
32+
public boolean isBlock() {
33+
return false;
34+
}
35+
3136
@Override
3237
public String toString() {
3338
return "Primitive " + expressionOrSequence.getClass().getSimpleName() + "@" + Integer.toHexString(hashCode());
3439
}
40+
41+
@Override
42+
public void propagateLoopCountThroughoutLexicalScope(final long count) {
43+
throw new UnsupportedOperationException(
44+
"This should not happen, primitives don't have lexically nested loops.");
45+
}
3546
}

src/som/interpreter/nodes/specialized/IntToByDoMessageNode.java

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package som.interpreter.nodes.specialized;
22

3+
import som.interpreter.Invokable;
34
import som.interpreter.nodes.ExpressionNode;
45
import som.interpreter.nodes.PreevaluatedExpression;
56
import som.interpreter.nodes.nary.QuaternaryExpressionNode;
@@ -8,13 +9,11 @@
89

910
import com.oracle.truffle.api.CompilerAsserts;
1011
import com.oracle.truffle.api.CompilerDirectives;
11-
import com.oracle.truffle.api.LoopCountReceiver;
1212
import com.oracle.truffle.api.Truffle;
1313
import com.oracle.truffle.api.dsl.Specialization;
1414
import com.oracle.truffle.api.frame.VirtualFrame;
1515
import com.oracle.truffle.api.nodes.DirectCallNode;
1616
import com.oracle.truffle.api.nodes.Node;
17-
import com.oracle.truffle.api.nodes.RootNode;
1817

1918

2019
public abstract class IntToByDoMessageNode extends QuaternaryExpressionNode
@@ -74,7 +73,7 @@ public final long doIntToByDo(final VirtualFrame frame, final long receiver, fin
7473
}
7574
} finally {
7675
if (CompilerDirectives.inInterpreter()) {
77-
reportLoopCount((int) limit - receiver);
76+
reportLoopCount((long) limit - receiver);
7877
}
7978
}
8079
return receiver;
@@ -83,14 +82,11 @@ public final long doIntToByDo(final VirtualFrame frame, final long receiver, fin
8382
protected final void reportLoopCount(final long count) {
8483
CompilerAsserts.neverPartOfCompilation();
8584
Node current = getParent();
86-
while (current != null && !(current instanceof RootNode)) {
85+
while (current != null && !(current instanceof Invokable)) {
8786
current = current.getParent();
8887
}
8988
if (current != null) {
90-
RootNode root = (RootNode) current;
91-
if (root.getCallTarget() instanceof LoopCountReceiver) {
92-
((LoopCountReceiver) root.getCallTarget()).reportLoopCount((int) count);
93-
}
89+
((Invokable) current).propagateLoopCountThroughoutLexicalScope(count);
9490
}
9591
}
9692
}

src/som/interpreter/nodes/specialized/IntToDoMessageNode.java

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package som.interpreter.nodes.specialized;
22

3+
import som.interpreter.Invokable;
34
import som.interpreter.nodes.ExpressionNode;
45
import som.interpreter.nodes.PreevaluatedExpression;
56
import som.interpreter.nodes.nary.TernaryExpressionNode;
@@ -9,7 +10,6 @@
910
import com.oracle.truffle.api.CompilerAsserts;
1011
import com.oracle.truffle.api.CompilerDirectives;
1112
import com.oracle.truffle.api.CompilerDirectives.SlowPath;
12-
import com.oracle.truffle.api.LoopCountReceiver;
1313
import com.oracle.truffle.api.Truffle;
1414
import com.oracle.truffle.api.dsl.Specialization;
1515
import com.oracle.truffle.api.frame.VirtualFrame;
@@ -88,10 +88,7 @@ private void reportLoopCount(final long count) {
8888
current = current.getParent();
8989
}
9090
if (current != null) {
91-
RootNode root = (RootNode) current;
92-
if (root.getCallTarget() instanceof LoopCountReceiver) {
93-
((LoopCountReceiver) root.getCallTarget()).reportLoopCount((int) count);
94-
}
91+
((Invokable) current).propagateLoopCountThroughoutLexicalScope(count);
9592
}
9693
}
9794
}

src/som/interpreter/nodes/specialized/WhileWithStaticBlocksNode.java

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package som.interpreter.nodes.specialized;
22

3+
import som.interpreter.Invokable;
34
import som.interpreter.nodes.literals.BlockNode;
45
import som.interpreter.nodes.nary.BinaryExpressionNode;
56
import som.vm.Universe;
@@ -9,7 +10,6 @@
910
import com.oracle.truffle.api.CallTarget;
1011
import com.oracle.truffle.api.CompilerAsserts;
1112
import com.oracle.truffle.api.CompilerDirectives;
12-
import com.oracle.truffle.api.LoopCountReceiver;
1313
import com.oracle.truffle.api.Truffle;
1414
import com.oracle.truffle.api.frame.VirtualFrame;
1515
import com.oracle.truffle.api.nodes.DirectCallNode;
@@ -73,7 +73,7 @@ public final void executeEvaluatedVoid(final VirtualFrame frame,
7373
protected final SObject doWhileConditionally(final VirtualFrame frame,
7474
final SBlock loopCondition,
7575
final SBlock loopBody) {
76-
int iterationCount = 0;
76+
long iterationCount = 0;
7777
boolean loopConditionResult = (boolean) conditionValueSend.call(
7878
frame, new Object[] {loopCondition});
7979

@@ -98,17 +98,14 @@ protected final SObject doWhileConditionally(final VirtualFrame frame,
9898
return universe.nilObject;
9999
}
100100

101-
protected final void reportLoopCount(final int count) {
101+
protected final void reportLoopCount(final long count) {
102102
CompilerAsserts.neverPartOfCompilation();
103103
Node current = getParent();
104104
while (current != null && !(current instanceof RootNode)) {
105105
current = current.getParent();
106106
}
107107
if (current != null) {
108-
RootNode root = (RootNode) current;
109-
if (root.getCallTarget() instanceof LoopCountReceiver) {
110-
((LoopCountReceiver) root.getCallTarget()).reportLoopCount(count);
111-
}
108+
((Invokable) current).propagateLoopCountThroughoutLexicalScope(count);
112109
}
113110
}
114111

0 commit comments

Comments
 (0)