make_foo_optimized_then_set_event()
finally:
sys.monitoring.set_events(TEST_TOOL, 0)
+
+
+class TestOptimizer(MonitoringTestBase, unittest.TestCase):
+
+ def setUp(self):
+ import _testinternalcapi
+ self.old_opt = _testinternalcapi.get_optimizer()
+ opt = _testinternalcapi.get_counter_optimizer()
+ _testinternalcapi.set_optimizer(opt)
+ super(TestOptimizer, self).setUp()
+
+ def tearDown(self):
+ import _testinternalcapi
+ super(TestOptimizer, self).tearDown()
+ _testinternalcapi.set_optimizer(self.old_opt)
+
+ def test_for_loop(self):
+ def test_func(x):
+ i = 0
+ while i < x:
+ i += 1
+
+ code = test_func.__code__
+ sys.monitoring.set_local_events(TEST_TOOL, code, E.PY_START)
+ self.assertEqual(sys.monitoring.get_local_events(TEST_TOOL, code), E.PY_START)
+ test_func(1000)
+ sys.monitoring.set_local_events(TEST_TOOL, code, 0)
+ self.assertEqual(sys.monitoring.get_local_events(TEST_TOOL, code), 0)
co->co_executors = NULL;
}
+void
+_PyCode_Clear_Executors(PyCodeObject *code) {
+ int code_len = (int)Py_SIZE(code);
+ for (int i = 0; i < code_len; i += _PyInstruction_GetLength(code, i)) {
+ _Py_CODEUNIT *instr = &_PyCode_CODE(code)[i];
+ uint8_t opcode = instr->op.code;
+ uint8_t oparg = instr->op.arg;
+ if (opcode == ENTER_EXECUTOR) {
+ _PyExecutorObject *exec = code->co_executors->executors[oparg];
+ assert(exec->vm_data.opcode != ENTER_EXECUTOR);
+ instr->op.code = exec->vm_data.opcode;
+ instr->op.arg = exec->vm_data.oparg;
+ }
+ }
+ clear_executors(code);
+}
+
static void
deopt_code(PyCodeObject *code, _Py_CODEUNIT *instructions)
{
#include "opcode_ids.h"
#include "pycore_call.h"
+#include "pycore_code.h" // _PyCode_Clear_Executors()
#include "pycore_frame.h"
#include "pycore_interp.h"
#include "pycore_long.h"
_Py_CODEUNIT *instr = &_PyCode_CODE(code)[i];
uint8_t *opcode_ptr = &instr->op.code;
int opcode = *opcode_ptr;
- if (opcode == ENTER_EXECUTOR) {
- int oparg = instr->op.arg;
- _PyExecutorObject *exec = code->co_executors->executors[oparg];
- opcode_ptr = &exec->vm_data.opcode;
- opcode = *opcode_ptr;
- assert(opcode != ENTER_EXECUTOR);
- }
+ assert(opcode != ENTER_EXECUTOR);
if (opcode == INSTRUMENTED_LINE) {
opcode_ptr = &code->_co_monitoring->lines[i].original_opcode;
opcode = *opcode_ptr;
assert(event != PY_MONITORING_EVENT_LINE);
assert(event != PY_MONITORING_EVENT_INSTRUCTION);
assert(PY_MONITORING_IS_INSTRUMENTED_EVENT(event));
- #ifndef NDEBUG
- _Py_CODEUNIT co_instr = _PyCode_CODE(code)[offset];
- uint8_t opcode = co_instr.op.code;
- uint8_t oparg = co_instr.op.arg;
- if (opcode == ENTER_EXECUTOR) {
- _PyExecutorObject *exec = code->co_executors->executors[oparg];
- assert(exec->vm_data.opcode != ENTER_EXECUTOR);
- opcode = _PyOpcode_Deopt[exec->vm_data.opcode];
- opcode = exec->vm_data.oparg;
- }
- else {
- opcode = _Py_GetBaseOpcode(code, offset);
- }
- assert(opcode != ENTER_EXECUTOR);
- assert(opcode_has_event(opcode));
- #endif
+ assert(opcode_has_event(_Py_GetBaseOpcode(code, offset)));
_PyCoMonitoringData *monitoring = code->_co_monitoring;
if (monitoring && monitoring->tools) {
monitoring->tools[offset] &= ~tools;
for (int i = 0; i < code_len; i++) {
_Py_CODEUNIT *instr = &_PyCode_CODE(code)[i];
int opcode = instr->op.code;
- int oparg = instr->op.arg;
- if (opcode == ENTER_EXECUTOR) {
- _PyExecutorObject *exec = code->co_executors->executors[oparg];
- opcode = exec->vm_data.opcode;
- oparg = exec->vm_data.oparg;
- }
- else if (opcode == INSTRUMENTED_LINE) {
+ assert(opcode != ENTER_EXECUTOR);
+ if (opcode == INSTRUMENTED_LINE) {
opcode = code->_co_monitoring->lines[i].original_opcode;
}
- assert(opcode != ENTER_EXECUTOR);
bool instrumented = is_instrumented(opcode);
if (instrumented) {
opcode = DE_INSTRUMENT[opcode];
if (instrumented) {
int8_t event;
if (opcode == RESUME) {
- event = oparg != 0;
+ event = instr->op.arg != 0;
}
else {
event = EVENT_FOR_OPCODE[opcode];
);
return 0;
}
+ if (code->co_executors != NULL) {
+ _PyCode_Clear_Executors(code);
+ }
int code_len = (int)Py_SIZE(code);
/* code->_co_firsttraceable >= code_len indicates
* that no instrumentation can be inserted.
for (int i = code->_co_firsttraceable; i < code_len; i+= _PyInstruction_GetLength(code, i)) {
_Py_CODEUNIT *instr = &_PyCode_CODE(code)[i];
CHECK(instr->op.code != 0);
+ assert(instr->op.code != ENTER_EXECUTOR);
int base_opcode = _Py_GetBaseOpcode(code, i);
+ assert(base_opcode != ENTER_EXECUTOR);
if (opcode_has_event(base_opcode)) {
int8_t event;
if (base_opcode == RESUME) {