Construct GeneratorExpressionExit

Performance Diagrams

Construct GeneratorExpressionExit 002000000020000000400000004000000060000000600000008000000080000000100000000100000000120000000120000000140000000140000000160000000160000000180000000180000000200000000200000000220000000220000000240000000240000000260000000260000000280000000280000000300000000300000000CPython 2.7Nuitka (historic)Nuitka (master)Nuitka (develop)Nuitka (factory)31311278472.9230769230769257.0CPython 2.70194.46153846153845504.11538461538464Nuitka (historic)164803271316.0374.04907694575445Nuitka (master)166003307437.53846153846143373.1019825668411Nuitka (develop)166003277559.0769230769231373.1020062434903Nuitka (factory)Construct GeneratorExpressionExitTicks Construct GeneratorExpressionExit 0010000000100000002000000020000000300000003000000040000000400000005000000050000000600000006000000070000000700000008000000080000000CPython 3.5Nuitka (historic)Nuitka (master)Nuitka (develop)Nuitka (factory)8137075573.61538461538461257.0CPython 3.50196.30769230769232504.11538461538464Nuitka (historic)74898903319.0000000000001276.6544101889413Nuitka (master)74500545441.69230769230774277.8641862366702Nuitka (develop)74506301564.3846153846155277.8467058021597Nuitka (factory)Construct GeneratorExpressionExitTicks

Source Code with Construct

def calledRepeatedly():
    # We measure making a generator iterator step or not.
    gen = (x for x in range(3))

    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.
    gen = (x for x in range(3))

    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
27     throw = gen.throw 27     throw = gen.throw
28     exc = GeneratorExit 28     exc = GeneratorExit
29 29
30     try: 30     try:
31 # construct_begin 31 # construct_begin
n 32         throw(exc) n 32  
33 # construct_alternative 33 # construct_alternative
t 34   t 34         pass
35   35 # construct_end
36     except exc: 36     except exc:
37         pass 37         pass
38 38
39     return throw, exc 39     return throw, exc
40 40

Context Diff of Generated Code


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