Skip to content

Commit 3bfa24e

Browse files
authored
gh-107265: Remove all ENTER_EXECUTOR when execute _Py_Instrument (gh-108539)
1 parent 19eddb5 commit 3bfa24e

File tree

4 files changed

+59
-32
lines changed

4 files changed

+59
-32
lines changed

Diff for: Include/internal/pycore_code.h

+3
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,9 @@ extern void _PyLineTable_InitAddressRange(
233233
extern int _PyLineTable_NextAddressRange(PyCodeAddressRange *range);
234234
extern int _PyLineTable_PreviousAddressRange(PyCodeAddressRange *range);
235235

236+
/** API for executors */
237+
extern void _PyCode_Clear_Executors(PyCodeObject *code);
238+
236239
#define ENABLE_SPECIALIZATION 1
237240

238241
/* Specialization functions */

Diff for: Lib/test/test_monitoring.py

+28
Original file line numberDiff line numberDiff line change
@@ -1718,3 +1718,31 @@ def make_foo_optimized_then_set_event():
17181718
make_foo_optimized_then_set_event()
17191719
finally:
17201720
sys.monitoring.set_events(TEST_TOOL, 0)
1721+
1722+
1723+
class TestOptimizer(MonitoringTestBase, unittest.TestCase):
1724+
1725+
def setUp(self):
1726+
import _testinternalcapi
1727+
self.old_opt = _testinternalcapi.get_optimizer()
1728+
opt = _testinternalcapi.get_counter_optimizer()
1729+
_testinternalcapi.set_optimizer(opt)
1730+
super(TestOptimizer, self).setUp()
1731+
1732+
def tearDown(self):
1733+
import _testinternalcapi
1734+
super(TestOptimizer, self).tearDown()
1735+
_testinternalcapi.set_optimizer(self.old_opt)
1736+
1737+
def test_for_loop(self):
1738+
def test_func(x):
1739+
i = 0
1740+
while i < x:
1741+
i += 1
1742+
1743+
code = test_func.__code__
1744+
sys.monitoring.set_local_events(TEST_TOOL, code, E.PY_START)
1745+
self.assertEqual(sys.monitoring.get_local_events(TEST_TOOL, code), E.PY_START)
1746+
test_func(1000)
1747+
sys.monitoring.set_local_events(TEST_TOOL, code, 0)
1748+
self.assertEqual(sys.monitoring.get_local_events(TEST_TOOL, code), 0)

Diff for: Objects/codeobject.c

+17
Original file line numberDiff line numberDiff line change
@@ -1479,6 +1479,23 @@ clear_executors(PyCodeObject *co)
14791479
co->co_executors = NULL;
14801480
}
14811481

