Construct GeneratorExit

Performance Diagrams

Construct GeneratorExit 002000000020000000400000004000000060000000600000008000000080000000100000000100000000120000000120000000140000000140000000160000000160000000180000000180000000200000000200000000220000000220000000240000000240000000260000000260000000280000000280000000300000000300000000CPython 2.7Nuitka (historic)Nuitka (master)Nuitka (develop)Nuitka (factory)31351282472.9230769230769257.0CPython 2.70194.46153846153845504.11538461538464Nuitka (historic)166054169316.0373.2290645093112Nuitka (master)166054162437.53846153846143373.22907002681336Nuitka (develop)166054144559.0769230769231373.2290842146761Nuitka (factory)Construct GeneratorExitTicks Construct GeneratorExit 0010000000100000002000000020000000300000003000000040000000400000005000000050000000600000006000000070000000700000008000000080000000CPython 3.5Nuitka (historic)Nuitka (master)Nuitka (develop)Nuitka (factory)8177097973.61538461538461257.0CPython 3.50196.30769230769232504.11538461538464Nuitka (historic)74397669319.0000000000001279.2824571604855Nuitka (master)74403447441.69230769230774279.26499579815663Nuitka (develop)74403441564.3846153846155279.2650139304124Nuitka (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


for x in xrange(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


for x in xrange(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
135 135
136     // Local variable declarations. 136     // Local variable declarations.
137     PyObject *var_generator = NULL; 137     PyObject *var_generator = NULL;
138     PyObject *var_gen = NULL; 138     PyObject *var_gen = NULL;
139     PyObject *var_throw = NULL; 139     PyObject *var_throw = NULL;
n 140     PyObject *var_exc = NULL; n
141     PyObject *exception_type = NULL, *exception_value = NULL; 140     PyObject *exception_type = NULL, *exception_value = NULL;
142     PyTracebackObject *exception_tb = NULL; 141     PyTracebackObject *exception_tb = NULL;
143     NUITKA_MAY_BE_UNUSED int exception_lineno = -1; 142     NUITKA_MAY_BE_UNUSED int exception_lineno = -1;
144     PyObject *exception_keeper_type_1; 143     PyObject *exception_keeper_type_1;
145     PyObject *exception_keeper_value_1; 144     PyObject *exception_keeper_value_1;
146     PyTracebackObject *exception_keeper_tb_1; 145     PyTracebackObject *exception_keeper_tb_1;
147     NUITKA_MAY_BE_UNUSED int exception_keeper_lineno_1; 146     NUITKA_MAY_BE_UNUSED int exception_keeper_lineno_1;
n 148     PyObject *exception_keeper_type_2; n
149     PyObject *exception_keeper_value_2;
150     PyTracebackObject *exception_keeper_tb_2;
151     NUITKA_MAY_BE_UNUSED int exception_keeper_lineno_2;
152     PyObject *exception_keeper_type_3;
153     PyObject *exception_keeper_value_3;
154     PyTracebackObject *exception_keeper_tb_3;
155     NUITKA_MAY_BE_UNUSED int exception_keeper_lineno_3;
156     PyObject *exception_preserved_type_1;
157     PyObject *exception_preserved_value_1;
158     PyTracebackObject *exception_preserved_tb_1;
159     PyObject *tmp_args_element_name_1;
160     PyObject *tmp_assign_source_1; 147     PyObject *tmp_assign_source_1;
161     PyObject *tmp_assign_source_2; 148     PyObject *tmp_assign_source_2;
162     PyObject *tmp_assign_source_3; 149     PyObject *tmp_assign_source_3;
n 163     PyObject *tmp_assign_source_4; n
164     PyObject *tmp_called_name_1; 150     PyObject *tmp_called_name_1;
n 165     PyObject *tmp_called_name_2; n
166     PyObject *tmp_compare_left_1;
167     PyObject *tmp_compare_right_1;
168     int tmp_exc_match_exception_match_1;
169     PyObject *tmp_frame_locals; 151     PyObject *tmp_frame_locals;
170     PyObject *tmp_return_value; 152     PyObject *tmp_return_value;
171     PyObject *tmp_source_name_1; 153     PyObject *tmp_source_name_1;
172     PyObject *tmp_tuple_element_1; 154     PyObject *tmp_tuple_element_1;
173     NUITKA_MAY_BE_UNUSED PyObject *tmp_unused; 155     NUITKA_MAY_BE_UNUSED PyObject *tmp_unused;
266         goto frame_exception_exit_1; 248         goto frame_exception_exit_1;
267     } 249     }
268     assert( var_throw == NULL ); 250     assert( var_throw == NULL );
269     var_throw = tmp_assign_source_3; 251     var_throw = tmp_assign_source_3;
270 252
n 271     tmp_assign_source_4 = PyExc_GeneratorExit; n
272     assert( var_exc == NULL );
273     Py_INCREF( tmp_assign_source_4 );
274     var_exc = tmp_assign_source_4;
275 253
n 276     // Tried code: n
277     tmp_called_name_2 = var_throw;
278  
279     tmp_args_element_name_1 = PyExc_GeneratorExit;
280     frame_function->f_lineno = 37;
281     {
282         PyObject *call_args[] = { tmp_args_element_name_1 };
283         tmp_unused = CALL_FUNCTION_WITH_ARGS1( tmp_called_name_2, call_args );
284     }
285  
286     if ( tmp_unused == NULL )
287     {
288         assert( ERROR_OCCURRED() );
289  
290         FETCH_ERROR_OCCURRED( &exception_type, &exception_value, &exception_tb );
291  
292  
293         exception_lineno = 37;
294         goto try_except_handler_2;
295     }
296     Py_DECREF( tmp_unused );
297     goto try_end_1;
298     // Exception handler code:
299     try_except_handler_2:;
300     exception_keeper_type_1 = exception_type;
301     exception_keeper_value_1 = exception_value;
302     exception_keeper_tb_1 = exception_tb;
303     exception_keeper_lineno_1 = exception_lineno;
304     exception_type = NULL;
305     exception_value = NULL;
306     exception_tb = NULL;
307     exception_lineno = -1;
308  
309     // Preserve existing published exception.
310     exception_preserved_type_1 = PyThreadState_GET()->exc_type;
311     Py_XINCREF( exception_preserved_type_1 );
312     exception_preserved_value_1 = PyThreadState_GET()->exc_value;
313     Py_XINCREF( exception_preserved_value_1 );
314     exception_preserved_tb_1 = (PyTracebackObject *)PyThreadState_GET()->exc_traceback;
315     Py_XINCREF( exception_preserved_tb_1 );
316  
317     if ( exception_keeper_tb_1 == NULL )
318     {
319         exception_keeper_tb_1 = MAKE_TRACEBACK( frame_function, exception_keeper_lineno_1 );
320     }
321     else if ( exception_keeper_lineno_1 != -1 )
322     {
323         exception_keeper_tb_1 = ADD_TRACEBACK( exception_keeper_tb_1, frame_function, exception_keeper_lineno_1 );
324     }
325  
326     NORMALIZE_EXCEPTION( &exception_keeper_type_1, &exception_keeper_value_1, &exception_keeper_tb_1 );
327     PyException_SetTraceback( exception_keeper_value_1, (PyObject *)exception_keeper_tb_1 );
328     PUBLISH_EXCEPTION( &exception_keeper_type_1, &exception_keeper_value_1, &exception_keeper_tb_1 );
329     // Tried code:
330     tmp_compare_left_1 = PyThreadState_GET()->exc_type;
331     tmp_compare_right_1 = var_exc;
332  
333     if ( tmp_compare_right_1 == NULL )
334     {
335  
336         exception_type = PyExc_UnboundLocalError;
337         Py_INCREF( exception_type );
338         exception_value = PyUnicode_FromFormat( "local variable '%s' referenced before assignment", "exc" );
339         exception_tb = NULL;
340         NORMALIZE_EXCEPTION( &exception_type, &exception_value, &exception_tb );
341         CHAIN_EXCEPTION( exception_value );
342  
343         exception_lineno = 41;
344         goto try_except_handler_3;
345     }
346  
347     tmp_exc_match_exception_match_1 = EXCEPTION_MATCH_BOOL( tmp_compare_left_1, tmp_compare_right_1 );
348     if ( tmp_exc_match_exception_match_1 == -1 )
349     {
350         assert( ERROR_OCCURRED() );
351  
352         FETCH_ERROR_OCCURRED( &exception_type, &exception_value, &exception_tb );
353  
354  
355         exception_lineno = 41;
356         goto try_except_handler_3;
357     }
358     if ( tmp_exc_match_exception_match_1 == 1 )
359     {
360         goto branch_no_1;
361     }
362     else
363     {
364         goto branch_yes_1;
365     }
366     branch_yes_1:;
367     RERAISE_EXCEPTION( &exception_type, &exception_value, &exception_tb );
368     if (exception_tb && exception_tb->tb_frame == frame_function) frame_function->f_lineno = exception_tb->tb_lineno;
369     goto try_except_handler_3;
370     branch_no_1:;
371     goto try_end_2;
372     // Exception handler code:
373     try_except_handler_3:;
374     exception_keeper_type_2 = exception_type;
375     exception_keeper_value_2 = exception_value;
376     exception_keeper_tb_2 = exception_tb;
377     exception_keeper_lineno_2 = exception_lineno;
378     exception_type = NULL;
379     exception_value = NULL;
380     exception_tb = NULL;
381     exception_lineno = -1;
382  
383     // Restore previous exception.
384     SET_CURRENT_EXCEPTION( exception_preserved_type_1, exception_preserved_value_1, exception_preserved_tb_1 );
385     // Re-raise.
386     exception_type = exception_keeper_type_2;
387     exception_value = exception_keeper_value_2;
388     exception_tb = exception_keeper_tb_2;
389     exception_lineno = exception_keeper_lineno_2;
390  
391     goto frame_exception_exit_1;
392     // End of try:
393     try_end_2:;
394     // Restore previous exception.
395     SET_CURRENT_EXCEPTION( exception_preserved_type_1, exception_preserved_value_1, exception_preserved_tb_1 );
396     goto try_end_1;
397     // exception handler codes exits in all cases
398     NUITKA_CANNOT_GET_HERE( __main__$$$function_1_calledRepeatedly );
399     return NULL;
400     // End of try:
401     try_end_1:;
402     tmp_return_value = PyTuple_New( 2 );
403     tmp_tuple_element_1 = var_throw;
404  
405     if ( tmp_tuple_element_1 == NULL )
406     {
407         Py_DECREF( tmp_return_value );
408         exception_type = PyExc_UnboundLocalError;
409         Py_INCREF( exception_type );
410         exception_value = PyUnicode_FromFormat( "local variable '%s' referenced before assignment", "throw" );
411         exception_tb = NULL;
412         NORMALIZE_EXCEPTION( &exception_type, &exception_value, &exception_tb );
413         CHAIN_EXCEPTION( exception_value );
414  
415         exception_lineno = 44;
416         goto frame_exception_exit_1;
417     }
418  
419     Py_INCREF( tmp_tuple_element_1 );
420     PyTuple_SET_ITEM( tmp_return_value, 0, tmp_tuple_element_1 );
421     tmp_tuple_element_1 = var_exc;
422  
423     if ( tmp_tuple_element_1 == NULL )
424     {
425         Py_DECREF( tmp_return_value );
426         exception_type = PyExc_UnboundLocalError;
427         Py_INCREF( exception_type );
428         exception_value = PyUnicode_FromFormat( "local variable '%s' referenced before assignment", "exc" );
429         exception_tb = NULL;
430         NORMALIZE_EXCEPTION( &exception_type, &exception_value, &exception_tb );
431         CHAIN_EXCEPTION( exception_value );
432  
433         exception_lineno = 44;
434         goto frame_exception_exit_1;
435     }
436  
437     Py_INCREF( tmp_tuple_element_1 );
438     PyTuple_SET_ITEM( tmp_return_value, 1, tmp_tuple_element_1 );
439     goto frame_return_exit_1;
440  
441 #if 1 254 #if 0
442     RESTORE_FRAME_EXCEPTION( frame_function ); 255     RESTORE_FRAME_EXCEPTION( frame_function );
443 #endif 256 #endif
444     // Put the previous frame back on top. 257     // Put the previous frame back on top.
445     popFrameStack(); 258     popFrameStack();
446 #if PYTHON_VERSION >= 340 259 #if PYTHON_VERSION >= 340
447     frame_function->f_executing -= 1; 260     frame_function->f_executing -= 1;
448 #endif 261 #endif
449     Py_DECREF( frame_function ); 262     Py_DECREF( frame_function );
450     goto frame_no_exception_1; 263     goto frame_no_exception_1;
451 264
n 452     frame_return_exit_1:; n
453 #if 1
454     RESTORE_FRAME_EXCEPTION( frame_function );
455 #endif
456     popFrameStack();
457 #if PYTHON_VERSION >= 340
458     frame_function->f_executing -= 1;
459 #endif
460     Py_DECREF( frame_function );
461     goto try_return_handler_1;
462  
463     frame_exception_exit_1:; 265     frame_exception_exit_1:;
n 464 #if 1 n 266 #if 0
465     RESTORE_FRAME_EXCEPTION( frame_function ); 267     RESTORE_FRAME_EXCEPTION( frame_function );
466 #endif 268 #endif
467 269
468     { 270     {
469         bool needs_detach = false; 271         bool needs_detach = false;
517                 ); 319                 );
518 320
519                 assert( res == 0 ); 321                 assert( res == 0 );
520             } 322             }
521 323
n 522             if ( var_exc ) n
523             {
524                 int res = PyDict_SetItem(
525                     tmp_frame_locals,
526                     const_str_plain_exc,
527                     var_exc
528                 );
529  
530                 assert( res == 0 );
531             }
532  
533 324
534 325
535             detachFrame( exception_tb, tmp_frame_locals ); 326             detachFrame( exception_tb, tmp_frame_locals );
536         } 327         }
537     } 328     }
546     // Return the error. 337     // Return the error.
547     goto try_except_handler_1; 338     goto try_except_handler_1;
548 339
549     frame_no_exception_1:; 340     frame_no_exception_1:;
550 341
n n 342     tmp_return_value = PyTuple_New( 2 );
343     tmp_tuple_element_1 = var_throw;
344  
345     Py_INCREF( tmp_tuple_element_1 );
346     PyTuple_SET_ITEM( tmp_return_value, 0, tmp_tuple_element_1 );
347     tmp_tuple_element_1 = PyExc_GeneratorExit;
348     Py_INCREF( tmp_tuple_element_1 );
349     PyTuple_SET_ITEM( tmp_return_value, 1, tmp_tuple_element_1 );
350     goto try_return_handler_1;
551     // tried codes exits in all cases 351     // tried codes exits in all cases
552     NUITKA_CANNOT_GET_HERE( __main__$$$function_1_calledRepeatedly ); 352     NUITKA_CANNOT_GET_HERE( __main__$$$function_1_calledRepeatedly );
553     return NULL; 353     return NULL;
554     // Return handler code: 354     // Return handler code:
555     try_return_handler_1:; 355     try_return_handler_1:;
560     var_gen = NULL; 360     var_gen = NULL;
561 361
562     Py_XDECREF( var_throw ); 362     Py_XDECREF( var_throw );
563     var_throw = NULL; 363     var_throw = NULL;
564 364
n 565     Py_XDECREF( var_exc ); n
566     var_exc = NULL;
567  
568     goto function_return_exit; 365     goto function_return_exit;
569     // Exception handler code: 366     // Exception handler code:
570     try_except_handler_1:; 367     try_except_handler_1:;
n 571     exception_keeper_type_3 = exception_type; n 368     exception_keeper_type_1 = exception_type;
572     exception_keeper_value_3 = exception_value; 369     exception_keeper_value_1 = exception_value;
573     exception_keeper_tb_3 = exception_tb; 370     exception_keeper_tb_1 = exception_tb;
574     exception_keeper_lineno_3 = exception_lineno; 371     exception_keeper_lineno_1 = exception_lineno;
575     exception_type = NULL; 372     exception_type = NULL;
576     exception_value = NULL; 373     exception_value = NULL;
577     exception_tb = NULL; 374     exception_tb = NULL;
578     exception_lineno = -1; 375     exception_lineno = -1;
579 376
581     var_generator = NULL; 378     var_generator = NULL;
582 379
583     Py_XDECREF( var_gen ); 380     Py_XDECREF( var_gen );
584     var_gen = NULL; 381     var_gen = NULL;
585 382
n 586     Py_XDECREF( var_throw ); n
587     var_throw = NULL;
588  
589     Py_XDECREF( var_exc );
590     var_exc = NULL;
591  
592     // Re-raise. 383     // Re-raise.
t 593     exception_type = exception_keeper_type_3; t 384     exception_type = exception_keeper_type_1;
594     exception_value = exception_keeper_value_3; 385     exception_value = exception_keeper_value_1;
595     exception_tb = exception_keeper_tb_3; 386     exception_tb = exception_keeper_tb_1;
596     exception_lineno = exception_keeper_lineno_3; 387     exception_lineno = exception_keeper_lineno_1;
597 388
598     goto function_exception_exit; 389     goto function_exception_exit;
599     // End of try: 390     // End of try:
600 391
601     // Return statement must have exited already. 392     // Return statement must have exited already.