Visitar URL original
[3.15] gh-142349: Simplify lazy import resolution (GH-158282) (#158569) · Kronuz/cpython@cc8f28a · GitHub
Skip to content

Commit cc8f28a

Browse files
committed
[3.15] pythongh-142349: Simplify lazy import resolution (pythonGH-158282) (python#158569)
1 parent b68a11b commit cc8f28a

21 files changed

Lines changed: 14124 additions & 837 deletions

‎Include/cpython/dictobject.h‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ typedef struct {
3232
PyDictValues *ma_values;
3333
} PyDictObject;
3434

35+
#define PyAnyDict_CheckExact(ob) PyDict_CheckExact(ob)
36+
#define PyAnyDict_Check(ob) PyDict_Check(ob)
37+
3538
PyAPI_FUNC(PyObject *) _PyDict_GetItem_KnownHash(PyObject *mp, PyObject *key,
3639
Py_hash_t hash);
3740
// PyDict_GetItemStringRef() can be used instead

‎Include/internal/pycore_ceval.h‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,7 @@ PyAPI_FUNC(void) _PyObjectArray_Free(PyObject **array, PyObject **scratch);
316316

317317
PyAPI_FUNC(PyObject *) _PyEval_GetANext(PyObject *aiter);
318318
PyAPI_FUNC(void) _PyEval_LoadGlobalStackRef(PyObject *globals, PyObject *builtins, PyObject *name, _PyStackRef *writeto);
319+
PyAPI_FUNC(PyObject*) _PyMapping_GetOptionalItem2(PyObject *obj, PyObject *key, int *err);
319320
PyAPI_FUNC(PyObject *) _PyEval_GetAwaitable(PyObject *iterable, int oparg);
320321
PyAPI_FUNC(PyObject *) _PyEval_LoadName(PyThreadState *tstate, _PyInterpreterFrame *frame, PyObject *name);
321322
PyAPI_FUNC(int)

‎Include/internal/pycore_dict.h‎

Lines changed: 9 additions & 4 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,
@@ -134,10 +139,10 @@ extern Py_ssize_t _PyDictKeys_StringLookup(PyDictKeysObject* dictkeys, PyObject
134139
*
135140
* Returns DKIX_EMPTY if the key is not present.
136141
*/
137-
extern Py_ssize_t _PyDictKeys_StringLookupAndVersion(PyDictKeysObject* dictkeys, PyObject *key, uint32_t *version);
138-
extern Py_ssize_t _PyDictKeys_StringLookupSplit(PyDictKeysObject* dictkeys, PyObject *key);
139-
PyAPI_FUNC(PyObject *)_PyDict_LoadGlobal(PyDictObject *, PyDictObject *, PyObject *);
140-
PyAPI_FUNC(void) _PyDict_LoadGlobalStackRef(PyDictObject *, PyDictObject *, PyObject *, _PyStackRef *);
142+
PyAPI_FUNC(Py_ssize_t) _PyDictKeys_StringLookupAndVersion(PyDictKeysObject* dictkeys, PyObject *key, uint32_t *version);
143+
PyAPI_FUNC(Py_ssize_t) _PyDictKeys_StringLookupSplit(PyDictKeysObject* dictkeys, PyObject *key);
144+
// Return the borrowed source dictionary, or NULL if absent or on error.
145+
PyAPI_FUNC(PyObject *) _PyDict_LoadGlobalStackRef(PyDictObject *, PyDictObject *, PyObject *, _PyStackRef *);
141146

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

‎Include/internal/pycore_import.h‎

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ typedef struct {
1717
int mode;
1818
int startup_mode;
1919
PyObject *filter;
20-
PyObject *importing_modules;
2120
PyObject *modules;
2221
PyObject *pending_submodules;
2322
PyObject *builtins_import_name;
@@ -54,20 +53,16 @@ extern int _PyImport_FixupBuiltin(
5453
PyObject *modules
5554
);
5655

57-
extern PyObject * _PyImport_ResolveName(
58-
PyThreadState *tstate, PyObject *name, PyObject *globals, int level);
5956
extern PyObject * _PyImport_GetAbsName(
6057
PyThreadState *tstate, PyObject *name, PyObject *globals, int level);
6158
// Symbol is exported for the JIT on Windows builds.
6259
PyAPI_FUNC(PyObject *) _PyImport_LoadLazyImportTstate(
6360
PyThreadState *tstate, PyObject *lazy_import);
64-
typedef enum {
65-
_Py_LAZY_SUBMODULE_ERROR = -1,
66-
_Py_LAZY_SUBMODULE_NOT_FOUND = 0,
67-
_Py_LAZY_SUBMODULE_LOADED = 1,
68-
} _PyLazySubmoduleImportResult;
69-
extern _PyLazySubmoduleImportResult _PyImport_TryLoadLazySubmodule(
70-
PyObject *mod_name, PyObject *attr_name, PyObject **result);
61+
// Bind a pending child on module before removing its registration. Return a
62+
// new reference, NULL without an exception if absent, or NULL on error.
63+
// Set recheck_dict if a concurrent lookup may have already bound the child.
64+
extern PyObject * _PyImport_TryLoadLazySubmodule(
65+
PyObject *module, PyObject *attr_name, int *recheck_dict);
7166
extern PyObject * _PyImport_LazyImportModuleLevelObject(
7267
PyThreadState *tstate, PyObject *name, PyObject *builtins,
7368
PyObject *globals, PyObject *locals, PyObject *fromlist, int level);

‎Include/internal/pycore_lazyimportobject.h‎

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,20 +14,18 @@ extern "C" {
1414
PyAPI_DATA(PyTypeObject) PyLazyImport_Type;
1515
#define PyLazyImport_CheckExact(op) Py_IS_TYPE((op), &PyLazyImport_Type)
1616

17-
typedef struct {
18-
PyObject_HEAD
19-
PyObject *lz_builtins;
20-
PyObject *lz_from;
21-
PyObject *lz_attr;
22-
// Frame information for the original import location.
23-
PyCodeObject *lz_code; // Code object where the lazy import was created.
24-
int lz_instr_offset; // Instruction offset where the lazy import was created.
25-
} PyLazyImportObject;
26-
27-
28-
PyAPI_FUNC(PyObject *) _PyLazyImport_GetName(PyObject *lazy_import);
2917
PyAPI_FUNC(PyObject *) _PyLazyImport_New(
30-
struct _PyInterpreterFrame *frame, PyObject *import_func, PyObject *from, PyObject *attr);
18+
struct _PyInterpreterFrame *frame, PyObject *builtins,
19+
PyObject *name, PyObject *fromlist);
20+
21+
extern int _PyLazyImport_IsResolving(PyThreadState *tstate, PyObject *op);
22+
23+
// Resolve a placeholder and replace its binding if it is unchanged or holds
24+
// the child module published by the normal importer during resolution.
25+
// namespace is the source captured during lookup, before resolution runs.
26+
PyAPI_FUNC(PyObject *) _PyLazyImport_Reify(
27+
PyThreadState *tstate, PyObject *placeholder,
28+
PyObject *name, PyObject *ns);
3129

3230
#ifdef __cplusplus
3331
}

‎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_tstate.h‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,10 @@ typedef struct _PyThreadStateImpl {
8383
#ifdef Py_GIL_DISABLED
8484
// gh-144438: Add padding to ensure that the fields above don't share a
8585
// cache line with other allocations.
86-
char __padding[64];
86+
// Lazy-import placeholders in progress on this thread (GH-158282 backport).
87+
// Carved from the reserved tail padding so sizeof stays byte-identical.
88+
PyObject *lazy_imports;
89+
char __padding[56];
8790
#endif
8891
} _PyThreadStateImpl;
8992

‎Include/internal/pycore_uop_metadata.h‎

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

0 commit comments

Comments
 (0)