@@ -364,45 +364,21 @@ dump_instrumentation_data_per_instruction(PyCodeObject *code, _PyCoMonitoringDat
364
364
}
365
365
366
366
static void
367
- dump_monitors (const char * prefix , _Py_Monitors monitors , FILE * out )
367
+ dump_global_monitors (const char * prefix , _Py_GlobalMonitors monitors , FILE * out )
368
368
{
369
369
fprintf (out , "%s monitors:\n" , prefix );
370
370
for (int event = 0 ; event < _PY_MONITORING_UNGROUPED_EVENTS ; event ++ ) {
371
371
fprintf (out , " Event %d: Tools %x\n" , event , monitors .tools [event ]);
372
372
}
373
373
}
374
374
375
- /* Like _Py_GetBaseOpcode but without asserts.
376
- * Does its best to give the right answer, but won't abort
377
- * if something is wrong */
378
- static int
379
- get_base_opcode_best_attempt (PyCodeObject * code , int offset )
375
+ static void
376
+ dump_local_monitors (const char * prefix , _Py_LocalMonitors monitors , FILE * out )
380
377
{
381
- int opcode = _Py_OPCODE (_PyCode_CODE (code )[offset ]);
382
- if (INSTRUMENTED_OPCODES [opcode ] != opcode ) {
383
- /* Not instrumented */
384
- return _PyOpcode_Deopt [opcode ] == 0 ? opcode : _PyOpcode_Deopt [opcode ];
385
- }
386
- if (opcode == INSTRUMENTED_INSTRUCTION ) {
387
- if (code -> _co_monitoring -> per_instruction_opcodes [offset ] == 0 ) {
388
- return opcode ;
389
- }
390
- opcode = code -> _co_monitoring -> per_instruction_opcodes [offset ];
391
- }
392
- if (opcode == INSTRUMENTED_LINE ) {
393
- if (code -> _co_monitoring -> lines [offset ].original_opcode == 0 ) {
394
- return opcode ;
395
- }
396
- opcode = code -> _co_monitoring -> lines [offset ].original_opcode ;
397
- }
398
- int deinstrumented = DE_INSTRUMENT [opcode ];
399
- if (deinstrumented ) {
400
- return deinstrumented ;
401
- }
402
- if (_PyOpcode_Deopt [opcode ] == 0 ) {
403
- return opcode ;
378
+ fprintf (out , "%s monitors:\n" , prefix );
379
+ for (int event = 0 ; event < _PY_MONITORING_LOCAL_EVENTS ; event ++ ) {
380
+ fprintf (out , " Event %d: Tools %x\n" , event , monitors .tools [event ]);
404
381
}
405
- return _PyOpcode_Deopt [opcode ];
406
382
}
407
383
408
384
/* No error checking -- Don't use this for anything but experimental debugging */
@@ -417,9 +393,9 @@ dump_instrumentation_data(PyCodeObject *code, int star, FILE*out)
417
393
fprintf (out , "NULL\n" );
418
394
return ;
419
395
}
420
- dump_monitors ("Global" , _PyInterpreterState_GET ()-> monitors , out );
421
- dump_monitors ("Code" , data -> local_monitors , out );
422
- dump_monitors ("Active" , data -> active_monitors , out );
396
+ dump_global_monitors ("Global" , _PyInterpreterState_GET ()-> monitors , out );
397
+ dump_local_monitors ("Code" , data -> local_monitors , out );
398
+ dump_local_monitors ("Active" , data -> active_monitors , out );
423
399
int code_len = (int )Py_SIZE (code );
424
400
bool starred = false;
425
401
for (int i = 0 ; i < code_len ; i += _PyInstruction_GetLength (code , i )) {
@@ -458,6 +434,9 @@ dump_instrumentation_data(PyCodeObject *code, int star, FILE*out)
458
434
static bool
459
435
valid_opcode (int opcode )
460
436
{
437
+ if (opcode == INSTRUMENTED_LINE ) {
438
+ return true;
439
+ }
461
440
if (IS_VALID_OPCODE (opcode ) &&
462
441
opcode != CACHE &&
463
442
opcode != RESERVED &&
@@ -475,18 +454,23 @@ sanity_check_instrumentation(PyCodeObject *code)
475
454
if (data == NULL ) {
476
455
return ;
477
456
}
478
- _Py_GlobalMonitors active_monitors = _PyInterpreterState_GET ()-> monitors ;
457
+ _Py_GlobalMonitors global_monitors = _PyInterpreterState_GET ()-> monitors ;
458
+ _Py_LocalMonitors active_monitors ;
479
459
if (code -> _co_monitoring ) {
480
- _Py_Monitors local_monitors = code -> _co_monitoring -> local_monitors ;
481
- active_monitors = local_union (active_monitors , local_monitors );
460
+ _Py_LocalMonitors local_monitors = code -> _co_monitoring -> local_monitors ;
461
+ active_monitors = local_union (global_monitors , local_monitors );
462
+ }
463
+ else {
464
+ _Py_LocalMonitors empty = (_Py_LocalMonitors ) { 0 };
465
+ active_monitors = local_union (global_monitors , empty );
482
466
}
483
467
assert (monitors_equals (
484
468
code -> _co_monitoring -> active_monitors ,
485
- active_monitors )
486
- );
469
+ active_monitors ));
487
470
int code_len = (int )Py_SIZE (code );
488
471
for (int i = 0 ; i < code_len ;) {
489
- int opcode = _PyCode_CODE (code )[i ].op .code ;
472
+ _Py_CODEUNIT * instr = & _PyCode_CODE (code )[i ];
473
+ int opcode = instr -> op .code ;
490
474
int base_opcode = _Py_GetBaseOpcode (code , i );
491
475
CHECK (valid_opcode (opcode ));
492
476
CHECK (valid_opcode (base_opcode ));
@@ -506,23 +490,30 @@ sanity_check_instrumentation(PyCodeObject *code)
506
490
opcode = data -> lines [i ].original_opcode ;
507
491
CHECK (opcode != END_FOR );
508
492
CHECK (opcode != RESUME );
493
+ CHECK (opcode != RESUME_CHECK );
509
494
CHECK (opcode != INSTRUMENTED_RESUME );
510
495
if (!is_instrumented (opcode )) {
511
496
CHECK (_PyOpcode_Deopt [opcode ] == opcode );
512
497
}
513
498
CHECK (opcode != INSTRUMENTED_LINE );
514
499
}
515
- else if (data -> lines && !is_instrumented (opcode )) {
516
- CHECK (data -> lines [i ].original_opcode == 0 ||
517
- data -> lines [i ].original_opcode == base_opcode ||
518
- DE_INSTRUMENT [data -> lines [i ].original_opcode ] == base_opcode );
500
+ else if (data -> lines ) {
501
+ /* If original_opcode is INSTRUMENTED_INSTRUCTION
502
+ * *and* we are executing a INSTRUMENTED_LINE instruction
503
+ * that has de-instrumented itself, then we will execute
504
+ * an invalid INSTRUMENTED_INSTRUCTION */
505
+ CHECK (data -> lines [i ].original_opcode != INSTRUMENTED_INSTRUCTION );
506
+ }
507
+ if (opcode == INSTRUMENTED_INSTRUCTION ) {
508
+ CHECK (data -> per_instruction_opcodes [i ] != 0 );
509
+ opcode = data -> per_instruction_opcodes [i ];
519
510
}
520
511
if (is_instrumented (opcode )) {
521
512
CHECK (DE_INSTRUMENT [opcode ] == base_opcode );
522
513
int event = EVENT_FOR_OPCODE [DE_INSTRUMENT [opcode ]];
523
514
if (event < 0 ) {
524
515
/* RESUME fixup */
525
- event = _PyCode_CODE ( code )[ i ]. op .arg ;
516
+ event = instr -> op .arg ? 1 : 0 ;
526
517
}
527
518
CHECK (active_monitors .tools [event ] != 0 );
528
519
}
@@ -608,30 +599,30 @@ static void
608
599
de_instrument_line (PyCodeObject * code , int i )
609
600
{
610
601
_Py_CODEUNIT * instr = & _PyCode_CODE (code )[i ];
611
- uint8_t * opcode_ptr = & instr -> op .code ;
612
- int opcode = * opcode_ptr ;
602
+ int opcode = instr -> op .code ;
613
603
if (opcode != INSTRUMENTED_LINE ) {
614
604
return ;
615
605
}
616
606
_PyCoLineInstrumentationData * lines = & code -> _co_monitoring -> lines [i ];
617
607
int original_opcode = lines -> original_opcode ;
608
+ if (original_opcode == INSTRUMENTED_INSTRUCTION ) {
609
+ lines -> original_opcode = code -> _co_monitoring -> per_instruction_opcodes [i ];
610
+ }
618
611
CHECK (original_opcode != 0 );
619
612
CHECK (original_opcode == _PyOpcode_Deopt [original_opcode ]);
620
- * opcode_ptr = instr -> op .code = original_opcode ;
613
+ instr -> op .code = original_opcode ;
621
614
if (_PyOpcode_Caches [original_opcode ]) {
622
615
instr [1 ].cache = adaptive_counter_warmup ();
623
616
}
624
- assert (* opcode_ptr != INSTRUMENTED_LINE );
625
617
assert (instr -> op .code != INSTRUMENTED_LINE );
626
618
}
627
619
628
-
629
620
static void
630
621
de_instrument_per_instruction (PyCodeObject * code , int i )
631
622
{
632
623
_Py_CODEUNIT * instr = & _PyCode_CODE (code )[i ];
633
624
uint8_t * opcode_ptr = & instr -> op .code ;
634
- int opcode = * opcode_ptr ;
625
+ int opcode = * opcode_ptr ;
635
626
if (opcode == INSTRUMENTED_LINE ) {
636
627
opcode_ptr = & code -> _co_monitoring -> lines [i ].original_opcode ;
637
628
opcode = * opcode_ptr ;
@@ -642,10 +633,11 @@ de_instrument_per_instruction(PyCodeObject *code, int i)
642
633
int original_opcode = code -> _co_monitoring -> per_instruction_opcodes [i ];
643
634
CHECK (original_opcode != 0 );
644
635
CHECK (original_opcode == _PyOpcode_Deopt [original_opcode ]);
645
- instr -> op . code = original_opcode ;
636
+ * opcode_ptr = original_opcode ;
646
637
if (_PyOpcode_Caches [original_opcode ]) {
647
638
instr [1 ].cache = adaptive_counter_warmup ();
648
639
}
640
+ assert (* opcode_ptr != INSTRUMENTED_INSTRUCTION );
649
641
assert (instr -> op .code != INSTRUMENTED_INSTRUCTION );
650
642
/* Keep things clean for sanity check */
651
643
code -> _co_monitoring -> per_instruction_opcodes [i ] = 0 ;
@@ -685,7 +677,7 @@ static void
685
677
instrument_line (PyCodeObject * code , int i )
686
678
{
687
679
uint8_t * opcode_ptr = & _PyCode_CODE (code )[i ].op .code ;
688
- int opcode = * opcode_ptr ;
680
+ int opcode = * opcode_ptr ;
689
681
if (opcode == INSTRUMENTED_LINE ) {
690
682
return ;
691
683
}
@@ -700,13 +692,14 @@ instrument_per_instruction(PyCodeObject *code, int i)
700
692
{
701
693
_Py_CODEUNIT * instr = & _PyCode_CODE (code )[i ];
702
694
uint8_t * opcode_ptr = & instr -> op .code ;
703
- int opcode = * opcode_ptr ;
695
+ int opcode = * opcode_ptr ;
704
696
if (opcode == INSTRUMENTED_LINE ) {
705
697
_PyCoLineInstrumentationData * lines = & code -> _co_monitoring -> lines [i ];
706
698
opcode_ptr = & lines -> original_opcode ;
707
699
opcode = * opcode_ptr ;
708
700
}
709
701
if (opcode == INSTRUMENTED_INSTRUCTION ) {
702
+ assert (code -> _co_monitoring -> per_instruction_opcodes [i ] > 0 );
710
703
return ;
711
704
}
712
705
CHECK (opcode != 0 );
@@ -1129,7 +1122,6 @@ _Py_call_instrumentation_line(PyThreadState *tstate, _PyInterpreterFrame* frame,
1129
1122
1130
1123
_PyCoMonitoringData * monitoring = code -> _co_monitoring ;
1131
1124
_PyCoLineInstrumentationData * line_data = & monitoring -> lines [i ];
1132
- uint8_t original_opcode = line_data -> original_opcode ;
1133
1125
if (tstate -> tracing ) {
1134
1126
goto done ;
1135
1127
}
@@ -1212,7 +1204,9 @@ _Py_call_instrumentation_line(PyThreadState *tstate, _PyInterpreterFrame* frame,
1212
1204
}
1213
1205
} while (tools );
1214
1206
Py_DECREF (line_obj );
1207
+ uint8_t original_opcode ;
1215
1208
done :
1209
+ original_opcode = line_data -> original_opcode ;
1216
1210
assert (original_opcode != 0 );
1217
1211
assert (original_opcode != INSTRUMENTED_LINE );
1218
1212
assert (_PyOpcode_Deopt [original_opcode ] == original_opcode );
@@ -1655,7 +1649,9 @@ _Py_Instrument(PyCodeObject *code, PyInterpreterState *interp)
1655
1649
i += _PyInstruction_GetLength (code , i );
1656
1650
}
1657
1651
}
1658
-
1652
+ #ifdef INSTRUMENT_DEBUG
1653
+ sanity_check_instrumentation (code );
1654
+ #endif
1659
1655
uint8_t new_line_tools = new_events .tools [PY_MONITORING_EVENT_LINE ];
1660
1656
uint8_t new_per_instruction_tools = new_events .tools [PY_MONITORING_EVENT_INSTRUCTION ];
1661
1657
0 commit comments