@@ -412,6 +412,42 @@ frame_stack_pop(PyFrameObject *f)
412
412
Py_DECREF (v );
413
413
}
414
414
415
+ static PyFrameState
416
+ _PyFrame_GetState (PyFrameObject * frame )
417
+ {
418
+ if (frame -> f_frame -> stacktop == 0 ) {
419
+ return FRAME_CLEARED ;
420
+ }
421
+ switch (frame -> f_frame -> owner ) {
422
+ case FRAME_OWNED_BY_GENERATOR :
423
+ {
424
+ PyGenObject * gen = _PyFrame_GetGenerator (frame -> f_frame );
425
+ return gen -> gi_frame_state ;
426
+ }
427
+ case FRAME_OWNED_BY_THREAD :
428
+ {
429
+ if (frame -> f_frame -> f_lasti < 0 ) {
430
+ return FRAME_CREATED ;
431
+ }
432
+ uint8_t * code = (uint8_t * )frame -> f_frame -> f_code -> co_code_adaptive ;
433
+ int opcode = code [frame -> f_frame -> f_lasti * sizeof (_Py_CODEUNIT )];
434
+ switch (_PyOpcode_Deopt [opcode ]) {
435
+ case COPY_FREE_VARS :
436
+ case MAKE_CELL :
437
+ case RETURN_GENERATOR :
438
+ /* Frame not fully initialized */
439
+ return FRAME_CREATED ;
440
+ default :
441
+ return FRAME_EXECUTING ;
442
+ }
443
+ }
444
+ case FRAME_OWNED_BY_FRAME_OBJECT :
445
+ return FRAME_COMPLETED ;
446
+ }
447
+ Py_UNREACHABLE ();
448
+ }
449
+
450
+
415
451
/* Setter for f_lineno - you can set f_lineno from within a trace function in
416
452
* order to jump to a given line of code, subject to some restrictions. Most
417
453
* lines are OK to jump to because they don't make any assumptions about the
@@ -440,6 +476,7 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno, void *Py_UNUSED(ignore
440
476
return -1 ;
441
477
}
442
478
479
+ PyFrameState state = _PyFrame_GetState (f );
443
480
/*
444
481
* This code preserves the historical restrictions on
445
482
* setting the line number of a frame.
@@ -448,28 +485,31 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno, void *Py_UNUSED(ignore
448
485
* In addition, jumps are forbidden when not tracing,
449
486
* as this is a debugging feature.
450
487
*/
451
- switch (f -> f_frame -> f_state ) {
452
- case FRAME_CREATED :
488
+ switch (PyThreadState_GET ()-> tracing_what ) {
489
+ case PyTrace_EXCEPTION :
490
+ PyErr_SetString (PyExc_ValueError ,
491
+ "can only jump from a 'line' trace event" );
492
+ return -1 ;
493
+ case PyTrace_CALL :
453
494
PyErr_Format (PyExc_ValueError ,
454
495
"can't jump from the 'call' trace event of a new frame" );
455
496
return -1 ;
456
- case FRAME_RETURNED :
457
- case FRAME_UNWINDING :
458
- case FRAME_RAISED :
459
- case FRAME_CLEARED :
497
+ case PyTrace_LINE :
498
+ break ;
499
+ case PyTrace_RETURN :
500
+ if (state == FRAME_SUSPENDED ) {
501
+ break ;
502
+ }
503
+ /* fall through */
504
+ default :
460
505
PyErr_SetString (PyExc_ValueError ,
461
506
"can only jump from a 'line' trace event" );
462
507
return -1 ;
463
- case FRAME_EXECUTING :
464
- case FRAME_SUSPENDED :
465
- /* You can only do this from within a trace function, not via
466
- * _getframe or similar hackery. */
467
- if (!f -> f_trace ) {
468
- PyErr_Format (PyExc_ValueError ,
469
- "f_lineno can only be set by a trace function" );
470
- return -1 ;
471
- }
472
- break ;
508
+ }
509
+ if (!f -> f_trace ) {
510
+ PyErr_Format (PyExc_ValueError ,
511
+ "f_lineno can only be set by a trace function" );
512
+ return -1 ;
473
513
}
474
514
475
515
int new_lineno ;
@@ -555,8 +595,7 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno, void *Py_UNUSED(ignore
555
595
PyErr_SetString (PyExc_ValueError , msg );
556
596
return -1 ;
557
597
}
558
- /* Unwind block stack. */
559
- if (f -> f_frame -> f_state == FRAME_SUSPENDED ) {
598
+ if (state == FRAME_SUSPENDED ) {
560
599
/* Account for value popped by yield */
561
600
start_stack = pop_value (start_stack );
562
601
}
@@ -623,7 +662,9 @@ frame_dealloc(PyFrameObject *f)
623
662
{
624
663
/* It is the responsibility of the owning generator/coroutine
625
664
* to have cleared the generator pointer */
626
- assert (!f -> f_frame -> is_generator );
665
+
666
+ assert (f -> f_frame -> owner != FRAME_OWNED_BY_GENERATOR ||
667
+ _PyFrame_GetGenerator (f -> f_frame )-> gi_frame_state == FRAME_CLEARED );
627
668
628
669
if (_PyObject_GC_IS_TRACKED (f )) {
629
670
_PyObject_GC_UNTRACK (f );
@@ -633,8 +674,7 @@ frame_dealloc(PyFrameObject *f)
633
674
PyCodeObject * co = NULL ;
634
675
635
676
/* Kill all local variables including specials, if we own them */
636
- if (f -> f_owns_frame ) {
637
- f -> f_owns_frame = 0 ;
677
+ if (f -> f_frame -> owner == FRAME_OWNED_BY_FRAME_OBJECT ) {
638
678
assert (f -> f_frame == (_PyInterpreterFrame * )f -> _f_frame_data );
639
679
_PyInterpreterFrame * frame = (_PyInterpreterFrame * )f -> _f_frame_data ;
640
680
/* Don't clear code object until the end */
@@ -659,7 +699,7 @@ frame_traverse(PyFrameObject *f, visitproc visit, void *arg)
659
699
{
660
700
Py_VISIT (f -> f_back );
661
701
Py_VISIT (f -> f_trace );
662
- if (f -> f_owns_frame == 0 ) {
702
+ if (f -> f_frame -> owner != FRAME_OWNED_BY_FRAME_OBJECT ) {
663
703
return 0 ;
664
704
}
665
705
assert (f -> f_frame -> frame_obj == NULL );
@@ -669,13 +709,6 @@ frame_traverse(PyFrameObject *f, visitproc visit, void *arg)
669
709
static int
670
710
frame_tp_clear (PyFrameObject * f )
671
711
{
672
- /* Before anything else, make sure that this frame is clearly marked
673
- * as being defunct! Else, e.g., a generator reachable from this
674
- * frame may also point to this frame, believe itself to still be
675
- * active, and try cleaning up this frame again.
676
- */
677
- f -> f_frame -> f_state = FRAME_CLEARED ;
678
-
679
712
Py_CLEAR (f -> f_trace );
680
713
681
714
/* locals and stack */
@@ -691,19 +724,25 @@ frame_tp_clear(PyFrameObject *f)
691
724
static PyObject *
692
725
frame_clear (PyFrameObject * f , PyObject * Py_UNUSED (ignored ))
693
726
{
694
- if (_PyFrame_IsExecuting (f -> f_frame )) {
695
- PyErr_SetString (PyExc_RuntimeError ,
696
- "cannot clear an executing frame" );
697
- return NULL ;
727
+ if (f -> f_frame -> owner == FRAME_OWNED_BY_GENERATOR ) {
728
+ PyGenObject * gen = _PyFrame_GetGenerator (f -> f_frame );
729
+ if (gen -> gi_frame_state == FRAME_EXECUTING ) {
730
+ goto running ;
731
+ }
732
+ _PyGen_Finalize ((PyObject * )gen );
698
733
}
699
- if (f -> f_frame -> is_generator ) {
700
- assert (!f -> f_owns_frame );
701
- size_t offset_in_gen = offsetof(PyGenObject , gi_iframe );
702
- PyObject * gen = (PyObject * )(((char * )f -> f_frame ) - offset_in_gen );
703
- _PyGen_Finalize (gen );
734
+ else if (f -> f_frame -> owner == FRAME_OWNED_BY_THREAD ) {
735
+ goto running ;
736
+ }
737
+ else {
738
+ assert (f -> f_frame -> owner == FRAME_OWNED_BY_FRAME_OBJECT );
739
+ (void )frame_tp_clear (f );
704
740
}
705
- (void )frame_tp_clear (f );
706
741
Py_RETURN_NONE ;
742
+ running :
743
+ PyErr_SetString (PyExc_RuntimeError ,
744
+ "cannot clear an executing frame" );
745
+ return NULL ;
707
746
}
708
747
709
748
PyDoc_STRVAR (clear__doc__ ,
@@ -835,7 +874,7 @@ PyFrame_New(PyThreadState *tstate, PyCodeObject *code,
835
874
}
836
875
init_frame ((_PyInterpreterFrame * )f -> _f_frame_data , func , locals );
837
876
f -> f_frame = (_PyInterpreterFrame * )f -> _f_frame_data ;
838
- f -> f_owns_frame = 1 ;
877
+ f -> f_frame -> owner = FRAME_OWNED_BY_FRAME_OBJECT ;
839
878
Py_DECREF (func );
840
879
_PyObject_GC_TRACK (f );
841
880
return f ;
@@ -912,7 +951,7 @@ _PyFrame_FastToLocalsWithError(_PyInterpreterFrame *frame) {
912
951
913
952
PyObject * name = PyTuple_GET_ITEM (co -> co_localsplusnames , i );
914
953
PyObject * value = fast [i ];
915
- if (frame -> f_state != FRAME_CLEARED ) {
954
+ if (frame -> stacktop ) {
916
955
if (kind & CO_FAST_FREE ) {
917
956
// The cell was set by COPY_FREE_VARS.
918
957
assert (value != NULL && PyCell_Check (value ));
@@ -1049,7 +1088,7 @@ _PyFrame_LocalsToFast(_PyInterpreterFrame *frame, int clear)
1049
1088
void
1050
1089
PyFrame_LocalsToFast (PyFrameObject * f , int clear )
1051
1090
{
1052
- if (f == NULL || f -> f_frame -> f_state == FRAME_CLEARED ) {
1091
+ if (f == NULL || _PyFrame_GetState ( f ) == FRAME_CLEARED ) {
1053
1092
return ;
1054
1093
}
1055
1094
_PyFrame_LocalsToFast (f -> f_frame , clear );
@@ -1096,3 +1135,5 @@ _PyEval_BuiltinsFromGlobals(PyThreadState *tstate, PyObject *globals)
1096
1135
1097
1136
return _PyEval_GetBuiltins (tstate );
1098
1137
}
1138
+
1139
+
0 commit comments