if caches:
cache_info = []
+ cache_offset = offset
for name, size in _cache_format[opname[deop]].items():
- data = code[offset + 2: offset + 2 + 2 * size]
+ data = code[cache_offset + 2: cache_offset + 2 + 2 * size]
+ cache_offset += size * 2
cache_info.append((name, size, data))
else:
cache_info = None
{'a':1, 'b':2}
)
+ def test_125868(self):
+
+ def make_special_dict():
+ """Create a dictionary an object with a this table:
+ index | key | value
+ ----- | --- | -----
+ 0 | 'b' | 'value'
+ 1 | 'b' | NULL
+ """
+ class A:
+ pass
+ a = A()
+ a.a = 1
+ a.b = 2
+ d = a.__dict__.copy()
+ del d['a']
+ del d['b']
+ d['b'] = "value"
+ return d
+
+ class NoInlineAorB:
+ pass
+ for i in range(ord('c'), ord('z')):
+ setattr(NoInlineAorB(), chr(i), i)
+
+ c = NoInlineAorB()
+ c.a = 0
+ c.b = 1
+ self.assertFalse(_testinternalcapi.has_inline_values(c))
+
+ def f(o, n):
+ for i in range(n):
+ o.b = i
+ # Prime f to store to dict slot 1
+ f(c, 100)
+
+ test_obj = NoInlineAorB()
+ test_obj.__dict__ = make_special_dict()
+ self.assertEqual(test_obj.b, "value")
+
+ #This should set x.b = 0
+ f(test_obj, 1)
+ self.assertEqual(test_obj.b, 0)
+
if __name__ == "__main__":
unittest.main()
--- /dev/null
+It was possible in 3.14.0a1 only for attribute lookup to give the wrong
+value. This was due to an incorrect specialization in very specific
+circumstances. This is fixed in 3.14.0a2.
assert(PyDict_CheckExact((PyObject *)dict));
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
DEOPT_IF(hint >= (size_t)dict->ma_keys->dk_nentries);
- PyObject *old_value;
DEOPT_IF(!DK_IS_UNICODE(dict->ma_keys));
PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(dict->ma_keys) + hint;
DEOPT_IF(ep->me_key != name);
+ PyObject *old_value = ep->me_value;
+ DEOPT_IF(old_value == NULL);
/* Ensure dict is GC tracked if it needs to be */
if (!_PyObject_GC_IS_TRACKED(dict) && _PyObject_GC_MAY_BE_TRACKED(PyStackRef_AsPyObjectBorrow(value))) {
_PyObject_GC_TRACK(dict);
}
- old_value = ep->me_value;
- PyDict_WatchEvent event = old_value == NULL ? PyDict_EVENT_ADDED : PyDict_EVENT_MODIFIED;
- _PyDict_NotifyEvent(tstate->interp, event, dict, name, PyStackRef_AsPyObjectBorrow(value));
+ _PyDict_NotifyEvent(tstate->interp, PyDict_EVENT_MODIFIED, dict, name, PyStackRef_AsPyObjectBorrow(value));
ep->me_value = PyStackRef_AsPyObjectSteal(value);
// old_value should be DECREFed after GC track checking is done, if not, it could raise a segmentation fault,
// when dict only holds the strong reference to value in ep->me_value.
UOP_STAT_INC(uopcode, miss);
JUMP_TO_JUMP_TARGET();
}
- PyObject *old_value;
if (!DK_IS_UNICODE(dict->ma_keys)) {
UOP_STAT_INC(uopcode, miss);
JUMP_TO_JUMP_TARGET();
UOP_STAT_INC(uopcode, miss);
JUMP_TO_JUMP_TARGET();
}
+ PyObject *old_value = ep->me_value;
+ if (old_value == NULL) {
+ UOP_STAT_INC(uopcode, miss);
+ JUMP_TO_JUMP_TARGET();
+ }
/* Ensure dict is GC tracked if it needs to be */
if (!_PyObject_GC_IS_TRACKED(dict) && _PyObject_GC_MAY_BE_TRACKED(PyStackRef_AsPyObjectBorrow(value))) {
_PyObject_GC_TRACK(dict);
}
- old_value = ep->me_value;
- PyDict_WatchEvent event = old_value == NULL ? PyDict_EVENT_ADDED : PyDict_EVENT_MODIFIED;
_PyFrame_SetStackPointer(frame, stack_pointer);
- _PyDict_NotifyEvent(tstate->interp, event, dict, name, PyStackRef_AsPyObjectBorrow(value));
+ _PyDict_NotifyEvent(tstate->interp, PyDict_EVENT_MODIFIED, dict, name, PyStackRef_AsPyObjectBorrow(value));
stack_pointer = _PyFrame_GetStackPointer(frame);
ep->me_value = PyStackRef_AsPyObjectSteal(value);
// old_value should be DECREFed after GC track checking is done, if not, it could raise a segmentation fault,
assert(PyDict_CheckExact((PyObject *)dict));
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
DEOPT_IF(hint >= (size_t)dict->ma_keys->dk_nentries, STORE_ATTR);
- PyObject *old_value;
DEOPT_IF(!DK_IS_UNICODE(dict->ma_keys), STORE_ATTR);
PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(dict->ma_keys) + hint;
DEOPT_IF(ep->me_key != name, STORE_ATTR);
+ PyObject *old_value = ep->me_value;
+ DEOPT_IF(old_value == NULL, STORE_ATTR);
/* Ensure dict is GC tracked if it needs to be */
if (!_PyObject_GC_IS_TRACKED(dict) && _PyObject_GC_MAY_BE_TRACKED(PyStackRef_AsPyObjectBorrow(value))) {
_PyObject_GC_TRACK(dict);
}
- old_value = ep->me_value;
- PyDict_WatchEvent event = old_value == NULL ? PyDict_EVENT_ADDED : PyDict_EVENT_MODIFIED;
_PyFrame_SetStackPointer(frame, stack_pointer);
- _PyDict_NotifyEvent(tstate->interp, event, dict, name, PyStackRef_AsPyObjectBorrow(value));
+ _PyDict_NotifyEvent(tstate->interp, PyDict_EVENT_MODIFIED, dict, name, PyStackRef_AsPyObjectBorrow(value));
stack_pointer = _PyFrame_GetStackPointer(frame);
ep->me_value = PyStackRef_AsPyObjectSteal(value);
// old_value should be DECREFed after GC track checking is done, if not, it could raise a segmentation fault,