Skip to content

Commit 4dc64c8

Browse files
committed
Share lazy import rebinding
Remember the namespace where lookup found the placeholder and use one helper to resolve and replace it. Only replace a binding that still holds the same placeholder, preserving assignments and deletions during import. Check and replace ordinary dict entries atomically. Keep the mapping protocol for custom namespaces and allow reads from readonly namespaces. Reuse the global lookup helper in the eval loop and remove the duplicate.
1 parent 917df44 commit 4dc64c8

13 files changed

Lines changed: 302 additions & 410 deletions

‎Include/internal/pycore_dict.h‎

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@ PyAPI_FUNC(int) _PyDict_DelItemIf(PyObject *mp, PyObject *key,
2323
int (*predicate)(PyObject *value, void *arg),
2424
void *arg);
2525

26+
// Atomically replace an existing value if it is expected (by identity).
27+
// Return 1 if replaced, 0 if absent or different, or -1 on error.
28+
extern int _PyDict_ReplaceItemIf(PyObject *dict, PyObject *key,
29+
PyObject *expected, PyObject *replacement);
30+
2631
// "KnownHash" variants
2732
// Export for '_asyncio' shared extension
2833
PyAPI_FUNC(int) _PyDict_SetItem_KnownHash(PyObject *mp, PyObject *key,
@@ -147,8 +152,8 @@ PyAPI_FUNC(Py_ssize_t) _PyDictKeys_StringLookup(PyDictKeysObject* dictkeys, PyOb
147152
*/
148153
PyAPI_FUNC(Py_ssize_t) _PyDictKeys_StringLookupAndVersion(PyDictKeysObject* dictkeys, PyObject *key, uint32_t *version);
149154
PyAPI_FUNC(Py_ssize_t) _PyDictKeys_StringLookupSplit(PyDictKeysObject* dictkeys, PyObject *key);
150-
PyAPI_FUNC(PyObject *)_PyDict_LoadGlobal(PyDictObject *, PyDictObject *, PyObject *);
151-
PyAPI_FUNC(void) _PyDict_LoadGlobalStackRef(PyDictObject *, PyDictObject *, PyObject *, _PyStackRef *);
155+
// Return the borrowed source dictionary, or NULL if absent or on error.
156+
PyAPI_FUNC(PyObject *) _PyDict_LoadGlobalStackRef(PyDictObject *, PyDictObject *, PyObject *, _PyStackRef *);
152157

153158
// Loads the __builtins__ object from the globals dict. Returns a new reference.
154159
extern PyObject *_PyDict_LoadBuiltinsFromGlobals(PyObject *globals);

‎Include/internal/pycore_lazyimportobject.h‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@ PyAPI_FUNC(PyObject *) _PyLazyImport_New(
2020

2121
extern int _PyLazyImport_IsResolving(PyThreadState *tstate, PyObject *op);
2222

23+
// Resolve a placeholder and replace its binding only if it is unchanged.
24+
// namespace is the source captured during lookup, before resolution runs.
25+
PyAPI_FUNC(PyObject *) _PyLazyImport_Reify(
26+
PyThreadState *tstate, PyObject *placeholder,
27+
PyObject *name, PyObject *ns);
28+
2329
#ifdef __cplusplus
2430
}
2531
#endif

‎Include/internal/pycore_opcode_metadata.h‎

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎Include/internal/pycore_uop_metadata.h‎

Lines changed: 15 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎Modules/_testinternalcapi/test_cases.c.h‎

Lines changed: 30 additions & 106 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)