]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-148659: Export some internal functions for the JIT (PEP-523) (#148634)
authorDino Viehland <dinoviehland@meta.com>
Thu, 16 Apr 2026 23:55:03 +0000 (16:55 -0700)
committerGitHub <noreply@github.com>
Thu, 16 Apr 2026 23:55:03 +0000 (01:55 +0200)
Export (as internal functions, not public ones) C API functions necessary to implement a JIT as a separate extension module.

Include/internal/pycore_abstract.h
Include/internal/pycore_call.h
Include/internal/pycore_dict.h
Include/internal/pycore_frame.h
Include/internal/pycore_function.h
Include/internal/pycore_interpframe.h
Include/internal/pycore_object.h
Include/internal/pycore_pyerrors.h
Include/internal/pycore_traceback.h
Include/internal/pycore_typeobject.h
Objects/dictobject.c

index 30809e097002ddf06a9e3100678395f757b25d8d..b9eb4fd9891e6699760878ca76e782cada69a938 100644 (file)
@@ -16,10 +16,11 @@ _PyIndex_Check(PyObject *obj)
     return (tp_as_number != NULL && tp_as_number->nb_index != NULL);
 }
 
-PyObject *_PyNumber_PowerNoMod(PyObject *lhs, PyObject *rhs);
-PyObject *_PyNumber_InPlacePowerNoMod(PyObject *lhs, PyObject *rhs);
+// Exported for external JIT support
+PyAPI_FUNC(PyObject *) _PyNumber_PowerNoMod(PyObject *lhs, PyObject *rhs);
+PyAPI_FUNC(PyObject *) _PyNumber_InPlacePowerNoMod(PyObject *lhs, PyObject *rhs);
 
-extern int _PyObject_HasLen(PyObject *o);
+PyAPI_FUNC(int) _PyObject_HasLen(PyObject *o);
 
 /* === Sequence protocol ================================================ */
 
index e544b4cf49d1fbc527272affe1e1070c8f1be29d..a9db8860e91c06c153ac22d5a7dc6072722f8d4f 100644 (file)
@@ -166,7 +166,8 @@ _PyStack_UnpackDict(PyThreadState *tstate,
     PyObject *const *args, Py_ssize_t nargs,
     PyObject *kwargs, PyObject **p_kwnames);
 
