8000 gh-109052: Use the base opcode when comparing code objects (gh-109107) · python/cpython@057bc72 · GitHub
[go: up one dir, main page]

Skip to content

Commit 057bc72

Browse files
gh-109052: Use the base opcode when comparing code objects (gh-109107)
1 parent a56c928 commit 057bc72

File tree

3 files changed

+24
-6
lines changed

3 files changed

+24
-6
lines changed

Lib/test/test_code.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,25 @@ def test_code_hash_uses_bytecode(self):
505505
self.assertNotEqual(c, c1)
506506
self.assertNotEqual(hash(c), hash(c1))
507507

508+
@cpython_only
509+
def test_code_equal_with_instrumentation(self):
510+
""" GH-109052
511+
512+
Make sure the instrumentation doesn't affect the code equality
513+
The validity of this test relies on the fact that "x is x" and
514+
"x in x" have only one different instruction and the instructions
515+
have the same argument.
516+
517+
"""
518+
code1 = compile("x is x", "example.py", "eval")
519+
code2 = compile("x in x", "example.py", "eval")
520+
sys._getframe().f_trace_opcodes = True
521+
sys.settrace(lambda *args: None)
522+
exec(code1, {'x': []})
523+
exec(code2, {'x': []})
524+
self.assertNotEqual(code1, code2)
525+
sys.settrace(None)
526+
508527

509528
def isinterned(s):
510529
return s is sys.intern(('_' + s + '_')[1:-1])
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Use the base opcode when comparing code objects to avoid interference from instrumentation

Objects/codeobject.c

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1798,28 +1798,26 @@ code_richcompare(PyObject *self, PyObject *other, int op)
17981798
for (int i = 0; i < Py_SIZE(co); i++) {
17991799
_Py_CODEUNIT co_instr = _PyCode_CODE(co)[i];
18001800
_Py_CODEUNIT cp_instr = _PyCode_CODE(cp)[i];
1801-
uint8_t co_code = co_instr.op.code;
1801+
uint8_t co_code = _Py_GetBaseOpcode(co, i);
18021802
uint8_t co_arg = co_instr.op.arg;
1803-
uint8_t cp_code = cp_instr.op.code;
1803+
uint8_t cp_code = _Py_GetBaseOpcode(cp, i);
18041804
uint8_t cp_arg = cp_instr.op.arg;
18051805

18061806
if (co_code == ENTER_EXECUTOR) {
18071807
const int exec_index = co_arg;
18081808
_PyExecutorObject *exec = co->co_executors->executors[exec_index];
1809-
co_code = exec->vm_data.opcode;
1809+
co_code = _PyOpcode_Deopt[exec->vm_data.opcode];
18101810
co_arg = exec->vm_data.oparg;
18111811
}
18121812
assert(co_code != ENTER_EXECUTOR);
1813-
co_code = _PyOpcode_Deopt[co_code];
18141813

18151814
if (cp_code == ENTER_EXECUTOR) {
18161815
const int exec_index = cp_arg;
18171816
_PyExecutorObject *exec = cp->co_executors->executors[exec_index];
1818-
cp_code = exec->vm_data.opcode;
1817+
cp_code = _PyOpcode_Deopt[exec->vm_data.opcode];
18191818
cp_arg = exec->vm_data.oparg;
18201819
}
18211820
assert(cp_code != ENTER_EXECUTOR);
1822-
cp_code = _PyOpcode_Deopt[cp_code];
18231821

18241822
if (co_code != cp_code || co_arg != cp_arg) {
18251823
goto unequal;

0 commit comments

Comments
 (0)
0