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