@@ -141,34 +141,95 @@ private static void checkResumable(PythonBuiltinBaseNode node, PGenerator self)
141
141
abstract static class ResumeGeneratorNode extends Node {
142
142
public abstract Object execute (VirtualFrame frame , PGenerator self , Object sendValue );
143
143
144
- @ Specialization (guards = " sameCallTarget(self.getCurrentCallTarget(), call.getCallTarget())" , limit = "getCallSiteInlineCacheMaxDepth()" )
145
- Object cached (VirtualFrame frame , PGenerator self , Object sendValue ,
144
+ @ Specialization (guards = { "!self.usesBytecode()" , " sameCallTarget(self.getCurrentCallTarget(), call.getCallTarget())"} , limit = "getCallSiteInlineCacheMaxDepth()" )
145
+ Object cachedAST (VirtualFrame frame , PGenerator self , Object sendValue ,
146
146
@ Cached ("createDirectCall(self.getCurrentCallTarget())" ) CallTargetInvokeNode call ) {
147
147
self .setRunning (true );
148
148
Object [] arguments = prepareArguments (self );
149
149
if (sendValue != null ) {
150
150
PArguments .setSpecialArgument (arguments , sendValue );
151
151
}
152
+ try {
153
+ return call .execute (frame , null , null , null , arguments );
154
+ } catch (PException e ) {
155
+ self .markAsFinished ();
156
+ throw e ;
157
+ } finally {
158
+ self .setRunning (false );
159
+ self .setNextCallTarget (PythonLanguage .get (this ));
160
+ }
161
+ }
162
+
163
+ @ Specialization (guards = "!self.usesBytecode()" , replaces = "cachedAST" )
164
+ @ Megamorphic
165
+ Object genericAST (VirtualFrame frame , PGenerator self , Object sendValue ,
166
+ @ Cached ConditionProfile hasFrameProfile ,
167
+ @ Cached GenericInvokeNode call ) {
168
+ self .setRunning (true );
169
+ Object [] arguments = prepareArguments (self );
170
+ if (sendValue != null ) {
171
+ PArguments .setSpecialArgument (arguments , sendValue );
172
+ }
173
+ try {
174
+ if (hasFrameProfile .profile (frame != null )) {
175
+ return call .execute (frame , self .getCurrentCallTarget (), arguments );
176
+ } else {
177
+ return call .execute (self .getCurrentCallTarget (), arguments );
178
+ }
179
+ } catch (PException e ) {
180
+ self .markAsFinished ();
181
+ throw e ;
182
+ } finally {
183
+ self .setRunning (false );
184
+ self .setNextCallTarget (PythonLanguage .get (this ));
185
+ }
186
+ }
187
+
188
+ @ Specialization (guards = {"self.usesBytecode()" , "sameCallTarget(self.getCurrentCallTarget(), call.getCallTarget())" }, limit = "getCallSiteInlineCacheMaxDepth()" )
189
+ Object cached (VirtualFrame frame , PGenerator self , Object sendValue ,
190
+ @ Cached ("createDirectCall(self.getCurrentCallTarget())" ) CallTargetInvokeNode call ,
191
+ @ Cached ConditionProfile returnProfile ,
192
+ @ Cached IsBuiltinClassProfile errorProfile ,
193
+ @ Cached PRaiseNode raiseNode ) {
194
+ self .setRunning (true );
195
+ Object [] arguments = prepareArguments (self );
196
+ if (sendValue != null ) {
197
+ PArguments .setSpecialArgument (arguments , sendValue );
198
+ }
152
199
Object result ;
153
200
try {
154
201
result = call .execute (frame , null , null , null , arguments );
155
202
} catch (PException e ) {
156
203
self .markAsFinished ();
157
- throw e ;
204
+ // PEP 479 - StopIteration raised from generator body needs to be wrapped in
205
+ // RuntimeError
206
+ e .expectStopIteration (errorProfile );
207
+ throw raiseNode .raise (RuntimeError , e .setCatchingFrameAndGetEscapedException (frame , this ), ErrorMessages .GENERATOR_RAISED_STOPITER );
158
208
} finally {
159
209
self .setRunning (false );
160
- if (!self .isFinished ()) {
161
- self .setNextCallTarget (PythonLanguage .get (this ));
210
+ }
211
+ if (returnProfile .profile (result == null )) {
212
+ // Null result indicates a generator return
213
+ Object returnValue = self .getReturnValue ();
214
+ if (returnValue != PNone .NONE ) {
215
+ throw raiseNode .raise (StopIteration , returnValue );
216
+ } else {
217
+ throw raiseNode .raise (StopIteration );
162
218
}
219
+ } else {
220
+ self .setNextCallTarget (PythonLanguage .get (this ));
163
221
}
164
222
return result ;
165
223
}
166
224
167
- @ Specialization (replaces = "cached" )
225
+ @ Specialization (guards = "self.usesBytecode()" , replaces = "cached" )
168
226
@ Megamorphic
169
227
Object generic (VirtualFrame frame , PGenerator self , Object sendValue ,
170
228
@ Cached ConditionProfile hasFrameProfile ,
171
- @ Cached GenericInvokeNode call ) {
229
+ @ Cached GenericInvokeNode call ,
230
+ @ Cached ConditionProfile returnProfile ,
231
+ @ Cached IsBuiltinClassProfile errorProfile ,
232
+ @ Cached PRaiseNode raiseNode ) {
172
233
self .setRunning (true );
173
234
Object [] arguments = prepareArguments (self );
174
235
if (sendValue != null ) {
@@ -183,12 +244,23 @@ Object generic(VirtualFrame frame, PGenerator self, Object sendValue,
183
244
}
184
245
} catch (PException e ) {
185
246
self .markAsFinished ();
186
- throw e ;
247
+ // PEP 479 - StopIteration raised from generator body needs to be wrapped in
248
+ // RuntimeError
249
+ e .expectStopIteration (errorProfile );
250
+ throw raiseNode .raise (RuntimeError , e .setCatchingFrameAndGetEscapedException (frame , this ), ErrorMessages .GENERATOR_RAISED_STOPITER );
187
251
} finally {
188
252
self .setRunning (false );
189
- if (!self .isFinished ()) {
190
- self .setNextCallTarget (PythonLanguage .get (this ));
253
+ }
254
+ if (returnProfile .profile (result == null )) {
255
+ // Null result indicates a generator return
256
+ Object returnValue = self .getReturnValue ();
257
+ if (returnValue != PNone .NONE ) {
258
+ throw raiseNode .raise (StopIteration , returnValue );
259
+ } else {
260
+ throw raiseNode .raise (StopIteration );
191
261
}
262
+ } else {
263
+ self .setNextCallTarget (PythonLanguage .get (this ));
192
264
}
193
265
return result ;
194
266
}
0 commit comments