-extern void _PyStack_UnpackDict_Free(
+// Exported for external JIT support
+PyAPI_FUNC(void) _PyStack_UnpackDict_Free(
     PyObject *const *stack,
     Py_ssize_t nargs,
     PyObject *kwnames);
index 5cf3091dc888304c412fd75db499bb5fafce22dd..6c6e3b77e69fabc6370fc9d052c74d69e9683943 100644 (file)
@@ -31,7 +31,8 @@ PyAPI_FUNC(int) _PyDict_SetItem_KnownHash(PyObject *mp, PyObject *key,
 PyAPI_FUNC(int) _PyDict_DelItem_KnownHash(PyObject *mp, PyObject *key,
                                           Py_hash_t hash);
 
-extern int _PyDict_DelItem_KnownHash_LockHeld(PyObject *mp, PyObject *key,
+// Exported for external JIT support
+PyAPI_FUNC(int) _PyDict_DelItem_KnownHash_LockHeld(PyObject *mp, PyObject *key,
                                               Py_hash_t hash);
 
 extern int _PyDict_Contains_KnownHash(PyObject *, PyObject *, Py_hash_t);
@@ -93,8 +94,9 @@ extern PyObject *_PyDict_Or(PyObject *self, PyObject *other);
 extern PyObject *_PyDict_IOr(PyObject *self, PyObject *other);
 
 /* Gets a version number unique to the current state of the keys of dict, if possible.
- * Returns the version number, or zero if it was not possible to get a version number. */
-extern uint32_t _PyDictKeys_GetVersionForCurrentState(
+ * Returns the version number, or zero if it was not possible to get a version number.
+ * Exported for external JIT support */
+PyAPI_FUNC(uint32_t) _PyDictKeys_GetVersionForCurrentState(
         PyInterpreterState *interp, PyDictKeysObject *dictkeys);
 
 /* Gets a version number unique to the current state of the keys of dict, if possible.
@@ -104,8 +106,9 @@ extern uint32_t _PyDictKeys_GetVersionForCurrentState(
  *
  * The caller must hold the per-object lock on dict.
  *
- * Returns the version number, or zero if it was not possible to get a version number. */
-extern uint32_t _PyDict_GetKeysVersionForCurrentState(
+ * Returns the version number, or zero if it was not possible to get a version number.
+ * Exported for external JIT support */
+PyAPI_FUNC(uint32_t) _PyDict_GetKeysVersionForCurrentState(
         PyInterpreterState *interp, PyDictObject *dict);
 
 extern size_t _PyDict_KeysSize(PyDictKeysObject *keys);
@@ -114,16 +117,18 @@ extern void _PyDictKeys_DecRef(PyDictKeysObject *keys);
 
 /* _Py_dict_lookup() returns index of entry which can be used like DK_ENTRIES(dk)[index].
  * -1 when no entry found, -3 when compare raises error.
+ * Exported for external JIT support
  */
-extern Py_ssize_t _Py_dict_lookup(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject **value_addr);
+PyAPI_FUNC(Py_ssize_t) _Py_dict_lookup(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject **value_addr);
 extern Py_ssize_t _Py_dict_lookup_threadsafe(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject **value_addr);
 extern Py_ssize_t _Py_dict_lookup_threadsafe_stackref(PyDictObject *mp, PyObject *key, Py_hash_t hash, _PyStackRef *value_addr);
 
 extern int _PyDict_GetMethodStackRef(PyDictObject *dict, PyObject *name, _PyStackRef *method);
 
-extern Py_ssize_t _PyDict_LookupIndexAndValue(PyDictObject *, PyObject *, PyObject **);
-extern Py_ssize_t _PyDict_LookupIndex(PyDictObject *, PyObject *);
-extern Py_ssize_t _PyDictKeys_StringLookup(PyDictKeysObject* dictkeys, PyObject *key);
+// Exported for external JIT support
+PyAPI_FUNC(Py_ssize_t) _PyDict_LookupIndexAndValue(PyDictObject *, PyObject *, PyObject **);
+PyAPI_FUNC(Py_ssize_t) _PyDict_LookupIndex(PyDictObject *, PyObject *);
+PyAPI_FUNC(Py_ssize_t) _PyDictKeys_StringLookup(PyDictKeysObject* dictkeys, PyObject *key);
 
 /* Look up a string key in an all unicode dict keys, assign the keys object a version, and
  * store it in version.
@@ -132,9 +137,11 @@ extern Py_ssize_t _PyDictKeys_StringLookup(PyDictKeysObject* dictkeys, PyObject
  * strings.
  *
  * Returns DKIX_EMPTY if the key is not present.
+ *
+ * Exported for external JIT support
  */
-extern Py_ssize_t _PyDictKeys_StringLookupAndVersion(PyDictKeysObject* dictkeys, PyObject *key, uint32_t *version);
-extern Py_ssize_t _PyDictKeys_StringLookupSplit(PyDictKeysObject* dictkeys, PyObject *key);
+PyAPI_FUNC(Py_ssize_t) _PyDictKeys_StringLookupAndVersion(PyDictKeysObject* dictkeys, PyObject *key, uint32_t *version);
+PyAPI_FUNC(Py_ssize_t) _PyDictKeys_StringLookupSplit(PyDictKeysObject* dictkeys, PyObject *key);
 PyAPI_FUNC(PyObject *)_PyDict_LoadGlobal(PyDictObject *, PyDictObject *, PyObject *);
 PyAPI_FUNC(void) _PyDict_LoadGlobalStackRef(PyDictObject *, PyDictObject *, PyObject *, _PyStackRef *);
 
@@ -144,7 +151,8 @@ extern PyObject *_PyDict_LoadBuiltinsFromGlobals(PyObject *globals);
 /* Consumes references to key and value */
 PyAPI_FUNC(int) _PyDict_SetItem_Take2(PyDictObject *op, PyObject *key, PyObject *value);
 PyAPI_FUNC(int) _PyDict_SetItem_Take2_KnownHash(PyDictObject *op, PyObject *key, PyObject *value, Py_hash_t hash);
-extern int _PyDict_SetItem_LockHeld(PyDictObject *dict, PyObject *name, PyObject *value);
+// Exported for external JIT support
+PyAPI_FUNC(int) _PyDict_SetItem_LockHeld(PyDictObject *dict, PyObject *name, PyObject *value);
 // Export for '_asyncio' shared extension
 PyAPI_FUNC(int) _PyDict_SetItem_KnownHash_LockHeld(PyDictObject *mp, PyObject *key,
                                                    PyObject *value, Py_hash_t hash);
@@ -329,6 +337,10 @@ _PyDictValues_AddToInsertionOrder(PyDictValues *values, Py_ssize_t ix)
     values->size = size+1;
 }
 
+// Exported for external JIT support
+PyAPI_FUNC(void)
+_PyDict_InsertSplitValue(PyDictObject *mp, PyObject *key, PyObject *value, Py_ssize_t ix);
+
 static inline size_t
 shared_keys_usable_size(PyDictKeysObject *keys)
 {
index 5e73ae3c8549b846e49da8be84988a10c7fb46cb..3c9ab99c34ebc64cdd54a52c8335bf2cfed84256 100644 (file)
@@ -38,7 +38,8 @@ struct _frame {
     PyObject *_f_frame_data[1];
 };
 
-extern PyFrameObject* _PyFrame_New_NoTrack(PyCodeObject *code);
+// Exported for external JIT support
+PyAPI_FUNC(PyFrameObject *) _PyFrame_New_NoTrack(PyCodeObject *code);
 
 
 /* other API */
index 99dacaf0fe7c545cb31582d271bdbae0781b2bae..2184f40956d4e24b98e52e37a16345cf72316a5f 100644 (file)
@@ -27,7 +27,8 @@ _PyFunction_IsVersionValid(uint32_t version)
     return version >= FUNC_VERSION_FIRST_VALID;
 }
 
-extern uint32_t _PyFunction_GetVersionForCurrentState(PyFunctionObject *func);
+// Exported for external JIT support
+PyAPI_FUNC(uint32_t) _PyFunction_GetVersionForCurrentState(PyFunctionObject *func);
 PyAPI_FUNC(void) _PyFunction_SetVersion(PyFunctionObject *func, uint32_t version);
 void _PyFunction_ClearCodeByVersion(uint32_t version);
 
index d744dd12cd04795424645fc034c70cd9b6dfabd2..28370ababc47b92095e19853f5a93c4d6d40e108 100644 (file)
@@ -302,7 +302,8 @@ _PyFrame_GetFrameObject(_PyInterpreterFrame *frame)
     return _PyFrame_MakeAndSetFrameObject(frame);
 }
 
-void
+// Exported for external JIT support
+PyAPI_FUNC(void)
 _PyFrame_ClearLocals(_PyInterpreterFrame *frame);
 
 /* Clears all references in the frame.
@@ -313,8 +314,10 @@ _PyFrame_ClearLocals(_PyInterpreterFrame *frame);
  * in the frame.
  * take should  be set to 1 for heap allocated
  * frames like the ones in generators and coroutines.
+ *
+ * Exported for external JIT support
  */
-void
+ PyAPI_FUNC(void)
 _PyFrame_ClearExceptCode(_PyInterpreterFrame * frame);
 
 int
@@ -338,7 +341,8 @@ _PyThreadState_HasStackSpace(PyThreadState *tstate, int size)
         size < tstate->datastack_limit - tstate->datastack_top;
 }
 
-extern _PyInterpreterFrame *
+// Exported for external JIT support
+PyAPI_FUNC(_PyInterpreterFrame *)
 _PyThreadState_PushFrame(PyThreadState *tstate, size_t size);
 
 PyAPI_FUNC(void) _PyThreadState_PopFrame(PyThreadState *tstate, _PyInterpreterFrame *frame);
index de701ced675cd46ea3785b76143b809874346478..c2c508c1a71c5c019e3d333376f399413b4ff607 100644 (file)
@@ -879,14 +879,16 @@ PyAPI_FUNC(PyObject *) _PyType_NewManagedObject(PyTypeObject *type);
 extern PyTypeObject* _PyType_CalculateMetaclass(PyTypeObject *, PyObject *);
 extern PyObject* _PyType_GetDocFromInternalDoc(const char *, const char *);
 extern PyObject* _PyType_GetTextSignatureFromInternalDoc(const char *, const char *, int);
-extern int _PyObject_SetAttributeErrorContext(PyObject *v, PyObject* name);
+// Exported for external JIT support
+PyAPI_FUNC(int) _PyObject_SetAttributeErrorContext(PyObject *v, PyObject* name);
 
 void _PyObject_InitInlineValues(PyObject *obj, PyTypeObject *tp);
 extern int _PyObject_StoreInstanceAttribute(PyObject *obj,
                                             PyObject *name, PyObject *value);
 extern bool _PyObject_TryGetInstanceAttribute(PyObject *obj, PyObject *name,
                                               PyObject **attr);
-extern PyObject *_PyType_LookupRefAndVersion(PyTypeObject *, PyObject *,
+// Exported for external JIT support
+PyAPI_FUNC(PyObject *) _PyType_LookupRefAndVersion(PyTypeObject *, PyObject *,
                                              unsigned int *);
 
 // Internal API to look for a name through the MRO.
@@ -910,7 +912,9 @@ PyAPI_FUNC(_PyStackRef) _PyObject_GetAttrStackRef(PyObject *obj, PyObject *name)
 // deferred reference counting.
 //
 // Returns 1 if the value was cached or 0 otherwise.
-extern int _PyType_CacheInitForSpecialization(PyHeapTypeObject *type,
+//
+// Exported for external JIT support
+PyAPI_FUNC(int) _PyType_CacheInitForSpecialization(PyHeapTypeObject *type,
                                               PyObject *init,
                                               unsigned int tp_version);
 
index e38472ab13a9dfa1454b741feb5d5fff1d74c357..e436aa6bf12cb27abf6967191dc1dfcf9e132c88 100644 (file)
@@ -170,7 +170,8 @@ extern PyObject* _PyErr_FormatFromCauseTstate(
     const char *format,
     ...);
 
-extern PyObject* _PyExc_CreateExceptionGroup(
+// Exported for external JIT support
+PyAPI_FUNC(PyObject *) _PyExc_CreateExceptionGroup(
     const char *msg,
     PyObject *excs);
 
@@ -181,7 +182,8 @@ extern PyObject* _PyExc_PrepReraiseStar(
 extern int _PyErr_CheckSignalsTstate(PyThreadState *tstate);
 
 extern void _Py_DumpExtensionModules(int fd, PyInterpreterState *interp);
-extern PyObject* _Py_CalculateSuggestions(PyObject *dir, PyObject *name);
+// Exported for external JIT support
+PyAPI_FUNC(PyObject *) _Py_CalculateSuggestions(PyObject *dir, PyObject *name);
 extern PyObject* _Py_Offer_Suggestions(PyObject* exception);
 
 // Export for '_testinternalcapi' shared extension
index 8357cce9d899fbb5d2a6944d9d86c6dd1a4eea5b..6b5e24979d5321684121774c9eb91961a4dbae76 100644 (file)
@@ -85,7 +85,8 @@ extern void _Py_DumpHexadecimal(
     uintptr_t value,
     Py_ssize_t width);
 
-extern PyObject* _PyTraceBack_FromFrame(
+// Exported for external JIT support
+PyAPI_FUNC(PyObject *) _PyTraceBack_FromFrame(
     PyObject *tb_next,
     PyFrameObject *frame);
 
index 8207de67cf17dbb26349a2247bfb6dea856a0857..8d48cf6605ca7e35eb93444bea1bdd0eca72dc03 100644 (file)
@@ -60,7 +60,8 @@ extern void _PyStaticType_FiniBuiltin(
 extern void _PyStaticType_ClearWeakRefs(
     PyInterpreterState *interp,
     PyTypeObject *type);
-extern managed_static_type_state * _PyStaticType_GetState(
+// Exported for external JIT support
+PyAPI_FUNC(managed_static_type_state *) _PyStaticType_GetState(
     PyInterpreterState *interp,
     PyTypeObject *type);
 
@@ -156,8 +157,9 @@ typedef int (*_py_validate_type)(PyTypeObject *);
 // It will verify the ``ty`` through user-defined validation function ``validate``,
 // and if the validation is passed, it will set the ``tp_version`` as valid
 // tp_version_tag from the ``ty``.
-extern int _PyType_Validate(PyTypeObject *ty, _py_validate_type validate, unsigned int *tp_version);
-extern int _PyType_CacheGetItemForSpecialization(PyHeapTypeObject *ht, PyObject *descriptor, uint32_t tp_version);
+// Exported for external JIT support
+int _PyType_Validate(PyTypeObject *ty, _py_validate_type validate, unsigned int *tp_version);
+int _PyType_CacheGetItemForSpecialization(PyHeapTypeObject *ht, PyObject *descriptor, uint32_t tp_version);
 
 // Precalculates count of non-unique slots and fills wrapperbase.name_count.
 extern int _PyType_InitSlotDefs(PyInterpreterState *interp);
index 483bddebb9949f4ec1a35adf3d991e32cf167b93..09db93b2d318207120956a79b0f4e8b6eaaa2061 100644 (file)
@@ -1910,8 +1910,8 @@ insert_split_key(PyDictKeysObject *keys, PyObject *key, Py_hash_t hash)
     return ix;
 }
 
-static void
-insert_split_value(PyDictObject *mp, PyObject *key, PyObject *value, Py_ssize_t ix)
+void
+_PyDict_InsertSplitValue(PyDictObject *mp, PyObject *key, PyObject *value, Py_ssize_t ix)
 {
     assert(can_modify_dict(mp));
     assert(PyUnicode_CheckExact(key));
@@ -1951,7 +1951,7 @@ insertdict(PyDictObject *mp,
     if (_PyDict_HasSplitTable(mp) && PyUnicode_CheckExact(key)) {
         ix = insert_split_key(mp->ma_keys, key, hash);
         if (ix != DKIX_EMPTY) {
-            insert_split_value(mp, key, value, ix);
+            _PyDict_InsertSplitValue(mp, key, value, ix);
             Py_DECREF(key);
             Py_DECREF(value);
             return 0;
@@ -4714,7 +4714,7 @@ dict_setdefault_ref_lock_held(PyObject *d, PyObject *key, PyObject *default_valu
             PyObject *value = mp->ma_values->values[ix];
             int already_present = value != NULL;
             if (!already_present) {
-                insert_split_value(mp, key, default_value, ix);
+                _PyDict_InsertSplitValue(mp, key, default_value, ix);
                 value = default_value;
             }
             if (result) {