pass
"""))
+ def test_attribute_changes_are_watched(self):
+ # Just running to make sure it doesn't crash.
+ script_helper.assert_python_ok("-c", textwrap.dedent("""
+ from concurrent.futures import ThreadPoolExecutor
+ from unittest import TestCase
+ NTHREADS = 6
+ BOTTOM = 0
+ TOP = 1250000
+ class A:
+ attr = 10**1000
+ class TestType(TestCase):
+ def read(id0):
+ for _ in range(BOTTOM, TOP):
+ A.attr
+ def write(id0):
+ x = A.attr
+ x += 1
+ A.attr = x
+ with ThreadPoolExecutor(NTHREADS) as pool:
+ pool.submit(read, (1,))
+ pool.submit(write, (1,))
+ """))
def global_identity(x):
return x
--- /dev/null
+Fix missing type watcher when promoting attribute loads to constants in the JIT. Patch by Ken Jin. Reproducer by Yuancheng Jiang.
}
static JitOptRef
-lookup_attr(JitOptContext *ctx, _PyUOpInstruction *this_instr,
+lookup_attr(JitOptContext *ctx, _PyBloomFilter *dependencies, _PyUOpInstruction *this_instr,
PyTypeObject *type, PyObject *name, uint16_t immortal,
uint16_t mortal)
{
if (lookup) {
int opcode = _Py_IsImmortal(lookup) ? immortal : mortal;
REPLACE_OP(this_instr, opcode, 0, (uintptr_t)lookup);
+ PyType_Watch(TYPE_WATCHER_ID, (PyObject *)type);
+ _Py_BloomFilter_Add(dependencies, type);
return sym_new_const(ctx, lookup);
}
}
(void)descr;
PyTypeObject *type = (PyTypeObject *)sym_get_const(ctx, owner);
PyObject *name = get_co_name(ctx, oparg >> 1);
- attr = lookup_attr(ctx, this_instr, type, name,
+ attr = lookup_attr(ctx, dependencies, this_instr, type, name,
_POP_TOP_LOAD_CONST_INLINE_BORROW,
_POP_TOP_LOAD_CONST_INLINE);
}
(void)descr;
PyTypeObject *type = sym_get_type(owner);
PyObject *name = get_co_name(ctx, oparg >> 1);
- attr = lookup_attr(ctx, this_instr, type, name,
+ attr = lookup_attr(ctx, dependencies, this_instr, type, name,
_POP_TOP_LOAD_CONST_INLINE_BORROW,
_POP_TOP_LOAD_CONST_INLINE);
}
(void)descr;
PyTypeObject *type = sym_get_type(owner);
PyObject *name = get_co_name(ctx, oparg >> 1);
- attr = lookup_attr(ctx, this_instr, type, name,
+ attr = lookup_attr(ctx, dependencies, this_instr, type, name,
_POP_TOP_LOAD_CONST_INLINE_BORROW,
_POP_TOP_LOAD_CONST_INLINE);
}
(void)descr;
PyTypeObject *type = sym_get_type(owner);
PyObject *name = get_co_name(ctx, oparg >> 1);
- attr = lookup_attr(ctx, this_instr, type, name,
+ attr = lookup_attr(ctx, dependencies, this_instr, type, name,
_LOAD_CONST_UNDER_INLINE_BORROW,
_LOAD_CONST_UNDER_INLINE);
self = owner;
(void)descr;
PyTypeObject *type = sym_get_type(owner);
PyObject *name = get_co_name(ctx, oparg >> 1);
- attr = lookup_attr(ctx, this_instr, type, name,
+ attr = lookup_attr(ctx, dependencies, this_instr, type, name,
_LOAD_CONST_UNDER_INLINE_BORROW,
_LOAD_CONST_UNDER_INLINE);
self = owner;
(void)descr;
PyTypeObject *type = sym_get_type(owner);
PyObject *name = get_co_name(ctx, oparg >> 1);
- attr = lookup_attr(ctx, this_instr, type, name,
+ attr = lookup_attr(ctx, dependencies, this_instr, type, name,
_LOAD_CONST_UNDER_INLINE_BORROW,
_LOAD_CONST_UNDER_INLINE);
self = owner;
(void)descr;
PyTypeObject *type = (PyTypeObject *)sym_get_const(ctx, owner);
PyObject *name = get_co_name(ctx, oparg >> 1);
- attr = lookup_attr(ctx, this_instr, type, name,
+ attr = lookup_attr(ctx, dependencies, this_instr, type, name,
_POP_TOP_LOAD_CONST_INLINE_BORROW,
_POP_TOP_LOAD_CONST_INLINE);
stack_pointer[-1] = attr;
(void)descr;
PyTypeObject *type = sym_get_type(owner);
PyObject *name = get_co_name(ctx, oparg >> 1);
- attr = lookup_attr(ctx, this_instr, type, name,
+ attr = lookup_attr(ctx, dependencies, this_instr, type, name,
_LOAD_CONST_UNDER_INLINE_BORROW,
_LOAD_CONST_UNDER_INLINE);
self = owner;
(void)descr;
PyTypeObject *type = sym_get_type(owner);
PyObject *name = get_co_name(ctx, oparg >> 1);
- attr = lookup_attr(ctx, this_instr, type, name,
+ attr = lookup_attr(ctx, dependencies, this_instr, type, name,
_LOAD_CONST_UNDER_INLINE_BORROW,
_LOAD_CONST_UNDER_INLINE);
self = owner;
(void)descr;
PyTypeObject *type = sym_get_type(owner);
PyObject *name = get_co_name(ctx, oparg >> 1);
- attr = lookup_attr(ctx, this_instr, type, name,
+ attr = lookup_attr(ctx, dependencies, this_instr, type, name,
_POP_TOP_LOAD_CONST_INLINE_BORROW,
_POP_TOP_LOAD_CONST_INLINE);
stack_pointer[-1] = attr;
(void)descr;
PyTypeObject *type = sym_get_type(owner);
PyObject *name = get_co_name(ctx, oparg >> 1);
- attr = lookup_attr(ctx, this_instr, type, name,
+ attr = lookup_attr(ctx, dependencies, this_instr, type, name,
_POP_TOP_LOAD_CONST_INLINE_BORROW,
_POP_TOP_LOAD_CONST_INLINE);
stack_pointer[-1] = attr;
(void)descr;
PyTypeObject *type = sym_get_type(owner);
PyObject *name = get_co_name(ctx, oparg >> 1);
- attr = lookup_attr(ctx, this_instr, type, name,
+ attr = lookup_attr(ctx, dependencies, this_instr, type, name,
_LOAD_CONST_UNDER_INLINE_BORROW,
_LOAD_CONST_UNDER_INLINE);
self = owner;