mirror of
https://github.com/python/cpython.git
synced 2025-07-07 19:35:27 +00:00
GH-131238: Core header refactor (GH-131250)
* Moves most structs in pycore_ header files into pycore_structs.h and pycore_runtime_structs.h * Removes many cross-header dependencies
This commit is contained in:
parent
3ae67ba97e
commit
a1aeec61c4
57 changed files with 1481 additions and 1356 deletions
|
@ -8,25 +8,6 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Total tool ids available */
|
|
||||||
#define _PY_MONITORING_TOOL_IDS 8
|
|
||||||
/* Count of all local monitoring events */
|
|
||||||
#define _PY_MONITORING_LOCAL_EVENTS 11
|
|
||||||
/* Count of all "real" monitoring events (not derived from other events) */
|
|
||||||
#define _PY_MONITORING_UNGROUPED_EVENTS 16
|
|
||||||
/* Count of all monitoring events */
|
|
||||||
#define _PY_MONITORING_EVENTS 19
|
|
||||||
|
|
||||||
/* Tables of which tools are active for each monitored event. */
|
|
||||||
typedef struct _Py_LocalMonitors {
|
|
||||||
uint8_t tools[_PY_MONITORING_LOCAL_EVENTS];
|
|
||||||
} _Py_LocalMonitors;
|
|
||||||
|
|
||||||
typedef struct _Py_GlobalMonitors {
|
|
||||||
uint8_t tools[_PY_MONITORING_UNGROUPED_EVENTS];
|
|
||||||
} _Py_GlobalMonitors;
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
PyObject *_co_code;
|
PyObject *_co_code;
|
||||||
PyObject *_co_varnames;
|
PyObject *_co_varnames;
|
||||||
|
@ -34,44 +15,12 @@ typedef struct {
|
||||||
PyObject *_co_freevars;
|
PyObject *_co_freevars;
|
||||||
} _PyCoCached;
|
} _PyCoCached;
|
||||||
|
|
||||||
/* Ancillary data structure used for instrumentation.
|
|
||||||
Line instrumentation creates this with sufficient
|
|
||||||
space for one entry per code unit. The total size
|
|
||||||
of the data will be `bytes_per_entry * Py_SIZE(code)` */
|
|
||||||
typedef struct {
|
|
||||||
uint8_t bytes_per_entry;
|
|
||||||
uint8_t data[1];
|
|
||||||
} _PyCoLineInstrumentationData;
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int size;
|
int size;
|
||||||
int capacity;
|
int capacity;
|
||||||
struct _PyExecutorObject *executors[1];
|
struct _PyExecutorObject *executors[1];
|
||||||
} _PyExecutorArray;
|
} _PyExecutorArray;
|
||||||
|
|
||||||
/* Main data structure used for instrumentation.
|
|
||||||
* This is allocated when needed for instrumentation
|
|
||||||
*/
|
|
||||||
typedef struct {
|
|
||||||
/* Monitoring specific to this code object */
|
|
||||||
_Py_LocalMonitors local_monitors;
|
|
||||||
/* Monitoring that is active on this code object */
|
|
||||||
_Py_LocalMonitors active_monitors;
|
|
||||||
/* The tools that are to be notified for events for the matching code unit */
|
|
||||||
uint8_t *tools;
|
|
||||||
/* The version of tools when they instrument the code */
|
|
||||||
uintptr_t tool_versions[_PY_MONITORING_TOOL_IDS];
|
|
||||||
/* Information to support line events */
|
|
||||||
_PyCoLineInstrumentationData *lines;
|
|
||||||
/* The tools that are to be notified for line events for the matching code unit */
|
|
||||||
uint8_t *line_tools;
|
|
||||||
/* Information to support instruction events */
|
|
||||||
/* The underlying instructions, which can themselves be instrumented */
|
|
||||||
uint8_t *per_instruction_opcodes;
|
|
||||||
/* The tools that are to be notified for instruction events for the matching code unit */
|
|
||||||
uint8_t *per_instruction_tools;
|
|
||||||
} _PyCoMonitoringData;
|
|
||||||
|
|
||||||
#ifdef Py_GIL_DISABLED
|
#ifdef Py_GIL_DISABLED
|
||||||
|
|
||||||
|
@ -151,7 +100,7 @@ typedef struct {
|
||||||
_PyExecutorArray *co_executors; /* executors from optimizer */ \
|
_PyExecutorArray *co_executors; /* executors from optimizer */ \
|
||||||
_PyCoCached *_co_cached; /* cached co_* attributes */ \
|
_PyCoCached *_co_cached; /* cached co_* attributes */ \
|
||||||
uintptr_t _co_instrumentation_version; /* current instrumentation version */ \
|
uintptr_t _co_instrumentation_version; /* current instrumentation version */ \
|
||||||
_PyCoMonitoringData *_co_monitoring; /* Monitoring data */ \
|
struct _PyCoMonitoringData *_co_monitoring; /* Monitoring data */ \
|
||||||
Py_ssize_t _co_unique_id; /* ID used for per-thread refcounting */ \
|
Py_ssize_t _co_unique_id; /* ID used for per-thread refcounting */ \
|
||||||
int _co_firsttraceable; /* index of first traceable instruction */ \
|
int _co_firsttraceable; /* index of first traceable instruction */ \
|
||||||
/* Scratch space for extra data relating to the code object. \
|
/* Scratch space for extra data relating to the code object. \
|
||||||
|
|
|
@ -512,7 +512,6 @@ PyAPI_FUNC(int) PyObject_VisitManagedDict(PyObject *obj, visitproc visit, void *
|
||||||
PyAPI_FUNC(int) _PyObject_SetManagedDict(PyObject *obj, PyObject *new_dict);
|
PyAPI_FUNC(int) _PyObject_SetManagedDict(PyObject *obj, PyObject *new_dict);
|
||||||
PyAPI_FUNC(void) PyObject_ClearManagedDict(PyObject *obj);
|
PyAPI_FUNC(void) PyObject_ClearManagedDict(PyObject *obj);
|
||||||
|
|
||||||
#define TYPE_MAX_WATCHERS 8
|
|
||||||
|
|
||||||
typedef int(*PyType_WatchCallback)(PyTypeObject *);
|
typedef int(*PyType_WatchCallback)(PyTypeObject *);
|
||||||
PyAPI_FUNC(int) PyType_AddWatcher(PyType_WatchCallback callback);
|
PyAPI_FUNC(int) PyType_AddWatcher(PyType_WatchCallback callback);
|
||||||
|
|
|
@ -12,44 +12,6 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
//###############
|
|
||||||
// runtime atexit
|
|
||||||
|
|
||||||
typedef void (*atexit_callbackfunc)(void);
|
|
||||||
|
|
||||||
struct _atexit_runtime_state {
|
|
||||||
PyMutex mutex;
|
|
||||||
#define NEXITFUNCS 32
|
|
||||||
atexit_callbackfunc callbacks[NEXITFUNCS];
|
|
||||||
int ncallbacks;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
//###################
|
|
||||||
// interpreter atexit
|
|
||||||
|
|
||||||
typedef void (*atexit_datacallbackfunc)(void *);
|
|
||||||
|
|
||||||
typedef struct atexit_callback {
|
|
||||||
atexit_datacallbackfunc func;
|
|
||||||
void *data;
|
|
||||||
struct atexit_callback *next;
|
|
||||||
} atexit_callback;
|
|
||||||
|
|
||||||
struct atexit_state {
|
|
||||||
#ifdef Py_GIL_DISABLED
|
|
||||||
PyMutex ll_callbacks_lock;
|
|
||||||
#endif
|
|
||||||
atexit_callback *ll_callbacks;
|
|
||||||
|
|
||||||
// XXX The rest of the state could be moved to the atexit module state
|
|
||||||
// and a low-level callback added for it during module exec.
|
|
||||||
// For the moment we leave it here.
|
|
||||||
|
|
||||||
// List containing tuples with callback information.
|
|
||||||
// e.g. [(func, args, kwargs), ...]
|
|
||||||
PyObject *callbacks;
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef Py_GIL_DISABLED
|
#ifdef Py_GIL_DISABLED
|
||||||
# define _PyAtExit_LockCallbacks(state) PyMutex_Lock(&state->ll_callbacks_lock);
|
# define _PyAtExit_LockCallbacks(state) PyMutex_Lock(&state->ll_callbacks_lock);
|
||||||
|
|
|
@ -10,14 +10,7 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdbool.h>
|
#include "pycore_structs.h" // _Py_BackoffCounter
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint16_t value_and_backoff;
|
|
||||||
} _Py_BackoffCounter;
|
|
||||||
|
|
||||||
|
|
||||||
/* 16-bit countdown counters using exponential backoff.
|
/* 16-bit countdown counters using exponential backoff.
|
||||||
|
|
||||||
|
|
|
@ -12,16 +12,6 @@ extern "C" {
|
||||||
#include "pycore_gil.h" // struct _gil_runtime_state
|
#include "pycore_gil.h" // struct _gil_runtime_state
|
||||||
|
|
||||||
|
|
||||||
typedef int (*_Py_pending_call_func)(void *);
|
|
||||||
|
|
||||||
struct _pending_call {
|
|
||||||
_Py_pending_call_func func;
|
|
||||||
void *arg;
|
|
||||||
int flags;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define PENDINGCALLSARRAYSIZE 300
|
|
||||||
|
|
||||||
#define MAXPENDINGCALLS PENDINGCALLSARRAYSIZE
|
#define MAXPENDINGCALLS PENDINGCALLSARRAYSIZE
|
||||||
/* For interpreter-level pending calls, we want to avoid spending too
|
/* For interpreter-level pending calls, we want to avoid spending too
|
||||||
much time on pending calls in any one thread, so we apply a limit. */
|
much time on pending calls in any one thread, so we apply a limit. */
|
||||||
|
@ -40,69 +30,6 @@ struct _pending_call {
|
||||||
pending calls for the main thread. */
|
pending calls for the main thread. */
|
||||||
#define MAXPENDINGCALLSLOOP_MAIN 0
|
#define MAXPENDINGCALLSLOOP_MAIN 0
|
||||||
|
|
||||||
struct _pending_calls {
|
|
||||||
PyThreadState *handling_thread;
|
|
||||||
PyMutex mutex;
|
|
||||||
/* Request for running pending calls. */
|
|
||||||
int32_t npending;
|
|
||||||
/* The maximum allowed number of pending calls.
|
|
||||||
If the queue fills up to this point then _PyEval_AddPendingCall()
|
|
||||||
will return _Py_ADD_PENDING_FULL. */
|
|
||||||
int32_t max;
|
|
||||||
/* We don't want a flood of pending calls to interrupt any one thread
|
|
||||||
for too long, so we keep a limit on the number handled per pass.
|
|
||||||
A value of 0 means there is no limit (other than the maximum
|
|
||||||
size of the list of pending calls). */
|
|
||||||
int32_t maxloop;
|
|
||||||
struct _pending_call calls[PENDINGCALLSARRAYSIZE];
|
|
||||||
int first;
|
|
||||||
int next;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
PERF_STATUS_FAILED = -1, // Perf trampoline is in an invalid state
|
|
||||||
PERF_STATUS_NO_INIT = 0, // Perf trampoline is not initialized
|
|
||||||
PERF_STATUS_OK = 1, // Perf trampoline is ready to be executed
|
|
||||||
} perf_status_t;
|
|
||||||
|
|
||||||
#ifdef PY_HAVE_PERF_TRAMPOLINE
|
|
||||||
struct code_arena_st;
|
|
||||||
|
|
||||||
struct trampoline_api_st {
|
|
||||||
void* (*init_state)(void);
|
|
||||||
void (*write_state)(void* state, const void *code_addr,
|
|
||||||
unsigned int code_size, PyCodeObject* code);
|
|
||||||
int (*free_state)(void* state);
|
|
||||||
void *state;
|
|
||||||
Py_ssize_t code_padding;
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
struct _ceval_runtime_state {
|
|
||||||
struct {
|
|
||||||
#ifdef PY_HAVE_PERF_TRAMPOLINE
|
|
||||||
perf_status_t status;
|
|
||||||
int perf_trampoline_type;
|
|
||||||
Py_ssize_t extra_code_index;
|
|
||||||
struct code_arena_st *code_arena;
|
|
||||||
struct trampoline_api_st trampoline_api;
|
|
||||||
FILE *map_file;
|
|
||||||
Py_ssize_t persist_after_fork;
|
|
||||||
#else
|
|
||||||
int _not_used;
|
|
||||||
#endif
|
|
||||||
} perf;
|
|
||||||
/* Pending calls to be made only on the main thread. */
|
|
||||||
// The signal machinery falls back on this
|
|
||||||
// so it must be especially stable and efficient.
|
|
||||||
// For example, we use a preallocated array
|
|
||||||
// for the list of pending calls.
|
|
||||||
struct _pending_calls pending_mainthread;
|
|
||||||
PyMutex sys_trace_profile_mutex;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef PY_HAVE_PERF_TRAMPOLINE
|
#ifdef PY_HAVE_PERF_TRAMPOLINE
|
||||||
# define _PyEval_RUNTIME_PERF_INIT \
|
# define _PyEval_RUNTIME_PERF_INIT \
|
||||||
|
@ -116,18 +43,6 @@ struct _ceval_runtime_state {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
struct _ceval_state {
|
|
||||||
/* This variable holds the global instrumentation version. When a thread is
|
|
||||||
running, this value is overlaid onto PyThreadState.eval_breaker so that
|
|
||||||
changes in the instrumentation version will trigger the eval breaker. */
|
|
||||||
uintptr_t instrumentation_version;
|
|
||||||
int recursion_limit;
|
|
||||||
struct _gil_runtime_state *gil;
|
|
||||||
int own_gil;
|
|
||||||
struct _pending_calls pending;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -8,30 +8,13 @@ extern "C" {
|
||||||
# error "this header requires Py_BUILD_CORE define"
|
# error "this header requires Py_BUILD_CORE define"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "pycore_structs.h" // _Py_CODEUNIT
|
||||||
#include "pycore_stackref.h" // _PyStackRef
|
#include "pycore_stackref.h" // _PyStackRef
|
||||||
#include "pycore_lock.h" // PyMutex
|
#include "pycore_lock.h" // PyMutex
|
||||||
#include "pycore_backoff.h" // _Py_BackoffCounter
|
#include "pycore_backoff.h" // _Py_BackoffCounter
|
||||||
#include "pycore_tstate.h" // _PyThreadStateImpl
|
#include "pycore_tstate.h" // _PyThreadStateImpl
|
||||||
|
|
||||||
|
|
||||||
/* Each instruction in a code object is a fixed-width value,
|
|
||||||
* currently 2 bytes: 1-byte opcode + 1-byte oparg. The EXTENDED_ARG
|
|
||||||
* opcode allows for larger values but the current limit is 3 uses
|
|
||||||
* of EXTENDED_ARG (see Python/compile.c), for a maximum
|
|
||||||
* 32-bit value. This aligns with the note in Python/compile.c
|
|
||||||
* (compiler_addop_i_line) indicating that the max oparg value is
|
|
||||||
* 2**32 - 1, rather than INT_MAX.
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef union {
|
|
||||||
uint16_t cache;
|
|
||||||
struct {
|
|
||||||
uint8_t code;
|
|
||||||
uint8_t arg;
|
|
||||||
} op;
|
|
||||||
_Py_BackoffCounter counter; // First cache entry of specializable op
|
|
||||||
} _Py_CODEUNIT;
|
|
||||||
|
|
||||||
#define _PyCode_CODE(CO) _Py_RVALUE((_Py_CODEUNIT *)(CO)->co_code_adaptive)
|
#define _PyCode_CODE(CO) _Py_RVALUE((_Py_CODEUNIT *)(CO)->co_code_adaptive)
|
||||||
#define _PyCode_NBYTES(CO) (Py_SIZE(CO) * (Py_ssize_t)sizeof(_Py_CODEUNIT))
|
#define _PyCode_NBYTES(CO) (Py_SIZE(CO) * (Py_ssize_t)sizeof(_Py_CODEUNIT))
|
||||||
|
|
||||||
|
@ -67,16 +50,10 @@ _py_set_opcode(_Py_CODEUNIT *word, uint8_t opcode)
|
||||||
#define _PyCode_HAS_INSTRUMENTATION(CODE) \
|
#define _PyCode_HAS_INSTRUMENTATION(CODE) \
|
||||||
(CODE->_co_instrumentation_version > 0)
|
(CODE->_co_instrumentation_version > 0)
|
||||||
|
|
||||||
struct _py_code_state {
|
|
||||||
PyMutex mutex;
|
|
||||||
// Interned constants from code objects. Used by the free-threaded build.
|
|
||||||
struct _Py_hashtable_t *constants;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern PyStatus _PyCode_Init(PyInterpreterState *interp);
|
extern PyStatus _PyCode_Init(PyInterpreterState *interp);
|
||||||
extern void _PyCode_Fini(PyInterpreterState *interp);
|
extern void _PyCode_Fini(PyInterpreterState *interp);
|
||||||
|
|
||||||
#define CODE_MAX_WATCHERS 8
|
|
||||||
|
|
||||||
/* PEP 659
|
/* PEP 659
|
||||||
* Specialization and quickening structs and helper functions
|
* Specialization and quickening structs and helper functions
|
||||||
|
@ -185,14 +162,6 @@ typedef struct {
|
||||||
|
|
||||||
#define INLINE_CACHE_ENTRIES_CONTAINS_OP CACHE_ENTRIES(_PyContainsOpCache)
|
#define INLINE_CACHE_ENTRIES_CONTAINS_OP CACHE_ENTRIES(_PyContainsOpCache)
|
||||||
|
|
||||||
// Borrowed references to common callables:
|
|
||||||
struct callable_cache {
|
|
||||||
PyObject *isinstance;
|
|
||||||
PyObject *len;
|
|
||||||
PyObject *list_append;
|
|
||||||
PyObject *object__getattribute__;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* "Locals plus" for a code object is the set of locals + cell vars +
|
/* "Locals plus" for a code object is the set of locals + cell vars +
|
||||||
* free vars. This relates to variable names as well as offsets into
|
* free vars. This relates to variable names as well as offsets into
|
||||||
* the "fast locals" storage array of execution frames. The compiler
|
* the "fast locals" storage array of execution frames. The compiler
|
||||||
|
|
|
@ -9,6 +9,7 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "pycore_lock.h" // PyMutex
|
#include "pycore_lock.h" // PyMutex
|
||||||
|
#include "pycore_runtime_structs.h" // struct codecs_state
|
||||||
|
|
||||||
/* Initialize codecs-related state for the given interpreter, including
|
/* Initialize codecs-related state for the given interpreter, including
|
||||||
registering the first codec search function. Must be called before any other
|
registering the first codec search function. Must be called before any other
|
||||||
|
@ -70,27 +71,6 @@ extern PyObject* _PyCodecInfo_GetIncrementalEncoder(
|
||||||
PyObject *codec_info,
|
PyObject *codec_info,
|
||||||
const char *errors);
|
const char *errors);
|
||||||
|
|
||||||
// Per-interpreter state used by codecs.c.
|
|
||||||
struct codecs_state {
|
|
||||||
// A list of callable objects used to search for codecs.
|
|
||||||
PyObject *search_path;
|
|
||||||
|
|
||||||
// A dict mapping codec names to codecs returned from a callable in
|
|
||||||
// search_path.
|
|
||||||
PyObject *search_cache;
|
|
||||||
|
|
||||||
// A dict mapping error handling strategies to functions to implement them.
|
|
||||||
PyObject *error_registry;
|
|
||||||
|
|
||||||
#ifdef Py_GIL_DISABLED
|
|
||||||
// Used to safely delete a specific item from search_path.
|
|
||||||
PyMutex search_path_mutex;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Whether or not the rest of the state is initialized.
|
|
||||||
int initialized;
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -5,9 +5,7 @@
|
||||||
# error "this header requires Py_BUILD_CORE define"
|
# error "this header requires Py_BUILD_CORE define"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "pycore_hamt.h" // PyHamtObject
|
#include "pycore_structs.h"
|
||||||
|
|
||||||
#define CONTEXT_MAX_WATCHERS 8
|
|
||||||
|
|
||||||
extern PyTypeObject _PyContextTokenMissing_Type;
|
extern PyTypeObject _PyContextTokenMissing_Type;
|
||||||
|
|
||||||
|
|
|
@ -11,53 +11,18 @@ extern "C" {
|
||||||
#include "pycore_pymath.h" // _PY_SHORT_FLOAT_REPR
|
#include "pycore_pymath.h" // _PY_SHORT_FLOAT_REPR
|
||||||
|
|
||||||
|
|
||||||
typedef uint32_t ULong;
|
|
||||||
|
|
||||||
struct
|
|
||||||
Bigint {
|
|
||||||
struct Bigint *next;
|
|
||||||
int k, maxwds, sign, wds;
|
|
||||||
ULong x[1];
|
|
||||||
};
|
|
||||||
|
|
||||||
#if defined(Py_USING_MEMORY_DEBUGGER) || _PY_SHORT_FLOAT_REPR == 0
|
#if defined(Py_USING_MEMORY_DEBUGGER) || _PY_SHORT_FLOAT_REPR == 0
|
||||||
|
|
||||||
struct _dtoa_state {
|
|
||||||
int _not_used;
|
|
||||||
};
|
|
||||||
#define _dtoa_state_INIT(INTERP) \
|
#define _dtoa_state_INIT(INTERP) \
|
||||||
{0}
|
{0}
|
||||||
|
|
||||||
#else // !Py_USING_MEMORY_DEBUGGER && _PY_SHORT_FLOAT_REPR != 0
|
#else
|
||||||
|
|
||||||
/* The size of the Bigint freelist */
|
|
||||||
#define Bigint_Kmax 7
|
|
||||||
|
|
||||||
/* The size of the cached powers of 5 array */
|
|
||||||
#define Bigint_Pow5size 8
|
|
||||||
|
|
||||||
#ifndef PRIVATE_MEM
|
|
||||||
#define PRIVATE_MEM 2304
|
|
||||||
#endif
|
|
||||||
#define Bigint_PREALLOC_SIZE \
|
|
||||||
((PRIVATE_MEM+sizeof(double)-1)/sizeof(double))
|
|
||||||
|
|
||||||
struct _dtoa_state {
|
|
||||||
// p5s is an array of powers of 5 of the form:
|
|
||||||
// 5**(2**(i+2)) for 0 <= i < Bigint_Pow5size
|
|
||||||
struct Bigint *p5s[Bigint_Pow5size];
|
|
||||||
// XXX This should be freed during runtime fini.
|
|
||||||
struct Bigint *freelist[Bigint_Kmax+1];
|
|
||||||
double preallocated[Bigint_PREALLOC_SIZE];
|
|
||||||
double *preallocated_next;
|
|
||||||
};
|
|
||||||
#define _dtoa_state_INIT(INTERP) \
|
#define _dtoa_state_INIT(INTERP) \
|
||||||
{ \
|
{ \
|
||||||
.preallocated_next = (INTERP)->dtoa.preallocated, \
|
.preallocated_next = (INTERP)->dtoa.preallocated, \
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
#endif // !Py_USING_MEMORY_DEBUGGER
|
|
||||||
|
|
||||||
|
|
||||||
extern double _Py_dg_strtod(const char *str, char **ptr);
|
extern double _Py_dg_strtod(const char *str, char **ptr);
|
||||||
extern char* _Py_dg_dtoa(double d, int mode, int ndigits,
|
extern char* _Py_dg_dtoa(double d, int mode, int ndigits,
|
||||||
|
|
|
@ -9,6 +9,7 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <locale.h> // struct lconv
|
#include <locale.h> // struct lconv
|
||||||
|
#include "pycore_runtime_structs.h" // _Py_error_handler
|
||||||
|
|
||||||
|
|
||||||
/* A routine to check if a file descriptor can be select()-ed. */
|
/* A routine to check if a file descriptor can be select()-ed. */
|
||||||
|
@ -19,22 +20,6 @@ extern "C" {
|
||||||
#define _PyIsSelectable_fd(FD) ((unsigned int)(FD) < (unsigned int)FD_SETSIZE)
|
#define _PyIsSelectable_fd(FD) ((unsigned int)(FD) < (unsigned int)FD_SETSIZE)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct _fileutils_state {
|
|
||||||
int force_ascii;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
_Py_ERROR_UNKNOWN=0,
|
|
||||||
_Py_ERROR_STRICT,
|
|
||||||
_Py_ERROR_SURROGATEESCAPE,
|
|
||||||
_Py_ERROR_REPLACE,
|
|
||||||
_Py_ERROR_IGNORE,
|
|
||||||
_Py_ERROR_BACKSLASHREPLACE,
|
|
||||||
_Py_ERROR_SURROGATEPASS,
|
|
||||||
_Py_ERROR_XMLCHARREFREPLACE,
|
|
||||||
_Py_ERROR_OTHER
|
|
||||||
} _Py_error_handler;
|
|
||||||
|
|
||||||
// Export for '_testinternalcapi' shared extension
|
// Export for '_testinternalcapi' shared extension
|
||||||
PyAPI_FUNC(_Py_error_handler) _Py_GetErrorHandler(const char *errors);
|
PyAPI_FUNC(_Py_error_handler) _Py_GetErrorHandler(const char *errors);
|
||||||
|
|
||||||
|
|
|
@ -17,20 +17,6 @@ extern PyStatus _PyFloat_InitTypes(PyInterpreterState *);
|
||||||
extern void _PyFloat_FiniType(PyInterpreterState *);
|
extern void _PyFloat_FiniType(PyInterpreterState *);
|
||||||
|
|
||||||
|
|
||||||
/* other API */
|
|
||||||
|
|
||||||
enum _py_float_format_type {
|
|
||||||
_py_float_format_unknown,
|
|
||||||
_py_float_format_ieee_big_endian,
|
|
||||||
_py_float_format_ieee_little_endian,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _Py_float_runtime_state {
|
|
||||||
enum _py_float_format_type float_format;
|
|
||||||
enum _py_float_format_type double_format;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
PyAPI_FUNC(void) _PyFloat_ExactDealloc(PyObject *op);
|
PyAPI_FUNC(void) _PyFloat_ExactDealloc(PyObject *op);
|
||||||
|
|
|
@ -16,33 +16,11 @@ extern PyObject* _PyFunction_Vectorcall(
|
||||||
size_t nargsf,
|
size_t nargsf,
|
||||||
PyObject *kwnames);
|
PyObject *kwnames);
|
||||||
|
|
||||||
#define FUNC_MAX_WATCHERS 8
|
|
||||||
|
|
||||||
#define FUNC_VERSION_UNSET 0
|
#define FUNC_VERSION_UNSET 0
|
||||||
#define FUNC_VERSION_CLEARED 1
|
#define FUNC_VERSION_CLEARED 1
|
||||||
#define FUNC_VERSION_FIRST_VALID 2
|
#define FUNC_VERSION_FIRST_VALID 2
|
||||||
|
|
||||||
#define FUNC_VERSION_CACHE_SIZE (1<<12) /* Must be a power of 2 */
|
|
||||||
|
|
||||||
struct _func_version_cache_item {
|
|
||||||
PyFunctionObject *func;
|
|
||||||
PyObject *code;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _py_func_state {
|
|
||||||
#ifdef Py_GIL_DISABLED
|
|
||||||
// Protects next_version
|
|
||||||
PyMutex mutex;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
uint32_t next_version;
|
|
||||||
// Borrowed references to function and code objects whose
|
|
||||||
// func_version % FUNC_VERSION_CACHE_SIZE
|
|
||||||
// once was equal to the index in the table.
|
|
||||||
// They are cleared when the function or code object is deallocated.
|
|
||||||
struct _func_version_cache_item func_version_cache[FUNC_VERSION_CACHE_SIZE];
|
|
||||||
};
|
|
||||||
|
|
||||||
extern PyFunctionObject* _PyFunction_FromConstructor(PyFrameConstructor *constr);
|
extern PyFunctionObject* _PyFunction_FromConstructor(PyFrameConstructor *constr);
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
|
|
|
@ -8,18 +8,7 @@ extern "C" {
|
||||||
# error "this header requires Py_BUILD_CORE define"
|
# error "this header requires Py_BUILD_CORE define"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* GC information is stored BEFORE the object structure. */
|
#include "pycore_runtime_structs.h"
|
||||||
typedef struct {
|
|
||||||
// Tagged pointer to next object in the list.
|
|
||||||
// 0 means the object is not tracked
|
|
||||||
uintptr_t _gc_next;
|
|
||||||
|
|
||||||
// Tagged pointer to previous object in the list.
|
|
||||||
// Lowest two bits are used for flags documented later.
|
|
||||||
uintptr_t _gc_prev;
|
|
||||||
} PyGC_Head;
|
|
||||||
|
|
||||||
#define _PyGC_Head_UNUSED PyGC_Head
|
|
||||||
|
|
||||||
|
|
||||||
/* Get an object's GC head */
|
/* Get an object's GC head */
|
||||||
|
@ -214,12 +203,6 @@ static inline void _PyGC_CLEAR_FINALIZED(PyObject *op) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* GC runtime state */
|
|
||||||
|
|
||||||
/* If we change this, we need to change the default value in the
|
|
||||||
signature of gc.collect. */
|
|
||||||
#define NUM_GENERATIONS 3
|
|
||||||
/*
|
/*
|
||||||
NOTE: about untracking of mutable objects.
|
NOTE: about untracking of mutable objects.
|
||||||
|
|
||||||
|
@ -261,90 +244,6 @@ static inline void _PyGC_CLEAR_FINALIZED(PyObject *op) {
|
||||||
the algorithm was refined in response to issue #14775.
|
the algorithm was refined in response to issue #14775.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct gc_generation {
|
|
||||||
PyGC_Head head;
|
|
||||||
int threshold; /* collection threshold */
|
|
||||||
int count; /* count of allocations or collections of younger
|
|
||||||
generations */
|
|
||||||
};
|
|
||||||
|
|
||||||
struct gc_collection_stats {
|
|
||||||
/* number of collected objects */
|
|
||||||
Py_ssize_t collected;
|
|
||||||
/* total number of uncollectable objects (put into gc.garbage) */
|
|
||||||
Py_ssize_t uncollectable;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Running stats per generation */
|
|
||||||
struct gc_generation_stats {
|
|
||||||
/* total number of collections */
|
|
||||||
Py_ssize_t collections;
|
|
||||||
/* total number of collected objects */
|
|
||||||
Py_ssize_t collected;
|
|
||||||
/* total number of uncollectable objects (put into gc.garbage) */
|
|
||||||
Py_ssize_t uncollectable;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum _GCPhase {
|
|
||||||
GC_PHASE_MARK = 0,
|
|
||||||
GC_PHASE_COLLECT = 1
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _gc_runtime_state {
|
|
||||||
/* List of objects that still need to be cleaned up, singly linked
|
|
||||||
* via their gc headers' gc_prev pointers. */
|
|
||||||
PyObject *trash_delete_later;
|
|
||||||
/* Current call-stack depth of tp_dealloc calls. */
|
|
||||||
int trash_delete_nesting;
|
|
||||||
|
|
||||||
/* Is automatic collection enabled? */
|
|
||||||
int enabled;
|
|
||||||
int debug;
|
|
||||||
/* linked lists of container objects */
|
|
||||||
struct gc_generation young;
|
|
||||||
struct gc_generation old[2];
|
|
||||||
/* a permanent generation which won't be collected */
|
|
||||||
struct gc_generation permanent_generation;
|
|
||||||
struct gc_generation_stats generation_stats[NUM_GENERATIONS];
|
|
||||||
/* true if we are currently running the collector */
|
|
||||||
int collecting;
|
|
||||||
/* list of uncollectable objects */
|
|
||||||
PyObject *garbage;
|
|
||||||
/* a list of callbacks to be invoked when collection is performed */
|
|
||||||
PyObject *callbacks;
|
|
||||||
|
|
||||||
Py_ssize_t heap_size;
|
|
||||||
Py_ssize_t work_to_do;
|
|
||||||
/* Which of the old spaces is the visited space */
|
|
||||||
int visited_space;
|
|
||||||
int phase;
|
|
||||||
|
|
||||||
#ifdef Py_GIL_DISABLED
|
|
||||||
/* This is the number of objects that survived the last full
|
|
||||||
collection. It approximates the number of long lived objects
|
|
||||||
tracked by the GC.
|
|
||||||
|
|
||||||
(by "full collection", we mean a collection of the oldest
|
|
||||||
generation). */
|
|
||||||
Py_ssize_t long_lived_total;
|
|
||||||
/* This is the number of objects that survived all "non-full"
|
|
||||||
collections, and are awaiting to undergo a full collection for
|
|
||||||
the first time. */
|
|
||||||
Py_ssize_t long_lived_pending;
|
|
||||||
|
|
||||||
/* True if gc.freeze() has been used. */
|
|
||||||
int freeze_active;
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef Py_GIL_DISABLED
|
|
||||||
struct _gc_thread_state {
|
|
||||||
/* Thread-local allocation count. */
|
|
||||||
Py_ssize_t alloc_count;
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
extern void _PyGC_InitState(struct _gc_runtime_state *);
|
extern void _PyGC_InitState(struct _gc_runtime_state *);
|
||||||
|
|
||||||
extern Py_ssize_t _PyGC_Collect(PyThreadState *tstate, int generation, _PyGC_Reason reason);
|
extern Py_ssize_t _PyGC_Collect(PyThreadState *tstate, int generation, _PyGC_Reason reason);
|
||||||
|
|
|
@ -8,18 +8,6 @@ extern "C" {
|
||||||
# error "this header requires Py_BUILD_CORE define"
|
# error "this header requires Py_BUILD_CORE define"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "pycore_context.h" // _PyContextTokenMissing
|
|
||||||
#include "pycore_gc.h" // _PyGC_Head_UNUSED
|
|
||||||
#include "pycore_global_strings.h" // struct _Py_global_strings
|
|
||||||
#include "pycore_hamt.h" // PyHamtNode_Bitmap
|
|
||||||
#include "pycore_hashtable.h" // _Py_hashtable_t
|
|
||||||
#include "pycore_typeobject.h" // pytype_slotdef
|
|
||||||
|
|
||||||
|
|
||||||
// These would be in pycore_long.h if it weren't for an include cycle.
|
|
||||||
#define _PY_NSMALLPOSINTS 257
|
|
||||||
#define _PY_NSMALLNEGINTS 5
|
|
||||||
|
|
||||||
|
|
||||||
// Only immutable objects should be considered runtime-global.
|
// Only immutable objects should be considered runtime-global.
|
||||||
// All others must be per-interpreter.
|
// All others must be per-interpreter.
|
||||||
|
@ -29,76 +17,16 @@ extern "C" {
|
||||||
#define _Py_SINGLETON(NAME) \
|
#define _Py_SINGLETON(NAME) \
|
||||||
_Py_GLOBAL_OBJECT(singletons.NAME)
|
_Py_GLOBAL_OBJECT(singletons.NAME)
|
||||||
|
|
||||||
struct _Py_cached_objects {
|
|
||||||
// XXX We could statically allocate the hashtable.
|
|
||||||
_Py_hashtable_t *interned_strings;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _Py_static_objects {
|
|
||||||
struct {
|
|
||||||
/* Small integers are preallocated in this array so that they
|
|
||||||
* can be shared.
|
|
||||||
* The integers that are preallocated are those in the range
|
|
||||||
* -_PY_NSMALLNEGINTS (inclusive) to _PY_NSMALLPOSINTS (exclusive).
|
|
||||||
*/
|
|
||||||
PyLongObject small_ints[_PY_NSMALLNEGINTS + _PY_NSMALLPOSINTS];
|
|
||||||
|
|
||||||
PyBytesObject bytes_empty;
|
|
||||||
struct {
|
|
||||||
PyBytesObject ob;
|
|
||||||
char eos;
|
|
||||||
} bytes_characters[256];
|
|
||||||
|
|
||||||
struct _Py_global_strings strings;
|
|
||||||
|
|
||||||
_PyGC_Head_UNUSED _tuple_empty_gc_not_used;
|
|
||||||
PyTupleObject tuple_empty;
|
|
||||||
|
|
||||||
_PyGC_Head_UNUSED _hamt_bitmap_node_empty_gc_not_used;
|
|
||||||
PyHamtNode_Bitmap hamt_bitmap_node_empty;
|
|
||||||
_PyContextTokenMissing context_token_missing;
|
|
||||||
} singletons;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define _Py_INTERP_CACHED_OBJECT(interp, NAME) \
|
#define _Py_INTERP_CACHED_OBJECT(interp, NAME) \
|
||||||
(interp)->cached_objects.NAME
|
(interp)->cached_objects.NAME
|
||||||
|
|
||||||
struct _Py_interp_cached_objects {
|
|
||||||
#ifdef Py_GIL_DISABLED
|
|
||||||
PyMutex interned_mutex;
|
|
||||||
#endif
|
|
||||||
PyObject *interned_strings;
|
|
||||||
|
|
||||||
/* object.__reduce__ */
|
|
||||||
PyObject *objreduce;
|
|
||||||
PyObject *type_slots_pname;
|
|
||||||
pytype_slotdef *type_slots_ptrs[MAX_EQUIV];
|
|
||||||
|
|
||||||
/* TypeVar and related types */
|
|
||||||
PyTypeObject *generic_type;
|
|
||||||
PyTypeObject *typevar_type;
|
|
||||||
PyTypeObject *typevartuple_type;
|
|
||||||
PyTypeObject *paramspec_type;
|
|
||||||
PyTypeObject *paramspecargs_type;
|
|
||||||
PyTypeObject *paramspeckwargs_type;
|
|
||||||
PyTypeObject *constevaluator_type;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define _Py_INTERP_STATIC_OBJECT(interp, NAME) \
|
#define _Py_INTERP_STATIC_OBJECT(interp, NAME) \
|
||||||
(interp)->static_objects.NAME
|
(interp)->static_objects.NAME
|
||||||
#define _Py_INTERP_SINGLETON(interp, NAME) \
|
#define _Py_INTERP_SINGLETON(interp, NAME) \
|
||||||
_Py_INTERP_STATIC_OBJECT(interp, singletons.NAME)
|
_Py_INTERP_STATIC_OBJECT(interp, singletons.NAME)
|
||||||
|
|
||||||
struct _Py_interp_static_objects {
|
|
||||||
struct {
|
|
||||||
int _not_used;
|
|
||||||
// hamt_empty is here instead of global because of its weakreflist.
|
|
||||||
_PyGC_Head_UNUSED _hamt_empty_gc_not_used;
|
|
||||||
PyHamtObject hamt_empty;
|
|
||||||
PyBaseExceptionObject last_resort_memory_error;
|
|
||||||
} singletons;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,8 @@ extern "C" {
|
||||||
# error "this header requires Py_BUILD_CORE define"
|
# error "this header requires Py_BUILD_CORE define"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "pycore_global_objects.h" // struct _Py_SINGLETON
|
||||||
|
|
||||||
// The data structure & init here are inspired by Tools/build/deepfreeze.py.
|
// The data structure & init here are inspired by Tools/build/deepfreeze.py.
|
||||||
|
|
||||||
// All field names generated by ASCII_STR() have a common prefix,
|
// All field names generated by ASCII_STR() have a common prefix,
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
# error "this header requires Py_BUILD_CORE define"
|
# error "this header requires Py_BUILD_CORE define"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "pycore_structs.h" // PyHamtNode
|
||||||
|
|
||||||
/*
|
/*
|
||||||
HAMT tree is shaped by hashes of keys. Every group of 5 bits of a hash denotes
|
HAMT tree is shaped by hashes of keys. Every group of 5 bits of a hash denotes
|
||||||
|
@ -34,28 +35,6 @@ extern PyTypeObject _PyHamtItems_Type;
|
||||||
#define PyHamt_Check(o) Py_IS_TYPE((o), &_PyHamt_Type)
|
#define PyHamt_Check(o) Py_IS_TYPE((o), &_PyHamt_Type)
|
||||||
|
|
||||||
|
|
||||||
/* Abstract tree node. */
|
|
||||||
typedef struct {
|
|
||||||
PyObject_HEAD
|
|
||||||
} PyHamtNode;
|
|
||||||
|
|
||||||
|
|
||||||
/* An HAMT immutable mapping collection. */
|
|
||||||
typedef struct {
|
|
||||||
PyObject_HEAD
|
|
||||||
PyHamtNode *h_root;
|
|
||||||
PyObject *h_weakreflist;
|
|
||||||
Py_ssize_t h_count;
|
|
||||||
} PyHamtObject;
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
PyObject_VAR_HEAD
|
|
||||||
uint32_t b_bitmap;
|
|
||||||
PyObject *b_array[1];
|
|
||||||
} PyHamtNode_Bitmap;
|
|
||||||
|
|
||||||
|
|
||||||
/* A struct to hold the state of depth-first traverse of the tree.
|
/* A struct to hold the state of depth-first traverse of the tree.
|
||||||
|
|
||||||
HAMT is an immutable collection. Iterators will hold a strong reference
|
HAMT is an immutable collection. Iterators will hold a strong reference
|
||||||
|
|
|
@ -10,6 +10,7 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "pycore_lock.h" // PyMutex
|
#include "pycore_lock.h" // PyMutex
|
||||||
|
#include "pycore_runtime_structs.h" // _import_state
|
||||||
#include "pycore_hashtable.h" // _Py_hashtable_t
|
#include "pycore_hashtable.h" // _Py_hashtable_t
|
||||||
|
|
||||||
extern int _PyImport_IsInitialized(PyInterpreterState *);
|
extern int _PyImport_IsInitialized(PyInterpreterState *);
|
||||||
|
@ -31,73 +32,6 @@ extern int _PyImport_FixupBuiltin(
|
||||||
PyObject *modules
|
PyObject *modules
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
struct _import_runtime_state {
|
|
||||||
/* The builtin modules (defined in config.c). */
|
|
||||||
struct _inittab *inittab;
|
|
||||||
/* The most recent value assigned to a PyModuleDef.m_base.m_index.
|
|
||||||
This is incremented each time PyModuleDef_Init() is called,
|
|
||||||
which is just about every time an extension module is imported.
|
|
||||||
See PyInterpreterState.modules_by_index for more info. */
|
|
||||||
Py_ssize_t last_module_index;
|
|
||||||
struct {
|
|
||||||
/* A lock to guard the cache. */
|
|
||||||
PyMutex mutex;
|
|
||||||
/* The actual cache of (filename, name, PyModuleDef) for modules.
|
|
||||||
Only legacy (single-phase init) extension modules are added
|
|
||||||
and only if they support multiple initialization (m_size >= 0)
|
|
||||||
or are imported in the main interpreter.
|
|
||||||
This is initialized lazily in fix_up_extension() in import.c.
|
|
||||||
Modules are added there and looked up in _imp.find_extension(). */
|
|
||||||
_Py_hashtable_t *hashtable;
|
|
||||||
} extensions;
|
|
||||||
/* Package context -- the full module name for package imports */
|
|
||||||
const char * pkgcontext;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _import_state {
|
|
||||||
/* cached sys.modules dictionary */
|
|
||||||
PyObject *modules;
|
|
||||||
/* This is the list of module objects for all legacy (single-phase init)
|
|
||||||
extension modules ever loaded in this process (i.e. imported
|
|
||||||
in this interpreter or in any other). Py_None stands in for
|
|
||||||
modules that haven't actually been imported in this interpreter.
|
|
||||||
|
|
||||||
A module's index (PyModuleDef.m_base.m_index) is used to look up
|
|
||||||
the corresponding module object for this interpreter, if any.
|
|
||||||
(See PyState_FindModule().) When any extension module
|
|
||||||
is initialized during import, its moduledef gets initialized by
|
|
||||||
PyModuleDef_Init(), and the first time that happens for each
|
|
||||||
PyModuleDef, its index gets set to the current value of
|
|
||||||
a global counter (see _PyRuntimeState.imports.last_module_index).
|
|
||||||
The entry for that index in this interpreter remains unset until
|
|
||||||
the module is actually imported here. (Py_None is used as
|
|
||||||
a placeholder.) Note that multi-phase init modules always get
|
|
||||||
an index for which there will never be a module set.
|
|
||||||
|
|
||||||
This is initialized lazily in PyState_AddModule(), which is also
|
|
||||||
where modules get added. */
|
|
||||||
PyObject *modules_by_index;
|
|
||||||
/* importlib module._bootstrap */
|
|
||||||
PyObject *importlib;
|
|
||||||
/* override for config->use_frozen_modules (for tests)
|
|
||||||
(-1: "off", 1: "on", 0: no override) */
|
|
||||||
int override_frozen_modules;
|
|
||||||
int override_multi_interp_extensions_check;
|
|
||||||
#ifdef HAVE_DLOPEN
|
|
||||||
int dlopenflags;
|
|
||||||
#endif
|
|
||||||
PyObject *import_func;
|
|
||||||
/* The global import lock. */
|
|
||||||
_PyRecursiveMutex lock;
|
|
||||||
/* diagnostic info in PyImport_ImportModuleLevelObject() */
|
|
||||||
struct {
|
|
||||||
int import_level;
|
|
||||||
PyTime_t accumulated;
|
|
||||||
int header;
|
|
||||||
} find_and_load;
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef HAVE_DLOPEN
|
#ifdef HAVE_DLOPEN
|
||||||
# include <dlfcn.h> // RTLD_NOW, RTLD_LAZY
|
# include <dlfcn.h> // RTLD_NOW, RTLD_LAZY
|
||||||
# if HAVE_DECL_RTLD_NOW
|
# if HAVE_DECL_RTLD_NOW
|
||||||
|
|
|
@ -13,32 +13,12 @@ extern "C" {
|
||||||
|
|
||||||
#ifdef Py_GIL_DISABLED
|
#ifdef Py_GIL_DISABLED
|
||||||
|
|
||||||
|
#include "pycore_interp_structs.h"
|
||||||
|
|
||||||
// This contains code for allocating unique indices in an array. It is used by
|
// This contains code for allocating unique indices in an array. It is used by
|
||||||
// the free-threaded build to assign each thread a globally unique index into
|
// the free-threaded build to assign each thread a globally unique index into
|
||||||
// each code object's thread-local bytecode array.
|
// each code object's thread-local bytecode array.
|
||||||
|
|
||||||
// A min-heap of indices
|
|
||||||
typedef struct _PyIndexHeap {
|
|
||||||
int32_t *values;
|
|
||||||
|
|
||||||
// Number of items stored in values
|
|
||||||
Py_ssize_t size;
|
|
||||||
|
|
||||||
// Maximum number of items that can be stored in values
|
|
||||||
Py_ssize_t capacity;
|
|
||||||
} _PyIndexHeap;
|
|
||||||
|
|
||||||
// An unbounded pool of indices. Indices are allocated starting from 0. They
|
|
||||||
// may be released back to the pool once they are no longer in use.
|
|
||||||
typedef struct _PyIndexPool {
|
|
||||||
PyMutex mutex;
|
|
||||||
|
|
||||||
// Min heap of indices available for allocation
|
|
||||||
_PyIndexHeap free_indices;
|
|
||||||
|
|
||||||
// Next index to allocate if no free indices are available
|
|
||||||
int32_t next_index;
|
|
||||||
} _PyIndexPool;
|
|
||||||
|
|
||||||
// Allocate the smallest available index. Returns -1 on error.
|
// Allocate the smallest available index. Returns -1 on error.
|
||||||
extern int32_t _PyIndexPool_AllocIndex(_PyIndexPool *indices);
|
extern int32_t _PyIndexPool_AllocIndex(_PyIndexPool *indices);
|
||||||
|
|
|
@ -5,14 +5,12 @@
|
||||||
# error "this header requires Py_BUILD_CORE define"
|
# error "this header requires Py_BUILD_CORE define"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "pycore_frame.h" // _PyInterpreterFrame
|
#include "pycore_structs.h" // _Py_CODEUNIT
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define PY_MONITORING_TOOL_IDS 8
|
|
||||||
|
|
||||||
typedef uint32_t _PyMonitoringEventSet;
|
typedef uint32_t _PyMonitoringEventSet;
|
||||||
|
|
||||||
/* Tool IDs */
|
/* Tool IDs */
|
||||||
|
@ -36,32 +34,32 @@ int _PyMonitoring_GetLocalEvents(PyCodeObject *code, int tool_id, _PyMonitoringE
|
||||||
|
|
||||||
extern int
|
extern int
|
||||||
_Py_call_instrumentation(PyThreadState *tstate, int event,
|
_Py_call_instrumentation(PyThreadState *tstate, int event,
|
||||||
_PyInterpreterFrame *frame, _Py_CODEUNIT *instr);
|
struct _PyInterpreterFrame *frame, _Py_CODEUNIT *instr);
|
||||||
|
|
||||||
extern int
|
extern int
|
||||||
_Py_call_instrumentation_line(PyThreadState *tstate, _PyInterpreterFrame* frame,
|
_Py_call_instrumentation_line(PyThreadState *tstate, struct _PyInterpreterFrame* frame,
|
||||||
_Py_CODEUNIT *instr, _Py_CODEUNIT *prev);
|
_Py_CODEUNIT *instr, _Py_CODEUNIT *prev);
|
||||||
|
|
||||||
extern int
|
extern int
|
||||||
_Py_call_instrumentation_instruction(
|
_Py_call_instrumentation_instruction(
|
||||||
PyThreadState *tstate, _PyInterpreterFrame* frame, _Py_CODEUNIT *instr);
|
PyThreadState *tstate, struct _PyInterpreterFrame* frame, _Py_CODEUNIT *instr);
|
||||||
|
|
||||||
_Py_CODEUNIT *
|
_Py_CODEUNIT *
|
||||||
_Py_call_instrumentation_jump(
|
_Py_call_instrumentation_jump(
|
||||||
_Py_CODEUNIT *instr, PyThreadState *tstate, int event,
|
_Py_CODEUNIT *instr, PyThreadState *tstate, int event,
|
||||||
_PyInterpreterFrame *frame, _Py_CODEUNIT *src, _Py_CODEUNIT *dest);
|
struct _PyInterpreterFrame *frame, _Py_CODEUNIT *src, _Py_CODEUNIT *dest);
|
||||||
|
|
||||||
extern int
|
extern int
|
||||||
_Py_call_instrumentation_arg(PyThreadState *tstate, int event,
|
_Py_call_instrumentation_arg(PyThreadState *tstate, int event,
|
||||||
_PyInterpreterFrame *frame, _Py_CODEUNIT *instr, PyObject *arg);
|
struct _PyInterpreterFrame *frame, _Py_CODEUNIT *instr, PyObject *arg);
|
||||||
|
|
||||||
extern int
|
extern int
|
||||||
_Py_call_instrumentation_2args(PyThreadState *tstate, int event,
|
_Py_call_instrumentation_2args(PyThreadState *tstate, int event,
|
||||||
_PyInterpreterFrame *frame, _Py_CODEUNIT *instr, PyObject *arg0, PyObject *arg1);
|
struct _PyInterpreterFrame *frame, _Py_CODEUNIT *instr, PyObject *arg0, PyObject *arg1);
|
||||||
|
|
||||||
extern void
|
extern void
|
||||||
_Py_call_instrumentation_exc2(PyThreadState *tstate, int event,
|
_Py_call_instrumentation_exc2(PyThreadState *tstate, int event,
|
||||||
_PyInterpreterFrame *frame, _Py_CODEUNIT *instr, PyObject *arg0, PyObject *arg1);
|
struct _PyInterpreterFrame *frame, _Py_CODEUNIT *instr, PyObject *arg0, PyObject *arg1);
|
||||||
|
|
||||||
extern int
|
extern int
|
||||||
_Py_Instrumentation_GetLine(PyCodeObject *code, int index);
|
_Py_Instrumentation_GetLine(PyCodeObject *code, int index);
|
||||||
|
@ -69,6 +67,59 @@ _Py_Instrumentation_GetLine(PyCodeObject *code, int index);
|
||||||
extern PyObject _PyInstrumentation_MISSING;
|
extern PyObject _PyInstrumentation_MISSING;
|
||||||
extern PyObject _PyInstrumentation_DISABLE;
|
extern PyObject _PyInstrumentation_DISABLE;
|
||||||
|
|
||||||
|
|
||||||
|
/* Total tool ids available */
|
||||||
|
#define PY_MONITORING_TOOL_IDS 8
|
||||||
|
/* Count of all local monitoring events */
|
||||||
|
#define _PY_MONITORING_LOCAL_EVENTS 11
|
||||||
|
/* Count of all "real" monitoring events (not derived from other events) */
|
||||||
|
#define _PY_MONITORING_UNGROUPED_EVENTS 16
|
||||||
|
/* Count of all monitoring events */
|
||||||
|
#define _PY_MONITORING_EVENTS 19
|
||||||
|
|
||||||
|
/* Tables of which tools are active for each monitored event. */
|
||||||
|
typedef struct _Py_LocalMonitors {
|
||||||
|
uint8_t tools[_PY_MONITORING_LOCAL_EVENTS];
|
||||||
|
} _Py_LocalMonitors;
|
||||||
|
|
||||||
|
typedef struct _Py_GlobalMonitors {
|
||||||
|
uint8_t tools[_PY_MONITORING_UNGROUPED_EVENTS];
|
||||||
|
} _Py_GlobalMonitors;
|
||||||
|
|
||||||
|
/* Ancillary data structure used for instrumentation.
|
||||||
|
Line instrumentation creates this with sufficient
|
||||||
|
space for one entry per code unit. The total size
|
||||||
|
of the data will be `bytes_per_entry * Py_SIZE(code)` */
|
||||||
|
typedef struct {
|
||||||
|
uint8_t bytes_per_entry;
|
||||||
|
uint8_t data[1];
|
||||||
|
} _PyCoLineInstrumentationData;
|
||||||
|
|
||||||
|
|
||||||
|
/* Main data structure used for instrumentation.
|
||||||
|
* This is allocated when needed for instrumentation
|
||||||
|
*/
|
||||||
|
typedef struct _PyCoMonitoringData {
|
||||||
|
/* Monitoring specific to this code object */
|
||||||
|
_Py_LocalMonitors local_monitors;
|
||||||
|
/* Monitoring that is active on this code object */
|
||||||
|
_Py_LocalMonitors active_monitors;
|
||||||
|
/* The tools that are to be notified for events for the matching code unit */
|
||||||
|
uint8_t *tools;
|
||||||
|
/* The version of tools when they instrument the code */
|
||||||
|
uintptr_t tool_versions[PY_MONITORING_TOOL_IDS];
|
||||||
|
/* Information to support line events */
|
||||||
|
_PyCoLineInstrumentationData *lines;
|
||||||
|
/* The tools that are to be notified for line events for the matching code unit */
|
||||||
|
uint8_t *line_tools;
|
||||||
|
/* Information to support instruction events */
|
||||||
|
/* The underlying instructions, which can themselves be instrumented */
|
||||||
|
uint8_t *per_instruction_opcodes;
|
||||||
|
/* The tools that are to be notified for instruction events for the matching code unit */
|
||||||
|
uint8_t *per_instruction_tools;
|
||||||
|
} _PyCoMonitoringData;
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -10,8 +10,7 @@ extern "C" {
|
||||||
|
|
||||||
#include <stdbool.h> // bool
|
#include <stdbool.h> // bool
|
||||||
|
|
||||||
#include "pycore_ast_state.h" // struct ast_state
|
#include "pycore_runtime_structs.h"
|
||||||
#include "pycore_atexit.h" // struct atexit_state
|
|
||||||
#include "pycore_ceval_state.h" // struct _ceval_state
|
#include "pycore_ceval_state.h" // struct _ceval_state
|
||||||
#include "pycore_code.h" // struct callable_cache
|
#include "pycore_code.h" // struct callable_cache
|
||||||
#include "pycore_codecs.h" // struct codecs_state
|
#include "pycore_codecs.h" // struct codecs_state
|
||||||
|
@ -43,70 +42,9 @@ extern "C" {
|
||||||
#include "pycore_warnings.h" // struct _warnings_runtime_state
|
#include "pycore_warnings.h" // struct _warnings_runtime_state
|
||||||
|
|
||||||
|
|
||||||
struct _Py_long_state {
|
|
||||||
int max_str_digits;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Support for stop-the-world events. This exists in both the PyRuntime struct
|
|
||||||
// for global pauses and in each PyInterpreterState for per-interpreter pauses.
|
|
||||||
struct _stoptheworld_state {
|
|
||||||
PyMutex mutex; // Serializes stop-the-world attempts.
|
|
||||||
|
|
||||||
// NOTE: The below fields are protected by HEAD_LOCK(runtime), not by the
|
|
||||||
// above mutex.
|
|
||||||
bool requested; // Set when a pause is requested.
|
|
||||||
bool world_stopped; // Set when the world is stopped.
|
|
||||||
bool is_global; // Set when contained in PyRuntime struct.
|
|
||||||
|
|
||||||
PyEvent stop_event; // Set when thread_countdown reaches zero.
|
|
||||||
Py_ssize_t thread_countdown; // Number of threads that must pause.
|
|
||||||
|
|
||||||
PyThreadState *requester; // Thread that requested the pause (may be NULL).
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef Py_GIL_DISABLED
|
|
||||||
// This should be prime but otherwise the choice is arbitrary. A larger value
|
|
||||||
// increases concurrency at the expense of memory.
|
|
||||||
# define NUM_WEAKREF_LIST_LOCKS 127
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* cross-interpreter data registry */
|
|
||||||
|
|
||||||
/* Tracks some rare events per-interpreter, used by the optimizer to turn on/off
|
|
||||||
specific optimizations. */
|
|
||||||
typedef struct _rare_events {
|
|
||||||
/* Setting an object's class, obj.__class__ = ... */
|
|
||||||
uint8_t set_class;
|
|
||||||
/* Setting the bases of a class, cls.__bases__ = ... */
|
|
||||||
uint8_t set_bases;
|
|
||||||
/* Setting the PEP 523 frame eval function, _PyInterpreterState_SetFrameEvalFunc() */
|
|
||||||
uint8_t set_eval_frame_func;
|
|
||||||
/* Modifying the builtins, __builtins__.__dict__[var] = ... */
|
|
||||||
uint8_t builtin_dict;
|
|
||||||
/* Modifying a function, e.g. func.__defaults__ = ..., etc. */
|
|
||||||
uint8_t func_modification;
|
|
||||||
} _rare_events;
|
|
||||||
|
|
||||||
/* interpreter state */
|
/* interpreter state */
|
||||||
|
|
||||||
/* PyInterpreterState holds the global state for one of the runtime's
|
|
||||||
interpreters. Typically the initial (main) interpreter is the only one.
|
|
||||||
|
|
||||||
The PyInterpreterState typedef is in Include/pytypedefs.h.
|
|
||||||
*/
|
|
||||||
struct _is {
|
|
||||||
|
|
||||||
/* This struct contains the eval_breaker,
|
|
||||||
* which is by far the hottest field in this struct
|
|
||||||
* and should be placed at the beginning. */
|
|
||||||
struct _ceval_state ceval;
|
|
||||||
|
|
||||||
PyInterpreterState *next;
|
|
||||||
|
|
||||||
int64_t id;
|
|
||||||
Py_ssize_t id_refcount;
|
|
||||||
int requires_idref;
|
|
||||||
|
|
||||||
#define _PyInterpreterState_WHENCE_NOTSET -1
|
#define _PyInterpreterState_WHENCE_NOTSET -1
|
||||||
#define _PyInterpreterState_WHENCE_UNKNOWN 0
|
#define _PyInterpreterState_WHENCE_UNKNOWN 0
|
||||||
#define _PyInterpreterState_WHENCE_RUNTIME 1
|
#define _PyInterpreterState_WHENCE_RUNTIME 1
|
||||||
|
@ -115,193 +53,6 @@ struct _is {
|
||||||
#define _PyInterpreterState_WHENCE_XI 4
|
#define _PyInterpreterState_WHENCE_XI 4
|
||||||
#define _PyInterpreterState_WHENCE_STDLIB 5
|
#define _PyInterpreterState_WHENCE_STDLIB 5
|
||||||
#define _PyInterpreterState_WHENCE_MAX 5
|
#define _PyInterpreterState_WHENCE_MAX 5
|
||||||
long _whence;
|
|
||||||
|
|
||||||
/* Has been initialized to a safe state.
|
|
||||||
|
|
||||||
In order to be effective, this must be set to 0 during or right
|
|
||||||
after allocation. */
|
|
||||||
int _initialized;
|
|
||||||
/* Has been fully initialized via pylifecycle.c. */
|
|
||||||
int _ready;
|
|
||||||
int finalizing;
|
|
||||||
|
|
||||||
uintptr_t last_restart_version;
|
|
||||||
struct pythreads {
|
|
||||||
uint64_t next_unique_id;
|
|
||||||
/* The linked list of threads, newest first. */
|
|
||||||
PyThreadState *head;
|
|
||||||
_PyThreadStateImpl *preallocated;
|
|
||||||
/* The thread currently executing in the __main__ module, if any. */
|
|
||||||
PyThreadState *main;
|
|
||||||
/* Used in Modules/_threadmodule.c. */
|
|
||||||
Py_ssize_t count;
|
|
||||||
/* Support for runtime thread stack size tuning.
|
|
||||||
A value of 0 means using the platform's default stack size
|
|
||||||
or the size specified by the THREAD_STACK_SIZE macro. */
|
|
||||||
/* Used in Python/thread.c. */
|
|
||||||
size_t stacksize;
|
|
||||||
} threads;
|
|
||||||
|
|
||||||
/* Reference to the _PyRuntime global variable. This field exists
|
|
||||||
to not have to pass runtime in addition to tstate to a function.
|
|
||||||
Get runtime from tstate: tstate->interp->runtime. */
|
|
||||||
struct pyruntimestate *runtime;
|
|
||||||
|
|
||||||
/* Set by Py_EndInterpreter().
|
|
||||||
|
|
||||||
Use _PyInterpreterState_GetFinalizing()
|
|
||||||
and _PyInterpreterState_SetFinalizing()
|
|
||||||
to access it, don't access it directly. */
|
|
||||||
PyThreadState* _finalizing;
|
|
||||||
/* The ID of the OS thread in which we are finalizing. */
|
|
||||||
unsigned long _finalizing_id;
|
|
||||||
|
|
||||||
struct _gc_runtime_state gc;
|
|
||||||
|
|
||||||
/* The following fields are here to avoid allocation during init.
|
|
||||||
The data is exposed through PyInterpreterState pointer fields.
|
|
||||||
These fields should not be accessed directly outside of init.
|
|
||||||
|
|
||||||
All other PyInterpreterState pointer fields are populated when
|
|
||||||
needed and default to NULL.
|
|
||||||
|
|
||||||
For now there are some exceptions to that rule, which require
|
|
||||||
allocation during init. These will be addressed on a case-by-case
|
|
||||||
basis. Also see _PyRuntimeState regarding the various mutex fields.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Dictionary of the sys module
|
|
||||||
PyObject *sysdict;
|
|
||||||
|
|
||||||
// Dictionary of the builtins module
|
|
||||||
PyObject *builtins;
|
|
||||||
|
|
||||||
struct _import_state imports;
|
|
||||||
|
|
||||||
/* The per-interpreter GIL, which might not be used. */
|
|
||||||
struct _gil_runtime_state _gil;
|
|
||||||
|
|
||||||
/* ---------- IMPORTANT ---------------------------
|
|
||||||
The fields above this line are declared as early as
|
|
||||||
possible to facilitate out-of-process observability
|
|
||||||
tools. */
|
|
||||||
|
|
||||||
struct codecs_state codecs;
|
|
||||||
|
|
||||||
PyConfig config;
|
|
||||||
unsigned long feature_flags;
|
|
||||||
|
|
||||||
PyObject *dict; /* Stores per-interpreter state */
|
|
||||||
|
|
||||||
PyObject *sysdict_copy;
|
|
||||||
PyObject *builtins_copy;
|
|
||||||
// Initialized to _PyEval_EvalFrameDefault().
|
|
||||||
_PyFrameEvalFunction eval_frame;
|
|
||||||
|
|
||||||
PyFunction_WatchCallback func_watchers[FUNC_MAX_WATCHERS];
|
|
||||||
// One bit is set for each non-NULL entry in func_watchers
|
|
||||||
uint8_t active_func_watchers;
|
|
||||||
|
|
||||||
Py_ssize_t co_extra_user_count;
|
|
||||||
freefunc co_extra_freefuncs[MAX_CO_EXTRA_USERS];
|
|
||||||
|
|
||||||
/* cross-interpreter data and utils */
|
|
||||||
_PyXI_state_t xi;
|
|
||||||
|
|
||||||
#ifdef HAVE_FORK
|
|
||||||
PyObject *before_forkers;
|
|
||||||
PyObject *after_forkers_parent;
|
|
||||||
PyObject *after_forkers_child;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct _warnings_runtime_state warnings;
|
|
||||||
struct atexit_state atexit;
|
|
||||||
struct _stoptheworld_state stoptheworld;
|
|
||||||
struct _qsbr_shared qsbr;
|
|
||||||
|
|
||||||
#if defined(Py_GIL_DISABLED)
|
|
||||||
struct _mimalloc_interp_state mimalloc;
|
|
||||||
struct _brc_state brc; // biased reference counting state
|
|
||||||
struct _Py_unique_id_pool unique_ids; // object ids for per-thread refcounts
|
|
||||||
PyMutex weakref_locks[NUM_WEAKREF_LIST_LOCKS];
|
|
||||||
_PyIndexPool tlbc_indices;
|
|
||||||
#endif
|
|
||||||
// Per-interpreter list of tasks, any lingering tasks from thread
|
|
||||||
// states gets added here and removed from the corresponding
|
|
||||||
// thread state's list.
|
|
||||||
struct llist_node asyncio_tasks_head;
|
|
||||||
// `asyncio_tasks_lock` is used when tasks are moved
|
|
||||||
// from thread's list to interpreter's list.
|
|
||||||
PyMutex asyncio_tasks_lock;
|
|
||||||
|
|
||||||
// Per-interpreter state for the obmalloc allocator. For the main
|
|
||||||
// interpreter and for all interpreters that don't have their
|
|
||||||
// own obmalloc state, this points to the static structure in
|
|
||||||
// obmalloc.c obmalloc_state_main. For other interpreters, it is
|
|
||||||
// heap allocated by _PyMem_init_obmalloc() and freed when the
|
|
||||||
// interpreter structure is freed. In the case of a heap allocated
|
|
||||||
// obmalloc state, it is not safe to hold on to or use memory after
|
|
||||||
// the interpreter is freed. The obmalloc state corresponding to
|
|
||||||
// that allocated memory is gone. See free_obmalloc_arenas() for
|
|
||||||
// more comments.
|
|
||||||
struct _obmalloc_state *obmalloc;
|
|
||||||
|
|
||||||
PyObject *audit_hooks;
|
|
||||||
PyType_WatchCallback type_watchers[TYPE_MAX_WATCHERS];
|
|
||||||
PyCode_WatchCallback code_watchers[CODE_MAX_WATCHERS];
|
|
||||||
PyContext_WatchCallback context_watchers[CONTEXT_MAX_WATCHERS];
|
|
||||||
// One bit is set for each non-NULL entry in code_watchers
|
|
||||||
uint8_t active_code_watchers;
|
|
||||||
uint8_t active_context_watchers;
|
|
||||||
|
|
||||||
struct _py_object_state object_state;
|
|
||||||
struct _Py_unicode_state unicode;
|
|
||||||
struct _Py_long_state long_state;
|
|
||||||
struct _dtoa_state dtoa;
|
|
||||||
struct _py_func_state func_state;
|
|
||||||
struct _py_code_state code_state;
|
|
||||||
|
|
||||||
struct _Py_dict_state dict_state;
|
|
||||||
struct _Py_exc_state exc_state;
|
|
||||||
struct _Py_mem_interp_free_queue mem_free_queue;
|
|
||||||
|
|
||||||
struct ast_state ast;
|
|
||||||
struct types_state types;
|
|
||||||
struct callable_cache callable_cache;
|
|
||||||
bool jit;
|
|
||||||
_PyExecutorObject *executor_list_head;
|
|
||||||
size_t trace_run_counter;
|
|
||||||
_rare_events rare_events;
|
|
||||||
PyDict_WatchCallback builtins_dict_watcher;
|
|
||||||
|
|
||||||
_Py_GlobalMonitors monitors;
|
|
||||||
bool sys_profile_initialized;
|
|
||||||
bool sys_trace_initialized;
|
|
||||||
Py_ssize_t sys_profiling_threads; /* Count of threads with c_profilefunc set */
|
|
||||||
Py_ssize_t sys_tracing_threads; /* Count of threads with c_tracefunc set */
|
|
||||||
PyObject *monitoring_callables[PY_MONITORING_TOOL_IDS][_PY_MONITORING_EVENTS];
|
|
||||||
PyObject *monitoring_tool_names[PY_MONITORING_TOOL_IDS];
|
|
||||||
uintptr_t monitoring_tool_versions[PY_MONITORING_TOOL_IDS];
|
|
||||||
|
|
||||||
struct _Py_interp_cached_objects cached_objects;
|
|
||||||
struct _Py_interp_static_objects static_objects;
|
|
||||||
|
|
||||||
Py_ssize_t _interactive_src_count;
|
|
||||||
|
|
||||||
/* the initial PyInterpreterState.threads.head */
|
|
||||||
_PyThreadStateImpl _initial_thread;
|
|
||||||
// _initial_thread should be the last field of PyInterpreterState.
|
|
||||||
// See https://github.com/python/cpython/issues/127117.
|
|
||||||
|
|
||||||
#if !defined(Py_GIL_DISABLED) && defined(Py_STACKREF_DEBUG)
|
|
||||||
uint64_t next_stackref;
|
|
||||||
_Py_hashtable_t *open_stackrefs_table;
|
|
||||||
# ifdef Py_STACKREF_CLOSE_DEBUG
|
|
||||||
_Py_hashtable_t *closed_stackrefs_table;
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/* other API */
|
/* other API */
|
||||||
|
|
967
Include/internal/pycore_interp_structs.h
Normal file
967
Include/internal/pycore_interp_structs.h
Normal file
|
@ -0,0 +1,967 @@
|
||||||
|
#ifndef Py_INTERNAL_INTERP_STRUCTS_H
|
||||||
|
#define Py_INTERNAL_INTERP_STRUCTS_H
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "pycore_structs.h"
|
||||||
|
#include "pycore_pymath.h" // _PY_SHORT_FLOAT_REPR
|
||||||
|
#include "pycore_llist.h"
|
||||||
|
#include "pycore_ast_state.h" // struct ast_state
|
||||||
|
|
||||||
|
|
||||||
|
/* This file contains the struct definitions for interpreter state
|
||||||
|
* and other necessary structs */
|
||||||
|
|
||||||
|
#define CODE_MAX_WATCHERS 8
|
||||||
|
#define CONTEXT_MAX_WATCHERS 8
|
||||||
|
#define FUNC_MAX_WATCHERS 8
|
||||||
|
#define TYPE_MAX_WATCHERS 8
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef Py_GIL_DISABLED
|
||||||
|
// This should be prime but otherwise the choice is arbitrary. A larger value
|
||||||
|
// increases concurrency at the expense of memory.
|
||||||
|
# define NUM_WEAKREF_LIST_LOCKS 127
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef int (*_Py_pending_call_func)(void *);
|
||||||
|
|
||||||
|
struct _pending_call {
|
||||||
|
_Py_pending_call_func func;
|
||||||
|
void *arg;
|
||||||
|
int flags;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define PENDINGCALLSARRAYSIZE 300
|
||||||
|
|
||||||
|
struct _pending_calls {
|
||||||
|
PyThreadState *handling_thread;
|
||||||
|
PyMutex mutex;
|
||||||
|
/* Request for running pending calls. */
|
||||||
|
int32_t npending;
|
||||||
|
/* The maximum allowed number of pending calls.
|
||||||
|
If the queue fills up to this point then _PyEval_AddPendingCall()
|
||||||
|
will return _Py_ADD_PENDING_FULL. */
|
||||||
|
int32_t max;
|
||||||
|
/* We don't want a flood of pending calls to interrupt any one thread
|
||||||
|
for too long, so we keep a limit on the number handled per pass.
|
||||||
|
A value of 0 means there is no limit (other than the maximum
|
||||||
|
size of the list of pending calls). */
|
||||||
|
int32_t maxloop;
|
||||||
|
struct _pending_call calls[PENDINGCALLSARRAYSIZE];
|
||||||
|
int first;
|
||||||
|
int next;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
PERF_STATUS_FAILED = -1, // Perf trampoline is in an invalid state
|
||||||
|
PERF_STATUS_NO_INIT = 0, // Perf trampoline is not initialized
|
||||||
|
PERF_STATUS_OK = 1, // Perf trampoline is ready to be executed
|
||||||
|
} perf_status_t;
|
||||||
|
|
||||||
|
#ifdef PY_HAVE_PERF_TRAMPOLINE
|
||||||
|
struct code_arena_st;
|
||||||
|
|
||||||
|
struct trampoline_api_st {
|
||||||
|
void* (*init_state)(void);
|
||||||
|
void (*write_state)(void* state, const void *code_addr,
|
||||||
|
unsigned int code_size, PyCodeObject* code);
|
||||||
|
int (*free_state)(void* state);
|
||||||
|
void *state;
|
||||||
|
Py_ssize_t code_padding;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
struct _ceval_runtime_state {
|
||||||
|
struct {
|
||||||
|
#ifdef PY_HAVE_PERF_TRAMPOLINE
|
||||||
|
perf_status_t status;
|
||||||
|
int perf_trampoline_type;
|
||||||
|
Py_ssize_t extra_code_index;
|
||||||
|
struct code_arena_st *code_arena;
|
||||||
|
struct trampoline_api_st trampoline_api;
|
||||||
|
FILE *map_file;
|
||||||
|
Py_ssize_t persist_after_fork;
|
||||||
|
#else
|
||||||
|
int _not_used;
|
||||||
|
#endif
|
||||||
|
} perf;
|
||||||
|
/* Pending calls to be made only on the main thread. */
|
||||||
|
// The signal machinery falls back on this
|
||||||
|
// so it must be especially stable and efficient.
|
||||||
|
// For example, we use a preallocated array
|
||||||
|
// for the list of pending calls.
|
||||||
|
struct _pending_calls pending_mainthread;
|
||||||
|
PyMutex sys_trace_profile_mutex;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct _ceval_state {
|
||||||
|
/* This variable holds the global instrumentation version. When a thread is
|
||||||
|
running, this value is overlaid onto PyThreadState.eval_breaker so that
|
||||||
|
changes in the instrumentation version will trigger the eval breaker. */
|
||||||
|
uintptr_t instrumentation_version;
|
||||||
|
int recursion_limit;
|
||||||
|
struct _gil_runtime_state *gil;
|
||||||
|
int own_gil;
|
||||||
|
struct _pending_calls pending;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//###############
|
||||||
|
// runtime atexit
|
||||||
|
|
||||||
|
typedef void (*atexit_callbackfunc)(void);
|
||||||
|
|
||||||
|
struct _atexit_runtime_state {
|
||||||
|
PyMutex mutex;
|
||||||
|
#define NEXITFUNCS 32
|
||||||
|
atexit_callbackfunc callbacks[NEXITFUNCS];
|
||||||
|
int ncallbacks;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//###################
|
||||||
|
// interpreter atexit
|
||||||
|
|
||||||
|
typedef void (*atexit_datacallbackfunc)(void *);
|
||||||
|
|
||||||
|
typedef struct atexit_callback {
|
||||||
|
atexit_datacallbackfunc func;
|
||||||
|
void *data;
|
||||||
|
struct atexit_callback *next;
|
||||||
|
} atexit_callback;
|
||||||
|
|
||||||
|
struct atexit_state {
|
||||||
|
#ifdef Py_GIL_DISABLED
|
||||||
|
PyMutex ll_callbacks_lock;
|
||||||
|
#endif
|
||||||
|
atexit_callback *ll_callbacks;
|
||||||
|
|
||||||
|
// XXX The rest of the state could be moved to the atexit module state
|
||||||
|
// and a low-level callback added for it during module exec.
|
||||||
|
// For the moment we leave it here.
|
||||||
|
|
||||||
|
// List containing tuples with callback information.
|
||||||
|
// e.g. [(func, args, kwargs), ...]
|
||||||
|
PyObject *callbacks;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/****** Garbage collector **********/
|
||||||
|
|
||||||
|
/* GC information is stored BEFORE the object structure. */
|
||||||
|
typedef struct {
|
||||||
|
// Tagged pointer to next object in the list.
|
||||||
|
// 0 means the object is not tracked
|
||||||
|
uintptr_t _gc_next;
|
||||||
|
|
||||||
|
// Tagged pointer to previous object in the list.
|
||||||
|
// Lowest two bits are used for flags documented later.
|
||||||
|
uintptr_t _gc_prev;
|
||||||
|
} PyGC_Head;
|
||||||
|
|
||||||
|
#define _PyGC_Head_UNUSED PyGC_Head
|
||||||
|
|
||||||
|
struct gc_generation {
|
||||||
|
PyGC_Head head;
|
||||||
|
int threshold; /* collection threshold */
|
||||||
|
int count; /* count of allocations or collections of younger
|
||||||
|
generations */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct gc_collection_stats {
|
||||||
|
/* number of collected objects */
|
||||||
|
Py_ssize_t collected;
|
||||||
|
/* total number of uncollectable objects (put into gc.garbage) */
|
||||||
|
Py_ssize_t uncollectable;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Running stats per generation */
|
||||||
|
struct gc_generation_stats {
|
||||||
|
/* total number of collections */
|
||||||
|
Py_ssize_t collections;
|
||||||
|
/* total number of collected objects */
|
||||||
|
Py_ssize_t collected;
|
||||||
|
/* total number of uncollectable objects (put into gc.garbage) */
|
||||||
|
Py_ssize_t uncollectable;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum _GCPhase {
|
||||||
|
GC_PHASE_MARK = 0,
|
||||||
|
GC_PHASE_COLLECT = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
/* If we change this, we need to change the default value in the
|
||||||
|
signature of gc.collect. */
|
||||||
|
#define NUM_GENERATIONS 3
|
||||||
|
|
||||||
|
struct _gc_runtime_state {
|
||||||
|
/* List of objects that still need to be cleaned up, singly linked
|
||||||
|
* via their gc headers' gc_prev pointers. */
|
||||||
|
PyObject *trash_delete_later;
|
||||||
|
/* Current call-stack depth of tp_dealloc calls. */
|
||||||
|
int trash_delete_nesting;
|
||||||
|
|
||||||
|
/* Is automatic collection enabled? */
|
||||||
|
int enabled;
|
||||||
|
int debug;
|
||||||
|
/* linked lists of container objects */
|
||||||
|
struct gc_generation young;
|
||||||
|
struct gc_generation old[2];
|
||||||
|
/* a permanent generation which won't be collected */
|
||||||
|
struct gc_generation permanent_generation;
|
||||||
|
struct gc_generation_stats generation_stats[NUM_GENERATIONS];
|
||||||
|
/* true if we are currently running the collector */
|
||||||
|
int collecting;
|
||||||
|
/* list of uncollectable objects */
|
||||||
|
PyObject *garbage;
|
||||||
|
/* a list of callbacks to be invoked when collection is performed */
|
||||||
|
PyObject *callbacks;
|
||||||
|
|
||||||
|
Py_ssize_t heap_size;
|
||||||
|
Py_ssize_t work_to_do;
|
||||||
|
/* Which of the old spaces is the visited space */
|
||||||
|
int visited_space;
|
||||||
|
int phase;
|
||||||
|
|
||||||
|
#ifdef Py_GIL_DISABLED
|
||||||
|
/* This is the number of objects that survived the last full
|
||||||
|
collection. It approximates the number of long lived objects
|
||||||
|
tracked by the GC.
|
||||||
|
|
||||||
|
(by "full collection", we mean a collection of the oldest
|
||||||
|
generation). */
|
||||||
|
Py_ssize_t long_lived_total;
|
||||||
|
/* This is the number of objects that survived all "non-full"
|
||||||
|
collections, and are awaiting to undergo a full collection for
|
||||||
|
the first time. */
|
||||||
|
Py_ssize_t long_lived_pending;
|
||||||
|
|
||||||
|
/* True if gc.freeze() has been used. */
|
||||||
|
int freeze_active;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef Py_GIL_DISABLED
|
||||||
|
struct _gc_thread_state {
|
||||||
|
/* Thread-local allocation count. */
|
||||||
|
Py_ssize_t alloc_count;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "pycore_gil.h"
|
||||||
|
|
||||||
|
/****** Thread state **************/
|
||||||
|
#include "pytypedefs.h"
|
||||||
|
#include "pystate.h"
|
||||||
|
#include "pycore_tstate.h"
|
||||||
|
|
||||||
|
|
||||||
|
/**** Import ********/
|
||||||
|
|
||||||
|
struct _import_runtime_state {
|
||||||
|
/* The builtin modules (defined in config.c). */
|
||||||
|
struct _inittab *inittab;
|
||||||
|
/* The most recent value assigned to a PyModuleDef.m_base.m_index.
|
||||||
|
This is incremented each time PyModuleDef_Init() is called,
|
||||||
|
which is just about every time an extension module is imported.
|
||||||
|
See PyInterpreterState.modules_by_index for more info. */
|
||||||
|
Py_ssize_t last_module_index;
|
||||||
|
struct {
|
||||||
|
/* A lock to guard the cache. */
|
||||||
|
PyMutex mutex;
|
||||||
|
/* The actual cache of (filename, name, PyModuleDef) for modules.
|
||||||
|
Only legacy (single-phase init) extension modules are added
|
||||||
|
and only if they support multiple initialization (m_size >= 0)
|
||||||
|
or are imported in the main interpreter.
|
||||||
|
This is initialized lazily in fix_up_extension() in import.c.
|
||||||
|
Modules are added there and looked up in _imp.find_extension(). */
|
||||||
|
struct _Py_hashtable_t *hashtable;
|
||||||
|
} extensions;
|
||||||
|
/* Package context -- the full module name for package imports */
|
||||||
|
const char * pkgcontext;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _import_state {
|
||||||
|
/* cached sys.modules dictionary */
|
||||||
|
PyObject *modules;
|
||||||
|
/* This is the list of module objects for all legacy (single-phase init)
|
||||||
|
extension modules ever loaded in this process (i.e. imported
|
||||||
|
in this interpreter or in any other). Py_None stands in for
|
||||||
|
modules that haven't actually been imported in this interpreter.
|
||||||
|
|
||||||
|
A module's index (PyModuleDef.m_base.m_index) is used to look up
|
||||||
|
the corresponding module object for this interpreter, if any.
|
||||||
|
(See PyState_FindModule().) When any extension module
|
||||||
|
is initialized during import, its moduledef gets initialized by
|
||||||
|
PyModuleDef_Init(), and the first time that happens for each
|
||||||
|
PyModuleDef, its index gets set to the current value of
|
||||||
|
a global counter (see _PyRuntimeState.imports.last_module_index).
|
||||||
|
The entry for that index in this interpreter remains unset until
|
||||||
|
the module is actually imported here. (Py_None is used as
|
||||||
|
a placeholder.) Note that multi-phase init modules always get
|
||||||
|
an index for which there will never be a module set.
|
||||||
|
|
||||||
|
This is initialized lazily in PyState_AddModule(), which is also
|
||||||
|
where modules get added. */
|
||||||
|
PyObject *modules_by_index;
|
||||||
|
/* importlib module._bootstrap */
|
||||||
|
PyObject *importlib;
|
||||||
|
/* override for config->use_frozen_modules (for tests)
|
||||||
|
(-1: "off", 1: "on", 0: no override) */
|
||||||
|
int override_frozen_modules;
|
||||||
|
int override_multi_interp_extensions_check;
|
||||||
|
#ifdef HAVE_DLOPEN
|
||||||
|
int dlopenflags;
|
||||||
|
#endif
|
||||||
|
PyObject *import_func;
|
||||||
|
/* The global import lock. */
|
||||||
|
_PyRecursiveMutex lock;
|
||||||
|
/* diagnostic info in PyImport_ImportModuleLevelObject() */
|
||||||
|
struct {
|
||||||
|
int import_level;
|
||||||
|
PyTime_t accumulated;
|
||||||
|
int header;
|
||||||
|
} find_and_load;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/********** Interpreter state **************/
|
||||||
|
|
||||||
|
#include "pycore_object_state.h"
|
||||||
|
#include "pycore_crossinterp.h"
|
||||||
|
|
||||||
|
|
||||||
|
struct _Py_long_state {
|
||||||
|
int max_str_digits;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct codecs_state {
|
||||||
|
// A list of callable objects used to search for codecs.
|
||||||
|
PyObject *search_path;
|
||||||
|
|
||||||
|
// A dict mapping codec names to codecs returned from a callable in
|
||||||
|
// search_path.
|
||||||
|
PyObject *search_cache;
|
||||||
|
|
||||||
|
// A dict mapping error handling strategies to functions to implement them.
|
||||||
|
PyObject *error_registry;
|
||||||
|
|
||||||
|
#ifdef Py_GIL_DISABLED
|
||||||
|
// Used to safely delete a specific item from search_path.
|
||||||
|
PyMutex search_path_mutex;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Whether or not the rest of the state is initialized.
|
||||||
|
int initialized;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Support for stop-the-world events. This exists in both the PyRuntime struct
|
||||||
|
// for global pauses and in each PyInterpreterState for per-interpreter pauses.
|
||||||
|
struct _stoptheworld_state {
|
||||||
|
PyMutex mutex; // Serializes stop-the-world attempts.
|
||||||
|
|
||||||
|
// NOTE: The below fields are protected by HEAD_LOCK(runtime), not by the
|
||||||
|
// above mutex.
|
||||||
|
bool requested; // Set when a pause is requested.
|
||||||
|
bool world_stopped; // Set when the world is stopped.
|
||||||
|
bool is_global; // Set when contained in PyRuntime struct.
|
||||||
|
|
||||||
|
PyEvent stop_event; // Set when thread_countdown reaches zero.
|
||||||
|
Py_ssize_t thread_countdown; // Number of threads that must pause.
|
||||||
|
|
||||||
|
PyThreadState *requester; // Thread that requested the pause (may be NULL).
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Tracks some rare events per-interpreter, used by the optimizer to turn on/off
|
||||||
|
specific optimizations. */
|
||||||
|
typedef struct _rare_events {
|
||||||
|
/* Setting an object's class, obj.__class__ = ... */
|
||||||
|
uint8_t set_class;
|
||||||
|
/* Setting the bases of a class, cls.__bases__ = ... */
|
||||||
|
uint8_t set_bases;
|
||||||
|
/* Setting the PEP 523 frame eval function, _PyInterpreterState_SetFrameEvalFunc() */
|
||||||
|
uint8_t set_eval_frame_func;
|
||||||
|
/* Modifying the builtins, __builtins__.__dict__[var] = ... */
|
||||||
|
uint8_t builtin_dict;
|
||||||
|
/* Modifying a function, e.g. func.__defaults__ = ..., etc. */
|
||||||
|
uint8_t func_modification;
|
||||||
|
} _rare_events;
|
||||||
|
|
||||||
|
struct
|
||||||
|
Bigint {
|
||||||
|
struct Bigint *next;
|
||||||
|
int k, maxwds, sign, wds;
|
||||||
|
uint32_t x[1];
|
||||||
|
};
|
||||||
|
|
||||||
|
#if defined(Py_USING_MEMORY_DEBUGGER) || _PY_SHORT_FLOAT_REPR == 0
|
||||||
|
|
||||||
|
struct _dtoa_state {
|
||||||
|
int _not_used;
|
||||||
|
};
|
||||||
|
|
||||||
|
#else // !Py_USING_MEMORY_DEBUGGER && _PY_SHORT_FLOAT_REPR != 0
|
||||||
|
|
||||||
|
/* The size of the Bigint freelist */
|
||||||
|
#define Bigint_Kmax 7
|
||||||
|
|
||||||
|
/* The size of the cached powers of 5 array */
|
||||||
|
#define Bigint_Pow5size 8
|
||||||
|
|
||||||
|
#ifndef PRIVATE_MEM
|
||||||
|
#define PRIVATE_MEM 2304
|
||||||
|
#endif
|
||||||
|
#define Bigint_PREALLOC_SIZE \
|
||||||
|
((PRIVATE_MEM+sizeof(double)-1)/sizeof(double))
|
||||||
|
|
||||||
|
struct _dtoa_state {
|
||||||
|
// p5s is an array of powers of 5 of the form:
|
||||||
|
// 5**(2**(i+2)) for 0 <= i < Bigint_Pow5size
|
||||||
|
struct Bigint *p5s[Bigint_Pow5size];
|
||||||
|
// XXX This should be freed during runtime fini.
|
||||||
|
struct Bigint *freelist[Bigint_Kmax+1];
|
||||||
|
double preallocated[Bigint_PREALLOC_SIZE];
|
||||||
|
double *preallocated_next;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // !Py_USING_MEMORY_DEBUGGER
|
||||||
|
|
||||||
|
struct _py_code_state {
|
||||||
|
PyMutex mutex;
|
||||||
|
// Interned constants from code objects. Used by the free-threaded build.
|
||||||
|
struct _Py_hashtable_t *constants;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define FUNC_VERSION_CACHE_SIZE (1<<12) /* Must be a power of 2 */
|
||||||
|
|
||||||
|
struct _func_version_cache_item {
|
||||||
|
PyFunctionObject *func;
|
||||||
|
PyObject *code;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _py_func_state {
|
||||||
|
#ifdef Py_GIL_DISABLED
|
||||||
|
// Protects next_version
|
||||||
|
PyMutex mutex;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uint32_t next_version;
|
||||||
|
// Borrowed references to function and code objects whose
|
||||||
|
// func_version % FUNC_VERSION_CACHE_SIZE
|
||||||
|
// once was equal to the index in the table.
|
||||||
|
// They are cleared when the function or code object is deallocated.
|
||||||
|
struct _func_version_cache_item func_version_cache[FUNC_VERSION_CACHE_SIZE];
|
||||||
|
};
|
||||||
|
|
||||||
|
#include "pycore_dict_state.h"
|
||||||
|
#include "pycore_exceptions.h"
|
||||||
|
|
||||||
|
|
||||||
|
/****** type state *********/
|
||||||
|
|
||||||
|
/* For now we hard-code this to a value for which we are confident
|
||||||
|
all the static builtin types will fit (for all builds). */
|
||||||
|
#define _Py_MAX_MANAGED_STATIC_BUILTIN_TYPES 200
|
||||||
|
#define _Py_MAX_MANAGED_STATIC_EXT_TYPES 10
|
||||||
|
#define _Py_MAX_MANAGED_STATIC_TYPES \
|
||||||
|
(_Py_MAX_MANAGED_STATIC_BUILTIN_TYPES + _Py_MAX_MANAGED_STATIC_EXT_TYPES)
|
||||||
|
|
||||||
|
struct _types_runtime_state {
|
||||||
|
/* Used to set PyTypeObject.tp_version_tag for core static types. */
|
||||||
|
// bpo-42745: next_version_tag remains shared by all interpreters
|
||||||
|
// because of static types.
|
||||||
|
unsigned int next_version_tag;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
struct {
|
||||||
|
PyTypeObject *type;
|
||||||
|
int64_t interp_count;
|
||||||
|
} types[_Py_MAX_MANAGED_STATIC_TYPES];
|
||||||
|
} managed_static;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Type attribute lookup cache: speed up attribute and method lookups,
|
||||||
|
// see _PyType_Lookup().
|
||||||
|
struct type_cache_entry {
|
||||||
|
unsigned int version; // initialized from type->tp_version_tag
|
||||||
|
#ifdef Py_GIL_DISABLED
|
||||||
|
_PySeqLock sequence;
|
||||||
|
#endif
|
||||||
|
PyObject *name; // reference to exactly a str or None
|
||||||
|
PyObject *value; // borrowed reference or NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
#define MCACHE_SIZE_EXP 12
|
||||||
|
|
||||||
|
struct type_cache {
|
||||||
|
struct type_cache_entry hashtable[1 << MCACHE_SIZE_EXP];
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
PyTypeObject *type;
|
||||||
|
int isbuiltin;
|
||||||
|
int readying;
|
||||||
|
int ready;
|
||||||
|
// XXX tp_dict can probably be statically allocated,
|
||||||
|
// instead of dynamically and stored on the interpreter.
|
||||||
|
PyObject *tp_dict;
|
||||||
|
PyObject *tp_subclasses;
|
||||||
|
/* We never clean up weakrefs for static builtin types since
|
||||||
|
they will effectively never get triggered. However, there
|
||||||
|
are also some diagnostic uses for the list of weakrefs,
|
||||||
|
so we still keep it. */
|
||||||
|
PyObject *tp_weaklist;
|
||||||
|
} managed_static_type_state;
|
||||||
|
|
||||||
|
#define TYPE_VERSION_CACHE_SIZE (1<<12) /* Must be a power of 2 */
|
||||||
|
|
||||||
|
struct types_state {
|
||||||
|
/* Used to set PyTypeObject.tp_version_tag.
|
||||||
|
It starts at _Py_MAX_GLOBAL_TYPE_VERSION_TAG + 1,
|
||||||
|
where all those lower numbers are used for core static types. */
|
||||||
|
unsigned int next_version_tag;
|
||||||
|
|
||||||
|
struct type_cache type_cache;
|
||||||
|
|
||||||
|
/* Every static builtin type is initialized for each interpreter
|
||||||
|
during its own initialization, including for the main interpreter
|
||||||
|
during global runtime initialization. This is done by calling
|
||||||
|
_PyStaticType_InitBuiltin().
|
||||||
|
|
||||||
|
The first time a static builtin type is initialized, all the
|
||||||
|
normal PyType_Ready() stuff happens. The only difference from
|
||||||
|
normal is that there are three PyTypeObject fields holding
|
||||||
|
objects which are stored here (on PyInterpreterState) rather
|
||||||
|
than in the corresponding PyTypeObject fields. Those are:
|
||||||
|
tp_dict (cls.__dict__), tp_subclasses (cls.__subclasses__),
|
||||||
|
and tp_weaklist.
|
||||||
|
|
||||||
|
When a subinterpreter is initialized, each static builtin type
|
||||||
|
is still initialized, but only the interpreter-specific portion,
|
||||||
|
namely those three objects.
|
||||||
|
|
||||||
|
Those objects are stored in the PyInterpreterState.types.builtins
|
||||||
|
array, at the index corresponding to each specific static builtin
|
||||||
|
type. That index (a size_t value) is stored in the tp_subclasses
|
||||||
|
field. For static builtin types, we re-purposed the now-unused
|
||||||
|
tp_subclasses to avoid adding another field to PyTypeObject.
|
||||||
|
In all other cases tp_subclasses holds a dict like before.
|
||||||
|
(The field was previously defined as PyObject*, but is now void*
|
||||||
|
to reflect its dual use.)
|
||||||
|
|
||||||
|
The index for each static builtin type isn't statically assigned.
|
||||||
|
Instead it is calculated the first time a type is initialized
|
||||||
|
(by the main interpreter). The index matches the order in which
|
||||||
|
the type was initialized relative to the others. The actual
|
||||||
|
value comes from the current value of num_builtins_initialized,
|
||||||
|
as each type is initialized for the main interpreter.
|
||||||
|
|
||||||
|
num_builtins_initialized is incremented once for each static
|
||||||
|
builtin type. Once initialization is over for a subinterpreter,
|
||||||
|
the value will be the same as for all other interpreters. */
|
||||||
|
struct {
|
||||||
|
size_t num_initialized;
|
||||||
|
managed_static_type_state initialized[_Py_MAX_MANAGED_STATIC_BUILTIN_TYPES];
|
||||||
|
} builtins;
|
||||||
|
/* We apply a similar strategy for managed extension modules. */
|
||||||
|
struct {
|
||||||
|
size_t num_initialized;
|
||||||
|
size_t next_index;
|
||||||
|
managed_static_type_state initialized[_Py_MAX_MANAGED_STATIC_EXT_TYPES];
|
||||||
|
} for_extensions;
|
||||||
|
PyMutex mutex;
|
||||||
|
|
||||||
|
// Borrowed references to type objects whose
|
||||||
|
// tp_version_tag % TYPE_VERSION_CACHE_SIZE
|
||||||
|
// once was equal to the index in the table.
|
||||||
|
// They are cleared when the type object is deallocated.
|
||||||
|
PyTypeObject *type_version_cache[TYPE_VERSION_CACHE_SIZE];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _warnings_runtime_state {
|
||||||
|
/* Both 'filters' and 'onceregistry' can be set in warnings.py;
|
||||||
|
get_warnings_attr() will reset these variables accordingly. */
|
||||||
|
PyObject *filters; /* List */
|
||||||
|
PyObject *once_registry; /* Dict */
|
||||||
|
PyObject *default_action; /* String */
|
||||||
|
_PyRecursiveMutex lock;
|
||||||
|
long filters_version;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _Py_mem_interp_free_queue {
|
||||||
|
int has_work; // true if the queue is not empty
|
||||||
|
PyMutex mutex; // protects the queue
|
||||||
|
struct llist_node head; // queue of _mem_work_chunk items
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/****** Unicode state *********/
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
_Py_ERROR_UNKNOWN=0,
|
||||||
|
_Py_ERROR_STRICT,
|
||||||
|
_Py_ERROR_SURROGATEESCAPE,
|
||||||
|
_Py_ERROR_REPLACE,
|
||||||
|
_Py_ERROR_IGNORE,
|
||||||
|
_Py_ERROR_BACKSLASHREPLACE,
|
||||||
|
_Py_ERROR_SURROGATEPASS,
|
||||||
|
_Py_ERROR_XMLCHARREFREPLACE,
|
||||||
|
_Py_ERROR_OTHER
|
||||||
|
} _Py_error_handler;
|
||||||
|
|
||||||
|
struct _Py_unicode_runtime_ids {
|
||||||
|
PyMutex mutex;
|
||||||
|
// next_index value must be preserved when Py_Initialize()/Py_Finalize()
|
||||||
|
// is called multiple times: see _PyUnicode_FromId() implementation.
|
||||||
|
Py_ssize_t next_index;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _Py_unicode_runtime_state {
|
||||||
|
struct _Py_unicode_runtime_ids ids;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* fs_codec.encoding is initialized to NULL.
|
||||||
|
Later, it is set to a non-NULL string by _PyUnicode_InitEncodings(). */
|
||||||
|
struct _Py_unicode_fs_codec {
|
||||||
|
char *encoding; // Filesystem encoding (encoded to UTF-8)
|
||||||
|
int utf8; // encoding=="utf-8"?
|
||||||
|
char *errors; // Filesystem errors (encoded to UTF-8)
|
||||||
|
_Py_error_handler error_handler;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _Py_unicode_ids {
|
||||||
|
Py_ssize_t size;
|
||||||
|
PyObject **array;
|
||||||
|
};
|
||||||
|
|
||||||
|
#include "pycore_ucnhash.h"
|
||||||
|
|
||||||
|
struct _Py_unicode_state {
|
||||||
|
struct _Py_unicode_fs_codec fs_codec;
|
||||||
|
|
||||||
|
_PyUnicode_Name_CAPI *ucnhash_capi;
|
||||||
|
|
||||||
|
// Unicode identifiers (_Py_Identifier): see _PyUnicode_FromId()
|
||||||
|
struct _Py_unicode_ids ids;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Borrowed references to common callables:
|
||||||
|
struct callable_cache {
|
||||||
|
PyObject *isinstance;
|
||||||
|
PyObject *len;
|
||||||
|
PyObject *list_append;
|
||||||
|
PyObject *object__getattribute__;
|
||||||
|
};
|
||||||
|
|
||||||
|
#include "pycore_obmalloc.h"
|
||||||
|
|
||||||
|
/* Length of array of slotdef pointers used to store slots with the
|
||||||
|
same __name__. There should be at most MAX_EQUIV-1 slotdef entries with
|
||||||
|
the same __name__, for any __name__. Since that's a static property, it is
|
||||||
|
appropriate to declare fixed-size arrays for this. */
|
||||||
|
#define MAX_EQUIV 10
|
||||||
|
|
||||||
|
typedef struct wrapperbase pytype_slotdef;
|
||||||
|
|
||||||
|
|
||||||
|
struct _Py_interp_cached_objects {
|
||||||
|
#ifdef Py_GIL_DISABLED
|
||||||
|
PyMutex interned_mutex;
|
||||||
|
#endif
|
||||||
|
PyObject *interned_strings;
|
||||||
|
|
||||||
|
/* object.__reduce__ */
|
||||||
|
PyObject *objreduce;
|
||||||
|
PyObject *type_slots_pname;
|
||||||
|
pytype_slotdef *type_slots_ptrs[MAX_EQUIV];
|
||||||
|
|
||||||
|
/* TypeVar and related types */
|
||||||
|
PyTypeObject *generic_type;
|
||||||
|
PyTypeObject *typevar_type;
|
||||||
|
PyTypeObject *typevartuple_type;
|
||||||
|
PyTypeObject *paramspec_type;
|
||||||
|
PyTypeObject *paramspecargs_type;
|
||||||
|
PyTypeObject *paramspeckwargs_type;
|
||||||
|
PyTypeObject *constevaluator_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _Py_interp_static_objects {
|
||||||
|
struct {
|
||||||
|
int _not_used;
|
||||||
|
// hamt_empty is here instead of global because of its weakreflist.
|
||||||
|
_PyGC_Head_UNUSED _hamt_empty_gc_not_used;
|
||||||
|
PyHamtObject hamt_empty;
|
||||||
|
PyBaseExceptionObject last_resort_memory_error;
|
||||||
|
} singletons;
|
||||||
|
};
|
||||||
|
|
||||||
|
#include "pycore_instruments.h"
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef Py_GIL_DISABLED
|
||||||
|
|
||||||
|
// A min-heap of indices
|
||||||
|
typedef struct _PyIndexHeap {
|
||||||
|
int32_t *values;
|
||||||
|
|
||||||
|
// Number of items stored in values
|
||||||
|
Py_ssize_t size;
|
||||||
|
|
||||||
|
// Maximum number of items that can be stored in values
|
||||||
|
Py_ssize_t capacity;
|
||||||
|
} _PyIndexHeap;
|
||||||
|
|
||||||
|
// An unbounded pool of indices. Indices are allocated starting from 0. They
|
||||||
|
// may be released back to the pool once they are no longer in use.
|
||||||
|
typedef struct _PyIndexPool {
|
||||||
|
PyMutex mutex;
|
||||||
|
|
||||||
|
// Min heap of indices available for allocation
|
||||||
|
_PyIndexHeap free_indices;
|
||||||
|
|
||||||
|
// Next index to allocate if no free indices are available
|
||||||
|
int32_t next_index;
|
||||||
|
} _PyIndexPool;
|
||||||
|
|
||||||
|
typedef union _Py_unique_id_entry {
|
||||||
|
// Points to the next free type id, when part of the freelist
|
||||||
|
union _Py_unique_id_entry *next;
|
||||||
|
|
||||||
|
// Stores the object when the id is assigned
|
||||||
|
PyObject *obj;
|
||||||
|
} _Py_unique_id_entry;
|
||||||
|
|
||||||
|
struct _Py_unique_id_pool {
|
||||||
|
PyMutex mutex;
|
||||||
|
|
||||||
|
// combined table of object with allocated unique ids and unallocated ids.
|
||||||
|
_Py_unique_id_entry *table;
|
||||||
|
|
||||||
|
// Next entry to allocate inside 'table' or NULL
|
||||||
|
_Py_unique_id_entry *freelist;
|
||||||
|
|
||||||
|
// size of 'table'
|
||||||
|
Py_ssize_t size;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* PyInterpreterState holds the global state for one of the runtime's
|
||||||
|
interpreters. Typically the initial (main) interpreter is the only one.
|
||||||
|
|
||||||
|
The PyInterpreterState typedef is in Include/pytypedefs.h.
|
||||||
|
*/
|
||||||
|
struct _is {
|
||||||
|
|
||||||
|
/* This struct contains the eval_breaker,
|
||||||
|
* which is by far the hottest field in this struct
|
||||||
|
* and should be placed at the beginning. */
|
||||||
|
struct _ceval_state ceval;
|
||||||
|
|
||||||
|
PyInterpreterState *next;
|
||||||
|
|
||||||
|
int64_t id;
|
||||||
|
Py_ssize_t id_refcount;
|
||||||
|
int requires_idref;
|
||||||
|
|
||||||
|
long _whence;
|
||||||
|
|
||||||
|
/* Has been initialized to a safe state.
|
||||||
|
|
||||||
|
In order to be effective, this must be set to 0 during or right
|
||||||
|
after allocation. */
|
||||||
|
int _initialized;
|
||||||
|
/* Has been fully initialized via pylifecycle.c. */
|
||||||
|
int _ready;
|
||||||
|
int finalizing;
|
||||||
|
|
||||||
|
uintptr_t last_restart_version;
|
||||||
|
struct pythreads {
|
||||||
|
uint64_t next_unique_id;
|
||||||
|
/* The linked list of threads, newest first. */
|
||||||
|
PyThreadState *head;
|
||||||
|
_PyThreadStateImpl *preallocated;
|
||||||
|
/* The thread currently executing in the __main__ module, if any. */
|
||||||
|
PyThreadState *main;
|
||||||
|
/* Used in Modules/_threadmodule.c. */
|
||||||
|
Py_ssize_t count;
|
||||||
|
/* Support for runtime thread stack size tuning.
|
||||||
|
A value of 0 means using the platform's default stack size
|
||||||
|
or the size specified by the THREAD_STACK_SIZE macro. */
|
||||||
|
/* Used in Python/thread.c. */
|
||||||
|
size_t stacksize;
|
||||||
|
} threads;
|
||||||
|
|
||||||
|
/* Reference to the _PyRuntime global variable. This field exists
|
||||||
|
to not have to pass runtime in addition to tstate to a function.
|
||||||
|
Get runtime from tstate: tstate->interp->runtime. */
|
||||||
|
struct pyruntimestate *runtime;
|
||||||
|
|
||||||
|
/* Set by Py_EndInterpreter().
|
||||||
|
|
||||||
|
Use _PyInterpreterState_GetFinalizing()
|
||||||
|
and _PyInterpreterState_SetFinalizing()
|
||||||
|
to access it, don't access it directly. */
|
||||||
|
PyThreadState* _finalizing;
|
||||||
|
/* The ID of the OS thread in which we are finalizing. */
|
||||||
|
unsigned long _finalizing_id;
|
||||||
|
|
||||||
|
struct _gc_runtime_state gc;
|
||||||
|
|
||||||
|
/* The following fields are here to avoid allocation during init.
|
||||||
|
The data is exposed through PyInterpreterState pointer fields.
|
||||||
|
These fields should not be accessed directly outside of init.
|
||||||
|
|
||||||
|
All other PyInterpreterState pointer fields are populated when
|
||||||
|
needed and default to NULL.
|
||||||
|
|
||||||
|
For now there are some exceptions to that rule, which require
|
||||||
|
allocation during init. These will be addressed on a case-by-case
|
||||||
|
basis. Also see _PyRuntimeState regarding the various mutex fields.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Dictionary of the sys module
|
||||||
|
PyObject *sysdict;
|
||||||
|
|
||||||
|
// Dictionary of the builtins module
|
||||||
|
PyObject *builtins;
|
||||||
|
|
||||||
|
struct _import_state imports;
|
||||||
|
|
||||||
|
/* The per-interpreter GIL, which might not be used. */
|
||||||
|
struct _gil_runtime_state _gil;
|
||||||
|
|
||||||
|
/* ---------- IMPORTANT ---------------------------
|
||||||
|
The fields above this line are declared as early as
|
||||||
|
possible to facilitate out-of-process observability
|
||||||
|
tools. */
|
||||||
|
|
||||||
|
struct codecs_state codecs;
|
||||||
|
|
||||||
|
PyConfig config;
|
||||||
|
unsigned long feature_flags;
|
||||||
|
|
||||||
|
PyObject *dict; /* Stores per-interpreter state */
|
||||||
|
|
||||||
|
PyObject *sysdict_copy;
|
||||||
|
PyObject *builtins_copy;
|
||||||
|
// Initialized to _PyEval_EvalFrameDefault().
|
||||||
|
_PyFrameEvalFunction eval_frame;
|
||||||
|
|
||||||
|
PyFunction_WatchCallback func_watchers[FUNC_MAX_WATCHERS];
|
||||||
|
// One bit is set for each non-NULL entry in func_watchers
|
||||||
|
uint8_t active_func_watchers;
|
||||||
|
|
||||||
|
Py_ssize_t co_extra_user_count;
|
||||||
|
freefunc co_extra_freefuncs[MAX_CO_EXTRA_USERS];
|
||||||
|
|
||||||
|
/* cross-interpreter data and utils */
|
||||||
|
_PyXI_state_t xi;
|
||||||
|
|
||||||
|
#ifdef HAVE_FORK
|
||||||
|
PyObject *before_forkers;
|
||||||
|
PyObject *after_forkers_parent;
|
||||||
|
PyObject *after_forkers_child;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct _warnings_runtime_state warnings;
|
||||||
|
struct atexit_state atexit;
|
||||||
|
struct _stoptheworld_state stoptheworld;
|
||||||
|
struct _qsbr_shared qsbr;
|
||||||
|
|
||||||
|
#if defined(Py_GIL_DISABLED)
|
||||||
|
struct _mimalloc_interp_state mimalloc;
|
||||||
|
struct _brc_state brc; // biased reference counting state
|
||||||
|
struct _Py_unique_id_pool unique_ids; // object ids for per-thread refcounts
|
||||||
|
PyMutex weakref_locks[NUM_WEAKREF_LIST_LOCKS];
|
||||||
|
_PyIndexPool tlbc_indices;
|
||||||
|
#endif
|
||||||
|
// Per-interpreter list of tasks, any lingering tasks from thread
|
||||||
|
// states gets added here and removed from the corresponding
|
||||||
|
// thread state's list.
|
||||||
|
struct llist_node asyncio_tasks_head;
|
||||||
|
// `asyncio_tasks_lock` is used when tasks are moved
|
||||||
|
// from thread's list to interpreter's list.
|
||||||
|
PyMutex asyncio_tasks_lock;
|
||||||
|
|
||||||
|
// Per-interpreter state for the obmalloc allocator. For the main
|
||||||
|
// interpreter and for all interpreters that don't have their
|
||||||
|
// own obmalloc state, this points to the static structure in
|
||||||
|
// obmalloc.c obmalloc_state_main. For other interpreters, it is
|
||||||
|
// heap allocated by _PyMem_init_obmalloc() and freed when the
|
||||||
|
// interpreter structure is freed. In the case of a heap allocated
|
||||||
|
// obmalloc state, it is not safe to hold on to or use memory after
|
||||||
|
// the interpreter is freed. The obmalloc state corresponding to
|
||||||
|
// that allocated memory is gone. See free_obmalloc_arenas() for
|
||||||
|
// more comments.
|
||||||
|
struct _obmalloc_state *obmalloc;
|
||||||
|
|
||||||
|
PyObject *audit_hooks;
|
||||||
|
PyType_WatchCallback type_watchers[TYPE_MAX_WATCHERS];
|
||||||
|
PyCode_WatchCallback code_watchers[CODE_MAX_WATCHERS];
|
||||||
|
PyContext_WatchCallback context_watchers[CONTEXT_MAX_WATCHERS];
|
||||||
|
// One bit is set for each non-NULL entry in code_watchers
|
||||||
|
uint8_t active_code_watchers;
|
||||||
|
uint8_t active_context_watchers;
|
||||||
|
|
||||||
|
struct _py_object_state object_state;
|
||||||
|
struct _Py_unicode_state unicode;
|
||||||
|
struct _Py_long_state long_state;
|
||||||
|
struct _dtoa_state dtoa;
|
||||||
|
struct _py_func_state func_state;
|
||||||
|
struct _py_code_state code_state;
|
||||||
|
|
||||||
|
struct _Py_dict_state dict_state;
|
||||||
|
struct _Py_exc_state exc_state;
|
||||||
|
struct _Py_mem_interp_free_queue mem_free_queue;
|
||||||
|
|
||||||
|
struct ast_state ast;
|
||||||
|
struct types_state types;
|
||||||
|
struct callable_cache callable_cache;
|
||||||
|
bool jit;
|
||||||
|
struct _PyExecutorObject *executor_list_head;
|
||||||
|
size_t trace_run_counter;
|
||||||
|
_rare_events rare_events;
|
||||||
|
PyDict_WatchCallback builtins_dict_watcher;
|
||||||
|
|
||||||
|
_Py_GlobalMonitors monitors;
|
||||||
|
bool sys_profile_initialized;
|
||||||
|
bool sys_trace_initialized;
|
||||||
|
Py_ssize_t sys_profiling_threads; /* Count of threads with c_profilefunc set */
|
||||||
|
Py_ssize_t sys_tracing_threads; /* Count of threads with c_tracefunc set */
|
||||||
|
PyObject *monitoring_callables[PY_MONITORING_TOOL_IDS][_PY_MONITORING_EVENTS];
|
||||||
|
PyObject *monitoring_tool_names[PY_MONITORING_TOOL_IDS];
|
||||||
|
uintptr_t monitoring_tool_versions[PY_MONITORING_TOOL_IDS];
|
||||||
|
|
||||||
|
struct _Py_interp_cached_objects cached_objects;
|
||||||
|
struct _Py_interp_static_objects static_objects;
|
||||||
|
|
||||||
|
Py_ssize_t _interactive_src_count;
|
||||||
|
|
||||||
|
/* the initial PyInterpreterState.threads.head */
|
||||||
|
_PyThreadStateImpl _initial_thread;
|
||||||
|
// _initial_thread should be the last field of PyInterpreterState.
|
||||||
|
// See https://github.com/python/cpython/issues/127117.
|
||||||
|
|
||||||
|
#if !defined(Py_GIL_DISABLED) && defined(Py_STACKREF_DEBUG)
|
||||||
|
uint64_t next_stackref;
|
||||||
|
_Py_hashtable_t *open_stackrefs_table;
|
||||||
|
# ifdef Py_STACKREF_CLOSE_DEBUG
|
||||||
|
_Py_hashtable_t *closed_stackrefs_table;
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif /* Py_INTERNAL_INTERP_STRUCTS_H */
|
|
@ -9,7 +9,8 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "pycore_bytesobject.h" // _PyBytesWriter
|
#include "pycore_bytesobject.h" // _PyBytesWriter
|
||||||
#include "pycore_global_objects.h"// _PY_NSMALLNEGINTS
|
#include "pycore_runtime_structs.h"// _PY_NSMALLNEGINTS
|
||||||
|
#include "pycore_global_objects.h"// _PY_SINGLETON
|
||||||
#include "pycore_runtime.h" // _PyRuntime
|
#include "pycore_runtime.h" // _PyRuntime
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -13,23 +13,6 @@ extern "C" {
|
||||||
#include "pycore_global_strings.h" // _Py_DECLARE_STR()
|
#include "pycore_global_strings.h" // _Py_DECLARE_STR()
|
||||||
#include "pycore_pyarena.h" // PyArena
|
#include "pycore_pyarena.h" // PyArena
|
||||||
|
|
||||||
|
|
||||||
#ifdef Py_DEBUG
|
|
||||||
#define _PYPEGEN_NSTATISTICS 2000
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct _parser_runtime_state {
|
|
||||||
#ifdef Py_DEBUG
|
|
||||||
long memo_statistics[_PYPEGEN_NSTATISTICS];
|
|
||||||
#ifdef Py_GIL_DISABLED
|
|
||||||
PyMutex mutex;
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
int _not_used;
|
|
||||||
#endif
|
|
||||||
struct _expr dummy_name;
|
|
||||||
};
|
|
||||||
|
|
||||||
_Py_DECLARE_STR(empty, "")
|
_Py_DECLARE_STR(empty, "")
|
||||||
#if defined(Py_DEBUG) && defined(Py_GIL_DISABLED)
|
#if defined(Py_DEBUG) && defined(Py_GIL_DISABLED)
|
||||||
#define _parser_runtime_state_INIT \
|
#define _parser_runtime_state_INIT \
|
||||||
|
|
|
@ -71,19 +71,6 @@ extern int _Py_HashSecret_Initialized;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
struct pyhash_runtime_state {
|
|
||||||
struct {
|
|
||||||
#ifndef MS_WINDOWS
|
|
||||||
int fd;
|
|
||||||
dev_t st_dev;
|
|
||||||
ino_t st_ino;
|
|
||||||
#else
|
|
||||||
// This is a placeholder so the struct isn't empty on Windows.
|
|
||||||
int _not_used;
|
|
||||||
#endif
|
|
||||||
} urandom_cache;
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifndef MS_WINDOWS
|
#ifndef MS_WINDOWS
|
||||||
# define _py_urandom_cache_INIT \
|
# define _py_urandom_cache_INIT \
|
||||||
{ \
|
{ \
|
||||||
|
|
|
@ -27,34 +27,6 @@ PyAPI_FUNC(char*) _PyMem_Strdup(const char *str);
|
||||||
// wcsdup() using PyMem_RawMalloc()
|
// wcsdup() using PyMem_RawMalloc()
|
||||||
extern wchar_t* _PyMem_RawWcsdup(const wchar_t *str);
|
extern wchar_t* _PyMem_RawWcsdup(const wchar_t *str);
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
/* We tag each block with an API ID in order to tag API violations */
|
|
||||||
char api_id;
|
|
||||||
PyMemAllocatorEx alloc;
|
|
||||||
} debug_alloc_api_t;
|
|
||||||
|
|
||||||
struct _pymem_allocators {
|
|
||||||
PyMutex mutex;
|
|
||||||
struct {
|
|
||||||
PyMemAllocatorEx raw;
|
|
||||||
PyMemAllocatorEx mem;
|
|
||||||
PyMemAllocatorEx obj;
|
|
||||||
} standard;
|
|
||||||
struct {
|
|
||||||
debug_alloc_api_t raw;
|
|
||||||
debug_alloc_api_t mem;
|
|
||||||
debug_alloc_api_t obj;
|
|
||||||
} debug;
|
|
||||||
int is_debug_enabled;
|
|
||||||
PyObjectArenaAllocator obj_arena;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _Py_mem_interp_free_queue {
|
|
||||||
int has_work; // true if the queue is not empty
|
|
||||||
PyMutex mutex; // protects the queue
|
|
||||||
struct llist_node head; // queue of _mem_work_chunk items
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Special bytes broadcast into debug memory blocks at appropriate times.
|
/* Special bytes broadcast into debug memory blocks at appropriate times.
|
||||||
Strings of these are unlikely to be valid addresses, floats, ints or
|
Strings of these are unlikely to be valid addresses, floats, ints or
|
||||||
7-bit ASCII.
|
7-bit ASCII.
|
||||||
|
|
|
@ -8,8 +8,10 @@ extern "C" {
|
||||||
# error "this header requires Py_BUILD_CORE define"
|
# error "this header requires Py_BUILD_CORE define"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "pycore_runtime.h" // _PyRuntime
|
#include "pycore_runtime_structs.h" // _PyRuntime
|
||||||
#include "pycore_tstate.h" // _PyThreadStateImpl
|
#include "pycore_runtime.h" // _PyRuntimeState_GetFinalizing
|
||||||
|
#include "pycore_tstate.h" // _PyThreadStateImpl
|
||||||
|
#include "pycore_interp.h" // _PyInterpreterState_GetConfig
|
||||||
|
|
||||||
// Values for PyThreadState.state. A thread must be in the "attached" state
|
// Values for PyThreadState.state. A thread must be in the "attached" state
|
||||||
// before calling most Python APIs. If the GIL is enabled, then "attached"
|
// before calling most Python APIs. If the GIL is enabled, then "attached"
|
||||||
|
|
|
@ -8,8 +8,8 @@ extern "C" {
|
||||||
# error "this header requires Py_BUILD_CORE define"
|
# error "this header requires Py_BUILD_CORE define"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "dynamic_annotations.h" // _Py_ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX
|
#include "dynamic_annotations.h" // _Py_ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX
|
||||||
#include "pycore_llist.h" // struct llist_node
|
#include "pycore_llist.h" // struct llist_node
|
||||||
|
|
||||||
// Get _POSIX_THREADS and _POSIX_SEMAPHORES macros if available
|
// Get _POSIX_THREADS and _POSIX_SEMAPHORES macros if available
|
||||||
#if (defined(HAVE_UNISTD_H) && !defined(_POSIX_THREADS) \
|
#if (defined(HAVE_UNISTD_H) && !defined(_POSIX_THREADS) \
|
||||||
|
|
|
@ -8,201 +8,9 @@ extern "C" {
|
||||||
# error "this header requires Py_BUILD_CORE define"
|
# error "this header requires Py_BUILD_CORE define"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "pycore_atexit.h" // struct _atexit_runtime_state
|
#include "pycore_runtime_structs.h"
|
||||||
#include "pycore_audit.h" // _Py_AuditHookEntry
|
|
||||||
#include "pycore_ceval_state.h" // struct _ceval_runtime_state
|
|
||||||
#include "pycore_crossinterp.h" // _PyXI_global_state_t
|
|
||||||
#include "pycore_debug_offsets.h" // _Py_DebugOffsets
|
|
||||||
#include "pycore_faulthandler.h" // struct _faulthandler_runtime_state
|
|
||||||
#include "pycore_floatobject.h" // struct _Py_float_runtime_state
|
|
||||||
#include "pycore_import.h" // struct _import_runtime_state
|
|
||||||
#include "pycore_interp.h" // PyInterpreterState
|
|
||||||
#include "pycore_object_state.h" // struct _py_object_runtime_state
|
|
||||||
#include "pycore_parser.h" // struct _parser_runtime_state
|
|
||||||
#include "pycore_pyhash.h" // struct pyhash_runtime_state
|
|
||||||
#include "pycore_pymem.h" // struct _pymem_allocators
|
|
||||||
#include "pycore_pythread.h" // struct _pythread_runtime_state
|
|
||||||
#include "pycore_signal.h" // struct _signals_runtime_state
|
|
||||||
#include "pycore_time.h" // struct _PyTime_runtime_state
|
|
||||||
#include "pycore_tracemalloc.h" // struct _tracemalloc_runtime_state
|
|
||||||
#include "pycore_typeobject.h" // struct _types_runtime_state
|
|
||||||
#include "pycore_unicodeobject.h" // struct _Py_unicode_runtime_state
|
|
||||||
|
|
||||||
|
/* API */
|
||||||
/* Full Python runtime state */
|
|
||||||
|
|
||||||
/* _PyRuntimeState holds the global state for the CPython runtime.
|
|
||||||
That data is exported by the internal API as a global variable
|
|
||||||
(_PyRuntime, defined near the top of pylifecycle.c).
|
|
||||||
*/
|
|
||||||
typedef struct pyruntimestate {
|
|
||||||
/* This field must be first to facilitate locating it by out of process
|
|
||||||
* debuggers. Out of process debuggers will use the offsets contained in this
|
|
||||||
* field to be able to locate other fields in several interpreter structures
|
|
||||||
* in a way that doesn't require them to know the exact layout of those
|
|
||||||
* structures.
|
|
||||||
*
|
|
||||||
* IMPORTANT:
|
|
||||||
* This struct is **NOT** backwards compatible between minor version of the
|
|
||||||
* interpreter and the members, order of members and size can change between
|
|
||||||
* minor versions. This struct is only guaranteed to be stable between patch
|
|
||||||
* versions for a given minor version of the interpreter.
|
|
||||||
*/
|
|
||||||
_Py_DebugOffsets debug_offsets;
|
|
||||||
|
|
||||||
/* Has been initialized to a safe state.
|
|
||||||
|
|
||||||
In order to be effective, this must be set to 0 during or right
|
|
||||||
after allocation. */
|
|
||||||
int _initialized;
|
|
||||||
|
|
||||||
/* Is running Py_PreInitialize()? */
|
|
||||||
int preinitializing;
|
|
||||||
|
|
||||||
/* Is Python preinitialized? Set to 1 by Py_PreInitialize() */
|
|
||||||
int preinitialized;
|
|
||||||
|
|
||||||
/* Is Python core initialized? Set to 1 by _Py_InitializeCore() */
|
|
||||||
int core_initialized;
|
|
||||||
|
|
||||||
/* Is Python fully initialized? Set to 1 by Py_Initialize() */
|
|
||||||
int initialized;
|
|
||||||
|
|
||||||
/* Set by Py_FinalizeEx(). Only reset to NULL if Py_Initialize()
|
|
||||||
is called again.
|
|
||||||
|
|
||||||
Use _PyRuntimeState_GetFinalizing() and _PyRuntimeState_SetFinalizing()
|
|
||||||
to access it, don't access it directly. */
|
|
||||||
PyThreadState *_finalizing;
|
|
||||||
/* The ID of the OS thread in which we are finalizing. */
|
|
||||||
unsigned long _finalizing_id;
|
|
||||||
|
|
||||||
struct pyinterpreters {
|
|
||||||
PyMutex mutex;
|
|
||||||
/* The linked list of interpreters, newest first. */
|
|
||||||
PyInterpreterState *head;
|
|
||||||
/* The runtime's initial interpreter, which has a special role
|
|
||||||
in the operation of the runtime. It is also often the only
|
|
||||||
interpreter. */
|
|
||||||
PyInterpreterState *main;
|
|
||||||
/* next_id is an auto-numbered sequence of small
|
|
||||||
integers. It gets initialized in _PyInterpreterState_Enable(),
|
|
||||||
which is called in Py_Initialize(), and used in
|
|
||||||
PyInterpreterState_New(). A negative interpreter ID
|
|
||||||
indicates an error occurred. The main interpreter will
|
|
||||||
always have an ID of 0. Overflow results in a RuntimeError.
|
|
||||||
If that becomes a problem later then we can adjust, e.g. by
|
|
||||||
using a Python int. */
|
|
||||||
int64_t next_id;
|
|
||||||
} interpreters;
|
|
||||||
|
|
||||||
/* Platform-specific identifier and PyThreadState, respectively, for the
|
|
||||||
main thread in the main interpreter. */
|
|
||||||
unsigned long main_thread;
|
|
||||||
PyThreadState *main_tstate;
|
|
||||||
|
|
||||||
/* ---------- IMPORTANT ---------------------------
|
|
||||||
The fields above this line are declared as early as
|
|
||||||
possible to facilitate out-of-process observability
|
|
||||||
tools. */
|
|
||||||
|
|
||||||
/* cross-interpreter data and utils */
|
|
||||||
_PyXI_global_state_t xi;
|
|
||||||
|
|
||||||
struct _pymem_allocators allocators;
|
|
||||||
struct _obmalloc_global_state obmalloc;
|
|
||||||
struct pyhash_runtime_state pyhash_state;
|
|
||||||
struct _pythread_runtime_state threads;
|
|
||||||
struct _signals_runtime_state signals;
|
|
||||||
|
|
||||||
/* Used for the thread state bound to the current thread. */
|
|
||||||
Py_tss_t autoTSSkey;
|
|
||||||
|
|
||||||
/* Used instead of PyThreadState.trash when there is not current tstate. */
|
|
||||||
Py_tss_t trashTSSkey;
|
|
||||||
|
|
||||||
PyWideStringList orig_argv;
|
|
||||||
|
|
||||||
struct _parser_runtime_state parser;
|
|
||||||
|
|
||||||
struct _atexit_runtime_state atexit;
|
|
||||||
|
|
||||||
struct _import_runtime_state imports;
|
|
||||||
struct _ceval_runtime_state ceval;
|
|
||||||
struct _gilstate_runtime_state {
|
|
||||||
/* bpo-26558: Flag to disable PyGILState_Check().
|
|
||||||
If set to non-zero, PyGILState_Check() always return 1. */
|
|
||||||
int check_enabled;
|
|
||||||
/* The single PyInterpreterState used by this process'
|
|
||||||
GILState implementation
|
|
||||||
*/
|
|
||||||
/* TODO: Given interp_main, it may be possible to kill this ref */
|
|
||||||
PyInterpreterState *autoInterpreterState;
|
|
||||||
} gilstate;
|
|
||||||
struct _getargs_runtime_state {
|
|
||||||
struct _PyArg_Parser *static_parsers;
|
|
||||||
} getargs;
|
|
||||||
struct _fileutils_state fileutils;
|
|
||||||
struct _faulthandler_runtime_state faulthandler;
|
|
||||||
struct _tracemalloc_runtime_state tracemalloc;
|
|
||||||
struct _reftracer_runtime_state ref_tracer;
|
|
||||||
|
|
||||||
// The rwmutex is used to prevent overlapping global and per-interpreter
|
|
||||||
// stop-the-world events. Global stop-the-world events lock the mutex
|
|
||||||
// exclusively (as a "writer"), while per-interpreter stop-the-world events
|
|
||||||
// lock it non-exclusively (as "readers").
|
|
||||||
_PyRWMutex stoptheworld_mutex;
|
|
||||||
struct _stoptheworld_state stoptheworld;
|
|
||||||
|
|
||||||
PyPreConfig preconfig;
|
|
||||||
|
|
||||||
// Audit values must be preserved when Py_Initialize()/Py_Finalize()
|
|
||||||
// is called multiple times.
|
|
||||||
Py_OpenCodeHookFunction open_code_hook;
|
|
||||||
void *open_code_userdata;
|
|
||||||
struct {
|
|
||||||
PyMutex mutex;
|
|
||||||
_Py_AuditHookEntry *head;
|
|
||||||
} audit_hooks;
|
|
||||||
|
|
||||||
struct _py_object_runtime_state object_state;
|
|
||||||
struct _Py_float_runtime_state float_state;
|
|
||||||
struct _Py_unicode_runtime_state unicode_state;
|
|
||||||
struct _types_runtime_state types;
|
|
||||||
struct _Py_time_runtime_state time;
|
|
||||||
|
|
||||||
#if defined(__EMSCRIPTEN__) && defined(PY_CALL_TRAMPOLINE)
|
|
||||||
// Used in "Python/emscripten_trampoline.c" to choose between type
|
|
||||||
// reflection trampoline and EM_JS trampoline.
|
|
||||||
int (*emscripten_count_args_function)(PyCFunctionWithKeywords func);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* All the objects that are shared by the runtime's interpreters. */
|
|
||||||
struct _Py_cached_objects cached_objects;
|
|
||||||
struct _Py_static_objects static_objects;
|
|
||||||
|
|
||||||
/* The following fields are here to avoid allocation during init.
|
|
||||||
The data is exposed through _PyRuntimeState pointer fields.
|
|
||||||
These fields should not be accessed directly outside of init.
|
|
||||||
|
|
||||||
All other _PyRuntimeState pointer fields are populated when
|
|
||||||
needed and default to NULL.
|
|
||||||
|
|
||||||
For now there are some exceptions to that rule, which require
|
|
||||||
allocation during init. These will be addressed on a case-by-case
|
|
||||||
basis. Most notably, we don't pre-allocated the several mutex
|
|
||||||
(PyThread_type_lock) fields, because on Windows we only ever get
|
|
||||||
a pointer type.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* _PyRuntimeState.interpreters.main */
|
|
||||||
PyInterpreterState _main_interpreter;
|
|
||||||
// _main_interpreter should be the last field of _PyRuntimeState.
|
|
||||||
// See https://github.com/python/cpython/issues/127117.
|
|
||||||
} _PyRuntimeState;
|
|
||||||
|
|
||||||
|
|
||||||
/* other API */
|
|
||||||
|
|
||||||
// Export _PyRuntime for shared extensions which use it in static inline
|
// Export _PyRuntime for shared extensions which use it in static inline
|
||||||
// functions for best performance, like _Py_IsMainThread() or _Py_ID().
|
// functions for best performance, like _Py_IsMainThread() or _Py_ID().
|
||||||
|
|
|
@ -8,11 +8,13 @@ extern "C" {
|
||||||
# error "this header requires Py_BUILD_CORE define"
|
# error "this header requires Py_BUILD_CORE define"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "pycore_structs.h"
|
||||||
#include "pycore_ceval_state.h" // _PyEval_RUNTIME_PERF_INIT
|
#include "pycore_ceval_state.h" // _PyEval_RUNTIME_PERF_INIT
|
||||||
#include "pycore_debug_offsets.h" // _Py_DebugOffsets_INIT()
|
#include "pycore_debug_offsets.h" // _Py_DebugOffsets_INIT()
|
||||||
#include "pycore_faulthandler.h" // _faulthandler_runtime_state_INIT
|
#include "pycore_faulthandler.h" // _faulthandler_runtime_state_INIT
|
||||||
#include "pycore_floatobject.h" // _py_float_format_unknown
|
#include "pycore_floatobject.h" // _py_float_format_unknown
|
||||||
#include "pycore_function.h"
|
#include "pycore_function.h"
|
||||||
|
#include "pycore_hamt.h" // _PyHamt_BitmapNode_Type
|
||||||
#include "pycore_object.h" // _PyObject_HEAD_INIT
|
#include "pycore_object.h" // _PyObject_HEAD_INIT
|
||||||
#include "pycore_obmalloc_init.h" // _obmalloc_global_state_INIT
|
#include "pycore_obmalloc_init.h" // _obmalloc_global_state_INIT
|
||||||
#include "pycore_parser.h" // _parser_runtime_state_INIT
|
#include "pycore_parser.h" // _parser_runtime_state_INIT
|
||||||
|
|
317
Include/internal/pycore_runtime_structs.h
Normal file
317
Include/internal/pycore_runtime_structs.h
Normal file
|
@ -0,0 +1,317 @@
|
||||||
|
#ifndef Py_INTERNAL_RUNTIME_STRUCTS_H
|
||||||
|
#define Py_INTERNAL_RUNTIME_STRUCTS_H
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* This file contains the struct definitions for the runtime, interpreter
|
||||||
|
* and thread states, plus all smaller structs contained therein */
|
||||||
|
|
||||||
|
#include "pycore_structs.h"
|
||||||
|
#include "pycore_interp_structs.h"
|
||||||
|
|
||||||
|
/************ Runtime state ************/
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
/* We tag each block with an API ID in order to tag API violations */
|
||||||
|
char api_id;
|
||||||
|
PyMemAllocatorEx alloc;
|
||||||
|
} debug_alloc_api_t;
|
||||||
|
|
||||||
|
struct _pymem_allocators {
|
||||||
|
PyMutex mutex;
|
||||||
|
struct {
|
||||||
|
PyMemAllocatorEx raw;
|
||||||
|
PyMemAllocatorEx mem;
|
||||||
|
PyMemAllocatorEx obj;
|
||||||
|
} standard;
|
||||||
|
struct {
|
||||||
|
debug_alloc_api_t raw;
|
||||||
|
debug_alloc_api_t mem;
|
||||||
|
debug_alloc_api_t obj;
|
||||||
|
} debug;
|
||||||
|
int is_debug_enabled;
|
||||||
|
PyObjectArenaAllocator obj_arena;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum _py_float_format_type {
|
||||||
|
_py_float_format_unknown,
|
||||||
|
_py_float_format_ieee_big_endian,
|
||||||
|
_py_float_format_ieee_little_endian,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _Py_float_runtime_state {
|
||||||
|
enum _py_float_format_type float_format;
|
||||||
|
enum _py_float_format_type double_format;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct pyhash_runtime_state {
|
||||||
|
struct {
|
||||||
|
#ifndef MS_WINDOWS
|
||||||
|
int fd;
|
||||||
|
dev_t st_dev;
|
||||||
|
ino_t st_ino;
|
||||||
|
#else
|
||||||
|
// This is a placeholder so the struct isn't empty on Windows.
|
||||||
|
int _not_used;
|
||||||
|
#endif
|
||||||
|
} urandom_cache;
|
||||||
|
};
|
||||||
|
|
||||||
|
#include "pycore_tracemalloc.h"
|
||||||
|
|
||||||
|
struct _fileutils_state {
|
||||||
|
int force_ascii;
|
||||||
|
};
|
||||||
|
|
||||||
|
#include "pycore_debug_offsets.h"
|
||||||
|
#include "pycore_signal.h"
|
||||||
|
#include "pycore_faulthandler.h"
|
||||||
|
#include "pycore_pythread.h"
|
||||||
|
#include "pycore_ast.h"
|
||||||
|
|
||||||
|
#ifdef Py_DEBUG
|
||||||
|
#define _PYPEGEN_NSTATISTICS 2000
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct _parser_runtime_state {
|
||||||
|
#ifdef Py_DEBUG
|
||||||
|
long memo_statistics[_PYPEGEN_NSTATISTICS];
|
||||||
|
#ifdef Py_GIL_DISABLED
|
||||||
|
PyMutex mutex;
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
int _not_used;
|
||||||
|
#endif
|
||||||
|
struct _expr dummy_name;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
PyTime_t numer;
|
||||||
|
PyTime_t denom;
|
||||||
|
} _PyTimeFraction;
|
||||||
|
|
||||||
|
struct _Py_time_runtime_state {
|
||||||
|
#if defined(MS_WINDOWS) || defined(__APPLE__)
|
||||||
|
_PyTimeFraction base;
|
||||||
|
#else
|
||||||
|
char _unused;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct _Py_cached_objects {
|
||||||
|
// XXX We could statically allocate the hashtable.
|
||||||
|
_Py_hashtable_t *interned_strings;
|
||||||
|
};
|
||||||
|
|
||||||
|
// These would be in pycore_long.h if it weren't for an include cycle.
|
||||||
|
#define _PY_NSMALLPOSINTS 257
|
||||||
|
#define _PY_NSMALLNEGINTS 5
|
||||||
|
|
||||||
|
#include "pycore_global_strings.h"
|
||||||
|
|
||||||
|
struct _Py_static_objects {
|
||||||
|
struct {
|
||||||
|
/* Small integers are preallocated in this array so that they
|
||||||
|
* can be shared.
|
||||||
|
* The integers that are preallocated are those in the range
|
||||||
|
* -_PY_NSMALLNEGINTS (inclusive) to _PY_NSMALLPOSINTS (exclusive).
|
||||||
|
*/
|
||||||
|
PyLongObject small_ints[_PY_NSMALLNEGINTS + _PY_NSMALLPOSINTS];
|
||||||
|
|
||||||
|
PyBytesObject bytes_empty;
|
||||||
|
struct {
|
||||||
|
PyBytesObject ob;
|
||||||
|
char eos;
|
||||||
|
} bytes_characters[256];
|
||||||
|
|
||||||
|
struct _Py_global_strings strings;
|
||||||
|
|
||||||
|
_PyGC_Head_UNUSED _tuple_empty_gc_not_used;
|
||||||
|
PyTupleObject tuple_empty;
|
||||||
|
|
||||||
|
_PyGC_Head_UNUSED _hamt_bitmap_node_empty_gc_not_used;
|
||||||
|
PyHamtNode_Bitmap hamt_bitmap_node_empty;
|
||||||
|
_PyContextTokenMissing context_token_missing;
|
||||||
|
} singletons;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Full Python runtime state */
|
||||||
|
|
||||||
|
/* _PyRuntimeState holds the global state for the CPython runtime.
|
||||||
|
That data is exported by the internal API as a global variable
|
||||||
|
(_PyRuntime, defined near the top of pylifecycle.c).
|
||||||
|
*/
|
||||||
|
typedef struct pyruntimestate {
|
||||||
|
/* This field must be first to facilitate locating it by out of process
|
||||||
|
* debuggers. Out of process debuggers will use the offsets contained in this
|
||||||
|
* field to be able to locate other fields in several interpreter structures
|
||||||
|
* in a way that doesn't require them to know the exact layout of those
|
||||||
|
* structures.
|
||||||
|
*
|
||||||
|
* IMPORTANT:
|
||||||
|
* This struct is **NOT** backwards compatible between minor version of the
|
||||||
|
* interpreter and the members, order of members and size can change between
|
||||||
|
* minor versions. This struct is only guaranteed to be stable between patch
|
||||||
|
* versions for a given minor version of the interpreter.
|
||||||
|
*/
|
||||||
|
_Py_DebugOffsets debug_offsets;
|
||||||
|
|
||||||
|
/* Has been initialized to a safe state.
|
||||||
|
|
||||||
|
In order to be effective, this must be set to 0 during or right
|
||||||
|
after allocation. */
|
||||||
|
int _initialized;
|
||||||
|
|
||||||
|
/* Is running Py_PreInitialize()? */
|
||||||
|
int preinitializing;
|
||||||
|
|
||||||
|
/* Is Python preinitialized? Set to 1 by Py_PreInitialize() */
|
||||||
|
int preinitialized;
|
||||||
|
|
||||||
|
/* Is Python core initialized? Set to 1 by _Py_InitializeCore() */
|
||||||
|
int core_initialized;
|
||||||
|
|
||||||
|
/* Is Python fully initialized? Set to 1 by Py_Initialize() */
|
||||||
|
int initialized;
|
||||||
|
|
||||||
|
/* Set by Py_FinalizeEx(). Only reset to NULL if Py_Initialize()
|
||||||
|
is called again.
|
||||||
|
|
||||||
|
Use _PyRuntimeState_GetFinalizing() and _PyRuntimeState_SetFinalizing()
|
||||||
|
to access it, don't access it directly. */
|
||||||
|
PyThreadState *_finalizing;
|
||||||
|
/* The ID of the OS thread in which we are finalizing. */
|
||||||
|
unsigned long _finalizing_id;
|
||||||
|
|
||||||
|
struct pyinterpreters {
|
||||||
|
PyMutex mutex;
|
||||||
|
/* The linked list of interpreters, newest first. */
|
||||||
|
PyInterpreterState *head;
|
||||||
|
/* The runtime's initial interpreter, which has a special role
|
||||||
|
in the operation of the runtime. It is also often the only
|
||||||
|
interpreter. */
|
||||||
|
PyInterpreterState *main;
|
||||||
|
/* next_id is an auto-numbered sequence of small
|
||||||
|
integers. It gets initialized in _PyInterpreterState_Enable(),
|
||||||
|
which is called in Py_Initialize(), and used in
|
||||||
|
PyInterpreterState_New(). A negative interpreter ID
|
||||||
|
indicates an error occurred. The main interpreter will
|
||||||
|
always have an ID of 0. Overflow results in a RuntimeError.
|
||||||
|
If that becomes a problem later then we can adjust, e.g. by
|
||||||
|
using a Python int. */
|
||||||
|
int64_t next_id;
|
||||||
|
} interpreters;
|
||||||
|
|
||||||
|
/* Platform-specific identifier and PyThreadState, respectively, for the
|
||||||
|
main thread in the main interpreter. */
|
||||||
|
unsigned long main_thread;
|
||||||
|
PyThreadState *main_tstate;
|
||||||
|
|
||||||
|
/* ---------- IMPORTANT ---------------------------
|
||||||
|
The fields above this line are declared as early as
|
||||||
|
possible to facilitate out-of-process observability
|
||||||
|
tools. */
|
||||||
|
|
||||||
|
/* cross-interpreter data and utils */
|
||||||
|
_PyXI_global_state_t xi;
|
||||||
|
|
||||||
|
struct _pymem_allocators allocators;
|
||||||
|
struct _obmalloc_global_state obmalloc;
|
||||||
|
struct pyhash_runtime_state pyhash_state;
|
||||||
|
struct _pythread_runtime_state threads;
|
||||||
|
struct _signals_runtime_state signals;
|
||||||
|
|
||||||
|
/* Used for the thread state bound to the current thread. */
|
||||||
|
Py_tss_t autoTSSkey;
|
||||||
|
|
||||||
|
/* Used instead of PyThreadState.trash when there is not current tstate. */
|
||||||
|
Py_tss_t trashTSSkey;
|
||||||
|
|
||||||
|
PyWideStringList orig_argv;
|
||||||
|
|
||||||
|
struct _parser_runtime_state parser;
|
||||||
|
|
||||||
|
struct _atexit_runtime_state atexit;
|
||||||
|
|
||||||
|
struct _import_runtime_state imports;
|
||||||
|
struct _ceval_runtime_state ceval;
|
||||||
|
struct _gilstate_runtime_state {
|
||||||
|
/* bpo-26558: Flag to disable PyGILState_Check().
|
||||||
|
If set to non-zero, PyGILState_Check() always return 1. */
|
||||||
|
int check_enabled;
|
||||||
|
/* The single PyInterpreterState used by this process'
|
||||||
|
GILState implementation
|
||||||
|
*/
|
||||||
|
/* TODO: Given interp_main, it may be possible to kill this ref */
|
||||||
|
PyInterpreterState *autoInterpreterState;
|
||||||
|
} gilstate;
|
||||||
|
struct _getargs_runtime_state {
|
||||||
|
struct _PyArg_Parser *static_parsers;
|
||||||
|
} getargs;
|
||||||
|
struct _fileutils_state fileutils;
|
||||||
|
struct _faulthandler_runtime_state faulthandler;
|
||||||
|
struct _tracemalloc_runtime_state tracemalloc;
|
||||||
|
struct _reftracer_runtime_state ref_tracer;
|
||||||
|
|
||||||
|
// The rwmutex is used to prevent overlapping global and per-interpreter
|
||||||
|
// stop-the-world events. Global stop-the-world events lock the mutex
|
||||||
|
// exclusively (as a "writer"), while per-interpreter stop-the-world events
|
||||||
|
// lock it non-exclusively (as "readers").
|
||||||
|
_PyRWMutex stoptheworld_mutex;
|
||||||
|
struct _stoptheworld_state stoptheworld;
|
||||||
|
|
||||||
|
PyPreConfig preconfig;
|
||||||
|
|
||||||
|
// Audit values must be preserved when Py_Initialize()/Py_Finalize()
|
||||||
|
// is called multiple times.
|
||||||
|
Py_OpenCodeHookFunction open_code_hook;
|
||||||
|
void *open_code_userdata;
|
||||||
|
struct {
|
||||||
|
PyMutex mutex;
|
||||||
|
struct _Py_AuditHookEntry *head;
|
||||||
|
} audit_hooks;
|
||||||
|
|
||||||
|
struct _py_object_runtime_state object_state;
|
||||||
|
struct _Py_float_runtime_state float_state;
|
||||||
|
struct _Py_unicode_runtime_state unicode_state;
|
||||||
|
struct _types_runtime_state types;
|
||||||
|
struct _Py_time_runtime_state time;
|
||||||
|
|
||||||
|
#if defined(__EMSCRIPTEN__) && defined(PY_CALL_TRAMPOLINE)
|
||||||
|
// Used in "Python/emscripten_trampoline.c" to choose between type
|
||||||
|
// reflection trampoline and EM_JS trampoline.
|
||||||
|
int (*emscripten_count_args_function)(PyCFunctionWithKeywords func);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* All the objects that are shared by the runtime's interpreters. */
|
||||||
|
struct _Py_cached_objects cached_objects;
|
||||||
|
struct _Py_static_objects static_objects;
|
||||||
|
|
||||||
|
/* The following fields are here to avoid allocation during init.
|
||||||
|
The data is exposed through _PyRuntimeState pointer fields.
|
||||||
|
These fields should not be accessed directly outside of init.
|
||||||
|
|
||||||
|
All other _PyRuntimeState pointer fields are populated when
|
||||||
|
needed and default to NULL.
|
||||||
|
|
||||||
|
For now there are some exceptions to that rule, which require
|
||||||
|
allocation during init. These will be addressed on a case-by-case
|
||||||
|
basis. Most notably, we don't pre-allocated the several mutex
|
||||||
|
(PyThread_type_lock) fields, because on Windows we only ever get
|
||||||
|
a pointer type.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* _PyRuntimeState.interpreters.main */
|
||||||
|
PyInterpreterState _main_interpreter;
|
||||||
|
// _main_interpreter should be the last field of _PyRuntimeState.
|
||||||
|
// See https://github.com/python/cpython/issues/127117.
|
||||||
|
} _PyRuntimeState;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif /* Py_INTERNAL_RUNTIME_STRUCTS_H */
|
|
@ -4,9 +4,6 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Define this to get precise tracking of stackrefs.
|
|
||||||
// #define Py_STACKREF_DEBUG 1
|
|
||||||
|
|
||||||
// Define this to get precise tracking of closed stackrefs.
|
// Define this to get precise tracking of closed stackrefs.
|
||||||
// This will use unbounded memory, as it can only grow.
|
// This will use unbounded memory, as it can only grow.
|
||||||
// Use this to track double closes in short-lived programs
|
// Use this to track double closes in short-lived programs
|
||||||
|
@ -60,10 +57,6 @@ extern "C" {
|
||||||
|
|
||||||
#if !defined(Py_GIL_DISABLED) && defined(Py_STACKREF_DEBUG)
|
#if !defined(Py_GIL_DISABLED) && defined(Py_STACKREF_DEBUG)
|
||||||
|
|
||||||
typedef union _PyStackRef {
|
|
||||||
uint64_t index;
|
|
||||||
} _PyStackRef;
|
|
||||||
|
|
||||||
#define Py_TAG_BITS 0
|
#define Py_TAG_BITS 0
|
||||||
|
|
||||||
PyAPI_FUNC(PyObject *) _Py_stackref_get_object(_PyStackRef ref);
|
PyAPI_FUNC(PyObject *) _Py_stackref_get_object(_PyStackRef ref);
|
||||||
|
@ -203,10 +196,6 @@ PyStackRef_IsHeapSafe(_PyStackRef ref)
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
typedef union _PyStackRef {
|
|
||||||
uintptr_t bits;
|
|
||||||
} _PyStackRef;
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef Py_GIL_DISABLED
|
#ifdef Py_GIL_DISABLED
|
||||||
|
|
||||||
|
|
74
Include/internal/pycore_structs.h
Normal file
74
Include/internal/pycore_structs.h
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
#ifndef Py_INTERNAL_STRUCTS_H
|
||||||
|
#define Py_INTERNAL_STRUCTS_H
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* This files contains various key structs that are widely used
|
||||||
|
* and do not depend on other headers. */
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint16_t value_and_backoff;
|
||||||
|
} _Py_BackoffCounter;
|
||||||
|
|
||||||
|
/* Each instruction in a code object is a fixed-width value,
|
||||||
|
* currently 2 bytes: 1-byte opcode + 1-byte oparg. The EXTENDED_ARG
|
||||||
|
* opcode allows for larger values but the current limit is 3 uses
|
||||||
|
* of EXTENDED_ARG (see Python/compile.c), for a maximum
|
||||||
|
* 32-bit value. This aligns with the note in Python/compile.c
|
||||||
|
* (compiler_addop_i_line) indicating that the max oparg value is
|
||||||
|
* 2**32 - 1, rather than INT_MAX.
|
||||||
|
*/
|
||||||
|
typedef union {
|
||||||
|
uint16_t cache;
|
||||||
|
struct {
|
||||||
|
uint8_t code;
|
||||||
|
uint8_t arg;
|
||||||
|
} op;
|
||||||
|
_Py_BackoffCounter counter; // First cache entry of specializable op
|
||||||
|
} _Py_CODEUNIT;
|
||||||
|
|
||||||
|
|
||||||
|
/* Abstract tree node. */
|
||||||
|
typedef struct {
|
||||||
|
PyObject_HEAD
|
||||||
|
} PyHamtNode;
|
||||||
|
|
||||||
|
|
||||||
|
/* An HAMT immutable mapping collection. */
|
||||||
|
typedef struct {
|
||||||
|
PyObject_HEAD
|
||||||
|
PyHamtNode *h_root;
|
||||||
|
PyObject *h_weakreflist;
|
||||||
|
Py_ssize_t h_count;
|
||||||
|
} PyHamtObject;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
PyObject_VAR_HEAD
|
||||||
|
uint32_t b_bitmap;
|
||||||
|
PyObject *b_array[1];
|
||||||
|
} PyHamtNode_Bitmap;
|
||||||
|
|
||||||
|
#include "pycore_context.h"
|
||||||
|
|
||||||
|
// Define this to get precise tracking of stackrefs.
|
||||||
|
// #define Py_STACKREF_DEBUG 1
|
||||||
|
|
||||||
|
typedef union _PyStackRef {
|
||||||
|
#if !defined(Py_GIL_DISABLED) && defined(Py_STACKREF_DEBUG)
|
||||||
|
uint64_t index;
|
||||||
|
#else
|
||||||
|
uintptr_t bits;
|
||||||
|
#endif
|
||||||
|
} _PyStackRef;
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif /* Py_INTERNAL_STRUCTS_H */
|
|
@ -57,6 +57,7 @@ extern "C" {
|
||||||
# error "this header requires Py_BUILD_CORE define"
|
# error "this header requires Py_BUILD_CORE define"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "pycore_runtime_structs.h"
|
||||||
|
|
||||||
#ifdef __clang__
|
#ifdef __clang__
|
||||||
struct timeval;
|
struct timeval;
|
||||||
|
@ -307,11 +308,6 @@ PyAPI_FUNC(PyTime_t) _PyDeadline_Get(PyTime_t deadline);
|
||||||
|
|
||||||
// --- _PyTimeFraction -------------------------------------------------------
|
// --- _PyTimeFraction -------------------------------------------------------
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
PyTime_t numer;
|
|
||||||
PyTime_t denom;
|
|
||||||
} _PyTimeFraction;
|
|
||||||
|
|
||||||
// Set a fraction.
|
// Set a fraction.
|
||||||
// Return 0 on success.
|
// Return 0 on success.
|
||||||
// Return -1 if the fraction is invalid.
|
// Return -1 if the fraction is invalid.
|
||||||
|
@ -330,17 +326,6 @@ extern PyTime_t _PyTimeFraction_Mul(
|
||||||
extern double _PyTimeFraction_Resolution(
|
extern double _PyTimeFraction_Resolution(
|
||||||
const _PyTimeFraction *frac);
|
const _PyTimeFraction *frac);
|
||||||
|
|
||||||
|
|
||||||
// --- _Py_time_runtime_state ------------------------------------------------
|
|
||||||
|
|
||||||
struct _Py_time_runtime_state {
|
|
||||||
#if defined(MS_WINDOWS) || defined(__APPLE__)
|
|
||||||
_PyTimeFraction base;
|
|
||||||
#else
|
|
||||||
char _unused;
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
extern PyStatus _PyTime_Init(struct _Py_time_runtime_state *state);
|
extern PyStatus _PyTime_Init(struct _Py_time_runtime_state *state);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
@ -10,6 +10,7 @@ extern "C" {
|
||||||
|
|
||||||
#include "pycore_moduleobject.h" // PyModuleObject
|
#include "pycore_moduleobject.h" // PyModuleObject
|
||||||
#include "pycore_lock.h" // PyMutex
|
#include "pycore_lock.h" // PyMutex
|
||||||
|
#include "pycore_runtime_structs.h" // type state
|
||||||
|
|
||||||
|
|
||||||
/* state */
|
/* state */
|
||||||
|
@ -32,126 +33,6 @@ extern "C" {
|
||||||
#define _Py_TYPE_BASE_VERSION_TAG (2<<16)
|
#define _Py_TYPE_BASE_VERSION_TAG (2<<16)
|
||||||
#define _Py_MAX_GLOBAL_TYPE_VERSION_TAG (_Py_TYPE_BASE_VERSION_TAG - 1)
|
#define _Py_MAX_GLOBAL_TYPE_VERSION_TAG (_Py_TYPE_BASE_VERSION_TAG - 1)
|
||||||
|
|
||||||
/* For now we hard-code this to a value for which we are confident
|
|
||||||
all the static builtin types will fit (for all builds). */
|
|
||||||
#define _Py_MAX_MANAGED_STATIC_BUILTIN_TYPES 200
|
|
||||||
#define _Py_MAX_MANAGED_STATIC_EXT_TYPES 10
|
|
||||||
#define _Py_MAX_MANAGED_STATIC_TYPES \
|
|
||||||
(_Py_MAX_MANAGED_STATIC_BUILTIN_TYPES + _Py_MAX_MANAGED_STATIC_EXT_TYPES)
|
|
||||||
|
|
||||||
struct _types_runtime_state {
|
|
||||||
/* Used to set PyTypeObject.tp_version_tag for core static types. */
|
|
||||||
// bpo-42745: next_version_tag remains shared by all interpreters
|
|
||||||
// because of static types.
|
|
||||||
unsigned int next_version_tag;
|
|
||||||
|
|
||||||
struct {
|
|
||||||
struct {
|
|
||||||
PyTypeObject *type;
|
|
||||||
int64_t interp_count;
|
|
||||||
} types[_Py_MAX_MANAGED_STATIC_TYPES];
|
|
||||||
} managed_static;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// Type attribute lookup cache: speed up attribute and method lookups,
|
|
||||||
// see _PyType_Lookup().
|
|
||||||
struct type_cache_entry {
|
|
||||||
unsigned int version; // initialized from type->tp_version_tag
|
|
||||||
#ifdef Py_GIL_DISABLED
|
|
||||||
_PySeqLock sequence;
|
|
||||||
#endif
|
|
||||||
PyObject *name; // reference to exactly a str or None
|
|
||||||
PyObject *value; // borrowed reference or NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
#define MCACHE_SIZE_EXP 12
|
|
||||||
|
|
||||||
struct type_cache {
|
|
||||||
struct type_cache_entry hashtable[1 << MCACHE_SIZE_EXP];
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
PyTypeObject *type;
|
|
||||||
int isbuiltin;
|
|
||||||
int readying;
|
|
||||||
int ready;
|
|
||||||
// XXX tp_dict can probably be statically allocated,
|
|
||||||
// instead of dynamically and stored on the interpreter.
|
|
||||||
PyObject *tp_dict;
|
|
||||||
PyObject *tp_subclasses;
|
|
||||||
/* We never clean up weakrefs for static builtin types since
|
|
||||||
they will effectively never get triggered. However, there
|
|
||||||
are also some diagnostic uses for the list of weakrefs,
|
|
||||||
so we still keep it. */
|
|
||||||
PyObject *tp_weaklist;
|
|
||||||
} managed_static_type_state;
|
|
||||||
|
|
||||||
#define TYPE_VERSION_CACHE_SIZE (1<<12) /* Must be a power of 2 */
|
|
||||||
|
|
||||||
struct types_state {
|
|
||||||
/* Used to set PyTypeObject.tp_version_tag.
|
|
||||||
It starts at _Py_MAX_GLOBAL_TYPE_VERSION_TAG + 1,
|
|
||||||
where all those lower numbers are used for core static types. */
|
|
||||||
unsigned int next_version_tag;
|
|
||||||
|
|
||||||
struct type_cache type_cache;
|
|
||||||
|
|
||||||
/* Every static builtin type is initialized for each interpreter
|
|
||||||
during its own initialization, including for the main interpreter
|
|
||||||
during global runtime initialization. This is done by calling
|
|
||||||
_PyStaticType_InitBuiltin().
|
|
||||||
|
|
||||||
The first time a static builtin type is initialized, all the
|
|
||||||
normal PyType_Ready() stuff happens. The only difference from
|
|
||||||
normal is that there are three PyTypeObject fields holding
|
|
||||||
objects which are stored here (on PyInterpreterState) rather
|
|
||||||
than in the corresponding PyTypeObject fields. Those are:
|
|
||||||
tp_dict (cls.__dict__), tp_subclasses (cls.__subclasses__),
|
|
||||||
and tp_weaklist.
|
|
||||||
|
|
||||||
When a subinterpreter is initialized, each static builtin type
|
|
||||||
is still initialized, but only the interpreter-specific portion,
|
|
||||||
namely those three objects.
|
|
||||||
|
|
||||||
Those objects are stored in the PyInterpreterState.types.builtins
|
|
||||||
array, at the index corresponding to each specific static builtin
|
|
||||||
type. That index (a size_t value) is stored in the tp_subclasses
|
|
||||||
field. For static builtin types, we re-purposed the now-unused
|
|
||||||
tp_subclasses to avoid adding another field to PyTypeObject.
|
|
||||||
In all other cases tp_subclasses holds a dict like before.
|
|
||||||
(The field was previously defined as PyObject*, but is now void*
|
|
||||||
to reflect its dual use.)
|
|
||||||
|
|
||||||
The index for each static builtin type isn't statically assigned.
|
|
||||||
Instead it is calculated the first time a type is initialized
|
|
||||||
(by the main interpreter). The index matches the order in which
|
|
||||||
the type was initialized relative to the others. The actual
|
|
||||||
value comes from the current value of num_builtins_initialized,
|
|
||||||
as each type is initialized for the main interpreter.
|
|
||||||
|
|
||||||
num_builtins_initialized is incremented once for each static
|
|
||||||
builtin type. Once initialization is over for a subinterpreter,
|
|
||||||
the value will be the same as for all other interpreters. */
|
|
||||||
struct {
|
|
||||||
size_t num_initialized;
|
|
||||||
managed_static_type_state initialized[_Py_MAX_MANAGED_STATIC_BUILTIN_TYPES];
|
|
||||||
} builtins;
|
|
||||||
/* We apply a similar strategy for managed extension modules. */
|
|
||||||
struct {
|
|
||||||
size_t num_initialized;
|
|
||||||
size_t next_index;
|
|
||||||
managed_static_type_state initialized[_Py_MAX_MANAGED_STATIC_EXT_TYPES];
|
|
||||||
} for_extensions;
|
|
||||||
PyMutex mutex;
|
|
||||||
|
|
||||||
// Borrowed references to type objects whose
|
|
||||||
// tp_version_tag % TYPE_VERSION_CACHE_SIZE
|
|
||||||
// once was equal to the index in the table.
|
|
||||||
// They are cleared when the type object is deallocated.
|
|
||||||
PyTypeObject *type_version_cache[TYPE_VERSION_CACHE_SIZE];
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/* runtime lifecycle */
|
/* runtime lifecycle */
|
||||||
|
|
||||||
|
@ -161,17 +42,6 @@ extern void _PyTypes_FiniExtTypes(PyInterpreterState *interp);
|
||||||
extern void _PyTypes_Fini(PyInterpreterState *);
|
extern void _PyTypes_Fini(PyInterpreterState *);
|
||||||
extern void _PyTypes_AfterFork(void);
|
extern void _PyTypes_AfterFork(void);
|
||||||
|
|
||||||
/* other API */
|
|
||||||
|
|
||||||
/* Length of array of slotdef pointers used to store slots with the
|
|
||||||
same __name__. There should be at most MAX_EQUIV-1 slotdef entries with
|
|
||||||
the same __name__, for any __name__. Since that's a static property, it is
|
|
||||||
appropriate to declare fixed-size arrays for this. */
|
|
||||||
#define MAX_EQUIV 10
|
|
||||||
|
|
||||||
typedef struct wrapperbase pytype_slotdef;
|
|
||||||
|
|
||||||
|
|
||||||
static inline PyObject **
|
static inline PyObject **
|
||||||
_PyStaticType_GET_WEAKREFS_LISTPTR(managed_static_type_state *state)
|
_PyStaticType_GET_WEAKREFS_LISTPTR(managed_static_type_state *state)
|
||||||
{
|
{
|
||||||
|
|
|
@ -287,40 +287,6 @@ extern void _PyUnicode_InternStatic(PyInterpreterState *interp, PyObject **);
|
||||||
|
|
||||||
/* --- Other API ---------------------------------------------------------- */
|
/* --- Other API ---------------------------------------------------------- */
|
||||||
|
|
||||||
struct _Py_unicode_runtime_ids {
|
|
||||||
PyMutex mutex;
|
|
||||||
// next_index value must be preserved when Py_Initialize()/Py_Finalize()
|
|
||||||
// is called multiple times: see _PyUnicode_FromId() implementation.
|
|
||||||
Py_ssize_t next_index;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _Py_unicode_runtime_state {
|
|
||||||
struct _Py_unicode_runtime_ids ids;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* fs_codec.encoding is initialized to NULL.
|
|
||||||
Later, it is set to a non-NULL string by _PyUnicode_InitEncodings(). */
|
|
||||||
struct _Py_unicode_fs_codec {
|
|
||||||
char *encoding; // Filesystem encoding (encoded to UTF-8)
|
|
||||||
int utf8; // encoding=="utf-8"?
|
|
||||||
char *errors; // Filesystem errors (encoded to UTF-8)
|
|
||||||
_Py_error_handler error_handler;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _Py_unicode_ids {
|
|
||||||
Py_ssize_t size;
|
|
||||||
PyObject **array;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _Py_unicode_state {
|
|
||||||
struct _Py_unicode_fs_codec fs_codec;
|
|
||||||
|
|
||||||
_PyUnicode_Name_CAPI *ucnhash_capi;
|
|
||||||
|
|
||||||
// Unicode identifiers (_Py_Identifier): see _PyUnicode_FromId()
|
|
||||||
struct _Py_unicode_ids ids;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern void _PyUnicode_ClearInterned(PyInterpreterState *interp);
|
extern void _PyUnicode_ClearInterned(PyInterpreterState *interp);
|
||||||
|
|
||||||
// Like PyUnicode_AsUTF8(), but check for embedded null characters.
|
// Like PyUnicode_AsUTF8(), but check for embedded null characters.
|
||||||
|
|
|
@ -24,26 +24,6 @@ extern "C" {
|
||||||
// Each entry implicitly represents a unique id based on its offset in the
|
// Each entry implicitly represents a unique id based on its offset in the
|
||||||
// table. Non-allocated entries form a free-list via the 'next' pointer.
|
// table. Non-allocated entries form a free-list via the 'next' pointer.
|
||||||
// Allocated entries store the corresponding PyObject.
|
// Allocated entries store the corresponding PyObject.
|
||||||
typedef union _Py_unique_id_entry {
|
|
||||||
// Points to the next free type id, when part of the freelist
|
|
||||||
union _Py_unique_id_entry *next;
|
|
||||||
|
|
||||||
// Stores the object when the id is assigned
|
|
||||||
PyObject *obj;
|
|
||||||
} _Py_unique_id_entry;
|
|
||||||
|
|
||||||
struct _Py_unique_id_pool {
|
|
||||||
PyMutex mutex;
|
|
||||||
|
|
||||||
// combined table of object with allocated unique ids and unallocated ids.
|
|
||||||
_Py_unique_id_entry *table;
|
|
||||||
|
|
||||||
// Next entry to allocate inside 'table' or NULL
|
|
||||||
_Py_unique_id_entry *freelist;
|
|
||||||
|
|
||||||
// size of 'table'
|
|
||||||
Py_ssize_t size;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define _Py_INVALID_UNIQUE_ID 0
|
#define _Py_INVALID_UNIQUE_ID 0
|
||||||
|
|
||||||
|
|
|
@ -8,16 +8,6 @@ extern "C" {
|
||||||
# error "this header requires Py_BUILD_CORE define"
|
# error "this header requires Py_BUILD_CORE define"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct _warnings_runtime_state {
|
|
||||||
/* Both 'filters' and 'onceregistry' can be set in warnings.py;
|
|
||||||
get_warnings_attr() will reset these variables accordingly. */
|
|
||||||
PyObject *filters; /* List */
|
|
||||||
PyObject *once_registry; /* Dict */
|
|
||||||
PyObject *default_action; /* String */
|
|
||||||
_PyRecursiveMutex lock;
|
|
||||||
long filters_version;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern int _PyWarnings_InitState(PyInterpreterState *interp);
|
extern int _PyWarnings_InitState(PyInterpreterState *interp);
|
||||||
|
|
||||||
extern PyObject* _PyWarnings_Init(void);
|
extern PyObject* _PyWarnings_Init(void);
|
||||||
|
|
|
@ -1255,6 +1255,7 @@ PYTHON_HEADERS= \
|
||||||
$(srcdir)/Include/internal/pycore_instruments.h \
|
$(srcdir)/Include/internal/pycore_instruments.h \
|
||||||
$(srcdir)/Include/internal/pycore_instruction_sequence.h \
|
$(srcdir)/Include/internal/pycore_instruction_sequence.h \
|
||||||
$(srcdir)/Include/internal/pycore_interp.h \
|
$(srcdir)/Include/internal/pycore_interp.h \
|
||||||
|
$(srcdir)/Include/internal/pycore_interp_structs.h \
|
||||||
$(srcdir)/Include/internal/pycore_intrinsics.h \
|
$(srcdir)/Include/internal/pycore_intrinsics.h \
|
||||||
$(srcdir)/Include/internal/pycore_jit.h \
|
$(srcdir)/Include/internal/pycore_jit.h \
|
||||||
$(srcdir)/Include/internal/pycore_list.h \
|
$(srcdir)/Include/internal/pycore_list.h \
|
||||||
|
@ -1297,11 +1298,13 @@ PYTHON_HEADERS= \
|
||||||
$(srcdir)/Include/internal/pycore_runtime.h \
|
$(srcdir)/Include/internal/pycore_runtime.h \
|
||||||
$(srcdir)/Include/internal/pycore_runtime_init.h \
|
$(srcdir)/Include/internal/pycore_runtime_init.h \
|
||||||
$(srcdir)/Include/internal/pycore_runtime_init_generated.h \
|
$(srcdir)/Include/internal/pycore_runtime_init_generated.h \
|
||||||
|
$(srcdir)/Include/internal/pycore_runtime_structs.h \
|
||||||
$(srcdir)/Include/internal/pycore_semaphore.h \
|
$(srcdir)/Include/internal/pycore_semaphore.h \
|
||||||
$(srcdir)/Include/internal/pycore_setobject.h \
|
$(srcdir)/Include/internal/pycore_setobject.h \
|
||||||
$(srcdir)/Include/internal/pycore_signal.h \
|
$(srcdir)/Include/internal/pycore_signal.h \
|
||||||
$(srcdir)/Include/internal/pycore_sliceobject.h \
|
$(srcdir)/Include/internal/pycore_sliceobject.h \
|
||||||
$(srcdir)/Include/internal/pycore_strhex.h \
|
$(srcdir)/Include/internal/pycore_strhex.h \
|
||||||
|
$(srcdir)/Include/internal/pycore_structs.h \
|
||||||
$(srcdir)/Include/internal/pycore_structseq.h \
|
$(srcdir)/Include/internal/pycore_structseq.h \
|
||||||
$(srcdir)/Include/internal/pycore_symtable.h \
|
$(srcdir)/Include/internal/pycore_symtable.h \
|
||||||
$(srcdir)/Include/internal/pycore_sysmodule.h \
|
$(srcdir)/Include/internal/pycore_sysmodule.h \
|
||||||
|
|
|
@ -32,6 +32,7 @@ Copyright (c) Corporation for National Research Initiatives.
|
||||||
|
|
||||||
#include "Python.h"
|
#include "Python.h"
|
||||||
#include "pycore_codecs.h" // _PyCodec_Lookup()
|
#include "pycore_codecs.h" // _PyCodec_Lookup()
|
||||||
|
#include "pycore_unicodeobject.h" // _PyUnicode_EncodeCharmap
|
||||||
|
|
||||||
#ifdef MS_WINDOWS
|
#ifdef MS_WINDOWS
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
|
@ -109,6 +109,7 @@ static const char PyCursesVersion[] = "2.2";
|
||||||
#include "pycore_long.h" // _PyLong_GetZero()
|
#include "pycore_long.h" // _PyLong_GetZero()
|
||||||
#include "pycore_structseq.h" // _PyStructSequence_NewType()
|
#include "pycore_structseq.h" // _PyStructSequence_NewType()
|
||||||
#include "pycore_sysmodule.h" // _PySys_GetOptionalAttrString()
|
#include "pycore_sysmodule.h" // _PySys_GetOptionalAttrString()
|
||||||
|
#include "pycore_fileutils.h" // _Py_set_inheritable
|
||||||
|
|
||||||
#ifdef __hpux
|
#ifdef __hpux
|
||||||
#define STRICT_SYSV_CURSES
|
#define STRICT_SYSV_CURSES
|
||||||
|
|
|
@ -32,6 +32,7 @@ Copyright (C) 1994 Steen Lumholt.
|
||||||
|
|
||||||
#include "pycore_long.h" // _PyLong_IsNegative()
|
#include "pycore_long.h" // _PyLong_IsNegative()
|
||||||
#include "pycore_sysmodule.h" // _PySys_GetOptionalAttrString()
|
#include "pycore_sysmodule.h" // _PySys_GetOptionalAttrString()
|
||||||
|
#include "pycore_unicodeobject.h" // _PyUnicode_AsUTF8String
|
||||||
|
|
||||||
#ifdef MS_WINDOWS
|
#ifdef MS_WINDOWS
|
||||||
# include <windows.h>
|
# include <windows.h>
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
#define _PY_INTERPRETER
|
#define _PY_INTERPRETER
|
||||||
|
|
||||||
#include "Python.h"
|
#include "Python.h"
|
||||||
|
#include "pycore_genobject.h"
|
||||||
|
|
||||||
#include "pycore_call.h" // _PyObject_CallNoArgs()
|
#include "pycore_call.h" // _PyObject_CallNoArgs()
|
||||||
#include "pycore_ceval.h" // _PyEval_EvalFrame()
|
#include "pycore_ceval.h" // _PyEval_EvalFrame()
|
||||||
#include "pycore_frame.h" // _PyInterpreterFrame
|
#include "pycore_frame.h" // _PyInterpreterFrame
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include "pycore_modsupport.h" // _PyArg_NoKwnames()
|
#include "pycore_modsupport.h" // _PyArg_NoKwnames()
|
||||||
#include "pycore_object.h" // _PyObject_GC_TRACK(), _PyDebugAllocatorStats()
|
#include "pycore_object.h" // _PyObject_GC_TRACK(), _PyDebugAllocatorStats()
|
||||||
#include "pycore_tuple.h" // _PyTuple_FromArray()
|
#include "pycore_tuple.h" // _PyTuple_FromArray()
|
||||||
|
#include "pycore_typeobject.h" // _Py_TYPE_VERSION_LIST
|
||||||
#include "pycore_setobject.h" // _PySet_NextEntry()
|
#include "pycore_setobject.h" // _PySet_NextEntry()
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include "pycore_initconfig.h" // _PyStatus_EXCEPTION()
|
#include "pycore_initconfig.h" // _PyStatus_EXCEPTION()
|
||||||
#include "pycore_instruction_sequence.h" // _PyInstructionSequence_Type
|
#include "pycore_instruction_sequence.h" // _PyInstructionSequence_Type
|
||||||
#include "pycore_hashtable.h" // _Py_hashtable_new()
|
#include "pycore_hashtable.h" // _Py_hashtable_new()
|
||||||
|
#include "pycore_hamt.h" // _PyHamtItems_Type
|
||||||
#include "pycore_memoryobject.h" // _PyManagedBuffer_Type
|
#include "pycore_memoryobject.h" // _PyManagedBuffer_Type
|
||||||
#include "pycore_namespace.h" // _PyNamespace_Type
|
#include "pycore_namespace.h" // _PyNamespace_Type
|
||||||
#include "pycore_object.h" // PyAPI_DATA() _Py_SwappedOp definition
|
#include "pycore_object.h" // PyAPI_DATA() _Py_SwappedOp definition
|
||||||
|
|
|
@ -53,6 +53,7 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
#include "pycore_object.h" // _PyObject_GC_TRACK(), _Py_FatalRefcountError()
|
#include "pycore_object.h" // _PyObject_GC_TRACK(), _Py_FatalRefcountError()
|
||||||
#include "pycore_pathconfig.h" // _Py_DumpPathConfig()
|
#include "pycore_pathconfig.h" // _Py_DumpPathConfig()
|
||||||
#include "pycore_pyerrors.h" // _PyUnicodeTranslateError_Create()
|
#include "pycore_pyerrors.h" // _PyUnicodeTranslateError_Create()
|
||||||
|
#include "pycore_pyhash.h" // _Py_HashSecret_t
|
||||||
#include "pycore_pylifecycle.h" // _Py_SetFileSystemEncoding()
|
#include "pycore_pylifecycle.h" // _Py_SetFileSystemEncoding()
|
||||||
#include "pycore_pystate.h" // _PyInterpreterState_GET()
|
#include "pycore_pystate.h" // _PyInterpreterState_GET()
|
||||||
#include "pycore_ucnhash.h" // _PyUnicode_Name_CAPI
|
#include "pycore_ucnhash.h" // _PyUnicode_Name_CAPI
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
#include <Python.h>
|
#include <Python.h>
|
||||||
#include "pycore_ast.h" // _PyAST_Validate(),
|
#include "pycore_ast.h" // _PyAST_Validate(),
|
||||||
#include "pycore_pystate.h" // _PyThreadState_GET()
|
#include "pycore_pystate.h" // _PyThreadState_GET()
|
||||||
|
#include "pycore_parser.h" // _PYPEGEN_NSTATISTICS
|
||||||
#include "pycore_pyerrors.h" // PyExc_IncompleteInputError
|
#include "pycore_pyerrors.h" // PyExc_IncompleteInputError
|
||||||
|
#include "pycore_runtime.h" // _PyRuntime
|
||||||
|
#include "pycore_unicodeobject.h" // _PyUnicode_InternImmortal
|
||||||
#include <errcode.h>
|
#include <errcode.h>
|
||||||
|
|
||||||
#include "lexer/lexer.h"
|
#include "lexer/lexer.h"
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "Python.h"
|
#include "Python.h"
|
||||||
#include "pycore_fileutils.h" // _Py_fstat_noraise()
|
#include "pycore_fileutils.h" // _Py_fstat_noraise()
|
||||||
#include "pycore_initconfig.h"
|
#include "pycore_initconfig.h"
|
||||||
|
#include "pycore_pyhash.h" // _Py_HashSecret_t
|
||||||
#include "pycore_pylifecycle.h" // _PyOS_URandomNonblock()
|
#include "pycore_pylifecycle.h" // _PyOS_URandomNonblock()
|
||||||
#include "pycore_runtime.h" // _PyRuntime
|
#include "pycore_runtime.h" // _PyRuntime
|
||||||
|
|
||||||
|
|
|
@ -122,6 +122,7 @@
|
||||||
#include "pycore_pystate.h" // _PyInterpreterState_GET()
|
#include "pycore_pystate.h" // _PyInterpreterState_GET()
|
||||||
#include <stdlib.h> // exit()
|
#include <stdlib.h> // exit()
|
||||||
|
|
||||||
|
|
||||||
/* if _PY_SHORT_FLOAT_REPR == 0, then don't even try to compile
|
/* if _PY_SHORT_FLOAT_REPR == 0, then don't even try to compile
|
||||||
the following code */
|
the following code */
|
||||||
#if _PY_SHORT_FLOAT_REPR == 1
|
#if _PY_SHORT_FLOAT_REPR == 1
|
||||||
|
@ -157,7 +158,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
// ULong is defined in pycore_dtoa.h.
|
typedef uint32_t ULong;
|
||||||
typedef int32_t Long;
|
typedef int32_t Long;
|
||||||
typedef uint64_t ULLong;
|
typedef uint64_t ULLong;
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include "Python.h"
|
#include "Python.h"
|
||||||
#include "pycore_fileutils.h" // _Py_GetLocaleconvNumeric()
|
#include "pycore_fileutils.h" // _Py_GetLocaleconvNumeric()
|
||||||
#include "pycore_long.h" // _PyLong_FormatWriter()
|
#include "pycore_long.h" // _PyLong_FormatWriter()
|
||||||
|
#include "pycore_unicodeobject.h" // PyUnicode_MAX_CHAR_VALUE()
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
|
|
||||||
/* Raises an exception about an unknown presentation type for this
|
/* Raises an exception about an unknown presentation type for this
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include "pycore_pyerrors.h" // _PyErr_GetRaisedException()
|
#include "pycore_pyerrors.h" // _PyErr_GetRaisedException()
|
||||||
#include "pycore_pylifecycle.h" // _Py_PreInitializeFromConfig()
|
#include "pycore_pylifecycle.h" // _Py_PreInitializeFromConfig()
|
||||||
#include "pycore_pymem.h" // _PyMem_DefaultRawMalloc()
|
#include "pycore_pymem.h" // _PyMem_DefaultRawMalloc()
|
||||||
|
#include "pycore_pyhash.h" // _Py_HashSecret
|
||||||
#include "pycore_pystate.h" // _PyThreadState_GET()
|
#include "pycore_pystate.h" // _PyThreadState_GET()
|
||||||
#include "pycore_pystats.h" // _Py_StatsOn()
|
#include "pycore_pystats.h" // _Py_StatsOn()
|
||||||
#include "pycore_sysmodule.h" // _PySys_SetIntMaxStrDigits()
|
#include "pycore_sysmodule.h" // _PySys_SetIntMaxStrDigits()
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include "pycore_pyatomic_ft_wrappers.h" // FT_ATOMIC_STORE_UINTPTR_RELEASE
|
#include "pycore_pyatomic_ft_wrappers.h" // FT_ATOMIC_STORE_UINTPTR_RELEASE
|
||||||
#include "pycore_pyerrors.h"
|
#include "pycore_pyerrors.h"
|
||||||
#include "pycore_pystate.h" // _PyInterpreterState_GET()
|
#include "pycore_pystate.h" // _PyInterpreterState_GET()
|
||||||
|
#include "pycore_runtime_structs.h" // _PyCoMonitoringData
|
||||||
|
|
||||||
/* Uncomment this to dump debugging output when assertions fail */
|
/* Uncomment this to dump debugging output when assertions fail */
|
||||||
// #define INSTRUMENT_DEBUG 1
|
// #define INSTRUMENT_DEBUG 1
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
/* PyInterpreterConfig API */
|
/* PyInterpreterConfig API */
|
||||||
|
|
||||||
#include "Python.h"
|
#include "Python.h"
|
||||||
|
#include "pycore_interp.h" // Py_RTFLAGS
|
||||||
#include "pycore_pylifecycle.h"
|
#include "pycore_pylifecycle.h"
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
|
@ -5,12 +5,15 @@
|
||||||
#include "pycore_frame.h"
|
#include "pycore_frame.h"
|
||||||
#include "pycore_function.h"
|
#include "pycore_function.h"
|
||||||
#include "pycore_global_objects.h"
|
#include "pycore_global_objects.h"
|
||||||
|
#include "pycore_genobject.h" // _PyAsyncGenValueWrapperNew
|
||||||
#include "pycore_compile.h" // _PyCompile_GetUnaryIntrinsicName, etc
|
#include "pycore_compile.h" // _PyCompile_GetUnaryIntrinsicName, etc
|
||||||
#include "pycore_intrinsics.h" // INTRINSIC_PRINT
|
#include "pycore_intrinsics.h" // INTRINSIC_PRINT
|
||||||
#include "pycore_pyerrors.h" // _PyErr_SetString()
|
#include "pycore_pyerrors.h" // _PyErr_SetString()
|
||||||
#include "pycore_runtime.h" // _Py_ID()
|
#include "pycore_runtime.h" // _Py_ID()
|
||||||
#include "pycore_sysmodule.h" // _PySys_GetRequiredAttr()
|
#include "pycore_sysmodule.h" // _PySys_GetRequiredAttr()
|
||||||
|
#include "pycore_tuple.h" // _PyTuple_FromArray()
|
||||||
#include "pycore_typevarobject.h" // _Py_make_typevar()
|
#include "pycore_typevarobject.h" // _Py_make_typevar()
|
||||||
|
#include "pycore_unicodeobject.h" // _PyUnicode_FromASCII
|
||||||
|
|
||||||
|
|
||||||
/******** Unary functions ********/
|
/******** Unary functions ********/
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
/* Python interpreter top-level routines, including init/exit */
|
/* Python interpreter top-level routines, including init/exit */
|
||||||
|
|
||||||
#include "Python.h"
|
#include "Python.h"
|
||||||
|
#include "pycore_runtime_structs.h"
|
||||||
|
#include "pycore_unicodeobject.h"
|
||||||
#include "pycore_audit.h" // _PySys_ClearAuditHooks()
|
#include "pycore_audit.h" // _PySys_ClearAuditHooks()
|
||||||
#include "pycore_call.h" // _PyObject_CallMethod()
|
#include "pycore_call.h" // _PyObject_CallMethod()
|
||||||
#include "pycore_ceval.h" // _PyEval_FiniGIL()
|
#include "pycore_ceval.h" // _PyEval_FiniGIL()
|
||||||
|
@ -13,6 +14,7 @@
|
||||||
#include "pycore_freelist.h" // _PyObject_ClearFreeLists()
|
#include "pycore_freelist.h" // _PyObject_ClearFreeLists()
|
||||||
#include "pycore_floatobject.h" // _PyFloat_InitTypes()
|
#include "pycore_floatobject.h" // _PyFloat_InitTypes()
|
||||||
#include "pycore_global_objects_fini_generated.h" // "_PyStaticObjects_CheckRefcnt()
|
#include "pycore_global_objects_fini_generated.h" // "_PyStaticObjects_CheckRefcnt()
|
||||||
|
#include "pycore_hamt.h" // _PyHamt_Type
|
||||||
#include "pycore_import.h" // _PyImport_BootstrapImp()
|
#include "pycore_import.h" // _PyImport_BootstrapImp()
|
||||||
#include "pycore_initconfig.h" // _PyStatus_OK()
|
#include "pycore_initconfig.h" // _PyStatus_OK()
|
||||||
#include "pycore_list.h" // _PyList_Fini()
|
#include "pycore_list.h" // _PyList_Fini()
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
/* Thread and interpreter state structures and their interfaces */
|
/* Thread and interpreter state structures and their interfaces */
|
||||||
|
|
||||||
#include "Python.h"
|
#include "Python.h"
|
||||||
|
#include "pycore_runtime_structs.h"
|
||||||
|
|
||||||
#include "pycore_abstract.h" // _PyIndex_Check()
|
#include "pycore_abstract.h" // _PyIndex_Check()
|
||||||
#include "pycore_audit.h" // _Py_AuditHookEntry
|
#include "pycore_audit.h" // _Py_AuditHookEntry
|
||||||
#include "pycore_ceval.h"
|
#include "pycore_ceval.h"
|
||||||
|
@ -18,6 +20,7 @@
|
||||||
#include "pycore_pylifecycle.h" // _PyAST_Fini()
|
#include "pycore_pylifecycle.h" // _PyAST_Fini()
|
||||||
#include "pycore_pymem.h" // _PyMem_DebugEnabled()
|
#include "pycore_pymem.h" // _PyMem_DebugEnabled()
|
||||||
#include "pycore_pystate.h"
|
#include "pycore_pystate.h"
|
||||||
|
#include "pycore_runtime.h" // _PyRuntime
|
||||||
#include "pycore_runtime_init.h" // _PyRuntimeState_INIT
|
#include "pycore_runtime_init.h" // _PyRuntimeState_INIT
|
||||||
#include "pycore_stackref.h" // Py_STACKREF_DEBUG
|
#include "pycore_stackref.h" // Py_STACKREF_DEBUG
|
||||||
#include "pycore_time.h" // _PyTime_Init()
|
#include "pycore_time.h" // _PyTime_Init()
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "pycore_frame.h"
|
#include "pycore_frame.h"
|
||||||
#include "pycore_pyerrors.h" // export _Py_UTF8_Edit_Cost()
|
#include "pycore_pyerrors.h" // export _Py_UTF8_Edit_Cost()
|
||||||
#include "pycore_runtime.h" // _Py_ID()
|
#include "pycore_runtime.h" // _Py_ID()
|
||||||
|
#include "pycore_unicodeobject.h" // _PyUnicode_Equal()
|
||||||
|
|
||||||
#define MAX_CANDIDATE_ITEMS 750
|
#define MAX_CANDIDATE_ITEMS 750
|
||||||
#define MAX_STRING_SIZE 40
|
#define MAX_STRING_SIZE 40
|
||||||
|
|
|
@ -277,7 +277,7 @@ def generate_runtime_init(identifiers, strings):
|
||||||
# First get some info from the declarations.
|
# First get some info from the declarations.
|
||||||
nsmallposints = None
|
nsmallposints = None
|
||||||
nsmallnegints = None
|
nsmallnegints = None
|
||||||
with open(os.path.join(INTERNAL, 'pycore_global_objects.h')) as infile:
|
with open(os.path.join(INTERNAL, 'pycore_runtime_structs.h')) as infile:
|
||||||
for line in infile:
|
for line in infile:
|
||||||
if line.startswith('#define _PY_NSMALLPOSINTS'):
|
if line.startswith('#define _PY_NSMALLPOSINTS'):
|
||||||
nsmallposints = int(line.split()[-1])
|
nsmallposints = int(line.split()[-1])
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue