((INTERP)->dict_state.global_version += DICT_VERSION_INCREMENT)
#endif
-void
+PyAPI_FUNC(void)
_PyDict_SendEvent(int watcher_bits,
PyDict_WatchEvent event,
PyDictObject *mp,
[STORE_ATTR] = { true, INSTR_FMT_IBC000, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
[STORE_ATTR_INSTANCE_VALUE] = { true, INSTR_FMT_IXC000, HAS_DEOPT_FLAG | HAS_EXIT_FLAG },
[STORE_ATTR_SLOT] = { true, INSTR_FMT_IXC000, HAS_EXIT_FLAG },
- [STORE_ATTR_WITH_HINT] = { true, INSTR_FMT_IBC000, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG },
+ [STORE_ATTR_WITH_HINT] = { true, INSTR_FMT_IBC000, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ESCAPES_FLAG },
[STORE_DEREF] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_FREE_FLAG | HAS_ESCAPES_FLAG },
[STORE_FAST] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_LOCAL_FLAG },
[STORE_FAST_LOAD_FAST] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_LOCAL_FLAG },
[STORE_ATTR] = { .nuops = 1, .uops = { { _STORE_ATTR, 0, 0 } } },
[STORE_ATTR_INSTANCE_VALUE] = { .nuops = 3, .uops = { { _GUARD_TYPE_VERSION, 2, 1 }, { _GUARD_DORV_NO_DICT, 0, 0 }, { _STORE_ATTR_INSTANCE_VALUE, 1, 3 } } },
[STORE_ATTR_SLOT] = { .nuops = 2, .uops = { { _GUARD_TYPE_VERSION, 2, 1 }, { _STORE_ATTR_SLOT, 1, 3 } } },
+ [STORE_ATTR_WITH_HINT] = { .nuops = 2, .uops = { { _GUARD_TYPE_VERSION, 2, 1 }, { _STORE_ATTR_WITH_HINT, 1, 3 } } },
[STORE_DEREF] = { .nuops = 1, .uops = { { _STORE_DEREF, 0, 0 } } },
[STORE_FAST] = { .nuops = 1, .uops = { { _STORE_FAST, 0, 0 } } },
[STORE_FAST_LOAD_FAST] = { .nuops = 2, .uops = { { _STORE_FAST, 5, 0 }, { _LOAD_FAST, 6, 0 } } },
#define _STORE_ATTR 436
#define _STORE_ATTR_INSTANCE_VALUE 437
#define _STORE_ATTR_SLOT 438
-#define _STORE_ATTR_WITH_HINT STORE_ATTR_WITH_HINT
+#define _STORE_ATTR_WITH_HINT 439
#define _STORE_DEREF STORE_DEREF
-#define _STORE_FAST 439
-#define _STORE_FAST_0 440
-#define _STORE_FAST_1 441
-#define _STORE_FAST_2 442
-#define _STORE_FAST_3 443
-#define _STORE_FAST_4 444
-#define _STORE_FAST_5 445
-#define _STORE_FAST_6 446
-#define _STORE_FAST_7 447
+#define _STORE_FAST 440
+#define _STORE_FAST_0 441
+#define _STORE_FAST_1 442
+#define _STORE_FAST_2 443
+#define _STORE_FAST_3 444
+#define _STORE_FAST_4 445
+#define _STORE_FAST_5 446
+#define _STORE_FAST_6 447
+#define _STORE_FAST_7 448
#define _STORE_FAST_LOAD_FAST STORE_FAST_LOAD_FAST
#define _STORE_FAST_STORE_FAST STORE_FAST_STORE_FAST
#define _STORE_GLOBAL STORE_GLOBAL
#define _STORE_NAME STORE_NAME
#define _STORE_SLICE STORE_SLICE
-#define _STORE_SUBSCR 448
+#define _STORE_SUBSCR 449
#define _STORE_SUBSCR_DICT STORE_SUBSCR_DICT
#define _STORE_SUBSCR_LIST_INT STORE_SUBSCR_LIST_INT
#define _SWAP SWAP
-#define _TIER2_RESUME_CHECK 449
-#define _TO_BOOL 450
+#define _TIER2_RESUME_CHECK 450
+#define _TO_BOOL 451
#define _TO_BOOL_BOOL TO_BOOL_BOOL
#define _TO_BOOL_INT TO_BOOL_INT
#define _TO_BOOL_LIST TO_BOOL_LIST
#define _UNARY_NEGATIVE UNARY_NEGATIVE
#define _UNARY_NOT UNARY_NOT
#define _UNPACK_EX UNPACK_EX
-#define _UNPACK_SEQUENCE 451
+#define _UNPACK_SEQUENCE 452
#define _UNPACK_SEQUENCE_LIST UNPACK_SEQUENCE_LIST
#define _UNPACK_SEQUENCE_TUPLE UNPACK_SEQUENCE_TUPLE
#define _UNPACK_SEQUENCE_TWO_TUPLE UNPACK_SEQUENCE_TWO_TUPLE
#define _WITH_EXCEPT_START WITH_EXCEPT_START
#define _YIELD_VALUE YIELD_VALUE
-#define MAX_UOP_ID 451
+#define MAX_UOP_ID 452
#ifdef __cplusplus
}
[_LOAD_ATTR_CLASS] = HAS_ARG_FLAG | HAS_OPARG_AND_1_FLAG,
[_GUARD_DORV_NO_DICT] = HAS_DEOPT_FLAG,
[_STORE_ATTR_INSTANCE_VALUE] = 0,
+ [_STORE_ATTR_WITH_HINT] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG,
[_STORE_ATTR_SLOT] = 0,
[_COMPARE_OP] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG,
[_COMPARE_OP_FLOAT] = HAS_ARG_FLAG,
[_STORE_ATTR] = "_STORE_ATTR",
[_STORE_ATTR_INSTANCE_VALUE] = "_STORE_ATTR_INSTANCE_VALUE",
[_STORE_ATTR_SLOT] = "_STORE_ATTR_SLOT",
+ [_STORE_ATTR_WITH_HINT] = "_STORE_ATTR_WITH_HINT",
[_STORE_DEREF] = "_STORE_DEREF",
[_STORE_FAST] = "_STORE_FAST",
[_STORE_FAST_0] = "_STORE_FAST_0",
return 1;
case _STORE_ATTR_INSTANCE_VALUE:
return 2;
+ case _STORE_ATTR_WITH_HINT:
+ return 2;
case _STORE_ATTR_SLOT:
return 2;
case _COMPARE_OP:
_GUARD_DORV_NO_DICT +
_STORE_ATTR_INSTANCE_VALUE;
- inst(STORE_ATTR_WITH_HINT, (unused/1, type_version/2, hint/1, value, owner --)) {
- PyTypeObject *tp = Py_TYPE(owner);
- assert(type_version != 0);
- DEOPT_IF(tp->tp_version_tag != type_version);
- assert(tp->tp_flags & Py_TPFLAGS_MANAGED_DICT);
+ op(_STORE_ATTR_WITH_HINT, (hint/1, value, owner --)) {
+ assert(Py_TYPE(owner)->tp_flags & Py_TPFLAGS_MANAGED_DICT);
PyDictObject *dict = _PyObject_GetManagedDict(owner);
DEOPT_IF(dict == NULL);
assert(PyDict_CheckExact((PyObject *)dict));
Py_DECREF(owner);
}
+ macro(STORE_ATTR_WITH_HINT) =
+ unused/1 +
+ _GUARD_TYPE_VERSION +
+ _STORE_ATTR_WITH_HINT;
+
op(_STORE_ATTR_SLOT, (index/1, value, owner --)) {
char *addr = (char *)owner + index;
STAT_INC(STORE_ATTR, hit);
break;
}
- /* _STORE_ATTR_WITH_HINT is not a viable micro-op for tier 2 because it has unused cache entries */
+ case _STORE_ATTR_WITH_HINT: {
+ PyObject *owner;
+ PyObject *value;
+ oparg = CURRENT_OPARG();
+ owner = stack_pointer[-1];
+ value = stack_pointer[-2];
+ uint16_t hint = (uint16_t)CURRENT_OPERAND();
+ assert(Py_TYPE(owner)->tp_flags & Py_TPFLAGS_MANAGED_DICT);
+ PyDictObject *dict = _PyObject_GetManagedDict(owner);
+ if (dict == NULL) {
+ UOP_STAT_INC(uopcode, miss);
+ JUMP_TO_JUMP_TARGET();
+ }
+ assert(PyDict_CheckExact((PyObject *)dict));
+ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
+ if (hint >= (size_t)dict->ma_keys->dk_nentries) {
+ UOP_STAT_INC(uopcode, miss);
+ JUMP_TO_JUMP_TARGET();
+ }
+ PyObject *old_value;
+ uint64_t new_version;
+ if (DK_IS_UNICODE(dict->ma_keys)) {
+ PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(dict->ma_keys) + hint;
+ if (ep->me_key != name) {
+ UOP_STAT_INC(uopcode, miss);
+ JUMP_TO_JUMP_TARGET();
+ }
+ old_value = ep->me_value;
+ if (old_value == NULL) {
+ UOP_STAT_INC(uopcode, miss);
+ JUMP_TO_JUMP_TARGET();
+ }
+ new_version = _PyDict_NotifyEvent(tstate->interp, PyDict_EVENT_MODIFIED, dict, name, value);
+ ep->me_value = value;
+ }
+ else {
+ PyDictKeyEntry *ep = DK_ENTRIES(dict->ma_keys) + hint;
+ if (ep->me_key != name) {
+ UOP_STAT_INC(uopcode, miss);
+ JUMP_TO_JUMP_TARGET();
+ }
+ old_value = ep->me_value;
+ if (old_value == NULL) {
+ UOP_STAT_INC(uopcode, miss);
+ JUMP_TO_JUMP_TARGET();
+ }
+ new_version = _PyDict_NotifyEvent(tstate->interp, PyDict_EVENT_MODIFIED, dict, name, value);
+ ep->me_value = value;
+ }
+ Py_DECREF(old_value);
+ STAT_INC(STORE_ATTR, hit);
+ /* Ensure dict is GC tracked if it needs to be */
+ if (!_PyObject_GC_IS_TRACKED(dict) && _PyObject_GC_MAY_BE_TRACKED(value)) {
+ _PyObject_GC_TRACK(dict);
+ }
+ /* PEP 509 */
+ dict->ma_version_tag = new_version;
+ Py_DECREF(owner);
+ stack_pointer += -2;
+ break;
+ }
case _STORE_ATTR_SLOT: {
PyObject *owner;
PyObject *owner;
PyObject *value;
/* Skip 1 cache entry */
+ // _GUARD_TYPE_VERSION
owner = stack_pointer[-1];
- value = stack_pointer[-2];
- uint32_t type_version = read_u32(&this_instr[2].cache);
- uint16_t hint = read_u16(&this_instr[4].cache);
- PyTypeObject *tp = Py_TYPE(owner);
- assert(type_version != 0);
- DEOPT_IF(tp->tp_version_tag != type_version, STORE_ATTR);
- assert(tp->tp_flags & Py_TPFLAGS_MANAGED_DICT);
- PyDictObject *dict = _PyObject_GetManagedDict(owner);
- DEOPT_IF(dict == NULL, STORE_ATTR);
- 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;
- uint64_t new_version;
- if (DK_IS_UNICODE(dict->ma_keys)) {
- PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(dict->ma_keys) + hint;
- DEOPT_IF(ep->me_key != name, STORE_ATTR);
- old_value = ep->me_value;
- DEOPT_IF(old_value == NULL, STORE_ATTR);
- new_version = _PyDict_NotifyEvent(tstate->interp, PyDict_EVENT_MODIFIED, dict, name, value);
- ep->me_value = value;
- }
- else {
- PyDictKeyEntry *ep = DK_ENTRIES(dict->ma_keys) + hint;
- DEOPT_IF(ep->me_key != name, STORE_ATTR);
- old_value = ep->me_value;
- DEOPT_IF(old_value == NULL, STORE_ATTR);
- new_version = _PyDict_NotifyEvent(tstate->interp, PyDict_EVENT_MODIFIED, dict, name, value);
- ep->me_value = value;
+ {
+ uint32_t type_version = read_u32(&this_instr[2].cache);
+ PyTypeObject *tp = Py_TYPE(owner);
+ assert(type_version != 0);
+ DEOPT_IF(tp->tp_version_tag != type_version, STORE_ATTR);
}
- Py_DECREF(old_value);
- STAT_INC(STORE_ATTR, hit);
- /* Ensure dict is GC tracked if it needs to be */
- if (!_PyObject_GC_IS_TRACKED(dict) && _PyObject_GC_MAY_BE_TRACKED(value)) {
- _PyObject_GC_TRACK(dict);
+ // _STORE_ATTR_WITH_HINT
+ value = stack_pointer[-2];
+ {
+ uint16_t hint = read_u16(&this_instr[4].cache);
+ assert(Py_TYPE(owner)->tp_flags & Py_TPFLAGS_MANAGED_DICT);
+ PyDictObject *dict = _PyObject_GetManagedDict(owner);
+ DEOPT_IF(dict == NULL, STORE_ATTR);
+ 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;
+ uint64_t new_version;
+ if (DK_IS_UNICODE(dict->ma_keys)) {
+ PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(dict->ma_keys) + hint;
+ DEOPT_IF(ep->me_key != name, STORE_ATTR);
+ old_value = ep->me_value;
+ DEOPT_IF(old_value == NULL, STORE_ATTR);
+ new_version = _PyDict_NotifyEvent(tstate->interp, PyDict_EVENT_MODIFIED, dict, name, value);
+ ep->me_value = value;
+ }
+ else {
+ PyDictKeyEntry *ep = DK_ENTRIES(dict->ma_keys) + hint;
+ DEOPT_IF(ep->me_key != name, STORE_ATTR);
+ old_value = ep->me_value;
+ DEOPT_IF(old_value == NULL, STORE_ATTR);
+ new_version = _PyDict_NotifyEvent(tstate->interp, PyDict_EVENT_MODIFIED, dict, name, value);
+ ep->me_value = value;
+ }
+ Py_DECREF(old_value);
+ STAT_INC(STORE_ATTR, hit);
+ /* Ensure dict is GC tracked if it needs to be */
+ if (!_PyObject_GC_IS_TRACKED(dict) && _PyObject_GC_MAY_BE_TRACKED(value)) {
+ _PyObject_GC_TRACK(dict);
+ }
+ /* PEP 509 */
+ dict->ma_version_tag = new_version;
+ Py_DECREF(owner);
}
- /* PEP 509 */
- dict->ma_version_tag = new_version;
- Py_DECREF(owner);
stack_pointer += -2;
DISPATCH();
}
break;
}
- /* _STORE_ATTR_WITH_HINT is not a viable micro-op for tier 2 */
+ case _STORE_ATTR_WITH_HINT: {
+ stack_pointer += -2;
+ break;
+ }
case _STORE_ATTR_SLOT: {
stack_pointer += -2;