Skip to content

Commit 4005487

Browse files
authored
Add Square supernodes (#220)
2 parents f9513bd + 87ef25c commit 4005487

10 files changed

+499
-6
lines changed

src/trufflesom/src/trufflesom/compiler/MethodGenerationContext.java

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,6 @@
2828
import static trufflesom.vm.SymbolTable.strBlockSelf;
2929
import static trufflesom.vm.SymbolTable.strFrameOnStack;
3030
import static trufflesom.vm.SymbolTable.strSelf;
31-
import static trufflesom.vm.SymbolTable.symBlockSelf;
32-
import static trufflesom.vm.SymbolTable.symFrameOnStack;
33-
import static trufflesom.vm.SymbolTable.symSelf;
3431
import static trufflesom.vm.SymbolTable.symbolFor;
3532

3633
import java.util.ArrayList;
@@ -59,6 +56,8 @@
5956
import trufflesom.interpreter.nodes.ReturnNonLocalNode.CatchNonLocalReturnNode;
6057
import trufflesom.interpreter.nodes.literals.BlockNode;
6158
import trufflesom.interpreter.supernodes.IntIncrementNode;
59+
import trufflesom.interpreter.supernodes.LocalVariableSquareNode;
60+
import trufflesom.interpreter.supernodes.NonLocalVariableSquareNode;
6261
import trufflesom.primitives.Primitives;
6362
import trufflesom.vmobjects.SClass;
6463
import trufflesom.vmobjects.SInvokable;
@@ -404,7 +403,18 @@ public ExpressionNode getLocalReadNode(final Variable variable, final long coord
404403

405404
public ExpressionNode getLocalWriteNode(final Variable variable,
406405
final ExpressionNode valExpr, final long coord) {
407-
return variable.getWriteNode(getContextLevel(variable), valExpr, coord);
406+
int ctxLevel = getContextLevel(variable);
407+
408+
if (valExpr instanceof LocalVariableSquareNode l) {
409+
return variable.getReadSquareWriteNode(ctxLevel, coord, l.getLocal(), 0);
410+
}
411+
412+
if (valExpr instanceof NonLocalVariableSquareNode nl) {
413+
return variable.getReadSquareWriteNode(ctxLevel, coord, nl.getLocal(),
414+
nl.getContextLevel());
415+
}
416+
417+
return variable.getWriteNode(ctxLevel, valExpr, coord);
408418
}
409419

410420
protected Local getLocal(final String varName) {

src/trufflesom/src/trufflesom/compiler/ParserAst.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,9 @@
3535
import trufflesom.interpreter.nodes.FieldNode;
3636
import trufflesom.interpreter.nodes.FieldNode.FieldReadNode;
3737
import trufflesom.interpreter.nodes.GlobalNode;
38+
import trufflesom.interpreter.nodes.LocalVariableNode.LocalVariableReadNode;
3839
import trufflesom.interpreter.nodes.MessageSendNode;
40+
import trufflesom.interpreter.nodes.NonLocalVariableNode.NonLocalVariableReadNode;
3941
import trufflesom.interpreter.nodes.SequenceNode;
4042
import trufflesom.interpreter.nodes.literals.BlockNode;
4143
import trufflesom.interpreter.nodes.literals.BlockNode.BlockNodeWithContext;
@@ -45,7 +47,9 @@
4547
import trufflesom.interpreter.nodes.literals.LiteralNode;
4648
import trufflesom.interpreter.supernodes.IntIncrementNodeGen;
4749
import trufflesom.interpreter.supernodes.LocalFieldStringEqualsNode;
50+
import trufflesom.interpreter.supernodes.LocalVariableSquareNodeGen;
4851
import trufflesom.interpreter.supernodes.NonLocalFieldStringEqualsNode;
52+
import trufflesom.interpreter.supernodes.NonLocalVariableSquareNodeGen;
4953
import trufflesom.interpreter.supernodes.StringEqualsNodeGen;
5054
import trufflesom.primitives.Primitives;
5155
import trufflesom.vm.Globals;
@@ -307,6 +311,20 @@ protected ExpressionNode binaryMessage(final MethodGenerationContext mgenc,
307311
return StringEqualsNodeGen.create(s, operand).initialize(coordWithL);
308312
}
309313
}
314+
} else if (binSelector.equals("*")) {
315+
if (receiver instanceof LocalVariableReadNode rcvr
316+
&& operand instanceof LocalVariableReadNode op) {
317+
if (rcvr.isSameLocal(op)) {
318+
return LocalVariableSquareNodeGen.create(rcvr.getLocal()).initialize(coordWithL);
319+
}
320+
} else if (receiver instanceof NonLocalVariableReadNode rcvr
321+
&& operand instanceof NonLocalVariableReadNode op) {
322+
if (rcvr.isSameLocal(op)) {
323+
assert rcvr.getContextLevel() == op.getContextLevel();
324+
return NonLocalVariableSquareNodeGen.create(
325+
rcvr.getContextLevel(), rcvr.getLocal()).initialize(coordWithL);
326+
}
327+
}
310328
}
311329

312330
ExpressionNode inlined =

src/trufflesom/src/trufflesom/compiler/Variable.java

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@
2727
import trufflesom.interpreter.nodes.LocalVariableNodeFactory.LocalVariableWriteNodeGen;
2828
import trufflesom.interpreter.nodes.NonLocalVariableNodeFactory.NonLocalVariableReadNodeGen;
2929
import trufflesom.interpreter.nodes.NonLocalVariableNodeFactory.NonLocalVariableWriteNodeGen;
30+
import trufflesom.interpreter.supernodes.LocalVariableReadSquareWriteNodeGen;
31+
import trufflesom.interpreter.supernodes.LocalVariableSquareNodeGen;
32+
import trufflesom.interpreter.supernodes.NonLocalVariableReadSquareWriteNodeGen;
33+
import trufflesom.interpreter.supernodes.NonLocalVariableSquareNodeGen;
3034
import trufflesom.vm.NotYetImplementedException;
3135
import trufflesom.vmobjects.SSymbol;
3236

@@ -59,6 +63,11 @@ public String toString() {
5963
public abstract ExpressionNode getWriteNode(
6064
int contextLevel, ExpressionNode valueExpr, long coord);
6165

66+
public abstract ExpressionNode getSquareNode(int contextLevel, long coord);
67+
68+
public abstract ExpressionNode getReadSquareWriteNode(int writeContextLevel, long coord,
69+
Local readLocal, int readContextLevel);
70+
6271
protected abstract void emitPop(BytecodeMethodGenContext mgenc);
6372

6473
protected abstract void emitPush(BytecodeMethodGenContext mgenc);
@@ -136,6 +145,17 @@ public ExpressionNode getWriteNode(final int contextLevel,
136145
}
137146
}
138147

148+
@Override
149+
public ExpressionNode getSquareNode(final int contextLevel, final long coord) {
150+
throw new NotYetImplementedException();
151+
}
152+
153+
@Override
154+
public ExpressionNode getReadSquareWriteNode(final int writeContextLevel, final long coord,
155+
final Local readLocal, final int readContextLevel) {
156+
throw new NotYetImplementedException();
157+
}
158+
139159
@Override
140160
public void emitPop(final BytecodeMethodGenContext mgenc) {
141161
emitPOPARGUMENT(mgenc, (byte) index, (byte) mgenc.getContextLevel(this));
@@ -176,6 +196,25 @@ public ExpressionNode getReadNode(final int contextLevel, final long coordinate)
176196
return LocalVariableReadNodeGen.create(this).initialize(coordinate);
177197
}
178198

199+
@Override
200+
public ExpressionNode getSquareNode(final int contextLevel, final long coord) {
201+
if (contextLevel > 0) {
202+
return NonLocalVariableSquareNodeGen.create(contextLevel, this).initialize(coord);
203+
}
204+
return LocalVariableSquareNodeGen.create(this).initialize(coord);
205+
}
206+
207+
@Override
208+
public ExpressionNode getReadSquareWriteNode(final int writeContextLevel, final long coord,
209+
final Local readLocal, final int readContextLevel) {
210+
if (writeContextLevel > 0 || readContextLevel > 0) {
211+
return NonLocalVariableReadSquareWriteNodeGen.create(
212+
writeContextLevel, this, readLocal, readContextLevel).initialize(coord);
213+
}
214+
assert readContextLevel == 0;
215+
return LocalVariableReadSquareWriteNodeGen.create(this, readLocal).initialize(coord);
216+
}
217+
179218
public final int getIndex() {
180219
return slotIndex;
181220
}
@@ -234,6 +273,19 @@ public ExpressionNode getReadNode(final int contextLevel, final long coordinate)
234273
+ "They are used directly by other nodes.");
235274
}
236275

