Construct GeneratorExit

Performance Diagrams

Construct GeneratorExit 002000000020000000400000004000000060000000600000008000000080000000100000000100000000120000000120000000140000000140000000160000000160000000180000000180000000200000000200000000220000000220000000240000000240000000260000000260000000280000000280000000300000000300000000CPython 2.7Nuitka (master)Nuitka (develop)Nuitka (factory)31351298488.11538461538461257.0CPython 2.7160354379240.03846153846155377.7217866987313Nuitka (master)160353959391.96153846153845377.7221177486937Nuitka (develop)160353923543.8846153846154377.72214612440473Nuitka (factory)Construct GeneratorExitTicks Construct GeneratorExit 0010000000100000002000000020000000300000003000000040000000400000005000000050000000600000006000000070000000700000008000000080000000CPython 3.5Nuitka (master)Nuitka (develop)Nuitka (factory)8177156788.95192307692307257.0CPython 3.567006055242.31730769230768301.62168588408093Nuitka (master)67000689395.6826923076923301.63790204823795Nuitka (develop)67003585549.0480769230769301.6291502757074Nuitka (factory)Construct GeneratorExitTicks

Source Code with Construct

def calledRepeatedly():
    # We measure making a generator iterator step or not.
    def generator():
        yield 1
        yield 2
        yield 3

    gen = generator()

    next(gen)

    # Take attribute lookup out of it, and built-in lookup too.
    throw = gen.throw
    exc = GeneratorExit

    try:
# construct_begin
        throw(exc)
# construct_alternative


    except exc:
        pass

    return throw, exc


import itertools
for x in itertools.repeat(None, 50000):
    calledRepeatedly()

print("OK.")

Source Code without Construct

def calledRepeatedly():
    # We measure making a generator iterator step or not.
    def generator():
        yield 1
        yield 2
        yield 3

    gen = generator()

    next(gen)

    # Take attribute lookup out of it, and built-in lookup too.
    throw = gen.throw
    exc = GeneratorExit

    try:
# construct_begin

# construct_alternative
        pass
# construct_end
    except exc:
        pass

    return throw, exc


import itertools
for x in itertools.repeat(None, 50000):
    calledRepeatedly()

print("OK.")

Context Diff of Source Code


Construct
Baseline
32     throw = gen.throw 32     throw = gen.throw
33     exc = GeneratorExit 33     exc = GeneratorExit
34 34
35     try: 35     try:
36 # construct_begin 36 # construct_begin
n 37         throw(exc) n 37  
38 # construct_alternative 38 # construct_alternative
t 39   t 39         pass
40   40 # construct_end
41     except exc: 41     except exc:
42         pass 42         pass
43 43
44     return throw, exc 44     return throw, exc
45 45

Context Diff of Generated Code


