29
29
import static com .oracle .graal .python .runtime .exception .PythonErrorType .UnboundLocalError ;
30
30
31
31
import com .oracle .graal .python .builtins .objects .cell .PCell ;
32
+ import com .oracle .graal .python .nodes .PBaseNode ;
32
33
import com .oracle .graal .python .nodes .PNode ;
34
+ import com .oracle .graal .python .nodes .cell .ReadLocalCellNodeGen .ReadFromCellNodeGen ;
33
35
import com .oracle .graal .python .nodes .frame .ReadLocalNode ;
34
36
import com .oracle .graal .python .nodes .frame .ReadLocalVariableNode ;
35
37
import com .oracle .graal .python .runtime .exception .PException ;
36
38
import com .oracle .truffle .api .CompilerDirectives ;
37
39
import com .oracle .truffle .api .dsl .Cached ;
40
+ import com .oracle .truffle .api .dsl .Fallback ;
38
41
import com .oracle .truffle .api .dsl .Specialization ;
39
42
import com .oracle .truffle .api .frame .FrameSlot ;
40
43
import com .oracle .truffle .api .frame .VirtualFrame ;
44
+ import com .oracle .truffle .api .nodes .NodeCost ;
41
45
import com .oracle .truffle .api .nodes .NodeInfo ;
42
46
import com .oracle .truffle .api .profiles .ValueProfile ;
43
47
44
48
@ NodeInfo (shortName = "read_cell" )
45
49
public abstract class ReadLocalCellNode extends PNode implements ReadLocalNode {
46
50
@ Child private PNode readLocal ;
47
-
51
+ @ Child private ReadFromCellNode readCell ;
48
52
private final FrameSlot frameSlot ;
49
- private final boolean isFreeVar ;
50
53
51
54
ReadLocalCellNode (FrameSlot frameSlot , boolean isFreeVar ) {
52
55
this .frameSlot = frameSlot ;
53
56
this .readLocal = ReadLocalVariableNode .create (frameSlot );
54
- this .isFreeVar = isFreeVar ;
57
+ this .readCell = ReadFromCellNodeGen . create ( isFreeVar , frameSlot . getIdentifier ()) ;
55
58
}
56
59
57
60
public static PNode create (FrameSlot frameSlot , boolean isFreeVar ) {
@@ -63,25 +66,56 @@ public PNode makeWriteNode(PNode rhs) {
63
66
return WriteLocalCellNode .create (frameSlot , rhs );
64
67
}
65
68
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 ());
72
91
if (ref != null ) {
73
92
return ref ;
93
+ } else {
94
+ throw raiseUnbound ();
74
95
}
75
- throw raiseUnbound ();
76
96
}
77
- CompilerDirectives .transferToInterpreter ();
78
- throw new IllegalStateException ("Expected a cell, got: " + cell .toString () + " instead." );
79
- }
80
97
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." );
84
102
}
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 ;
86
120
}
87
121
}
0 commit comments