1482+
void
1483+
_PyCode_Clear_Executors(PyCodeObject *code) {
1484+
int code_len = (int)Py_SIZE(code);
1485+
for (int i = 0; i < code_len; i += _PyInstruction_GetLength(code, i)) {
1486+
_Py_CODEUNIT *instr = &_PyCode_CODE(code)[i];
1487+
uint8_t opcode = instr->op.code;
1488+
uint8_t oparg = instr->op.arg;
1489+
if (opcode == ENTER_EXECUTOR) {
1490+
_PyExecutorObject *exec = code->co_executors->executors[oparg];
1491+
assert(exec->vm_data.opcode != ENTER_EXECUTOR);
1492+
instr->op.code = exec->vm_data.opcode;
1493+
instr->op.arg = exec->vm_data.oparg;
1494+
}
1495+
}
1496+
clear_executors(code);
1497+
}
1498+
14821499
static void
14831500
deopt_code(PyCodeObject *code, _Py_CODEUNIT *instructions)
14841501
{

Diff for: Python/instrumentation.c

+11-32
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "opcode_ids.h"
44

55
#include "pycore_call.h"
6+
#include "pycore_code.h" // _PyCode_Clear_Executors()
67
#include "pycore_frame.h"
78
#include "pycore_interp.h"
89
#include "pycore_long.h"
@@ -583,13 +584,7 @@ de_instrument(PyCodeObject *code, int i, int event)
583584
_Py_CODEUNIT *instr = &_PyCode_CODE(code)[i];
584585
uint8_t *opcode_ptr = &instr->op.code;
585586
int opcode = *opcode_ptr;
586-
if (opcode == ENTER_EXECUTOR) {
587-
int oparg = instr->op.arg;
588-
_PyExecutorObject *exec = code->co_executors->executors[oparg];
589-
opcode_ptr = &exec->vm_data.opcode;
590-
opcode = *opcode_ptr;
591-
assert(opcode != ENTER_EXECUTOR);
592-
}
587+
assert(opcode != ENTER_EXECUTOR);
593588
if (opcode == INSTRUMENTED_LINE) {
594589
opcode_ptr = &code->_co_monitoring->lines[i].original_opcode;
595590
opcode = *opcode_ptr;
@@ -734,22 +729,7 @@ remove_tools(PyCodeObject * code, int offset, int event, int tools)
734729
assert(event != PY_MONITORING_EVENT_LINE);
735730
assert(event != PY_MONITORING_EVENT_INSTRUCTION);
736731
assert(PY_MONITORING_IS_INSTRUMENTED_EVENT(event));
737-
#ifndef NDEBUG
738-
_Py_CODEUNIT co_instr = _PyCode_CODE(code)[offset];
739-
uint8_t opcode = co_instr.op.code;
740-
uint8_t oparg = co_instr.op.arg;
741-
if (opcode == ENTER_EXECUTOR) {
742-
_PyExecutorObject *exec = code->co_executors->executors[oparg];
743-
assert(exec->vm_data.opcode != ENTER_EXECUTOR);
744-
opcode = _PyOpcode_Deopt[exec->vm_data.opcode];
745-
opcode = exec->vm_data.oparg;
746-
}
747-
else {
748-
opcode = _Py_GetBaseOpcode(code, offset);
749-
}
750-
assert(opcode != ENTER_EXECUTOR);
751-
assert(opcode_has_event(opcode));
752-
#endif
732+
assert(opcode_has_event(_Py_GetBaseOpcode(code, offset)));
753733
_PyCoMonitoringData *monitoring = code->_co_monitoring;
754734
if (monitoring && monitoring->tools) {
755735
monitoring->tools[offset] &= ~tools;
@@ -1315,16 +1295,10 @@ initialize_tools(PyCodeObject *code)
13151295
for (int i = 0; i < code_len; i++) {
13161296
_Py_CODEUNIT *instr = &_PyCode_CODE(code)[i];
13171297
int opcode = instr->op.code;
1318-
int oparg = instr->op.arg;
1319-
if (opcode == ENTER_EXECUTOR) {
1320-
_PyExecutorObject *exec = code->co_executors->executors[oparg];
1321-
opcode = exec->vm_data.opcode;
1322-
oparg = exec->vm_data.oparg;
1323-
}
1324-
else if (opcode == INSTRUMENTED_LINE) {
1298+
assert(opcode != ENTER_EXECUTOR);
1299+
if (opcode == INSTRUMENTED_LINE) {
13251300
opcode = code->_co_monitoring->lines[i].original_opcode;
13261301
}
1327-
assert(opcode != ENTER_EXECUTOR);
13281302
bool instrumented = is_instrumented(opcode);
13291303
if (instrumented) {
13301304
opcode = DE_INSTRUMENT[opcode];
@@ -1335,7 +1309,7 @@ initialize_tools(PyCodeObject *code)
13351309
if (instrumented) {
13361310
int8_t event;
13371311
if (opcode == RESUME) {
1338-
event = oparg != 0;
1312+
event = instr->op.arg != 0;
13391313
}
13401314
else {
13411315
event = EVENT_FOR_OPCODE[opcode];
@@ -1588,6 +1562,9 @@ _Py_Instrument(PyCodeObject *code, PyInterpreterState *interp)
15881562
);
15891563
return 0;
15901564
}
1565+
if (code->co_executors != NULL) {
1566+
_PyCode_Clear_Executors(code);
1567+
}
15911568
int code_len = (int)Py_SIZE(code);
15921569
/* code->_co_firsttraceable >= code_len indicates
15931570
* that no instrumentation can be inserted.
@@ -1629,7 +1606,9 @@ _Py_Instrument(PyCodeObject *code, PyInterpreterState *interp)
16291606
for (int i = code->_co_firsttraceable; i < code_len; i+= _PyInstruction_GetLength(code, i)) {
16301607
_Py_CODEUNIT *instr = &_PyCode_CODE(code)[i];
16311608
CHECK(instr->op.code != 0);
1609+
assert(instr->op.code != ENTER_EXECUTOR);
16321610
int base_opcode = _Py_GetBaseOpcode(code, i);
1611+
assert(base_opcode != ENTER_EXECUTOR);
16331612
if (opcode_has_event(base_opcode)) {
16341613
int8_t event;
16351614
if (base_opcode == RESUME) {

0 commit comments

Comments
 (0)