@@ -130,18 +130,64 @@ private static Object[] prepareArguments(PGenerator self) {
130
130
return arguments ;
131
131
}
132
132
133
- private static Object resumeGenerator (PGenerator self , Object sendValue ) {
134
- try {
133
+ public static void checkResumable (PythonBuiltinBaseNode node , PGenerator self ) {
134
+ if (self .isFinished ()) {
135
+ throw node .raise (StopIteration );
136
+ }
137
+ if (self .isRunning ()) {
138
+ throw node .raise (ValueError , ErrorMessages .GENERATOR_ALREADY_EXECUTING );
139
+ }
140
+ }
141
+
142
+ @ ImportStatic ({PGuards .class , PythonOptions .class })
143
+ @ ReportPolymorphism
144
+ abstract static class ResumeGeneratorNode extends Node {
145
+ public abstract Object execute (VirtualFrame frame , PGenerator self , Object sendValue );
146
+
147
+ @ Specialization (guards = "sameCallTarget(self.getCurrentCallTarget(), call.getCallTarget())" , limit = "getCallSiteInlineCacheMaxDepth()" )
148
+ public Object cached (VirtualFrame frame , PGenerator self , Object sendValue ,
149
+ @ Cached ("createDirectCall(self.getCurrentCallTarget())" ) CallTargetInvokeNode call ) {
150
+ self .setRunning (true );
151
+ Object [] arguments = prepareArguments (self );
152
+ if (sendValue != null ) {
153
+ PArguments .setSpecialArgument (arguments , sendValue );
154
+ }
155
+ try {
156
+ return call .execute (frame , null , null , arguments );
157
+ } catch (PException e ) {
158
+ self .markAsFinished ();
159
+ throw e ;
160
+ } finally {
161
+ self .setRunning (false );
162
+ self .setNextCallTarget ();
163
+ }
164
+ }
165
+
166
+ @ Specialization (replaces = "cached" )
167
+ public Object generic (VirtualFrame frame , PGenerator self , Object sendValue ,
168
+ @ Cached GenericInvokeNode call ) {
135
169
self .setRunning (true );
136
- PArguments .setSpecialArgument (self .getArguments (), sendValue );
137
- return self .getCurrentCallTarget ().call (prepareArguments (self ));
138
- } catch (PException e ) {
139
- self .markAsFinished ();
140
- throw e ;
141
- } finally {
142
- self .setRunning (false );
143
- self .setNextCallTarget ();
144
- PArguments .setSpecialArgument (self .getArguments (), null );
170
+ Object [] arguments = prepareArguments (self );
171
+ if (sendValue != null ) {
172
+ PArguments .setSpecialArgument (arguments , sendValue );
173
+ }
174
+ try {
175
+ return call .execute (frame , self .getCurrentCallTarget (), arguments );
176
+ } catch (PException e ) {
177
+ self .markAsFinished ();
178
+ throw e ;
179
+ } finally {
180
+ self .setRunning (false );
181
+ self .setNextCallTarget ();
182
+ }
183
+ }
184
+
185
+ protected static CallTargetInvokeNode createDirectCall (CallTarget target ) {
186
+ return CallTargetInvokeNode .create (target , false , true );
187
+ }
188
+
189
+ protected static boolean sameCallTarget (RootCallTarget target1 , CallTarget target2 ) {
190
+ return target1 == target2 ;
145
191
}
146
192
}
147
193
@@ -204,65 +250,12 @@ public Object iter(PGenerator self) {
204
250
205
251
@ Builtin (name = __NEXT__ , minNumOfPositionalArgs = 1 )
206
252
@ GenerateNodeFactory
207
- @ ReportPolymorphism
208
253
public abstract static class NextNode extends PythonUnaryBuiltinNode {
209
-
210
- protected static CallTargetInvokeNode createDirectCall (CallTarget target ) {
211
- return CallTargetInvokeNode .create (target , false , true );
212
- }
213
-
214
- protected static GenericInvokeNode createIndirectCall () {
215
- return GenericInvokeNode .create ();
216
- }
217
-
218
- protected static boolean sameCallTarget (RootCallTarget target1 , CallTarget target2 ) {
219
- return target1 == target2 ;
220
- }
221
-
222
- @ Specialization (guards = "sameCallTarget(self.getCurrentCallTarget(), call.getCallTarget())" , limit = "getCallSiteInlineCacheMaxDepth()" )
223
- public Object nextCached (VirtualFrame frame , PGenerator self ,
224
- @ Cached ("createDirectCall(self.getCurrentCallTarget())" ) CallTargetInvokeNode call ,
225
- @ Cached BranchProfile alreadyRunning ) {
226
- if (self .isFinished ()) {
227
- throw raise (StopIteration );
228
- }
229
- if (self .isRunning ()) {
230
- alreadyRunning .enter ();
231
- throw raise (ValueError , ErrorMessages .GENERATOR_ALREADY_EXECUTING );
232
- }
233
- try {
234
- self .setRunning (true );
235
- return call .execute (frame , null , null , prepareArguments (self ));
236
- } catch (PException e ) {
237
- self .markAsFinished ();
238
- throw e ;
239
- } finally {
240
- self .setRunning (false );
241
- self .setNextCallTarget ();
242
- }
243
- }
244
-
245
- @ Specialization (replaces = "nextCached" )
254
+ @ Specialization
246
255
public Object next (VirtualFrame frame , PGenerator self ,
247
- @ Cached ("createIndirectCall()" ) GenericInvokeNode call ,
248
- @ Cached BranchProfile alreadyRunning ) {
249
- if (self .isFinished ()) {
250
- throw raise (StopIteration );
251
- }
252
- if (self .isRunning ()) {
253
- alreadyRunning .enter ();
254
- throw raise (ValueError , ErrorMessages .GENERATOR_ALREADY_EXECUTING );
255
- }
256
- try {
257
- self .setRunning (true );
258
- return call .execute (frame , self .getCurrentCallTarget (), prepareArguments (self ));
259
- } catch (PException e ) {
260
- self .markAsFinished ();
261
- throw e ;
262
- } finally {
263
- self .setRunning (false );
264
- self .setNextCallTarget ();
265
- }
256
+ @ Cached ResumeGeneratorNode resumeGeneratorNode ) {
257
+ checkResumable (this , self );
258
+ return resumeGeneratorNode .execute (frame , self , null );
266
259
}
267
260
}
268
261
@@ -271,13 +264,10 @@ public Object next(VirtualFrame frame, PGenerator self,
271
264
public abstract static class SendNode extends PythonBuiltinNode {
272
265
273
266
@ Specialization
274
- public Object send (PGenerator self , Object value ,
275
- @ Cached BranchProfile alreadyRunning ) {
276
- if (self .isRunning ()) {
277
- alreadyRunning .enter ();
278
- throw raise (ValueError , ErrorMessages .GENERATOR_ALREADY_EXECUTING );
279
- }
280
- return resumeGenerator (self , value );
267
+ public Object send (VirtualFrame frame , PGenerator self , Object value ,
268
+ @ Cached ResumeGeneratorNode resumeGeneratorNode ) {
269
+ checkResumable (this , self );
270
+ return resumeGeneratorNode .execute (frame , self , value );
281
271
}
282
272
}
283
273
@@ -393,38 +383,32 @@ private void checkExceptionClass(Object type) {
393
383
@ Specialization
394
384
Object sendThrow (VirtualFrame frame , PGenerator self , Object typ , Object val , @ SuppressWarnings ("unused" ) PNone tb ,
395
385
@ Cached PrepareExceptionNode prepareExceptionNode ,
396
- @ Cached BranchProfile alreadyRunning ,
386
+ @ Cached ResumeGeneratorNode resumeGeneratorNode ,
397
387
@ Shared ("language" ) @ CachedLanguage PythonLanguage language ) {
398
- if (self .isRunning ()) {
399
- alreadyRunning .enter ();
400
- throw raise (ValueError , ErrorMessages .GENERATOR_ALREADY_EXECUTING );
401
- }
388
+ checkResumable (this , self );
402
389
PBaseException instance = prepareExceptionNode .execute (frame , typ , val );
403
- return doThrow (self , instance , language );
390
+ return doThrow (frame , resumeGeneratorNode , self , instance , language );
404
391
}
405
392
406
393
@ Specialization
407
394
Object sendThrow (VirtualFrame frame , PGenerator self , Object typ , Object val , PTraceback tb ,
408
395
@ Cached PrepareExceptionNode prepareExceptionNode ,
409
- @ Cached BranchProfile alreadyRunning ,
396
+ @ Cached ResumeGeneratorNode resumeGeneratorNode ,
410
397
@ Shared ("language" ) @ CachedLanguage PythonLanguage language ) {
411
- if (self .isRunning ()) {
412
- alreadyRunning .enter ();
413
- throw raise (ValueError , ErrorMessages .GENERATOR_ALREADY_EXECUTING );
414
- }
398
+ checkResumable (this , self );
415
399
PBaseException instance = prepareExceptionNode .execute (frame , typ , val );
416
400
instance .setTraceback (tb );
417
- return doThrow (self , instance , language );
401
+ return doThrow (frame , resumeGeneratorNode , self , instance , language );
418
402
}
419
403
420
- private Object doThrow (PGenerator self , PBaseException instance , PythonLanguage language ) {
404
+ private Object doThrow (VirtualFrame frame , ResumeGeneratorNode resumeGeneratorNode , PGenerator self , PBaseException instance , PythonLanguage language ) {
421
405
instance .setContext (null ); // Will be filled when caught
422
406
if (self .isStarted ()) {
423
407
instance .ensureReified ();
424
408
// Pass it to the generator where it will be thrown by the last yield, the location
425
409
// will be filled there
426
410
PException pException = PException .fromObject (instance , null , PythonOptions .isPExceptionWithJavaStacktrace (language ));
427
- return resumeGenerator ( self , pException );
411
+ return resumeGeneratorNode . execute ( frame , self , pException );
428
412
} else {
429
413
// Unstarted generator, we cannot pass the exception into the generator as there is
430
414
// nothing that would handle it.
@@ -470,24 +454,24 @@ private GetTracebackNode ensureGetTracebackNode() {
470
454
@ GenerateNodeFactory
471
455
public abstract static class CloseNode extends PythonUnaryBuiltinNode {
472
456
@ Specialization
473
- Object close (PGenerator self ,
457
+ Object close (VirtualFrame frame , PGenerator self ,
474
458
@ CachedLibrary (limit = "3" ) PythonObjectLibrary lib ,
475
459
@ Cached IsBuiltinClassProfile isGeneratorExit ,
476
460
@ Cached IsBuiltinClassProfile isStopIteration ,
477
- @ Cached BranchProfile alreadyRunning ,
461
+ @ Cached ResumeGeneratorNode resumeGeneratorNode ,
462
+ @ Cached ConditionProfile isStartedPorfile ,
478
463
@ CachedLanguage PythonLanguage language ) {
479
464
if (self .isRunning ()) {
480
- alreadyRunning .enter ();
481
465
throw raise (ValueError , ErrorMessages .GENERATOR_ALREADY_EXECUTING );
482
466
}
483
- if (self .isStarted ()) {
467
+ if (isStartedPorfile . profile ( self .isStarted () )) {
484
468
PBaseException pythonException = factory ().createBaseException (GeneratorExit );
485
469
// Pass it to the generator where it will be thrown by the last yield, the location
486
470
// will be filled there
487
471
boolean withJavaStacktrace = PythonOptions .isPExceptionWithJavaStacktrace (language );
488
472
PException pException = PException .fromObject (pythonException , null , withJavaStacktrace );
489
473
try {
490
- resumeGenerator ( self , pException );
474
+ resumeGeneratorNode . execute ( frame , self , pException );
491
475
} catch (PException pe ) {
492
476
if (isGeneratorExit .profileException (pe , GeneratorExit , lib ) || isStopIteration .profileException (pe , StopIteration , lib )) {
493
477
// This is the "success" path
0 commit comments