Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

bpo-45340: Don't create object dictionaries unless actually needed#28802

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from1 commit
Commits
Show all changes
25 commits
Select commitHold shift + click to select a range
8214006
Add insertion order bit-vector to dict values to allow dicts to share…
markshannonSep 21, 2021
45c9814
Add NEWS
markshannonSep 23, 2021
c3de09e
Never change types' cached keys. It could invalidate inline attribute…
markshannonSep 23, 2021
58dd2a0
Lazily create object dictionaries. Work in progress.
markshannonSep 23, 2021
769183a
Restore specialization for inline attributes.
markshannonSep 30, 2021
1e6cd1f
Turn on stats
markshannonSep 30, 2021
a8fbb34
Fix specialization of LOAD/STORE_ATTR.
markshannonOct 1, 2021
37d8cc6
Turn off stats.
markshannonOct 1, 2021
0e022f9
Don't update shared keys version for deletion of value.
markshannonOct 4, 2021
ddd2e2c
Merge main into inline-attributes-with-opt
markshannonOct 6, 2021
e979575
Fix refrence leak.
markshannonOct 6, 2021
42361ad
Change 'InlineAttribute' to 'InstanceAttribute' as they are not inlin…
markshannonOct 6, 2021
e9b09d5
Merge branch 'main' into inline-attributes-with-opt
markshannonOct 6, 2021
70dc34f
Update gdb support to handle instance values.
markshannonOct 7, 2021
022f2c5
Rename SPLIT_KEYS opcodes to INSTANCE_VALUE.
markshannonOct 7, 2021
4ec5f11
Tidy test_gc
markshannonOct 7, 2021
1818a5a
Don't lose errors.
markshannonOct 7, 2021
bfc7be0
Make sure order is updated when deleting from values array.
markshannonOct 7, 2021
62a3a59
Update test_dict.
markshannonOct 7, 2021
7978220
Add NEWS
markshannonOct 8, 2021
b25b1d9
Merge branch 'main' into inline-attributes-with-opt
markshannonOct 12, 2021
7b2efa4
Merge branch 'main' into inline-attributes-with-opt
markshannonOct 12, 2021
459e29e
Make sure that instance dicts are GC tracked when necessary.
markshannonOct 12, 2021
83b90c5
Support older versions of Python in gdb.
markshannonOct 12, 2021
8c894f3
Rename function and move to internal header.
markshannonOct 12, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
PrevPrevious commit
NextNext commit
Restore specialization for inline attributes.
  • Loading branch information
@markshannon
markshannon committedSep 30, 2021
commit769183a45ffe056353848c220b517856e1abf35c
19 changes: 10 additions & 9 deletionsInclude/opcode.h
View file
Open in desktop

Some generated files are not rendered by default. Learn more abouthow customized files appear on GitHub.

1 change: 1 addition & 0 deletionsLib/opcode.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -242,6 +242,7 @@ def jabs_op(name, op):
"LOAD_METHOD_CACHED",
"LOAD_METHOD_CLASS",
"LOAD_METHOD_MODULE",
"LOAD_METHOD_NO_DICT",
"STORE_ATTR_ADAPTIVE",
"STORE_ATTR_SPLIT_KEYS",
"STORE_ATTR_SLOT",
Expand Down
70 changes: 36 additions & 34 deletionsPython/ceval.c
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -3615,6 +3615,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr
}

TARGET(LOAD_ATTR_SPLIT_KEYS): {
/* TO DO: rename instruction */
assert(cframe.use_tracing == 0);
PyObject *owner = TOP();
PyObject *res;
Expand All@@ -3625,11 +3626,10 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr
assert(cache1->tp_version != 0);
DEOPT_IF(tp->tp_version_tag != cache1->tp_version, LOAD_ATTR);
assert(tp->tp_dictoffset > 0);
PyDictObject *dict = *(PyDictObject **)(((char *)owner) + tp->tp_dictoffset);
DEOPT_IF(dict == NULL, LOAD_ATTR);
assert(PyDict_CheckExact((PyObject *)dict));
DEOPT_IF(dict->ma_keys->dk_version != cache1->dk_version_or_hint, LOAD_ATTR);
res = dict->ma_values->values[cache0->index];
assert(tp->tp_inline_values_offset > 0);
PyDictValues *values = *(PyDictValues **)(((char *)owner) + tp->tp_inline_values_offset);
DEOPT_IF(values == NULL, LOAD_ATTR);
res = values->values[cache0->index];
DEOPT_IF(res == NULL, LOAD_ATTR);
STAT_INC(LOAD_ATTR, hit);
record_cache_hit(cache0);
Expand DownExpand Up@@ -3722,6 +3722,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr
}

