55
55
import com .oracle .graal .python .runtime .exception .PException ;
56
56
import com .oracle .truffle .api .CompilerAsserts ;
57
57
import com .oracle .truffle .api .CompilerDirectives ;
58
+ import com .oracle .truffle .api .CompilerDirectives .CompilationFinal ;
58
59
import com .oracle .truffle .api .CompilerDirectives .TruffleBoundary ;
60
+ import com .oracle .truffle .api .frame .Frame ;
59
61
import com .oracle .truffle .api .frame .MaterializedFrame ;
60
62
import com .oracle .truffle .api .frame .VirtualFrame ;
63
+ import com .oracle .truffle .api .nodes .ExplodeLoop ;
61
64
import com .oracle .truffle .api .profiles .ConditionProfile ;
62
65
import com .oracle .truffle .api .source .SourceSection ;
63
66
@@ -70,6 +73,16 @@ public class PBytecodeGeneratorRootNode extends PRootNode {
70
73
@ Child private IsBuiltinClassProfile errorProfile ;
71
74
@ Child private PRaiseNode raise = PRaiseNode .create ();
72
75
76
+ private enum FrameSlotType {
77
+ Object ,
78
+ Int ,
79
+ Long ,
80
+ Double ,
81
+ Boolean
82
+ }
83
+
84
+ @ CompilationFinal (dimensions = 1 ) private FrameSlotType [] frameSlotTypes ;
85
+
73
86
private final ConditionProfile returnProfile = ConditionProfile .create ();
74
87
75
88
@ TruffleBoundary
@@ -78,6 +91,105 @@ public PBytecodeGeneratorRootNode(PythonLanguage language, PBytecodeRootNode roo
78
91
this .rootNode = rootNode ;
79
92
this .resumeBci = resumeBci ;
80
93
this .resumeStackTop = resumeStackTop ;
94
+ frameSlotTypes = new FrameSlotType [resumeStackTop ];
95
+ }
96
+
97
+ @ ExplodeLoop
98
+ private void copyFrameSlotsIntoVirtualFrame (MaterializedFrame generatorFrame , VirtualFrame virtualFrame ) {
99
+ for (int i = 0 ; i < frameSlotTypes .length ; i ++) {
100
+ switch (frameSlotTypes [i ]) {
101
+ case Object :
102
+ if (generatorFrame .isObject (i )) {
103
+ virtualFrame .setObject (i , generatorFrame .getObject (i ));
104
+ continue ;
105
+ }
106
+ break ;
107
+ case Int :
108
+ if (generatorFrame .isInt (i )) {
109
+ virtualFrame .setInt (i , generatorFrame .getInt (i ));
110
+ continue ;
111
+ }
112
+ break ;
113
+ case Long :
114
+ if (generatorFrame .isLong (i )) {
115
+ virtualFrame .setLong (i , generatorFrame .getLong (i ));
116
+ continue ;
117
+ }
118
+ break ;
119
+ case Double :
120
+ if (generatorFrame .isDouble (i )) {
121
+ virtualFrame .setDouble (i , generatorFrame .getDouble (i ));
122
+ continue ;
123
+ }
124
+ break ;
125
+ case Boolean :
126
+ if (generatorFrame .isBoolean (i )) {
127
+ virtualFrame .setBoolean (i , generatorFrame .getBoolean (i ));
128
+ continue ;
129
+ }
130
+ break ;
131
+ }
132
+ CompilerDirectives .transferToInterpreterAndInvalidate ();
133
+ if (generatorFrame .isObject (i )) {
134
+ virtualFrame .setObject (i , generatorFrame .getObject (i ));
135
+ frameSlotTypes [i ] = FrameSlotType .Object ;
136
+ } else if (generatorFrame .isInt (i )) {
137
+ virtualFrame .setInt (i , generatorFrame .getInt (i ));
138
+ frameSlotTypes [i ] = FrameSlotType .Int ;
139
+ } else if (generatorFrame .isLong (i )) {
140
+ virtualFrame .setLong (i , generatorFrame .getLong (i ));
141
+ frameSlotTypes [i ] = FrameSlotType .Long ;
142
+ } else if (generatorFrame .isDouble (i )) {
143
+ virtualFrame .setDouble (i , generatorFrame .getDouble (i ));
144
+ frameSlotTypes [i ] = FrameSlotType .Double ;
145
+ } else if (generatorFrame .isBoolean (i )) {
146
+ virtualFrame .setBoolean (i , generatorFrame .getBoolean (i ));
147
+ frameSlotTypes [i ] = FrameSlotType .Boolean ;
148
+ } else {
149
+ throw new IllegalStateException ("unexpected frame slot type" );
150
+ }
151
+ }
152
+ }
153
+
154
+ @ ExplodeLoop
155
+ private void copyFrameSlotsToGeneratorFrame (VirtualFrame virtualFrame , MaterializedFrame generatorFrame ) {
156
+ for (int i = 0 ; i < frameSlotTypes .length ; i ++) {
157
+ if (virtualFrame .isObject (i )) {
158
+ generatorFrame .setObject (i , virtualFrame .getObject (i ));
159
+ } else if (virtualFrame .isInt (i )) {
160
+ generatorFrame .setInt (i , virtualFrame .getInt (i ));
161
+ } else if (virtualFrame .isLong (i )) {
162
+ generatorFrame .setLong (i , virtualFrame .getLong (i ));
163
+ } else if (virtualFrame .isDouble (i )) {
164
+ generatorFrame .setDouble (i , virtualFrame .getDouble (i ));
165
+ } else if (virtualFrame .isBoolean (i )) {
166
+ generatorFrame .setBoolean (i , virtualFrame .getBoolean (i ));
167
+ } else {
168
+ throw CompilerDirectives .shouldNotReachHere ("unexpected frame slot type" );
169
+ }
170
+ }
171
+ generatorFrame .setInt (rootNode .bcioffset , virtualFrame .getInt (rootNode .bcioffset ));
172
+ generatorFrame .setInt (rootNode .generatorStackTopOffset , virtualFrame .getInt (rootNode .generatorStackTopOffset ));
173
+ generatorFrame .setObject (rootNode .generatorReturnOffset , virtualFrame .getObject (rootNode .generatorReturnOffset ));
174
+ }
175
+
176
+ private void profileFrameSlots (MaterializedFrame generatorFrame ) {
177
+ CompilerAsserts .neverPartOfCompilation ();
178
+ for (int i = 0 ; i < frameSlotTypes .length ; i ++) {
179
+ if (generatorFrame .isObject (i )) {
180
+ frameSlotTypes [i ] = FrameSlotType .Object ;
181
+ } else if (generatorFrame .isInt (i )) {
182
+ frameSlotTypes [i ] = FrameSlotType .Int ;
183
+ } else if (generatorFrame .isLong (i )) {
184
+ frameSlotTypes [i ] = FrameSlotType .Long ;
185
+ } else if (generatorFrame .isDouble (i )) {
186
+ frameSlotTypes [i ] = FrameSlotType .Double ;
187
+ } else if (generatorFrame .isBoolean (i )) {
188
+ frameSlotTypes [i ] = FrameSlotType .Boolean ;
189
+ } else {
190
+ throw new IllegalStateException ("unexpected frame slot type" );
191
+ }
192
+ }
81
193
}
82
194
83
195
@ Override
@@ -93,14 +205,25 @@ public Object execute(VirtualFrame frame) {
93
205
PException outerException = PArguments .getException (frame );
94
206
PArguments .setException (frame , localException == null ? outerException : localException );
95
207
Object result ;
208
+ Frame localFrame ;
209
+ if (CompilerDirectives .inInterpreter ()) {
210
+ profileFrameSlots (generatorFrame );
211
+ localFrame = generatorFrame ;
212
+ } else {
213
+ copyFrameSlotsIntoVirtualFrame (generatorFrame , frame );
214
+ localFrame = frame ;
215
+ }
96
216
try {
97
- result = rootNode .executeFromBci (frame , resumeBci , resumeStackTop );
217
+ result = rootNode .executeFromBci (frame , localFrame , resumeBci , resumeStackTop );
98
218
} catch (PException pe ) {
99
219
// PEP 479 - StopIteration raised from generator body needs to be wrapped in
100
220
// RuntimeError
101
221
pe .expectStopIteration (getErrorProfile ());
102
222
throw raise .raise (RuntimeError , pe .setCatchingFrameAndGetEscapedException (frame , this ), ErrorMessages .GENERATOR_RAISED_STOPITER );
103
223
} finally {
224
+ if (CompilerDirectives .inCompiledCode ()) {
225
+ copyFrameSlotsToGeneratorFrame (frame , generatorFrame );
226
+ }
104
227
calleeContext .exit (frame , this );
105
228
PException exception = PArguments .getException (frame );
106
229
if (exception != outerException && exception != PException .NO_EXCEPTION ) {
0 commit comments