1
1
2
2
3
3
4
+
4
5
#include "Python.h"
5
6
#include "pycore_call.h"
6
7
#include "pycore_frame.h"
@@ -355,45 +356,21 @@ dump_instrumentation_data_per_instruction(PyCodeObject *code, _PyCoMonitoringDat
355
356
}
356
357
357
358
static void
358
- dump_monitors (const char * prefix , _Py_Monitors monitors , FILE * out )
359
+ dump_global_monitors (const char * prefix , _Py_GlobalMonitors monitors , FILE * out )
359
360
{
360
361
fprintf (out , "%s monitors:\n" , prefix );
361
362
for (int event = 0 ; event < _PY_MONITORING_UNGROUPED_EVENTS ; event ++ ) {
362
363
fprintf (out , " Event %d: Tools %x\n" , event , monitors .tools [event ]);
363
364
}
364
365
}
365
366
366
- /* Like _Py_GetBaseOpcode but without asserts.
367
- * Does its best to give the right answer, but won't abort
368
- * if something is wrong */
369
- static int
370
- get_base_opcode_best_attempt (PyCodeObject * code , int offset )
367
+ static void
368
+ dump_local_monitors (const char * prefix , _Py_LocalMonitors monitors , FILE * out )
371
369
{
372
- int opcode = _Py_OPCODE (_PyCode_CODE (code )[offset ]);
373
- if (INSTRUMENTED_OPCODES [opcode ] != opcode ) {
374
- /* Not instrumented */
375
- return _PyOpcode_Deopt [opcode ] == 0 ? opcode : _PyOpcode_Deopt [opcode ];
376
- }
377
- if (opcode == INSTRUMENTED_INSTRUCTION ) {
378
- if (code -> _co_monitoring -> per_instruction_opcodes [offset ] == 0 ) {
379
- return opcode ;
380
- }
381
- opcode = code -> _co_monitoring -> per_instruction_opcodes [offset ];
382
- }
383
- if (opcode == INSTRUMENTED_LINE ) {
384
- if (code -> _co_monitoring -> lines [offset ].original_opcode == 0 ) {
385
- return opcode ;
386
- }
387
- opcode = code -> _co_monitoring -> lines [offset ].original_opcode ;
388
- }
389
- int deinstrumented = DE_INSTRUMENT [opcode ];
390
- if (deinstrumented ) {
391
- return deinstrumented ;
392
- }
393
- if (_PyOpcode_Deopt [opcode ] == 0 ) {
394
- return opcode ;
370
+ fprintf (out , "%s monitors:\n" , prefix );
371
+ for (int event = 0 ; event < _PY_MONITORING_LOCAL_EVENTS ; event ++ ) {
372
+ fprintf (out , " Event %d: Tools %x\n" , event , monitors .tools [event ]);
395
373
}
396
- return _PyOpcode_Deopt [opcode ];
397
374
}
398
375
399
376
/* No error checking -- Don't use this for anything but experimental debugging */
@@ -408,9 +385,9 @@ dump_instrumentation_data(PyCodeObject *code, int star, FILE*out)
408
385
fprintf (out , "NULL\n" );
409
386
return ;
410
387
}
411
- dump_monitors ("Global" , PyInterpreterState_Get ()-> monitors , out );
412
- dump_monitors ("Code" , data -> local_monitors , out );
413
- dump_monitors ("Active" , data -> active_monitors , out );
388
+ dump_global_monitors ("Global" , _PyInterpreterState_GET ()-> monitors , out );
389
+ dump_local_monitors ("Code" , data -> local_monitors , out );
390
+ dump_local_monitors ("Active" , data -> active_monitors , out );
414
391
int code_len = (int )Py_SIZE (code );
415
392
bool starred = false;
416
393
for (int i = 0 ; i < code_len ; i += instruction_length (code , i )) {
@@ -467,18 +444,23 @@ sanity_check_instrumentation(PyCodeObject *code)
467
444
if (data == NULL ) {
468
445
return ;
469
446
}
470
- _Py_GlobalMonitors active_monitors = _PyInterpreterState_GET ()-> monitors ;
447
+ _Py_GlobalMonitors global_monitors = _PyInterpreterState_GET ()-> monitors ;
448
+ _Py_LocalMonitors active_monitors ;
471
449
if (code -> _co_monitoring ) {
472
- _Py_Monitors local_monitors = code -> _co_monitoring -> local_monitors ;
473
- active_monitors = local_union (active_monitors , local_monitors );
450
+ _Py_LocalMonitors local_monitors = code -> _co_monitoring -> local_monitors ;
451
+ active_monitors = local_union (global_monitors , local_monitors );
452
+ }
453
+ else {
454
+ _Py_LocalMonitors empty = (_Py_LocalMonitors ) { 0 };
455
+ active_monitors = local_union (global_monitors , empty );
474
456
}
475
457
assert (monitors_equals (
476
458
code -> _co_monitoring -> active_monitors ,
477
- active_monitors )
478
- );
459
+ active_monitors ));
479
460
int code_len = (int )Py_SIZE (code );
480
461
for (int i = 0 ; i < code_len ;) {
481
- int opcode = _PyCode_CODE (code )[i ].op .code ;
462
+ _Py_CODEUNIT * instr = & _PyCode_CODE (code )[i ];
463
+ int opcode = instr -> op .code ;
482
464
int base_opcode = _Py_GetBaseOpcode (code , i );
483
465
CHECK (valid_opcode (opcode ));
484
466
CHECK (valid_opcode (base_opcode ));
@@ -498,23 +480,30 @@ sanity_check_instrumentation(PyCodeObject *code)
498
480
opcode = data -> lines [i ].original_opcode ;
499
481
CHECK (opcode != END_FOR );
500
482
CHECK (opcode != RESUME );
483
+ CHECK (opcode != RESUME_CHECK );
501
484
CHECK (opcode != INSTRUMENTED_RESUME );
502
485
if (!is_instrumented (opcode )) {
503
486
CHECK (_PyOpcode_Deopt [opcode ] == opcode );
504
487
}
505
488
CHECK (opcode != INSTRUMENTED_LINE );
506
489
}
507
- else if (data -> lines && !is_instrumented (opcode )) {
508
- CHECK (data -> lines [i ].original_opcode == 0 ||
509
- data -> lines [i ].original_opcode == base_opcode ||
510
- DE_INSTRUMENT [data -> lines [i ].original_opcode ] == base_opcode );
490
+ else if (data -> lines ) {
491
+ /* If original_opcode is INSTRUMENTED_INSTRUCTION
492
+ * *and* we are executing a INSTRUMENTED_LINE instruction
493
+ * that has de-instrumented itself, then we will execute
494
+ * an invalid INSTRUMENTED_INSTRUCTION */
495
+ CHECK (data -> lines [i ].original_opcode != INSTRUMENTED_INSTRUCTION );
496
+ }
497
+ if (opcode == INSTRUMENTED_INSTRUCTION ) {
498
+ CHECK (data -> per_instruction_opcodes [i ] != 0 );
499
+ opcode = data -> per_instruction_opcodes [i ];
511
500
}
512
501
if (is_instrumented (opcode )) {
513
502
CHECK (DE_INSTRUMENT [opcode ] == base_opcode );
514
503
int event = EVENT_FOR_OPCODE [DE_INSTRUMENT [opcode ]];
515
504
if (event < 0 ) {
516
505
/* RESUME fixup */
517
- event = _PyCode_CODE ( code )[ i ]. op .arg ;
506
+ event = instr -> op .arg ? 1 : 0 ;
518
507
}
519
508
CHECK (active_monitors .tools [event ] != 0 );
520
509
}
@@ -599,30 +588,30 @@ static void
599
588
de_instrument_line (PyCodeObject * code , int i )
600
589
{
601
590
_Py_CODEUNIT * instr = & _PyCode_CODE (code )[i ];
602
- uint8_t * opcode_ptr = & instr -> op .code ;
603
- int opcode = * opcode_ptr ;
591
+ int opcode = instr -> op .code ;
604
592
if (opcode != INSTRUMENTED_LINE ) {
605
593
return ;
606
594
}
607
595
_PyCoLineInstrumentationData * lines = & code -> _co_monitoring -> lines [i ];
608
596
int original_opcode = lines -> original_opcode ;
597
+ if (original_opcode == INSTRUMENTED_INSTRUCTION ) {
598
+ lines -> original_opcode = code -> _co_monitoring -> per_instruction_opcodes [i ];
599
+ }
609
600
CHECK (original_opcode != 0 );
610
601
CHECK (original_opcode == _PyOpcode_Deopt [original_opcode ]);
611
- * opcode_ptr = instr -> op .code = original_opcode ;
602
+ instr -> op .code = original_opcode ;
612
603
if (_PyOpcode_Caches [original_opcode ]) {
613
604
instr [1 ].cache = adaptive_counter_warmup ();
614
605
}
615
- assert (* opcode_ptr != INSTRUMENTED_LINE );
616
606
assert (instr -> op .code != INSTRUMENTED_LINE );
617
607
}
618
608
619
-
620
609
static void
621
610
de_instrument_per_instruction (PyCodeObject * code , int i )
622
611
{
623
612
_Py_CODEUNIT * instr = & _PyCode_CODE (code )[i ];
624
613
uint8_t * opcode_ptr = & instr -> op .code ;
625
- int opcode = * opcode_ptr ;
614
+ int opcode = * opcode_ptr ;
626
615
if (opcode == INSTRUMENTED_LINE ) {
627
616
opcode_ptr = & code -> _co_monitoring -> lines [i ].original_opcode ;
628
617
opcode = * opcode_ptr ;
@@ -633,10 +622,11 @@ de_instrument_per_instruction(PyCodeObject *code, int i)
633
622
int original_opcode = code -> _co_monitoring -> per_instruction_opcodes [i ];
634
623
CHECK (original_opcode != 0 );
635
624
CHECK (original_opcode == _PyOpcode_Deopt [original_opcode ]);
636
- instr -> op . code = original_opcode ;
625
+ * opcode_ptr = original_opcode ;
637
626
if (_PyOpcode_Caches [original_opcode ]) {
638
627
instr [1 ].cache = adaptive_counter_warmup ();
639
628
}
629
+ assert (* opcode_ptr != INSTRUMENTED_INSTRUCTION );
640
630
assert (instr -> op .code != INSTRUMENTED_INSTRUCTION );
641
631
/* Keep things clean for sanity check */
642
632
code -> _co_monitoring -> per_instruction_opcodes [i ] = 0 ;
@@ -676,7 +666,7 @@ static void
676
666
instrument_line (PyCodeObject * code , int i )
677
667
{
678
668
uint8_t * opcode_ptr = & _PyCode_CODE (code )[i ].op .code ;
679
- int opcode = * opcode_ptr ;
669
+ int opcode = * opcode_ptr ;
680
670
if (opcode == INSTRUMENTED_LINE ) {
681
671
return ;
682
672
}
@@ -691,13 +681,14 @@ instrument_per_instruction(PyCodeObject *code, int i)
691
681
{
692
682
_Py_CODEUNIT * instr = & _PyCode_CODE (code )[i ];
693
683
uint8_t * opcode_ptr = & instr -> op .code ;
694
- int opcode = * opcode_ptr ;
684
+ int opcode = * opcode_ptr ;
695
685
if (opcode == INSTRUMENTED_LINE ) {
696
686
_PyCoLineInstrumentationData * lines = & code -> _co_monitoring -> lines [i ];
697
687
opcode_ptr = & lines -> original_opcode ;
698
688
opcode = * opcode_ptr ;
699
689
}
700
690
if (opcode == INSTRUMENTED_INSTRUCTION ) {
691
+ assert (code -> _co_monitoring -> per_instruction_opcodes [i ] > 0 );
701
692
return ;
702
693
}
703
694
CHECK (opcode != 0 );
@@ -1127,7 +1118,6 @@ _Py_call_instrumentation_line(PyThreadState *tstate, _PyInterpreterFrame* frame,
1127
1118
1128
1119
_PyCoMonitoringData * monitoring = code -> _co_monitoring ;
1129
1120
_PyCoLineInstrumentationData * line_data = & monitoring -> lines [i ];
1130
- uint8_t original_opcode = line_data -> original_opcode ;
1131
1121
if (tstate -> tracing ) {
1132
1122
goto done ;
1133
1123
}
@@ -1178,7 +1168,9 @@ _Py_call_instrumentation_line(PyThreadState *tstate, _PyInterpreterFrame* frame,
1178
1168
}
1179
1169
}
1180
1170
Py_DECREF (line_obj );
1171
+ uint8_t original_opcode ;
1181
1172
done :
1173
+ original_opcode = line_data -> original_opcode ;
1182
1174
assert (original_opcode != 0 );
1183
1175
assert (original_opcode < INSTRUMENTED_LINE );
1184
1176
assert (_PyOpcode_Deopt [original_opcode ] == original_opcode );
@@ -1633,7 +1625,9 @@ _Py_Instrument(PyCodeObject *code, PyInterpreterState *interp)
1633
1625
i += instruction_length (code , i );
1634
1626
}
1635
1627
}
1636
-
1628
+ #ifdef INSTRUMENT_DEBUG
1629
+ sanity_check_instrumentation (code );
1630
+ #endif
1637
1631
uint8_t new_line_tools = new_events .tools [PY_MONITORING_EVENT_LINE ];
1638
1632
uint8_t new_per_instruction_tools = new_events .tools [PY_MONITORING_EVENT_INSTRUCTION ];
1639
1633
0 commit comments