gh-109052: Use the base opcode when comparing code objects (gh-109107)

This commit is contained in:
Tian Gao 2023-09-08 18:24:49 -07:00 committed by GitHub
parent a56c928756
commit 057bc72490
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 24 additions and 6 deletions

View File

@ -505,6 +505,25 @@ class CodeTest(unittest.TestCase):
self.assertNotEqual(c, c1)
self.assertNotEqual(hash(c), hash(c1))
@cpython_only
def test_code_equal_with_instrumentation(self):
""" GH-109052
Make sure the instrumentation doesn't affect the code equality
The validity of this test relies on the fact that "x is x" and
"x in x" have only one different instruction and the instructions
have the same argument.
"""
code1 = compile("x is x", "example.py", "eval")
code2 = compile("x in x", "example.py", "eval")
sys._getframe().f_trace_opcodes = True
sys.settrace(lambda *args: None)
exec(code1, {'x': []})
exec(code2, {'x': []})
self.assertNotEqual(code1, code2)
sys.settrace(None)
def isinterned(s):
return s is sys.intern(('_' + s + '_')[1:-1])

View File

@ -0,0 +1 @@
Use the base opcode when comparing code objects to avoid interference from instrumentation

View File

@ -1798,28 +1798,26 @@ code_richcompare(PyObject *self, PyObject *other, int op)
for (int i = 0; i < Py_SIZE(co); i++) {
_Py_CODEUNIT co_instr = _PyCode_CODE(co)[i];
_Py_CODEUNIT cp_instr = _PyCode_CODE(cp)[i];
uint8_t co_code = co_instr.op.code;
uint8_t co_code = _Py_GetBaseOpcode(co, i);
uint8_t co_arg = co_instr.op.arg;
uint8_t cp_code = cp_instr.op.code;
uint8_t cp_code = _Py_GetBaseOpcode(cp, i);
uint8_t cp_arg = cp_instr.op.arg;
if (co_code == ENTER_EXECUTOR) {
const int exec_index = co_arg;
_PyExecutorObject *exec = co->co_executors->executors[exec_index];
co_code = exec->vm_data.opcode;
co_code = _PyOpcode_Deopt[exec->vm_data.opcode];
co_arg = exec->vm_data.oparg;
}
assert(co_code != ENTER_EXECUTOR);
co_code = _PyOpcode_Deopt[co_code];
if (cp_code == ENTER_EXECUTOR) {
const int exec_index = cp_arg;
_PyExecutorObject *exec = cp->co_executors->executors[exec_index];
cp_code = exec->vm_data.opcode;
cp_code = _PyOpcode_Deopt[exec->vm_data.opcode];
cp_arg = exec->vm_data.oparg;
}
assert(cp_code != ENTER_EXECUTOR);
cp_code = _PyOpcode_Deopt[cp_code];
if (co_code != cp_code || co_arg != cp_arg) {
goto unequal;