Construct GeneratorExpressionExit

Performance Diagrams

Construct GeneratorExpressionExit 002000000020000000400000004000000060000000600000008000000080000000100000000100000000120000000120000000140000000140000000160000000160000000180000000180000000200000000200000000220000000220000000240000000240000000260000000260000000280000000280000000300000000300000000CPython 2.7Nuitka (historic)Nuitka (master)Nuitka (develop)Nuitka (factory)31311278472.9230769230769257.0CPython 2.70194.46153846153845504.11538461538464Nuitka (historic)166003271316.0373.1020109788201Nuitka (master)166003523437.53846153846143373.10181209496704Nuitka (develop)166003565559.0769230769231373.1017789476582Nuitka (factory)Construct GeneratorExpressionExitTicks Construct GeneratorExpressionExit 0010000000100000002000000020000000300000003000000040000000400000005000000050000000600000006000000070000000700000008000000080000000CPython 3.5Nuitka (historic)Nuitka (master)Nuitka (develop)Nuitka (factory)8137075573.61538461538461257.0CPython 3.50196.30769230769232504.11538461538464Nuitka (historic)74499707319.0000000000001277.86673116441864Nuitka (master)74522838441.69230769230774277.7964844773682Nuitka (develop)74480362564.3846153846155277.9254801230019Nuitka (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
139 #endif 139 #endif
140 140
141     // Local variable declarations. 141     // Local variable declarations.
142     PyObject *var_gen = NULL; 142     PyObject *var_gen = NULL;
143     PyObject *var_throw = NULL; 143     PyObject *var_throw = NULL;
n 144     PyObject *var_exc = NULL; n
145     PyObject *exception_type = NULL, *exception_value = NULL; 144     PyObject *exception_type = NULL, *exception_value = NULL;
146     PyTracebackObject *exception_tb = NULL; 145     PyTracebackObject *exception_tb = NULL;
147     NUITKA_MAY_BE_UNUSED int exception_lineno = -1; 146     NUITKA_MAY_BE_UNUSED int exception_lineno = -1;
148     PyObject *exception_keeper_type_1; 147     PyObject *exception_keeper_type_1;
149     PyObject *exception_keeper_value_1; 148     PyObject *exception_keeper_value_1;
150     PyTracebackObject *exception_keeper_tb_1; 149     PyTracebackObject *exception_keeper_tb_1;
151     NUITKA_MAY_BE_UNUSED int exception_keeper_lineno_1; 150     NUITKA_MAY_BE_UNUSED int exception_keeper_lineno_1;
n 152     PyObject *exception_keeper_type_2; n
153     PyObject *exception_keeper_value_2;
154     PyTracebackObject *exception_keeper_tb_2;
155     NUITKA_MAY_BE_UNUSED int exception_keeper_lineno_2;
156     PyObject *exception_keeper_type_3;
157     PyObject *exception_keeper_value_3;
158     PyTracebackObject *exception_keeper_tb_3;
159     NUITKA_MAY_BE_UNUSED int exception_keeper_lineno_3;
160     PyObject *exception_preserved_type_1;
161     PyObject *exception_preserved_value_1;
162     PyTracebackObject *exception_preserved_tb_1;
163     PyObject *tmp_args_element_name_1;
164     PyObject *tmp_assign_source_1; 151     PyObject *tmp_assign_source_1;
165     PyObject *tmp_assign_source_2; 152     PyObject *tmp_assign_source_2;
n 166     PyObject *tmp_assign_source_3; n
167     PyObject *tmp_called_name_1;
168     PyObject *tmp_compare_left_1;
169     PyObject *tmp_compare_right_1;
170     PyObject *tmp_dircall_arg1_1; 153     PyObject *tmp_dircall_arg1_1;
n 171     int tmp_exc_match_exception_match_1; n
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;
176     NUITKA_MAY_BE_UNUSED PyObject *tmp_unused; 158     NUITKA_MAY_BE_UNUSED PyObject *tmp_unused;
194     assert( tmp_assign_source_1 != NULL ); 176     assert( tmp_assign_source_1 != NULL );
195     assert( var_gen == NULL ); 177     assert( var_gen == NULL );
196     var_gen = tmp_assign_source_1; 178     var_gen = tmp_assign_source_1;
197 179
198     // Tried code: 180     // Tried code:
n 199     MAKE_OR_REUSE_FRAME( cache_frame_function, codeobj_c9a1497f79c5a9848337ce6e8a5b74a7, module___main__, sizeof(PyObject *)+sizeof(PyObject *)+sizeof(PyObject *) ); n 181     MAKE_OR_REUSE_FRAME( cache_frame_function, codeobj_c9a1497f79c5a9848337ce6e8a5b74a7, module___main__, sizeof(void *)+sizeof(PyObject *)+sizeof(PyObject *) );
200     frame_function = cache_frame_function; 182     frame_function = cache_frame_function;
201 183
202     // Push the new frame as the currently active one. 184     // Push the new frame as the currently active one.
203     pushFrameStack( frame_function ); 185     pushFrameStack( frame_function );
204 186
222         { 204         {
223             FETCH_ERROR_OCCURRED( &exception_type, &exception_value, &exception_tb ); 205             FETCH_ERROR_OCCURRED( &exception_type, &exception_value, &exception_tb );
224         } 206         }
225 207
226 208
n 227         type_description = "ooo"; n 209         type_description = "ooN";
228         exception_lineno = 24; 210         exception_lineno = 24;
229         goto frame_exception_exit_1; 211         goto frame_exception_exit_1;
230     } 212     }
231     Py_DECREF( tmp_unused ); 213     Py_DECREF( tmp_unused );
232     tmp_source_name_1 = var_gen; 214     tmp_source_name_1 = var_gen;
240         exception_tb = NULL; 222         exception_tb = NULL;
241         NORMALIZE_EXCEPTION( &exception_type, &exception_value, &exception_tb ); 223         NORMALIZE_EXCEPTION( &exception_type, &exception_value, &exception_tb );
242         CHAIN_EXCEPTION( exception_value ); 224         CHAIN_EXCEPTION( exception_value );
243 225
244         exception_lineno = 27; 226         exception_lineno = 27;
n 245         type_description = "ooo"; n 227         type_description = "ooN";
246         goto frame_exception_exit_1; 228         goto frame_exception_exit_1;
247     } 229     }
248 230
249     tmp_assign_source_2 = LOOKUP_ATTRIBUTE( tmp_source_name_1, const_str_plain_throw ); 231     tmp_assign_source_2 = LOOKUP_ATTRIBUTE( tmp_source_name_1, const_str_plain_throw );
250     if ( tmp_assign_source_2 == NULL ) 232     if ( tmp_assign_source_2 == NULL )
253 235
254         FETCH_ERROR_OCCURRED( &exception_type, &exception_value, &exception_tb ); 236         FETCH_ERROR_OCCURRED( &exception_type, &exception_value, &exception_tb );
255 237
256 238
257         exception_lineno = 27; 239         exception_lineno = 27;
n 258         type_description = "ooo"; n 240         type_description = "ooN";
259         goto frame_exception_exit_1; 241         goto frame_exception_exit_1;
260     } 242     }
261     assert( var_throw == NULL ); 243     assert( var_throw == NULL );
262     var_throw = tmp_assign_source_2; 244     var_throw = tmp_assign_source_2;
263 245
n 264     tmp_assign_source_3 = PyExc_GeneratorExit; n
265     assert( var_exc == NULL );
266     Py_INCREF( tmp_assign_source_3 );
267     var_exc = tmp_assign_source_3;
268 246
n 269     // Tried code: n 247 #if 0
270     tmp_called_name_1 = var_throw; 248     RESTORE_FRAME_EXCEPTION( frame_function );
249 #endif
271 250
n 272     tmp_args_element_name_1 = PyExc_GeneratorExit; n 251     // Put the previous frame back on top.
273     frame_function->m_frame.f_lineno = 32; 252     popFrameStack();
274     { 253  
275         PyObject *call_args[] = { tmp_args_element_name_1 }; 254     goto frame_no_exception_1;
276         tmp_unused = CALL_FUNCTION_WITH_ARGS1( tmp_called_name_1, call_args ); 255  
256     frame_exception_exit_1:;
257  
258 #if 0
259     RESTORE_FRAME_EXCEPTION( frame_function );
260 #endif
261  
262     if ( exception_tb == NULL )
277     } 263     {
278   264         exception_tb = MAKE_TRACEBACK( frame_function, exception_lineno );
279     if ( tmp_unused == NULL )
280     { 265     }
281         assert( ERROR_OCCURRED() ); 266     else if ( exception_tb->tb_frame != &frame_function->m_frame )
267     {
268         exception_tb = ADD_TRACEBACK( exception_tb, frame_function, exception_lineno );
269     }
282 270
n 283         FETCH_ERROR_OCCURRED( &exception_type, &exception_value, &exception_tb ); n 271     Nuitka_Frame_AttachLocals( (struct Nuitka_FrameObject *)frame_function, type_description ,var_gen, var_throw, NULL );
284 272
n n 273     // Release cached frame.
274     if ( frame_function == cache_frame_function )
275     {
276         Py_DECREF( frame_function );
277     }
278     cache_frame_function = NULL;
285 279
n 286         exception_lineno = 32; n 280     assertFrameObject( frame_function );
287         type_description = "ooo"; 281  
282  
283     // Put the previous frame back on top.
284     popFrameStack();
285  
286     // Return the error.
288         goto try_except_handler_2; 287     goto try_except_handler_1;
289     } 288  
290     Py_DECREF( tmp_unused ); 289     frame_no_exception_1:;
290  
291     tmp_return_value = PyTuple_New( 2 );
292     tmp_tuple_element_1 = var_throw;
293  
294     Py_INCREF( tmp_tuple_element_1 );
295     PyTuple_SET_ITEM( tmp_return_value, 0, tmp_tuple_element_1 );
296     tmp_tuple_element_1 = PyExc_GeneratorExit;
297     Py_INCREF( tmp_tuple_element_1 );
298     PyTuple_SET_ITEM( tmp_return_value, 1, tmp_tuple_element_1 );
291     goto try_end_1; 299     goto try_return_handler_1;
300     // tried codes exits in all cases
301     NUITKA_CANNOT_GET_HERE( __main__$$$function_1_calledRepeatedly );
302     return NULL;
303     // Return handler code:
304     try_return_handler_1:;
305     Py_XDECREF( var_gen );
306     var_gen = NULL;
307  
308     Py_XDECREF( var_throw );
309     var_throw = NULL;
310  
311     goto function_return_exit;
292     // Exception handler code: 312     // Exception handler code:
n 293     try_except_handler_2:; n 313     try_except_handler_1:;
294     exception_keeper_type_1 = exception_type; 314     exception_keeper_type_1 = exception_type;
295     exception_keeper_value_1 = exception_value; 315     exception_keeper_value_1 = exception_value;
296     exception_keeper_tb_1 = exception_tb; 316     exception_keeper_tb_1 = exception_tb;
297     exception_keeper_lineno_1 = exception_lineno; 317     exception_keeper_lineno_1 = exception_lineno;
298     exception_type = NULL; 318     exception_type = NULL;
299     exception_value = NULL; 319     exception_value = NULL;
300     exception_tb = NULL; 320     exception_tb = NULL;
301     exception_lineno = -1; 321     exception_lineno = -1;
302 322
n 303     // Preserve existing published exception. n
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         type_description = "ooo";
339         goto try_except_handler_3;
340     }
341  
342     tmp_exc_match_exception_match_1 = EXCEPTION_MATCH_BOOL( tmp_compare_left_1, tmp_compare_right_1 );
343     if ( tmp_exc_match_exception_match_1 == -1 )
344     {
345         assert( ERROR_OCCURRED() );
346  
347         FETCH_ERROR_OCCURRED( &exception_type, &exception_value, &exception_tb );
348  
349  
350         exception_lineno = 36;
351         type_description = "ooo";
352         goto try_except_handler_3;
353     }
354     if ( tmp_exc_match_exception_match_1 == 1 )
355     {
356         goto branch_no_1;
357     }
358     else
359     {
360         goto branch_yes_1;
361     }
362     branch_yes_1:;
363     RERAISE_EXCEPTION( &exception_type, &exception_value, &exception_tb );
364     if (exception_tb && exception_tb->tb_frame == &frame_function->m_frame) frame_function->m_frame.f_lineno = exception_tb->tb_lineno;
365     type_description = "ooo";
366     goto try_except_handler_3;
367     branch_no_1:;
368     goto try_end_2;
369     // Exception handler code:
370     try_except_handler_3:;
371     exception_keeper_type_2 = exception_type;
372     exception_keeper_value_2 = exception_value;
373     exception_keeper_tb_2 = exception_tb;
374     exception_keeper_lineno_2 = exception_lineno;
375     exception_type = NULL;
376     exception_value = NULL;
377     exception_tb = NULL;
378     exception_lineno = -1;
379  
380     // Restore previous exception.
381     SET_CURRENT_EXCEPTION( exception_preserved_type_1, exception_preserved_value_1, exception_preserved_tb_1 );
382     // Re-raise.
383     exception_type = exception_keeper_type_2;
384     exception_value = exception_keeper_value_2;
385     exception_tb = exception_keeper_tb_2;
386     exception_lineno = exception_keeper_lineno_2;
387  
388     goto frame_exception_exit_1;
389     // End of try:
390     try_end_2:;
391     // Restore previous exception.
392     SET_CURRENT_EXCEPTION( exception_preserved_type_1, exception_preserved_value_1, exception_preserved_tb_1 );
393     goto try_end_1;
394     // exception handler codes exits in all cases
395     NUITKA_CANNOT_GET_HERE( __main__$$$function_1_calledRepeatedly );
396     return NULL;
397     // End of try:
398     try_end_1:;
399     tmp_return_value = PyTuple_New( 2 );
400     tmp_tuple_element_1 = var_throw;
401  
402     if ( tmp_tuple_element_1 == NULL )
403     {
404         Py_DECREF( tmp_return_value );
405         exception_type = PyExc_UnboundLocalError;
406         Py_INCREF( exception_type );
407         exception_value = PyUnicode_FromFormat( "local variable '%s' referenced before assignment", "throw" );
408         exception_tb = NULL;
409         NORMALIZE_EXCEPTION( &exception_type, &exception_value, &exception_tb );
410         CHAIN_EXCEPTION( exception_value );
411  
412         exception_lineno = 39;
413         type_description = "ooo";
414         goto frame_exception_exit_1;
415     }
416  
417     Py_INCREF( tmp_tuple_element_1 );
418     PyTuple_SET_ITEM( tmp_return_value, 0, tmp_tuple_element_1 );
419     tmp_tuple_element_1 = var_exc;
420  
421     if ( tmp_tuple_element_1 == NULL )
422     {
423         Py_DECREF( tmp_return_value );
424         exception_type = PyExc_UnboundLocalError;
425         Py_INCREF( exception_type );
426         exception_value = PyUnicode_FromFormat( "local variable '%s' referenced before assignment", "exc" );
427         exception_tb = NULL;
428         NORMALIZE_EXCEPTION( &exception_type, &exception_value, &exception_tb );
429         CHAIN_EXCEPTION( exception_value );
430  
431         exception_lineno = 39;
432         type_description = "ooo";
433         goto frame_exception_exit_1;
434     }
435  
436     Py_INCREF( tmp_tuple_element_1 );
437     PyTuple_SET_ITEM( tmp_return_value, 1, tmp_tuple_element_1 );
438     goto frame_return_exit_1;
439  
440 #if 1
441     RESTORE_FRAME_EXCEPTION( frame_function );
442 #endif
443  
444     // Put the previous frame back on top.
445     popFrameStack();
446  
447     goto frame_no_exception_1;
448  
449     frame_return_exit_1:;
450 #if 1
451     RESTORE_FRAME_EXCEPTION( frame_function );
452 #endif
453  
454     // Put the previous frame back on top.
455     popFrameStack();
456  
457     goto try_return_handler_1;
458  
459     frame_exception_exit_1:;
460  
461 #if 1
462     RESTORE_FRAME_EXCEPTION( frame_function );
463 #endif
464  
465     if ( exception_tb == NULL )
466     {
467         exception_tb = MAKE_TRACEBACK( frame_function, exception_lineno );
468     }
469     else if ( exception_tb->tb_frame != &frame_function->m_frame )
470     {
471         exception_tb = ADD_TRACEBACK( exception_tb, frame_function, exception_lineno );
472     }
473  
474     Nuitka_Frame_AttachLocals( (struct Nuitka_FrameObject *)frame_function, type_description ,var_gen, var_throw, var_exc );
475  
476     // Release cached frame.
477     if ( frame_function == cache_frame_function )
478     {
479         Py_DECREF( frame_function );
480     }
481     cache_frame_function = NULL;
482  
483     assertFrameObject( frame_function );
484  
485  
486     // Put the previous frame back on top.
487     popFrameStack();
488  
489     // Return the error.
490     goto try_except_handler_1;
491  
492     frame_no_exception_1:;
493  
494     // tried codes exits in all cases
495     NUITKA_CANNOT_GET_HERE( __main__$$$function_1_calledRepeatedly );
496     return NULL;
497     // Return handler code:
498     try_return_handler_1:;
499     Py_XDECREF( var_gen ); 323     Py_XDECREF( var_gen );
500     var_gen = NULL; 324     var_gen = NULL;
501 325
n 502     Py_XDECREF( var_throw ); n
503     var_throw = NULL;
504  
505     Py_XDECREF( var_exc );
506     var_exc = NULL;
507  
508     goto function_return_exit;
509     // Exception handler code:
510     try_except_handler_1:;
511     exception_keeper_type_3 = exception_type;
512     exception_keeper_value_3 = exception_value;
513     exception_keeper_tb_3 = exception_tb;
514     exception_keeper_lineno_3 = exception_lineno;
515     exception_type = NULL;
516     exception_value = NULL;
517     exception_tb = NULL;
518     exception_lineno = -1;
519  
520     Py_XDECREF( var_gen );
521     var_gen = NULL;
522  
523     Py_XDECREF( var_throw );
524     var_throw = NULL;
525  
526     Py_XDECREF( var_exc );
527     var_exc = NULL;
528  
529     // Re-raise. 326     // Re-raise.
t 530     exception_type = exception_keeper_type_3; t 327     exception_type = exception_keeper_type_1;
531     exception_value = exception_keeper_value_3; 328     exception_value = exception_keeper_value_1;
532     exception_tb = exception_keeper_tb_3; 329     exception_tb = exception_keeper_tb_1;
533     exception_lineno = exception_keeper_lineno_3; 330     exception_lineno = exception_keeper_lineno_1;
534 331
535     goto function_exception_exit; 332     goto function_exception_exit;
536     // End of try: 333     // End of try:
537 334
538     // Return statement must have exited already. 335     // Return statement must have exited already.