Construct
Baseline
147 147
148     // Local variable declarations. 148     // Local variable declarations.
149     PyObject *var_generator = NULL; 149     PyObject *var_generator = NULL;
150     PyObject *var_gen = NULL; 150     PyObject *var_gen = NULL;
151     PyObject *var_throw = NULL; 151     PyObject *var_throw = NULL;
n 152     PyObject *var_exc = NULL; n
153     PyObject *exception_type = NULL; 152     PyObject *exception_type = NULL;
154     PyObject *exception_value = NULL; 153     PyObject *exception_value = NULL;
155     PyTracebackObject *exception_tb = NULL; 154     PyTracebackObject *exception_tb = NULL;
156     NUITKA_MAY_BE_UNUSED int exception_lineno = 0; 155     NUITKA_MAY_BE_UNUSED int exception_lineno = 0;
157     PyObject *exception_keeper_type_1; 156     PyObject *exception_keeper_type_1;
158     PyObject *exception_keeper_value_1; 157     PyObject *exception_keeper_value_1;
159     PyTracebackObject *exception_keeper_tb_1; 158     PyTracebackObject *exception_keeper_tb_1;
160     NUITKA_MAY_BE_UNUSED int exception_keeper_lineno_1; 159     NUITKA_MAY_BE_UNUSED int exception_keeper_lineno_1;
n 161     PyObject *exception_keeper_type_2; n
162     PyObject *exception_keeper_value_2;
163     PyTracebackObject *exception_keeper_tb_2;
164     NUITKA_MAY_BE_UNUSED int exception_keeper_lineno_2;
165     PyObject *exception_keeper_type_3;
166     PyObject *exception_keeper_value_3;
167     PyTracebackObject *exception_keeper_tb_3;
168     NUITKA_MAY_BE_UNUSED int exception_keeper_lineno_3;
169     PyObject *exception_preserved_type_1;
170     PyObject *exception_preserved_value_1;
171     PyTracebackObject *exception_preserved_tb_1;
172     PyObject *tmp_args_element_name_1;
173     PyObject *tmp_assign_source_1; 160     PyObject *tmp_assign_source_1;
174     PyObject *tmp_assign_source_2; 161     PyObject *tmp_assign_source_2;
175     PyObject *tmp_assign_source_3; 162     PyObject *tmp_assign_source_3;
n 176     PyObject *tmp_assign_source_4; n
177     PyObject *tmp_called_name_1; 163     PyObject *tmp_called_name_1;
n 178     PyObject *tmp_called_name_2; n
179     PyObject *tmp_compare_left_1;
180     PyObject *tmp_compare_right_1;
181     int tmp_exc_match_exception_match_1;
182     bool tmp_result;
183     PyObject *tmp_return_value; 164     PyObject *tmp_return_value;
184     PyObject *tmp_source_name_1; 165     PyObject *tmp_source_name_1;
185     PyObject *tmp_tuple_element_1; 166     PyObject *tmp_tuple_element_1;
186     NUITKA_MAY_BE_UNUSED PyObject *tmp_unused; 167     NUITKA_MAY_BE_UNUSED PyObject *tmp_unused;
187     PyObject *tmp_value_name_1; 168     PyObject *tmp_value_name_1;
219 200
220         FETCH_ERROR_OCCURRED( &exception_type, &exception_value, &exception_tb ); 201         FETCH_ERROR_OCCURRED( &exception_type, &exception_value, &exception_tb );
221 202
222 203
223         exception_lineno = 27; 204         exception_lineno = 27;
n 224         type_description_1 = "oooo"; n 205         type_description_1 = "oooN";
225         goto frame_exception_exit_1; 206         goto frame_exception_exit_1;
226     } 207     }
227     assert( var_gen == NULL ); 208     assert( var_gen == NULL );
228     var_gen = tmp_assign_source_2; 209     var_gen = tmp_assign_source_2;
229 210
244         { 225         {
245             FETCH_ERROR_OCCURRED( &exception_type, &exception_value, &exception_tb ); 226             FETCH_ERROR_OCCURRED( &exception_type, &exception_value, &exception_tb );
246         } 227         }
247 228
248 229
n 249         type_description_1 = "oooo"; n 230         type_description_1 = "oooN";
250         exception_lineno = 29; 231         exception_lineno = 29;
251         goto frame_exception_exit_1; 232         goto frame_exception_exit_1;
252     } 233     }
253     Py_DECREF( tmp_unused ); 234     Py_DECREF( tmp_unused );
254     tmp_source_name_1 = var_gen; 235     tmp_source_name_1 = var_gen;
262         exception_tb = NULL; 243         exception_tb = NULL;
263         NORMALIZE_EXCEPTION( &exception_type, &exception_value, &exception_tb ); 244         NORMALIZE_EXCEPTION( &exception_type, &exception_value, &exception_tb );
264         CHAIN_EXCEPTION( exception_value ); 245         CHAIN_EXCEPTION( exception_value );
265 246
266         exception_lineno = 32; 247         exception_lineno = 32;
n 267         type_description_1 = "oooo"; n 248         type_description_1 = "oooN";
268         goto frame_exception_exit_1; 249         goto frame_exception_exit_1;
269     } 250     }
270 251
271     tmp_assign_source_3 = LOOKUP_ATTRIBUTE( tmp_source_name_1, const_str_plain_throw ); 252     tmp_assign_source_3 = LOOKUP_ATTRIBUTE( tmp_source_name_1, const_str_plain_throw );
272     if ( tmp_assign_source_3 == NULL ) 253     if ( tmp_assign_source_3 == NULL )
275 256
276         FETCH_ERROR_OCCURRED( &exception_type, &exception_value, &exception_tb ); 257         FETCH_ERROR_OCCURRED( &exception_type, &exception_value, &exception_tb );
277 258
278 259
279         exception_lineno = 32; 260         exception_lineno = 32;
n 280         type_description_1 = "oooo"; n 261         type_description_1 = "oooN";
281         goto frame_exception_exit_1; 262         goto frame_exception_exit_1;
282     } 263     }
283     assert( var_throw == NULL ); 264     assert( var_throw == NULL );
284     var_throw = tmp_assign_source_3; 265     var_throw = tmp_assign_source_3;
285 266
n 286     tmp_assign_source_4 = PyExc_GeneratorExit; n
287     assert( var_exc == NULL );
288     Py_INCREF( tmp_assign_source_4 );
289     var_exc = tmp_assign_source_4;
290 267
n 291     // Tried code: n 268 #if 0
292     tmp_called_name_2 = var_throw; 269     RESTORE_FRAME_EXCEPTION( frame_00847bd2dd5d50a5d6520b40c3514b19 );
270 #endif
293 271
n 294     CHECK_OBJECT( tmp_called_name_2 ); n 272     // Put the previous frame back on top.
295     tmp_args_element_name_1 = PyExc_GeneratorExit; 273     popFrameStack();
296     frame_00847bd2dd5d50a5d6520b40c3514b19->m_frame.f_lineno = 37; 274  
297     { 275     goto frame_no_exception_1;
298         PyObject *call_args[] = { tmp_args_element_name_1 }; 276  
299         tmp_unused = CALL_FUNCTION_WITH_ARGS1( tmp_called_name_2, call_args ); 277     frame_exception_exit_1:;
278  
279 #if 0
280     RESTORE_FRAME_EXCEPTION( frame_00847bd2dd5d50a5d6520b40c3514b19 );
281 #endif
282  
283     if ( exception_tb == NULL )
300     } 284     {
301   285         exception_tb = MAKE_TRACEBACK( frame_00847bd2dd5d50a5d6520b40c3514b19, exception_lineno );
302     if ( tmp_unused == NULL )
303     { 286     }
304         assert( ERROR_OCCURRED() ); 287     else if ( exception_tb->tb_frame != &frame_00847bd2dd5d50a5d6520b40c3514b19->m_frame )
288     {
289         exception_tb = ADD_TRACEBACK( exception_tb, frame_00847bd2dd5d50a5d6520b40c3514b19, exception_lineno );
290     }
305 291
n 306         FETCH_ERROR_OCCURRED( &exception_type, &exception_value, &exception_tb ); n 292     // Attachs locals to frame if any.
307   293     Nuitka_Frame_AttachLocals(
308   294         (struct Nuitka_FrameObject *)frame_00847bd2dd5d50a5d6520b40c3514b19,
309         exception_lineno = 37;
310         type_description_1 = "oooo"; 295         type_description_1,
296         var_generator,
297         var_gen,
298         var_throw,
299         NULL
300     );
301  
302  
303     // Release cached frame.
304     if ( frame_00847bd2dd5d50a5d6520b40c3514b19 == cache_frame_00847bd2dd5d50a5d6520b40c3514b19 )
305     {
306         Py_DECREF( frame_00847bd2dd5d50a5d6520b40c3514b19 );
307     }
308     cache_frame_00847bd2dd5d50a5d6520b40c3514b19 = NULL;
309  
310     assertFrameObject( frame_00847bd2dd5d50a5d6520b40c3514b19 );
311  
312     // Put the previous frame back on top.
313     popFrameStack();
314  
315     // Return the error.
311         goto try_except_handler_2; 316     goto try_except_handler_1;
312     } 317  
313     Py_DECREF( tmp_unused ); 318     frame_no_exception_1:;
319  
320     tmp_return_value = PyTuple_New( 2 );
321     tmp_tuple_element_1 = var_throw;
322  
323     CHECK_OBJECT( tmp_tuple_element_1 );
324     Py_INCREF( tmp_tuple_element_1 );
325     PyTuple_SET_ITEM( tmp_return_value, 0, tmp_tuple_element_1 );
326     tmp_tuple_element_1 = PyExc_GeneratorExit;
327     Py_INCREF( tmp_tuple_element_1 );
328     PyTuple_SET_ITEM( tmp_return_value, 1, tmp_tuple_element_1 );
314     goto try_end_1; 329     goto try_return_handler_1;
330     // tried codes exits in all cases
331     NUITKA_CANNOT_GET_HERE( __main__$$$function_1_calledRepeatedly );
332     return NULL;
333     // Return handler code:
334     try_return_handler_1:;
335     Py_XDECREF( var_generator );
336     var_generator = NULL;
337  
338     Py_XDECREF( var_gen );
339     var_gen = NULL;
340  
341     Py_XDECREF( var_throw );
342     var_throw = NULL;
343  
344     goto function_return_exit;
315     // Exception handler code: 345     // Exception handler code:
n 316     try_except_handler_2:; n 346     try_except_handler_1:;
317     exception_keeper_type_1 = exception_type; 347     exception_keeper_type_1 = exception_type;
318     exception_keeper_value_1 = exception_value; 348     exception_keeper_value_1 = exception_value;
319     exception_keeper_tb_1 = exception_tb; 349     exception_keeper_tb_1 = exception_tb;
320     exception_keeper_lineno_1 = exception_lineno; 350     exception_keeper_lineno_1 = exception_lineno;
321     exception_type = NULL; 351     exception_type = NULL;
322     exception_value = NULL; 352     exception_value = NULL;
323     exception_tb = NULL; 353     exception_tb = NULL;
324     exception_lineno = 0; 354     exception_lineno = 0;
325 355
n 326     // Preserve existing published exception. n
327     exception_preserved_type_1 = PyThreadState_GET()->exc_type;
328     Py_XINCREF( exception_preserved_type_1 );
329     exception_preserved_value_1 = PyThreadState_GET()->exc_value;
330     Py_XINCREF( exception_preserved_value_1 );
331     exception_preserved_tb_1 = (PyTracebackObject *)PyThreadState_GET()->exc_traceback;
332     Py_XINCREF( exception_preserved_tb_1 );
333  
334     if ( exception_keeper_tb_1 == NULL )
335     {
336         exception_keeper_tb_1 = MAKE_TRACEBACK( frame_00847bd2dd5d50a5d6520b40c3514b19, exception_keeper_lineno_1 );
337     }
338     else if ( exception_keeper_lineno_1 != 0 )
339     {
340         exception_keeper_tb_1 = ADD_TRACEBACK( exception_keeper_tb_1, frame_00847bd2dd5d50a5d6520b40c3514b19, exception_keeper_lineno_1 );
341     }
342  
343     NORMALIZE_EXCEPTION( &exception_keeper_type_1, &exception_keeper_value_1, &exception_keeper_tb_1 );
344     PyException_SetTraceback( exception_keeper_value_1, (PyObject *)exception_keeper_tb_1 );
345     PUBLISH_EXCEPTION( &exception_keeper_type_1, &exception_keeper_value_1, &exception_keeper_tb_1 );
346     // Tried code:
347     tmp_compare_left_1 = PyThreadState_GET()->exc_type;
348     tmp_compare_right_1 = var_exc;
349  
350     if ( tmp_compare_right_1 == NULL )
351     {
352  
353         exception_type = PyExc_UnboundLocalError;
354         Py_INCREF( exception_type );
355         exception_value = PyUnicode_FromFormat( "local variable '%s' referenced before assignment", "exc" );
356         exception_tb = NULL;
357         NORMALIZE_EXCEPTION( &exception_type, &exception_value, &exception_tb );
358         CHAIN_EXCEPTION( exception_value );
359  
360         exception_lineno = 41;
361         type_description_1 = "oooo";
362         goto try_except_handler_3;
363     }
364  
365     tmp_exc_match_exception_match_1 = EXCEPTION_MATCH_BOOL( tmp_compare_left_1, tmp_compare_right_1 );
366     if ( tmp_exc_match_exception_match_1 == -1 )
367     {
368         assert( ERROR_OCCURRED() );
369  
370         FETCH_ERROR_OCCURRED( &exception_type, &exception_value, &exception_tb );
371  
372  
373         exception_lineno = 41;
374         type_description_1 = "oooo";
375         goto try_except_handler_3;
376     }
377     if ( tmp_exc_match_exception_match_1 == 1 )
378     {
379         goto branch_no_1;
380     }
381     else
382     {
383         goto branch_yes_1;
384     }
385     branch_yes_1:;
386     tmp_result = RERAISE_EXCEPTION( &exception_type, &exception_value, &exception_tb );
387     if (unlikely( tmp_result == false ))
388     {
389         exception_lineno = 35;
390     }
391  
392     if (exception_tb && exception_tb->tb_frame == &frame_00847bd2dd5d50a5d6520b40c3514b19->m_frame) frame_00847bd2dd5d50a5d6520b40c3514b19->m_frame.f_lineno = exception_tb->tb_lineno;
393     type_description_1 = "oooo";
394     goto try_except_handler_3;
395     branch_no_1:;
396     goto try_end_2;
397     // Exception handler code:
398     try_except_handler_3:;
399     exception_keeper_type_2 = exception_type;
400     exception_keeper_value_2 = exception_value;
401     exception_keeper_tb_2 = exception_tb;
402     exception_keeper_lineno_2 = exception_lineno;
403     exception_type = NULL;
404     exception_value = NULL;
405     exception_tb = NULL;
406     exception_lineno = 0;
407  
408     // Restore previous exception.
409     SET_CURRENT_EXCEPTION( exception_preserved_type_1, exception_preserved_value_1, exception_preserved_tb_1 );
410     // Re-raise.
411     exception_type = exception_keeper_type_2;
412     exception_value = exception_keeper_value_2;
413     exception_tb = exception_keeper_tb_2;
414     exception_lineno = exception_keeper_lineno_2;
415  
416     goto frame_exception_exit_1;
417     // End of try:
418     try_end_2:;
419     // Restore previous exception.
420     SET_CURRENT_EXCEPTION( exception_preserved_type_1, exception_preserved_value_1, exception_preserved_tb_1 );
421     goto try_end_1;
422     // exception handler codes exits in all cases
423     NUITKA_CANNOT_GET_HERE( __main__$$$function_1_calledRepeatedly );
424     return NULL;
425     // End of try:
426     try_end_1:;
427     tmp_return_value = PyTuple_New( 2 );
428     tmp_tuple_element_1 = var_throw;
429  
430     if ( tmp_tuple_element_1 == NULL )
431     {
432         Py_DECREF( tmp_return_value );
433         exception_type = PyExc_UnboundLocalError;
434         Py_INCREF( exception_type );
435         exception_value = PyUnicode_FromFormat( "local variable '%s' referenced before assignment", "throw" );
436         exception_tb = NULL;
437         NORMALIZE_EXCEPTION( &exception_type, &exception_value, &exception_tb );
438         CHAIN_EXCEPTION( exception_value );
439  
440         exception_lineno = 44;
441         type_description_1 = "oooo";
442         goto frame_exception_exit_1;
443     }
444  
445     Py_INCREF( tmp_tuple_element_1 );
446     PyTuple_SET_ITEM( tmp_return_value, 0, tmp_tuple_element_1 );
447     tmp_tuple_element_1 = var_exc;
448  
449     if ( tmp_tuple_element_1 == NULL )
450     {
451         Py_DECREF( tmp_return_value );
452         exception_type = PyExc_UnboundLocalError;
453         Py_INCREF( exception_type );
454         exception_value = PyUnicode_FromFormat( "local variable '%s' referenced before assignment", "exc" );
455         exception_tb = NULL;
456         NORMALIZE_EXCEPTION( &exception_type, &exception_value, &exception_tb );
457         CHAIN_EXCEPTION( exception_value );
458  
459         exception_lineno = 44;
460         type_description_1 = "oooo";
461         goto frame_exception_exit_1;
462     }
463  
464     Py_INCREF( tmp_tuple_element_1 );
465     PyTuple_SET_ITEM( tmp_return_value, 1, tmp_tuple_element_1 );
466     goto frame_return_exit_1;
467  
468 #if 1
469     RESTORE_FRAME_EXCEPTION( frame_00847bd2dd5d50a5d6520b40c3514b19 );
470 #endif
471  
472     // Put the previous frame back on top.
473     popFrameStack();
474  
475     goto frame_no_exception_1;
476  
477     frame_return_exit_1:;
478 #if 1
479     RESTORE_FRAME_EXCEPTION( frame_00847bd2dd5d50a5d6520b40c3514b19 );
480 #endif
481  
482     // Put the previous frame back on top.
483     popFrameStack();
484  
485     goto try_return_handler_1;
486  
487     frame_exception_exit_1:;
488  
489 #if 1
490     RESTORE_FRAME_EXCEPTION( frame_00847bd2dd5d50a5d6520b40c3514b19 );
491 #endif
492  
493     if ( exception_tb == NULL )
494     {
495         exception_tb = MAKE_TRACEBACK( frame_00847bd2dd5d50a5d6520b40c3514b19, exception_lineno );
496     }
497     else if ( exception_tb->tb_frame != &frame_00847bd2dd5d50a5d6520b40c3514b19->m_frame )
498     {
499         exception_tb = ADD_TRACEBACK( exception_tb, frame_00847bd2dd5d50a5d6520b40c3514b19, exception_lineno );
500     }
501  
502     // Attachs locals to frame if any.
503     Nuitka_Frame_AttachLocals(
504         (struct Nuitka_FrameObject *)frame_00847bd2dd5d50a5d6520b40c3514b19,
505         type_description_1,
506         var_generator,
507         var_gen,
508         var_throw,
509         var_exc
510     );
511  
512  
513     // Release cached frame.
514     if ( frame_00847bd2dd5d50a5d6520b40c3514b19 == cache_frame_00847bd2dd5d50a5d6520b40c3514b19 )
515     {
516         Py_DECREF( frame_00847bd2dd5d50a5d6520b40c3514b19 );
517     }
518     cache_frame_00847bd2dd5d50a5d6520b40c3514b19 = NULL;
519  
520     assertFrameObject( frame_00847bd2dd5d50a5d6520b40c3514b19 );
521  
522     // Put the previous frame back on top.
523     popFrameStack();
524  
525     // Return the error.
526     goto try_except_handler_1;
527  
528     frame_no_exception_1:;
529  
530     // tried codes exits in all cases
531     NUITKA_CANNOT_GET_HERE( __main__$$$function_1_calledRepeatedly );
532     return NULL;
533     // Return handler code:
534     try_return_handler_1:;
535     Py_XDECREF( var_generator ); 356     Py_XDECREF( var_generator );
536     var_generator = NULL; 357     var_generator = NULL;
537 358
538     Py_XDECREF( var_gen ); 359     Py_XDECREF( var_gen );
539     var_gen = NULL; 360     var_gen = NULL;
540 361
n 541     Py_XDECREF( var_throw ); n
542     var_throw = NULL;
543  
544     Py_XDECREF( var_exc );
545     var_exc = NULL;
546  
547     goto function_return_exit;
548     // Exception handler code:
549     try_except_handler_1:;
550     exception_keeper_type_3 = exception_type;
551     exception_keeper_value_3 = exception_value;
552     exception_keeper_tb_3 = exception_tb;
553     exception_keeper_lineno_3 = exception_lineno;
554     exception_type = NULL;
555     exception_value = NULL;
556     exception_tb = NULL;
557     exception_lineno = 0;
558  
559     Py_XDECREF( var_generator );
560     var_generator = NULL;
561  
562     Py_XDECREF( var_gen );
563     var_gen = NULL;
564  
565     Py_XDECREF( var_throw );
566     var_throw = NULL;
567  
568     Py_XDECREF( var_exc );
569     var_exc = NULL;
570  
571     // Re-raise. 362     // Re-raise.
t 572     exception_type = exception_keeper_type_3; t 363     exception_type = exception_keeper_type_1;
573     exception_value = exception_keeper_value_3; 364     exception_value = exception_keeper_value_1;
574     exception_tb = exception_keeper_tb_3; 365     exception_tb = exception_keeper_tb_1;
575     exception_lineno = exception_keeper_lineno_3; 366     exception_lineno = exception_keeper_lineno_1;
576 367
577     goto function_exception_exit; 368     goto function_exception_exit;
578     // End of try: 369     // End of try:
579 370
580     // Return statement must have exited already. 371     // Return statement must have exited already.