Skip to content

Commit 9437597

Browse files
committed
try to assume cells are effectively final
1 parent 7c5b614 commit 9437597

File tree

2 files changed

+66
-19
lines changed

2 files changed

+66
-19
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cell/PCell.java

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,14 @@
4747
import com.oracle.graal.python.builtins.PythonBuiltinClassType;
4848
import com.oracle.graal.python.builtins.objects.PNone;
4949
import com.oracle.graal.python.builtins.objects.object.PythonBuiltinObject;
50+
import com.oracle.truffle.api.Assumption;
5051
import com.oracle.truffle.api.CompilerAsserts;
52+
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
53+
import com.oracle.truffle.api.Truffle;
5154

5255
public class PCell extends PythonBuiltinObject {
53-
private Object ref;
56+
private final Assumption effectivelyFinal = Truffle.getRuntime().createAssumption("cell is effectively final");
57+
@CompilationFinal private Object ref;
5458

5559
public PCell() {
5660
super(PythonLanguage.getCore().lookupType(PythonBuiltinClassType.PCell));
@@ -61,13 +65,22 @@ public Object getRef() {
6165
}
6266

6367
public void clearRef() {
64-
ref = null;
68+
setRef(null);
6569
}
6670

6771
public void setRef(Object ref) {
72+
if (effectivelyFinal.isValid()) {
73+
if (this.ref != null) {
74+
effectivelyFinal.invalidate();
75+
}
76+
}
6877
this.ref = ref;
6978
}
7079

80+
public Assumption isEffectivelyFinalAssumption() {
81+
return effectivelyFinal;
82+
}
83+
7184
public Object getPythonRef() {
7285
if (ref == null) {
7386
return PNone.NONE;

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/cell/ReadLocalCellNode.java

Lines changed: 51 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -29,29 +29,32 @@
2929
import static com.oracle.graal.python.runtime.exception.PythonErrorType.UnboundLocalError;
3030

3131
import com.oracle.graal.python.builtins.objects.cell.PCell;
32+
import com.oracle.graal.python.nodes.PBaseNode;
3233
import com.oracle.graal.python.nodes.PNode;
34+
import com.oracle.graal.python.nodes.cell.ReadLocalCellNodeGen.ReadFromCellNodeGen;
3335
import com.oracle.graal.python.nodes.frame.ReadLocalNode;
3436
import com.oracle.graal.python.nodes.frame.ReadLocalVariableNode;
3537
import com.oracle.graal.python.runtime.exception.PException;
3638
import com.oracle.truffle.api.CompilerDirectives;
3739
import com.oracle.truffle.api.dsl.Cached;
40+
import com.oracle.truffle.api.dsl.Fallback;
3841
import com.oracle.truffle.api.dsl.Specialization;
3942
import com.oracle.truffle.api.frame.FrameSlot;
4043
import com.oracle.truffle.api.frame.VirtualFrame;
44+
import com.oracle.truffle.api.nodes.NodeCost;
4145
import com.oracle.truffle.api.nodes.NodeInfo;
4246
import com.oracle.truffle.api.profiles.ValueProfile;
4347

4448
@NodeInfo(shortName = "read_cell")
4549
public abstract class ReadLocalCellNode extends PNode implements ReadLocalNode {
4650
@Child private PNode readLocal;
47-
51+
@Child private ReadFromCellNode readCell;
4852
private final FrameSlot frameSlot;
49-
private final boolean isFreeVar;
5053

5154
ReadLocalCellNode(FrameSlot frameSlot, boolean isFreeVar) {
5255
this.frameSlot = frameSlot;
5356
this.readLocal = ReadLocalVariableNode.create(frameSlot);
54-
this.isFreeVar = isFreeVar;
57+
this.readCell = ReadFromCellNodeGen.create(isFreeVar, frameSlot.getIdentifier());
5558
}
5659

5760
public static PNode create(FrameSlot frameSlot, boolean isFreeVar) {
@@ -63,25 +66,56 @@ public PNode makeWriteNode(PNode rhs) {
6366
return WriteLocalCellNode.create(frameSlot, rhs);
6467
}
6568

66-
@Specialization
67-
Object readObject(VirtualFrame frame,
68-
@Cached("createClassProfile()") ValueProfile refTypeProfile) {
69-
Object cell = readLocal.execute(frame);
70-
if (cell instanceof PCell) {
71-
Object ref = refTypeProfile.profile(((PCell) cell).getRef());
69+
static abstract class ReadFromCellNode extends PBaseNode {
70+
private final boolean isFreeVar;
71+
private final Object identifier;
72+
73+
public ReadFromCellNode(boolean isFreeVar, Object identifier) {
74+
this.isFreeVar = isFreeVar;
75+
this.identifier = identifier;
76+
}
77+
78+
abstract Object execute(Object cell);
79+
80+
@Specialization(guards = "cachedCell == cell", limit = "1", assumptions = "cachedCell.isEffectivelyFinalAssumption()")
81+
Object readFinal(@SuppressWarnings("unused") PCell cell,
82+
@SuppressWarnings("unused") @Cached("cell") PCell cachedCell,
83+
@Cached("cell.getRef()") Object ref) {
84+
return ref;
85+
}
86+
87+
@Specialization(replaces = "readFinal")
88+
Object read(PCell cell,
89+
@Cached("createClassProfile()") ValueProfile refTypeProfile) {
90+
Object ref = refTypeProfile.profile(cell.getRef());
7291
if (ref != null) {
7392
return ref;
93+
} else {
94+
throw raiseUnbound();
7495
}
75-
throw raiseUnbound();
7696
}
77-
CompilerDirectives.transferToInterpreter();
78-
throw new IllegalStateException("Expected a cell, got: " + cell.toString() + " instead.");
79-
}
8097

81-
private PException raiseUnbound() {
82-
if (isFreeVar) {
83-
return raise(NameError, "free variable '%s' referenced before assignment in enclosing scope", frameSlot.getIdentifier());
98+
@Fallback
99+
Object read(Object cell) {
100+
CompilerDirectives.transferToInterpreter();
101+
throw new IllegalStateException("Expected a cell, got: " + cell.toString() + " instead.");
84102
}
85-
return raise(UnboundLocalError, "local variable '%s' referenced before assignment", frameSlot.getIdentifier());
103+
104+
private PException raiseUnbound() {
105+
if (isFreeVar) {
106+
return raise(NameError, "free variable '%s' referenced before assignment in enclosing scope", identifier);
107+
}
108+
return raise(UnboundLocalError, "local variable '%s' referenced before assignment", identifier);
109+
}
110+
}
111+
112+
@Specialization
113+
Object readObject(VirtualFrame frame) {
114+
return readCell.execute(readLocal.execute(frame));
115+
}
116+
117+
@Override
118+
public NodeCost getCost() {
119+
return NodeCost.NONE;
86120
}
87121
}

0 commit comments

Comments
 (0)