TARGET(STORE_ATTR_SPLIT_KEYS): {
/* TO DO: rename instruction */
assert(cframe.use_tracing == 0);
PyObject *owner = TOP();
PyTypeObject *tp = Py_TYPE(owner);
Expand All@@ -3731,31 +3732,23 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr
assert(cache1->tp_version != 0);
DEOPT_IF(tp->tp_version_tag != cache1->tp_version, STORE_ATTR);
assert(tp->tp_dictoffset > 0);
PyDictObject *dict = *(PyDictObject **)(((char *)owner) + tp->tp_dictoffset);
DEOPT_IF(dict == NULL, STORE_ATTR);
assert(PyDict_CheckExact((PyObject *)dict));
DEOPT_IF(dict->ma_keys->dk_version != cache1->dk_version_or_hint, STORE_ATTR);
assert(tp->tp_inline_values_offset > 0);
PyDictValues *values = *(PyDictValues **)(((char *)owner) + tp->tp_inline_values_offset);
DEOPT_IF(values == NULL, STORE_ATTR);
STAT_INC(STORE_ATTR, hit);
record_cache_hit(cache0);
int index = cache0->index;
STACK_SHRINK(1);
PyObject *value = POP();
PyObject *old_value =dict->ma_values->values[index];
dict->ma_values->values[index] = value;
PyObject *old_value =values->values[index];
values->values[index] = value;
if (old_value == NULL) {
assert(index < 16);
dict->ma_values->mv_order = (dict->ma_values->mv_order << 4) | index;
dict->ma_used++;
values->mv_order = (values->mv_order << 4) | index;
}
else {
Py_DECREF(old_value);
}
/* 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 = DICT_NEXT_VERSION();
Py_DECREF(owner);
DISPATCH();
}
Expand DownExpand Up@@ -4470,21 +4463,31 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr
_PyObjectCache *cache2 = &caches[-2].obj;

DEOPT_IF(self_cls->tp_version_tag != cache1->tp_version, LOAD_METHOD);
assert(cache1->dk_version_or_hint != 0);
assert(cache1->tp_version != 0);
assert(self_cls->tp_dictoffset >= 0);
assert(Py_TYPE(self_cls)->tp_dictoffset > 0);

// inline version of _PyObject_GetDictPtr for offset >= 0
PyObject *dict = self_cls->tp_dictoffset != 0 ?
*(PyObject **) ((char *)self + self_cls->tp_dictoffset) : NULL;

// Ensure self.__dict__ didn't modify keys.
// Don't care if self has no dict, it could be builtin or __slots__.
DEOPT_IF(dict != NULL &&
((PyDictObject *)dict)->ma_keys->dk_version !=
cache1->dk_version_or_hint, LOAD_METHOD);
assert(self_cls->tp_dictoffset > 0);
assert(self_cls->tp_inline_values_offset > 0);
PyDictObject *dict = *(PyDictObject **)(((char *)self) + self_cls->tp_dictoffset);
DEOPT_IF(dict != NULL, LOAD_METHOD);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Wait is this due to the new scheme that objects shouldn't have dict unless really required?

Copy link
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Yes, it is. We assume that having no__dict__ is the most common case, so it isn't worth bothering to check for the shared key dict case.

DEOPT_IF(((PyHeapTypeObject *)self_cls)->ht_cached_keys->dk_version != cache1->dk_version_or_hint, LOAD_METHOD);
STAT_INC(LOAD_METHOD, hit);
record_cache_hit(cache0);
PyObject *res = cache2->obj;
assert(res != NULL);
assert(_PyType_HasFeature(Py_TYPE(res), Py_TPFLAGS_METHOD_DESCRIPTOR));
Py_INCREF(res);
SET_TOP(res);
PUSH(self);
DISPATCH();
}

TARGET(LOAD_METHOD_NO_DICT): {
PyObject *self = TOP();
PyTypeObject *self_cls = Py_TYPE(self);
SpecializedCacheEntry *caches = GET_CACHE();
_PyAdaptiveEntry *cache0 = &caches[0].adaptive;
_PyAttrCache *cache1 = &caches[-1].attr;
_PyObjectCache *cache2 = &caches[-2].obj;
DEOPT_IF(self_cls->tp_version_tag != cache1->tp_version, LOAD_METHOD);
assert(self_cls->tp_dictoffset == 0);
STAT_INC(LOAD_METHOD, hit);
record_cache_hit(cache0);
PyObject *res = cache2->obj;
Expand DownExpand Up@@ -4526,7 +4529,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr
record_cache_hit(cache0);
PyObject *res = cache2->obj;
assert(res != NULL);
assert(_PyType_HasFeature(Py_TYPE(res), Py_TPFLAGS_METHOD_DESCRIPTOR));
Py_INCREF(res);
SET_TOP(NULL);
Py_DECREF(cls);
Expand Down
16 changes: 8 additions & 8 deletionsPython/opcode_targets.h
View file
Open in desktop

Some generated files are not rendered by default. Learn more abouthow customized files appear on GitHub.

Loading

[8]ページ先頭

©2009-2025 Movatter.jp