276+
@Override
277+
public ExpressionNode getSquareNode(final int contextLevel, final long coord) {
278+
throw new UnsupportedOperationException(
279+
"There shouldn't be any language-level square nodes for internal slots. ");
280+
}
281+
282+
@Override
283+
public ExpressionNode getReadSquareWriteNode(final int readContextLevel, final long coord,
284+
final Local readLocal, final int writeContextLevel) {
285+
throw new UnsupportedOperationException(
286+
"There shouldn't be any language-level square nodes for internal slots. ");
287+
}
288+
237289
@Override
238290
public Internal split() {
239291
return new Internal(name, coord, slotIndex);

src/trufflesom/src/trufflesom/interpreter/nodes/LocalVariableNode.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ public abstract class LocalVariableNode extends NoPreEvalExprNode
2222
// TODO: We currently assume that there is a 1:1 mapping between lexical contexts
2323
// and frame descriptors, which is apparently not strictly true anymore in Truffle 1.0.0.
2424
// Generally, we also need to revise everything in this area and address issue SOMns#240.
25-
private LocalVariableNode(final Local local) {
25+
protected LocalVariableNode(final Local local) {
2626
this.local = local;
2727
this.slotIndex = local.getIndex();
2828
}
@@ -46,6 +46,10 @@ public LocalVariableReadNode(final LocalVariableReadNode node) {
4646
this(node.local);
4747
}
4848

49+
public boolean isSameLocal(final LocalVariableNode node) {
50+
return local.equals(node.local);
51+
}
52+
4953
@Specialization(guards = "isUninitialized(frame)")
5054
public static final SObject doNil(@SuppressWarnings("unused") final VirtualFrame frame) {
5155
return Nil.nilObject;

src/trufflesom/src/trufflesom/interpreter/nodes/NonLocalVariableNode.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,16 @@ public abstract class NonLocalVariableNode extends ContextualNode
2424
protected final int slotIndex;
2525
protected final Local local;
2626

27-
private NonLocalVariableNode(final int contextLevel, final Local local) {
27+
protected NonLocalVariableNode(final int contextLevel, final Local local) {
2828
super(contextLevel);
2929
this.local = local;
3030
this.slotIndex = local.getIndex();
3131
}
3232

33+
public boolean isSameLocal(final NonLocalVariableNode node) {
34+
return local.equals(node.local);
35+
}
36+
3337
@Override
3438
public String getInvocationIdentifier() {
3539
return local.name;
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
package trufflesom.interpreter.supernodes;
2+
3+
import com.oracle.truffle.api.dsl.Specialization;
4+
import com.oracle.truffle.api.frame.FrameDescriptor;
5+
import com.oracle.truffle.api.frame.FrameSlotKind;
6+
import com.oracle.truffle.api.frame.FrameSlotTypeException;
7+
import com.oracle.truffle.api.frame.VirtualFrame;
8+
import trufflesom.bdt.inlining.ScopeAdaptationVisitor;
9+
import trufflesom.bdt.inlining.ScopeAdaptationVisitor.ScopeElement;
10+
import trufflesom.compiler.Variable.Local;
11+
import trufflesom.interpreter.nodes.LocalVariableNode;
12+
13+
14+
public abstract class LocalVariableReadSquareWriteNode extends LocalVariableNode {
15+
16+
protected final Local readLocal;
17+
protected final int readIndex;
18+
19+
public LocalVariableReadSquareWriteNode(final Local writeLocal, final Local readLocal) {
20+
super(writeLocal);
21+
this.readLocal = readLocal;
22+
this.readIndex = readLocal.getIndex();
23+
}
24+
25+
@Specialization(guards = {"isLongKind(frame)", "frame.isLong(readIndex)"},
26+
rewriteOn = {FrameSlotTypeException.class})
27+
public final long writeLong(final VirtualFrame frame) throws FrameSlotTypeException {
28+
long current = frame.getLong(readIndex);
29+
long result = Math.multiplyExact(current, current);
30+
frame.setLong(slotIndex, result);
31+
return result;
32+
}
33+
34+
@Specialization(guards = {"isDoubleKind(frame)", "frame.isDouble(readIndex)"},
35+
rewriteOn = {FrameSlotTypeException.class})
36+
public final double writeDouble(final VirtualFrame frame) throws FrameSlotTypeException {
37+
double current = frame.getDouble(readIndex);
38+
double result = current * current;
39+
frame.setDouble(slotIndex, result);
40+
return result;
41+
}
42+
43+
// uses frame to make sure guard is not converted to assertion
44+
protected final boolean isLongKind(final VirtualFrame frame) {
45+
FrameDescriptor descriptor = local.getFrameDescriptor();
46+
if (descriptor.getSlotKind(slotIndex) == FrameSlotKind.Long) {
47+
return true;
48+
}
49+
if (descriptor.getSlotKind(slotIndex) == FrameSlotKind.Illegal) {
50+
descriptor.setSlotKind(slotIndex, FrameSlotKind.Long);
51+
return true;
52+
}
53+
return false;
54+
}
55+
56+
// uses frame to make sure guard is not converted to assertion
57+
protected final boolean isDoubleKind(final VirtualFrame frame) {
58+
FrameDescriptor descriptor = local.getFrameDescriptor();
59+
if (descriptor.getSlotKind(slotIndex) == FrameSlotKind.Double) {
60+
return true;
61+
}
62+
if (descriptor.getSlotKind(slotIndex) == FrameSlotKind.Illegal) {
63+
descriptor.setSlotKind(slotIndex, FrameSlotKind.Double);
64+
return true;
65+
}
66+
return false;
67+
}
68+
69+
@Override
70+
public void replaceAfterScopeChange(final ScopeAdaptationVisitor inliner) {
71+
ScopeElement seWrite = inliner.getAdaptedVar(local);
72+
ScopeElement seRead = inliner.getAdaptedVar(readLocal);
73+
74+
assert seWrite.contextLevel == seRead.contextLevel;
75+
76+
if (seWrite.var != local || seWrite.contextLevel < 0) {
77+
assert seRead.var != readLocal || seRead.contextLevel < 0;
78+
replace(seWrite.var.getReadSquareWriteNode(seWrite.contextLevel, sourceCoord,
79+
(Local) seRead.var, seRead.contextLevel));
80+
} else {
81+
assert 0 == seWrite.contextLevel;
82+
}
83+
}
84+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package trufflesom.interpreter.supernodes;
2+
3+
import com.oracle.truffle.api.dsl.Specialization;
4+
import com.oracle.truffle.api.frame.FrameSlotTypeException;
5+
import com.oracle.truffle.api.frame.VirtualFrame;
6+
import trufflesom.bdt.inlining.ScopeAdaptationVisitor;
7+
import trufflesom.bdt.inlining.ScopeAdaptationVisitor.ScopeElement;
8+
import trufflesom.compiler.Variable.Local;
9+
import trufflesom.interpreter.nodes.LocalVariableNode;
10+
11+
12+
public abstract class LocalVariableSquareNode extends LocalVariableNode {
13+
14+
public LocalVariableSquareNode(final Local variable) {
15+
super(variable);
16+
}
17+
18+
@Specialization(guards = {"frame.isLong(slotIndex)"},
19+
rewriteOn = {FrameSlotTypeException.class})
20+
public final long doLong(final VirtualFrame frame) throws FrameSlotTypeException {
21+
long value = frame.getLong(slotIndex);
22+
return Math.multiplyExact(value, value);
23+
}
24+
25+
@Specialization(guards = {"frame.isDouble(slotIndex)"},
26+
rewriteOn = {FrameSlotTypeException.class})
27+
public final double doDouble(final VirtualFrame frame) throws FrameSlotTypeException {
28+
double value = frame.getDouble(slotIndex);
29+
return value * value;
30+
}
31+
32+
@Override
33+
public void replaceAfterScopeChange(final ScopeAdaptationVisitor inliner) {
34+
ScopeElement se = inliner.getAdaptedVar(local);
35+
if (se.var != local || se.contextLevel < 0) {
36+
replace(se.var.getSquareNode(se.contextLevel, sourceCoord));
37+
} else {
38+
assert 0 == se.contextLevel;
39+
}
40+
}
41+
}

0 commit comments

Comments
 (0)