Add pre-build wheels to support python 3.10/3.12 cuda 12.1
This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
#ifndef Py_INTERNAL_ABSTRACT_H
|
||||
#define Py_INTERNAL_ABSTRACT_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef Py_BUILD_CORE
|
||||
# error "this header requires Py_BUILD_CORE define"
|
||||
#endif
|
||||
|
||||
// Fast inlined version of PyIndex_Check()
|
||||
static inline int
|
||||
_PyIndex_Check(PyObject *obj)
|
||||
{
|
||||
PyNumberMethods *tp_as_number = Py_TYPE(obj)->tp_as_number;
|
||||
return (tp_as_number != NULL && tp_as_number->nb_index != NULL);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* !Py_INTERNAL_ABSTRACT_H */
|
||||
@@ -0,0 +1,39 @@
|
||||
#ifndef Py_LIMITED_API
|
||||
#ifndef Py_INTERNAL_ACCU_H
|
||||
#define Py_INTERNAL_ACCU_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*** This is a private API for use by the interpreter and the stdlib.
|
||||
*** Its definition may be changed or removed at any moment.
|
||||
***/
|
||||
|
||||
#ifndef Py_BUILD_CORE
|
||||
# error "this header requires Py_BUILD_CORE define"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* A two-level accumulator of unicode objects that avoids both the overhead
|
||||
* of keeping a huge number of small separate objects, and the quadratic
|
||||
* behaviour of using a naive repeated concatenation scheme.
|
||||
*/
|
||||
|
||||
#undef small /* defined by some Windows headers */
|
||||
|
||||
typedef struct {
|
||||
PyObject *large; /* A list of previously accumulated large strings */
|
||||
PyObject *small; /* Pending small strings */
|
||||
} _PyAccu;
|
||||
|
||||
PyAPI_FUNC(int) _PyAccu_Init(_PyAccu *acc);
|
||||
PyAPI_FUNC(int) _PyAccu_Accumulate(_PyAccu *acc, PyObject *unicode);
|
||||
PyAPI_FUNC(PyObject *) _PyAccu_FinishAsList(_PyAccu *acc);
|
||||
PyAPI_FUNC(PyObject *) _PyAccu_Finish(_PyAccu *acc);
|
||||
PyAPI_FUNC(void) _PyAccu_Destroy(_PyAccu *acc);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* !Py_INTERNAL_ACCU_H */
|
||||
#endif /* !Py_LIMITED_API */
|
||||
@@ -0,0 +1,112 @@
|
||||
#ifndef Py_INTERNAL_ASDL_H
|
||||
#define Py_INTERNAL_ASDL_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef Py_BUILD_CORE
|
||||
# error "this header requires Py_BUILD_CORE define"
|
||||
#endif
|
||||
|
||||
#include "pycore_pyarena.h" // _PyArena_Malloc()
|
||||
|
||||
typedef PyObject * identifier;
|
||||
typedef PyObject * string;
|
||||
typedef PyObject * object;
|
||||
typedef PyObject * constant;
|
||||
|
||||
/* It would be nice if the code generated by asdl_c.py was completely
|
||||
independent of Python, but it is a goal the requires too much work
|
||||
at this stage. So, for example, I'll represent identifiers as
|
||||
interned Python strings.
|
||||
*/
|
||||
|
||||
#define _ASDL_SEQ_HEAD \
|
||||
Py_ssize_t size; \
|
||||
void **elements;
|
||||
|
||||
typedef struct {
|
||||
_ASDL_SEQ_HEAD
|
||||
} asdl_seq;
|
||||
|
||||
typedef struct {
|
||||
_ASDL_SEQ_HEAD
|
||||
void *typed_elements[1];
|
||||
} asdl_generic_seq;
|
||||
|
||||
typedef struct {
|
||||
_ASDL_SEQ_HEAD
|
||||
PyObject *typed_elements[1];
|
||||
} asdl_identifier_seq;
|
||||
|
||||
typedef struct {
|
||||
_ASDL_SEQ_HEAD
|
||||
int typed_elements[1];
|
||||
} asdl_int_seq;
|
||||
|
||||
asdl_generic_seq *_Py_asdl_generic_seq_new(Py_ssize_t size, PyArena *arena);
|
||||
asdl_identifier_seq *_Py_asdl_identifier_seq_new(Py_ssize_t size, PyArena *arena);
|
||||
asdl_int_seq *_Py_asdl_int_seq_new(Py_ssize_t size, PyArena *arena);
|
||||
|
||||
|
||||
#define GENERATE_ASDL_SEQ_CONSTRUCTOR(NAME, TYPE) \
|
||||
asdl_ ## NAME ## _seq *_Py_asdl_ ## NAME ## _seq_new(Py_ssize_t size, PyArena *arena) \
|
||||
{ \
|
||||
asdl_ ## NAME ## _seq *seq = NULL; \
|
||||
size_t n; \
|
||||
/* check size is sane */ \
|
||||
if (size < 0 || \
|
||||
(size && (((size_t)size - 1) > (SIZE_MAX / sizeof(void *))))) { \
|
||||
PyErr_NoMemory(); \
|
||||
return NULL; \
|
||||
} \
|
||||
n = (size ? (sizeof(TYPE *) * (size - 1)) : 0); \
|
||||
/* check if size can be added safely */ \
|
||||
if (n > SIZE_MAX - sizeof(asdl_ ## NAME ## _seq)) { \
|
||||
PyErr_NoMemory(); \
|
||||
return NULL; \
|
||||
} \
|
||||
n += sizeof(asdl_ ## NAME ## _seq); \
|
||||
seq = (asdl_ ## NAME ## _seq *)_PyArena_Malloc(arena, n); \
|
||||
if (!seq) { \
|
||||
PyErr_NoMemory(); \
|
||||
return NULL; \
|
||||
} \
|
||||
memset(seq, 0, n); \
|
||||
seq->size = size; \
|
||||
seq->elements = (void**)seq->typed_elements; \
|
||||
return seq; \
|
||||
}
|
||||
|
||||
#define asdl_seq_GET_UNTYPED(S, I) (S)->elements[(I)]
|
||||
#define asdl_seq_GET(S, I) (S)->typed_elements[(I)]
|
||||
#define asdl_seq_LEN(S) ((S) == NULL ? 0 : (S)->size)
|
||||
|
||||
#ifdef Py_DEBUG
|
||||
# define asdl_seq_SET(S, I, V) \
|
||||
do { \
|
||||
Py_ssize_t _asdl_i = (I); \
|
||||
assert((S) != NULL); \
|
||||
assert(0 <= _asdl_i && _asdl_i < (S)->size); \
|
||||
(S)->typed_elements[_asdl_i] = (V); \
|
||||
} while (0)
|
||||
#else
|
||||
# define asdl_seq_SET(S, I, V) (S)->typed_elements[I] = (V)
|
||||
#endif
|
||||
|
||||
#ifdef Py_DEBUG
|
||||
# define asdl_seq_SET_UNTYPED(S, I, V) \
|
||||
do { \
|
||||
Py_ssize_t _asdl_i = (I); \
|
||||
assert((S) != NULL); \
|
||||
assert(0 <= _asdl_i && _asdl_i < (S)->size); \
|
||||
(S)->elements[_asdl_i] = (V); \
|
||||
} while (0)
|
||||
#else
|
||||
# define asdl_seq_SET_UNTYPED(S, I, V) (S)->elements[I] = (V)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* !Py_INTERNAL_ASDL_H */
|
||||
@@ -0,0 +1,855 @@
|
||||
// File automatically generated by Parser/asdl_c.py.
|
||||
|
||||
#ifndef Py_INTERNAL_AST_H
|
||||
#define Py_INTERNAL_AST_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef Py_BUILD_CORE
|
||||
# error "this header requires Py_BUILD_CORE define"
|
||||
#endif
|
||||
|
||||
#include "pycore_asdl.h"
|
||||
|
||||
typedef struct _mod *mod_ty;
|
||||
|
||||
typedef struct _stmt *stmt_ty;
|
||||
|
||||
typedef struct _expr *expr_ty;
|
||||
|
||||
typedef enum _expr_context { Load=1, Store=2, Del=3 } expr_context_ty;
|
||||
|
||||
typedef enum _boolop { And=1, Or=2 } boolop_ty;
|
||||
|
||||
typedef enum _operator { Add=1, Sub=2, Mult=3, MatMult=4, Div=5, Mod=6, Pow=7,
|
||||
LShift=8, RShift=9, BitOr=10, BitXor=11, BitAnd=12,
|
||||
FloorDiv=13 } operator_ty;
|
||||
|
||||
typedef enum _unaryop { Invert=1, Not=2, UAdd=3, USub=4 } unaryop_ty;
|
||||
|
||||
typedef enum _cmpop { Eq=1, NotEq=2, Lt=3, LtE=4, Gt=5, GtE=6, Is=7, IsNot=8,
|
||||
In=9, NotIn=10 } cmpop_ty;
|
||||
|
||||
typedef struct _comprehension *comprehension_ty;
|
||||
|
||||
typedef struct _excepthandler *excepthandler_ty;
|
||||
|
||||
typedef struct _arguments *arguments_ty;
|
||||
|
||||
typedef struct _arg *arg_ty;
|
||||
|
||||
typedef struct _keyword *keyword_ty;
|
||||
|
||||
typedef struct _alias *alias_ty;
|
||||
|
||||
typedef struct _withitem *withitem_ty;
|
||||
|
||||
typedef struct _match_case *match_case_ty;
|
||||
|
||||
typedef struct _pattern *pattern_ty;
|
||||
|
||||
typedef struct _type_ignore *type_ignore_ty;
|
||||
|
||||
|
||||
typedef struct {
|
||||
_ASDL_SEQ_HEAD
|
||||
mod_ty typed_elements[1];
|
||||
} asdl_mod_seq;
|
||||
|
||||
asdl_mod_seq *_Py_asdl_mod_seq_new(Py_ssize_t size, PyArena *arena);
|
||||
|
||||
typedef struct {
|
||||
_ASDL_SEQ_HEAD
|
||||
stmt_ty typed_elements[1];
|
||||
} asdl_stmt_seq;
|
||||
|
||||
asdl_stmt_seq *_Py_asdl_stmt_seq_new(Py_ssize_t size, PyArena *arena);
|
||||
|
||||
typedef struct {
|
||||
_ASDL_SEQ_HEAD
|
||||
expr_ty typed_elements[1];
|
||||
} asdl_expr_seq;
|
||||
|
||||
asdl_expr_seq *_Py_asdl_expr_seq_new(Py_ssize_t size, PyArena *arena);
|
||||
|
||||
typedef struct {
|
||||
_ASDL_SEQ_HEAD
|
||||
comprehension_ty typed_elements[1];
|
||||
} asdl_comprehension_seq;
|
||||
|
||||
asdl_comprehension_seq *_Py_asdl_comprehension_seq_new(Py_ssize_t size, PyArena
|
||||
*arena);
|
||||
|
||||
typedef struct {
|
||||
_ASDL_SEQ_HEAD
|
||||
excepthandler_ty typed_elements[1];
|
||||
} asdl_excepthandler_seq;
|
||||
|
||||
asdl_excepthandler_seq *_Py_asdl_excepthandler_seq_new(Py_ssize_t size, PyArena
|
||||
*arena);
|
||||
|
||||
typedef struct {
|
||||
_ASDL_SEQ_HEAD
|
||||
arguments_ty typed_elements[1];
|
||||
} asdl_arguments_seq;
|
||||
|
||||
asdl_arguments_seq *_Py_asdl_arguments_seq_new(Py_ssize_t size, PyArena *arena);
|
||||
|
||||
typedef struct {
|
||||
_ASDL_SEQ_HEAD
|
||||
arg_ty typed_elements[1];
|
||||
} asdl_arg_seq;
|
||||
|
||||
asdl_arg_seq *_Py_asdl_arg_seq_new(Py_ssize_t size, PyArena *arena);
|
||||
|
||||
typedef struct {
|
||||
_ASDL_SEQ_HEAD
|
||||
keyword_ty typed_elements[1];
|
||||
} asdl_keyword_seq;
|
||||
|
||||
asdl_keyword_seq *_Py_asdl_keyword_seq_new(Py_ssize_t size, PyArena *arena);
|
||||
|
||||
typedef struct {
|
||||
_ASDL_SEQ_HEAD
|
||||
alias_ty typed_elements[1];
|
||||
} asdl_alias_seq;
|
||||
|
||||
asdl_alias_seq *_Py_asdl_alias_seq_new(Py_ssize_t size, PyArena *arena);
|
||||
|
||||
typedef struct {
|
||||
_ASDL_SEQ_HEAD
|
||||
withitem_ty typed_elements[1];
|
||||
} asdl_withitem_seq;
|
||||
|
||||
asdl_withitem_seq *_Py_asdl_withitem_seq_new(Py_ssize_t size, PyArena *arena);
|
||||
|
||||
typedef struct {
|
||||
_ASDL_SEQ_HEAD
|
||||
match_case_ty typed_elements[1];
|
||||
} asdl_match_case_seq;
|
||||
|
||||
asdl_match_case_seq *_Py_asdl_match_case_seq_new(Py_ssize_t size, PyArena
|
||||
*arena);
|
||||
|
||||
typedef struct {
|
||||
_ASDL_SEQ_HEAD
|
||||
pattern_ty typed_elements[1];
|
||||
} asdl_pattern_seq;
|
||||
|
||||
asdl_pattern_seq *_Py_asdl_pattern_seq_new(Py_ssize_t size, PyArena *arena);
|
||||
|
||||
typedef struct {
|
||||
_ASDL_SEQ_HEAD
|
||||
type_ignore_ty typed_elements[1];
|
||||
} asdl_type_ignore_seq;
|
||||
|
||||
asdl_type_ignore_seq *_Py_asdl_type_ignore_seq_new(Py_ssize_t size, PyArena
|
||||
*arena);
|
||||
|
||||
|
||||
enum _mod_kind {Module_kind=1, Interactive_kind=2, Expression_kind=3,
|
||||
FunctionType_kind=4};
|
||||
struct _mod {
|
||||
enum _mod_kind kind;
|
||||
union {
|
||||
struct {
|
||||
asdl_stmt_seq *body;
|
||||
asdl_type_ignore_seq *type_ignores;
|
||||
} Module;
|
||||
|
||||
struct {
|
||||
asdl_stmt_seq *body;
|
||||
} Interactive;
|
||||
|
||||
struct {
|
||||
expr_ty body;
|
||||
} Expression;
|
||||
|
||||
struct {
|
||||
asdl_expr_seq *argtypes;
|
||||
expr_ty returns;
|
||||
} FunctionType;
|
||||
|
||||
} v;
|
||||
};
|
||||
|
||||
enum _stmt_kind {FunctionDef_kind=1, AsyncFunctionDef_kind=2, ClassDef_kind=3,
|
||||
Return_kind=4, Delete_kind=5, Assign_kind=6,
|
||||
AugAssign_kind=7, AnnAssign_kind=8, For_kind=9,
|
||||
AsyncFor_kind=10, While_kind=11, If_kind=12, With_kind=13,
|
||||
AsyncWith_kind=14, Match_kind=15, Raise_kind=16, Try_kind=17,
|
||||
Assert_kind=18, Import_kind=19, ImportFrom_kind=20,
|
||||
Global_kind=21, Nonlocal_kind=22, Expr_kind=23, Pass_kind=24,
|
||||
Break_kind=25, Continue_kind=26};
|
||||
struct _stmt {
|
||||
enum _stmt_kind kind;
|
||||
union {
|
||||
struct {
|
||||
identifier name;
|
||||
arguments_ty args;
|
||||
asdl_stmt_seq *body;
|
||||
asdl_expr_seq *decorator_list;
|
||||
expr_ty returns;
|
||||
string type_comment;
|
||||
} FunctionDef;
|
||||
|
||||
struct {
|
||||
identifier name;
|
||||
arguments_ty args;
|
||||
asdl_stmt_seq *body;
|
||||
asdl_expr_seq *decorator_list;
|
||||
expr_ty returns;
|
||||
string type_comment;
|
||||
} AsyncFunctionDef;
|
||||
|
||||
struct {
|
||||
identifier name;
|
||||
asdl_expr_seq *bases;
|
||||
asdl_keyword_seq *keywords;
|
||||
asdl_stmt_seq *body;
|
||||
asdl_expr_seq *decorator_list;
|
||||
} ClassDef;
|
||||
|
||||
struct {
|
||||
expr_ty value;
|
||||
} Return;
|
||||
|
||||
struct {
|
||||
asdl_expr_seq *targets;
|
||||
} Delete;
|
||||
|
||||
struct {
|
||||
asdl_expr_seq *targets;
|
||||
expr_ty value;
|
||||
string type_comment;
|
||||
} Assign;
|
||||
|
||||
struct {
|
||||
expr_ty target;
|
||||
operator_ty op;
|
||||
expr_ty value;
|
||||
} AugAssign;
|
||||
|
||||
struct {
|
||||
expr_ty target;
|
||||
expr_ty annotation;
|
||||
expr_ty value;
|
||||
int simple;
|
||||
} AnnAssign;
|
||||
|
||||
struct {
|
||||
expr_ty target;
|
||||
expr_ty iter;
|
||||
asdl_stmt_seq *body;
|
||||
asdl_stmt_seq *orelse;
|
||||
string type_comment;
|
||||
} For;
|
||||
|
||||
struct {
|
||||
expr_ty target;
|
||||
expr_ty iter;
|
||||
asdl_stmt_seq *body;
|
||||
asdl_stmt_seq *orelse;
|
||||
string type_comment;
|
||||
} AsyncFor;
|
||||
|
||||
struct {
|
||||
expr_ty test;
|
||||
asdl_stmt_seq *body;
|
||||
asdl_stmt_seq *orelse;
|
||||
} While;
|
||||
|
||||
struct {
|
||||
expr_ty test;
|
||||
asdl_stmt_seq *body;
|
||||
asdl_stmt_seq *orelse;
|
||||
} If;
|
||||
|
||||
struct {
|
||||
asdl_withitem_seq *items;
|
||||
asdl_stmt_seq *body;
|
||||
string type_comment;
|
||||
} With;
|
||||
|
||||
struct {
|
||||
asdl_withitem_seq *items;
|
||||
asdl_stmt_seq *body;
|
||||
string type_comment;
|
||||
} AsyncWith;
|
||||
|
||||
struct {
|
||||
expr_ty subject;
|
||||
asdl_match_case_seq *cases;
|
||||
} Match;
|
||||
|
||||
struct {
|
||||
expr_ty exc;
|
||||
expr_ty cause;
|
||||
} Raise;
|
||||
|
||||
struct {
|
||||
asdl_stmt_seq *body;
|
||||
asdl_excepthandler_seq *handlers;
|
||||
asdl_stmt_seq *orelse;
|
||||
asdl_stmt_seq *finalbody;
|
||||
} Try;
|
||||
|
||||
struct {
|
||||
expr_ty test;
|
||||
expr_ty msg;
|
||||
} Assert;
|
||||
|
||||
struct {
|
||||
asdl_alias_seq *names;
|
||||
} Import;
|
||||
|
||||
struct {
|
||||
identifier module;
|
||||
asdl_alias_seq *names;
|
||||
int level;
|
||||
} ImportFrom;
|
||||
|
||||
struct {
|
||||
asdl_identifier_seq *names;
|
||||
} Global;
|
||||
|
||||
struct {
|
||||
asdl_identifier_seq *names;
|
||||
} Nonlocal;
|
||||
|
||||
struct {
|
||||
expr_ty value;
|
||||
} Expr;
|
||||
|
||||
} v;
|
||||
int lineno;
|
||||
int col_offset;
|
||||
int end_lineno;
|
||||
int end_col_offset;
|
||||
};
|
||||
|
||||
enum _expr_kind {BoolOp_kind=1, NamedExpr_kind=2, BinOp_kind=3, UnaryOp_kind=4,
|
||||
Lambda_kind=5, IfExp_kind=6, Dict_kind=7, Set_kind=8,
|
||||
ListComp_kind=9, SetComp_kind=10, DictComp_kind=11,
|
||||
GeneratorExp_kind=12, Await_kind=13, Yield_kind=14,
|
||||
YieldFrom_kind=15, Compare_kind=16, Call_kind=17,
|
||||
FormattedValue_kind=18, JoinedStr_kind=19, Constant_kind=20,
|
||||
Attribute_kind=21, Subscript_kind=22, Starred_kind=23,
|
||||
Name_kind=24, List_kind=25, Tuple_kind=26, Slice_kind=27};
|
||||
struct _expr {
|
||||
enum _expr_kind kind;
|
||||
union {
|
||||
struct {
|
||||
boolop_ty op;
|
||||
asdl_expr_seq *values;
|
||||
} BoolOp;
|
||||
|
||||
struct {
|
||||
expr_ty target;
|
||||
expr_ty value;
|
||||
} NamedExpr;
|
||||
|
||||
struct {
|
||||
expr_ty left;
|
||||
operator_ty op;
|
||||
expr_ty right;
|
||||
} BinOp;
|
||||
|
||||
struct {
|
||||
unaryop_ty op;
|
||||
expr_ty operand;
|
||||
} UnaryOp;
|
||||
|
||||
struct {
|
||||
arguments_ty args;
|
||||
expr_ty body;
|
||||
} Lambda;
|
||||
|
||||
struct {
|
||||
expr_ty test;
|
||||
expr_ty body;
|
||||
expr_ty orelse;
|
||||
} IfExp;
|
||||
|
||||
struct {
|
||||
asdl_expr_seq *keys;
|
||||
asdl_expr_seq *values;
|
||||
} Dict;
|
||||
|
||||
struct {
|
||||
asdl_expr_seq *elts;
|
||||
} Set;
|
||||
|
||||
struct {
|
||||
expr_ty elt;
|
||||
asdl_comprehension_seq *generators;
|
||||
} ListComp;
|
||||
|
||||
struct {
|
||||
expr_ty elt;
|
||||
asdl_comprehension_seq *generators;
|
||||
} SetComp;
|
||||
|
||||
struct {
|
||||
expr_ty key;
|
||||
expr_ty value;
|
||||
asdl_comprehension_seq *generators;
|
||||
} DictComp;
|
||||
|
||||
struct {
|
||||
expr_ty elt;
|
||||
asdl_comprehension_seq *generators;
|
||||
} GeneratorExp;
|
||||
|
||||
struct {
|
||||
expr_ty value;
|
||||
} Await;
|
||||
|
||||
struct {
|
||||
expr_ty value;
|
||||
} Yield;
|
||||
|
||||
struct {
|
||||
expr_ty value;
|
||||
} YieldFrom;
|
||||
|
||||
struct {
|
||||
expr_ty left;
|
||||
asdl_int_seq *ops;
|
||||
asdl_expr_seq *comparators;
|
||||
} Compare;
|
||||
|
||||
struct {
|
||||
expr_ty func;
|
||||
asdl_expr_seq *args;
|
||||
asdl_keyword_seq *keywords;
|
||||
} Call;
|
||||
|
||||
struct {
|
||||
expr_ty value;
|
||||
int conversion;
|
||||
expr_ty format_spec;
|
||||
} FormattedValue;
|
||||
|
||||
struct {
|
||||
asdl_expr_seq *values;
|
||||
} JoinedStr;
|
||||
|
||||
struct {
|
||||
constant value;
|
||||
string kind;
|
||||
} Constant;
|
||||
|
||||
struct {
|
||||
expr_ty value;
|
||||
identifier attr;
|
||||
expr_context_ty ctx;
|
||||
} Attribute;
|
||||
|
||||
struct {
|
||||
expr_ty value;
|
||||
expr_ty slice;
|
||||
expr_context_ty ctx;
|
||||
} Subscript;
|
||||
|
||||
struct {
|
||||
expr_ty value;
|
||||
expr_context_ty ctx;
|
||||
} Starred;
|
||||
|
||||
struct {
|
||||
identifier id;
|
||||
expr_context_ty ctx;
|
||||
} Name;
|
||||
|
||||
struct {
|
||||
asdl_expr_seq *elts;
|
||||
expr_context_ty ctx;
|
||||
} List;
|
||||
|
||||
struct {
|
||||
asdl_expr_seq *elts;
|
||||
expr_context_ty ctx;
|
||||
} Tuple;
|
||||
|
||||
struct {
|
||||
expr_ty lower;
|
||||
expr_ty upper;
|
||||
expr_ty step;
|
||||
} Slice;
|
||||
|
||||
} v;
|
||||
int lineno;
|
||||
int col_offset;
|
||||
int end_lineno;
|
||||
int end_col_offset;
|
||||
};
|
||||
|
||||
struct _comprehension {
|
||||
expr_ty target;
|
||||
expr_ty iter;
|
||||
asdl_expr_seq *ifs;
|
||||
int is_async;
|
||||
};
|
||||
|
||||
enum _excepthandler_kind {ExceptHandler_kind=1};
|
||||
struct _excepthandler {
|
||||
enum _excepthandler_kind kind;
|
||||
union {
|
||||
struct {
|
||||
expr_ty type;
|
||||
identifier name;
|
||||
asdl_stmt_seq *body;
|
||||
} ExceptHandler;
|
||||
|
||||
} v;
|
||||
int lineno;
|
||||
int col_offset;
|
||||
int end_lineno;
|
||||
int end_col_offset;
|
||||
};
|
||||
|
||||
struct _arguments {
|
||||
asdl_arg_seq *posonlyargs;
|
||||
asdl_arg_seq *args;
|
||||
arg_ty vararg;
|
||||
asdl_arg_seq *kwonlyargs;
|
||||
asdl_expr_seq *kw_defaults;
|
||||
arg_ty kwarg;
|
||||
asdl_expr_seq *defaults;
|
||||
};
|
||||
|
||||
struct _arg {
|
||||
identifier arg;
|
||||
expr_ty annotation;
|
||||
string type_comment;
|
||||
int lineno;
|
||||
int col_offset;
|
||||
int end_lineno;
|
||||
int end_col_offset;
|
||||
};
|
||||
|
||||
struct _keyword {
|
||||
identifier arg;
|
||||
expr_ty value;
|
||||
int lineno;
|
||||
int col_offset;
|
||||
int end_lineno;
|
||||
int end_col_offset;
|
||||
};
|
||||
|
||||
struct _alias {
|
||||
identifier name;
|
||||
identifier asname;
|
||||
int lineno;
|
||||
int col_offset;
|
||||
int end_lineno;
|
||||
int end_col_offset;
|
||||
};
|
||||
|
||||
struct _withitem {
|
||||
expr_ty context_expr;
|
||||
expr_ty optional_vars;
|
||||
};
|
||||
|
||||
struct _match_case {
|
||||
pattern_ty pattern;
|
||||
expr_ty guard;
|
||||
asdl_stmt_seq *body;
|
||||
};
|
||||
|
||||
enum _pattern_kind {MatchValue_kind=1, MatchSingleton_kind=2,
|
||||
MatchSequence_kind=3, MatchMapping_kind=4,
|
||||
MatchClass_kind=5, MatchStar_kind=6, MatchAs_kind=7,
|
||||
MatchOr_kind=8};
|
||||
struct _pattern {
|
||||
enum _pattern_kind kind;
|
||||
union {
|
||||
struct {
|
||||
expr_ty value;
|
||||
} MatchValue;
|
||||
|
||||
struct {
|
||||
constant value;
|
||||
} MatchSingleton;
|
||||
|
||||
struct {
|
||||
asdl_pattern_seq *patterns;
|
||||
} MatchSequence;
|
||||
|
||||
struct {
|
||||
asdl_expr_seq *keys;
|
||||
asdl_pattern_seq *patterns;
|
||||
identifier rest;
|
||||
} MatchMapping;
|
||||
|
||||
struct {
|
||||
expr_ty cls;
|
||||
asdl_pattern_seq *patterns;
|
||||
asdl_identifier_seq *kwd_attrs;
|
||||
asdl_pattern_seq *kwd_patterns;
|
||||
} MatchClass;
|
||||
|
||||
struct {
|
||||
identifier name;
|
||||
} MatchStar;
|
||||
|
||||
struct {
|
||||
pattern_ty pattern;
|
||||
identifier name;
|
||||
} MatchAs;
|
||||
|
||||
struct {
|
||||
asdl_pattern_seq *patterns;
|
||||
} MatchOr;
|
||||
|
||||
} v;
|
||||
int lineno;
|
||||
int col_offset;
|
||||
int end_lineno;
|
||||
int end_col_offset;
|
||||
};
|
||||
|
||||
enum _type_ignore_kind {TypeIgnore_kind=1};
|
||||
struct _type_ignore {
|
||||
enum _type_ignore_kind kind;
|
||||
union {
|
||||
struct {
|
||||
int lineno;
|
||||
string tag;
|
||||
} TypeIgnore;
|
||||
|
||||
} v;
|
||||
};
|
||||
|
||||
|
||||
// Note: these macros affect function definitions, not only call sites.
|
||||
mod_ty _PyAST_Module(asdl_stmt_seq * body, asdl_type_ignore_seq * type_ignores,
|
||||
PyArena *arena);
|
||||
mod_ty _PyAST_Interactive(asdl_stmt_seq * body, PyArena *arena);
|
||||
mod_ty _PyAST_Expression(expr_ty body, PyArena *arena);
|
||||
mod_ty _PyAST_FunctionType(asdl_expr_seq * argtypes, expr_ty returns, PyArena
|
||||
*arena);
|
||||
stmt_ty _PyAST_FunctionDef(identifier name, arguments_ty args, asdl_stmt_seq *
|
||||
body, asdl_expr_seq * decorator_list, expr_ty
|
||||
returns, string type_comment, int lineno, int
|
||||
col_offset, int end_lineno, int end_col_offset,
|
||||
PyArena *arena);
|
||||
stmt_ty _PyAST_AsyncFunctionDef(identifier name, arguments_ty args,
|
||||
asdl_stmt_seq * body, asdl_expr_seq *
|
||||
decorator_list, expr_ty returns, string
|
||||
type_comment, int lineno, int col_offset, int
|
||||
end_lineno, int end_col_offset, PyArena *arena);
|
||||
stmt_ty _PyAST_ClassDef(identifier name, asdl_expr_seq * bases,
|
||||
asdl_keyword_seq * keywords, asdl_stmt_seq * body,
|
||||
asdl_expr_seq * decorator_list, int lineno, int
|
||||
col_offset, int end_lineno, int end_col_offset, PyArena
|
||||
*arena);
|
||||
stmt_ty _PyAST_Return(expr_ty value, int lineno, int col_offset, int
|
||||
end_lineno, int end_col_offset, PyArena *arena);
|
||||
stmt_ty _PyAST_Delete(asdl_expr_seq * targets, int lineno, int col_offset, int
|
||||
end_lineno, int end_col_offset, PyArena *arena);
|
||||
stmt_ty _PyAST_Assign(asdl_expr_seq * targets, expr_ty value, string
|
||||
type_comment, int lineno, int col_offset, int end_lineno,
|
||||
int end_col_offset, PyArena *arena);
|
||||
stmt_ty _PyAST_AugAssign(expr_ty target, operator_ty op, expr_ty value, int
|
||||
lineno, int col_offset, int end_lineno, int
|
||||
end_col_offset, PyArena *arena);
|
||||
stmt_ty _PyAST_AnnAssign(expr_ty target, expr_ty annotation, expr_ty value, int
|
||||
simple, int lineno, int col_offset, int end_lineno,
|
||||
int end_col_offset, PyArena *arena);
|
||||
stmt_ty _PyAST_For(expr_ty target, expr_ty iter, asdl_stmt_seq * body,
|
||||
asdl_stmt_seq * orelse, string type_comment, int lineno, int
|
||||
col_offset, int end_lineno, int end_col_offset, PyArena
|
||||
*arena);
|
||||
stmt_ty _PyAST_AsyncFor(expr_ty target, expr_ty iter, asdl_stmt_seq * body,
|
||||
asdl_stmt_seq * orelse, string type_comment, int
|
||||
lineno, int col_offset, int end_lineno, int
|
||||
end_col_offset, PyArena *arena);
|
||||
stmt_ty _PyAST_While(expr_ty test, asdl_stmt_seq * body, asdl_stmt_seq *
|
||||
orelse, int lineno, int col_offset, int end_lineno, int
|
||||
end_col_offset, PyArena *arena);
|
||||
stmt_ty _PyAST_If(expr_ty test, asdl_stmt_seq * body, asdl_stmt_seq * orelse,
|
||||
int lineno, int col_offset, int end_lineno, int
|
||||
end_col_offset, PyArena *arena);
|
||||
stmt_ty _PyAST_With(asdl_withitem_seq * items, asdl_stmt_seq * body, string
|
||||
type_comment, int lineno, int col_offset, int end_lineno,
|
||||
int end_col_offset, PyArena *arena);
|
||||
stmt_ty _PyAST_AsyncWith(asdl_withitem_seq * items, asdl_stmt_seq * body,
|
||||
string type_comment, int lineno, int col_offset, int
|
||||
end_lineno, int end_col_offset, PyArena *arena);
|
||||
stmt_ty _PyAST_Match(expr_ty subject, asdl_match_case_seq * cases, int lineno,
|
||||
int col_offset, int end_lineno, int end_col_offset,
|
||||
PyArena *arena);
|
||||
stmt_ty _PyAST_Raise(expr_ty exc, expr_ty cause, int lineno, int col_offset,
|
||||
int end_lineno, int end_col_offset, PyArena *arena);
|
||||
stmt_ty _PyAST_Try(asdl_stmt_seq * body, asdl_excepthandler_seq * handlers,
|
||||
asdl_stmt_seq * orelse, asdl_stmt_seq * finalbody, int
|
||||
lineno, int col_offset, int end_lineno, int end_col_offset,
|
||||
PyArena *arena);
|
||||
stmt_ty _PyAST_Assert(expr_ty test, expr_ty msg, int lineno, int col_offset,
|
||||
int end_lineno, int end_col_offset, PyArena *arena);
|
||||
stmt_ty _PyAST_Import(asdl_alias_seq * names, int lineno, int col_offset, int
|
||||
end_lineno, int end_col_offset, PyArena *arena);
|
||||
stmt_ty _PyAST_ImportFrom(identifier module, asdl_alias_seq * names, int level,
|
||||
int lineno, int col_offset, int end_lineno, int
|
||||
end_col_offset, PyArena *arena);
|
||||
stmt_ty _PyAST_Global(asdl_identifier_seq * names, int lineno, int col_offset,
|
||||
int end_lineno, int end_col_offset, PyArena *arena);
|
||||
stmt_ty _PyAST_Nonlocal(asdl_identifier_seq * names, int lineno, int
|
||||
col_offset, int end_lineno, int end_col_offset, PyArena
|
||||
*arena);
|
||||
stmt_ty _PyAST_Expr(expr_ty value, int lineno, int col_offset, int end_lineno,
|
||||
int end_col_offset, PyArena *arena);
|
||||
stmt_ty _PyAST_Pass(int lineno, int col_offset, int end_lineno, int
|
||||
end_col_offset, PyArena *arena);
|
||||
stmt_ty _PyAST_Break(int lineno, int col_offset, int end_lineno, int
|
||||
end_col_offset, PyArena *arena);
|
||||
stmt_ty _PyAST_Continue(int lineno, int col_offset, int end_lineno, int
|
||||
end_col_offset, PyArena *arena);
|
||||
expr_ty _PyAST_BoolOp(boolop_ty op, asdl_expr_seq * values, int lineno, int
|
||||
col_offset, int end_lineno, int end_col_offset, PyArena
|
||||
*arena);
|
||||
expr_ty _PyAST_NamedExpr(expr_ty target, expr_ty value, int lineno, int
|
||||
col_offset, int end_lineno, int end_col_offset,
|
||||
PyArena *arena);
|
||||
expr_ty _PyAST_BinOp(expr_ty left, operator_ty op, expr_ty right, int lineno,
|
||||
int col_offset, int end_lineno, int end_col_offset,
|
||||
PyArena *arena);
|
||||
expr_ty _PyAST_UnaryOp(unaryop_ty op, expr_ty operand, int lineno, int
|
||||
col_offset, int end_lineno, int end_col_offset, PyArena
|
||||
*arena);
|
||||
expr_ty _PyAST_Lambda(arguments_ty args, expr_ty body, int lineno, int
|
||||
col_offset, int end_lineno, int end_col_offset, PyArena
|
||||
*arena);
|
||||
expr_ty _PyAST_IfExp(expr_ty test, expr_ty body, expr_ty orelse, int lineno,
|
||||
int col_offset, int end_lineno, int end_col_offset,
|
||||
PyArena *arena);
|
||||
expr_ty _PyAST_Dict(asdl_expr_seq * keys, asdl_expr_seq * values, int lineno,
|
||||
int col_offset, int end_lineno, int end_col_offset, PyArena
|
||||
*arena);
|
||||
expr_ty _PyAST_Set(asdl_expr_seq * elts, int lineno, int col_offset, int
|
||||
end_lineno, int end_col_offset, PyArena *arena);
|
||||
expr_ty _PyAST_ListComp(expr_ty elt, asdl_comprehension_seq * generators, int
|
||||
lineno, int col_offset, int end_lineno, int
|
||||
end_col_offset, PyArena *arena);
|
||||
expr_ty _PyAST_SetComp(expr_ty elt, asdl_comprehension_seq * generators, int
|
||||
lineno, int col_offset, int end_lineno, int
|
||||
end_col_offset, PyArena *arena);
|
||||
expr_ty _PyAST_DictComp(expr_ty key, expr_ty value, asdl_comprehension_seq *
|
||||
generators, int lineno, int col_offset, int end_lineno,
|
||||
int end_col_offset, PyArena *arena);
|
||||
expr_ty _PyAST_GeneratorExp(expr_ty elt, asdl_comprehension_seq * generators,
|
||||
int lineno, int col_offset, int end_lineno, int
|
||||
end_col_offset, PyArena *arena);
|
||||
expr_ty _PyAST_Await(expr_ty value, int lineno, int col_offset, int end_lineno,
|
||||
int end_col_offset, PyArena *arena);
|
||||
expr_ty _PyAST_Yield(expr_ty value, int lineno, int col_offset, int end_lineno,
|
||||
int end_col_offset, PyArena *arena);
|
||||
expr_ty _PyAST_YieldFrom(expr_ty value, int lineno, int col_offset, int
|
||||
end_lineno, int end_col_offset, PyArena *arena);
|
||||
expr_ty _PyAST_Compare(expr_ty left, asdl_int_seq * ops, asdl_expr_seq *
|
||||
comparators, int lineno, int col_offset, int end_lineno,
|
||||
int end_col_offset, PyArena *arena);
|
||||
expr_ty _PyAST_Call(expr_ty func, asdl_expr_seq * args, asdl_keyword_seq *
|
||||
keywords, int lineno, int col_offset, int end_lineno, int
|
||||
end_col_offset, PyArena *arena);
|
||||
expr_ty _PyAST_FormattedValue(expr_ty value, int conversion, expr_ty
|
||||
format_spec, int lineno, int col_offset, int
|
||||
end_lineno, int end_col_offset, PyArena *arena);
|
||||
expr_ty _PyAST_JoinedStr(asdl_expr_seq * values, int lineno, int col_offset,
|
||||
int end_lineno, int end_col_offset, PyArena *arena);
|
||||
expr_ty _PyAST_Constant(constant value, string kind, int lineno, int
|
||||
col_offset, int end_lineno, int end_col_offset, PyArena
|
||||
*arena);
|
||||
expr_ty _PyAST_Attribute(expr_ty value, identifier attr, expr_context_ty ctx,
|
||||
int lineno, int col_offset, int end_lineno, int
|
||||
end_col_offset, PyArena *arena);
|
||||
expr_ty _PyAST_Subscript(expr_ty value, expr_ty slice, expr_context_ty ctx, int
|
||||
lineno, int col_offset, int end_lineno, int
|
||||
end_col_offset, PyArena *arena);
|
||||
expr_ty _PyAST_Starred(expr_ty value, expr_context_ty ctx, int lineno, int
|
||||
col_offset, int end_lineno, int end_col_offset, PyArena
|
||||
*arena);
|
||||
expr_ty _PyAST_Name(identifier id, expr_context_ty ctx, int lineno, int
|
||||
col_offset, int end_lineno, int end_col_offset, PyArena
|
||||
*arena);
|
||||
expr_ty _PyAST_List(asdl_expr_seq * elts, expr_context_ty ctx, int lineno, int
|
||||
col_offset, int end_lineno, int end_col_offset, PyArena
|
||||
*arena);
|
||||
expr_ty _PyAST_Tuple(asdl_expr_seq * elts, expr_context_ty ctx, int lineno, int
|
||||
col_offset, int end_lineno, int end_col_offset, PyArena
|
||||
*arena);
|
||||
expr_ty _PyAST_Slice(expr_ty lower, expr_ty upper, expr_ty step, int lineno,
|
||||
int col_offset, int end_lineno, int end_col_offset,
|
||||
PyArena *arena);
|
||||
comprehension_ty _PyAST_comprehension(expr_ty target, expr_ty iter,
|
||||
asdl_expr_seq * ifs, int is_async,
|
||||
PyArena *arena);
|
||||
excepthandler_ty _PyAST_ExceptHandler(expr_ty type, identifier name,
|
||||
asdl_stmt_seq * body, int lineno, int
|
||||
col_offset, int end_lineno, int
|
||||
end_col_offset, PyArena *arena);
|
||||
arguments_ty _PyAST_arguments(asdl_arg_seq * posonlyargs, asdl_arg_seq * args,
|
||||
arg_ty vararg, asdl_arg_seq * kwonlyargs,
|
||||
asdl_expr_seq * kw_defaults, arg_ty kwarg,
|
||||
asdl_expr_seq * defaults, PyArena *arena);
|
||||
arg_ty _PyAST_arg(identifier arg, expr_ty annotation, string type_comment, int
|
||||
lineno, int col_offset, int end_lineno, int end_col_offset,
|
||||
PyArena *arena);
|
||||
keyword_ty _PyAST_keyword(identifier arg, expr_ty value, int lineno, int
|
||||
col_offset, int end_lineno, int end_col_offset,
|
||||
PyArena *arena);
|
||||
alias_ty _PyAST_alias(identifier name, identifier asname, int lineno, int
|
||||
col_offset, int end_lineno, int end_col_offset, PyArena
|
||||
*arena);
|
||||
withitem_ty _PyAST_withitem(expr_ty context_expr, expr_ty optional_vars,
|
||||
PyArena *arena);
|
||||
match_case_ty _PyAST_match_case(pattern_ty pattern, expr_ty guard,
|
||||
asdl_stmt_seq * body, PyArena *arena);
|
||||
pattern_ty _PyAST_MatchValue(expr_ty value, int lineno, int col_offset, int
|
||||
end_lineno, int end_col_offset, PyArena *arena);
|
||||
pattern_ty _PyAST_MatchSingleton(constant value, int lineno, int col_offset,
|
||||
int end_lineno, int end_col_offset, PyArena
|
||||
*arena);
|
||||
pattern_ty _PyAST_MatchSequence(asdl_pattern_seq * patterns, int lineno, int
|
||||
col_offset, int end_lineno, int end_col_offset,
|
||||
PyArena *arena);
|
||||
pattern_ty _PyAST_MatchMapping(asdl_expr_seq * keys, asdl_pattern_seq *
|
||||
patterns, identifier rest, int lineno, int
|
||||
col_offset, int end_lineno, int end_col_offset,
|
||||
PyArena *arena);
|
||||
pattern_ty _PyAST_MatchClass(expr_ty cls, asdl_pattern_seq * patterns,
|
||||
asdl_identifier_seq * kwd_attrs, asdl_pattern_seq
|
||||
* kwd_patterns, int lineno, int col_offset, int
|
||||
end_lineno, int end_col_offset, PyArena *arena);
|
||||
pattern_ty _PyAST_MatchStar(identifier name, int lineno, int col_offset, int
|
||||
end_lineno, int end_col_offset, PyArena *arena);
|
||||
pattern_ty _PyAST_MatchAs(pattern_ty pattern, identifier name, int lineno, int
|
||||
col_offset, int end_lineno, int end_col_offset,
|
||||
PyArena *arena);
|
||||
pattern_ty _PyAST_MatchOr(asdl_pattern_seq * patterns, int lineno, int
|
||||
col_offset, int end_lineno, int end_col_offset,
|
||||
PyArena *arena);
|
||||
type_ignore_ty _PyAST_TypeIgnore(int lineno, string tag, PyArena *arena);
|
||||
|
||||
|
||||
PyObject* PyAST_mod2obj(mod_ty t);
|
||||
mod_ty PyAST_obj2mod(PyObject* ast, PyArena* arena, int mode);
|
||||
int PyAST_Check(PyObject* obj);
|
||||
|
||||
extern int _PyAST_Validate(mod_ty);
|
||||
|
||||
/* _PyAST_ExprAsUnicode is defined in ast_unparse.c */
|
||||
extern PyObject* _PyAST_ExprAsUnicode(expr_ty);
|
||||
|
||||
/* Return the borrowed reference to the first literal string in the
|
||||
sequence of statements or NULL if it doesn't start from a literal string.
|
||||
Doesn't set exception. */
|
||||
extern PyObject* _PyAST_GetDocString(asdl_stmt_seq *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* !Py_INTERNAL_AST_H */
|
||||
@@ -0,0 +1,255 @@
|
||||
// File automatically generated by Parser/asdl_c.py.
|
||||
|
||||
#ifndef Py_INTERNAL_AST_STATE_H
|
||||
#define Py_INTERNAL_AST_STATE_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef Py_BUILD_CORE
|
||||
# error "this header requires Py_BUILD_CORE define"
|
||||
#endif
|
||||
|
||||
struct ast_state {
|
||||
int initialized;
|
||||
PyObject *AST_type;
|
||||
PyObject *Add_singleton;
|
||||
PyObject *Add_type;
|
||||
PyObject *And_singleton;
|
||||
PyObject *And_type;
|
||||
PyObject *AnnAssign_type;
|
||||
PyObject *Assert_type;
|
||||
PyObject *Assign_type;
|
||||
PyObject *AsyncFor_type;
|
||||
PyObject *AsyncFunctionDef_type;
|
||||
PyObject *AsyncWith_type;
|
||||
PyObject *Attribute_type;
|
||||
PyObject *AugAssign_type;
|
||||
PyObject *Await_type;
|
||||
PyObject *BinOp_type;
|
||||
PyObject *BitAnd_singleton;
|
||||
PyObject *BitAnd_type;
|
||||
PyObject *BitOr_singleton;
|
||||
PyObject *BitOr_type;
|
||||
PyObject *BitXor_singleton;
|
||||
PyObject *BitXor_type;
|
||||
PyObject *BoolOp_type;
|
||||
PyObject *Break_type;
|
||||
PyObject *Call_type;
|
||||
PyObject *ClassDef_type;
|
||||
PyObject *Compare_type;
|
||||
PyObject *Constant_type;
|
||||
PyObject *Continue_type;
|
||||
PyObject *Del_singleton;
|
||||
PyObject *Del_type;
|
||||
PyObject *Delete_type;
|
||||
PyObject *DictComp_type;
|
||||
PyObject *Dict_type;
|
||||
PyObject *Div_singleton;
|
||||
PyObject *Div_type;
|
||||
PyObject *Eq_singleton;
|
||||
PyObject *Eq_type;
|
||||
PyObject *ExceptHandler_type;
|
||||
PyObject *Expr_type;
|
||||
PyObject *Expression_type;
|
||||
PyObject *FloorDiv_singleton;
|
||||
PyObject *FloorDiv_type;
|
||||
PyObject *For_type;
|
||||
PyObject *FormattedValue_type;
|
||||
PyObject *FunctionDef_type;
|
||||
PyObject *FunctionType_type;
|
||||
PyObject *GeneratorExp_type;
|
||||
PyObject *Global_type;
|
||||
PyObject *GtE_singleton;
|
||||
PyObject *GtE_type;
|
||||
PyObject *Gt_singleton;
|
||||
PyObject *Gt_type;
|
||||
PyObject *IfExp_type;
|
||||
PyObject *If_type;
|
||||
PyObject *ImportFrom_type;
|
||||
PyObject *Import_type;
|
||||
PyObject *In_singleton;
|
||||
PyObject *In_type;
|
||||
PyObject *Interactive_type;
|
||||
PyObject *Invert_singleton;
|
||||
PyObject *Invert_type;
|
||||
PyObject *IsNot_singleton;
|
||||
PyObject *IsNot_type;
|
||||
PyObject *Is_singleton;
|
||||
PyObject *Is_type;
|
||||
PyObject *JoinedStr_type;
|
||||
PyObject *LShift_singleton;
|
||||
PyObject *LShift_type;
|
||||
PyObject *Lambda_type;
|
||||
PyObject *ListComp_type;
|
||||
PyObject *List_type;
|
||||
PyObject *Load_singleton;
|
||||
PyObject *Load_type;
|
||||
PyObject *LtE_singleton;
|
||||
PyObject *LtE_type;
|
||||
PyObject *Lt_singleton;
|
||||
PyObject *Lt_type;
|
||||
PyObject *MatMult_singleton;
|
||||
PyObject *MatMult_type;
|
||||
PyObject *MatchAs_type;
|
||||
PyObject *MatchClass_type;
|
||||
PyObject *MatchMapping_type;
|
||||
PyObject *MatchOr_type;
|
||||
PyObject *MatchSequence_type;
|
||||
PyObject *MatchSingleton_type;
|
||||
PyObject *MatchStar_type;
|
||||
PyObject *MatchValue_type;
|
||||
PyObject *Match_type;
|
||||
PyObject *Mod_singleton;
|
||||
PyObject *Mod_type;
|
||||
PyObject *Module_type;
|
||||
PyObject *Mult_singleton;
|
||||
PyObject *Mult_type;
|
||||
PyObject *Name_type;
|
||||
PyObject *NamedExpr_type;
|
||||
PyObject *Nonlocal_type;
|
||||
PyObject *NotEq_singleton;
|
||||
PyObject *NotEq_type;
|
||||
PyObject *NotIn_singleton;
|
||||
PyObject *NotIn_type;
|
||||
PyObject *Not_singleton;
|
||||
PyObject *Not_type;
|
||||
PyObject *Or_singleton;
|
||||
PyObject *Or_type;
|
||||
PyObject *Pass_type;
|
||||
PyObject *Pow_singleton;
|
||||
PyObject *Pow_type;
|
||||
PyObject *RShift_singleton;
|
||||
PyObject *RShift_type;
|
||||
PyObject *Raise_type;
|
||||
PyObject *Return_type;
|
||||
PyObject *SetComp_type;
|
||||
PyObject *Set_type;
|
||||
PyObject *Slice_type;
|
||||
PyObject *Starred_type;
|
||||
PyObject *Store_singleton;
|
||||
PyObject *Store_type;
|
||||
PyObject *Sub_singleton;
|
||||
PyObject *Sub_type;
|
||||
PyObject *Subscript_type;
|
||||
PyObject *Try_type;
|
||||
PyObject *Tuple_type;
|
||||
PyObject *TypeIgnore_type;
|
||||
PyObject *UAdd_singleton;
|
||||
PyObject *UAdd_type;
|
||||
PyObject *USub_singleton;
|
||||
PyObject *USub_type;
|
||||
PyObject *UnaryOp_type;
|
||||
PyObject *While_type;
|
||||
PyObject *With_type;
|
||||
PyObject *YieldFrom_type;
|
||||
PyObject *Yield_type;
|
||||
PyObject *__dict__;
|
||||
PyObject *__doc__;
|
||||
PyObject *__match_args__;
|
||||
PyObject *__module__;
|
||||
PyObject *_attributes;
|
||||
PyObject *_fields;
|
||||
PyObject *alias_type;
|
||||
PyObject *annotation;
|
||||
PyObject *arg;
|
||||
PyObject *arg_type;
|
||||
PyObject *args;
|
||||
PyObject *argtypes;
|
||||
PyObject *arguments_type;
|
||||
PyObject *asname;
|
||||
PyObject *ast;
|
||||
PyObject *attr;
|
||||
PyObject *bases;
|
||||
PyObject *body;
|
||||
PyObject *boolop_type;
|
||||
PyObject *cases;
|
||||
PyObject *cause;
|
||||
PyObject *cls;
|
||||
PyObject *cmpop_type;
|
||||
PyObject *col_offset;
|
||||
PyObject *comparators;
|
||||
PyObject *comprehension_type;
|
||||
PyObject *context_expr;
|
||||
PyObject *conversion;
|
||||
PyObject *ctx;
|
||||
PyObject *decorator_list;
|
||||
PyObject *defaults;
|
||||
PyObject *elt;
|
||||
PyObject *elts;
|
||||
PyObject *end_col_offset;
|
||||
PyObject *end_lineno;
|
||||
PyObject *exc;
|
||||
PyObject *excepthandler_type;
|
||||
PyObject *expr_context_type;
|
||||
PyObject *expr_type;
|
||||
PyObject *finalbody;
|
||||
PyObject *format_spec;
|
||||
PyObject *func;
|
||||
PyObject *generators;
|
||||
PyObject *guard;
|
||||
PyObject *handlers;
|
||||
PyObject *id;
|
||||
PyObject *ifs;
|
||||
PyObject *is_async;
|
||||
PyObject *items;
|
||||
PyObject *iter;
|
||||
PyObject *key;
|
||||
PyObject *keys;
|
||||
PyObject *keyword_type;
|
||||
PyObject *keywords;
|
||||
PyObject *kind;
|
||||
PyObject *kw_defaults;
|
||||
PyObject *kwarg;
|
||||
PyObject *kwd_attrs;
|
||||
PyObject *kwd_patterns;
|
||||
PyObject *kwonlyargs;
|
||||
PyObject *left;
|
||||
PyObject *level;
|
||||
PyObject *lineno;
|
||||
PyObject *lower;
|
||||
PyObject *match_case_type;
|
||||
PyObject *mod_type;
|
||||
PyObject *module;
|
||||
PyObject *msg;
|
||||
PyObject *name;
|
||||
PyObject *names;
|
||||
PyObject *op;
|
||||
PyObject *operand;
|
||||
PyObject *operator_type;
|
||||
PyObject *ops;
|
||||
PyObject *optional_vars;
|
||||
PyObject *orelse;
|
||||
PyObject *pattern;
|
||||
PyObject *pattern_type;
|
||||
PyObject *patterns;
|
||||
PyObject *posonlyargs;
|
||||
PyObject *rest;
|
||||
PyObject *returns;
|
||||
PyObject *right;
|
||||
PyObject *simple;
|
||||
PyObject *slice;
|
||||
PyObject *step;
|
||||
PyObject *stmt_type;
|
||||
PyObject *subject;
|
||||
PyObject *tag;
|
||||
PyObject *target;
|
||||
PyObject *targets;
|
||||
PyObject *test;
|
||||
PyObject *type;
|
||||
PyObject *type_comment;
|
||||
PyObject *type_ignore_type;
|
||||
PyObject *type_ignores;
|
||||
PyObject *unaryop_type;
|
||||
PyObject *upper;
|
||||
PyObject *value;
|
||||
PyObject *values;
|
||||
PyObject *vararg;
|
||||
PyObject *withitem_type;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* !Py_INTERNAL_AST_STATE_H */
|
||||
|
||||
@@ -0,0 +1,557 @@
|
||||
#ifndef Py_ATOMIC_H
|
||||
#define Py_ATOMIC_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef Py_BUILD_CORE
|
||||
# error "this header requires Py_BUILD_CORE define"
|
||||
#endif
|
||||
|
||||
#include "dynamic_annotations.h" /* _Py_ANNOTATE_MEMORY_ORDER */
|
||||
#include "pyconfig.h"
|
||||
|
||||
#ifdef HAVE_STD_ATOMIC
|
||||
# include <stdatomic.h>
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#include <intrin.h>
|
||||
#if defined(_M_IX86) || defined(_M_X64)
|
||||
# include <immintrin.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* This is modeled after the atomics interface from C1x, according to
|
||||
* the draft at
|
||||
* http://www.open-std.org/JTC1/SC22/wg14/www/docs/n1425.pdf.
|
||||
* Operations and types are named the same except with a _Py_ prefix
|
||||
* and have the same semantics.
|
||||
*
|
||||
* Beware, the implementations here are deep magic.
|
||||
*/
|
||||
|
||||
#if defined(HAVE_STD_ATOMIC)
|
||||
|
||||
typedef enum _Py_memory_order {
|
||||
_Py_memory_order_relaxed = memory_order_relaxed,
|
||||
_Py_memory_order_acquire = memory_order_acquire,
|
||||
_Py_memory_order_release = memory_order_release,
|
||||
_Py_memory_order_acq_rel = memory_order_acq_rel,
|
||||
_Py_memory_order_seq_cst = memory_order_seq_cst
|
||||
} _Py_memory_order;
|
||||
|
||||
typedef struct _Py_atomic_address {
|
||||
atomic_uintptr_t _value;
|
||||
} _Py_atomic_address;
|
||||
|
||||
typedef struct _Py_atomic_int {
|
||||
atomic_int _value;
|
||||
} _Py_atomic_int;
|
||||
|
||||
#define _Py_atomic_signal_fence(/*memory_order*/ ORDER) \
|
||||
atomic_signal_fence(ORDER)
|
||||
|
||||
#define _Py_atomic_thread_fence(/*memory_order*/ ORDER) \
|
||||
atomic_thread_fence(ORDER)
|
||||
|
||||
#define _Py_atomic_store_explicit(ATOMIC_VAL, NEW_VAL, ORDER) \
|
||||
atomic_store_explicit(&((ATOMIC_VAL)->_value), NEW_VAL, ORDER)
|
||||
|
||||
#define _Py_atomic_load_explicit(ATOMIC_VAL, ORDER) \
|
||||
atomic_load_explicit(&((ATOMIC_VAL)->_value), ORDER)
|
||||
|
||||
// Use builtin atomic operations in GCC >= 4.7 and clang
|
||||
#elif defined(HAVE_BUILTIN_ATOMIC)
|
||||
|
||||
typedef enum _Py_memory_order {
|
||||
_Py_memory_order_relaxed = __ATOMIC_RELAXED,
|
||||
_Py_memory_order_acquire = __ATOMIC_ACQUIRE,
|
||||
_Py_memory_order_release = __ATOMIC_RELEASE,
|
||||
_Py_memory_order_acq_rel = __ATOMIC_ACQ_REL,
|
||||
_Py_memory_order_seq_cst = __ATOMIC_SEQ_CST
|
||||
} _Py_memory_order;
|
||||
|
||||
typedef struct _Py_atomic_address {
|
||||
uintptr_t _value;
|
||||
} _Py_atomic_address;
|
||||
|
||||
typedef struct _Py_atomic_int {
|
||||
int _value;
|
||||
} _Py_atomic_int;
|
||||
|
||||
#define _Py_atomic_signal_fence(/*memory_order*/ ORDER) \
|
||||
__atomic_signal_fence(ORDER)
|
||||
|
||||
#define _Py_atomic_thread_fence(/*memory_order*/ ORDER) \
|
||||
__atomic_thread_fence(ORDER)
|
||||
|
||||
#define _Py_atomic_store_explicit(ATOMIC_VAL, NEW_VAL, ORDER) \
|
||||
(assert((ORDER) == __ATOMIC_RELAXED \
|
||||
|| (ORDER) == __ATOMIC_SEQ_CST \
|
||||
|| (ORDER) == __ATOMIC_RELEASE), \
|
||||
__atomic_store_n(&((ATOMIC_VAL)->_value), NEW_VAL, ORDER))
|
||||
|
||||
#define _Py_atomic_load_explicit(ATOMIC_VAL, ORDER) \
|
||||
(assert((ORDER) == __ATOMIC_RELAXED \
|
||||
|| (ORDER) == __ATOMIC_SEQ_CST \
|
||||
|| (ORDER) == __ATOMIC_ACQUIRE \
|
||||
|| (ORDER) == __ATOMIC_CONSUME), \
|
||||
__atomic_load_n(&((ATOMIC_VAL)->_value), ORDER))
|
||||
|
||||
/* Only support GCC (for expression statements) and x86 (for simple
|
||||
* atomic semantics) and MSVC x86/x64/ARM */
|
||||
#elif defined(__GNUC__) && (defined(__i386__) || defined(__amd64))
|
||||
typedef enum _Py_memory_order {
|
||||
_Py_memory_order_relaxed,
|
||||
_Py_memory_order_acquire,
|
||||
_Py_memory_order_release,
|
||||
_Py_memory_order_acq_rel,
|
||||
_Py_memory_order_seq_cst
|
||||
} _Py_memory_order;
|
||||
|
||||
typedef struct _Py_atomic_address {
|
||||
uintptr_t _value;
|
||||
} _Py_atomic_address;
|
||||
|
||||
typedef struct _Py_atomic_int {
|
||||
int _value;
|
||||
} _Py_atomic_int;
|
||||
|
||||
|
||||
static __inline__ void
|
||||
_Py_atomic_signal_fence(_Py_memory_order order)
|
||||
{
|
||||
if (order != _Py_memory_order_relaxed)
|
||||
__asm__ volatile("":::"memory");
|
||||
}
|
||||
|
||||
static __inline__ void
|
||||
_Py_atomic_thread_fence(_Py_memory_order order)
|
||||
{
|
||||
if (order != _Py_memory_order_relaxed)
|
||||
__asm__ volatile("mfence":::"memory");
|
||||
}
|
||||
|
||||
/* Tell the race checker about this operation's effects. */
|
||||
static __inline__ void
|
||||
_Py_ANNOTATE_MEMORY_ORDER(const volatile void *address, _Py_memory_order order)
|
||||
{
|
||||
(void)address; /* shut up -Wunused-parameter */
|
||||
switch(order) {
|
||||
case _Py_memory_order_release:
|
||||
case _Py_memory_order_acq_rel:
|
||||
case _Py_memory_order_seq_cst:
|
||||
_Py_ANNOTATE_HAPPENS_BEFORE(address);
|
||||
break;
|
||||
case _Py_memory_order_relaxed:
|
||||
case _Py_memory_order_acquire:
|
||||
break;
|
||||
}
|
||||
switch(order) {
|
||||
case _Py_memory_order_acquire:
|
||||
case _Py_memory_order_acq_rel:
|
||||
case _Py_memory_order_seq_cst:
|
||||
_Py_ANNOTATE_HAPPENS_AFTER(address);
|
||||
break;
|
||||
case _Py_memory_order_relaxed:
|
||||
case _Py_memory_order_release:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#define _Py_atomic_store_explicit(ATOMIC_VAL, NEW_VAL, ORDER) \
|
||||
__extension__ ({ \
|
||||
__typeof__(ATOMIC_VAL) atomic_val = ATOMIC_VAL; \
|
||||
__typeof__(atomic_val->_value) new_val = NEW_VAL;\
|
||||
volatile __typeof__(new_val) *volatile_data = &atomic_val->_value; \
|
||||
_Py_memory_order order = ORDER; \
|
||||
_Py_ANNOTATE_MEMORY_ORDER(atomic_val, order); \
|
||||
\
|
||||
/* Perform the operation. */ \
|
||||
_Py_ANNOTATE_IGNORE_WRITES_BEGIN(); \
|
||||
switch(order) { \
|
||||
case _Py_memory_order_release: \
|
||||
_Py_atomic_signal_fence(_Py_memory_order_release); \
|
||||
/* fallthrough */ \
|
||||
case _Py_memory_order_relaxed: \
|
||||
*volatile_data = new_val; \
|
||||
break; \
|
||||
\
|
||||
case _Py_memory_order_acquire: \
|
||||
case _Py_memory_order_acq_rel: \
|
||||
case _Py_memory_order_seq_cst: \
|
||||
__asm__ volatile("xchg %0, %1" \
|
||||
: "+r"(new_val) \
|
||||
: "m"(atomic_val->_value) \
|
||||
: "memory"); \
|
||||
break; \
|
||||
} \
|
||||
_Py_ANNOTATE_IGNORE_WRITES_END(); \
|
||||
})
|
||||
|
||||
#define _Py_atomic_load_explicit(ATOMIC_VAL, ORDER) \
|
||||
__extension__ ({ \
|
||||
__typeof__(ATOMIC_VAL) atomic_val = ATOMIC_VAL; \
|
||||
__typeof__(atomic_val->_value) result; \
|
||||
volatile __typeof__(result) *volatile_data = &atomic_val->_value; \
|
||||
_Py_memory_order order = ORDER; \
|
||||
_Py_ANNOTATE_MEMORY_ORDER(atomic_val, order); \
|
||||
\
|
||||
/* Perform the operation. */ \
|
||||
_Py_ANNOTATE_IGNORE_READS_BEGIN(); \
|
||||
switch(order) { \
|
||||
case _Py_memory_order_release: \
|
||||
case _Py_memory_order_acq_rel: \
|
||||
case _Py_memory_order_seq_cst: \
|
||||
/* Loads on x86 are not releases by default, so need a */ \
|
||||
/* thread fence. */ \
|
||||
_Py_atomic_thread_fence(_Py_memory_order_release); \
|
||||
break; \
|
||||
default: \
|
||||
/* No fence */ \
|
||||
break; \
|
||||
} \
|
||||
result = *volatile_data; \
|
||||
switch(order) { \
|
||||
case _Py_memory_order_acquire: \
|
||||
case _Py_memory_order_acq_rel: \
|
||||
case _Py_memory_order_seq_cst: \
|
||||
/* Loads on x86 are automatically acquire operations so */ \
|
||||
/* can get by with just a compiler fence. */ \
|
||||
_Py_atomic_signal_fence(_Py_memory_order_acquire); \
|
||||
break; \
|
||||
default: \
|
||||
/* No fence */ \
|
||||
break; \
|
||||
} \
|
||||
_Py_ANNOTATE_IGNORE_READS_END(); \
|
||||
result; \
|
||||
})
|
||||
|
||||
#elif defined(_MSC_VER)
|
||||
/* _Interlocked* functions provide a full memory barrier and are therefore
|
||||
enough for acq_rel and seq_cst. If the HLE variants aren't available
|
||||
in hardware they will fall back to a full memory barrier as well.
|
||||
|
||||
This might affect performance but likely only in some very specific and
|
||||
hard to measure scenario.
|
||||
*/
|
||||
#if defined(_M_IX86) || defined(_M_X64)
|
||||
typedef enum _Py_memory_order {
|
||||
_Py_memory_order_relaxed,
|
||||
_Py_memory_order_acquire,
|
||||
_Py_memory_order_release,
|
||||
_Py_memory_order_acq_rel,
|
||||
_Py_memory_order_seq_cst
|
||||
} _Py_memory_order;
|
||||
|
||||
typedef struct _Py_atomic_address {
|
||||
volatile uintptr_t _value;
|
||||
} _Py_atomic_address;
|
||||
|
||||
typedef struct _Py_atomic_int {
|
||||
volatile int _value;
|
||||
} _Py_atomic_int;
|
||||
|
||||
|
||||
#if defined(_M_X64)
|
||||
#define _Py_atomic_store_64bit(ATOMIC_VAL, NEW_VAL, ORDER) \
|
||||
switch (ORDER) { \
|
||||
case _Py_memory_order_acquire: \
|
||||
_InterlockedExchange64_HLEAcquire((__int64 volatile*)&((ATOMIC_VAL)->_value), (__int64)(NEW_VAL)); \
|
||||
break; \
|
||||
case _Py_memory_order_release: \
|
||||
_InterlockedExchange64_HLERelease((__int64 volatile*)&((ATOMIC_VAL)->_value), (__int64)(NEW_VAL)); \
|
||||
break; \
|
||||
default: \
|
||||
_InterlockedExchange64((__int64 volatile*)&((ATOMIC_VAL)->_value), (__int64)(NEW_VAL)); \
|
||||
break; \
|
||||
}
|
||||
#else
|
||||
#define _Py_atomic_store_64bit(ATOMIC_VAL, NEW_VAL, ORDER) ((void)0);
|
||||
#endif
|
||||
|
||||
#define _Py_atomic_store_32bit(ATOMIC_VAL, NEW_VAL, ORDER) \
|
||||
switch (ORDER) { \
|
||||
case _Py_memory_order_acquire: \
|
||||
_InterlockedExchange_HLEAcquire((volatile long*)&((ATOMIC_VAL)->_value), (int)(NEW_VAL)); \
|
||||
break; \
|
||||
case _Py_memory_order_release: \
|
||||
_InterlockedExchange_HLERelease((volatile long*)&((ATOMIC_VAL)->_value), (int)(NEW_VAL)); \
|
||||
break; \
|
||||
default: \
|
||||
_InterlockedExchange((volatile long*)&((ATOMIC_VAL)->_value), (int)(NEW_VAL)); \
|
||||
break; \
|
||||
}
|
||||
|
||||
#if defined(_M_X64)
|
||||
/* This has to be an intptr_t for now.
|
||||
gil_created() uses -1 as a sentinel value, if this returns
|
||||
a uintptr_t it will do an unsigned compare and crash
|
||||
*/
|
||||
inline intptr_t _Py_atomic_load_64bit_impl(volatile uintptr_t* value, int order) {
|
||||
__int64 old;
|
||||
switch (order) {
|
||||
case _Py_memory_order_acquire:
|
||||
{
|
||||
do {
|
||||
old = *value;
|
||||
} while(_InterlockedCompareExchange64_HLEAcquire((volatile __int64*)value, old, old) != old);
|
||||
break;
|
||||
}
|
||||
case _Py_memory_order_release:
|
||||
{
|
||||
do {
|
||||
old = *value;
|
||||
} while(_InterlockedCompareExchange64_HLERelease((volatile __int64*)value, old, old) != old);
|
||||
break;
|
||||
}
|
||||
case _Py_memory_order_relaxed:
|
||||
old = *value;
|
||||
break;
|
||||
default:
|
||||
{
|
||||
do {
|
||||
old = *value;
|
||||
} while(_InterlockedCompareExchange64((volatile __int64*)value, old, old) != old);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return old;
|
||||
}
|
||||
|
||||
#define _Py_atomic_load_64bit(ATOMIC_VAL, ORDER) \
|
||||
_Py_atomic_load_64bit_impl((volatile uintptr_t*)&((ATOMIC_VAL)->_value), (ORDER))
|
||||
|
||||
#else
|
||||
#define _Py_atomic_load_64bit(ATOMIC_VAL, ORDER) ((ATOMIC_VAL)->_value)
|
||||
#endif
|
||||
|
||||
inline int _Py_atomic_load_32bit_impl(volatile int* value, int order) {
|
||||
long old;
|
||||
switch (order) {
|
||||
case _Py_memory_order_acquire:
|
||||
{
|
||||
do {
|
||||
old = *value;
|
||||
} while(_InterlockedCompareExchange_HLEAcquire((volatile long*)value, old, old) != old);
|
||||
break;
|
||||
}
|
||||
case _Py_memory_order_release:
|
||||
{
|
||||
do {
|
||||
old = *value;
|
||||
} while(_InterlockedCompareExchange_HLERelease((volatile long*)value, old, old) != old);
|
||||
break;
|
||||
}
|
||||
case _Py_memory_order_relaxed:
|
||||
old = *value;
|
||||
break;
|
||||
default:
|
||||
{
|
||||
do {
|
||||
old = *value;
|
||||
} while(_InterlockedCompareExchange((volatile long*)value, old, old) != old);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return old;
|
||||
}
|
||||
|
||||
#define _Py_atomic_load_32bit(ATOMIC_VAL, ORDER) \
|
||||
_Py_atomic_load_32bit_impl((volatile int*)&((ATOMIC_VAL)->_value), (ORDER))
|
||||
|
||||
#define _Py_atomic_store_explicit(ATOMIC_VAL, NEW_VAL, ORDER) \
|
||||
if (sizeof((ATOMIC_VAL)->_value) == 8) { \
|
||||
_Py_atomic_store_64bit((ATOMIC_VAL), NEW_VAL, ORDER) } else { \
|
||||
_Py_atomic_store_32bit((ATOMIC_VAL), NEW_VAL, ORDER) }
|
||||
|
||||
#define _Py_atomic_load_explicit(ATOMIC_VAL, ORDER) \
|
||||
( \
|
||||
sizeof((ATOMIC_VAL)->_value) == 8 ? \
|
||||
_Py_atomic_load_64bit((ATOMIC_VAL), ORDER) : \
|
||||
_Py_atomic_load_32bit((ATOMIC_VAL), ORDER) \
|
||||
)
|
||||
#elif defined(_M_ARM) || defined(_M_ARM64)
|
||||
typedef enum _Py_memory_order {
|
||||
_Py_memory_order_relaxed,
|
||||
_Py_memory_order_acquire,
|
||||
_Py_memory_order_release,
|
||||
_Py_memory_order_acq_rel,
|
||||
_Py_memory_order_seq_cst
|
||||
} _Py_memory_order;
|
||||
|
||||
typedef struct _Py_atomic_address {
|
||||
volatile uintptr_t _value;
|
||||
} _Py_atomic_address;
|
||||
|
||||
typedef struct _Py_atomic_int {
|
||||
volatile int _value;
|
||||
} _Py_atomic_int;
|
||||
|
||||
|
||||
#if defined(_M_ARM64)
|
||||
#define _Py_atomic_store_64bit(ATOMIC_VAL, NEW_VAL, ORDER) \
|
||||
switch (ORDER) { \
|
||||
case _Py_memory_order_acquire: \
|
||||
_InterlockedExchange64_acq((__int64 volatile*)&((ATOMIC_VAL)->_value), (__int64)NEW_VAL); \
|
||||
break; \
|
||||
case _Py_memory_order_release: \
|
||||
_InterlockedExchange64_rel((__int64 volatile*)&((ATOMIC_VAL)->_value), (__int64)NEW_VAL); \
|
||||
break; \
|
||||
default: \
|
||||
_InterlockedExchange64((__int64 volatile*)&((ATOMIC_VAL)->_value), (__int64)NEW_VAL); \
|
||||
break; \
|
||||
}
|
||||
#else
|
||||
#define _Py_atomic_store_64bit(ATOMIC_VAL, NEW_VAL, ORDER) ((void)0);
|
||||
#endif
|
||||
|
||||
#define _Py_atomic_store_32bit(ATOMIC_VAL, NEW_VAL, ORDER) \
|
||||
switch (ORDER) { \
|
||||
case _Py_memory_order_acquire: \
|
||||
_InterlockedExchange_acq((volatile long*)&((ATOMIC_VAL)->_value), (int)NEW_VAL); \
|
||||
break; \
|
||||
case _Py_memory_order_release: \
|
||||
_InterlockedExchange_rel((volatile long*)&((ATOMIC_VAL)->_value), (int)NEW_VAL); \
|
||||
break; \
|
||||
default: \
|
||||
_InterlockedExchange((volatile long*)&((ATOMIC_VAL)->_value), (int)NEW_VAL); \
|
||||
break; \
|
||||
}
|
||||
|
||||
#if defined(_M_ARM64)
|
||||
/* This has to be an intptr_t for now.
|
||||
gil_created() uses -1 as a sentinel value, if this returns
|
||||
a uintptr_t it will do an unsigned compare and crash
|
||||
*/
|
||||
inline intptr_t _Py_atomic_load_64bit_impl(volatile uintptr_t* value, int order) {
|
||||
uintptr_t old;
|
||||
switch (order) {
|
||||
case _Py_memory_order_acquire:
|
||||
{
|
||||
do {
|
||||
old = *value;
|
||||
} while(_InterlockedCompareExchange64_acq(value, old, old) != old);
|
||||
break;
|
||||
}
|
||||
case _Py_memory_order_release:
|
||||
{
|
||||
do {
|
||||
old = *value;
|
||||
} while(_InterlockedCompareExchange64_rel(value, old, old) != old);
|
||||
break;
|
||||
}
|
||||
case _Py_memory_order_relaxed:
|
||||
old = *value;
|
||||
break;
|
||||
default:
|
||||
{
|
||||
do {
|
||||
old = *value;
|
||||
} while(_InterlockedCompareExchange64(value, old, old) != old);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return old;
|
||||
}
|
||||
|
||||
#define _Py_atomic_load_64bit(ATOMIC_VAL, ORDER) \
|
||||
_Py_atomic_load_64bit_impl((volatile uintptr_t*)&((ATOMIC_VAL)->_value), (ORDER))
|
||||
|
||||
#else
|
||||
#define _Py_atomic_load_64bit(ATOMIC_VAL, ORDER) ((ATOMIC_VAL)->_value)
|
||||
#endif
|
||||
|
||||
inline int _Py_atomic_load_32bit_impl(volatile int* value, int order) {
|
||||
int old;
|
||||
switch (order) {
|
||||
case _Py_memory_order_acquire:
|
||||
{
|
||||
do {
|
||||
old = *value;
|
||||
} while(_InterlockedCompareExchange_acq(value, old, old) != old);
|
||||
break;
|
||||
}
|
||||
case _Py_memory_order_release:
|
||||
{
|
||||
do {
|
||||
old = *value;
|
||||
} while(_InterlockedCompareExchange_rel(value, old, old) != old);
|
||||
break;
|
||||
}
|
||||
case _Py_memory_order_relaxed:
|
||||
old = *value;
|
||||
break;
|
||||
default:
|
||||
{
|
||||
do {
|
||||
old = *value;
|
||||
} while(_InterlockedCompareExchange(value, old, old) != old);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return old;
|
||||
}
|
||||
|
||||
#define _Py_atomic_load_32bit(ATOMIC_VAL, ORDER) \
|
||||
_Py_atomic_load_32bit_impl((volatile int*)&((ATOMIC_VAL)->_value), (ORDER))
|
||||
|
||||
#define _Py_atomic_store_explicit(ATOMIC_VAL, NEW_VAL, ORDER) \
|
||||
if (sizeof((ATOMIC_VAL)->_value) == 8) { \
|
||||
_Py_atomic_store_64bit((ATOMIC_VAL), (NEW_VAL), (ORDER)) } else { \
|
||||
_Py_atomic_store_32bit((ATOMIC_VAL), (NEW_VAL), (ORDER)) }
|
||||
|
||||
#define _Py_atomic_load_explicit(ATOMIC_VAL, ORDER) \
|
||||
( \
|
||||
sizeof((ATOMIC_VAL)->_value) == 8 ? \
|
||||
_Py_atomic_load_64bit((ATOMIC_VAL), (ORDER)) : \
|
||||
_Py_atomic_load_32bit((ATOMIC_VAL), (ORDER)) \
|
||||
)
|
||||
#endif
|
||||
#else /* !gcc x86 !_msc_ver */
|
||||
typedef enum _Py_memory_order {
|
||||
_Py_memory_order_relaxed,
|
||||
_Py_memory_order_acquire,
|
||||
_Py_memory_order_release,
|
||||
_Py_memory_order_acq_rel,
|
||||
_Py_memory_order_seq_cst
|
||||
} _Py_memory_order;
|
||||
|
||||
typedef struct _Py_atomic_address {
|
||||
uintptr_t _value;
|
||||
} _Py_atomic_address;
|
||||
|
||||
typedef struct _Py_atomic_int {
|
||||
int _value;
|
||||
} _Py_atomic_int;
|
||||
/* Fall back to other compilers and processors by assuming that simple
|
||||
volatile accesses are atomic. This is false, so people should port
|
||||
this. */
|
||||
#define _Py_atomic_signal_fence(/*memory_order*/ ORDER) ((void)0)
|
||||
#define _Py_atomic_thread_fence(/*memory_order*/ ORDER) ((void)0)
|
||||
#define _Py_atomic_store_explicit(ATOMIC_VAL, NEW_VAL, ORDER) \
|
||||
((ATOMIC_VAL)->_value = NEW_VAL)
|
||||
#define _Py_atomic_load_explicit(ATOMIC_VAL, ORDER) \
|
||||
((ATOMIC_VAL)->_value)
|
||||
#endif
|
||||
|
||||
/* Standardized shortcuts. */
|
||||
#define _Py_atomic_store(ATOMIC_VAL, NEW_VAL) \
|
||||
_Py_atomic_store_explicit((ATOMIC_VAL), (NEW_VAL), _Py_memory_order_seq_cst)
|
||||
#define _Py_atomic_load(ATOMIC_VAL) \
|
||||
_Py_atomic_load_explicit((ATOMIC_VAL), _Py_memory_order_seq_cst)
|
||||
|
||||
/* Python-local extensions */
|
||||
|
||||
#define _Py_atomic_store_relaxed(ATOMIC_VAL, NEW_VAL) \
|
||||
_Py_atomic_store_explicit((ATOMIC_VAL), (NEW_VAL), _Py_memory_order_relaxed)
|
||||
#define _Py_atomic_load_relaxed(ATOMIC_VAL) \
|
||||
_Py_atomic_load_explicit((ATOMIC_VAL), _Py_memory_order_relaxed)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* Py_ATOMIC_H */
|
||||
@@ -0,0 +1,94 @@
|
||||
/* Atomic functions: similar to pycore_atomic.h, but don't need
|
||||
to declare variables as atomic.
|
||||
|
||||
Py_ssize_t type:
|
||||
|
||||
* value = _Py_atomic_size_get(&var)
|
||||
* _Py_atomic_size_set(&var, value)
|
||||
|
||||
Use sequentially-consistent ordering (__ATOMIC_SEQ_CST memory order):
|
||||
enforce total ordering with all other atomic functions.
|
||||
*/
|
||||
#ifndef Py_ATOMIC_FUNC_H
|
||||
#define Py_ATOMIC_FUNC_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef Py_BUILD_CORE
|
||||
# error "this header requires Py_BUILD_CORE define"
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# include <intrin.h> // _InterlockedExchange()
|
||||
#endif
|
||||
|
||||
|
||||
// Use builtin atomic operations in GCC >= 4.7 and clang
|
||||
#ifdef HAVE_BUILTIN_ATOMIC
|
||||
|
||||
static inline Py_ssize_t _Py_atomic_size_get(Py_ssize_t *var)
|
||||
{
|
||||
return __atomic_load_n(var, __ATOMIC_SEQ_CST);
|
||||
}
|
||||
|
||||
static inline void _Py_atomic_size_set(Py_ssize_t *var, Py_ssize_t value)
|
||||
{
|
||||
__atomic_store_n(var, value, __ATOMIC_SEQ_CST);
|
||||
}
|
||||
|
||||
#elif defined(_MSC_VER)
|
||||
|
||||
static inline Py_ssize_t _Py_atomic_size_get(Py_ssize_t *var)
|
||||
{
|
||||
#if SIZEOF_VOID_P == 8
|
||||
Py_BUILD_ASSERT(sizeof(__int64) == sizeof(*var));
|
||||
volatile __int64 *volatile_var = (volatile __int64 *)var;
|
||||
__int64 old;
|
||||
do {
|
||||
old = *volatile_var;
|
||||
} while(_InterlockedCompareExchange64(volatile_var, old, old) != old);
|
||||
#else
|
||||
Py_BUILD_ASSERT(sizeof(long) == sizeof(*var));
|
||||
volatile long *volatile_var = (volatile long *)var;
|
||||
long old;
|
||||
do {
|
||||
old = *volatile_var;
|
||||
} while(_InterlockedCompareExchange(volatile_var, old, old) != old);
|
||||
#endif
|
||||
return old;
|
||||
}
|
||||
|
||||
static inline void _Py_atomic_size_set(Py_ssize_t *var, Py_ssize_t value)
|
||||
{
|
||||
#if SIZEOF_VOID_P == 8
|
||||
Py_BUILD_ASSERT(sizeof(__int64) == sizeof(*var));
|
||||
volatile __int64 *volatile_var = (volatile __int64 *)var;
|
||||
_InterlockedExchange64(volatile_var, value);
|
||||
#else
|
||||
Py_BUILD_ASSERT(sizeof(long) == sizeof(*var));
|
||||
volatile long *volatile_var = (volatile long *)var;
|
||||
_InterlockedExchange(volatile_var, value);
|
||||
#endif
|
||||
}
|
||||
|
||||
#else
|
||||
// Fallback implementation using volatile
|
||||
|
||||
static inline Py_ssize_t _Py_atomic_size_get(Py_ssize_t *var)
|
||||
{
|
||||
volatile Py_ssize_t *volatile_var = (volatile Py_ssize_t *)var;
|
||||
return *volatile_var;
|
||||
}
|
||||
|
||||
static inline void _Py_atomic_size_set(Py_ssize_t *var, Py_ssize_t value)
|
||||
{
|
||||
volatile Py_ssize_t *volatile_var = (volatile Py_ssize_t *)var;
|
||||
*volatile_var = value;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* Py_ATOMIC_FUNC_H */
|
||||
@@ -0,0 +1,176 @@
|
||||
/* Bit and bytes utilities.
|
||||
|
||||
Bytes swap functions, reverse order of bytes:
|
||||
|
||||
- _Py_bswap16(uint16_t)
|
||||
- _Py_bswap32(uint32_t)
|
||||
- _Py_bswap64(uint64_t)
|
||||
*/
|
||||
|
||||
#ifndef Py_INTERNAL_BITUTILS_H
|
||||
#define Py_INTERNAL_BITUTILS_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef Py_BUILD_CORE
|
||||
# error "this header requires Py_BUILD_CORE define"
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) \
|
||||
&& ((__GNUC__ >= 5) || (__GNUC__ == 4) && (__GNUC_MINOR__ >= 8))
|
||||
/* __builtin_bswap16() is available since GCC 4.8,
|
||||
__builtin_bswap32() is available since GCC 4.3,
|
||||
__builtin_bswap64() is available since GCC 4.3. */
|
||||
# define _PY_HAVE_BUILTIN_BSWAP
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
/* Get _byteswap_ushort(), _byteswap_ulong(), _byteswap_uint64() */
|
||||
# include <intrin.h>
|
||||
#endif
|
||||
|
||||
static inline uint16_t
|
||||
_Py_bswap16(uint16_t word)
|
||||
{
|
||||
#if defined(_PY_HAVE_BUILTIN_BSWAP) || _Py__has_builtin(__builtin_bswap16)
|
||||
return __builtin_bswap16(word);
|
||||
#elif defined(_MSC_VER)
|
||||
Py_BUILD_ASSERT(sizeof(word) == sizeof(unsigned short));
|
||||
return _byteswap_ushort(word);
|
||||
#else
|
||||
// Portable implementation which doesn't rely on circular bit shift
|
||||
return ( ((word & UINT16_C(0x00FF)) << 8)
|
||||
| ((word & UINT16_C(0xFF00)) >> 8));
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
_Py_bswap32(uint32_t word)
|
||||
{
|
||||
#if defined(_PY_HAVE_BUILTIN_BSWAP) || _Py__has_builtin(__builtin_bswap32)
|
||||
return __builtin_bswap32(word);
|
||||
#elif defined(_MSC_VER)
|
||||
Py_BUILD_ASSERT(sizeof(word) == sizeof(unsigned long));
|
||||
return _byteswap_ulong(word);
|
||||
#else
|
||||
// Portable implementation which doesn't rely on circular bit shift
|
||||
return ( ((word & UINT32_C(0x000000FF)) << 24)
|
||||
| ((word & UINT32_C(0x0000FF00)) << 8)
|
||||
| ((word & UINT32_C(0x00FF0000)) >> 8)
|
||||
| ((word & UINT32_C(0xFF000000)) >> 24));
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline uint64_t
|
||||
_Py_bswap64(uint64_t word)
|
||||
{
|
||||
#if defined(_PY_HAVE_BUILTIN_BSWAP) || _Py__has_builtin(__builtin_bswap64)
|
||||
return __builtin_bswap64(word);
|
||||
#elif defined(_MSC_VER)
|
||||
return _byteswap_uint64(word);
|
||||
#else
|
||||
// Portable implementation which doesn't rely on circular bit shift
|
||||
return ( ((word & UINT64_C(0x00000000000000FF)) << 56)
|
||||
| ((word & UINT64_C(0x000000000000FF00)) << 40)
|
||||
| ((word & UINT64_C(0x0000000000FF0000)) << 24)
|
||||
| ((word & UINT64_C(0x00000000FF000000)) << 8)
|
||||
| ((word & UINT64_C(0x000000FF00000000)) >> 8)
|
||||
| ((word & UINT64_C(0x0000FF0000000000)) >> 24)
|
||||
| ((word & UINT64_C(0x00FF000000000000)) >> 40)
|
||||
| ((word & UINT64_C(0xFF00000000000000)) >> 56));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// Population count: count the number of 1's in 'x'
|
||||
// (number of bits set to 1), also known as the hamming weight.
|
||||
//
|
||||
// Implementation note. CPUID is not used, to test if x86 POPCNT instruction
|
||||
// can be used, to keep the implementation simple. For example, Visual Studio
|
||||
// __popcnt() is not used this reason. The clang and GCC builtin function can
|
||||
// use the x86 POPCNT instruction if the target architecture has SSE4a or
|
||||
// newer.
|
||||
static inline int
|
||||
_Py_popcount32(uint32_t x)
|
||||
{
|
||||
#if (defined(__clang__) || defined(__GNUC__))
|
||||
|
||||
#if SIZEOF_INT >= 4
|
||||
Py_BUILD_ASSERT(sizeof(x) <= sizeof(unsigned int));
|
||||
return __builtin_popcount(x);
|
||||
#else
|
||||
// The C standard guarantees that unsigned long will always be big enough
|
||||
// to hold a uint32_t value without losing information.
|
||||
Py_BUILD_ASSERT(sizeof(x) <= sizeof(unsigned long));
|
||||
return __builtin_popcountl(x);
|
||||
#endif
|
||||
|
||||
#else
|
||||
// 32-bit SWAR (SIMD Within A Register) popcount
|
||||
|
||||
// Binary: 0 1 0 1 ...
|
||||
const uint32_t M1 = 0x55555555;
|
||||
// Binary: 00 11 00 11. ..
|
||||
const uint32_t M2 = 0x33333333;
|
||||
// Binary: 0000 1111 0000 1111 ...
|
||||
const uint32_t M4 = 0x0F0F0F0F;
|
||||
// 256**4 + 256**3 + 256**2 + 256**1
|
||||
const uint32_t SUM = 0x01010101;
|
||||
|
||||
// Put count of each 2 bits into those 2 bits
|
||||
x = x - ((x >> 1) & M1);
|
||||
// Put count of each 4 bits into those 4 bits
|
||||
x = (x & M2) + ((x >> 2) & M2);
|
||||
// Put count of each 8 bits into those 8 bits
|
||||
x = (x + (x >> 4)) & M4;
|
||||
// Sum of the 4 byte counts
|
||||
return (uint32_t)((uint64_t)x * (uint64_t)SUM) >> 24;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// Return the index of the most significant 1 bit in 'x'. This is the smallest
|
||||
// integer k such that x < 2**k. Equivalent to floor(log2(x)) + 1 for x != 0.
|
||||
static inline int
|
||||
_Py_bit_length(unsigned long x)
|
||||
{
|
||||
#if (defined(__clang__) || defined(__GNUC__))
|
||||
if (x != 0) {
|
||||
// __builtin_clzl() is available since GCC 3.4.
|
||||
// Undefined behavior for x == 0.
|
||||
return (int)sizeof(unsigned long) * 8 - __builtin_clzl(x);
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
#elif defined(_MSC_VER)
|
||||
// _BitScanReverse() is documented to search 32 bits.
|
||||
Py_BUILD_ASSERT(sizeof(unsigned long) <= 4);
|
||||
unsigned long msb;
|
||||
if (_BitScanReverse(&msb, x)) {
|
||||
return (int)msb + 1;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
const int BIT_LENGTH_TABLE[32] = {
|
||||
0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
|
||||
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
|
||||
};
|
||||
int msb = 0;
|
||||
while (x >= 32) {
|
||||
msb += 6;
|
||||
x >>= 6;
|
||||
}
|
||||
msb += BIT_LENGTH_TABLE[x];
|
||||
return msb;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* !Py_INTERNAL_BITUTILS_H */
|
||||
@@ -0,0 +1,317 @@
|
||||
/*
|
||||
_BlocksOutputBuffer is used to maintain an output buffer
|
||||
that has unpredictable size. Suitable for compression/decompression
|
||||
API (bz2/lzma/zlib) that has stream->next_out and stream->avail_out:
|
||||
|
||||
stream->next_out: point to the next output position.
|
||||
stream->avail_out: the number of available bytes left in the buffer.
|
||||
|
||||
It maintains a list of bytes object, so there is no overhead of resizing
|
||||
the buffer.
|
||||
|
||||
Usage:
|
||||
|
||||
1, Initialize the struct instance like this:
|
||||
_BlocksOutputBuffer buffer = {.list = NULL};
|
||||
Set .list to NULL for _BlocksOutputBuffer_OnError()
|
||||
|
||||
2, Initialize the buffer use one of these functions:
|
||||
_BlocksOutputBuffer_InitAndGrow()
|
||||
_BlocksOutputBuffer_InitWithSize()
|
||||
|
||||
3, If (avail_out == 0), grow the buffer:
|
||||
_BlocksOutputBuffer_Grow()
|
||||
|
||||
4, Get the current outputted data size:
|
||||
_BlocksOutputBuffer_GetDataSize()
|
||||
|
||||
5, Finish the buffer, and return a bytes object:
|
||||
_BlocksOutputBuffer_Finish()
|
||||
|
||||
6, Clean up the buffer when an error occurred:
|
||||
_BlocksOutputBuffer_OnError()
|
||||
*/
|
||||
|
||||
#ifndef Py_INTERNAL_BLOCKS_OUTPUT_BUFFER_H
|
||||
#define Py_INTERNAL_BLOCKS_OUTPUT_BUFFER_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "Python.h"
|
||||
|
||||
typedef struct {
|
||||
// List of bytes objects
|
||||
PyObject *list;
|
||||
// Number of whole allocated size
|
||||
Py_ssize_t allocated;
|
||||
// Max length of the buffer, negative number means unlimited length.
|
||||
Py_ssize_t max_length;
|
||||
} _BlocksOutputBuffer;
|
||||
|
||||
static const char unable_allocate_msg[] = "Unable to allocate output buffer.";
|
||||
|
||||
/* In 32-bit build, the max block size should <= INT32_MAX. */
|
||||
#define OUTPUT_BUFFER_MAX_BLOCK_SIZE (256*1024*1024)
|
||||
|
||||
/* Block size sequence */
|
||||
#define KB (1024)
|
||||
#define MB (1024*1024)
|
||||
static const Py_ssize_t BUFFER_BLOCK_SIZE[] =
|
||||
{ 32*KB, 64*KB, 256*KB, 1*MB, 4*MB, 8*MB, 16*MB, 16*MB,
|
||||
32*MB, 32*MB, 32*MB, 32*MB, 64*MB, 64*MB, 128*MB, 128*MB,
|
||||
OUTPUT_BUFFER_MAX_BLOCK_SIZE };
|
||||
#undef KB
|
||||
#undef MB
|
||||
|
||||
/* According to the block sizes defined by BUFFER_BLOCK_SIZE, the whole
|
||||
allocated size growth step is:
|
||||
1 32 KB +32 KB
|
||||
2 96 KB +64 KB
|
||||
3 352 KB +256 KB
|
||||
4 1.34 MB +1 MB
|
||||
5 5.34 MB +4 MB
|
||||
6 13.34 MB +8 MB
|
||||
7 29.34 MB +16 MB
|
||||
8 45.34 MB +16 MB
|
||||
9 77.34 MB +32 MB
|
||||
10 109.34 MB +32 MB
|
||||
11 141.34 MB +32 MB
|
||||
12 173.34 MB +32 MB
|
||||
13 237.34 MB +64 MB
|
||||
14 301.34 MB +64 MB
|
||||
15 429.34 MB +128 MB
|
||||
16 557.34 MB +128 MB
|
||||
17 813.34 MB +256 MB
|
||||
18 1069.34 MB +256 MB
|
||||
19 1325.34 MB +256 MB
|
||||
20 1581.34 MB +256 MB
|
||||
21 1837.34 MB +256 MB
|
||||
22 2093.34 MB +256 MB
|
||||
...
|
||||
*/
|
||||
|
||||
/* Initialize the buffer, and grow the buffer.
|
||||
|
||||
max_length: Max length of the buffer, -1 for unlimited length.
|
||||
|
||||
On success, return allocated size (>=0)
|
||||
On failure, return -1
|
||||
*/
|
||||
static inline Py_ssize_t
|
||||
_BlocksOutputBuffer_InitAndGrow(_BlocksOutputBuffer *buffer,
|
||||
const Py_ssize_t max_length,
|
||||
void **next_out)
|
||||
{
|
||||
PyObject *b;
|
||||
Py_ssize_t block_size;
|
||||
|
||||
// ensure .list was set to NULL
|
||||
assert(buffer->list == NULL);
|
||||
|
||||
// get block size
|
||||
if (0 <= max_length && max_length < BUFFER_BLOCK_SIZE[0]) {
|
||||
block_size = max_length;
|
||||
} else {
|
||||
block_size = BUFFER_BLOCK_SIZE[0];
|
||||
}
|
||||
|
||||
// the first block
|
||||
b = PyBytes_FromStringAndSize(NULL, block_size);
|
||||
if (b == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// create the list
|
||||
buffer->list = PyList_New(1);
|
||||
if (buffer->list == NULL) {
|
||||
Py_DECREF(b);
|
||||
return -1;
|
||||
}
|
||||
PyList_SET_ITEM(buffer->list, 0, b);
|
||||
|
||||
// set variables
|
||||
buffer->allocated = block_size;
|
||||
buffer->max_length = max_length;
|
||||
|
||||
*next_out = PyBytes_AS_STRING(b);
|
||||
return block_size;
|
||||
}
|
||||
|
||||
/* Initialize the buffer, with an initial size.
|
||||
|
||||
Check block size limit in the outer wrapper function. For example, some libs
|
||||
accept UINT32_MAX as the maximum block size, then init_size should <= it.
|
||||
|
||||
On success, return allocated size (>=0)
|
||||
On failure, return -1
|
||||
*/
|
||||
static inline Py_ssize_t
|
||||
_BlocksOutputBuffer_InitWithSize(_BlocksOutputBuffer *buffer,
|
||||
const Py_ssize_t init_size,
|
||||
void **next_out)
|
||||
{
|
||||
PyObject *b;
|
||||
|
||||
// ensure .list was set to NULL
|
||||
assert(buffer->list == NULL);
|
||||
|
||||
// the first block
|
||||
b = PyBytes_FromStringAndSize(NULL, init_size);
|
||||
if (b == NULL) {
|
||||
PyErr_SetString(PyExc_MemoryError, unable_allocate_msg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// create the list
|
||||
buffer->list = PyList_New(1);
|
||||
if (buffer->list == NULL) {
|
||||
Py_DECREF(b);
|
||||
return -1;
|
||||
}
|
||||
PyList_SET_ITEM(buffer->list, 0, b);
|
||||
|
||||
// set variables
|
||||
buffer->allocated = init_size;
|
||||
buffer->max_length = -1;
|
||||
|
||||
*next_out = PyBytes_AS_STRING(b);
|
||||
return init_size;
|
||||
}
|
||||
|
||||
/* Grow the buffer. The avail_out must be 0, please check it before calling.
|
||||
|
||||
On success, return allocated size (>=0)
|
||||
On failure, return -1
|
||||
*/
|
||||
static inline Py_ssize_t
|
||||
_BlocksOutputBuffer_Grow(_BlocksOutputBuffer *buffer,
|
||||
void **next_out,
|
||||
const Py_ssize_t avail_out)
|
||||
{
|
||||
PyObject *b;
|
||||
const Py_ssize_t list_len = Py_SIZE(buffer->list);
|
||||
Py_ssize_t block_size;
|
||||
|
||||
// ensure no gaps in the data
|
||||
if (avail_out != 0) {
|
||||
PyErr_SetString(PyExc_SystemError,
|
||||
"avail_out is non-zero in _BlocksOutputBuffer_Grow().");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// get block size
|
||||
if (list_len < (Py_ssize_t) Py_ARRAY_LENGTH(BUFFER_BLOCK_SIZE)) {
|
||||
block_size = BUFFER_BLOCK_SIZE[list_len];
|
||||
} else {
|
||||
block_size = BUFFER_BLOCK_SIZE[Py_ARRAY_LENGTH(BUFFER_BLOCK_SIZE) - 1];
|
||||
}
|
||||
|
||||
// check max_length
|
||||
if (buffer->max_length >= 0) {
|
||||
// if (rest == 0), should not grow the buffer.
|
||||
Py_ssize_t rest = buffer->max_length - buffer->allocated;
|
||||
assert(rest > 0);
|
||||
|
||||
// block_size of the last block
|
||||
if (block_size > rest) {
|
||||
block_size = rest;
|
||||
}
|
||||
}
|
||||
|
||||
// check buffer->allocated overflow
|
||||
if (block_size > PY_SSIZE_T_MAX - buffer->allocated) {
|
||||
PyErr_SetString(PyExc_MemoryError, unable_allocate_msg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// create the block
|
||||
b = PyBytes_FromStringAndSize(NULL, block_size);
|
||||
if (b == NULL) {
|
||||
PyErr_SetString(PyExc_MemoryError, unable_allocate_msg);
|
||||
return -1;
|
||||
}
|
||||
if (PyList_Append(buffer->list, b) < 0) {
|
||||
Py_DECREF(b);
|
||||
return -1;
|
||||
}
|
||||
Py_DECREF(b);
|
||||
|
||||
// set variables
|
||||
buffer->allocated += block_size;
|
||||
|
||||
*next_out = PyBytes_AS_STRING(b);
|
||||
return block_size;
|
||||
}
|
||||
|
||||
/* Return the current outputted data size. */
|
||||
static inline Py_ssize_t
|
||||
_BlocksOutputBuffer_GetDataSize(_BlocksOutputBuffer *buffer,
|
||||
const Py_ssize_t avail_out)
|
||||
{
|
||||
return buffer->allocated - avail_out;
|
||||
}
|
||||
|
||||
/* Finish the buffer.
|
||||
|
||||
Return a bytes object on success
|
||||
Return NULL on failure
|
||||
*/
|
||||
static inline PyObject *
|
||||
_BlocksOutputBuffer_Finish(_BlocksOutputBuffer *buffer,
|
||||
const Py_ssize_t avail_out)
|
||||
{
|
||||
PyObject *result, *block;
|
||||
const Py_ssize_t list_len = Py_SIZE(buffer->list);
|
||||
|
||||
// fast path for single block
|
||||
if ((list_len == 1 && avail_out == 0) ||
|
||||
(list_len == 2 && Py_SIZE(PyList_GET_ITEM(buffer->list, 1)) == avail_out))
|
||||
{
|
||||
block = PyList_GET_ITEM(buffer->list, 0);
|
||||
Py_INCREF(block);
|
||||
|
||||
Py_CLEAR(buffer->list);
|
||||
return block;
|
||||
}
|
||||
|
||||
// final bytes object
|
||||
result = PyBytes_FromStringAndSize(NULL, buffer->allocated - avail_out);
|
||||
if (result == NULL) {
|
||||
PyErr_SetString(PyExc_MemoryError, unable_allocate_msg);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// memory copy
|
||||
if (list_len > 0) {
|
||||
char *posi = PyBytes_AS_STRING(result);
|
||||
|
||||
// blocks except the last one
|
||||
Py_ssize_t i = 0;
|
||||
for (; i < list_len-1; i++) {
|
||||
block = PyList_GET_ITEM(buffer->list, i);
|
||||
memcpy(posi, PyBytes_AS_STRING(block), Py_SIZE(block));
|
||||
posi += Py_SIZE(block);
|
||||
}
|
||||
// the last block
|
||||
block = PyList_GET_ITEM(buffer->list, i);
|
||||
memcpy(posi, PyBytes_AS_STRING(block), Py_SIZE(block) - avail_out);
|
||||
} else {
|
||||
assert(Py_SIZE(result) == 0);
|
||||
}
|
||||
|
||||
Py_CLEAR(buffer->list);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Clean up the buffer when an error occurred. */
|
||||
static inline void
|
||||
_BlocksOutputBuffer_OnError(_BlocksOutputBuffer *buffer)
|
||||
{
|
||||
Py_CLEAR(buffer->list);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* Py_INTERNAL_BLOCKS_OUTPUT_BUFFER_H */
|
||||
@@ -0,0 +1,73 @@
|
||||
#ifndef Py_LIMITED_API
|
||||
#ifndef Py_BYTES_CTYPE_H
|
||||
#define Py_BYTES_CTYPE_H
|
||||
|
||||
#ifndef Py_BUILD_CORE
|
||||
# error "this header requires Py_BUILD_CORE define"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The internal implementation behind PyBytes (bytes) and PyByteArray (bytearray)
|
||||
* methods of the given names, they operate on ASCII byte strings.
|
||||
*/
|
||||
extern PyObject* _Py_bytes_isspace(const char *cptr, Py_ssize_t len);
|
||||
extern PyObject* _Py_bytes_isalpha(const char *cptr, Py_ssize_t len);
|
||||
extern PyObject* _Py_bytes_isalnum(const char *cptr, Py_ssize_t len);
|
||||
extern PyObject* _Py_bytes_isascii(const char *cptr, Py_ssize_t len);
|
||||
extern PyObject* _Py_bytes_isdigit(const char *cptr, Py_ssize_t len);
|
||||
extern PyObject* _Py_bytes_islower(const char *cptr, Py_ssize_t len);
|
||||
extern PyObject* _Py_bytes_isupper(const char *cptr, Py_ssize_t len);
|
||||
extern PyObject* _Py_bytes_istitle(const char *cptr, Py_ssize_t len);
|
||||
|
||||
/* These store their len sized answer in the given preallocated *result arg. */
|
||||
extern void _Py_bytes_lower(char *result, const char *cptr, Py_ssize_t len);
|
||||
extern void _Py_bytes_upper(char *result, const char *cptr, Py_ssize_t len);
|
||||
extern void _Py_bytes_title(char *result, const char *s, Py_ssize_t len);
|
||||
extern void _Py_bytes_capitalize(char *result, const char *s, Py_ssize_t len);
|
||||
extern void _Py_bytes_swapcase(char *result, const char *s, Py_ssize_t len);
|
||||
|
||||
extern PyObject *_Py_bytes_find(const char *str, Py_ssize_t len, PyObject *args);
|
||||
extern PyObject *_Py_bytes_index(const char *str, Py_ssize_t len, PyObject *args);
|
||||
extern PyObject *_Py_bytes_rfind(const char *str, Py_ssize_t len, PyObject *args);
|
||||
extern PyObject *_Py_bytes_rindex(const char *str, Py_ssize_t len, PyObject *args);
|
||||
extern PyObject *_Py_bytes_count(const char *str, Py_ssize_t len, PyObject *args);
|
||||
extern int _Py_bytes_contains(const char *str, Py_ssize_t len, PyObject *arg);
|
||||
extern PyObject *_Py_bytes_startswith(const char *str, Py_ssize_t len, PyObject *args);
|
||||
extern PyObject *_Py_bytes_endswith(const char *str, Py_ssize_t len, PyObject *args);
|
||||
|
||||
/* The maketrans() static method. */
|
||||
extern PyObject* _Py_bytes_maketrans(Py_buffer *frm, Py_buffer *to);
|
||||
|
||||
/* Shared __doc__ strings. */
|
||||
extern const char _Py_isspace__doc__[];
|
||||
extern const char _Py_isalpha__doc__[];
|
||||
extern const char _Py_isalnum__doc__[];
|
||||
extern const char _Py_isascii__doc__[];
|
||||
extern const char _Py_isdigit__doc__[];
|
||||
extern const char _Py_islower__doc__[];
|
||||
extern const char _Py_isupper__doc__[];
|
||||
extern const char _Py_istitle__doc__[];
|
||||
extern const char _Py_lower__doc__[];
|
||||
extern const char _Py_upper__doc__[];
|
||||
extern const char _Py_title__doc__[];
|
||||
extern const char _Py_capitalize__doc__[];
|
||||
extern const char _Py_swapcase__doc__[];
|
||||
extern const char _Py_count__doc__[];
|
||||
extern const char _Py_find__doc__[];
|
||||
extern const char _Py_index__doc__[];
|
||||
extern const char _Py_rfind__doc__[];
|
||||
extern const char _Py_rindex__doc__[];
|
||||
extern const char _Py_startswith__doc__[];
|
||||
extern const char _Py_endswith__doc__[];
|
||||
extern const char _Py_maketrans__doc__[];
|
||||
extern const char _Py_expandtabs__doc__[];
|
||||
extern const char _Py_ljust__doc__[];
|
||||
extern const char _Py_rjust__doc__[];
|
||||
extern const char _Py_center__doc__[];
|
||||
extern const char _Py_zfill__doc__[];
|
||||
|
||||
/* this is needed because some docs are shared from the .o, not static */
|
||||
#define PyDoc_STRVAR_shared(name,str) const char name[] = PyDoc_STR(str)
|
||||
|
||||
#endif /* !Py_BYTES_CTYPE_H */
|
||||
#endif /* !Py_LIMITED_API */
|
||||
@@ -0,0 +1,39 @@
|
||||
#ifndef Py_INTERNAL_CALL_H
|
||||
#define Py_INTERNAL_CALL_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef Py_BUILD_CORE
|
||||
# error "this header requires Py_BUILD_CORE define"
|
||||
#endif
|
||||
|
||||
PyAPI_FUNC(PyObject *) _PyObject_Call_Prepend(
|
||||
PyThreadState *tstate,
|
||||
PyObject *callable,
|
||||
PyObject *obj,
|
||||
PyObject *args,
|
||||
PyObject *kwargs);
|
||||
|
||||
PyAPI_FUNC(PyObject *) _PyObject_FastCallDictTstate(
|
||||
PyThreadState *tstate,
|
||||
PyObject *callable,
|
||||
PyObject *const *args,
|
||||
size_t nargsf,
|
||||
PyObject *kwargs);
|
||||
|
||||
PyAPI_FUNC(PyObject *) _PyObject_Call(
|
||||
PyThreadState *tstate,
|
||||
PyObject *callable,
|
||||
PyObject *args,
|
||||
PyObject *kwargs);
|
||||
|
||||
static inline PyObject *
|
||||
_PyObject_CallNoArgTstate(PyThreadState *tstate, PyObject *func) {
|
||||
return _PyObject_VectorcallTstate(tstate, func, NULL, 0, NULL);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* !Py_INTERNAL_CALL_H */
|
||||
@@ -0,0 +1,114 @@
|
||||
#ifndef Py_INTERNAL_CEVAL_H
|
||||
#define Py_INTERNAL_CEVAL_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef Py_BUILD_CORE
|
||||
# error "this header requires Py_BUILD_CORE define"
|
||||
#endif
|
||||
|
||||
/* Forward declarations */
|
||||
struct pyruntimestate;
|
||||
struct _ceval_runtime_state;
|
||||
|
||||
#include "pycore_interp.h" /* PyInterpreterState.eval_frame */
|
||||
|
||||
extern void _Py_FinishPendingCalls(PyThreadState *tstate);
|
||||
extern void _PyEval_InitRuntimeState(struct _ceval_runtime_state *);
|
||||
extern int _PyEval_InitState(struct _ceval_state *ceval);
|
||||
extern void _PyEval_FiniState(struct _ceval_state *ceval);
|
||||
PyAPI_FUNC(void) _PyEval_SignalReceived(PyInterpreterState *interp);
|
||||
PyAPI_FUNC(int) _PyEval_AddPendingCall(
|
||||
PyInterpreterState *interp,
|
||||
int (*func)(void *),
|
||||
void *arg);
|
||||
PyAPI_FUNC(void) _PyEval_SignalAsyncExc(PyInterpreterState *interp);
|
||||
#ifdef HAVE_FORK
|
||||
extern PyStatus _PyEval_ReInitThreads(PyThreadState *tstate);
|
||||
#endif
|
||||
PyAPI_FUNC(void) _PyEval_SetCoroutineOriginTrackingDepth(
|
||||
PyThreadState *tstate,
|
||||
int new_depth);
|
||||
|
||||
void _PyEval_Fini(void);
|
||||
|
||||
|
||||
extern PyObject* _PyEval_GetBuiltins(PyThreadState *tstate);
|
||||
extern PyObject *_PyEval_BuiltinsFromGlobals(
|
||||
PyThreadState *tstate,
|
||||
PyObject *globals);
|
||||
|
||||
|
||||
static inline PyObject*
|
||||
_PyEval_EvalFrame(PyThreadState *tstate, PyFrameObject *f, int throwflag)
|
||||
{
|
||||
return tstate->interp->eval_frame(tstate, f, throwflag);
|
||||
}
|
||||
|
||||
extern PyObject *
|
||||
_PyEval_Vector(PyThreadState *tstate,
|
||||
PyFrameConstructor *desc, PyObject *locals,
|
||||
PyObject* const* args, size_t argcount,
|
||||
PyObject *kwnames);
|
||||
|
||||
#ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
|
||||
extern int _PyEval_ThreadsInitialized(PyInterpreterState *interp);
|
||||
#else
|
||||
extern int _PyEval_ThreadsInitialized(struct pyruntimestate *runtime);
|
||||
#endif
|
||||
extern PyStatus _PyEval_InitGIL(PyThreadState *tstate);
|
||||
extern void _PyEval_FiniGIL(PyInterpreterState *interp);
|
||||
|
||||
extern void _PyEval_ReleaseLock(PyThreadState *tstate);
|
||||
|
||||
extern void _PyEval_DeactivateOpCache(void);
|
||||
|
||||
|
||||
/* --- _Py_EnterRecursiveCall() ----------------------------------------- */
|
||||
|
||||
#ifdef USE_STACKCHECK
|
||||
/* With USE_STACKCHECK macro defined, trigger stack checks in
|
||||
_Py_CheckRecursiveCall() on every 64th call to Py_EnterRecursiveCall. */
|
||||
static inline int _Py_MakeRecCheck(PyThreadState *tstate) {
|
||||
return (++tstate->recursion_depth > tstate->interp->ceval.recursion_limit
|
||||
|| ++tstate->stackcheck_counter > 64);
|
||||
}
|
||||
#else
|
||||
static inline int _Py_MakeRecCheck(PyThreadState *tstate) {
|
||||
return (++tstate->recursion_depth > tstate->interp->ceval.recursion_limit);
|
||||
}
|
||||
#endif
|
||||
|
||||
PyAPI_FUNC(int) _Py_CheckRecursiveCall(
|
||||
PyThreadState *tstate,
|
||||
const char *where);
|
||||
|
||||
static inline int _Py_EnterRecursiveCall(PyThreadState *tstate,
|
||||
const char *where) {
|
||||
return (_Py_MakeRecCheck(tstate) && _Py_CheckRecursiveCall(tstate, where));
|
||||
}
|
||||
|
||||
static inline int _Py_EnterRecursiveCall_inline(const char *where) {
|
||||
PyThreadState *tstate = PyThreadState_GET();
|
||||
return _Py_EnterRecursiveCall(tstate, where);
|
||||
}
|
||||
|
||||
#define Py_EnterRecursiveCall(where) _Py_EnterRecursiveCall_inline(where)
|
||||
|
||||
static inline void _Py_LeaveRecursiveCall(PyThreadState *tstate) {
|
||||
tstate->recursion_depth--;
|
||||
}
|
||||
|
||||
static inline void _Py_LeaveRecursiveCall_inline(void) {
|
||||
PyThreadState *tstate = PyThreadState_GET();
|
||||
_Py_LeaveRecursiveCall(tstate);
|
||||
}
|
||||
|
||||
#define Py_LeaveRecursiveCall() _Py_LeaveRecursiveCall_inline()
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* !Py_INTERNAL_CEVAL_H */
|
||||
@@ -0,0 +1,34 @@
|
||||
#ifndef Py_INTERNAL_CODE_H
|
||||
#define Py_INTERNAL_CODE_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
PyObject *ptr; /* Cached pointer (borrowed reference) */
|
||||
uint64_t globals_ver; /* ma_version of global dict */
|
||||
uint64_t builtins_ver; /* ma_version of builtin dict */
|
||||
} _PyOpcache_LoadGlobal;
|
||||
|
||||
typedef struct {
|
||||
PyTypeObject *type;
|
||||
Py_ssize_t hint;
|
||||
unsigned int tp_version_tag;
|
||||
} _PyOpCodeOpt_LoadAttr;
|
||||
|
||||
struct _PyOpcache {
|
||||
union {
|
||||
_PyOpcache_LoadGlobal lg;
|
||||
_PyOpCodeOpt_LoadAttr la;
|
||||
} u;
|
||||
char optimized;
|
||||
};
|
||||
|
||||
/* Private API */
|
||||
int _PyCode_InitOpcache(PyCodeObject *co);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* !Py_INTERNAL_CODE_H */
|
||||
@@ -0,0 +1,44 @@
|
||||
#ifndef Py_INTERNAL_COMPILE_H
|
||||
#define Py_INTERNAL_COMPILE_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef Py_BUILD_CORE
|
||||
# error "this header requires Py_BUILD_CORE define"
|
||||
#endif
|
||||
|
||||
struct _arena; // Type defined in pycore_pyarena.h
|
||||
struct _mod; // Type defined in pycore_ast.h
|
||||
|
||||
// Export the symbol for test_peg_generator (built as a library)
|
||||
PyAPI_FUNC(PyCodeObject*) _PyAST_Compile(
|
||||
struct _mod *mod,
|
||||
PyObject *filename,
|
||||
PyCompilerFlags *flags,
|
||||
int optimize,
|
||||
struct _arena *arena);
|
||||
extern PyFutureFeatures* _PyFuture_FromAST(
|
||||
struct _mod * mod,
|
||||
PyObject *filename
|
||||
);
|
||||
|
||||
extern PyObject* _Py_Mangle(PyObject *p, PyObject *name);
|
||||
|
||||
typedef struct {
|
||||
int optimize;
|
||||
int ff_features;
|
||||
|
||||
int recursion_depth; /* current recursion depth */
|
||||
int recursion_limit; /* recursion limit */
|
||||
} _PyASTOptimizeState;
|
||||
|
||||
extern int _PyAST_Optimize(
|
||||
struct _mod *,
|
||||
struct _arena *arena,
|
||||
_PyASTOptimizeState *state);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* !Py_INTERNAL_COMPILE_H */
|
||||
@@ -0,0 +1,95 @@
|
||||
#ifndef Py_INTERNAL_CONDVAR_H
|
||||
#define Py_INTERNAL_CONDVAR_H
|
||||
|
||||
#ifndef Py_BUILD_CORE
|
||||
# error "this header requires Py_BUILD_CORE define"
|
||||
#endif
|
||||
|
||||
#ifndef _POSIX_THREADS
|
||||
/* This means pthreads are not implemented in libc headers, hence the macro
|
||||
not present in unistd.h. But they still can be implemented as an external
|
||||
library (e.g. gnu pth in pthread emulation) */
|
||||
# ifdef HAVE_PTHREAD_H
|
||||
# include <pthread.h> /* _POSIX_THREADS */
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef _POSIX_THREADS
|
||||
/*
|
||||
* POSIX support
|
||||
*/
|
||||
#define Py_HAVE_CONDVAR
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#define PyMUTEX_T pthread_mutex_t
|
||||
#define PyCOND_T pthread_cond_t
|
||||
|
||||
#elif defined(NT_THREADS)
|
||||
/*
|
||||
* Windows (XP, 2003 server and later, as well as (hopefully) CE) support
|
||||
*
|
||||
* Emulated condition variables ones that work with XP and later, plus
|
||||
* example native support on VISTA and onwards.
|
||||
*/
|
||||
#define Py_HAVE_CONDVAR
|
||||
|
||||
/* include windows if it hasn't been done before */
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
|
||||
/* options */
|
||||
/* non-emulated condition variables are provided for those that want
|
||||
* to target Windows Vista. Modify this macro to enable them.
|
||||
*/
|
||||
#ifndef _PY_EMULATED_WIN_CV
|
||||
#define _PY_EMULATED_WIN_CV 1 /* use emulated condition variables */
|
||||
#endif
|
||||
|
||||
/* fall back to emulation if not targeting Vista */
|
||||
#if !defined NTDDI_VISTA || NTDDI_VERSION < NTDDI_VISTA
|
||||
#undef _PY_EMULATED_WIN_CV
|
||||
#define _PY_EMULATED_WIN_CV 1
|
||||
#endif
|
||||
|
||||
#if _PY_EMULATED_WIN_CV
|
||||
|
||||
typedef CRITICAL_SECTION PyMUTEX_T;
|
||||
|
||||
/* The ConditionVariable object. From XP onwards it is easily emulated
|
||||
with a Semaphore.
|
||||
Semaphores are available on Windows XP (2003 server) and later.
|
||||
We use a Semaphore rather than an auto-reset event, because although
|
||||
an auto-resent event might appear to solve the lost-wakeup bug (race
|
||||
condition between releasing the outer lock and waiting) because it
|
||||
maintains state even though a wait hasn't happened, there is still
|
||||
a lost wakeup problem if more than one thread are interrupted in the
|
||||
critical place. A semaphore solves that, because its state is
|
||||
counted, not Boolean.
|
||||
Because it is ok to signal a condition variable with no one
|
||||
waiting, we need to keep track of the number of
|
||||
waiting threads. Otherwise, the semaphore's state could rise
|
||||
without bound. This also helps reduce the number of "spurious wakeups"
|
||||
that would otherwise happen.
|
||||
*/
|
||||
|
||||
typedef struct _PyCOND_T
|
||||
{
|
||||
HANDLE sem;
|
||||
int waiting; /* to allow PyCOND_SIGNAL to be a no-op */
|
||||
} PyCOND_T;
|
||||
|
||||
#else /* !_PY_EMULATED_WIN_CV */
|
||||
|
||||
/* Use native Win7 primitives if build target is Win7 or higher */
|
||||
|
||||
/* SRWLOCK is faster and better than CriticalSection */
|
||||
typedef SRWLOCK PyMUTEX_T;
|
||||
|
||||
typedef CONDITION_VARIABLE PyCOND_T;
|
||||
|
||||
#endif /* _PY_EMULATED_WIN_CV */
|
||||
|
||||
#endif /* _POSIX_THREADS, NT_THREADS */
|
||||
|
||||
#endif /* Py_INTERNAL_CONDVAR_H */
|
||||
@@ -0,0 +1,42 @@
|
||||
#ifndef Py_INTERNAL_CONTEXT_H
|
||||
#define Py_INTERNAL_CONTEXT_H
|
||||
|
||||
#ifndef Py_BUILD_CORE
|
||||
# error "this header requires Py_BUILD_CORE define"
|
||||
#endif
|
||||
|
||||
#include "pycore_hamt.h" /* PyHamtObject */
|
||||
|
||||
struct _pycontextobject {
|
||||
PyObject_HEAD
|
||||
PyContext *ctx_prev;
|
||||
PyHamtObject *ctx_vars;
|
||||
PyObject *ctx_weakreflist;
|
||||
int ctx_entered;
|
||||
};
|
||||
|
||||
|
||||
struct _pycontextvarobject {
|
||||
PyObject_HEAD
|
||||
PyObject *var_name;
|
||||
PyObject *var_default;
|
||||
PyObject *var_cached;
|
||||
uint64_t var_cached_tsid;
|
||||
uint64_t var_cached_tsver;
|
||||
Py_hash_t var_hash;
|
||||
};
|
||||
|
||||
|
||||
struct _pycontexttokenobject {
|
||||
PyObject_HEAD
|
||||
PyContext *tok_ctx;
|
||||
PyContextVar *tok_var;
|
||||
PyObject *tok_oldval;
|
||||
int tok_used;
|
||||
};
|
||||
|
||||
|
||||
int _PyContext_Init(void);
|
||||
void _PyContext_Fini(PyInterpreterState *interp);
|
||||
|
||||
#endif /* !Py_INTERNAL_CONTEXT_H */
|
||||
@@ -0,0 +1,23 @@
|
||||
#ifndef PY_NO_SHORT_FLOAT_REPR
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef Py_BUILD_CORE
|
||||
# error "this header requires Py_BUILD_CORE define"
|
||||
#endif
|
||||
|
||||
/* These functions are used by modules compiled as C extension like math:
|
||||
they must be exported. */
|
||||
|
||||
PyAPI_FUNC(double) _Py_dg_strtod(const char *str, char **ptr);
|
||||
PyAPI_FUNC(char *) _Py_dg_dtoa(double d, int mode, int ndigits,
|
||||
int *decpt, int *sign, char **rve);
|
||||
PyAPI_FUNC(void) _Py_dg_freedtoa(char *s);
|
||||
PyAPI_FUNC(double) _Py_dg_stdnan(int sign);
|
||||
PyAPI_FUNC(double) _Py_dg_infinity(int sign);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* !PY_NO_SHORT_FLOAT_REPR */
|
||||
@@ -0,0 +1,71 @@
|
||||
#ifndef Py_INTERNAL_FILEUTILS_H
|
||||
#define Py_INTERNAL_FILEUTILS_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef Py_BUILD_CORE
|
||||
# error "Py_BUILD_CORE must be defined to include this header"
|
||||
#endif
|
||||
|
||||
#include <locale.h> /* struct lconv */
|
||||
|
||||
PyAPI_DATA(int) _Py_HasFileSystemDefaultEncodeErrors;
|
||||
|
||||
PyAPI_FUNC(int) _Py_DecodeUTF8Ex(
|
||||
const char *arg,
|
||||
Py_ssize_t arglen,
|
||||
wchar_t **wstr,
|
||||
size_t *wlen,
|
||||
const char **reason,
|
||||
_Py_error_handler errors);
|
||||
|
||||
PyAPI_FUNC(int) _Py_EncodeUTF8Ex(
|
||||
const wchar_t *text,
|
||||
char **str,
|
||||
size_t *error_pos,
|
||||
const char **reason,
|
||||
int raw_malloc,
|
||||
_Py_error_handler errors);
|
||||
|
||||
PyAPI_FUNC(wchar_t*) _Py_DecodeUTF8_surrogateescape(
|
||||
const char *arg,
|
||||
Py_ssize_t arglen,
|
||||
size_t *wlen);
|
||||
|
||||
PyAPI_FUNC(int) _Py_GetForceASCII(void);
|
||||
|
||||
/* Reset "force ASCII" mode (if it was initialized).
|
||||
|
||||
This function should be called when Python changes the LC_CTYPE locale,
|
||||
so the "force ASCII" mode can be detected again on the new locale
|
||||
encoding. */
|
||||
PyAPI_FUNC(void) _Py_ResetForceASCII(void);
|
||||
|
||||
|
||||
PyAPI_FUNC(int) _Py_GetLocaleconvNumeric(
|
||||
struct lconv *lc,
|
||||
PyObject **decimal_point,
|
||||
PyObject **thousands_sep);
|
||||
|
||||
PyAPI_FUNC(void) _Py_closerange(int first, int last);
|
||||
|
||||
PyAPI_FUNC(wchar_t*) _Py_GetLocaleEncoding(void);
|
||||
PyAPI_FUNC(PyObject*) _Py_GetLocaleEncodingObject(void);
|
||||
|
||||
#ifdef HAVE_NON_UNICODE_WCHAR_T_REPRESENTATION
|
||||
extern int _Py_LocaleUsesNonUnicodeWchar(void);
|
||||
|
||||
extern wchar_t* _Py_DecodeNonUnicodeWchar(
|
||||
const wchar_t* native,
|
||||
Py_ssize_t size);
|
||||
|
||||
extern int _Py_EncodeNonUnicodeWchar_InPlace(
|
||||
wchar_t* unicode,
|
||||
Py_ssize_t size);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* !Py_INTERNAL_FILEUTILS_H */
|
||||
@@ -0,0 +1,27 @@
|
||||
#ifndef Py_INTERNAL_FORMAT_H
|
||||
#define Py_INTERNAL_FORMAT_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef Py_BUILD_CORE
|
||||
# error "this header requires Py_BUILD_CORE define"
|
||||
#endif
|
||||
|
||||
/* Format codes
|
||||
* F_LJUST '-'
|
||||
* F_SIGN '+'
|
||||
* F_BLANK ' '
|
||||
* F_ALT '#'
|
||||
* F_ZERO '0'
|
||||
*/
|
||||
#define F_LJUST (1<<0)
|
||||
#define F_SIGN (1<<1)
|
||||
#define F_BLANK (1<<2)
|
||||
#define F_ALT (1<<3)
|
||||
#define F_ZERO (1<<4)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* !Py_INTERNAL_FORMAT_H */
|
||||
@@ -0,0 +1,181 @@
|
||||
#ifndef Py_INTERNAL_GC_H
|
||||
#define Py_INTERNAL_GC_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef Py_BUILD_CORE
|
||||
# error "this header requires Py_BUILD_CORE define"
|
||||
#endif
|
||||
|
||||
/* GC information is stored BEFORE the object structure. */
|
||||
typedef struct {
|
||||
// Pointer to next object in the list.
|
||||
// 0 means the object is not tracked
|
||||
uintptr_t _gc_next;
|
||||
|
||||
// Pointer to previous object in the list.
|
||||
// Lowest two bits are used for flags documented later.
|
||||
uintptr_t _gc_prev;
|
||||
} PyGC_Head;
|
||||
|
||||
#define _Py_AS_GC(o) ((PyGC_Head *)(o)-1)
|
||||
|
||||
/* True if the object is currently tracked by the GC. */
|
||||
#define _PyObject_GC_IS_TRACKED(o) (_Py_AS_GC(o)->_gc_next != 0)
|
||||
|
||||
/* True if the object may be tracked by the GC in the future, or already is.
|
||||
This can be useful to implement some optimizations. */
|
||||
#define _PyObject_GC_MAY_BE_TRACKED(obj) \
|
||||
(PyObject_IS_GC(obj) && \
|
||||
(!PyTuple_CheckExact(obj) || _PyObject_GC_IS_TRACKED(obj)))
|
||||
|
||||
|
||||
/* Bit flags for _gc_prev */
|
||||
/* Bit 0 is set when tp_finalize is called */
|
||||
#define _PyGC_PREV_MASK_FINALIZED (1)
|
||||
/* Bit 1 is set when the object is in generation which is GCed currently. */
|
||||
#define _PyGC_PREV_MASK_COLLECTING (2)
|
||||
/* The (N-2) most significant bits contain the real address. */
|
||||
#define _PyGC_PREV_SHIFT (2)
|
||||
#define _PyGC_PREV_MASK (((uintptr_t) -1) << _PyGC_PREV_SHIFT)
|
||||
|
||||
// Lowest bit of _gc_next is used for flags only in GC.
|
||||
// But it is always 0 for normal code.
|
||||
#define _PyGCHead_NEXT(g) ((PyGC_Head*)(g)->_gc_next)
|
||||
#define _PyGCHead_SET_NEXT(g, p) ((g)->_gc_next = (uintptr_t)(p))
|
||||
|
||||
// Lowest two bits of _gc_prev is used for _PyGC_PREV_MASK_* flags.
|
||||
#define _PyGCHead_PREV(g) ((PyGC_Head*)((g)->_gc_prev & _PyGC_PREV_MASK))
|
||||
#define _PyGCHead_SET_PREV(g, p) do { \
|
||||
assert(((uintptr_t)p & ~_PyGC_PREV_MASK) == 0); \
|
||||
(g)->_gc_prev = ((g)->_gc_prev & ~_PyGC_PREV_MASK) \
|
||||
| ((uintptr_t)(p)); \
|
||||
} while (0)
|
||||
|
||||
#define _PyGCHead_FINALIZED(g) \
|
||||
(((g)->_gc_prev & _PyGC_PREV_MASK_FINALIZED) != 0)
|
||||
#define _PyGCHead_SET_FINALIZED(g) \
|
||||
((g)->_gc_prev |= _PyGC_PREV_MASK_FINALIZED)
|
||||
|
||||
#define _PyGC_FINALIZED(o) \
|
||||
_PyGCHead_FINALIZED(_Py_AS_GC(o))
|
||||
#define _PyGC_SET_FINALIZED(o) \
|
||||
_PyGCHead_SET_FINALIZED(_Py_AS_GC(o))
|
||||
|
||||
|
||||
/* 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.
|
||||
|
||||
Certain types of container cannot participate in a reference cycle, and
|
||||
so do not need to be tracked by the garbage collector. Untracking these
|
||||
objects reduces the cost of garbage collections. However, determining
|
||||
which objects may be untracked is not free, and the costs must be
|
||||
weighed against the benefits for garbage collection.
|
||||
|
||||
There are two possible strategies for when to untrack a container:
|
||||
|
||||
i) When the container is created.
|
||||
ii) When the container is examined by the garbage collector.
|
||||
|
||||
Tuples containing only immutable objects (integers, strings etc, and
|
||||
recursively, tuples of immutable objects) do not need to be tracked.
|
||||
The interpreter creates a large number of tuples, many of which will
|
||||
not survive until garbage collection. It is therefore not worthwhile
|
||||
to untrack eligible tuples at creation time.
|
||||
|
||||
Instead, all tuples except the empty tuple are tracked when created.
|
||||
During garbage collection it is determined whether any surviving tuples
|
||||
can be untracked. A tuple can be untracked if all of its contents are
|
||||
already not tracked. Tuples are examined for untracking in all garbage
|
||||
collection cycles. It may take more than one cycle to untrack a tuple.
|
||||
|
||||
Dictionaries containing only immutable objects also do not need to be
|
||||
tracked. Dictionaries are untracked when created. If a tracked item is
|
||||
inserted into a dictionary (either as a key or value), the dictionary
|
||||
becomes tracked. During a full garbage collection (all generations),
|
||||
the collector will untrack any dictionaries whose contents are not
|
||||
tracked.
|
||||
|
||||
The module provides the python function is_tracked(obj), which returns
|
||||
the CURRENT tracking status of the object. Subsequent garbage
|
||||
collections may change the tracking status of the object.
|
||||
|
||||
Untracking of certain containers was introduced in issue #4688, and
|
||||
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 */
|
||||
};
|
||||
|
||||
/* 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;
|
||||
};
|
||||
|
||||
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;
|
||||
|
||||
int enabled;
|
||||
int debug;
|
||||
/* linked lists of container objects */
|
||||
struct gc_generation generations[NUM_GENERATIONS];
|
||||
PyGC_Head *generation0;
|
||||
/* 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;
|
||||
/* 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;
|
||||
};
|
||||
|
||||
extern void _PyGC_InitState(struct _gc_runtime_state *);
|
||||
|
||||
extern Py_ssize_t _PyGC_CollectNoFail(PyThreadState *tstate);
|
||||
|
||||
|
||||
// Functions to clear types free lists
|
||||
extern void _PyFrame_ClearFreeList(PyInterpreterState *interp);
|
||||
extern void _PyTuple_ClearFreeList(PyInterpreterState *interp);
|
||||
extern void _PyFloat_ClearFreeList(PyInterpreterState *interp);
|
||||
extern void _PyList_ClearFreeList(PyInterpreterState *interp);
|
||||
extern void _PyDict_ClearFreeList(PyInterpreterState *interp);
|
||||
extern void _PyAsyncGen_ClearFreeLists(PyInterpreterState *interp);
|
||||
extern void _PyContext_ClearFreeList(PyInterpreterState *interp);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* !Py_INTERNAL_GC_H */
|
||||
@@ -0,0 +1,22 @@
|
||||
#ifndef Py_INTERNAL_PYGETOPT_H
|
||||
#define Py_INTERNAL_PYGETOPT_H
|
||||
|
||||
#ifndef Py_BUILD_CORE
|
||||
# error "this header requires Py_BUILD_CORE define"
|
||||
#endif
|
||||
|
||||
extern int _PyOS_opterr;
|
||||
extern Py_ssize_t _PyOS_optind;
|
||||
extern const wchar_t *_PyOS_optarg;
|
||||
|
||||
extern void _PyOS_ResetGetOpt(void);
|
||||
|
||||
typedef struct {
|
||||
const wchar_t *name;
|
||||
int has_arg;
|
||||
int val;
|
||||
} _PyOS_LongOption;
|
||||
|
||||
extern int _PyOS_GetOpt(Py_ssize_t argc, wchar_t * const *argv, int *longindex);
|
||||
|
||||
#endif /* !Py_INTERNAL_PYGETOPT_H */
|
||||
@@ -0,0 +1,50 @@
|
||||
#ifndef Py_INTERNAL_GIL_H
|
||||
#define Py_INTERNAL_GIL_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef Py_BUILD_CORE
|
||||
# error "this header requires Py_BUILD_CORE define"
|
||||
#endif
|
||||
|
||||
#include "pycore_atomic.h" /* _Py_atomic_address */
|
||||
#include "pycore_condvar.h" /* PyCOND_T */
|
||||
|
||||
#ifndef Py_HAVE_CONDVAR
|
||||
# error You need either a POSIX-compatible or a Windows system!
|
||||
#endif
|
||||
|
||||
/* Enable if you want to force the switching of threads at least
|
||||
every `interval`. */
|
||||
#undef FORCE_SWITCHING
|
||||
#define FORCE_SWITCHING
|
||||
|
||||
struct _gil_runtime_state {
|
||||
/* microseconds (the Python API uses seconds, though) */
|
||||
unsigned long interval;
|
||||
/* Last PyThreadState holding / having held the GIL. This helps us
|
||||
know whether anyone else was scheduled after we dropped the GIL. */
|
||||
_Py_atomic_address last_holder;
|
||||
/* Whether the GIL is already taken (-1 if uninitialized). This is
|
||||
atomic because it can be read without any lock taken in ceval.c. */
|
||||
_Py_atomic_int locked;
|
||||
/* Number of GIL switches since the beginning. */
|
||||
unsigned long switch_number;
|
||||
/* This condition variable allows one or several threads to wait
|
||||
until the GIL is released. In addition, the mutex also protects
|
||||
the above variables. */
|
||||
PyCOND_T cond;
|
||||
PyMUTEX_T mutex;
|
||||
#ifdef FORCE_SWITCHING
|
||||
/* This condition variable helps the GIL-releasing thread wait for
|
||||
a GIL-awaiting thread to be scheduled and take the GIL. */
|
||||
PyCOND_T switch_cond;
|
||||
PyMUTEX_T switch_mutex;
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* !Py_INTERNAL_GIL_H */
|
||||
@@ -0,0 +1,128 @@
|
||||
#ifndef Py_INTERNAL_HAMT_H
|
||||
#define Py_INTERNAL_HAMT_H
|
||||
|
||||
#ifndef Py_BUILD_CORE
|
||||
# error "this header requires Py_BUILD_CORE define"
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
HAMT tree is shaped by hashes of keys. Every group of 5 bits of a hash denotes
|
||||
the exact position of the key in one level of the tree. Since we're using
|
||||
32 bit hashes, we can have at most 7 such levels. Although if there are
|
||||
two distinct keys with equal hashes, they will have to occupy the same
|
||||
cell in the 7th level of the tree -- so we'd put them in a "collision" node.
|
||||
Which brings the total possible tree depth to 8. Read more about the actual
|
||||
layout of the HAMT tree in `hamt.c`.
|
||||
|
||||
This constant is used to define a datastucture for storing iteration state.
|
||||
*/
|
||||
#define _Py_HAMT_MAX_TREE_DEPTH 8
|
||||
|
||||
|
||||
#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;
|
||||
|
||||
|
||||
/* A struct to hold the state of depth-first traverse of the tree.
|
||||
|
||||
HAMT is an immutable collection. Iterators will hold a strong reference
|
||||
to it, and every node in the HAMT has strong references to its children.
|
||||
|
||||
So for iterators, we can implement zero allocations and zero reference
|
||||
inc/dec depth-first iteration.
|
||||
|
||||
- i_nodes: an array of seven pointers to tree nodes
|
||||
- i_level: the current node in i_nodes
|
||||
- i_pos: an array of positions within nodes in i_nodes.
|
||||
*/
|
||||
typedef struct {
|
||||
PyHamtNode *i_nodes[_Py_HAMT_MAX_TREE_DEPTH];
|
||||
Py_ssize_t i_pos[_Py_HAMT_MAX_TREE_DEPTH];
|
||||
int8_t i_level;
|
||||
} PyHamtIteratorState;
|
||||
|
||||
|
||||
/* Base iterator object.
|
||||
|
||||
Contains the iteration state, a pointer to the HAMT tree,
|
||||
and a pointer to the 'yield function'. The latter is a simple
|
||||
function that returns a key/value tuple for the 'Items' iterator,
|
||||
just a key for the 'Keys' iterator, and a value for the 'Values'
|
||||
iterator.
|
||||
*/
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
PyHamtObject *hi_obj;
|
||||
PyHamtIteratorState hi_iter;
|
||||
binaryfunc hi_yield;
|
||||
} PyHamtIterator;
|
||||
|
||||
|
||||
PyAPI_DATA(PyTypeObject) _PyHamt_Type;
|
||||
PyAPI_DATA(PyTypeObject) _PyHamt_ArrayNode_Type;
|
||||
PyAPI_DATA(PyTypeObject) _PyHamt_BitmapNode_Type;
|
||||
PyAPI_DATA(PyTypeObject) _PyHamt_CollisionNode_Type;
|
||||
PyAPI_DATA(PyTypeObject) _PyHamtKeys_Type;
|
||||
PyAPI_DATA(PyTypeObject) _PyHamtValues_Type;
|
||||
PyAPI_DATA(PyTypeObject) _PyHamtItems_Type;
|
||||
|
||||
|
||||
/* Create a new HAMT immutable mapping. */
|
||||
PyHamtObject * _PyHamt_New(void);
|
||||
|
||||
/* Return a new collection based on "o", but with an additional
|
||||
key/val pair. */
|
||||
PyHamtObject * _PyHamt_Assoc(PyHamtObject *o, PyObject *key, PyObject *val);
|
||||
|
||||
/* Return a new collection based on "o", but without "key". */
|
||||
PyHamtObject * _PyHamt_Without(PyHamtObject *o, PyObject *key);
|
||||
|
||||
/* Find "key" in the "o" collection.
|
||||
|
||||
Return:
|
||||
- -1: An error occurred.
|
||||
- 0: "key" wasn't found in "o".
|
||||
- 1: "key" is in "o"; "*val" is set to its value (a borrowed ref).
|
||||
*/
|
||||
int _PyHamt_Find(PyHamtObject *o, PyObject *key, PyObject **val);
|
||||
|
||||
/* Check if "v" is equal to "w".
|
||||
|
||||
Return:
|
||||
- 0: v != w
|
||||
- 1: v == w
|
||||
- -1: An error occurred.
|
||||
*/
|
||||
int _PyHamt_Eq(PyHamtObject *v, PyHamtObject *w);
|
||||
|
||||
/* Return the size of "o"; equivalent of "len(o)". */
|
||||
Py_ssize_t _PyHamt_Len(PyHamtObject *o);
|
||||
|
||||
/* Return a Keys iterator over "o". */
|
||||
PyObject * _PyHamt_NewIterKeys(PyHamtObject *o);
|
||||
|
||||
/* Return a Values iterator over "o". */
|
||||
PyObject * _PyHamt_NewIterValues(PyHamtObject *o);
|
||||
|
||||
/* Return a Items iterator over "o". */
|
||||
PyObject * _PyHamt_NewIterItems(PyHamtObject *o);
|
||||
|
||||
int _PyHamt_Init(void);
|
||||
void _PyHamt_Fini(void);
|
||||
|
||||
#endif /* !Py_INTERNAL_HAMT_H */
|
||||
@@ -0,0 +1,148 @@
|
||||
#ifndef Py_INTERNAL_HASHTABLE_H
|
||||
#define Py_INTERNAL_HASHTABLE_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef Py_BUILD_CORE
|
||||
# error "this header requires Py_BUILD_CORE define"
|
||||
#endif
|
||||
|
||||
/* Single linked list */
|
||||
|
||||
typedef struct _Py_slist_item_s {
|
||||
struct _Py_slist_item_s *next;
|
||||
} _Py_slist_item_t;
|
||||
|
||||
typedef struct {
|
||||
_Py_slist_item_t *head;
|
||||
} _Py_slist_t;
|
||||
|
||||
#define _Py_SLIST_ITEM_NEXT(ITEM) (((_Py_slist_item_t *)ITEM)->next)
|
||||
|
||||
#define _Py_SLIST_HEAD(SLIST) (((_Py_slist_t *)SLIST)->head)
|
||||
|
||||
|
||||
/* _Py_hashtable: table entry */
|
||||
|
||||
typedef struct {
|
||||
/* used by _Py_hashtable_t.buckets to link entries */
|
||||
_Py_slist_item_t _Py_slist_item;
|
||||
|
||||
Py_uhash_t key_hash;
|
||||
void *key;
|
||||
void *value;
|
||||
} _Py_hashtable_entry_t;
|
||||
|
||||
|
||||
/* _Py_hashtable: prototypes */
|
||||
|
||||
/* Forward declaration */
|
||||
struct _Py_hashtable_t;
|
||||
typedef struct _Py_hashtable_t _Py_hashtable_t;
|
||||
|
||||
typedef Py_uhash_t (*_Py_hashtable_hash_func) (const void *key);
|
||||
typedef int (*_Py_hashtable_compare_func) (const void *key1, const void *key2);
|
||||
typedef void (*_Py_hashtable_destroy_func) (void *key);
|
||||
typedef _Py_hashtable_entry_t* (*_Py_hashtable_get_entry_func)(_Py_hashtable_t *ht,
|
||||
const void *key);
|
||||
|
||||
typedef struct {
|
||||
// Allocate a memory block
|
||||
void* (*malloc) (size_t size);
|
||||
|
||||
// Release a memory block
|
||||
void (*free) (void *ptr);
|
||||
} _Py_hashtable_allocator_t;
|
||||
|
||||
|
||||
/* _Py_hashtable: table */
|
||||
struct _Py_hashtable_t {
|
||||
size_t nentries; // Total number of entries in the table
|
||||
size_t nbuckets;
|
||||
_Py_slist_t *buckets;
|
||||
|
||||
_Py_hashtable_get_entry_func get_entry_func;
|
||||
_Py_hashtable_hash_func hash_func;
|
||||
_Py_hashtable_compare_func compare_func;
|
||||
_Py_hashtable_destroy_func key_destroy_func;
|
||||
_Py_hashtable_destroy_func value_destroy_func;
|
||||
_Py_hashtable_allocator_t alloc;
|
||||
};
|
||||
|
||||
/* Hash a pointer (void*) */
|
||||
PyAPI_FUNC(Py_uhash_t) _Py_hashtable_hash_ptr(const void *key);
|
||||
|
||||
/* Comparison using memcmp() */
|
||||
PyAPI_FUNC(int) _Py_hashtable_compare_direct(
|
||||
const void *key1,
|
||||
const void *key2);
|
||||
|
||||
PyAPI_FUNC(_Py_hashtable_t *) _Py_hashtable_new(
|
||||
_Py_hashtable_hash_func hash_func,
|
||||
_Py_hashtable_compare_func compare_func);
|
||||
|
||||
PyAPI_FUNC(_Py_hashtable_t *) _Py_hashtable_new_full(
|
||||
_Py_hashtable_hash_func hash_func,
|
||||
_Py_hashtable_compare_func compare_func,
|
||||
_Py_hashtable_destroy_func key_destroy_func,
|
||||
_Py_hashtable_destroy_func value_destroy_func,
|
||||
_Py_hashtable_allocator_t *allocator);
|
||||
|
||||
PyAPI_FUNC(void) _Py_hashtable_destroy(_Py_hashtable_t *ht);
|
||||
|
||||
PyAPI_FUNC(void) _Py_hashtable_clear(_Py_hashtable_t *ht);
|
||||
|
||||
typedef int (*_Py_hashtable_foreach_func) (_Py_hashtable_t *ht,
|
||||
const void *key, const void *value,
|
||||
void *user_data);
|
||||
|
||||
/* Call func() on each entry of the hashtable.
|
||||
Iteration stops if func() result is non-zero, in this case it's the result
|
||||
of the call. Otherwise, the function returns 0. */
|
||||
PyAPI_FUNC(int) _Py_hashtable_foreach(
|
||||
_Py_hashtable_t *ht,
|
||||
_Py_hashtable_foreach_func func,
|
||||
void *user_data);
|
||||
|
||||
PyAPI_FUNC(size_t) _Py_hashtable_size(const _Py_hashtable_t *ht);
|
||||
|
||||
/* Add a new entry to the hash. The key must not be present in the hash table.
|
||||
Return 0 on success, -1 on memory error. */
|
||||
PyAPI_FUNC(int) _Py_hashtable_set(
|
||||
_Py_hashtable_t *ht,
|
||||
const void *key,
|
||||
void *value);
|
||||
|
||||
|
||||
/* Get an entry.
|
||||
Return NULL if the key does not exist. */
|
||||
static inline _Py_hashtable_entry_t *
|
||||
_Py_hashtable_get_entry(_Py_hashtable_t *ht, const void *key)
|
||||
{
|
||||
return ht->get_entry_func(ht, key);
|
||||
}
|
||||
|
||||
|
||||
/* Get value from an entry.
|
||||
Return NULL if the entry is not found.
|
||||
|
||||
Use _Py_hashtable_get_entry() to distinguish entry value equal to NULL
|
||||
and entry not found. */
|
||||
PyAPI_FUNC(void*) _Py_hashtable_get(_Py_hashtable_t *ht, const void *key);
|
||||
|
||||
|
||||
/* Remove a key and its associated value without calling key and value destroy
|
||||
functions.
|
||||
|
||||
Return the removed value if the key was found.
|
||||
Return NULL if the key was not found. */
|
||||
PyAPI_FUNC(void*) _Py_hashtable_steal(
|
||||
_Py_hashtable_t *ht,
|
||||
const void *key);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* !Py_INTERNAL_HASHTABLE_H */
|
||||
@@ -0,0 +1,17 @@
|
||||
#ifndef Py_LIMITED_API
|
||||
#ifndef Py_INTERNAL_IMPORT_H
|
||||
#define Py_INTERNAL_IMPORT_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_FORK
|
||||
extern PyStatus _PyImport_ReInitLock(void);
|
||||
#endif
|
||||
extern PyObject* _PyImport_BootstrapImp(PyThreadState *tstate);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* !Py_INTERNAL_IMPORT_H */
|
||||
#endif /* !Py_LIMITED_API */
|
||||
@@ -0,0 +1,178 @@
|
||||
#ifndef Py_INTERNAL_CORECONFIG_H
|
||||
#define Py_INTERNAL_CORECONFIG_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef Py_BUILD_CORE
|
||||
# error "this header requires Py_BUILD_CORE define"
|
||||
#endif
|
||||
|
||||
/* Forward declaration */
|
||||
struct pyruntimestate;
|
||||
|
||||
/* --- PyStatus ----------------------------------------------- */
|
||||
|
||||
/* Almost all errors causing Python initialization to fail */
|
||||
#ifdef _MSC_VER
|
||||
/* Visual Studio 2015 doesn't implement C99 __func__ in C */
|
||||
# define _PyStatus_GET_FUNC() __FUNCTION__
|
||||
#else
|
||||
# define _PyStatus_GET_FUNC() __func__
|
||||
#endif
|
||||
|
||||
#define _PyStatus_OK() \
|
||||
(PyStatus){._type = _PyStatus_TYPE_OK,}
|
||||
/* other fields are set to 0 */
|
||||
#define _PyStatus_ERR(ERR_MSG) \
|
||||
(PyStatus){ \
|
||||
._type = _PyStatus_TYPE_ERROR, \
|
||||
.func = _PyStatus_GET_FUNC(), \
|
||||
.err_msg = (ERR_MSG)}
|
||||
/* other fields are set to 0 */
|
||||
#define _PyStatus_NO_MEMORY() _PyStatus_ERR("memory allocation failed")
|
||||
#define _PyStatus_EXIT(EXITCODE) \
|
||||
(PyStatus){ \
|
||||
._type = _PyStatus_TYPE_EXIT, \
|
||||
.exitcode = (EXITCODE)}
|
||||
#define _PyStatus_IS_ERROR(err) \
|
||||
(err._type == _PyStatus_TYPE_ERROR)
|
||||
#define _PyStatus_IS_EXIT(err) \
|
||||
(err._type == _PyStatus_TYPE_EXIT)
|
||||
#define _PyStatus_EXCEPTION(err) \
|
||||
(err._type != _PyStatus_TYPE_OK)
|
||||
#define _PyStatus_UPDATE_FUNC(err) \
|
||||
do { err.func = _PyStatus_GET_FUNC(); } while (0)
|
||||
|
||||
PyObject* _PyErr_SetFromPyStatus(PyStatus status);
|
||||
|
||||
/* --- PyWideStringList ------------------------------------------------ */
|
||||
|
||||
#define _PyWideStringList_INIT (PyWideStringList){.length = 0, .items = NULL}
|
||||
|
||||
#ifndef NDEBUG
|
||||
PyAPI_FUNC(int) _PyWideStringList_CheckConsistency(const PyWideStringList *list);
|
||||
#endif
|
||||
PyAPI_FUNC(void) _PyWideStringList_Clear(PyWideStringList *list);
|
||||
PyAPI_FUNC(int) _PyWideStringList_Copy(PyWideStringList *list,
|
||||
const PyWideStringList *list2);
|
||||
PyAPI_FUNC(PyStatus) _PyWideStringList_Extend(PyWideStringList *list,
|
||||
const PyWideStringList *list2);
|
||||
PyAPI_FUNC(PyObject*) _PyWideStringList_AsList(const PyWideStringList *list);
|
||||
|
||||
|
||||
/* --- _PyArgv ---------------------------------------------------- */
|
||||
|
||||
typedef struct _PyArgv {
|
||||
Py_ssize_t argc;
|
||||
int use_bytes_argv;
|
||||
char * const *bytes_argv;
|
||||
wchar_t * const *wchar_argv;
|
||||
} _PyArgv;
|
||||
|
||||
PyAPI_FUNC(PyStatus) _PyArgv_AsWstrList(const _PyArgv *args,
|
||||
PyWideStringList *list);
|
||||
|
||||
|
||||
/* --- Helper functions ------------------------------------------- */
|
||||
|
||||
PyAPI_FUNC(int) _Py_str_to_int(
|
||||
const char *str,
|
||||
int *result);
|
||||
PyAPI_FUNC(const wchar_t*) _Py_get_xoption(
|
||||
const PyWideStringList *xoptions,
|
||||
const wchar_t *name);
|
||||
PyAPI_FUNC(const char*) _Py_GetEnv(
|
||||
int use_environment,
|
||||
const char *name);
|
||||
PyAPI_FUNC(void) _Py_get_env_flag(
|
||||
int use_environment,
|
||||
int *flag,
|
||||
const char *name);
|
||||
|
||||
/* Py_GetArgcArgv() helper */
|
||||
PyAPI_FUNC(void) _Py_ClearArgcArgv(void);
|
||||
|
||||
|
||||
/* --- _PyPreCmdline ------------------------------------------------- */
|
||||
|
||||
typedef struct {
|
||||
PyWideStringList argv;
|
||||
PyWideStringList xoptions; /* "-X value" option */
|
||||
int isolated; /* -I option */
|
||||
int use_environment; /* -E option */
|
||||
int dev_mode; /* -X dev and PYTHONDEVMODE */
|
||||
int warn_default_encoding; /* -X warn_default_encoding and PYTHONWARNDEFAULTENCODING */
|
||||
} _PyPreCmdline;
|
||||
|
||||
#define _PyPreCmdline_INIT \
|
||||
(_PyPreCmdline){ \
|
||||
.use_environment = -1, \
|
||||
.isolated = -1, \
|
||||
.dev_mode = -1}
|
||||
/* Note: _PyPreCmdline_INIT sets other fields to 0/NULL */
|
||||
|
||||
extern void _PyPreCmdline_Clear(_PyPreCmdline *cmdline);
|
||||
extern PyStatus _PyPreCmdline_SetArgv(_PyPreCmdline *cmdline,
|
||||
const _PyArgv *args);
|
||||
extern PyStatus _PyPreCmdline_SetConfig(
|
||||
const _PyPreCmdline *cmdline,
|
||||
PyConfig *config);
|
||||
extern PyStatus _PyPreCmdline_Read(_PyPreCmdline *cmdline,
|
||||
const PyPreConfig *preconfig);
|
||||
|
||||
|
||||
/* --- PyPreConfig ----------------------------------------------- */
|
||||
|
||||
PyAPI_FUNC(void) _PyPreConfig_InitCompatConfig(PyPreConfig *preconfig);
|
||||
extern void _PyPreConfig_InitFromConfig(
|
||||
PyPreConfig *preconfig,
|
||||
const PyConfig *config);
|
||||
extern PyStatus _PyPreConfig_InitFromPreConfig(
|
||||
PyPreConfig *preconfig,
|
||||
const PyPreConfig *config2);
|
||||
extern PyObject* _PyPreConfig_AsDict(const PyPreConfig *preconfig);
|
||||
extern void _PyPreConfig_GetConfig(PyPreConfig *preconfig,
|
||||
const PyConfig *config);
|
||||
extern PyStatus _PyPreConfig_Read(PyPreConfig *preconfig,
|
||||
const _PyArgv *args);
|
||||
extern PyStatus _PyPreConfig_Write(const PyPreConfig *preconfig);
|
||||
|
||||
|
||||
/* --- PyConfig ---------------------------------------------- */
|
||||
|
||||
typedef enum {
|
||||
/* Py_Initialize() API: backward compatibility with Python 3.6 and 3.7 */
|
||||
_PyConfig_INIT_COMPAT = 1,
|
||||
_PyConfig_INIT_PYTHON = 2,
|
||||
_PyConfig_INIT_ISOLATED = 3
|
||||
} _PyConfigInitEnum;
|
||||
|
||||
PyAPI_FUNC(void) _PyConfig_InitCompatConfig(PyConfig *config);
|
||||
extern PyStatus _PyConfig_Copy(
|
||||
PyConfig *config,
|
||||
const PyConfig *config2);
|
||||
extern PyStatus _PyConfig_InitPathConfig(
|
||||
PyConfig *config,
|
||||
int compute_path_config);
|
||||
extern PyStatus _PyConfig_Read(PyConfig *config, int compute_path_config);
|
||||
extern PyStatus _PyConfig_Write(const PyConfig *config,
|
||||
struct pyruntimestate *runtime);
|
||||
extern PyStatus _PyConfig_SetPyArgv(
|
||||
PyConfig *config,
|
||||
const _PyArgv *args);
|
||||
|
||||
PyAPI_FUNC(PyObject*) _PyConfig_AsDict(const PyConfig *config);
|
||||
PyAPI_FUNC(int) _PyConfig_FromDict(PyConfig *config, PyObject *dict);
|
||||
|
||||
extern int _Py_global_config_int_max_str_digits;
|
||||
|
||||
|
||||
/* --- Function used for testing ---------------------------------- */
|
||||
|
||||
PyAPI_FUNC(PyObject*) _Py_GetConfigsAsDict(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* !Py_INTERNAL_CORECONFIG_H */
|
||||
@@ -0,0 +1,339 @@
|
||||
#ifndef Py_INTERNAL_INTERP_H
|
||||
#define Py_INTERNAL_INTERP_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef Py_BUILD_CORE
|
||||
# error "this header requires Py_BUILD_CORE define"
|
||||
#endif
|
||||
|
||||
#include "pycore_atomic.h" // _Py_atomic_address
|
||||
#include "pycore_ast_state.h" // struct ast_state
|
||||
#include "pycore_gil.h" // struct _gil_runtime_state
|
||||
#include "pycore_gc.h" // struct _gc_runtime_state
|
||||
#include "pycore_warnings.h" // struct _warnings_runtime_state
|
||||
|
||||
struct _pending_calls {
|
||||
PyThread_type_lock lock;
|
||||
/* Request for running pending calls. */
|
||||
_Py_atomic_int calls_to_do;
|
||||
/* Request for looking at the `async_exc` field of the current
|
||||
thread state.
|
||||
Guarded by the GIL. */
|
||||
int async_exc;
|
||||
#define NPENDINGCALLS 32
|
||||
struct {
|
||||
int (*func)(void *);
|
||||
void *arg;
|
||||
} calls[NPENDINGCALLS];
|
||||
int first;
|
||||
int last;
|
||||
};
|
||||
|
||||
struct _ceval_state {
|
||||
int recursion_limit;
|
||||
/* This single variable consolidates all requests to break out of
|
||||
the fast path in the eval loop. */
|
||||
_Py_atomic_int eval_breaker;
|
||||
/* Request for dropping the GIL */
|
||||
_Py_atomic_int gil_drop_request;
|
||||
struct _pending_calls pending;
|
||||
#ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
|
||||
struct _gil_runtime_state gil;
|
||||
#endif
|
||||
};
|
||||
|
||||
/* 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_bytes_state {
|
||||
PyObject *empty_string;
|
||||
PyBytesObject *characters[256];
|
||||
};
|
||||
|
||||
struct _Py_unicode_ids {
|
||||
Py_ssize_t size;
|
||||
PyObject **array;
|
||||
};
|
||||
|
||||
struct _Py_unicode_state {
|
||||
// The empty Unicode object is a singleton to improve performance.
|
||||
PyObject *empty_string;
|
||||
/* Single character Unicode strings in the Latin-1 range are being
|
||||
shared as well. */
|
||||
PyObject *latin1[256];
|
||||
struct _Py_unicode_fs_codec fs_codec;
|
||||
|
||||
// Unused member kept for ABI backward compatibility with Python 3.10.0:
|
||||
// see bpo-46006.
|
||||
PyObject *unused_interned;
|
||||
|
||||
// Unicode identifiers (_Py_Identifier): see _PyUnicode_FromId()
|
||||
struct _Py_unicode_ids ids;
|
||||
};
|
||||
|
||||
struct _Py_float_state {
|
||||
/* Special free list
|
||||
free_list is a singly-linked list of available PyFloatObjects,
|
||||
linked via abuse of their ob_type members. */
|
||||
int numfree;
|
||||
PyFloatObject *free_list;
|
||||
};
|
||||
|
||||
/* Speed optimization to avoid frequent malloc/free of small tuples */
|
||||
#ifndef PyTuple_MAXSAVESIZE
|
||||
// Largest tuple to save on free list
|
||||
# define PyTuple_MAXSAVESIZE 20
|
||||
#endif
|
||||
#ifndef PyTuple_MAXFREELIST
|
||||
// Maximum number of tuples of each size to save
|
||||
# define PyTuple_MAXFREELIST 2000
|
||||
#endif
|
||||
|
||||
struct _Py_tuple_state {
|
||||
#if PyTuple_MAXSAVESIZE > 0
|
||||
/* Entries 1 up to PyTuple_MAXSAVESIZE are free lists,
|
||||
entry 0 is the empty tuple () of which at most one instance
|
||||
will be allocated. */
|
||||
PyTupleObject *free_list[PyTuple_MAXSAVESIZE];
|
||||
int numfree[PyTuple_MAXSAVESIZE];
|
||||
#endif
|
||||
};
|
||||
|
||||
/* Empty list reuse scheme to save calls to malloc and free */
|
||||
#ifndef PyList_MAXFREELIST
|
||||
# define PyList_MAXFREELIST 80
|
||||
#endif
|
||||
|
||||
struct _Py_list_state {
|
||||
PyListObject *free_list[PyList_MAXFREELIST];
|
||||
int numfree;
|
||||
};
|
||||
|
||||
#ifndef PyDict_MAXFREELIST
|
||||
# define PyDict_MAXFREELIST 80
|
||||
#endif
|
||||
|
||||
struct _Py_dict_state {
|
||||
/* Dictionary reuse scheme to save calls to malloc and free */
|
||||
PyDictObject *free_list[PyDict_MAXFREELIST];
|
||||
int numfree;
|
||||
PyDictKeysObject *keys_free_list[PyDict_MAXFREELIST];
|
||||
int keys_numfree;
|
||||
};
|
||||
|
||||
struct _Py_frame_state {
|
||||
PyFrameObject *free_list;
|
||||
/* number of frames currently in free_list */
|
||||
int numfree;
|
||||
};
|
||||
|
||||
#ifndef _PyAsyncGen_MAXFREELIST
|
||||
# define _PyAsyncGen_MAXFREELIST 80
|
||||
#endif
|
||||
|
||||
struct _Py_async_gen_state {
|
||||
/* Freelists boost performance 6-10%; they also reduce memory
|
||||
fragmentation, as _PyAsyncGenWrappedValue and PyAsyncGenASend
|
||||
are short-living objects that are instantiated for every
|
||||
__anext__() call. */
|
||||
struct _PyAsyncGenWrappedValue* value_freelist[_PyAsyncGen_MAXFREELIST];
|
||||
int value_numfree;
|
||||
|
||||
struct PyAsyncGenASend* asend_freelist[_PyAsyncGen_MAXFREELIST];
|
||||
int asend_numfree;
|
||||
};
|
||||
|
||||
struct _Py_context_state {
|
||||
// List of free PyContext objects
|
||||
PyContext *freelist;
|
||||
int numfree;
|
||||
};
|
||||
|
||||
struct _Py_exc_state {
|
||||
// The dict mapping from errno codes to OSError subclasses
|
||||
PyObject *errnomap;
|
||||
PyBaseExceptionObject *memerrors_freelist;
|
||||
int memerrors_numfree;
|
||||
};
|
||||
|
||||
|
||||
// atexit state
|
||||
typedef struct {
|
||||
PyObject *func;
|
||||
PyObject *args;
|
||||
PyObject *kwargs;
|
||||
} atexit_callback;
|
||||
|
||||
struct atexit_state {
|
||||
atexit_callback **callbacks;
|
||||
int ncallbacks;
|
||||
int callback_len;
|
||||
};
|
||||
|
||||
|
||||
// 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
|
||||
PyObject *name; // reference to exactly a str or None
|
||||
PyObject *value; // borrowed reference or NULL
|
||||
};
|
||||
|
||||
#define MCACHE_SIZE_EXP 12
|
||||
#define MCACHE_STATS 0
|
||||
|
||||
struct type_cache {
|
||||
struct type_cache_entry hashtable[1 << MCACHE_SIZE_EXP];
|
||||
#if MCACHE_STATS
|
||||
size_t hits;
|
||||
size_t misses;
|
||||
size_t collisions;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
/* interpreter state */
|
||||
|
||||
#define _PY_NSMALLPOSINTS 257
|
||||
#define _PY_NSMALLNEGINTS 5
|
||||
|
||||
// _PyLong_GetZero() and _PyLong_GetOne() must always be available
|
||||
#if _PY_NSMALLPOSINTS < 2
|
||||
# error "_PY_NSMALLPOSINTS must be greater than 1"
|
||||
#endif
|
||||
|
||||
// The PyInterpreterState typedef is in Include/pystate.h.
|
||||
struct _is {
|
||||
|
||||
struct _is *next;
|
||||
struct _ts *tstate_head;
|
||||
|
||||
/* 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;
|
||||
|
||||
int64_t id;
|
||||
int64_t id_refcount;
|
||||
int requires_idref;
|
||||
PyThread_type_lock id_mutex;
|
||||
|
||||
int finalizing;
|
||||
|
||||
struct _ceval_state ceval;
|
||||
struct _gc_runtime_state gc;
|
||||
|
||||
// sys.modules dictionary
|
||||
PyObject *modules;
|
||||
PyObject *modules_by_index;
|
||||
// Dictionary of the sys module
|
||||
PyObject *sysdict;
|
||||
// Dictionary of the builtins module
|
||||
PyObject *builtins;
|
||||
// importlib module
|
||||
PyObject *importlib;
|
||||
|
||||
/* Used in Modules/_threadmodule.c. */
|
||||
long num_threads;
|
||||
/* 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 pythread_stacksize;
|
||||
|
||||
PyObject *codec_search_path;
|
||||
PyObject *codec_search_cache;
|
||||
PyObject *codec_error_registry;
|
||||
int codecs_initialized;
|
||||
|
||||
PyConfig config;
|
||||
#ifdef HAVE_DLOPEN
|
||||
int dlopenflags;
|
||||
#endif
|
||||
|
||||
PyObject *dict; /* Stores per-interpreter state */
|
||||
|
||||
PyObject *builtins_copy;
|
||||
PyObject *import_func;
|
||||
// Initialized to _PyEval_EvalFrameDefault().
|
||||
_PyFrameEvalFunction eval_frame;
|
||||
|
||||
Py_ssize_t co_extra_user_count;
|
||||
freefunc co_extra_freefuncs[MAX_CO_EXTRA_USERS];
|
||||
|
||||
#ifdef HAVE_FORK
|
||||
PyObject *before_forkers;
|
||||
PyObject *after_forkers_parent;
|
||||
PyObject *after_forkers_child;
|
||||
#endif
|
||||
|
||||
uint64_t tstate_next_unique_id;
|
||||
|
||||
struct _warnings_runtime_state warnings;
|
||||
struct atexit_state atexit;
|
||||
|
||||
PyObject *audit_hooks;
|
||||
|
||||
/* 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 (not inclusive).
|
||||
*/
|
||||
PyLongObject* small_ints[_PY_NSMALLNEGINTS + _PY_NSMALLPOSINTS];
|
||||
struct _Py_bytes_state bytes;
|
||||
struct _Py_unicode_state unicode;
|
||||
struct _Py_float_state float_state;
|
||||
/* Using a cache is very effective since typically only a single slice is
|
||||
created and then deleted again. */
|
||||
PySliceObject *slice_cache;
|
||||
|
||||
struct _Py_tuple_state tuple;
|
||||
struct _Py_list_state list;
|
||||
struct _Py_dict_state dict_state;
|
||||
struct _Py_frame_state frame;
|
||||
struct _Py_async_gen_state async_gen;
|
||||
struct _Py_context_state context;
|
||||
struct _Py_exc_state exc_state;
|
||||
|
||||
struct ast_state ast;
|
||||
struct type_cache type_cache;
|
||||
|
||||
int int_max_str_digits;
|
||||
};
|
||||
|
||||
extern void _PyInterpreterState_ClearModules(PyInterpreterState *interp);
|
||||
extern void _PyInterpreterState_Clear(PyThreadState *tstate);
|
||||
|
||||
|
||||
/* cross-interpreter data registry */
|
||||
|
||||
/* For now we use a global registry of shareable classes. An
|
||||
alternative would be to add a tp_* slot for a class's
|
||||
crossinterpdatafunc. It would be simpler and more efficient. */
|
||||
|
||||
struct _xidregitem;
|
||||
|
||||
struct _xidregitem {
|
||||
PyTypeObject *cls;
|
||||
crossinterpdatafunc getdata;
|
||||
struct _xidregitem *next;
|
||||
};
|
||||
|
||||
PyAPI_FUNC(struct _is*) _PyInterpreterState_LookUpID(int64_t);
|
||||
|
||||
PyAPI_FUNC(int) _PyInterpreterState_IDInitref(struct _is *);
|
||||
PyAPI_FUNC(int) _PyInterpreterState_IDIncref(struct _is *);
|
||||
PyAPI_FUNC(void) _PyInterpreterState_IDDecref(struct _is *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* !Py_INTERNAL_INTERP_H */
|
||||
@@ -0,0 +1,20 @@
|
||||
#ifndef Py_INTERNAL_LIST_H
|
||||
#define Py_INTERNAL_LIST_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef Py_BUILD_CORE
|
||||
# error "this header requires Py_BUILD_CORE define"
|
||||
#endif
|
||||
|
||||
#include "listobject.h" // _PyList_CAST()
|
||||
|
||||
|
||||
#define _PyList_ITEMS(op) (_PyList_CAST(op)->ob_item)
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* !Py_INTERNAL_LIST_H */
|
||||
@@ -0,0 +1,75 @@
|
||||
#ifndef Py_INTERNAL_LONG_H
|
||||
#define Py_INTERNAL_LONG_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef Py_BUILD_CORE
|
||||
# error "this header requires Py_BUILD_CORE define"
|
||||
#endif
|
||||
|
||||
#include "pycore_interp.h" // PyInterpreterState.small_ints
|
||||
#include "pycore_pystate.h" // _PyThreadState_GET()
|
||||
|
||||
/*
|
||||
* Default int base conversion size limitation: Denial of Service prevention.
|
||||
*
|
||||
* Chosen such that this isn't wildly slow on modern hardware and so that
|
||||
* everyone's existing deployed numpy test suite passes before
|
||||
* https://github.com/numpy/numpy/issues/22098 is widely available.
|
||||
*
|
||||
* $ python -m timeit -s 's = "1"*4300' 'int(s)'
|
||||
* 2000 loops, best of 5: 125 usec per loop
|
||||
* $ python -m timeit -s 's = "1"*4300; v = int(s)' 'str(v)'
|
||||
* 1000 loops, best of 5: 311 usec per loop
|
||||
* (zen2 cloud VM)
|
||||
*
|
||||
* 4300 decimal digits fits a ~14284 bit number.
|
||||
*/
|
||||
#define _PY_LONG_DEFAULT_MAX_STR_DIGITS 4300
|
||||
/*
|
||||
* Threshold for max digits check. For performance reasons int() and
|
||||
* int.__str__() don't checks values that are smaller than this
|
||||
* threshold. Acts as a guaranteed minimum size limit for bignums that
|
||||
* applications can expect from CPython.
|
||||
*
|
||||
* % python -m timeit -s 's = "1"*640; v = int(s)' 'str(int(s))'
|
||||
* 20000 loops, best of 5: 12 usec per loop
|
||||
*
|
||||
* "640 digits should be enough for anyone." - gps
|
||||
* fits a ~2126 bit decimal number.
|
||||
*/
|
||||
#define _PY_LONG_MAX_STR_DIGITS_THRESHOLD 640
|
||||
|
||||
#if ((_PY_LONG_DEFAULT_MAX_STR_DIGITS != 0) && \
|
||||
(_PY_LONG_DEFAULT_MAX_STR_DIGITS < _PY_LONG_MAX_STR_DIGITS_THRESHOLD))
|
||||
# error "_PY_LONG_DEFAULT_MAX_STR_DIGITS smaller than threshold."
|
||||
#endif
|
||||
|
||||
// Don't call this function but _PyLong_GetZero() and _PyLong_GetOne()
|
||||
static inline PyObject* __PyLong_GetSmallInt_internal(int value)
|
||||
{
|
||||
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||
assert(-_PY_NSMALLNEGINTS <= value && value < _PY_NSMALLPOSINTS);
|
||||
size_t index = _PY_NSMALLNEGINTS + value;
|
||||
PyObject *obj = (PyObject*)interp->small_ints[index];
|
||||
// _PyLong_GetZero(), _PyLong_GetOne() and get_small_int() must not be
|
||||
// called before _PyLong_Init() nor after _PyLong_Fini().
|
||||
assert(obj != NULL);
|
||||
return obj;
|
||||
}
|
||||
|
||||
// Return a borrowed reference to the zero singleton.
|
||||
// The function cannot return NULL.
|
||||
static inline PyObject* _PyLong_GetZero(void)
|
||||
{ return __PyLong_GetSmallInt_internal(0); }
|
||||
|
||||
// Return a borrowed reference to the one singleton.
|
||||
// The function cannot return NULL.
|
||||
static inline PyObject* _PyLong_GetOne(void)
|
||||
{ return __PyLong_GetSmallInt_internal(1); }
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* !Py_INTERNAL_LONG_H */
|
||||
@@ -0,0 +1,42 @@
|
||||
#ifndef Py_INTERNAL_MODULEOBJECT_H
|
||||
#define Py_INTERNAL_MODULEOBJECT_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef Py_BUILD_CORE
|
||||
# error "this header requires Py_BUILD_CORE define"
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
PyObject *md_dict;
|
||||
struct PyModuleDef *md_def;
|
||||
void *md_state;
|
||||
PyObject *md_weaklist;
|
||||
// for logging purposes after md_dict is cleared
|
||||
PyObject *md_name;
|
||||
} PyModuleObject;
|
||||
|
||||
static inline PyModuleDef* _PyModule_GetDef(PyObject *mod) {
|
||||
assert(PyModule_Check(mod));
|
||||
return ((PyModuleObject *)mod)->md_def;
|
||||
}
|
||||
|
||||
static inline void* _PyModule_GetState(PyObject* mod) {
|
||||
assert(PyModule_Check(mod));
|
||||
return ((PyModuleObject *)mod)->md_state;
|
||||
}
|
||||
|
||||
static inline PyObject* _PyModule_GetDict(PyObject *mod) {
|
||||
assert(PyModule_Check(mod));
|
||||
PyObject *dict = ((PyModuleObject *)mod) -> md_dict;
|
||||
// _PyModule_GetDict(mod) must not be used after calling module_clear(mod)
|
||||
assert(dict != NULL);
|
||||
return dict;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* !Py_INTERNAL_MODULEOBJECT_H */
|
||||
@@ -0,0 +1,186 @@
|
||||
#ifndef Py_INTERNAL_OBJECT_H
|
||||
#define Py_INTERNAL_OBJECT_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef Py_BUILD_CORE
|
||||
# error "this header requires Py_BUILD_CORE define"
|
||||
#endif
|
||||
|
||||
#include "pycore_gc.h" // _PyObject_GC_IS_TRACKED()
|
||||
#include "pycore_interp.h" // PyInterpreterState.gc
|
||||
#include "pycore_pystate.h" // _PyInterpreterState_GET()
|
||||
|
||||
PyAPI_FUNC(int) _PyType_CheckConsistency(PyTypeObject *type);
|
||||
PyAPI_FUNC(int) _PyDict_CheckConsistency(PyObject *mp, int check_content);
|
||||
|
||||
/* Update the Python traceback of an object. This function must be called
|
||||
when a memory block is reused from a free list.
|
||||
|
||||
Internal function called by _Py_NewReference(). */
|
||||
extern int _PyTraceMalloc_NewReference(PyObject *op);
|
||||
|
||||
// Fast inlined version of PyType_HasFeature()
|
||||
static inline int
|
||||
_PyType_HasFeature(PyTypeObject *type, unsigned long feature) {
|
||||
return ((type->tp_flags & feature) != 0);
|
||||
}
|
||||
|
||||
extern void _PyType_InitCache(PyInterpreterState *interp);
|
||||
|
||||
/* Only private in Python 3.10 and 3.9.8+; public in 3.11 */
|
||||
extern PyObject *_PyType_GetQualName(PyTypeObject *type);
|
||||
|
||||
/* Inline functions trading binary compatibility for speed:
|
||||
_PyObject_Init() is the fast version of PyObject_Init(), and
|
||||
_PyObject_InitVar() is the fast version of PyObject_InitVar().
|
||||
|
||||
These inline functions must not be called with op=NULL. */
|
||||
static inline void
|
||||
_PyObject_Init(PyObject *op, PyTypeObject *typeobj)
|
||||
{
|
||||
assert(op != NULL);
|
||||
Py_SET_TYPE(op, typeobj);
|
||||
if (_PyType_HasFeature(typeobj, Py_TPFLAGS_HEAPTYPE)) {
|
||||
Py_INCREF(typeobj);
|
||||
}
|
||||
_Py_NewReference(op);
|
||||
}
|
||||
|
||||
static inline void
|
||||
_PyObject_InitVar(PyVarObject *op, PyTypeObject *typeobj, Py_ssize_t size)
|
||||
{
|
||||
assert(op != NULL);
|
||||
Py_SET_SIZE(op, size);
|
||||
_PyObject_Init((PyObject *)op, typeobj);
|
||||
}
|
||||
|
||||
|
||||
/* Tell the GC to track this object.
|
||||
*
|
||||
* The object must not be tracked by the GC.
|
||||
*
|
||||
* NB: While the object is tracked by the collector, it must be safe to call the
|
||||
* ob_traverse method.
|
||||
*
|
||||
* Internal note: interp->gc.generation0->_gc_prev doesn't have any bit flags
|
||||
* because it's not object header. So we don't use _PyGCHead_PREV() and
|
||||
* _PyGCHead_SET_PREV() for it to avoid unnecessary bitwise operations.
|
||||
*
|
||||
* See also the public PyObject_GC_Track() function.
|
||||
*/
|
||||
static inline void _PyObject_GC_TRACK(
|
||||
// The preprocessor removes _PyObject_ASSERT_FROM() calls if NDEBUG is defined
|
||||
#ifndef NDEBUG
|
||||
const char *filename, int lineno,
|
||||
#endif
|
||||
PyObject *op)
|
||||
{
|
||||
_PyObject_ASSERT_FROM(op, !_PyObject_GC_IS_TRACKED(op),
|
||||
"object already tracked by the garbage collector",
|
||||
filename, lineno, __func__);
|
||||
|
||||
PyGC_Head *gc = _Py_AS_GC(op);
|
||||
_PyObject_ASSERT_FROM(op,
|
||||
(gc->_gc_prev & _PyGC_PREV_MASK_COLLECTING) == 0,
|
||||
"object is in generation which is garbage collected",
|
||||
filename, lineno, __func__);
|
||||
|
||||
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||
PyGC_Head *generation0 = interp->gc.generation0;
|
||||
PyGC_Head *last = (PyGC_Head*)(generation0->_gc_prev);
|
||||
_PyGCHead_SET_NEXT(last, gc);
|
||||
_PyGCHead_SET_PREV(gc, last);
|
||||
_PyGCHead_SET_NEXT(gc, generation0);
|
||||
generation0->_gc_prev = (uintptr_t)gc;
|
||||
}
|
||||
|
||||
/* Tell the GC to stop tracking this object.
|
||||
*
|
||||
* Internal note: This may be called while GC. So _PyGC_PREV_MASK_COLLECTING
|
||||
* must be cleared. But _PyGC_PREV_MASK_FINALIZED bit is kept.
|
||||
*
|
||||
* The object must be tracked by the GC.
|
||||
*
|
||||
* See also the public PyObject_GC_UnTrack() which accept an object which is
|
||||
* not tracked.
|
||||
*/
|
||||
static inline void _PyObject_GC_UNTRACK(
|
||||
// The preprocessor removes _PyObject_ASSERT_FROM() calls if NDEBUG is defined
|
||||
#ifndef NDEBUG
|
||||
const char *filename, int lineno,
|
||||
#endif
|
||||
PyObject *op)
|
||||
{
|
||||
_PyObject_ASSERT_FROM(op, _PyObject_GC_IS_TRACKED(op),
|
||||
"object not tracked by the garbage collector",
|
||||
filename, lineno, __func__);
|
||||
|
||||
PyGC_Head *gc = _Py_AS_GC(op);
|
||||
PyGC_Head *prev = _PyGCHead_PREV(gc);
|
||||
PyGC_Head *next = _PyGCHead_NEXT(gc);
|
||||
_PyGCHead_SET_NEXT(prev, next);
|
||||
_PyGCHead_SET_PREV(next, prev);
|
||||
gc->_gc_next = 0;
|
||||
gc->_gc_prev &= _PyGC_PREV_MASK_FINALIZED;
|
||||
}
|
||||
|
||||
// Macros to accept any type for the parameter, and to automatically pass
|
||||
// the filename and the filename (if NDEBUG is not defined) where the macro
|
||||
// is called.
|
||||
#ifdef NDEBUG
|
||||
# define _PyObject_GC_TRACK(op) \
|
||||
_PyObject_GC_TRACK(_PyObject_CAST(op))
|
||||
# define _PyObject_GC_UNTRACK(op) \
|
||||
_PyObject_GC_UNTRACK(_PyObject_CAST(op))
|
||||
#else
|
||||
# define _PyObject_GC_TRACK(op) \
|
||||
_PyObject_GC_TRACK(__FILE__, __LINE__, _PyObject_CAST(op))
|
||||
# define _PyObject_GC_UNTRACK(op) \
|
||||
_PyObject_GC_UNTRACK(__FILE__, __LINE__, _PyObject_CAST(op))
|
||||
#endif
|
||||
|
||||
#ifdef Py_REF_DEBUG
|
||||
extern void _PyDebug_PrintTotalRefs(void);
|
||||
#endif
|
||||
|
||||
#ifdef Py_TRACE_REFS
|
||||
extern void _Py_AddToAllObjects(PyObject *op, int force);
|
||||
extern void _Py_PrintReferences(FILE *);
|
||||
extern void _Py_PrintReferenceAddresses(FILE *);
|
||||
#endif
|
||||
|
||||
static inline PyObject **
|
||||
_PyObject_GET_WEAKREFS_LISTPTR(PyObject *op)
|
||||
{
|
||||
Py_ssize_t offset = Py_TYPE(op)->tp_weaklistoffset;
|
||||
return (PyObject **)((char *)op + offset);
|
||||
}
|
||||
|
||||
// Fast inlined version of PyObject_IS_GC()
|
||||
static inline int
|
||||
_PyObject_IS_GC(PyObject *obj)
|
||||
{
|
||||
return (PyType_IS_GC(Py_TYPE(obj))
|
||||
&& (Py_TYPE(obj)->tp_is_gc == NULL
|
||||
|| Py_TYPE(obj)->tp_is_gc(obj)));
|
||||
}
|
||||
|
||||
// Fast inlined version of PyType_IS_GC()
|
||||
#define _PyType_IS_GC(t) _PyType_HasFeature((t), Py_TPFLAGS_HAVE_GC)
|
||||
|
||||
// Usage: assert(_Py_CheckSlotResult(obj, "__getitem__", result != NULL));
|
||||
extern int _Py_CheckSlotResult(
|
||||
PyObject *obj,
|
||||
const char *slot_name,
|
||||
int success);
|
||||
|
||||
// PyType_Ready() must be called if _PyType_IsReady() is false.
|
||||
// See also the Py_TPFLAGS_READY flag.
|
||||
#define _PyType_IsReady(type) ((type)->tp_dict != NULL)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* !Py_INTERNAL_OBJECT_H */
|
||||
@@ -0,0 +1,31 @@
|
||||
#ifndef Py_INTERNAL_PARSER_H
|
||||
#define Py_INTERNAL_PARSER_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef Py_BUILD_CORE
|
||||
# error "this header requires Py_BUILD_CORE define"
|
||||
#endif
|
||||
|
||||
extern struct _mod* _PyParser_ASTFromString(
|
||||
const char *str,
|
||||
PyObject* filename,
|
||||
int mode,
|
||||
PyCompilerFlags *flags,
|
||||
PyArena *arena);
|
||||
extern struct _mod* _PyParser_ASTFromFile(
|
||||
FILE *fp,
|
||||
PyObject *filename_ob,
|
||||
const char *enc,
|
||||
int mode,
|
||||
const char *ps1,
|
||||
const char *ps2,
|
||||
PyCompilerFlags *flags,
|
||||
int *errcode,
|
||||
PyArena *arena);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* !Py_INTERNAL_PARSER_H */
|
||||
@@ -0,0 +1,73 @@
|
||||
#ifndef Py_INTERNAL_PATHCONFIG_H
|
||||
#define Py_INTERNAL_PATHCONFIG_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef Py_BUILD_CORE
|
||||
# error "this header requires Py_BUILD_CORE define"
|
||||
#endif
|
||||
|
||||
typedef struct _PyPathConfig {
|
||||
/* Full path to the Python program */
|
||||
wchar_t *program_full_path;
|
||||
wchar_t *prefix;
|
||||
wchar_t *exec_prefix;
|
||||
/* Set by Py_SetPath(), or computed by _PyConfig_InitPathConfig() */
|
||||
wchar_t *module_search_path;
|
||||
/* Python program name */
|
||||
wchar_t *program_name;
|
||||
/* Set by Py_SetPythonHome() or PYTHONHOME environment variable */
|
||||
wchar_t *home;
|
||||
#ifdef MS_WINDOWS
|
||||
/* isolated and site_import are used to set Py_IsolatedFlag and
|
||||
Py_NoSiteFlag flags on Windows in read_pth_file(). These fields
|
||||
are ignored when their value are equal to -1 (unset). */
|
||||
int isolated;
|
||||
int site_import;
|
||||
/* Set when a venv is detected */
|
||||
wchar_t *base_executable;
|
||||
#endif
|
||||
} _PyPathConfig;
|
||||
|
||||
#ifdef MS_WINDOWS
|
||||
# define _PyPathConfig_INIT \
|
||||
{.module_search_path = NULL, \
|
||||
.isolated = -1, \
|
||||
.site_import = -1}
|
||||
#else
|
||||
# define _PyPathConfig_INIT \
|
||||
{.module_search_path = NULL}
|
||||
#endif
|
||||
/* Note: _PyPathConfig_INIT sets other fields to 0/NULL */
|
||||
|
||||
PyAPI_DATA(_PyPathConfig) _Py_path_config;
|
||||
#ifdef MS_WINDOWS
|
||||
PyAPI_DATA(wchar_t*) _Py_dll_path;
|
||||
#endif
|
||||
|
||||
extern void _PyPathConfig_ClearGlobal(void);
|
||||
|
||||
extern PyStatus _PyPathConfig_Calculate(
|
||||
_PyPathConfig *pathconfig,
|
||||
const PyConfig *config);
|
||||
extern int _PyPathConfig_ComputeSysPath0(
|
||||
const PyWideStringList *argv,
|
||||
PyObject **path0);
|
||||
extern PyStatus _Py_FindEnvConfigValue(
|
||||
FILE *env_file,
|
||||
const wchar_t *key,
|
||||
wchar_t **value_p);
|
||||
|
||||
#ifdef MS_WINDOWS
|
||||
extern wchar_t* _Py_GetDLLPath(void);
|
||||
#endif
|
||||
|
||||
extern PyStatus _PyConfig_WritePathConfig(const PyConfig *config);
|
||||
extern void _Py_DumpPathConfig(PyThreadState *tstate);
|
||||
extern PyObject* _PyPathConfig_AsDict(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* !Py_INTERNAL_PATHCONFIG_H */
|
||||
@@ -0,0 +1,64 @@
|
||||
/* An arena-like memory interface for the compiler.
|
||||
*/
|
||||
|
||||
#ifndef Py_INTERNAL_PYARENA_H
|
||||
#define Py_INTERNAL_PYARENA_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef Py_BUILD_CORE
|
||||
# error "this header requires Py_BUILD_CORE define"
|
||||
#endif
|
||||
|
||||
typedef struct _arena PyArena;
|
||||
|
||||
/* _PyArena_New() and _PyArena_Free() create a new arena and free it,
|
||||
respectively. Once an arena has been created, it can be used
|
||||
to allocate memory via _PyArena_Malloc(). Pointers to PyObject can
|
||||
also be registered with the arena via _PyArena_AddPyObject(), and the
|
||||
arena will ensure that the PyObjects stay alive at least until
|
||||
_PyArena_Free() is called. When an arena is freed, all the memory it
|
||||
allocated is freed, the arena releases internal references to registered
|
||||
PyObject*, and none of its pointers are valid.
|
||||
XXX (tim) What does "none of its pointers are valid" mean? Does it
|
||||
XXX mean that pointers previously obtained via _PyArena_Malloc() are
|
||||
XXX no longer valid? (That's clearly true, but not sure that's what
|
||||
XXX the text is trying to say.)
|
||||
|
||||
_PyArena_New() returns an arena pointer. On error, it
|
||||
returns a negative number and sets an exception.
|
||||
XXX (tim): Not true. On error, _PyArena_New() actually returns NULL,
|
||||
XXX and looks like it may or may not set an exception (e.g., if the
|
||||
XXX internal PyList_New(0) returns NULL, _PyArena_New() passes that on
|
||||
XXX and an exception is set; OTOH, if the internal
|
||||
XXX block_new(DEFAULT_BLOCK_SIZE) returns NULL, that's passed on but
|
||||
XXX an exception is not set in that case).
|
||||
*/
|
||||
PyAPI_FUNC(PyArena*) _PyArena_New(void);
|
||||
PyAPI_FUNC(void) _PyArena_Free(PyArena *);
|
||||
|
||||
/* Mostly like malloc(), return the address of a block of memory spanning
|
||||
* `size` bytes, or return NULL (without setting an exception) if enough
|
||||
* new memory can't be obtained. Unlike malloc(0), _PyArena_Malloc() with
|
||||
* size=0 does not guarantee to return a unique pointer (the pointer
|
||||
* returned may equal one or more other pointers obtained from
|
||||
* _PyArena_Malloc()).
|
||||
* Note that pointers obtained via _PyArena_Malloc() must never be passed to
|
||||
* the system free() or realloc(), or to any of Python's similar memory-
|
||||
* management functions. _PyArena_Malloc()-obtained pointers remain valid
|
||||
* until _PyArena_Free(ar) is called, at which point all pointers obtained
|
||||
* from the arena `ar` become invalid simultaneously.
|
||||
*/
|
||||
PyAPI_FUNC(void*) _PyArena_Malloc(PyArena *, size_t size);
|
||||
|
||||
/* This routine isn't a proper arena allocation routine. It takes
|
||||
* a PyObject* and records it so that it can be DECREFed when the
|
||||
* arena is freed.
|
||||
*/
|
||||
PyAPI_FUNC(int) _PyArena_AddPyObject(PyArena *, PyObject *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* !Py_INTERNAL_PYARENA_H */
|
||||
@@ -0,0 +1,96 @@
|
||||
#ifndef Py_INTERNAL_PYERRORS_H
|
||||
#define Py_INTERNAL_PYERRORS_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef Py_BUILD_CORE
|
||||
# error "this header requires Py_BUILD_CORE define"
|
||||
#endif
|
||||
|
||||
static inline PyObject* _PyErr_Occurred(PyThreadState *tstate)
|
||||
{
|
||||
assert(tstate != NULL);
|
||||
return tstate->curexc_type;
|
||||
}
|
||||
|
||||
static inline void _PyErr_ClearExcState(_PyErr_StackItem *exc_state)
|
||||
{
|
||||
PyObject *t, *v, *tb;
|
||||
t = exc_state->exc_type;
|
||||
v = exc_state->exc_value;
|
||||
tb = exc_state->exc_traceback;
|
||||
exc_state->exc_type = NULL;
|
||||
exc_state->exc_value = NULL;
|
||||
exc_state->exc_traceback = NULL;
|
||||
Py_XDECREF(t);
|
||||
Py_XDECREF(v);
|
||||
Py_XDECREF(tb);
|
||||
}
|
||||
|
||||
|
||||
PyAPI_FUNC(void) _PyErr_Fetch(
|
||||
PyThreadState *tstate,
|
||||
PyObject **type,
|
||||
PyObject **value,
|
||||
PyObject **traceback);
|
||||
|
||||
PyAPI_FUNC(int) _PyErr_ExceptionMatches(
|
||||
PyThreadState *tstate,
|
||||
PyObject *exc);
|
||||
|
||||
PyAPI_FUNC(void) _PyErr_Restore(
|
||||
PyThreadState *tstate,
|
||||
PyObject *type,
|
||||
PyObject *value,
|
||||
PyObject *traceback);
|
||||
|
||||
PyAPI_FUNC(void) _PyErr_SetObject(
|
||||
PyThreadState *tstate,
|
||||
PyObject *type,
|
||||
PyObject *value);
|
||||
|
||||
PyAPI_FUNC(void) _PyErr_ChainStackItem(
|
||||
_PyErr_StackItem *exc_info);
|
||||
|
||||
PyAPI_FUNC(void) _PyErr_Clear(PyThreadState *tstate);
|
||||
|
||||
PyAPI_FUNC(void) _PyErr_SetNone(PyThreadState *tstate, PyObject *exception);
|
||||
|
||||
PyAPI_FUNC(PyObject *) _PyErr_NoMemory(PyThreadState *tstate);
|
||||
|
||||
PyAPI_FUNC(void) _PyErr_SetString(
|
||||
PyThreadState *tstate,
|
||||
PyObject *exception,
|
||||
const char *string);
|
||||
|
||||
PyAPI_FUNC(PyObject *) _PyErr_Format(
|
||||
PyThreadState *tstate,
|
||||
PyObject *exception,
|
||||
const char *format,
|
||||
...);
|
||||
|
||||
PyAPI_FUNC(void) _PyErr_NormalizeException(
|
||||
PyThreadState *tstate,
|
||||
PyObject **exc,
|
||||
PyObject **val,
|
||||
PyObject **tb);
|
||||
|
||||
PyAPI_FUNC(PyObject *) _PyErr_FormatFromCauseTstate(
|
||||
PyThreadState *tstate,
|
||||
PyObject *exception,
|
||||
const char *format,
|
||||
...);
|
||||
|
||||
PyAPI_FUNC(int) _PyErr_CheckSignalsTstate(PyThreadState *tstate);
|
||||
|
||||
PyAPI_FUNC(void) _Py_DumpExtensionModules(int fd, PyInterpreterState *interp);
|
||||
|
||||
extern PyObject* _Py_Offer_Suggestions(PyObject* exception);
|
||||
PyAPI_FUNC(Py_ssize_t) _Py_UTF8_Edit_Cost(PyObject *str_a, PyObject *str_b,
|
||||
Py_ssize_t max_cost);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* !Py_INTERNAL_PYERRORS_H */
|
||||
@@ -0,0 +1,10 @@
|
||||
#ifndef Py_INTERNAL_HASH_H
|
||||
#define Py_INTERNAL_HASH_H
|
||||
|
||||
#ifndef Py_BUILD_CORE
|
||||
# error "this header requires Py_BUILD_CORE define"
|
||||
#endif
|
||||
|
||||
uint64_t _Py_KeyedHash(uint64_t, const char *, Py_ssize_t);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,141 @@
|
||||
#ifndef Py_INTERNAL_LIFECYCLE_H
|
||||
#define Py_INTERNAL_LIFECYCLE_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef Py_BUILD_CORE
|
||||
# error "this header requires Py_BUILD_CORE define"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SIGNAL_H
|
||||
#include <signal.h>
|
||||
#endif
|
||||
|
||||
#include "pycore_runtime.h" // _PyRuntimeState
|
||||
|
||||
#ifndef NSIG
|
||||
# if defined(_NSIG)
|
||||
# define NSIG _NSIG /* For BSD/SysV */
|
||||
# elif defined(_SIGMAX)
|
||||
# define NSIG (_SIGMAX + 1) /* For QNX */
|
||||
# elif defined(SIGMAX)
|
||||
# define NSIG (SIGMAX + 1) /* For djgpp */
|
||||
# else
|
||||
# define NSIG 64 /* Use a reasonable default value */
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Forward declarations */
|
||||
struct _PyArgv;
|
||||
struct pyruntimestate;
|
||||
|
||||
/* True if the main interpreter thread exited due to an unhandled
|
||||
* KeyboardInterrupt exception, suggesting the user pressed ^C. */
|
||||
PyAPI_DATA(int) _Py_UnhandledKeyboardInterrupt;
|
||||
|
||||
extern int _Py_SetFileSystemEncoding(
|
||||
const char *encoding,
|
||||
const char *errors);
|
||||
extern void _Py_ClearFileSystemEncoding(void);
|
||||
extern PyStatus _PyUnicode_InitEncodings(PyThreadState *tstate);
|
||||
#ifdef MS_WINDOWS
|
||||
extern int _PyUnicode_EnableLegacyWindowsFSEncoding(void);
|
||||
#endif
|
||||
|
||||
PyAPI_FUNC(void) _Py_ClearStandardStreamEncoding(void);
|
||||
|
||||
PyAPI_FUNC(int) _Py_IsLocaleCoercionTarget(const char *ctype_loc);
|
||||
|
||||
/* Various one-time initializers */
|
||||
|
||||
extern PyStatus _PyUnicode_Init(PyInterpreterState *interp);
|
||||
extern PyStatus _PyUnicode_InitTypes(void);
|
||||
extern PyStatus _PyBytes_Init(PyInterpreterState *interp);
|
||||
extern int _PyStructSequence_Init(void);
|
||||
extern int _PyLong_Init(PyInterpreterState *interp);
|
||||
extern int _PyLong_InitTypes(void);
|
||||
extern PyStatus _PyTuple_Init(PyInterpreterState *interp);
|
||||
extern PyStatus _PyFaulthandler_Init(int enable);
|
||||
extern int _PyTraceMalloc_Init(int enable);
|
||||
extern PyObject * _PyBuiltin_Init(PyInterpreterState *interp);
|
||||
extern PyStatus _PySys_Create(
|
||||
PyThreadState *tstate,
|
||||
PyObject **sysmod_p);
|
||||
extern PyStatus _PySys_ReadPreinitWarnOptions(PyWideStringList *options);
|
||||
extern PyStatus _PySys_ReadPreinitXOptions(PyConfig *config);
|
||||
extern int _PySys_UpdateConfig(PyThreadState *tstate);
|
||||
extern PyStatus _PyExc_Init(PyInterpreterState *interp);
|
||||
extern PyStatus _PyErr_InitTypes(void);
|
||||
extern PyStatus _PyBuiltins_AddExceptions(PyObject * bltinmod);
|
||||
extern void _PyFloat_Init(void);
|
||||
extern int _PyFloat_InitTypes(void);
|
||||
extern PyStatus _Py_HashRandomization_Init(const PyConfig *);
|
||||
|
||||
extern PyStatus _PyTypes_Init(void);
|
||||
extern PyStatus _PyTypes_InitSlotDefs(void);
|
||||
extern PyStatus _PyImportZip_Init(PyThreadState *tstate);
|
||||
extern PyStatus _PyGC_Init(PyInterpreterState *interp);
|
||||
extern PyStatus _PyAtExit_Init(PyInterpreterState *interp);
|
||||
|
||||
|
||||
/* Various internal finalizers */
|
||||
|
||||
extern void _PyFrame_Fini(PyInterpreterState *interp);
|
||||
extern void _PyDict_Fini(PyInterpreterState *interp);
|
||||
extern void _PyTuple_Fini(PyInterpreterState *interp);
|
||||
extern void _PyList_Fini(PyInterpreterState *interp);
|
||||
extern void _PyBytes_Fini(PyInterpreterState *interp);
|
||||
extern void _PyFloat_Fini(PyInterpreterState *interp);
|
||||
extern void _PySlice_Fini(PyInterpreterState *interp);
|
||||
extern void _PyAsyncGen_Fini(PyInterpreterState *interp);
|
||||
|
||||
extern int _PySignal_Init(int install_signal_handlers);
|
||||
extern void _PySignal_Fini(void);
|
||||
|
||||
extern void _PyExc_Fini(PyInterpreterState *interp);
|
||||
extern void _PyImport_Fini(void);
|
||||
extern void _PyImport_Fini2(void);
|
||||
extern void _PyGC_Fini(PyInterpreterState *interp);
|
||||
extern void _PyType_Fini(PyInterpreterState *interp);
|
||||
extern void _Py_HashRandomization_Fini(void);
|
||||
extern void _PyUnicode_Fini(PyInterpreterState *interp);
|
||||
extern void _PyUnicode_ClearInterned(PyInterpreterState *interp);
|
||||
extern void _PyLong_Fini(PyInterpreterState *interp);
|
||||
extern void _PyFaulthandler_Fini(void);
|
||||
extern void _PyHash_Fini(void);
|
||||
extern void _PyTraceMalloc_Fini(void);
|
||||
extern void _PyWarnings_Fini(PyInterpreterState *interp);
|
||||
extern void _PyAST_Fini(PyInterpreterState *interp);
|
||||
extern void _PyAtExit_Fini(PyInterpreterState *interp);
|
||||
|
||||
extern PyStatus _PyGILState_Init(_PyRuntimeState *runtime);
|
||||
extern PyStatus _PyGILState_SetTstate(PyThreadState *tstate);
|
||||
extern void _PyGILState_Fini(PyInterpreterState *interp);
|
||||
|
||||
PyAPI_FUNC(void) _PyGC_DumpShutdownStats(PyInterpreterState *interp);
|
||||
|
||||
PyAPI_FUNC(PyStatus) _Py_PreInitializeFromPyArgv(
|
||||
const PyPreConfig *src_config,
|
||||
const struct _PyArgv *args);
|
||||
PyAPI_FUNC(PyStatus) _Py_PreInitializeFromConfig(
|
||||
const PyConfig *config,
|
||||
const struct _PyArgv *args);
|
||||
|
||||
|
||||
PyAPI_FUNC(int) _Py_HandleSystemExit(int *exitcode_p);
|
||||
|
||||
PyAPI_FUNC(PyObject*) _PyErr_WriteUnraisableDefaultHook(PyObject *unraisable);
|
||||
|
||||
PyAPI_FUNC(void) _PyErr_Print(PyThreadState *tstate);
|
||||
PyAPI_FUNC(void) _PyErr_Display(PyObject *file, PyObject *exception,
|
||||
PyObject *value, PyObject *tb);
|
||||
|
||||
PyAPI_FUNC(void) _PyThreadState_DeleteCurrent(PyThreadState *tstate);
|
||||
|
||||
extern void _PyAtExit_Call(PyInterpreterState *interp);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* !Py_INTERNAL_LIFECYCLE_H */
|
||||
@@ -0,0 +1,101 @@
|
||||
#ifndef Py_INTERNAL_PYMEM_H
|
||||
#define Py_INTERNAL_PYMEM_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef Py_BUILD_CORE
|
||||
# error "this header requires Py_BUILD_CORE define"
|
||||
#endif
|
||||
|
||||
#include "pymem.h" // PyMemAllocatorName
|
||||
|
||||
|
||||
/* Set the memory allocator of the specified domain to the default.
|
||||
Save the old allocator into *old_alloc if it's non-NULL.
|
||||
Return on success, or return -1 if the domain is unknown. */
|
||||
PyAPI_FUNC(int) _PyMem_SetDefaultAllocator(
|
||||
PyMemAllocatorDomain domain,
|
||||
PyMemAllocatorEx *old_alloc);
|
||||
|
||||
/* Special bytes broadcast into debug memory blocks at appropriate times.
|
||||
Strings of these are unlikely to be valid addresses, floats, ints or
|
||||
7-bit ASCII.
|
||||
|
||||
- PYMEM_CLEANBYTE: clean (newly allocated) memory
|
||||
- PYMEM_DEADBYTE dead (newly freed) memory
|
||||
- PYMEM_FORBIDDENBYTE: untouchable bytes at each end of a block
|
||||
|
||||
Byte patterns 0xCB, 0xDB and 0xFB have been replaced with 0xCD, 0xDD and
|
||||
0xFD to use the same values than Windows CRT debug malloc() and free().
|
||||
If modified, _PyMem_IsPtrFreed() should be updated as well. */
|
||||
#define PYMEM_CLEANBYTE 0xCD
|
||||
#define PYMEM_DEADBYTE 0xDD
|
||||
#define PYMEM_FORBIDDENBYTE 0xFD
|
||||
|
||||
/* Heuristic checking if a pointer value is newly allocated
|
||||
(uninitialized), newly freed or NULL (is equal to zero).
|
||||
|
||||
The pointer is not dereferenced, only the pointer value is checked.
|
||||
|
||||
The heuristic relies on the debug hooks on Python memory allocators which
|
||||
fills newly allocated memory with CLEANBYTE (0xCD) and newly freed memory
|
||||
with DEADBYTE (0xDD). Detect also "untouchable bytes" marked
|
||||
with FORBIDDENBYTE (0xFD). */
|
||||
static inline int _PyMem_IsPtrFreed(const void *ptr)
|
||||
{
|
||||
uintptr_t value = (uintptr_t)ptr;
|
||||
#if SIZEOF_VOID_P == 8
|
||||
return (value == 0
|
||||
|| value == (uintptr_t)0xCDCDCDCDCDCDCDCD
|
||||
|| value == (uintptr_t)0xDDDDDDDDDDDDDDDD
|
||||
|| value == (uintptr_t)0xFDFDFDFDFDFDFDFD);
|
||||
#elif SIZEOF_VOID_P == 4
|
||||
return (value == 0
|
||||
|| value == (uintptr_t)0xCDCDCDCD
|
||||
|| value == (uintptr_t)0xDDDDDDDD
|
||||
|| value == (uintptr_t)0xFDFDFDFD);
|
||||
#else
|
||||
# error "unknown pointer size"
|
||||
#endif
|
||||
}
|
||||
|
||||
PyAPI_FUNC(int) _PyMem_GetAllocatorName(
|
||||
const char *name,
|
||||
PyMemAllocatorName *allocator);
|
||||
|
||||
/* Configure the Python memory allocators.
|
||||
Pass PYMEM_ALLOCATOR_DEFAULT to use default allocators.
|
||||
PYMEM_ALLOCATOR_NOT_SET does nothing. */
|
||||
PyAPI_FUNC(int) _PyMem_SetupAllocators(PyMemAllocatorName allocator);
|
||||
|
||||
struct _PyTraceMalloc_Config {
|
||||
/* Module initialized?
|
||||
Variable protected by the GIL */
|
||||
enum {
|
||||
TRACEMALLOC_NOT_INITIALIZED,
|
||||
TRACEMALLOC_INITIALIZED,
|
||||
TRACEMALLOC_FINALIZED
|
||||
} initialized;
|
||||
|
||||
/* Is tracemalloc tracing memory allocations?
|
||||
Variable protected by the GIL */
|
||||
int tracing;
|
||||
|
||||
/* limit of the number of frames in a traceback, 1 by default.
|
||||
Variable protected by the GIL. */
|
||||
int max_nframe;
|
||||
};
|
||||
|
||||
#define _PyTraceMalloc_Config_INIT \
|
||||
{.initialized = TRACEMALLOC_NOT_INITIALIZED, \
|
||||
.tracing = 0, \
|
||||
.max_nframe = 1}
|
||||
|
||||
PyAPI_DATA(struct _PyTraceMalloc_Config) _Py_tracemalloc_config;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* !Py_INTERNAL_PYMEM_H */
|
||||
@@ -0,0 +1,153 @@
|
||||
#ifndef Py_INTERNAL_PYSTATE_H
|
||||
#define Py_INTERNAL_PYSTATE_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef Py_BUILD_CORE
|
||||
# error "this header requires Py_BUILD_CORE define"
|
||||
#endif
|
||||
|
||||
#include "pycore_runtime.h" /* PyRuntimeState */
|
||||
|
||||
|
||||
/* Check if the current thread is the main thread.
|
||||
Use _Py_IsMainInterpreter() to check if it's the main interpreter. */
|
||||
static inline int
|
||||
_Py_IsMainThread(void)
|
||||
{
|
||||
unsigned long thread = PyThread_get_thread_ident();
|
||||
return (thread == _PyRuntime.main_thread);
|
||||
}
|
||||
|
||||
|
||||
static inline int
|
||||
_Py_IsMainInterpreter(PyInterpreterState *interp)
|
||||
{
|
||||
/* Use directly _PyRuntime rather than tstate->interp->runtime, since
|
||||
this function is used in performance critical code path (ceval) */
|
||||
return (interp == _PyRuntime.interpreters.main);
|
||||
}
|
||||
|
||||
|
||||
/* Only handle signals on the main thread of the main interpreter. */
|
||||
static inline int
|
||||
_Py_ThreadCanHandleSignals(PyInterpreterState *interp)
|
||||
{
|
||||
return (_Py_IsMainThread() && interp == _PyRuntime.interpreters.main);
|
||||
}
|
||||
|
||||
|
||||
/* Only execute pending calls on the main thread. */
|
||||
static inline int
|
||||
_Py_ThreadCanHandlePendingCalls(void)
|
||||
{
|
||||
return _Py_IsMainThread();
|
||||
}
|
||||
|
||||
|
||||
/* Variable and macro for in-line access to current thread
|
||||
and interpreter state */
|
||||
|
||||
#ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
|
||||
PyAPI_FUNC(PyThreadState*) _PyThreadState_GetTSS(void);
|
||||
#endif
|
||||
|
||||
static inline PyThreadState*
|
||||
_PyRuntimeState_GetThreadState(_PyRuntimeState *runtime)
|
||||
{
|
||||
#ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
|
||||
return _PyThreadState_GetTSS();
|
||||
#else
|
||||
return (PyThreadState*)_Py_atomic_load_relaxed(&runtime->gilstate.tstate_current);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Get the current Python thread state.
|
||||
|
||||
Efficient macro reading directly the 'gilstate.tstate_current' atomic
|
||||
variable. The macro is unsafe: it does not check for error and it can
|
||||
return NULL.
|
||||
|
||||
The caller must hold the GIL.
|
||||
|
||||
See also PyThreadState_Get() and PyThreadState_GET(). */
|
||||
static inline PyThreadState*
|
||||
_PyThreadState_GET(void)
|
||||
{
|
||||
#ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
|
||||
return _PyThreadState_GetTSS();
|
||||
#else
|
||||
return _PyRuntimeState_GetThreadState(&_PyRuntime);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Redefine PyThreadState_GET() as an alias to _PyThreadState_GET() */
|
||||
#undef PyThreadState_GET
|
||||
#define PyThreadState_GET() _PyThreadState_GET()
|
||||
|
||||
PyAPI_FUNC(void) _Py_NO_RETURN _Py_FatalError_TstateNULL(const char *func);
|
||||
|
||||
static inline void
|
||||
_Py_EnsureFuncTstateNotNULL(const char *func, PyThreadState *tstate)
|
||||
{
|
||||
if (tstate == NULL) {
|
||||
_Py_FatalError_TstateNULL(func);
|
||||
}
|
||||
}
|
||||
|
||||
// Call Py_FatalError() if tstate is NULL
|
||||
#define _Py_EnsureTstateNotNULL(tstate) \
|
||||
_Py_EnsureFuncTstateNotNULL(__func__, tstate)
|
||||
|
||||
|
||||
/* Get the current interpreter state.
|
||||
|
||||
The macro is unsafe: it does not check for error and it can return NULL.
|
||||
|
||||
The caller must hold the GIL.
|
||||
|
||||
See also _PyInterpreterState_Get()
|
||||
and _PyGILState_GetInterpreterStateUnsafe(). */
|
||||
static inline PyInterpreterState* _PyInterpreterState_GET(void) {
|
||||
PyThreadState *tstate = _PyThreadState_GET();
|
||||
#ifdef Py_DEBUG
|
||||
_Py_EnsureTstateNotNULL(tstate);
|
||||
#endif
|
||||
return tstate->interp;
|
||||
}
|
||||
|
||||
|
||||
/* Other */
|
||||
|
||||
PyAPI_FUNC(void) _PyThreadState_Init(
|
||||
PyThreadState *tstate);
|
||||
PyAPI_FUNC(void) _PyThreadState_DeleteExcept(
|
||||
_PyRuntimeState *runtime,
|
||||
PyThreadState *tstate);
|
||||
|
||||
PyAPI_FUNC(PyThreadState *) _PyThreadState_Swap(
|
||||
struct _gilstate_runtime_state *gilstate,
|
||||
PyThreadState *newts);
|
||||
|
||||
PyAPI_FUNC(PyStatus) _PyInterpreterState_Enable(_PyRuntimeState *runtime);
|
||||
|
||||
#ifdef HAVE_FORK
|
||||
extern PyStatus _PyInterpreterState_DeleteExceptMain(_PyRuntimeState *runtime);
|
||||
extern PyStatus _PyGILState_Reinit(_PyRuntimeState *runtime);
|
||||
extern void _PySignal_AfterFork(void);
|
||||
#endif
|
||||
|
||||
|
||||
PyAPI_FUNC(int) _PyState_AddModule(
|
||||
PyThreadState *tstate,
|
||||
PyObject* module,
|
||||
struct PyModuleDef* def);
|
||||
|
||||
|
||||
PyAPI_FUNC(int) _PyOS_InterruptOccurred(PyThreadState *tstate);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* !Py_INTERNAL_PYSTATE_H */
|
||||
@@ -0,0 +1,157 @@
|
||||
#ifndef Py_INTERNAL_RUNTIME_H
|
||||
#define Py_INTERNAL_RUNTIME_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef Py_BUILD_CORE
|
||||
# error "this header requires Py_BUILD_CORE define"
|
||||
#endif
|
||||
|
||||
#include "pycore_atomic.h" /* _Py_atomic_address */
|
||||
#include "pycore_gil.h" // struct _gil_runtime_state
|
||||
|
||||
/* ceval state */
|
||||
|
||||
struct _ceval_runtime_state {
|
||||
/* Request for checking signals. It is shared by all interpreters (see
|
||||
bpo-40513). Any thread of any interpreter can receive a signal, but only
|
||||
the main thread of the main interpreter can handle signals: see
|
||||
_Py_ThreadCanHandleSignals(). */
|
||||
_Py_atomic_int signals_pending;
|
||||
#ifndef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS
|
||||
struct _gil_runtime_state gil;
|
||||
#endif
|
||||
};
|
||||
|
||||
/* GIL state */
|
||||
|
||||
struct _gilstate_runtime_state {
|
||||
/* bpo-26558: Flag to disable PyGILState_Check().
|
||||
If set to non-zero, PyGILState_Check() always return 1. */
|
||||
int check_enabled;
|
||||
/* Assuming the current thread holds the GIL, this is the
|
||||
PyThreadState for the current thread. */
|
||||
_Py_atomic_address tstate_current;
|
||||
/* The single PyInterpreterState used by this process'
|
||||
GILState implementation
|
||||
*/
|
||||
/* TODO: Given interp_main, it may be possible to kill this ref */
|
||||
PyInterpreterState *autoInterpreterState;
|
||||
Py_tss_t autoTSSkey;
|
||||
};
|
||||
|
||||
/* Runtime audit hook state */
|
||||
|
||||
typedef struct _Py_AuditHookEntry {
|
||||
struct _Py_AuditHookEntry *next;
|
||||
Py_AuditHookFunction hookCFunction;
|
||||
void *userData;
|
||||
} _Py_AuditHookEntry;
|
||||
|
||||
struct _Py_unicode_runtime_ids {
|
||||
PyThread_type_lock lock;
|
||||
// next_index value must be preserved when Py_Initialize()/Py_Finalize()
|
||||
// is called multiple times: see _PyUnicode_FromId() implementation.
|
||||
Py_ssize_t next_index;
|
||||
};
|
||||
|
||||
/* Full Python runtime state */
|
||||
|
||||
typedef struct pyruntimestate {
|
||||
/* 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. */
|
||||
_Py_atomic_address _finalizing;
|
||||
|
||||
struct pyinterpreters {
|
||||
PyThread_type_lock mutex;
|
||||
PyInterpreterState *head;
|
||||
PyInterpreterState *main;
|
||||
/* _next_interp_id is an auto-numbered sequence of small
|
||||
integers. It gets initialized in _PyInterpreterState_Init(),
|
||||
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;
|
||||
// XXX Remove this field once we have a tp_* slot.
|
||||
struct _xidregistry {
|
||||
PyThread_type_lock mutex;
|
||||
struct _xidregitem *head;
|
||||
} xidregistry;
|
||||
|
||||
unsigned long main_thread;
|
||||
|
||||
#define NEXITFUNCS 32
|
||||
void (*exitfuncs[NEXITFUNCS])(void);
|
||||
int nexitfuncs;
|
||||
|
||||
struct _ceval_runtime_state ceval;
|
||||
struct _gilstate_runtime_state gilstate;
|
||||
|
||||
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;
|
||||
_Py_AuditHookEntry *audit_hook_head;
|
||||
|
||||
struct _Py_unicode_runtime_ids unicode_ids;
|
||||
|
||||
// XXX Consolidate globals found via the check-c-globals script.
|
||||
} _PyRuntimeState;
|
||||
|
||||
#define _PyRuntimeState_INIT \
|
||||
{.preinitialized = 0, .core_initialized = 0, .initialized = 0}
|
||||
/* Note: _PyRuntimeState_INIT sets other fields to 0/NULL */
|
||||
|
||||
|
||||
PyAPI_DATA(_PyRuntimeState) _PyRuntime;
|
||||
|
||||
PyAPI_FUNC(PyStatus) _PyRuntimeState_Init(_PyRuntimeState *runtime);
|
||||
PyAPI_FUNC(void) _PyRuntimeState_Fini(_PyRuntimeState *runtime);
|
||||
|
||||
#ifdef HAVE_FORK
|
||||
extern PyStatus _PyRuntimeState_ReInitThreads(_PyRuntimeState *runtime);
|
||||
#endif
|
||||
|
||||
/* Initialize _PyRuntimeState.
|
||||
Return NULL on success, or return an error message on failure. */
|
||||
PyAPI_FUNC(PyStatus) _PyRuntime_Initialize(void);
|
||||
|
||||
PyAPI_FUNC(void) _PyRuntime_Finalize(void);
|
||||
|
||||
|
||||
static inline PyThreadState*
|
||||
_PyRuntimeState_GetFinalizing(_PyRuntimeState *runtime) {
|
||||
return (PyThreadState*)_Py_atomic_load_relaxed(&runtime->_finalizing);
|
||||
}
|
||||
|
||||
static inline void
|
||||
_PyRuntimeState_SetFinalizing(_PyRuntimeState *runtime, PyThreadState *tstate) {
|
||||
_Py_atomic_store_relaxed(&runtime->_finalizing, (uintptr_t)tstate);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* !Py_INTERNAL_RUNTIME_H */
|
||||
@@ -0,0 +1,21 @@
|
||||
#ifndef Py_INTERNAL_STRUCTSEQ_H
|
||||
#define Py_INTERNAL_STRUCTSEQ_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef Py_BUILD_CORE
|
||||
# error "this header requires Py_BUILD_CORE define"
|
||||
#endif
|
||||
|
||||
|
||||
PyAPI_FUNC(int) _PyStructSequence_InitType(
|
||||
PyTypeObject *type,
|
||||
PyStructSequence_Desc *desc,
|
||||
unsigned long tp_flags);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* !Py_INTERNAL_STRUCTSEQ_H */
|
||||
@@ -0,0 +1,133 @@
|
||||
#ifndef Py_INTERNAL_SYMTABLE_H
|
||||
#define Py_INTERNAL_SYMTABLE_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef Py_BUILD_CORE
|
||||
# error "this header requires Py_BUILD_CORE define"
|
||||
#endif
|
||||
|
||||
struct _mod; // Type defined in pycore_ast.h
|
||||
|
||||
typedef enum _block_type { FunctionBlock, ClassBlock, ModuleBlock, AnnotationBlock }
|
||||
_Py_block_ty;
|
||||
|
||||
typedef enum _comprehension_type {
|
||||
NoComprehension = 0,
|
||||
ListComprehension = 1,
|
||||
DictComprehension = 2,
|
||||
SetComprehension = 3,
|
||||
GeneratorExpression = 4 } _Py_comprehension_ty;
|
||||
|
||||
struct _symtable_entry;
|
||||
|
||||
struct symtable {
|
||||
PyObject *st_filename; /* name of file being compiled,
|
||||
decoded from the filesystem encoding */
|
||||
struct _symtable_entry *st_cur; /* current symbol table entry */
|
||||
struct _symtable_entry *st_top; /* symbol table entry for module */
|
||||
PyObject *st_blocks; /* dict: map AST node addresses
|
||||
* to symbol table entries */
|
||||
PyObject *st_stack; /* list: stack of namespace info */
|
||||
PyObject *st_global; /* borrowed ref to st_top->ste_symbols */
|
||||
int st_nblocks; /* number of blocks used. kept for
|
||||
consistency with the corresponding
|
||||
compiler structure */
|
||||
PyObject *st_private; /* name of current class or NULL */
|
||||
PyFutureFeatures *st_future; /* module's future features that affect
|
||||
the symbol table */
|
||||
int recursion_depth; /* current recursion depth */
|
||||
int recursion_limit; /* recursion limit */
|
||||
};
|
||||
|
||||
typedef struct _symtable_entry {
|
||||
PyObject_HEAD
|
||||
PyObject *ste_id; /* int: key in ste_table->st_blocks */
|
||||
PyObject *ste_symbols; /* dict: variable names to flags */
|
||||
PyObject *ste_name; /* string: name of current block */
|
||||
PyObject *ste_varnames; /* list of function parameters */
|
||||
PyObject *ste_children; /* list of child blocks */
|
||||
PyObject *ste_directives;/* locations of global and nonlocal statements */
|
||||
_Py_block_ty ste_type; /* module, class or function */
|
||||
int ste_nested; /* true if block is nested */
|
||||
unsigned ste_free : 1; /* true if block has free variables */
|
||||
unsigned ste_child_free : 1; /* true if a child block has free vars,
|
||||
including free refs to globals */
|
||||
unsigned ste_generator : 1; /* true if namespace is a generator */
|
||||
unsigned ste_coroutine : 1; /* true if namespace is a coroutine */
|
||||
_Py_comprehension_ty ste_comprehension; /* Kind of comprehension (if any) */
|
||||
unsigned ste_varargs : 1; /* true if block has varargs */
|
||||
unsigned ste_varkeywords : 1; /* true if block has varkeywords */
|
||||
unsigned ste_returns_value : 1; /* true if namespace uses return with
|
||||
an argument */
|
||||
unsigned ste_needs_class_closure : 1; /* for class scopes, true if a
|
||||
closure over __class__
|
||||
should be created */
|
||||
unsigned ste_comp_iter_target : 1; /* true if visiting comprehension target */
|
||||
int ste_comp_iter_expr; /* non-zero if visiting a comprehension range expression */
|
||||
int ste_lineno; /* first line of block */
|
||||
int ste_col_offset; /* offset of first line of block */
|
||||
int ste_end_lineno; /* end line of block */
|
||||
int ste_end_col_offset; /* end offset of first line of block */
|
||||
int ste_opt_lineno; /* lineno of last exec or import * */
|
||||
int ste_opt_col_offset; /* offset of last exec or import * */
|
||||
struct symtable *ste_table;
|
||||
} PySTEntryObject;
|
||||
|
||||
extern PyTypeObject PySTEntry_Type;
|
||||
|
||||
#define PySTEntry_Check(op) Py_IS_TYPE(op, &PySTEntry_Type)
|
||||
|
||||
extern int _PyST_GetScope(PySTEntryObject *, PyObject *);
|
||||
|
||||
extern struct symtable* _PySymtable_Build(
|
||||
struct _mod *mod,
|
||||
PyObject *filename,
|
||||
PyFutureFeatures *future);
|
||||
PyAPI_FUNC(PySTEntryObject *) PySymtable_Lookup(struct symtable *, void *);
|
||||
|
||||
extern void _PySymtable_Free(struct symtable *);
|
||||
|
||||
/* Flags for def-use information */
|
||||
|
||||
#define DEF_GLOBAL 1 /* global stmt */
|
||||
#define DEF_LOCAL 2 /* assignment in code block */
|
||||
#define DEF_PARAM 2<<1 /* formal parameter */
|
||||
#define DEF_NONLOCAL 2<<2 /* nonlocal stmt */
|
||||
#define USE 2<<3 /* name is used */
|
||||
#define DEF_FREE 2<<4 /* name used but not defined in nested block */
|
||||
#define DEF_FREE_CLASS 2<<5 /* free variable from class's method */
|
||||
#define DEF_IMPORT 2<<6 /* assignment occurred via import */
|
||||
#define DEF_ANNOT 2<<7 /* this name is annotated */
|
||||
#define DEF_COMP_ITER 2<<8 /* this name is a comprehension iteration variable */
|
||||
|
||||
#define DEF_BOUND (DEF_LOCAL | DEF_PARAM | DEF_IMPORT)
|
||||
|
||||
/* GLOBAL_EXPLICIT and GLOBAL_IMPLICIT are used internally by the symbol
|
||||
table. GLOBAL is returned from PyST_GetScope() for either of them.
|
||||
It is stored in ste_symbols at bits 12-15.
|
||||
*/
|
||||
#define SCOPE_OFFSET 11
|
||||
#define SCOPE_MASK (DEF_GLOBAL | DEF_LOCAL | DEF_PARAM | DEF_NONLOCAL)
|
||||
|
||||
#define LOCAL 1
|
||||
#define GLOBAL_EXPLICIT 2
|
||||
#define GLOBAL_IMPLICIT 3
|
||||
#define FREE 4
|
||||
#define CELL 5
|
||||
|
||||
#define GENERATOR 1
|
||||
#define GENERATOR_EXPRESSION 2
|
||||
|
||||
// Used by symtablemodule.c
|
||||
extern struct symtable* _Py_SymtableStringObjectFlags(
|
||||
const char *str,
|
||||
PyObject *filename,
|
||||
int start,
|
||||
PyCompilerFlags *flags);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* !Py_INTERNAL_SYMTABLE_H */
|
||||
@@ -0,0 +1,24 @@
|
||||
#ifndef Py_INTERNAL_SYSMODULE_H
|
||||
#define Py_INTERNAL_SYSMODULE_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef Py_BUILD_CORE
|
||||
# error "this header requires Py_BUILD_CORE define"
|
||||
#endif
|
||||
|
||||
PyAPI_FUNC(int) _PySys_Audit(
|
||||
PyThreadState *tstate,
|
||||
const char *event,
|
||||
const char *argFormat,
|
||||
...);
|
||||
|
||||
/* We want minimal exposure of this function, so use extern rather than
|
||||
PyAPI_FUNC() to not export the symbol. */
|
||||
extern void _PySys_ClearAuditHooks(PyThreadState *tstate);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* !Py_INTERNAL_SYSMODULE_H */
|
||||
@@ -0,0 +1,93 @@
|
||||
#ifndef Py_INTERNAL_TRACEBACK_H
|
||||
#define Py_INTERNAL_TRACEBACK_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef Py_BUILD_CORE
|
||||
# error "this header requires Py_BUILD_CORE define"
|
||||
#endif
|
||||
|
||||
/* Forward declaration */
|
||||
struct _is;
|
||||
|
||||
/* Write the Python traceback into the file 'fd'. For example:
|
||||
|
||||
Traceback (most recent call first):
|
||||
File "xxx", line xxx in <xxx>
|
||||
File "xxx", line xxx in <xxx>
|
||||
...
|
||||
File "xxx", line xxx in <xxx>
|
||||
|
||||
This function is written for debug purpose only, to dump the traceback in
|
||||
the worst case: after a segmentation fault, at fatal error, etc. That's why,
|
||||
it is very limited. Strings are truncated to 100 characters and encoded to
|
||||
ASCII with backslashreplace. It doesn't write the source code, only the
|
||||
function name, filename and line number of each frame. Write only the first
|
||||
100 frames: if the traceback is truncated, write the line " ...".
|
||||
|
||||
This function is signal safe. */
|
||||
|
||||
PyAPI_FUNC(void) _Py_DumpTraceback(
|
||||
int fd,
|
||||
PyThreadState *tstate);
|
||||
|
||||
/* Write the traceback of all threads into the file 'fd'. current_thread can be
|
||||
NULL.
|
||||
|
||||
Return NULL on success, or an error message on error.
|
||||
|
||||
This function is written for debug purpose only. It calls
|
||||
_Py_DumpTraceback() for each thread, and so has the same limitations. It
|
||||
only write the traceback of the first 100 threads: write "..." if there are
|
||||
more threads.
|
||||
|
||||
If current_tstate is NULL, the function tries to get the Python thread state
|
||||
of the current thread. It is not an error if the function is unable to get
|
||||
the current Python thread state.
|
||||
|
||||
If interp is NULL, the function tries to get the interpreter state from
|
||||
the current Python thread state, or from
|
||||
_PyGILState_GetInterpreterStateUnsafe() in last resort.
|
||||
|
||||
It is better to pass NULL to interp and current_tstate, the function tries
|
||||
different options to retrieve this information.
|
||||
|
||||
This function is signal safe. */
|
||||
|
||||
PyAPI_FUNC(const char*) _Py_DumpTracebackThreads(
|
||||
int fd,
|
||||
struct _is *interp,
|
||||
PyThreadState *current_tstate);
|
||||
|
||||
/* Write a Unicode object into the file descriptor fd. Encode the string to
|
||||
ASCII using the backslashreplace error handler.
|
||||
|
||||
Do nothing if text is not a Unicode object. The function accepts Unicode
|
||||
string which is not ready (PyUnicode_WCHAR_KIND).
|
||||
|
||||
This function is signal safe. */
|
||||
PyAPI_FUNC(void) _Py_DumpASCII(int fd, PyObject *text);
|
||||
|
||||
/* Format an integer as decimal into the file descriptor fd.
|
||||
|
||||
This function is signal safe. */
|
||||
PyAPI_FUNC(void) _Py_DumpDecimal(
|
||||
int fd,
|
||||
size_t value);
|
||||
|
||||
/* Format an integer as hexadecimal with width digits into fd file descriptor.
|
||||
The function is signal safe. */
|
||||
PyAPI_FUNC(void) _Py_DumpHexadecimal(
|
||||
int fd,
|
||||
uintptr_t value,
|
||||
Py_ssize_t width);
|
||||
|
||||
PyAPI_FUNC(PyObject*) _PyTraceBack_FromFrame(
|
||||
PyObject *tb_next,
|
||||
PyFrameObject *frame);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* !Py_INTERNAL_TRACEBACK_H */
|
||||
@@ -0,0 +1,20 @@
|
||||
#ifndef Py_INTERNAL_TUPLE_H
|
||||
#define Py_INTERNAL_TUPLE_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef Py_BUILD_CORE
|
||||
# error "this header requires Py_BUILD_CORE define"
|
||||
#endif
|
||||
|
||||
#include "tupleobject.h" /* _PyTuple_CAST() */
|
||||
|
||||
#define _PyTuple_ITEMS(op) (_PyTuple_CAST(op)->ob_item)
|
||||
|
||||
PyAPI_FUNC(PyObject *) _PyTuple_FromArray(PyObject *const *, Py_ssize_t);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* !Py_INTERNAL_TUPLE_H */
|
||||
@@ -0,0 +1,34 @@
|
||||
/* Unicode name database interface */
|
||||
#ifndef Py_INTERNAL_UCNHASH_H
|
||||
#define Py_INTERNAL_UCNHASH_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef Py_BUILD_CORE
|
||||
# error "this header requires Py_BUILD_CORE define"
|
||||
#endif
|
||||
|
||||
/* revised ucnhash CAPI interface (exported through a "wrapper") */
|
||||
|
||||
#define PyUnicodeData_CAPSULE_NAME "unicodedata._ucnhash_CAPI"
|
||||
|
||||
typedef struct {
|
||||
|
||||
/* Get name for a given character code.
|
||||
Returns non-zero if success, zero if not.
|
||||
Does not set Python exceptions. */
|
||||
int (*getname)(Py_UCS4 code, char* buffer, int buflen,
|
||||
int with_alias_and_seq);
|
||||
|
||||
/* Get character code for a given name.
|
||||
Same error handling as for getname(). */
|
||||
int (*getcode)(const char* name, int namelen, Py_UCS4* code,
|
||||
int with_named_seq);
|
||||
|
||||
} _PyUnicode_Name_CAPI;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* !Py_INTERNAL_UCNHASH_H */
|
||||
@@ -0,0 +1,22 @@
|
||||
#ifndef Py_INTERNAL_UNIONOBJECT_H
|
||||
#define Py_INTERNAL_UNIONOBJECT_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef Py_BUILD_CORE
|
||||
# error "this header requires Py_BUILD_CORE define"
|
||||
#endif
|
||||
|
||||
extern PyTypeObject _PyUnion_Type;
|
||||
#define _PyUnion_Check(op) Py_IS_TYPE(op, &_PyUnion_Type)
|
||||
extern PyObject *_Py_union_type_or(PyObject *, PyObject *);
|
||||
|
||||
#define _PyGenericAlias_Check(op) PyObject_TypeCheck(op, &Py_GenericAliasType)
|
||||
extern PyObject *_Py_subs_parameters(PyObject *, PyObject *, PyObject *, PyObject *);
|
||||
extern PyObject *_Py_make_parameters(PyObject *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* !Py_INTERNAL_UNIONOBJECT_H */
|
||||
@@ -0,0 +1,25 @@
|
||||
#ifndef Py_INTERNAL_WARNINGS_H
|
||||
#define Py_INTERNAL_WARNINGS_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef Py_BUILD_CORE
|
||||
# error "this header requires Py_BUILD_CORE define"
|
||||
#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 */
|
||||
long filters_version;
|
||||
};
|
||||
|
||||
extern int _PyWarnings_InitState(PyInterpreterState *interp);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* !Py_INTERNAL_WARNINGS_H */
|
||||
Reference in New Issue
Block a user