Python-checkins
Threads by month
- ----- 2025 -----
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
January 2025
- 1 participants
- 549 discussions
Docs C API: Clarify what happens when null bytes are passed to `PyUnicode_AsUTF8` (#127458)
by vstinner Jan. 20, 2025
by vstinner Jan. 20, 2025
Jan. 20, 2025
https://github.com/python/cpython/commit/e792f4bc2e712bb6e2143599d2b88dd339…
commit: e792f4bc2e712bb6e2143599d2b88dd339de83e6
branch: main
author: Peter Bierma <zintensitydev(a)gmail.com>
committer: vstinner <vstinner(a)python.org>
date: 2025-01-20T16:54:29+01:00
summary:
Docs C API: Clarify what happens when null bytes are passed to `PyUnicode_AsUTF8` (#127458)
Co-authored-by: Stan U. <89152624+StanFromIreland(a)users.noreply.github.com>
Co-authored-by: Tomas R. <tomas.roun8(a)gmail.com>
Co-authored-by: Victor Stinner <vstinner(a)python.org>
files:
M Doc/c-api/unicode.rst
diff --git a/Doc/c-api/unicode.rst b/Doc/c-api/unicode.rst
index f19b86a8dbfb66..94110d48ed7d85 100644
--- a/Doc/c-api/unicode.rst
+++ b/Doc/c-api/unicode.rst
@@ -1054,6 +1054,15 @@ These are the UTF-8 codec APIs:
As :c:func:`PyUnicode_AsUTF8AndSize`, but does not store the size.
+ .. warning::
+
+ This function does not have any special behavior for
+ `null characters <https://en.wikipedia.org/wiki/Null_character>`_ embedded within
+ *unicode*. As a result, strings containing null characters will remain in the returned
+ string, which some C functions might interpret as the end of the string, leading to
+ truncation. If truncation is an issue, it is recommended to use :c:func:`PyUnicode_AsUTF8AndSize`
+ instead.
+
.. versionadded:: 3.3
.. versionchanged:: 3.7
1
0
[3.13] gh-129044: Update glossary entry for 'loader' to reflect current import system (GH-129073) (#129077)
by AA-Turner Jan. 20, 2025
by AA-Turner Jan. 20, 2025
Jan. 20, 2025
https://github.com/python/cpython/commit/2f8eefe97ab03ecf92f85918a2b4cb23be…
commit: 2f8eefe97ab03ecf92f85918a2b4cb23be7ee04c
branch: 3.13
author: Miss Islington (bot) <31488909+miss-islington(a)users.noreply.github.com>
committer: AA-Turner <9087854+AA-Turner(a)users.noreply.github.com>
date: 2025-01-20T15:51:52Z
summary:
[3.13] gh-129044: Update glossary entry for 'loader' to reflect current import system (GH-129073) (#129077)
gh-129044: Update glossary entry for 'loader' to reflect current import system (GH-129073)
(cherry picked from commit e1fa2fcc7c1bf5291a7f71300b7828b49be9ab72)
Co-authored-by: nikalinov <92603661+nikalinov(a)users.noreply.github.com>
Co-authored-by: Adam Turner <9087854+AA-Turner(a)users.noreply.github.com>
files:
M Doc/glossary.rst
M Doc/tools/.nitignore
diff --git a/Doc/glossary.rst b/Doc/glossary.rst
index d8488ca99246d2..858c2b39ee5e33 100644
--- a/Doc/glossary.rst
+++ b/Doc/glossary.rst
@@ -801,9 +801,11 @@ Glossary
processed.
loader
- An object that loads a module. It must define a method named
- :meth:`load_module`. A loader is typically returned by a
- :term:`finder`. See also:
+ An object that loads a module.
+ It must define the :meth:`!exec_module` and :meth:`!create_module` methods
+ to implement the :class:`~importlib.abc.Loader` interface.
+ A loader is typically returned by a :term:`finder`.
+ See also:
* :ref:`finders-and-loaders`
* :class:`importlib.abc.Loader`
diff --git a/Doc/tools/.nitignore b/Doc/tools/.nitignore
index 8485766034ca77..9e36087ff10c3e 100644
--- a/Doc/tools/.nitignore
+++ b/Doc/tools/.nitignore
@@ -12,7 +12,6 @@ Doc/c-api/stable.rst
Doc/c-api/type.rst
Doc/c-api/typeobj.rst
Doc/extending/extending.rst
-Doc/glossary.rst
Doc/library/ast.rst
Doc/library/asyncio-extending.rst
Doc/library/asyncio-policy.rst
1
0
https://github.com/python/cpython/commit/f0f7b978be84c432139da1b107825aa2dc…
commit: f0f7b978be84c432139da1b107825aa2dc536854
branch: main
author: Mark Shannon <mark(a)hotpy.org>
committer: markshannon <mark(a)hotpy.org>
date: 2025-01-20T15:49:15Z
summary:
GH-128939: Refactor JIT optimize structs (GH-128940)
files:
M Include/internal/pycore_optimizer.h
M Lib/test/test_capi/test_opt.py
M Lib/test/test_generated_cases.py
M Modules/_testinternalcapi.c
M Python/optimizer_analysis.c
M Python/optimizer_bytecodes.c
M Python/optimizer_cases.c.h
M Python/optimizer_symbols.c
M Tools/cases_generator/optimizer_generator.py
diff --git a/Include/internal/pycore_optimizer.h b/Include/internal/pycore_optimizer.h
index a02b9ab4291bfc..03ce4d4491acd7 100644
--- a/Include/internal/pycore_optimizer.h
+++ b/Include/internal/pycore_optimizer.h
@@ -148,15 +148,6 @@ extern PyTypeObject _PyDefaultOptimizer_Type;
extern PyTypeObject _PyUOpExecutor_Type;
extern PyTypeObject _PyUOpOptimizer_Type;
-/* Symbols */
-/* See explanation in optimizer_symbols.c */
-
-struct _Py_UopsSymbol {
- int flags; // 0 bits: Top; 2 or more bits: Bottom
- PyTypeObject *typ; // Borrowed reference
- PyObject *const_val; // Owned reference (!)
- unsigned int type_version; // currently stores type version
-};
#define UOP_FORMAT_TARGET 0
#define UOP_FORMAT_JUMP 1
@@ -193,16 +184,63 @@ static inline uint16_t uop_get_error_target(const _PyUOpInstruction *inst)
// handle before rejoining the rest of the program.
#define MAX_CHAIN_DEPTH 4
-typedef struct _Py_UopsSymbol _Py_UopsSymbol;
+/* Symbols */
+/* See explanation in optimizer_symbols.c */
+
+
+typedef enum _JitSymType {
+ JIT_SYM_UNKNOWN_TAG = 1,
+ JIT_SYM_NULL_TAG = 2,
+ JIT_SYM_NON_NULL_TAG = 3,
+ JIT_SYM_BOTTOM_TAG = 4,
+ JIT_SYM_TYPE_VERSION_TAG = 5,
+ JIT_SYM_KNOWN_CLASS_TAG = 6,
+ JIT_SYM_KNOWN_VALUE_TAG = 7,
+ JIT_SYM_TUPLE_TAG = 8,
+} JitSymType;
+
+typedef struct _jit_opt_known_class {
+ uint8_t tag;
+ uint32_t version;
+ PyTypeObject *type;
+} JitOptKnownClass;
+
+typedef struct _jit_opt_known_version {
+ uint8_t tag;
+ uint32_t version;
+} JitOptKnownVersion;
+
+typedef struct _jit_opt_known_value {
+ uint8_t tag;
+ PyObject *value;
+} JitOptKnownValue;
+
+#define MAX_SYMBOLIC_TUPLE_SIZE 7
+
+typedef struct _jit_opt_tuple {
+ uint8_t tag;
+ uint8_t length;
+ uint16_t items[MAX_SYMBOLIC_TUPLE_SIZE];
+} JitOptTuple;
+
+typedef union _jit_opt_symbol {
+ uint8_t tag;
+ JitOptKnownClass cls;
+ JitOptKnownValue value;
+ JitOptKnownVersion version;
+ JitOptTuple tuple;
+} JitOptSymbol;
+
+
struct _Py_UOpsAbstractFrame {
// Max stacklen
int stack_len;
int locals_len;
- _Py_UopsSymbol **stack_pointer;
- _Py_UopsSymbol **stack;
- _Py_UopsSymbol **locals;
+ JitOptSymbol **stack_pointer;
+ JitOptSymbol **stack;
+ JitOptSymbol **locals;
};
typedef struct _Py_UOpsAbstractFrame _Py_UOpsAbstractFrame;
@@ -210,10 +248,10 @@ typedef struct _Py_UOpsAbstractFrame _Py_UOpsAbstractFrame;
typedef struct ty_arena {
int ty_curr_number;
int ty_max_number;
- _Py_UopsSymbol arena[TY_ARENA_SIZE];
+ JitOptSymbol arena[TY_ARENA_SIZE];
} ty_arena;
-struct _Py_UOpsContext {
+typedef struct _JitOptContext {
char done;
char out_of_space;
bool contradiction;
@@ -225,46 +263,47 @@ struct _Py_UOpsContext {
// Arena for the symbolic types.
ty_arena t_arena;
- _Py_UopsSymbol **n_consumed;
- _Py_UopsSymbol **limit;
- _Py_UopsSymbol *locals_and_stack[MAX_ABSTRACT_INTERP_SIZE];
-};
-
-typedef struct _Py_UOpsContext _Py_UOpsContext;
-
-extern bool _Py_uop_sym_is_null(_Py_UopsSymbol *sym);
-extern bool _Py_uop_sym_is_not_null(_Py_UopsSymbol *sym);
-extern bool _Py_uop_sym_is_const(_Py_UopsSymbol *sym);
-extern PyObject *_Py_uop_sym_get_const(_Py_UopsSymbol *sym);
-extern _Py_UopsSymbol *_Py_uop_sym_new_unknown(_Py_UOpsContext *ctx);
-extern _Py_UopsSymbol *_Py_uop_sym_new_not_null(_Py_UOpsContext *ctx);
-extern _Py_UopsSymbol *_Py_uop_sym_new_type(
- _Py_UOpsContext *ctx, PyTypeObject *typ);
-extern _Py_UopsSymbol *_Py_uop_sym_new_const(_Py_UOpsContext *ctx, PyObject *const_val);
-extern _Py_UopsSymbol *_Py_uop_sym_new_null(_Py_UOpsContext *ctx);
-extern bool _Py_uop_sym_has_type(_Py_UopsSymbol *sym);
-extern bool _Py_uop_sym_matches_type(_Py_UopsSymbol *sym, PyTypeObject *typ);
-extern bool _Py_uop_sym_matches_type_version(_Py_UopsSymbol *sym, unsigned int version);
-extern void _Py_uop_sym_set_null(_Py_UOpsContext *ctx, _Py_UopsSymbol *sym);
-extern void _Py_uop_sym_set_non_null(_Py_UOpsContext *ctx, _Py_UopsSymbol *sym);
-extern void _Py_uop_sym_set_type(_Py_UOpsContext *ctx, _Py_UopsSymbol *sym, PyTypeObject *typ);
-extern bool _Py_uop_sym_set_type_version(_Py_UOpsContext *ctx, _Py_UopsSymbol *sym, unsigned int version);
-extern void _Py_uop_sym_set_const(_Py_UOpsContext *ctx, _Py_UopsSymbol *sym, PyObject *const_val);
-extern bool _Py_uop_sym_is_bottom(_Py_UopsSymbol *sym);
-extern int _Py_uop_sym_truthiness(_Py_UopsSymbol *sym);
-extern PyTypeObject *_Py_uop_sym_get_type(_Py_UopsSymbol *sym);
-
-
-extern void _Py_uop_abstractcontext_init(_Py_UOpsContext *ctx);
-extern void _Py_uop_abstractcontext_fini(_Py_UOpsContext *ctx);
+ JitOptSymbol **n_consumed;
+ JitOptSymbol **limit;
+ JitOptSymbol *locals_and_stack[MAX_ABSTRACT_INTERP_SIZE];
+} JitOptContext;
+
+extern bool _Py_uop_sym_is_null(JitOptSymbol *sym);
+extern bool _Py_uop_sym_is_not_null(JitOptSymbol *sym);
+extern bool _Py_uop_sym_is_const(JitOptSymbol *sym);
+extern PyObject *_Py_uop_sym_get_const(JitOptSymbol *sym);
+extern JitOptSymbol *_Py_uop_sym_new_unknown(JitOptContext *ctx);
+extern JitOptSymbol *_Py_uop_sym_new_not_null(JitOptContext *ctx);
+extern JitOptSymbol *_Py_uop_sym_new_type(
+ JitOptContext *ctx, PyTypeObject *typ);
+extern JitOptSymbol *_Py_uop_sym_new_const(JitOptContext *ctx, PyObject *const_val);
+extern JitOptSymbol *_Py_uop_sym_new_null(JitOptContext *ctx);
+extern bool _Py_uop_sym_has_type(JitOptSymbol *sym);
+extern bool _Py_uop_sym_matches_type(JitOptSymbol *sym, PyTypeObject *typ);
+extern bool _Py_uop_sym_matches_type_version(JitOptSymbol *sym, unsigned int version);
+extern void _Py_uop_sym_set_null(JitOptContext *ctx, JitOptSymbol *sym);
+extern void _Py_uop_sym_set_non_null(JitOptContext *ctx, JitOptSymbol *sym);
+extern void _Py_uop_sym_set_type(JitOptContext *ctx, JitOptSymbol *sym, PyTypeObject *typ);
+extern bool _Py_uop_sym_set_type_version(JitOptContext *ctx, JitOptSymbol *sym, unsigned int version);
+extern void _Py_uop_sym_set_const(JitOptContext *ctx, JitOptSymbol *sym, PyObject *const_val);
+extern bool _Py_uop_sym_is_bottom(JitOptSymbol *sym);
+extern int _Py_uop_sym_truthiness(JitOptSymbol *sym);
+extern PyTypeObject *_Py_uop_sym_get_type(JitOptSymbol *sym);
+extern bool _Py_uop_sym_is_immortal(JitOptSymbol *sym);
+extern JitOptSymbol *_Py_uop_sym_new_tuple(JitOptContext *ctx, int size, JitOptSymbol **args);
+extern JitOptSymbol *_Py_uop_sym_tuple_getitem(JitOptContext *ctx, JitOptSymbol *sym, int item);
+extern int _Py_uop_sym_tuple_length(JitOptSymbol *sym);
+
+extern void _Py_uop_abstractcontext_init(JitOptContext *ctx);
+extern void _Py_uop_abstractcontext_fini(JitOptContext *ctx);
extern _Py_UOpsAbstractFrame *_Py_uop_frame_new(
- _Py_UOpsContext *ctx,
+ JitOptContext *ctx,
PyCodeObject *co,
int curr_stackentries,
- _Py_UopsSymbol **args,
+ JitOptSymbol **args,
int arg_len);
-extern int _Py_uop_frame_pop(_Py_UOpsContext *ctx);
+extern int _Py_uop_frame_pop(JitOptContext *ctx);
PyAPI_FUNC(PyObject *) _Py_uop_symbols_test(PyObject *self, PyObject *ignored);
diff --git a/Lib/test/test_capi/test_opt.py b/Lib/test/test_capi/test_opt.py
index a74b8fdd3923b7..9cfc6c142da6cd 100644
--- a/Lib/test/test_capi/test_opt.py
+++ b/Lib/test/test_capi/test_opt.py
@@ -1465,6 +1465,25 @@ def f(l: complex, r: complex) -> None:
with self.subTest(l=l, r=r, x=x, y=y):
script_helper.assert_python_ok("-c", s)
+ def test_symbols_flow_through_tuples(self):
+ def testfunc(n):
+ for _ in range(n):
+ a = 1
+ b = 2
+ t = a, b
+ x, y = t
+ r = x + y
+ return r
+
+ res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD)
+ self.assertEqual(res, 3)
+ self.assertIsNotNone(ex)
+ uops = get_opnames(ex)
+ self.assertIn("_BINARY_OP_ADD_INT", uops)
+ self.assertNotIn("_GUARD_BOTH_INT", uops)
+ self.assertNotIn("_GUARD_NOS_INT", uops)
+ self.assertNotIn("_GUARD_TOS_INT", uops)
+
def test_decref_escapes(self):
class Convert9999ToNone:
def __del__(self):
diff --git a/Lib/test/test_generated_cases.py b/Lib/test/test_generated_cases.py
index 7a50a29bb0126c..aa92145266961a 100644
--- a/Lib/test/test_generated_cases.py
+++ b/Lib/test/test_generated_cases.py
@@ -1842,8 +1842,8 @@ def test_overridden_abstract_args(self):
"""
output = """
case OP: {
- _Py_UopsSymbol *arg1;
- _Py_UopsSymbol *out;
+ JitOptSymbol *arg1;
+ JitOptSymbol *out;
arg1 = stack_pointer[-1];
out = EGGS(arg1);
stack_pointer[-1] = out;
@@ -1851,7 +1851,7 @@ def test_overridden_abstract_args(self):
}
case OP2: {
- _Py_UopsSymbol *out;
+ JitOptSymbol *out;
out = sym_new_not_null(ctx);
stack_pointer[-1] = out;
break;
@@ -1876,14 +1876,14 @@ def test_no_overridden_case(self):
"""
output = """
case OP: {
- _Py_UopsSymbol *out;
+ JitOptSymbol *out;
out = sym_new_not_null(ctx);
stack_pointer[-1] = out;
break;
}
case OP2: {
- _Py_UopsSymbol *out;
+ JitOptSymbol *out;
out = NULL;
stack_pointer[-1] = out;
break;
diff --git a/Modules/_testinternalcapi.c b/Modules/_testinternalcapi.c
index aae09f620b8898..e77df5b57b0504 100644
--- a/Modules/_testinternalcapi.c
+++ b/Modules/_testinternalcapi.c
@@ -27,7 +27,7 @@
#include "pycore_instruction_sequence.h" // _PyInstructionSequence_New()
#include "pycore_long.h" // _PyLong_Sign()
#include "pycore_object.h" // _PyObject_IsFreed()
-#include "pycore_optimizer.h" // _Py_UopsSymbol, etc.
+#include "pycore_optimizer.h" // JitOptSymbol, etc.
#include "pycore_pathconfig.h" // _PyPathConfig_ClearGlobal()
#include "pycore_pyerrors.h" // _PyErr_ChainExceptions1()
#include "pycore_pylifecycle.h" // _PyInterpreterConfig_AsDict()
diff --git a/Python/optimizer_analysis.c b/Python/optimizer_analysis.c
index 0ef15c630e91db..b9ac30ea04e4e8 100644
--- a/Python/optimizer_analysis.c
+++ b/Python/optimizer_analysis.c
@@ -368,13 +368,17 @@ remove_globals(_PyInterpreterFrame *frame, _PyUOpInstruction *buffer,
#define sym_truthiness _Py_uop_sym_truthiness
#define frame_new _Py_uop_frame_new
#define frame_pop _Py_uop_frame_pop
+#define sym_new_tuple _Py_uop_sym_new_tuple
+#define sym_tuple_getitem _Py_uop_sym_tuple_getitem
+#define sym_tuple_length _Py_uop_sym_tuple_length
+#define sym_is_immortal _Py_uop_sym_is_immortal
static int
optimize_to_bool(
_PyUOpInstruction *this_instr,
- _Py_UOpsContext *ctx,
- _Py_UopsSymbol *value,
- _Py_UopsSymbol **result_ptr)
+ JitOptContext *ctx,
+ JitOptSymbol *value,
+ JitOptSymbol **result_ptr)
{
if (sym_matches_type(value, &PyBool_Type)) {
REPLACE_OP(this_instr, _NOP, 0, 0);
@@ -460,8 +464,8 @@ optimize_uops(
)
{
- _Py_UOpsContext context;
- _Py_UOpsContext *ctx = &context;
+ JitOptContext context;
+ JitOptContext *ctx = &context;
uint32_t opcode = UINT16_MAX;
int curr_space = 0;
int max_space = 0;
@@ -486,7 +490,7 @@ optimize_uops(
int oparg = this_instr->oparg;
opcode = this_instr->opcode;
- _Py_UopsSymbol **stack_pointer = ctx->frame->stack_pointer;
+ JitOptSymbol **stack_pointer = ctx->frame->stack_pointer;
#ifdef Py_DEBUG
if (get_lltrace() >= 3) {
diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c
index 4d96ada5acf00f..881a607ca2aa29 100644
--- a/Python/optimizer_bytecodes.c
+++ b/Python/optimizer_bytecodes.c
@@ -6,8 +6,6 @@
#define op(name, ...) /* NAME is ignored */
-typedef struct _Py_UopsSymbol _Py_UopsSymbol;
-typedef struct _Py_UOpsContext _Py_UOpsContext;
typedef struct _Py_UOpsAbstractFrame _Py_UOpsAbstractFrame;
/* Shortened forms for convenience */
@@ -32,13 +30,17 @@ typedef struct _Py_UOpsAbstractFrame _Py_UOpsAbstractFrame;
#define sym_is_bottom _Py_uop_sym_is_bottom
#define frame_new _Py_uop_frame_new
#define frame_pop _Py_uop_frame_pop
+#define sym_new_tuple _Py_uop_sym_new_tuple
+#define sym_tuple_getitem _Py_uop_sym_tuple_getitem
+#define sym_tuple_length _Py_uop_sym_tuple_length
+#define sym_is_immortal _Py_uop_sym_is_immortal
extern int
optimize_to_bool(
_PyUOpInstruction *this_instr,
- _Py_UOpsContext *ctx,
- _Py_UopsSymbol *value,
- _Py_UopsSymbol **result_ptr);
+ JitOptContext *ctx,
+ JitOptSymbol *value,
+ JitOptSymbol **result_ptr);
extern void
eliminate_pop_guard(_PyUOpInstruction *this_instr, bool exit);
@@ -50,17 +52,17 @@ dummy_func(void) {
PyCodeObject *co;
int oparg;
- _Py_UopsSymbol *flag;
- _Py_UopsSymbol *left;
- _Py_UopsSymbol *right;
- _Py_UopsSymbol *value;
- _Py_UopsSymbol *res;
- _Py_UopsSymbol *iter;
- _Py_UopsSymbol *top;
- _Py_UopsSymbol *bottom;
+ JitOptSymbol *flag;
+ JitOptSymbol *left;
+ JitOptSymbol *right;
+ JitOptSymbol *value;
+ JitOptSymbol *res;
+ JitOptSymbol *iter;
+ JitOptSymbol *top;
+ JitOptSymbol *bottom;
_Py_UOpsAbstractFrame *frame;
_Py_UOpsAbstractFrame *new_frame;
- _Py_UOpsContext *ctx;
+ JitOptContext *ctx;
_PyUOpInstruction *this_instr;
_PyBloomFilter *dependencies;
int modified;
@@ -85,7 +87,7 @@ dummy_func(void) {
op(_LOAD_FAST_AND_CLEAR, (-- value)) {
value = GETLOCAL(oparg);
- _Py_UopsSymbol *temp = sym_new_null(ctx);
+ JitOptSymbol *temp = sym_new_null(ctx);
GETLOCAL(oparg) = temp;
}
@@ -365,7 +367,7 @@ dummy_func(void) {
}
op(_BINARY_OP_INPLACE_ADD_UNICODE, (left, right -- )) {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
if (sym_is_const(left) && sym_is_const(right) &&
sym_matches_type(left, &PyUnicode_Type) && sym_matches_type(right, &PyUnicode_Type)) {
PyObject *temp = PyUnicode_Concat(sym_get_const(left), sym_get_const(right));
@@ -949,6 +951,22 @@ dummy_func(void) {
res = sym_new_const(ctx, Py_True);
}
+ op(_BUILD_TUPLE, (values[oparg] -- tup)) {
+ tup = sym_new_tuple(ctx, oparg, values);
+ }
+
+ op(_UNPACK_SEQUENCE_TWO_TUPLE, (seq -- val1, val0)) {
+ val0 = sym_tuple_getitem(ctx, seq, 0);
+ val1 = sym_tuple_getitem(ctx, seq, 1);
+ }
+
+ op(_UNPACK_SEQUENCE_TUPLE, (seq -- values[oparg])) {
+ for (int i = 0; i < oparg; i++) {
+ values[i] = sym_tuple_getitem(ctx, seq, i);
+ }
+ }
+
+
// END BYTECODES //
}
diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h
index 1f2b29c947434f..fa0b4ed4345320 100644
--- a/Python/optimizer_cases.c.h
+++ b/Python/optimizer_cases.c.h
@@ -26,7 +26,7 @@
/* _MONITOR_RESUME is not a viable micro-op for tier 2 */
case _LOAD_FAST_CHECK: {
- _Py_UopsSymbol *value;
+ JitOptSymbol *value;
value = GETLOCAL(oparg);
// We guarantee this will error - just bail and don't optimize it.
if (sym_is_null(value)) {
@@ -39,7 +39,7 @@
}
case _LOAD_FAST: {
- _Py_UopsSymbol *value;
+ JitOptSymbol *value;
value = GETLOCAL(oparg);
stack_pointer[0] = value;
stack_pointer += 1;
@@ -48,9 +48,9 @@
}
case _LOAD_FAST_AND_CLEAR: {
- _Py_UopsSymbol *value;
+ JitOptSymbol *value;
value = GETLOCAL(oparg);
- _Py_UopsSymbol *temp = sym_new_null(ctx);
+ JitOptSymbol *temp = sym_new_null(ctx);
GETLOCAL(oparg) = temp;
stack_pointer[0] = value;
stack_pointer += 1;
@@ -61,7 +61,7 @@
/* _LOAD_CONST is not a viable micro-op for tier 2 */
case _LOAD_CONST_MORTAL: {
- _Py_UopsSymbol *value;
+ JitOptSymbol *value;
PyObject *val = PyTuple_GET_ITEM(co->co_consts, this_instr->oparg);
int opcode = _Py_IsImmortal(val) ? _LOAD_CONST_INLINE_BORROW : _LOAD_CONST_INLINE;
REPLACE_OP(this_instr, opcode, 0, (uintptr_t)val);
@@ -73,7 +73,7 @@
}
case _LOAD_CONST_IMMORTAL: {
- _Py_UopsSymbol *value;
+ JitOptSymbol *value;
PyObject *val = PyTuple_GET_ITEM(co->co_consts, this_instr->oparg);
REPLACE_OP(this_instr, _LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)val);
value = sym_new_const(ctx, val);
@@ -84,7 +84,7 @@
}
case _LOAD_SMALL_INT: {
- _Py_UopsSymbol *value;
+ JitOptSymbol *value;
PyObject *val = PyLong_FromLong(this_instr->oparg);
value = sym_new_const(ctx, val);
stack_pointer[0] = value;
@@ -94,7 +94,7 @@
}
case _STORE_FAST: {
- _Py_UopsSymbol *value;
+ JitOptSymbol *value;
value = stack_pointer[-1];
GETLOCAL(oparg) = value;
stack_pointer += -1;
@@ -109,7 +109,7 @@
}
case _PUSH_NULL: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_null(ctx);
stack_pointer[0] = res;
stack_pointer += 1;
@@ -124,7 +124,7 @@
}
case _END_SEND: {
- _Py_UopsSymbol *val;
+ JitOptSymbol *val;
val = sym_new_not_null(ctx);
stack_pointer[-2] = val;
stack_pointer += -1;
@@ -133,22 +133,22 @@
}
case _UNARY_NEGATIVE: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-1] = res;
break;
}
case _UNARY_NOT: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-1] = res;
break;
}
case _TO_BOOL: {
- _Py_UopsSymbol *value;
- _Py_UopsSymbol *res;
+ JitOptSymbol *value;
+ JitOptSymbol *res;
value = stack_pointer[-1];
if (!optimize_to_bool(this_instr, ctx, value, &res)) {
res = sym_new_type(ctx, &PyBool_Type);
@@ -158,8 +158,8 @@
}
case _TO_BOOL_BOOL: {
- _Py_UopsSymbol *value;
- _Py_UopsSymbol *res;
+ JitOptSymbol *value;
+ JitOptSymbol *res;
value = stack_pointer[-1];
if (!optimize_to_bool(this_instr, ctx, value, &res)) {
sym_set_type(value, &PyBool_Type);
@@ -170,8 +170,8 @@
}
case _TO_BOOL_INT: {
- _Py_UopsSymbol *value;
- _Py_UopsSymbol *res;
+ JitOptSymbol *value;
+ JitOptSymbol *res;
value = stack_pointer[-1];
if (!optimize_to_bool(this_instr, ctx, value, &res)) {
sym_set_type(value, &PyLong_Type);
@@ -182,8 +182,8 @@
}
case _TO_BOOL_LIST: {
- _Py_UopsSymbol *value;
- _Py_UopsSymbol *res;
+ JitOptSymbol *value;
+ JitOptSymbol *res;
value = stack_pointer[-1];
if (!optimize_to_bool(this_instr, ctx, value, &res)) {
sym_set_type(value, &PyList_Type);
@@ -194,8 +194,8 @@
}
case _TO_BOOL_NONE: {
- _Py_UopsSymbol *value;
- _Py_UopsSymbol *res;
+ JitOptSymbol *value;
+ JitOptSymbol *res;
value = stack_pointer[-1];
if (!optimize_to_bool(this_instr, ctx, value, &res)) {
sym_set_const(value, Py_None);
@@ -206,8 +206,8 @@
}
case _TO_BOOL_STR: {
- _Py_UopsSymbol *value;
- _Py_UopsSymbol *res;
+ JitOptSymbol *value;
+ JitOptSymbol *res;
value = stack_pointer[-1];
if (!optimize_to_bool(this_instr, ctx, value, &res)) {
res = sym_new_type(ctx, &PyBool_Type);
@@ -218,22 +218,22 @@
}
case _REPLACE_WITH_TRUE: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_const(ctx, Py_True);
stack_pointer[-1] = res;
break;
}
case _UNARY_INVERT: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-1] = res;
break;
}
case _GUARD_BOTH_INT: {
- _Py_UopsSymbol *right;
- _Py_UopsSymbol *left;
+ JitOptSymbol *right;
+ JitOptSymbol *left;
right = stack_pointer[-1];
left = stack_pointer[-2];
if (sym_matches_type(left, &PyLong_Type)) {
@@ -263,9 +263,9 @@
}
case _BINARY_OP_MULTIPLY_INT: {
- _Py_UopsSymbol *right;
- _Py_UopsSymbol *left;
- _Py_UopsSymbol *res;
+ JitOptSymbol *right;
+ JitOptSymbol *left;
+ JitOptSymbol *res;
right = stack_pointer[-1];
left = stack_pointer[-2];
if (sym_is_const(left) && sym_is_const(right) &&
@@ -296,9 +296,9 @@
}
case _BINARY_OP_ADD_INT: {
- _Py_UopsSymbol *right;
- _Py_UopsSymbol *left;
- _Py_UopsSymbol *res;
+ JitOptSymbol *right;
+ JitOptSymbol *left;
+ JitOptSymbol *res;
right = stack_pointer[-1];
left = stack_pointer[-2];
if (sym_is_const(left) && sym_is_const(right) &&
@@ -329,9 +329,9 @@
}
case _BINARY_OP_SUBTRACT_INT: {
- _Py_UopsSymbol *right;
- _Py_UopsSymbol *left;
- _Py_UopsSymbol *res;
+ JitOptSymbol *right;
+ JitOptSymbol *left;
+ JitOptSymbol *res;
right = stack_pointer[-1];
left = stack_pointer[-2];
if (sym_is_const(left) && sym_is_const(right) &&
@@ -362,8 +362,8 @@
}
case _GUARD_BOTH_FLOAT: {
- _Py_UopsSymbol *right;
- _Py_UopsSymbol *left;
+ JitOptSymbol *right;
+ JitOptSymbol *left;
right = stack_pointer[-1];
left = stack_pointer[-2];
if (sym_matches_type(left, &PyFloat_Type)) {
@@ -393,9 +393,9 @@
}
case _BINARY_OP_MULTIPLY_FLOAT: {
- _Py_UopsSymbol *right;
- _Py_UopsSymbol *left;
- _Py_UopsSymbol *res;
+ JitOptSymbol *right;
+ JitOptSymbol *left;
+ JitOptSymbol *res;
right = stack_pointer[-1];
left = stack_pointer[-2];
if (sym_is_const(left) && sym_is_const(right) &&
@@ -427,9 +427,9 @@
}
case _BINARY_OP_ADD_FLOAT: {
- _Py_UopsSymbol *right;
- _Py_UopsSymbol *left;
- _Py_UopsSymbol *res;
+ JitOptSymbol *right;
+ JitOptSymbol *left;
+ JitOptSymbol *res;
right = stack_pointer[-1];
left = stack_pointer[-2];
if (sym_is_const(left) && sym_is_const(right) &&
@@ -461,9 +461,9 @@
}
case _BINARY_OP_SUBTRACT_FLOAT: {
- _Py_UopsSymbol *right;
- _Py_UopsSymbol *left;
- _Py_UopsSymbol *res;
+ JitOptSymbol *right;
+ JitOptSymbol *left;
+ JitOptSymbol *res;
right = stack_pointer[-1];
left = stack_pointer[-2];
if (sym_is_const(left) && sym_is_const(right) &&
@@ -495,8 +495,8 @@
}
case _GUARD_BOTH_UNICODE: {
- _Py_UopsSymbol *right;
- _Py_UopsSymbol *left;
+ JitOptSymbol *right;
+ JitOptSymbol *left;
right = stack_pointer[-1];
left = stack_pointer[-2];
if (sym_matches_type(left, &PyUnicode_Type) &&
@@ -509,9 +509,9 @@
}
case _BINARY_OP_ADD_UNICODE: {
- _Py_UopsSymbol *right;
- _Py_UopsSymbol *left;
- _Py_UopsSymbol *res;
+ JitOptSymbol *right;
+ JitOptSymbol *left;
+ JitOptSymbol *res;
right = stack_pointer[-1];
left = stack_pointer[-2];
if (sym_is_const(left) && sym_is_const(right) &&
@@ -536,11 +536,11 @@
}
case _BINARY_OP_INPLACE_ADD_UNICODE: {
- _Py_UopsSymbol *right;
- _Py_UopsSymbol *left;
+ JitOptSymbol *right;
+ JitOptSymbol *left;
right = stack_pointer[-1];
left = stack_pointer[-2];
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
if (sym_is_const(left) && sym_is_const(right) &&
sym_matches_type(left, &PyUnicode_Type) && sym_matches_type(right, &PyUnicode_Type)) {
PyObject *temp = PyUnicode_Concat(sym_get_const(left), sym_get_const(right));
@@ -567,7 +567,7 @@
}
case _BINARY_OP_EXTEND: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-2] = res;
stack_pointer += -1;
@@ -576,7 +576,7 @@
}
case _BINARY_SUBSCR: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-2] = res;
stack_pointer += -1;
@@ -585,7 +585,7 @@
}
case _BINARY_SLICE: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-3] = res;
stack_pointer += -2;
@@ -600,7 +600,7 @@
}
case _BINARY_SUBSCR_LIST_INT: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-2] = res;
stack_pointer += -1;
@@ -609,7 +609,7 @@
}
case _BINARY_SUBSCR_STR_INT: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-2] = res;
stack_pointer += -1;
@@ -618,7 +618,7 @@
}
case _BINARY_SUBSCR_TUPLE_INT: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-2] = res;
stack_pointer += -1;
@@ -627,7 +627,7 @@
}
case _BINARY_SUBSCR_DICT: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-2] = res;
stack_pointer += -1;
@@ -636,7 +636,7 @@
}
case _BINARY_SUBSCR_CHECK_FUNC: {
- _Py_UopsSymbol *getitem;
+ JitOptSymbol *getitem;
getitem = sym_new_not_null(ctx);
stack_pointer[0] = getitem;
stack_pointer += 1;
@@ -645,9 +645,9 @@
}
case _BINARY_SUBSCR_INIT_CALL: {
- _Py_UopsSymbol *getitem;
- _Py_UopsSymbol *sub;
- _Py_UopsSymbol *container;
+ JitOptSymbol *getitem;
+ JitOptSymbol *sub;
+ JitOptSymbol *container;
_Py_UOpsAbstractFrame *new_frame;
getitem = stack_pointer[-1];
sub = stack_pointer[-2];
@@ -657,7 +657,7 @@
(void)getitem;
new_frame = NULL;
ctx->done = true;
- stack_pointer[-3] = (_Py_UopsSymbol *)new_frame;
+ stack_pointer[-3] = (JitOptSymbol *)new_frame;
stack_pointer += -2;
assert(WITHIN_STACK_BOUNDS());
break;
@@ -700,14 +700,14 @@
}
case _CALL_INTRINSIC_1: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-1] = res;
break;
}
case _CALL_INTRINSIC_2: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-2] = res;
stack_pointer += -1;
@@ -716,8 +716,8 @@
}
case _RETURN_VALUE: {
- _Py_UopsSymbol *retval;
- _Py_UopsSymbol *res;
+ JitOptSymbol *retval;
+ JitOptSymbol *res;
retval = stack_pointer[-1];
stack_pointer += -1;
assert(WITHIN_STACK_BOUNDS());
@@ -744,14 +744,14 @@
}
case _GET_AITER: {
- _Py_UopsSymbol *iter;
+ JitOptSymbol *iter;
iter = sym_new_not_null(ctx);
stack_pointer[-1] = iter;
break;
}
case _GET_ANEXT: {
- _Py_UopsSymbol *awaitable;
+ JitOptSymbol *awaitable;
awaitable = sym_new_not_null(ctx);
stack_pointer[0] = awaitable;
stack_pointer += 1;
@@ -760,7 +760,7 @@
}
case _GET_AWAITABLE: {
- _Py_UopsSymbol *iter;
+ JitOptSymbol *iter;
iter = sym_new_not_null(ctx);
stack_pointer[-1] = iter;
break;
@@ -775,7 +775,7 @@
}
case _YIELD_VALUE: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_unknown(ctx);
stack_pointer[-1] = res;
break;
@@ -788,7 +788,7 @@
}
case _LOAD_COMMON_CONSTANT: {
- _Py_UopsSymbol *value;
+ JitOptSymbol *value;
value = sym_new_not_null(ctx);
stack_pointer[0] = value;
stack_pointer += 1;
@@ -797,7 +797,7 @@
}
case _LOAD_BUILD_CLASS: {
- _Py_UopsSymbol *bc;
+ JitOptSymbol *bc;
bc = sym_new_not_null(ctx);
stack_pointer[0] = bc;
stack_pointer += 1;
@@ -816,8 +816,8 @@
}
case _UNPACK_SEQUENCE: {
- _Py_UopsSymbol *seq;
- _Py_UopsSymbol **values;
+ JitOptSymbol *seq;
+ JitOptSymbol **values;
seq = stack_pointer[-1];
values = &stack_pointer[-1];
/* This has to be done manually */
@@ -831,10 +831,12 @@
}
case _UNPACK_SEQUENCE_TWO_TUPLE: {
- _Py_UopsSymbol *val1;
- _Py_UopsSymbol *val0;
- val1 = sym_new_not_null(ctx);
- val0 = sym_new_not_null(ctx);
+ JitOptSymbol *seq;
+ JitOptSymbol *val1;
+ JitOptSymbol *val0;
+ seq = stack_pointer[-1];
+ val0 = sym_tuple_getitem(ctx, seq, 0);
+ val1 = sym_tuple_getitem(ctx, seq, 1);
stack_pointer[-1] = val1;
stack_pointer[0] = val0;
stack_pointer += 1;
@@ -843,10 +845,12 @@
}
case _UNPACK_SEQUENCE_TUPLE: {
- _Py_UopsSymbol **values;
+ JitOptSymbol *seq;
+ JitOptSymbol **values;
+ seq = stack_pointer[-1];
values = &stack_pointer[-1];
- for (int _i = oparg; --_i >= 0;) {
- values[_i] = sym_new_not_null(ctx);
+ for (int i = 0; i < oparg; i++) {
+ values[i] = sym_tuple_getitem(ctx, seq, i);
}
stack_pointer += -1 + oparg;
assert(WITHIN_STACK_BOUNDS());
@@ -854,7 +858,7 @@
}
case _UNPACK_SEQUENCE_LIST: {
- _Py_UopsSymbol **values;
+ JitOptSymbol **values;
values = &stack_pointer[-1];
for (int _i = oparg; --_i >= 0;) {
values[_i] = sym_new_not_null(ctx);
@@ -865,8 +869,8 @@
}
case _UNPACK_EX: {
- _Py_UopsSymbol *seq;
- _Py_UopsSymbol **values;
+ JitOptSymbol *seq;
+ JitOptSymbol **values;
seq = stack_pointer[-1];
values = &stack_pointer[-1];
/* This has to be done manually */
@@ -903,7 +907,7 @@
}
case _LOAD_LOCALS: {
- _Py_UopsSymbol *locals;
+ JitOptSymbol *locals;
locals = sym_new_not_null(ctx);
stack_pointer[0] = locals;
stack_pointer += 1;
@@ -914,7 +918,7 @@
/* _LOAD_FROM_DICT_OR_GLOBALS is not a viable micro-op for tier 2 */
case _LOAD_NAME: {
- _Py_UopsSymbol *v;
+ JitOptSymbol *v;
v = sym_new_not_null(ctx);
stack_pointer[0] = v;
stack_pointer += 1;
@@ -923,8 +927,8 @@
}
case _LOAD_GLOBAL: {
- _Py_UopsSymbol **res;
- _Py_UopsSymbol *null = NULL;
+ JitOptSymbol **res;
+ JitOptSymbol *null = NULL;
res = &stack_pointer[0];
res[0] = sym_new_not_null(ctx);
null = sym_new_null(ctx);
@@ -939,7 +943,7 @@
}
case _GUARD_GLOBALS_VERSION_PUSH_KEYS: {
- _Py_UopsSymbol *globals_keys;
+ JitOptSymbol *globals_keys;
uint16_t version = (uint16_t)this_instr->operand0;
globals_keys = sym_new_unknown(ctx);
(void)version;
@@ -950,7 +954,7 @@
}
case _GUARD_BUILTINS_VERSION_PUSH_KEYS: {
- _Py_UopsSymbol *builtins_keys;
+ JitOptSymbol *builtins_keys;
uint16_t version = (uint16_t)this_instr->operand0;
builtins_keys = sym_new_unknown(ctx);
(void)version;
@@ -961,8 +965,8 @@
}
case _LOAD_GLOBAL_MODULE_FROM_KEYS: {
- _Py_UopsSymbol *res;
- _Py_UopsSymbol *null = NULL;
+ JitOptSymbol *res;
+ JitOptSymbol *null = NULL;
res = sym_new_not_null(ctx);
null = sym_new_null(ctx);
stack_pointer[-1] = res;
@@ -973,8 +977,8 @@
}
case _LOAD_GLOBAL_BUILTINS_FROM_KEYS: {
- _Py_UopsSymbol *res;
- _Py_UopsSymbol *null = NULL;
+ JitOptSymbol *res;
+ JitOptSymbol *null = NULL;
res = sym_new_not_null(ctx);
null = sym_new_null(ctx);
stack_pointer[-1] = res;
@@ -997,14 +1001,14 @@
}
case _LOAD_FROM_DICT_OR_DEREF: {
- _Py_UopsSymbol *value;
+ JitOptSymbol *value;
value = sym_new_not_null(ctx);
stack_pointer[-1] = value;
break;
}
case _LOAD_DEREF: {
- _Py_UopsSymbol *value;
+ JitOptSymbol *value;
value = sym_new_not_null(ctx);
stack_pointer[0] = value;
stack_pointer += 1;
@@ -1023,7 +1027,7 @@
}
case _BUILD_STRING: {
- _Py_UopsSymbol *str;
+ JitOptSymbol *str;
str = sym_new_not_null(ctx);
stack_pointer[-oparg] = str;
stack_pointer += 1 - oparg;
@@ -1032,8 +1036,10 @@
}
case _BUILD_TUPLE: {
- _Py_UopsSymbol *tup;
- tup = sym_new_not_null(ctx);
+ JitOptSymbol **values;
+ JitOptSymbol *tup;
+ values = &stack_pointer[-oparg];
+ tup = sym_new_tuple(ctx, oparg, values);
stack_pointer[-oparg] = tup;
stack_pointer += 1 - oparg;
assert(WITHIN_STACK_BOUNDS());
@@ -1041,7 +1047,7 @@
}
case _BUILD_LIST: {
- _Py_UopsSymbol *list;
+ JitOptSymbol *list;
list = sym_new_not_null(ctx);
stack_pointer[-oparg] = list;
stack_pointer += 1 - oparg;
@@ -1062,7 +1068,7 @@
}
case _BUILD_SET: {
- _Py_UopsSymbol *set;
+ JitOptSymbol *set;
set = sym_new_not_null(ctx);
stack_pointer[-oparg] = set;
stack_pointer += 1 - oparg;
@@ -1071,7 +1077,7 @@
}
case _BUILD_MAP: {
- _Py_UopsSymbol *map;
+ JitOptSymbol *map;
map = sym_new_not_null(ctx);
stack_pointer[-oparg*2] = map;
stack_pointer += 1 - oparg*2;
@@ -1104,7 +1110,7 @@
/* _INSTRUMENTED_LOAD_SUPER_ATTR is not a viable micro-op for tier 2 */
case _LOAD_SUPER_ATTR_ATTR: {
- _Py_UopsSymbol *attr_st;
+ JitOptSymbol *attr_st;
attr_st = sym_new_not_null(ctx);
stack_pointer[-3] = attr_st;
stack_pointer += -2;
@@ -1113,8 +1119,8 @@
}
case _LOAD_SUPER_ATTR_METHOD: {
- _Py_UopsSymbol *attr;
- _Py_UopsSymbol *self_or_null;
+ JitOptSymbol *attr;
+ JitOptSymbol *self_or_null;
attr = sym_new_not_null(ctx);
self_or_null = sym_new_not_null(ctx);
stack_pointer[-3] = attr;
@@ -1125,9 +1131,9 @@
}
case _LOAD_ATTR: {
- _Py_UopsSymbol *owner;
- _Py_UopsSymbol *attr;
- _Py_UopsSymbol *self_or_null = NULL;
+ JitOptSymbol *owner;
+ JitOptSymbol *attr;
+ JitOptSymbol *self_or_null = NULL;
owner = stack_pointer[-1];
(void)owner;
attr = sym_new_not_null(ctx);
@@ -1140,7 +1146,7 @@
}
case _GUARD_TYPE_VERSION: {
- _Py_UopsSymbol *owner;
+ JitOptSymbol *owner;
owner = stack_pointer[-1];
uint32_t type_version = (uint32_t)this_instr->operand0;
assert(type_version);
@@ -1174,9 +1180,9 @@
}
case _LOAD_ATTR_INSTANCE_VALUE: {
- _Py_UopsSymbol *owner;
- _Py_UopsSymbol *attr;
- _Py_UopsSymbol *null = NULL;
+ JitOptSymbol *owner;
+ JitOptSymbol *attr;
+ JitOptSymbol *null = NULL;
owner = stack_pointer[-1];
uint16_t offset = (uint16_t)this_instr->operand0;
attr = sym_new_not_null(ctx);
@@ -1191,8 +1197,8 @@
}
case _CHECK_ATTR_MODULE_PUSH_KEYS: {
- _Py_UopsSymbol *owner;
- _Py_UopsSymbol *mod_keys;
+ JitOptSymbol *owner;
+ JitOptSymbol *mod_keys;
owner = stack_pointer[-1];
uint32_t dict_version = (uint32_t)this_instr->operand0;
(void)dict_version;
@@ -1222,9 +1228,9 @@
}
case _LOAD_ATTR_MODULE_FROM_KEYS: {
- _Py_UopsSymbol *owner;
- _Py_UopsSymbol *attr;
- _Py_UopsSymbol *null = NULL;
+ JitOptSymbol *owner;
+ JitOptSymbol *attr;
+ JitOptSymbol *null = NULL;
owner = stack_pointer[-2];
uint16_t index = (uint16_t)this_instr->operand0;
(void)index;
@@ -1263,8 +1269,8 @@
}
case _CHECK_ATTR_WITH_HINT: {
- _Py_UopsSymbol *owner;
- _Py_UopsSymbol *dict;
+ JitOptSymbol *owner;
+ JitOptSymbol *dict;
owner = stack_pointer[-1];
dict = sym_new_not_null(ctx);
(void)owner;
@@ -1275,10 +1281,10 @@
}
case _LOAD_ATTR_WITH_HINT: {
- _Py_UopsSymbol *dict;
- _Py_UopsSymbol *owner;
- _Py_UopsSymbol *attr;
- _Py_UopsSymbol *null = NULL;
+ JitOptSymbol *dict;
+ JitOptSymbol *owner;
+ JitOptSymbol *attr;
+ JitOptSymbol *null = NULL;
dict = stack_pointer[-1];
owner = stack_pointer[-2];
uint16_t hint = (uint16_t)this_instr->operand0;
@@ -1295,9 +1301,9 @@
}
case _LOAD_ATTR_SLOT: {
- _Py_UopsSymbol *owner;
- _Py_UopsSymbol *attr;
- _Py_UopsSymbol *null = NULL;
+ JitOptSymbol *owner;
+ JitOptSymbol *attr;
+ JitOptSymbol *null = NULL;
owner = stack_pointer[-1];
uint16_t index = (uint16_t)this_instr->operand0;
attr = sym_new_not_null(ctx);
@@ -1316,9 +1322,9 @@
}
case _LOAD_ATTR_CLASS: {
- _Py_UopsSymbol *owner;
- _Py_UopsSymbol *attr;
- _Py_UopsSymbol *null = NULL;
+ JitOptSymbol *owner;
+ JitOptSymbol *attr;
+ JitOptSymbol *null = NULL;
owner = stack_pointer[-1];
PyObject *descr = (PyObject *)this_instr->operand0;
attr = sym_new_not_null(ctx);
@@ -1333,7 +1339,7 @@
}
case _LOAD_ATTR_PROPERTY_FRAME: {
- _Py_UopsSymbol *owner;
+ JitOptSymbol *owner;
_Py_UOpsAbstractFrame *new_frame;
owner = stack_pointer[-1];
PyObject *fget = (PyObject *)this_instr->operand0;
@@ -1341,7 +1347,7 @@
(void)owner;
new_frame = NULL;
ctx->done = true;
- stack_pointer[-1] = (_Py_UopsSymbol *)new_frame;
+ stack_pointer[-1] = (JitOptSymbol *)new_frame;
break;
}
@@ -1370,9 +1376,9 @@
}
case _COMPARE_OP: {
- _Py_UopsSymbol *right;
- _Py_UopsSymbol *left;
- _Py_UopsSymbol *res;
+ JitOptSymbol *right;
+ JitOptSymbol *left;
+ JitOptSymbol *res;
right = stack_pointer[-1];
left = stack_pointer[-2];
(void)left;
@@ -1394,9 +1400,9 @@
}
case _COMPARE_OP_FLOAT: {
- _Py_UopsSymbol *right;
- _Py_UopsSymbol *left;
- _Py_UopsSymbol *res;
+ JitOptSymbol *right;
+ JitOptSymbol *left;
+ JitOptSymbol *res;
right = stack_pointer[-1];
left = stack_pointer[-2];
(void)left;
@@ -1409,9 +1415,9 @@
}
case _COMPARE_OP_INT: {
- _Py_UopsSymbol *right;
- _Py_UopsSymbol *left;
- _Py_UopsSymbol *res;
+ JitOptSymbol *right;
+ JitOptSymbol *left;
+ JitOptSymbol *res;
right = stack_pointer[-1];
left = stack_pointer[-2];
(void)left;
@@ -1424,9 +1430,9 @@
}
case _COMPARE_OP_STR: {
- _Py_UopsSymbol *right;
- _Py_UopsSymbol *left;
- _Py_UopsSymbol *res;
+ JitOptSymbol *right;
+ JitOptSymbol *left;
+ JitOptSymbol *res;
right = stack_pointer[-1];
left = stack_pointer[-2];
(void)left;
@@ -1439,9 +1445,9 @@
}
case _IS_OP: {
- _Py_UopsSymbol *right;
- _Py_UopsSymbol *left;
- _Py_UopsSymbol *res;
+ JitOptSymbol *right;
+ JitOptSymbol *left;
+ JitOptSymbol *res;
right = stack_pointer[-1];
left = stack_pointer[-2];
(void)left;
@@ -1454,9 +1460,9 @@
}
case _CONTAINS_OP: {
- _Py_UopsSymbol *right;
- _Py_UopsSymbol *left;
- _Py_UopsSymbol *res;
+ JitOptSymbol *right;
+ JitOptSymbol *left;
+ JitOptSymbol *res;
right = stack_pointer[-1];
left = stack_pointer[-2];
(void)left;
@@ -1469,7 +1475,7 @@
}
case _CONTAINS_OP_SET: {
- _Py_UopsSymbol *b;
+ JitOptSymbol *b;
b = sym_new_not_null(ctx);
stack_pointer[-2] = b;
stack_pointer += -1;
@@ -1478,7 +1484,7 @@
}
case _CONTAINS_OP_DICT: {
- _Py_UopsSymbol *b;
+ JitOptSymbol *b;
b = sym_new_not_null(ctx);
stack_pointer[-2] = b;
stack_pointer += -1;
@@ -1487,8 +1493,8 @@
}
case _CHECK_EG_MATCH: {
- _Py_UopsSymbol *rest;
- _Py_UopsSymbol *match;
+ JitOptSymbol *rest;
+ JitOptSymbol *match;
rest = sym_new_not_null(ctx);
match = sym_new_not_null(ctx);
stack_pointer[-2] = rest;
@@ -1497,14 +1503,14 @@
}
case _CHECK_EXC_MATCH: {
- _Py_UopsSymbol *b;
+ JitOptSymbol *b;
b = sym_new_not_null(ctx);
stack_pointer[-1] = b;
break;
}
case _IMPORT_NAME: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-2] = res;
stack_pointer += -1;
@@ -1513,7 +1519,7 @@
}
case _IMPORT_FROM: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[0] = res;
stack_pointer += 1;
@@ -1526,14 +1532,14 @@
/* _POP_JUMP_IF_TRUE is not a viable micro-op for tier 2 */
case _IS_NONE: {
- _Py_UopsSymbol *b;
+ JitOptSymbol *b;
b = sym_new_not_null(ctx);
stack_pointer[-1] = b;
break;
}
case _GET_LEN: {
- _Py_UopsSymbol *len;
+ JitOptSymbol *len;
len = sym_new_not_null(ctx);
stack_pointer[0] = len;
stack_pointer += 1;
@@ -1542,7 +1548,7 @@
}
case _MATCH_CLASS: {
- _Py_UopsSymbol *attrs;
+ JitOptSymbol *attrs;
attrs = sym_new_not_null(ctx);
stack_pointer[-3] = attrs;
stack_pointer += -2;
@@ -1551,7 +1557,7 @@
}
case _MATCH_MAPPING: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[0] = res;
stack_pointer += 1;
@@ -1560,7 +1566,7 @@
}
case _MATCH_SEQUENCE: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[0] = res;
stack_pointer += 1;
@@ -1569,7 +1575,7 @@
}
case _MATCH_KEYS: {
- _Py_UopsSymbol *values_or_none;
+ JitOptSymbol *values_or_none;
values_or_none = sym_new_not_null(ctx);
stack_pointer[0] = values_or_none;
stack_pointer += 1;
@@ -1578,14 +1584,14 @@
}
case _GET_ITER: {
- _Py_UopsSymbol *iter;
+ JitOptSymbol *iter;
iter = sym_new_not_null(ctx);
stack_pointer[-1] = iter;
break;
}
case _GET_YIELD_FROM_ITER: {
- _Py_UopsSymbol *iter;
+ JitOptSymbol *iter;
iter = sym_new_not_null(ctx);
stack_pointer[-1] = iter;
break;
@@ -1594,7 +1600,7 @@
/* _FOR_ITER is not a viable micro-op for tier 2 */
case _FOR_ITER_TIER_TWO: {
- _Py_UopsSymbol *next;
+ JitOptSymbol *next;
next = sym_new_not_null(ctx);
stack_pointer[0] = next;
stack_pointer += 1;
@@ -1615,7 +1621,7 @@
}
case _ITER_NEXT_LIST: {
- _Py_UopsSymbol *next;
+ JitOptSymbol *next;
next = sym_new_not_null(ctx);
stack_pointer[0] = next;
stack_pointer += 1;
@@ -1634,7 +1640,7 @@
}
case _ITER_NEXT_TUPLE: {
- _Py_UopsSymbol *next;
+ JitOptSymbol *next;
next = sym_new_not_null(ctx);
stack_pointer[0] = next;
stack_pointer += 1;
@@ -1653,8 +1659,8 @@
}
case _ITER_NEXT_RANGE: {
- _Py_UopsSymbol *iter;
- _Py_UopsSymbol *next;
+ JitOptSymbol *iter;
+ JitOptSymbol *next;
iter = stack_pointer[-1];
next = sym_new_type(ctx, &PyLong_Type);
(void)iter;
@@ -1671,9 +1677,9 @@
}
case _LOAD_SPECIAL: {
- _Py_UopsSymbol *owner;
- _Py_UopsSymbol *attr;
- _Py_UopsSymbol *self_or_null;
+ JitOptSymbol *owner;
+ JitOptSymbol *attr;
+ JitOptSymbol *self_or_null;
owner = stack_pointer[-1];
(void)owner;
attr = sym_new_not_null(ctx);
@@ -1686,7 +1692,7 @@
}
case _WITH_EXCEPT_START: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[0] = res;
stack_pointer += 1;
@@ -1695,8 +1701,8 @@
}
case _PUSH_EXC_INFO: {
- _Py_UopsSymbol *prev_exc;
- _Py_UopsSymbol *new_exc;
+ JitOptSymbol *prev_exc;
+ JitOptSymbol *new_exc;
prev_exc = sym_new_not_null(ctx);
new_exc = sym_new_not_null(ctx);
stack_pointer[-1] = prev_exc;
@@ -1715,9 +1721,9 @@
}
case _LOAD_ATTR_METHOD_WITH_VALUES: {
- _Py_UopsSymbol *owner;
- _Py_UopsSymbol *attr;
- _Py_UopsSymbol *self = NULL;
+ JitOptSymbol *owner;
+ JitOptSymbol *attr;
+ JitOptSymbol *self = NULL;
owner = stack_pointer[-1];
PyObject *descr = (PyObject *)this_instr->operand0;
(void)descr;
@@ -1731,9 +1737,9 @@
}
case _LOAD_ATTR_METHOD_NO_DICT: {
- _Py_UopsSymbol *owner;
- _Py_UopsSymbol *attr;
- _Py_UopsSymbol *self = NULL;
+ JitOptSymbol *owner;
+ JitOptSymbol *attr;
+ JitOptSymbol *self = NULL;
owner = stack_pointer[-1];
PyObject *descr = (PyObject *)this_instr->operand0;
(void)descr;
@@ -1747,14 +1753,14 @@
}
case _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES: {
- _Py_UopsSymbol *attr;
+ JitOptSymbol *attr;
attr = sym_new_not_null(ctx);
stack_pointer[-1] = attr;
break;
}
case _LOAD_ATTR_NONDESCRIPTOR_NO_DICT: {
- _Py_UopsSymbol *attr;
+ JitOptSymbol *attr;
attr = sym_new_not_null(ctx);
stack_pointer[-1] = attr;
break;
@@ -1765,9 +1771,9 @@
}
case _LOAD_ATTR_METHOD_LAZY_DICT: {
- _Py_UopsSymbol *owner;
- _Py_UopsSymbol *attr;
- _Py_UopsSymbol *self = NULL;
+ JitOptSymbol *owner;
+ JitOptSymbol *attr;
+ JitOptSymbol *self = NULL;
owner = stack_pointer[-1];
PyObject *descr = (PyObject *)this_instr->operand0;
(void)descr;
@@ -1781,11 +1787,11 @@
}
case _MAYBE_EXPAND_METHOD: {
- _Py_UopsSymbol **args;
- _Py_UopsSymbol *self_or_null;
- _Py_UopsSymbol *callable;
- _Py_UopsSymbol *func;
- _Py_UopsSymbol *maybe_self;
+ JitOptSymbol **args;
+ JitOptSymbol *self_or_null;
+ JitOptSymbol *callable;
+ JitOptSymbol *func;
+ JitOptSymbol *maybe_self;
args = &stack_pointer[-oparg];
self_or_null = stack_pointer[-1 - oparg];
callable = stack_pointer[-2 - oparg];
@@ -1805,8 +1811,8 @@
/* _MONITOR_CALL is not a viable micro-op for tier 2 */
case _PY_FRAME_GENERAL: {
- _Py_UopsSymbol *self_or_null;
- _Py_UopsSymbol *callable;
+ JitOptSymbol *self_or_null;
+ JitOptSymbol *callable;
_Py_UOpsAbstractFrame *new_frame;
self_or_null = stack_pointer[-1 - oparg];
callable = stack_pointer[-2 - oparg];
@@ -1822,15 +1828,15 @@
break;
}
new_frame = frame_new(ctx, co, 0, NULL, 0);
- stack_pointer[0] = (_Py_UopsSymbol *)new_frame;
+ stack_pointer[0] = (JitOptSymbol *)new_frame;
stack_pointer += 1;
assert(WITHIN_STACK_BOUNDS());
break;
}
case _CHECK_FUNCTION_VERSION: {
- _Py_UopsSymbol *self_or_null;
- _Py_UopsSymbol *callable;
+ JitOptSymbol *self_or_null;
+ JitOptSymbol *callable;
self_or_null = stack_pointer[-1 - oparg];
callable = stack_pointer[-2 - oparg];
uint32_t func_version = (uint32_t)this_instr->operand0;
@@ -1853,8 +1859,8 @@
}
case _EXPAND_METHOD: {
- _Py_UopsSymbol **method;
- _Py_UopsSymbol **self;
+ JitOptSymbol **method;
+ JitOptSymbol **self;
method = &stack_pointer[-2 - oparg];
self = &stack_pointer[-1 - oparg];
method[0] = sym_new_not_null(ctx);
@@ -1867,7 +1873,7 @@
}
case _CALL_NON_PY_GENERAL: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-2 - oparg] = res;
stack_pointer += -1 - oparg;
@@ -1876,8 +1882,8 @@
}
case _CHECK_CALL_BOUND_METHOD_EXACT_ARGS: {
- _Py_UopsSymbol *null;
- _Py_UopsSymbol *callable;
+ JitOptSymbol *null;
+ JitOptSymbol *callable;
null = stack_pointer[-1 - oparg];
callable = stack_pointer[-2 - oparg];
sym_set_null(null);
@@ -1886,9 +1892,9 @@
}
case _INIT_CALL_BOUND_METHOD_EXACT_ARGS: {
- _Py_UopsSymbol *callable;
- _Py_UopsSymbol *func;
- _Py_UopsSymbol *self;
+ JitOptSymbol *callable;
+ JitOptSymbol *func;
+ JitOptSymbol *self;
callable = stack_pointer[-2 - oparg];
(void)callable;
func = sym_new_not_null(ctx);
@@ -1908,8 +1914,8 @@
}
case _CHECK_FUNCTION_EXACT_ARGS: {
- _Py_UopsSymbol *self_or_null;
- _Py_UopsSymbol *callable;
+ JitOptSymbol *self_or_null;
+ JitOptSymbol *callable;
self_or_null = stack_pointer[-1 - oparg];
callable = stack_pointer[-2 - oparg];
assert(sym_matches_type(callable, &PyFunction_Type));
@@ -1933,9 +1939,9 @@
}
case _INIT_CALL_PY_EXACT_ARGS: {
- _Py_UopsSymbol **args;
- _Py_UopsSymbol *self_or_null;
- _Py_UopsSymbol *callable;
+ JitOptSymbol **args;
+ JitOptSymbol *self_or_null;
+ JitOptSymbol *callable;
_Py_UOpsAbstractFrame *new_frame;
args = &stack_pointer[-oparg];
self_or_null = stack_pointer[-1 - oparg];
@@ -1963,7 +1969,7 @@
} else {
new_frame = frame_new(ctx, co, 0, NULL, 0);
}
- stack_pointer[0] = (_Py_UopsSymbol *)new_frame;
+ stack_pointer[0] = (JitOptSymbol *)new_frame;
stack_pointer += 1;
assert(WITHIN_STACK_BOUNDS());
break;
@@ -2008,7 +2014,7 @@
}
case _CALL_TYPE_1: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-3] = res;
stack_pointer += -2;
@@ -2017,7 +2023,7 @@
}
case _CALL_STR_1: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-3] = res;
stack_pointer += -2;
@@ -2026,7 +2032,7 @@
}
case _CALL_TUPLE_1: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-3] = res;
stack_pointer += -2;
@@ -2035,11 +2041,11 @@
}
case _CHECK_AND_ALLOCATE_OBJECT: {
- _Py_UopsSymbol **args;
- _Py_UopsSymbol *null;
- _Py_UopsSymbol *callable;
- _Py_UopsSymbol *self;
- _Py_UopsSymbol *init;
+ JitOptSymbol **args;
+ JitOptSymbol *null;
+ JitOptSymbol *callable;
+ JitOptSymbol *self;
+ JitOptSymbol *init;
args = &stack_pointer[-oparg];
null = stack_pointer[-1 - oparg];
callable = stack_pointer[-2 - oparg];
@@ -2057,9 +2063,9 @@
}
case _CREATE_INIT_FRAME: {
- _Py_UopsSymbol **args;
- _Py_UopsSymbol *init;
- _Py_UopsSymbol *self;
+ JitOptSymbol **args;
+ JitOptSymbol *init;
+ JitOptSymbol *self;
_Py_UOpsAbstractFrame *init_frame;
args = &stack_pointer[-oparg];
init = stack_pointer[-1 - oparg];
@@ -2069,7 +2075,7 @@
(void)args;
init_frame = NULL;
ctx->done = true;
- stack_pointer[-2 - oparg] = (_Py_UopsSymbol *)init_frame;
+ stack_pointer[-2 - oparg] = (JitOptSymbol *)init_frame;
stack_pointer += -1 - oparg;
assert(WITHIN_STACK_BOUNDS());
break;
@@ -2082,7 +2088,7 @@
}
case _CALL_BUILTIN_CLASS: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-2 - oparg] = res;
stack_pointer += -1 - oparg;
@@ -2091,7 +2097,7 @@
}
case _CALL_BUILTIN_O: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-2 - oparg] = res;
stack_pointer += -1 - oparg;
@@ -2100,7 +2106,7 @@
}
case _CALL_BUILTIN_FAST: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-2 - oparg] = res;
stack_pointer += -1 - oparg;
@@ -2109,7 +2115,7 @@
}
case _CALL_BUILTIN_FAST_WITH_KEYWORDS: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-2 - oparg] = res;
stack_pointer += -1 - oparg;
@@ -2118,7 +2124,7 @@
}
case _CALL_LEN: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-2 - oparg] = res;
stack_pointer += -1 - oparg;
@@ -2127,7 +2133,7 @@
}
case _CALL_ISINSTANCE: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-2 - oparg] = res;
stack_pointer += -1 - oparg;
@@ -2142,7 +2148,7 @@
}
case _CALL_METHOD_DESCRIPTOR_O: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-2 - oparg] = res;
stack_pointer += -1 - oparg;
@@ -2151,7 +2157,7 @@
}
case _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-2 - oparg] = res;
stack_pointer += -1 - oparg;
@@ -2160,7 +2166,7 @@
}
case _CALL_METHOD_DESCRIPTOR_NOARGS: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-2 - oparg] = res;
stack_pointer += -1 - oparg;
@@ -2169,7 +2175,7 @@
}
case _CALL_METHOD_DESCRIPTOR_FAST: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-2 - oparg] = res;
stack_pointer += -1 - oparg;
@@ -2180,10 +2186,10 @@
/* _INSTRUMENTED_CALL_KW is not a viable micro-op for tier 2 */
case _MAYBE_EXPAND_METHOD_KW: {
- _Py_UopsSymbol **func;
- _Py_UopsSymbol **maybe_self;
- _Py_UopsSymbol **args;
- _Py_UopsSymbol *kwnames_out;
+ JitOptSymbol **func;
+ JitOptSymbol **maybe_self;
+ JitOptSymbol **args;
+ JitOptSymbol *kwnames_out;
func = &stack_pointer[-3 - oparg];
maybe_self = &stack_pointer[-2 - oparg];
args = &stack_pointer[-1 - oparg];
@@ -2200,10 +2206,10 @@
/* _DO_CALL_KW is not a viable micro-op for tier 2 */
case _PY_FRAME_KW: {
- _Py_UopsSymbol *kwnames;
- _Py_UopsSymbol **args;
- _Py_UopsSymbol *self_or_null;
- _Py_UopsSymbol *callable;
+ JitOptSymbol *kwnames;
+ JitOptSymbol **args;
+ JitOptSymbol *self_or_null;
+ JitOptSymbol *callable;
_Py_UOpsAbstractFrame *new_frame;
kwnames = stack_pointer[-1];
args = &stack_pointer[-1 - oparg];
@@ -2215,7 +2221,7 @@
(void)kwnames;
new_frame = NULL;
ctx->done = true;
- stack_pointer[-3 - oparg] = (_Py_UopsSymbol *)new_frame;
+ stack_pointer[-3 - oparg] = (JitOptSymbol *)new_frame;
stack_pointer += -2 - oparg;
assert(WITHIN_STACK_BOUNDS());
break;
@@ -2230,8 +2236,8 @@
}
case _EXPAND_METHOD_KW: {
- _Py_UopsSymbol **method;
- _Py_UopsSymbol **self;
+ JitOptSymbol **method;
+ JitOptSymbol **self;
method = &stack_pointer[-3 - oparg];
self = &stack_pointer[-2 - oparg];
method[0] = sym_new_not_null(ctx);
@@ -2244,7 +2250,7 @@
}
case _CALL_KW_NON_PY: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-3 - oparg] = res;
stack_pointer += -2 - oparg;
@@ -2255,8 +2261,8 @@
/* _INSTRUMENTED_CALL_FUNCTION_EX is not a viable micro-op for tier 2 */
case _MAKE_CALLARGS_A_TUPLE: {
- _Py_UopsSymbol *tuple;
- _Py_UopsSymbol *kwargs_out = NULL;
+ JitOptSymbol *tuple;
+ JitOptSymbol *kwargs_out = NULL;
tuple = sym_new_not_null(ctx);
kwargs_out = sym_new_not_null(ctx);
stack_pointer[-1 - (oparg & 1)] = tuple;
@@ -2267,14 +2273,14 @@
/* _DO_CALL_FUNCTION_EX is not a viable micro-op for tier 2 */
case _MAKE_FUNCTION: {
- _Py_UopsSymbol *func;
+ JitOptSymbol *func;
func = sym_new_not_null(ctx);
stack_pointer[-1] = func;
break;
}
case _SET_FUNCTION_ATTRIBUTE: {
- _Py_UopsSymbol *func_out;
+ JitOptSymbol *func_out;
func_out = sym_new_not_null(ctx);
stack_pointer[-2] = func_out;
stack_pointer += -1;
@@ -2283,7 +2289,7 @@
}
case _RETURN_GENERATOR: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
ctx->frame->stack_pointer = stack_pointer;
frame_pop(ctx);
stack_pointer = ctx->frame->stack_pointer;
@@ -2307,7 +2313,7 @@
}
case _BUILD_SLICE: {
- _Py_UopsSymbol *slice;
+ JitOptSymbol *slice;
slice = sym_new_not_null(ctx);
stack_pointer[-2 - ((oparg == 3) ? 1 : 0)] = slice;
stack_pointer += -1 - ((oparg == 3) ? 1 : 0);
@@ -2316,21 +2322,21 @@
}
case _CONVERT_VALUE: {
- _Py_UopsSymbol *result;
+ JitOptSymbol *result;
result = sym_new_not_null(ctx);
stack_pointer[-1] = result;
break;
}
case _FORMAT_SIMPLE: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-1] = res;
break;
}
case _FORMAT_WITH_SPEC: {
- _Py_UopsSymbol *res;
+ JitOptSymbol *res;
res = sym_new_not_null(ctx);
stack_pointer[-2] = res;
stack_pointer += -1;
@@ -2339,8 +2345,8 @@
}
case _COPY: {
- _Py_UopsSymbol *bottom;
- _Py_UopsSymbol *top;
+ JitOptSymbol *bottom;
+ JitOptSymbol *top;
bottom = stack_pointer[-1 - (oparg-1)];
assert(oparg > 0);
top = bottom;
@@ -2351,9 +2357,9 @@
}
case _BINARY_OP: {
- _Py_UopsSymbol *right;
- _Py_UopsSymbol *left;
- _Py_UopsSymbol *res;
+ JitOptSymbol *right;
+ JitOptSymbol *left;
+ JitOptSymbol *res;
right = stack_pointer[-1];
left = stack_pointer[-2];
bool lhs_int = sym_matches_type(left, &PyLong_Type);
@@ -2426,10 +2432,10 @@
}
case _SWAP: {
- _Py_UopsSymbol *top_in;
- _Py_UopsSymbol *bottom_in;
- _Py_UopsSymbol *top_out;
- _Py_UopsSymbol *bottom_out;
+ JitOptSymbol *top_in;
+ JitOptSymbol *bottom_in;
+ JitOptSymbol *top_out;
+ JitOptSymbol *bottom_out;
top_in = stack_pointer[-1];
bottom_in = stack_pointer[-2 - (oparg-2)];
bottom_out = bottom_in;
@@ -2458,7 +2464,7 @@
/* _INSTRUMENTED_POP_JUMP_IF_NOT_NONE is not a viable micro-op for tier 2 */
case _GUARD_IS_TRUE_POP: {
- _Py_UopsSymbol *flag;
+ JitOptSymbol *flag;
flag = stack_pointer[-1];
if (sym_is_const(flag)) {
PyObject *value = sym_get_const(flag);
@@ -2475,7 +2481,7 @@
}
case _GUARD_IS_FALSE_POP: {
- _Py_UopsSymbol *flag;
+ JitOptSymbol *flag;
flag = stack_pointer[-1];
if (sym_is_const(flag)) {
PyObject *value = sym_get_const(flag);
@@ -2492,7 +2498,7 @@
}
case _GUARD_IS_NONE_POP: {
- _Py_UopsSymbol *flag;
+ JitOptSymbol *flag;
flag = stack_pointer[-1];
if (sym_is_const(flag)) {
PyObject *value = sym_get_const(flag);
@@ -2517,7 +2523,7 @@
}
case _GUARD_IS_NOT_NONE_POP: {
- _Py_UopsSymbol *flag;
+ JitOptSymbol *flag;
flag = stack_pointer[-1];
if (sym_is_const(flag)) {
PyObject *value = sym_get_const(flag);
@@ -2575,7 +2581,7 @@
}
case _LOAD_CONST_INLINE: {
- _Py_UopsSymbol *value;
+ JitOptSymbol *value;
PyObject *ptr = (PyObject *)this_instr->operand0;
value = sym_new_const(ctx, ptr);
stack_pointer[0] = value;
@@ -2585,7 +2591,7 @@
}
case _LOAD_CONST_INLINE_BORROW: {
- _Py_UopsSymbol *value;
+ JitOptSymbol *value;
PyObject *ptr = (PyObject *)this_instr->operand0;
value = sym_new_const(ctx, ptr);
stack_pointer[0] = value;
@@ -2595,15 +2601,15 @@
}
case _POP_TOP_LOAD_CONST_INLINE_BORROW: {
- _Py_UopsSymbol *value;
+ JitOptSymbol *value;
value = sym_new_not_null(ctx);
stack_pointer[-1] = value;
break;
}
case _LOAD_CONST_INLINE_WITH_NULL: {
- _Py_UopsSymbol *value;
- _Py_UopsSymbol *null;
+ JitOptSymbol *value;
+ JitOptSymbol *null;
PyObject *ptr = (PyObject *)this_instr->operand0;
value = sym_new_const(ctx, ptr);
null = sym_new_null(ctx);
@@ -2615,8 +2621,8 @@
}
case _LOAD_CONST_INLINE_BORROW_WITH_NULL: {
- _Py_UopsSymbol *value;
- _Py_UopsSymbol *null;
+ JitOptSymbol *value;
+ JitOptSymbol *null;
PyObject *ptr = (PyObject *)this_instr->operand0;
value = sym_new_const(ctx, ptr);
null = sym_new_null(ctx);
@@ -2632,8 +2638,8 @@
}
case _LOAD_GLOBAL_MODULE: {
- _Py_UopsSymbol *res;
- _Py_UopsSymbol *null = NULL;
+ JitOptSymbol *res;
+ JitOptSymbol *null = NULL;
res = sym_new_not_null(ctx);
null = sym_new_null(ctx);
stack_pointer[0] = res;
@@ -2644,8 +2650,8 @@
}
case _LOAD_GLOBAL_BUILTINS: {
- _Py_UopsSymbol *res;
- _Py_UopsSymbol *null = NULL;
+ JitOptSymbol *res;
+ JitOptSymbol *null = NULL;
res = sym_new_not_null(ctx);
null = sym_new_null(ctx);
stack_pointer[0] = res;
@@ -2656,8 +2662,8 @@
}
case _LOAD_ATTR_MODULE: {
- _Py_UopsSymbol *attr;
- _Py_UopsSymbol *null = NULL;
+ JitOptSymbol *attr;
+ JitOptSymbol *null = NULL;
attr = sym_new_not_null(ctx);
null = sym_new_null(ctx);
stack_pointer[-1] = attr;
diff --git a/Python/optimizer_symbols.c b/Python/optimizer_symbols.c
index 40cbf95e3d6d39..dcde8e7ce81577 100644
--- a/Python/optimizer_symbols.c
+++ b/Python/optimizer_symbols.c
@@ -28,11 +28,6 @@
- Bottom: IS_NULL and NOT_NULL flags set, type and const_val NULL.
*/
-// Flags for below.
-#define IS_NULL 1 << 0
-#define NOT_NULL 1 << 1
-#define NO_SPACE 1 << 2
-
#ifdef Py_DEBUG
static inline int get_lltrace(void) {
char *uop_debug = Py_GETENV("PYTHON_OPT_DEBUG");
@@ -48,187 +43,254 @@ static inline int get_lltrace(void) {
#define DPRINTF(level, ...)
#endif
-static _Py_UopsSymbol NO_SPACE_SYMBOL = {
- .flags = IS_NULL | NOT_NULL | NO_SPACE,
- .typ = NULL,
- .const_val = NULL,
- .type_version = 0,
+
+static JitOptSymbol NO_SPACE_SYMBOL = {
+ .tag = JIT_SYM_BOTTOM_TAG
};
-_Py_UopsSymbol *
-out_of_space(_Py_UOpsContext *ctx)
+JitOptSymbol *
+out_of_space(JitOptContext *ctx)
{
ctx->done = true;
ctx->out_of_space = true;
return &NO_SPACE_SYMBOL;
}
-static _Py_UopsSymbol *
-sym_new(_Py_UOpsContext *ctx)
+static JitOptSymbol *
+sym_new(JitOptContext *ctx)
{
- _Py_UopsSymbol *self = &ctx->t_arena.arena[ctx->t_arena.ty_curr_number];
+ JitOptSymbol *self = &ctx->t_arena.arena[ctx->t_arena.ty_curr_number];
if (ctx->t_arena.ty_curr_number >= ctx->t_arena.ty_max_number) {
OPT_STAT_INC(optimizer_failure_reason_no_memory);
DPRINTF(1, "out of space for symbolic expression type\n");
return NULL;
}
ctx->t_arena.ty_curr_number++;
- self->flags = 0;
- self->typ = NULL;
- self->const_val = NULL;
- self->type_version = 0;
-
+ self->tag = JIT_SYM_UNKNOWN_TAG;
return self;
}
static inline void
-sym_set_flag(_Py_UopsSymbol *sym, int flag)
-{
- sym->flags |= flag;
-}
-
-static inline void
-sym_set_bottom(_Py_UOpsContext *ctx, _Py_UopsSymbol *sym)
+sym_set_bottom(JitOptContext *ctx, JitOptSymbol *sym)
{
- sym_set_flag(sym, IS_NULL | NOT_NULL);
- sym->typ = NULL;
- Py_CLEAR(sym->const_val);
+ sym->tag = JIT_SYM_BOTTOM_TAG;
ctx->done = true;
ctx->contradiction = true;
}
bool
-_Py_uop_sym_is_bottom(_Py_UopsSymbol *sym)
+_Py_uop_sym_is_bottom(JitOptSymbol *sym)
{
- if ((sym->flags & IS_NULL) && (sym->flags & NOT_NULL)) {
- assert(sym->flags == (IS_NULL | NOT_NULL));
- assert(sym->typ == NULL);
- assert(sym->const_val == NULL);
- return true;
- }
- return false;
+ return sym->tag == JIT_SYM_BOTTOM_TAG;
}
bool
-_Py_uop_sym_is_not_null(_Py_UopsSymbol *sym)
-{
- return sym->flags == NOT_NULL;
+_Py_uop_sym_is_not_null(JitOptSymbol *sym) {
+ return sym->tag == JIT_SYM_NON_NULL_TAG || sym->tag > JIT_SYM_BOTTOM_TAG;
}
bool
-_Py_uop_sym_is_null(_Py_UopsSymbol *sym)
+_Py_uop_sym_is_const(JitOptSymbol *sym)
{
- return sym->flags == IS_NULL;
+ return sym->tag == JIT_SYM_KNOWN_VALUE_TAG;
}
bool
-_Py_uop_sym_is_const(_Py_UopsSymbol *sym)
+_Py_uop_sym_is_null(JitOptSymbol *sym)
{
- return sym->const_val != NULL;
+ return sym->tag == JIT_SYM_NULL_TAG;
}
+
PyObject *
-_Py_uop_sym_get_const(_Py_UopsSymbol *sym)
+_Py_uop_sym_get_const(JitOptSymbol *sym)
{
- return sym->const_val;
+ if (sym->tag == JIT_SYM_KNOWN_VALUE_TAG) {
+ return sym->value.value;
+ }
+ return NULL;
}
void
-_Py_uop_sym_set_type(_Py_UOpsContext *ctx, _Py_UopsSymbol *sym, PyTypeObject *typ)
+_Py_uop_sym_set_type(JitOptContext *ctx, JitOptSymbol *sym, PyTypeObject *typ)
{
- assert(typ != NULL && PyType_Check(typ));
- if (sym->flags & IS_NULL) {
- sym_set_bottom(ctx, sym);
- return;
- }
- if (sym->typ != NULL) {
- if (sym->typ != typ) {
+ JitSymType tag = sym->tag;
+ switch(tag) {
+ case JIT_SYM_NULL_TAG:
sym_set_bottom(ctx, sym);
return;
- }
- }
- else {
- sym_set_flag(sym, NOT_NULL);
- sym->typ = typ;
+ case JIT_SYM_KNOWN_CLASS_TAG:
+ if (sym->cls.type != typ) {
+ sym_set_bottom(ctx, sym);
+ }
+ return;
+ case JIT_SYM_TYPE_VERSION_TAG:
+ if (sym->version.version == typ->tp_version_tag) {
+ sym->tag = JIT_SYM_KNOWN_CLASS_TAG;
+ sym->cls.type = typ;
+ sym->cls.version = typ->tp_version_tag;
+ }
+ else {
+ sym_set_bottom(ctx, sym);
+ }
+ return;
+ case JIT_SYM_KNOWN_VALUE_TAG:
+ if (Py_TYPE(sym->value.value) != typ) {
+ Py_CLEAR(sym->value.value);
+ sym_set_bottom(ctx, sym);
+ }
+ return;
+ case JIT_SYM_TUPLE_TAG:
+ if (typ != &PyTuple_Type) {
+ sym_set_bottom(ctx, sym);
+ }
+ return;
+ case JIT_SYM_BOTTOM_TAG:
+ return;
+ case JIT_SYM_NON_NULL_TAG:
+ case JIT_SYM_UNKNOWN_TAG:
+ sym->tag = JIT_SYM_KNOWN_CLASS_TAG;
+ sym->cls.version = 0;
+ sym->cls.type = typ;
+ return;
}
}
bool
-_Py_uop_sym_set_type_version(_Py_UOpsContext *ctx, _Py_UopsSymbol *sym, unsigned int version)
+_Py_uop_sym_set_type_version(JitOptContext *ctx, JitOptSymbol *sym, unsigned int version)
{
- // if the type version was already set, then it must be different and we should set it to bottom
- if (sym->type_version) {
- sym_set_bottom(ctx, sym);
- return false;
+ JitSymType tag = sym->tag;
+ switch(tag) {
+ case JIT_SYM_NULL_TAG:
+ sym_set_bottom(ctx, sym);
+ return false;
+ case JIT_SYM_KNOWN_CLASS_TAG:
+ if (sym->cls.type->tp_version_tag != version) {
+ sym_set_bottom(ctx, sym);
+ return false;
+ }
+ else {
+ sym->cls.version = version;
+ return true;
+ }
+ case JIT_SYM_KNOWN_VALUE_TAG:
+ Py_CLEAR(sym->value.value);
+ sym_set_bottom(ctx, sym);
+ return false;
+ case JIT_SYM_TUPLE_TAG:
+ sym_set_bottom(ctx, sym);
+ return false;
+ case JIT_SYM_TYPE_VERSION_TAG:
+ if (sym->version.version == version) {
+ return true;
+ }
+ sym_set_bottom(ctx, sym);
+ return false;
+ case JIT_SYM_BOTTOM_TAG:
+ return false;
+ case JIT_SYM_NON_NULL_TAG:
+ case JIT_SYM_UNKNOWN_TAG:
+ sym->tag = JIT_SYM_TYPE_VERSION_TAG;
+ sym->version.version = version;
+ return true;
}
- sym->type_version = version;
- return true;
+ Py_UNREACHABLE();
+}
+
+static void make_const(JitOptSymbol *sym, PyObject *val)
+{
+ sym->tag = JIT_SYM_KNOWN_VALUE_TAG;
+ sym->value.value = Py_NewRef(val);
}
void
-_Py_uop_sym_set_const(_Py_UOpsContext *ctx, _Py_UopsSymbol *sym, PyObject *const_val)
+_Py_uop_sym_set_const(JitOptContext *ctx, JitOptSymbol *sym, PyObject *const_val)
{
- assert(const_val != NULL);
- if (sym->flags & IS_NULL) {
- sym_set_bottom(ctx, sym);
- }
- PyTypeObject *typ = Py_TYPE(const_val);
- if (sym->typ != NULL && sym->typ != typ) {
- sym_set_bottom(ctx, sym);
- }
- if (sym->const_val != NULL) {
- if (sym->const_val != const_val) {
- // TODO: What if they're equal?
+ JitSymType tag = sym->tag;
+ switch(tag) {
+ case JIT_SYM_NULL_TAG:
sym_set_bottom(ctx, sym);
- }
- }
- else {
- sym_set_flag(sym, NOT_NULL);
- sym->typ = typ;
- sym->const_val = Py_NewRef(const_val);
+ return;
+ case JIT_SYM_KNOWN_CLASS_TAG:
+ if (sym->cls.type != Py_TYPE(const_val)) {
+ sym_set_bottom(ctx, sym);
+ return;
+ }
+ make_const(sym, const_val);
+ return;
+ case JIT_SYM_KNOWN_VALUE_TAG:
+ if (sym->value.value != const_val) {
+ Py_CLEAR(sym->value.value);
+ sym_set_bottom(ctx, sym);
+ }
+ return;
+ case JIT_SYM_TUPLE_TAG:
+ sym_set_bottom(ctx, sym);
+ return;
+ case JIT_SYM_TYPE_VERSION_TAG:
+ if (sym->version.version != Py_TYPE(const_val)->tp_version_tag) {
+ sym_set_bottom(ctx, sym);
+ return;
+ }
+ make_const(sym, const_val);
+ return;
+ case JIT_SYM_BOTTOM_TAG:
+ return;
+ case JIT_SYM_NON_NULL_TAG:
+ case JIT_SYM_UNKNOWN_TAG:
+ make_const(sym, const_val);
+ return;
}
}
void
-_Py_uop_sym_set_null(_Py_UOpsContext *ctx, _Py_UopsSymbol *sym)
+_Py_uop_sym_set_null(JitOptContext *ctx, JitOptSymbol *sym)
{
- if (_Py_uop_sym_is_not_null(sym)) {
+ if (sym->tag == JIT_SYM_UNKNOWN_TAG) {
+ sym->tag = JIT_SYM_NULL_TAG;
+ }
+ else if (sym->tag > JIT_SYM_NULL_TAG) {
sym_set_bottom(ctx, sym);
}
- sym_set_flag(sym, IS_NULL);
}
void
-_Py_uop_sym_set_non_null(_Py_UOpsContext *ctx, _Py_UopsSymbol *sym)
+_Py_uop_sym_set_non_null(JitOptContext *ctx, JitOptSymbol *sym)
{
- if (_Py_uop_sym_is_null(sym)) {
+ if (sym->tag == JIT_SYM_UNKNOWN_TAG) {
+ sym->tag = JIT_SYM_NON_NULL_TAG;
+ }
+ else if (sym->tag == JIT_SYM_NULL_TAG) {
sym_set_bottom(ctx, sym);
}
- sym_set_flag(sym, NOT_NULL);
}
-_Py_UopsSymbol *
-_Py_uop_sym_new_unknown(_Py_UOpsContext *ctx)
+JitOptSymbol *
+_Py_uop_sym_new_unknown(JitOptContext *ctx)
{
- return sym_new(ctx);
+ JitOptSymbol *res = sym_new(ctx);
+ if (res == NULL) {
+ return out_of_space(ctx);
+ }
+ return res;
}
-_Py_UopsSymbol *
-_Py_uop_sym_new_not_null(_Py_UOpsContext *ctx)
+JitOptSymbol *
+_Py_uop_sym_new_not_null(JitOptContext *ctx)
{
- _Py_UopsSymbol *res = _Py_uop_sym_new_unknown(ctx);
+ JitOptSymbol *res = sym_new(ctx);
if (res == NULL) {
return out_of_space(ctx);
}
- sym_set_flag(res, NOT_NULL);
+ res->tag = JIT_SYM_NON_NULL_TAG;
return res;
}
-_Py_UopsSymbol *
-_Py_uop_sym_new_type(_Py_UOpsContext *ctx, PyTypeObject *typ)
+JitOptSymbol *
+_Py_uop_sym_new_type(JitOptContext *ctx, PyTypeObject *typ)
{
- _Py_UopsSymbol *res = sym_new(ctx);
+ JitOptSymbol *res = sym_new(ctx);
if (res == NULL) {
return out_of_space(ctx);
}
@@ -237,11 +299,11 @@ _Py_uop_sym_new_type(_Py_UOpsContext *ctx, PyTypeObject *typ)
}
// Adds a new reference to const_val, owned by the symbol.
-_Py_UopsSymbol *
-_Py_uop_sym_new_const(_Py_UOpsContext *ctx, PyObject *const_val)
+JitOptSymbol *
+_Py_uop_sym_new_const(JitOptContext *ctx, PyObject *const_val)
{
assert(const_val != NULL);
- _Py_UopsSymbol *res = sym_new(ctx);
+ JitOptSymbol *res = sym_new(ctx);
if (res == NULL) {
return out_of_space(ctx);
}
@@ -249,10 +311,10 @@ _Py_uop_sym_new_const(_Py_UOpsContext *ctx, PyObject *const_val)
return res;
}
-_Py_UopsSymbol *
-_Py_uop_sym_new_null(_Py_UOpsContext *ctx)
+JitOptSymbol *
+_Py_uop_sym_new_null(JitOptContext *ctx)
{
- _Py_UopsSymbol *null_sym = _Py_uop_sym_new_unknown(ctx);
+ JitOptSymbol *null_sym = sym_new(ctx);
if (null_sym == NULL) {
return out_of_space(ctx);
}
@@ -261,64 +323,105 @@ _Py_uop_sym_new_null(_Py_UOpsContext *ctx)
}
PyTypeObject *
-_Py_uop_sym_get_type(_Py_UopsSymbol *sym)
+_Py_uop_sym_get_type(JitOptSymbol *sym)
{
- if (_Py_uop_sym_is_bottom(sym)) {
- return NULL;
- }
- return sym->typ;
+ JitSymType tag = sym->tag;
+ switch(tag) {
+ case JIT_SYM_NULL_TAG:
+ case JIT_SYM_TYPE_VERSION_TAG:
+ case JIT_SYM_BOTTOM_TAG:
+ case JIT_SYM_NON_NULL_TAG:
+ case JIT_SYM_UNKNOWN_TAG:
+ return NULL;
+ case JIT_SYM_KNOWN_CLASS_TAG:
+ return sym->cls.type;
+ case JIT_SYM_KNOWN_VALUE_TAG:
+ return Py_TYPE(sym->value.value);
+ case JIT_SYM_TUPLE_TAG:
+ return &PyTuple_Type;
+ }
+ Py_UNREACHABLE();
}
unsigned int
-_Py_uop_sym_get_type_version(_Py_UopsSymbol *sym)
+_Py_uop_sym_get_type_version(JitOptSymbol *sym)
{
- return sym->type_version;
+ JitSymType tag = sym->tag;
+ switch(tag) {
+ case JIT_SYM_NULL_TAG:
+ case JIT_SYM_BOTTOM_TAG:
+ case JIT_SYM_NON_NULL_TAG:
+ case JIT_SYM_UNKNOWN_TAG:
+ return 0;
+ case JIT_SYM_TYPE_VERSION_TAG:
+ return sym->version.version;
+ case JIT_SYM_KNOWN_CLASS_TAG:
+ return sym->cls.version;
+ case JIT_SYM_KNOWN_VALUE_TAG:
+ return Py_TYPE(sym->value.value)->tp_version_tag;
+ case JIT_SYM_TUPLE_TAG:
+ return PyTuple_Type.tp_version_tag;
+ }
+ Py_UNREACHABLE();
}
bool
-_Py_uop_sym_has_type(_Py_UopsSymbol *sym)
+_Py_uop_sym_has_type(JitOptSymbol *sym)
{
- if (_Py_uop_sym_is_bottom(sym)) {
- return false;
- }
- return sym->typ != NULL;
+ JitSymType tag = sym->tag;
+ switch(tag) {
+ case JIT_SYM_NULL_TAG:
+ case JIT_SYM_TYPE_VERSION_TAG:
+ case JIT_SYM_BOTTOM_TAG:
+ case JIT_SYM_NON_NULL_TAG:
+ case JIT_SYM_UNKNOWN_TAG:
+ return false;
+ case JIT_SYM_KNOWN_CLASS_TAG:
+ case JIT_SYM_KNOWN_VALUE_TAG:
+ case JIT_SYM_TUPLE_TAG:
+ return true;
+ }
+ Py_UNREACHABLE();
}
bool
-_Py_uop_sym_matches_type(_Py_UopsSymbol *sym, PyTypeObject *typ)
+_Py_uop_sym_matches_type(JitOptSymbol *sym, PyTypeObject *typ)
{
assert(typ != NULL && PyType_Check(typ));
return _Py_uop_sym_get_type(sym) == typ;
}
bool
-_Py_uop_sym_matches_type_version(_Py_UopsSymbol *sym, unsigned int version)
+_Py_uop_sym_matches_type_version(JitOptSymbol *sym, unsigned int version)
{
return _Py_uop_sym_get_type_version(sym) == version;
}
-
int
-_Py_uop_sym_truthiness(_Py_UopsSymbol *sym)
-{
- /* There are some non-constant values for
- * which `bool(val)` always evaluates to
- * True or False, such as tuples with known
- * length, but unknown contents, or bound-methods.
- * This function will need updating
- * should we support those values.
- */
- if (_Py_uop_sym_is_bottom(sym)) {
- return -1;
- }
- if (!_Py_uop_sym_is_const(sym)) {
- return -1;
- }
- PyObject *value = _Py_uop_sym_get_const(sym);
+_Py_uop_sym_truthiness(JitOptSymbol *sym)
+{
+ switch(sym->tag) {
+ case JIT_SYM_NULL_TAG:
+ case JIT_SYM_TYPE_VERSION_TAG:
+ case JIT_SYM_BOTTOM_TAG:
+ case JIT_SYM_NON_NULL_TAG:
+ case JIT_SYM_UNKNOWN_TAG:
+ return -1;
+ case JIT_SYM_KNOWN_CLASS_TAG:
+ /* TODO :
+ * Instances of some classes are always
+ * true. We should return 1 in those cases */
+ return -1;
+ case JIT_SYM_KNOWN_VALUE_TAG:
+ break;
+ case JIT_SYM_TUPLE_TAG:
+ return sym->tuple.length != 0;
+ }
+ PyObject *value = sym->value.value;
+ /* Only handle a few known safe types */
if (value == Py_None) {
return 0;
}
- /* Only handle a few known safe types */
PyTypeObject *tp = Py_TYPE(value);
if (tp == &PyLong_Type) {
return !_PyLong_IsZero((PyLongObject *)value);
@@ -332,13 +435,84 @@ _Py_uop_sym_truthiness(_Py_UopsSymbol *sym)
return -1;
}
+static JitOptSymbol *
+allocation_base(JitOptContext *ctx)
+{
+ return ctx->t_arena.arena;
+}
+
+JitOptSymbol *
+_Py_uop_sym_new_tuple(JitOptContext *ctx, int size, JitOptSymbol **args)
+{
+ JitOptSymbol *res = sym_new(ctx);
+ if (res == NULL) {
+ return out_of_space(ctx);
+ }
+ if (size > MAX_SYMBOLIC_TUPLE_SIZE) {
+ res->tag = JIT_SYM_KNOWN_CLASS_TAG;
+ res->cls.type = &PyTuple_Type;
+ }
+ else {
+ res->tag = JIT_SYM_TUPLE_TAG;
+ res->tuple.length = size;
+ for (int i = 0; i < size; i++) {
+ res->tuple.items[i] = (uint16_t)(args[i] - allocation_base(ctx));
+ }
+ }
+ return res;
+}
+
+JitOptSymbol *
+_Py_uop_sym_tuple_getitem(JitOptContext *ctx, JitOptSymbol *sym, int item)
+{
+ assert(item >= 0);
+ if (sym->tag == JIT_SYM_KNOWN_VALUE_TAG) {
+ PyObject *tuple = sym->value.value;
+ if (PyTuple_CheckExact(tuple) && item < PyTuple_GET_SIZE(tuple)) {
+ return _Py_uop_sym_new_const(ctx, PyTuple_GET_ITEM(tuple, item));
+ }
+ }
+ else if (sym->tag == JIT_SYM_TUPLE_TAG && item < sym->tuple.length) {
+ return allocation_base(ctx) + sym->tuple.items[item];
+ }
+ return _Py_uop_sym_new_unknown(ctx);
+}
+
+int
+_Py_uop_sym_tuple_length(JitOptSymbol *sym)
+{
+ if (sym->tag == JIT_SYM_KNOWN_VALUE_TAG) {
+ PyObject *tuple = sym->value.value;
+ if (PyTuple_CheckExact(tuple)) {
+ return PyTuple_GET_SIZE(tuple);
+ }
+ }
+ else if (sym->tag == JIT_SYM_TUPLE_TAG) {
+ return sym->tuple.length;
+ }
+ return -1;
+}
+
+// Return true if known to be immortal.
+bool
+_Py_uop_sym_is_immortal(JitOptSymbol *sym)
+{
+ if (sym->tag == JIT_SYM_KNOWN_VALUE_TAG) {
+ return _Py_IsImmortal(sym->value.value);
+ }
+ if (sym->tag == JIT_SYM_KNOWN_CLASS_TAG) {
+ return sym->cls.type == &PyBool_Type;
+ }
+ return false;
+}
+
// 0 on success, -1 on error.
_Py_UOpsAbstractFrame *
_Py_uop_frame_new(
- _Py_UOpsContext *ctx,
+ JitOptContext *ctx,
PyCodeObject *co,
int curr_stackentries,
- _Py_UopsSymbol **args,
+ JitOptSymbol **args,
int arg_len)
{
assert(ctx->curr_frame_depth < MAX_ABSTRACT_FRAME_DEPTH);
@@ -363,14 +537,14 @@ _Py_uop_frame_new(
}
for (int i = arg_len; i < co->co_nlocalsplus; i++) {
- _Py_UopsSymbol *local = _Py_uop_sym_new_unknown(ctx);
+ JitOptSymbol *local = _Py_uop_sym_new_unknown(ctx);
frame->locals[i] = local;
}
// Initialize the stack as well
for (int i = 0; i < curr_stackentries; i++) {
- _Py_UopsSymbol *stackvar = _Py_uop_sym_new_unknown(ctx);
+ JitOptSymbol *stackvar = _Py_uop_sym_new_unknown(ctx);
frame->stack[i] = stackvar;
}
@@ -378,7 +552,7 @@ _Py_uop_frame_new(
}
void
-_Py_uop_abstractcontext_fini(_Py_UOpsContext *ctx)
+_Py_uop_abstractcontext_fini(JitOptContext *ctx)
{
if (ctx == NULL) {
return;
@@ -386,13 +560,17 @@ _Py_uop_abstractcontext_fini(_Py_UOpsContext *ctx)
ctx->curr_frame_depth = 0;
int tys = ctx->t_arena.ty_curr_number;
for (int i = 0; i < tys; i++) {
- Py_CLEAR(ctx->t_arena.arena[i].const_val);
+ JitOptSymbol *sym = &ctx->t_arena.arena[i];
+ if (sym->tag == JIT_SYM_KNOWN_VALUE_TAG) {
+ Py_CLEAR(sym->value.value);
+ }
}
}
void
-_Py_uop_abstractcontext_init(_Py_UOpsContext *ctx)
+_Py_uop_abstractcontext_init(JitOptContext *ctx)
{
+ static_assert(sizeof(JitOptSymbol) <= 2*sizeof(uint64_t));
ctx->limit = ctx->locals_and_stack + MAX_ABSTRACT_INTERP_SIZE;
ctx->n_consumed = ctx->locals_and_stack;
#ifdef Py_DEBUG // Aids debugging a little. There should never be NULL in the abstract interpreter.
@@ -410,7 +588,7 @@ _Py_uop_abstractcontext_init(_Py_UOpsContext *ctx)
}
int
-_Py_uop_frame_pop(_Py_UOpsContext *ctx)
+_Py_uop_frame_pop(JitOptContext *ctx)
{
_Py_UOpsAbstractFrame *frame = ctx->frame;
ctx->n_consumed = frame->locals;
@@ -431,26 +609,25 @@ do { \
} \
} while (0)
-static _Py_UopsSymbol *
-make_bottom(_Py_UOpsContext *ctx)
+static JitOptSymbol *
+make_bottom(JitOptContext *ctx)
{
- _Py_UopsSymbol *sym = _Py_uop_sym_new_unknown(ctx);
- _Py_uop_sym_set_null(ctx, sym);
- _Py_uop_sym_set_non_null(ctx, sym);
+ JitOptSymbol *sym = sym_new(ctx);
+ sym->tag = JIT_SYM_BOTTOM_TAG;
return sym;
}
PyObject *
_Py_uop_symbols_test(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(ignored))
{
- _Py_UOpsContext context;
- _Py_UOpsContext *ctx = &context;
+ JitOptContext context;
+ JitOptContext *ctx = &context;
_Py_uop_abstractcontext_init(ctx);
PyObject *val_42 = NULL;
PyObject *val_43 = NULL;
// Use a single 'sym' variable so copy-pasting tests is easier.
- _Py_UopsSymbol *sym = _Py_uop_sym_new_unknown(ctx);
+ JitOptSymbol *sym = _Py_uop_sym_new_unknown(ctx);
if (sym == NULL) {
goto fail;
}
@@ -510,6 +687,7 @@ _Py_uop_symbols_test(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(ignored))
TEST_PREDICATE(_Py_uop_sym_is_const(sym), "42 is not a constant");
TEST_PREDICATE(_Py_uop_sym_get_const(sym) != NULL, "42 as constant is NULL");
TEST_PREDICATE(_Py_uop_sym_get_const(sym) == val_42, "42 as constant isn't 42");
+ TEST_PREDICATE(_Py_uop_sym_is_immortal(sym), "42 is not immortal");
_Py_uop_sym_set_type(ctx, sym, &PyLong_Type); // Should be a no-op
TEST_PREDICATE(_Py_uop_sym_matches_type(sym, &PyLong_Type), "(42 and 42) isn't an int");
@@ -518,6 +696,9 @@ _Py_uop_symbols_test(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(ignored))
_Py_uop_sym_set_type(ctx, sym, &PyFloat_Type); // Should make it bottom
TEST_PREDICATE(_Py_uop_sym_is_bottom(sym), "(42 and float) isn't bottom");
+ sym = _Py_uop_sym_new_type(ctx, &PyBool_Type);
+ TEST_PREDICATE(_Py_uop_sym_is_immortal(sym), "a bool is not immortal");
+
sym = _Py_uop_sym_new_type(ctx, &PyLong_Type);
if (sym == NULL) {
goto fail;
@@ -534,15 +715,37 @@ _Py_uop_symbols_test(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(ignored))
sym = _Py_uop_sym_new_const(ctx, PyLong_FromLong(0));
TEST_PREDICATE(_Py_uop_sym_truthiness(sym) == 0, "bool(0) is not False");
+ JitOptSymbol *i1 = _Py_uop_sym_new_type(ctx, &PyFloat_Type);
+ JitOptSymbol *i2 = _Py_uop_sym_new_const(ctx, val_43);
+ JitOptSymbol *array[2] = { i1, i2 };
+ sym = _Py_uop_sym_new_tuple(ctx, 2, array);
+ TEST_PREDICATE(
+ _Py_uop_sym_matches_type(_Py_uop_sym_tuple_getitem(ctx, sym, 0), &PyFloat_Type),
+ "tuple item does not match value used to create tuple"
+ );
+ TEST_PREDICATE(
+ _Py_uop_sym_get_const(_Py_uop_sym_tuple_getitem(ctx, sym, 1)) == val_43,
+ "tuple item does not match value used to create tuple"
+ );
+ PyObject *pair[2] = { val_42, val_43 };
+ PyObject *tuple = _PyTuple_FromArray(pair, 2);
+ sym = _Py_uop_sym_new_const(ctx, tuple);
+ TEST_PREDICATE(
+ _Py_uop_sym_get_const(_Py_uop_sym_tuple_getitem(ctx, sym, 1)) == val_43,
+ "tuple item does not match value used to create tuple"
+ );
+
_Py_uop_abstractcontext_fini(ctx);
Py_DECREF(val_42);
Py_DECREF(val_43);
+ Py_DECREF(tuple);
Py_RETURN_NONE;
fail:
_Py_uop_abstractcontext_fini(ctx);
Py_XDECREF(val_42);
Py_XDECREF(val_43);
+ Py_DECREF(tuple);
return NULL;
}
diff --git a/Tools/cases_generator/optimizer_generator.py b/Tools/cases_generator/optimizer_generator.py
index 2928440fecca0c..5cfec4bfecbf07 100644
--- a/Tools/cases_generator/optimizer_generator.py
+++ b/Tools/cases_generator/optimizer_generator.py
@@ -36,10 +36,10 @@ def validate_uop(override: Uop, uop: Uop) -> None:
def type_name(var: StackItem) -> str:
if var.is_array():
- return f"_Py_UopsSymbol **"
+ return f"JitOptSymbol **"
if var.type:
return var.type
- return f"_Py_UopsSymbol *"
+ return f"JitOptSymbol *"
def declare_variables(uop: Uop, out: CWriter, skip_inputs: bool) -> None:
@@ -151,11 +151,11 @@ def write_uop(
var.defined = False
storage = emitter.emit_tokens(override, storage, None)
out.start_line()
- storage.flush(out, cast_type="_Py_UopsSymbol *")
+ storage.flush(out, cast_type="JitOptSymbol *")
else:
emit_default(out, uop, stack)
out.start_line()
- stack.flush(out, cast_type="_Py_UopsSymbol *")
+ stack.flush(out, cast_type="JitOptSymbol *")
except StackError as ex:
raise analysis_error(ex.args[0], prototype.body[0]) # from None
1
0
gh-129044: Update glossary entry for 'loader' to reflect current import system (#129073)
by AA-Turner Jan. 20, 2025
by AA-Turner Jan. 20, 2025
Jan. 20, 2025
https://github.com/python/cpython/commit/e1fa2fcc7c1bf5291a7f71300b7828b49b…
commit: e1fa2fcc7c1bf5291a7f71300b7828b49be9ab72
branch: main
author: nikalinov <92603661+nikalinov(a)users.noreply.github.com>
committer: AA-Turner <9087854+AA-Turner(a)users.noreply.github.com>
date: 2025-01-20T15:46:09Z
summary:
gh-129044: Update glossary entry for 'loader' to reflect current import system (#129073)
Co-authored-by: Adam Turner <9087854+AA-Turner(a)users.noreply.github.com>
files:
M Doc/glossary.rst
M Doc/tools/.nitignore
diff --git a/Doc/glossary.rst b/Doc/glossary.rst
index 33e77c9de211eb..e3a14601398e89 100644
--- a/Doc/glossary.rst
+++ b/Doc/glossary.rst
@@ -811,9 +811,11 @@ Glossary
processed.
loader
- An object that loads a module. It must define a method named
- :meth:`load_module`. A loader is typically returned by a
- :term:`finder`. See also:
+ An object that loads a module.
+ It must define the :meth:`!exec_module` and :meth:`!create_module` methods
+ to implement the :class:`~importlib.abc.Loader` interface.
+ A loader is typically returned by a :term:`finder`.
+ See also:
* :ref:`finders-and-loaders`
* :class:`importlib.abc.Loader`
diff --git a/Doc/tools/.nitignore b/Doc/tools/.nitignore
index 6940c95ab2c9a1..ad24fe82f754fc 100644
--- a/Doc/tools/.nitignore
+++ b/Doc/tools/.nitignore
@@ -12,7 +12,6 @@ Doc/c-api/stable.rst
Doc/c-api/type.rst
Doc/c-api/typeobj.rst
Doc/extending/extending.rst
-Doc/glossary.rst
Doc/library/ast.rst
Doc/library/asyncio-extending.rst
Doc/library/asyncio-subprocess.rst
1
0
Jan. 20, 2025
https://github.com/python/cpython/commit/8ceb6cb117c8eda8c6913547f3a7de032e…
commit: 8ceb6cb117c8eda8c6913547f3a7de032ed25880
branch: main
author: Victor Stinner <vstinner(a)python.org>
committer: vstinner <vstinner(a)python.org>
date: 2025-01-20T16:31:33+01:00
summary:
gh-129033: Remove _PyInterpreterState_SetConfig() function (#129048)
Remove _PyInterpreterState_GetConfigCopy() and
_PyInterpreterState_SetConfig() private functions. PEP 741 "Python
Configuration C API" added a better public C API: PyConfig_Get() and
PyConfig_Set().
files:
A Misc/NEWS.d/next/C_API/2025-01-20-10-40-11.gh-issue-129033.d1jltB.rst
D Lib/test/_test_embed_set_config.py
M Include/internal/pycore_interp.h
M Lib/test/support/__init__.py
M Lib/test/test_capi/test_misc.py
M Lib/test/test_embed.py
M Lib/test/test_regrtest.py
M Modules/_testinternalcapi.c
M Programs/_testembed.c
M Python/pylifecycle.c
M Python/pystate.c
diff --git a/Include/internal/pycore_interp.h b/Include/internal/pycore_interp.h
index a3c14dceffd7a0..f745b09796753b 100644
--- a/Include/internal/pycore_interp.h
+++ b/Include/internal/pycore_interp.h
@@ -341,43 +341,6 @@ extern void _PyInterpreterState_SetWhence(
extern const PyConfig* _PyInterpreterState_GetConfig(PyInterpreterState *interp);
-// Get a copy of the current interpreter configuration.
-//
-// Return 0 on success. Raise an exception and return -1 on error.
-//
-// The caller must initialize 'config', using PyConfig_InitPythonConfig()
-// for example.
-//
-// Python must be preinitialized to call this method.
-// The caller must hold the GIL.
-//
-// Once done with the configuration, PyConfig_Clear() must be called to clear
-// it.
-//
-// Export for '_testinternalcapi' shared extension.
-PyAPI_FUNC(int) _PyInterpreterState_GetConfigCopy(
- struct PyConfig *config);
-
-// Set the configuration of the current interpreter.
-//
-// This function should be called during or just after the Python
-// initialization.
-//
-// Update the sys module with the new configuration. If the sys module was
-// modified directly after the Python initialization, these changes are lost.
-//
-// Some configuration like faulthandler or warnoptions can be updated in the
-// configuration, but don't reconfigure Python (don't enable/disable
-// faulthandler and don't reconfigure warnings filters).
-//
-// Return 0 on success. Raise an exception and return -1 on error.
-//
-// The configuration should come from _PyInterpreterState_GetConfigCopy().
-//
-// Export for '_testinternalcapi' shared extension.
-PyAPI_FUNC(int) _PyInterpreterState_SetConfig(
- const struct PyConfig *config);
-
/*
Runtime Feature Flags
diff --git a/Lib/test/_test_embed_set_config.py b/Lib/test/_test_embed_set_config.py
deleted file mode 100644
index 7edb35da463aa0..00000000000000
--- a/Lib/test/_test_embed_set_config.py
+++ /dev/null
@@ -1,291 +0,0 @@
-# bpo-42260: Test _PyInterpreterState_GetConfigCopy()
-# and _PyInterpreterState_SetConfig().
-#
-# Test run in a subprocess since set_config(get_config())
-# does reset sys attributes to their state of the Python startup
-# (before the site module is run).
-
-import _testinternalcapi
-import sys
-import unittest
-from test import support
-from test.support import MS_WINDOWS
-
-
-MAX_HASH_SEED = 4294967295
-
-
-BOOL_OPTIONS = [
- 'isolated',
- 'use_environment',
- 'dev_mode',
- 'install_signal_handlers',
- 'use_hash_seed',
- 'faulthandler',
- 'import_time',
- 'code_debug_ranges',
- 'show_ref_count',
- 'dump_refs',
- 'malloc_stats',
- 'parse_argv',
- 'site_import',
- 'warn_default_encoding',
- 'inspect',
- 'interactive',
- 'parser_debug',
- 'write_bytecode',
- 'quiet',
- 'user_site_directory',
- 'configure_c_stdio',
- 'buffered_stdio',
- 'use_frozen_modules',
- 'safe_path',
- 'pathconfig_warnings',
- 'module_search_paths_set',
- 'skip_source_first_line',
- '_install_importlib',
- '_init_main',
- '_is_python_build',
-]
-if MS_WINDOWS:
- BOOL_OPTIONS.append('legacy_windows_stdio')
-
-
-class SetConfigTests(unittest.TestCase):
- def setUp(self):
- self.old_config = _testinternalcapi.get_config()
- self.sys_copy = dict(sys.__dict__)
-
- def tearDown(self):
- _testinternalcapi.reset_path_config()
- _testinternalcapi.set_config(self.old_config)
- sys.__dict__.clear()
- sys.__dict__.update(self.sys_copy)
-
- def set_config(self, **kwargs):
- _testinternalcapi.set_config(self.old_config | kwargs)
-
- def check(self, **kwargs):
- self.set_config(**kwargs)
- for key, value in kwargs.items():
- self.assertEqual(getattr(sys, key), value,
- (key, value))
-
- def test_set_invalid(self):
- invalid_uint = -1
- NULL = None
- invalid_wstr = NULL
- # PyWideStringList strings must be non-NULL
- invalid_wstrlist = ["abc", NULL, "def"]
-
- type_tests = []
- value_tests = [
- # enum
- ('_config_init', 0),
- ('_config_init', 4),
- # unsigned long
- ("hash_seed", -1),
- ("hash_seed", MAX_HASH_SEED + 1),
- ]
-
- # int (unsigned)
- int_options = [
- '_config_init',
- 'bytes_warning',
- 'optimization_level',
- 'tracemalloc',
- 'verbose',
- ]
- int_options.extend(BOOL_OPTIONS)
- for key in int_options:
- value_tests.append((key, invalid_uint))
- type_tests.append((key, "abc"))
- type_tests.append((key, 2.0))
-
- # wchar_t*
- for key in (
- 'filesystem_encoding',
- 'filesystem_errors',
- 'stdio_encoding',
- 'stdio_errors',
- 'check_hash_pycs_mode',
- 'program_name',
- 'platlibdir',
- # optional wstr:
- # 'pythonpath_env'
- # 'home'
- # 'pycache_prefix'
- # 'run_command'
- # 'run_module'
- # 'run_filename'
- # 'executable'
- # 'prefix'
- # 'exec_prefix'
- # 'base_executable'
- # 'base_prefix'
- # 'base_exec_prefix'
- ):
- value_tests.append((key, invalid_wstr))
- type_tests.append((key, b'bytes'))
- type_tests.append((key, 123))
-
- # PyWideStringList
- for key in (
- 'orig_argv',
- 'argv',
- 'xoptions',
- 'warnoptions',
- 'module_search_paths',
- ):
- if key != 'xoptions':
- value_tests.append((key, invalid_wstrlist))
- type_tests.append((key, 123))
- type_tests.append((key, "abc"))
- type_tests.append((key, [123]))
- type_tests.append((key, [b"bytes"]))
-
-
- if MS_WINDOWS:
- value_tests.append(('legacy_windows_stdio', invalid_uint))
-
- for exc_type, tests in (
- (ValueError, value_tests),
- (TypeError, type_tests),
- ):
- for key, value in tests:
- config = self.old_config | {key: value}
- with self.subTest(key=key, value=value, exc_type=exc_type):
- with self.assertRaises(exc_type):
- _testinternalcapi.set_config(config)
-
- def test_flags(self):
- bool_options = set(BOOL_OPTIONS)
- for sys_attr, key, value in (
- ("debug", "parser_debug", 2),
- ("inspect", "inspect", 3),
- ("interactive", "interactive", 4),
- ("optimize", "optimization_level", 5),
- ("verbose", "verbose", 6),
- ("bytes_warning", "bytes_warning", 7),
- ("quiet", "quiet", 8),
- ("isolated", "isolated", 9),
- ):
- with self.subTest(sys=sys_attr, key=key, value=value):
- self.set_config(**{key: value, 'parse_argv': 0})
- if key in bool_options:
- self.assertEqual(getattr(sys.flags, sys_attr), int(bool(value)))
- else:
- self.assertEqual(getattr(sys.flags, sys_attr), value)
-
- self.set_config(write_bytecode=0)
- self.assertEqual(sys.flags.dont_write_bytecode, True)
- self.assertEqual(sys.dont_write_bytecode, True)
-
- self.set_config(write_bytecode=1)
- self.assertEqual(sys.flags.dont_write_bytecode, False)
- self.assertEqual(sys.dont_write_bytecode, False)
-
- self.set_config(user_site_directory=0, isolated=0)
- self.assertEqual(sys.flags.no_user_site, 1)
- self.set_config(user_site_directory=1, isolated=0)
- self.assertEqual(sys.flags.no_user_site, 0)
-
- self.set_config(site_import=0)
- self.assertEqual(sys.flags.no_site, 1)
- self.set_config(site_import=1)
- self.assertEqual(sys.flags.no_site, 0)
-
- self.set_config(dev_mode=0)
- self.assertEqual(sys.flags.dev_mode, False)
- self.set_config(dev_mode=1)
- self.assertEqual(sys.flags.dev_mode, True)
-
- self.set_config(use_environment=0, isolated=0)
- self.assertEqual(sys.flags.ignore_environment, 1)
- self.set_config(use_environment=1, isolated=0)
- self.assertEqual(sys.flags.ignore_environment, 0)
-
- self.set_config(use_hash_seed=1, hash_seed=0)
- self.assertEqual(sys.flags.hash_randomization, 0)
- self.set_config(use_hash_seed=0, hash_seed=0)
- self.assertEqual(sys.flags.hash_randomization, 1)
- self.set_config(use_hash_seed=1, hash_seed=123)
- self.assertEqual(sys.flags.hash_randomization, 1)
-
- if support.Py_GIL_DISABLED:
- self.set_config(enable_gil=-1)
- self.assertEqual(sys.flags.gil, None)
- self.set_config(enable_gil=0)
- self.assertEqual(sys.flags.gil, 0)
- self.set_config(enable_gil=1)
- self.assertEqual(sys.flags.gil, 1)
- else:
- # Builds without Py_GIL_DISABLED don't have
- # PyConfig.enable_gil. sys.flags.gil is always defined to 1, for
- # consistency.
- self.assertEqual(sys.flags.gil, 1)
-
- def test_options(self):
- self.check(warnoptions=[])
- self.check(warnoptions=["default", "ignore"])
-
- self.set_config(xoptions={})
- self.assertEqual(sys._xoptions, {})
- self.set_config(xoptions={"dev": True, "tracemalloc": "5"})
- self.assertEqual(sys._xoptions, {"dev": True, "tracemalloc": "5"})
-
- def test_pathconfig(self):
- self.check(
- executable='executable',
- prefix="prefix",
- base_prefix="base_prefix",
- exec_prefix="exec_prefix",
- base_exec_prefix="base_exec_prefix",
- platlibdir="platlibdir")
-
- self.set_config(base_executable="base_executable")
- self.assertEqual(sys._base_executable, "base_executable")
-
- # When base_xxx is NULL, value is copied from xxxx
- self.set_config(
- executable='executable',
- prefix="prefix",
- exec_prefix="exec_prefix",
- base_executable=None,
- base_prefix=None,
- base_exec_prefix=None)
- self.assertEqual(sys._base_executable, "executable")
- self.assertEqual(sys.base_prefix, "prefix")
- self.assertEqual(sys.base_exec_prefix, "exec_prefix")
-
- def test_path(self):
- self.set_config(module_search_paths_set=1,
- module_search_paths=['a', 'b', 'c'])
- self.assertEqual(sys.path, ['a', 'b', 'c'])
-
- # sys.path is reset if module_search_paths_set=0
- self.set_config(module_search_paths_set=0,
- module_search_paths=['new_path'])
- self.assertNotEqual(sys.path, ['a', 'b', 'c'])
- self.assertNotEqual(sys.path, ['new_path'])
-
- def test_argv(self):
- self.set_config(parse_argv=0,
- argv=['python_program', 'args'],
- orig_argv=['orig', 'orig_args'])
- self.assertEqual(sys.argv, ['python_program', 'args'])
- self.assertEqual(sys.orig_argv, ['orig', 'orig_args'])
-
- self.set_config(parse_argv=0,
- argv=[],
- orig_argv=[])
- self.assertEqual(sys.argv, [''])
- self.assertEqual(sys.orig_argv, [])
-
- def test_pycache_prefix(self):
- self.check(pycache_prefix=None)
- self.check(pycache_prefix="pycache_prefix")
-
-
-if __name__ == "__main__":
- unittest.main()
diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py
index e05e91babc2499..084b2411e799f4 100644
--- a/Lib/test/support/__init__.py
+++ b/Lib/test/support/__init__.py
@@ -505,10 +505,10 @@ def requires_lzma(reason='requires lzma'):
def has_no_debug_ranges():
try:
- import _testinternalcapi
+ import _testcapi
except ImportError:
raise unittest.SkipTest("_testinternalcapi required")
- config = _testinternalcapi.get_config()
+ return not _testcapi.config_get('code_debug_ranges')
return not bool(config['code_debug_ranges'])
def requires_debug_ranges(reason='requires co_positions / debug_ranges'):
diff --git a/Lib/test/test_capi/test_misc.py b/Lib/test/test_capi/test_misc.py
index ac09d72c7741c9..31a4a224ec8f88 100644
--- a/Lib/test/test_capi/test_misc.py
+++ b/Lib/test/test_capi/test_misc.py
@@ -2141,28 +2141,27 @@ async def foo(arg): return await arg # Py 3.5
self.assertEqual(ret, 0)
self.assertEqual(pickle.load(f), {'a': '123x', 'b': '123'})
+ # _testcapi cannot be imported in a subinterpreter on a Free Threaded build
+ @support.requires_gil_enabled()
def test_py_config_isoloated_per_interpreter(self):
# A config change in one interpreter must not leak to out to others.
#
# This test could verify ANY config value, it just happens to have been
# written around the time of int_max_str_digits. Refactoring is okay.
code = """if 1:
- import sys, _testinternalcapi
+ import sys, _testcapi
# Any config value would do, this happens to be the one being
# double checked at the time this test was written.
- config = _testinternalcapi.get_config()
- config['int_max_str_digits'] = 55555
- config['parse_argv'] = 0
- _testinternalcapi.set_config(config)
- sub_value = _testinternalcapi.get_config()['int_max_str_digits']
+ _testcapi.config_set('int_max_str_digits', 55555)
+ sub_value = _testcapi.config_get('int_max_str_digits')
assert sub_value == 55555, sub_value
"""
- before_config = _testinternalcapi.get_config()
- assert before_config['int_max_str_digits'] != 55555
+ before_config = _testcapi.config_get('int_max_str_digits')
+ assert before_config != 55555
self.assertEqual(support.run_in_subinterp(code), 0,
'subinterp code failure, check stderr.')
- after_config = _testinternalcapi.get_config()
+ after_config = _testcapi.config_get('int_max_str_digits')
self.assertIsNot(
before_config, after_config,
"Expected get_config() to return a new dict on each call")
diff --git a/Lib/test/test_embed.py b/Lib/test/test_embed.py
index 6d1b4cce498276..bd01913e49d170 100644
--- a/Lib/test/test_embed.py
+++ b/Lib/test/test_embed.py
@@ -1746,14 +1746,6 @@ def test_init_warnoptions(self):
self.check_all_configs("test_init_warnoptions", config, preconfig,
api=API_PYTHON)
- def test_init_set_config(self):
- config = {
- 'bytes_warning': 2,
- 'warnoptions': ['error::BytesWarning'],
- }
- self.check_all_configs("test_init_set_config", config,
- api=API_ISOLATED)
-
@unittest.skipIf(support.check_bolt_optimized, "segfaults on BOLT instrumented binaries")
def test_initconfig_api(self):
preconfig = {
@@ -1845,22 +1837,6 @@ def test_init_in_background_thread(self):
self.assertEqual(err, "")
-class SetConfigTests(unittest.TestCase):
- def test_set_config(self):
- # bpo-42260: Test _PyInterpreterState_SetConfig()
- import_helper.import_module('_testcapi')
- cmd = [sys.executable, '-X', 'utf8', '-I', '-m', 'test._test_embed_set_config']
- proc = subprocess.run(cmd,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE,
- encoding='utf-8', errors='backslashreplace')
- if proc.returncode and support.verbose:
- print(proc.stdout)
- print(proc.stderr)
- self.assertEqual(proc.returncode, 0,
- (proc.returncode, proc.stdout, proc.stderr))
-
-
class AuditingTests(EmbeddingTestsMixin, unittest.TestCase):
def test_open_code_hook(self):
self.run_embedded_interpreter("test_open_code_hook")
diff --git a/Lib/test/test_regrtest.py b/Lib/test/test_regrtest.py
index ab46ccbf004a3a..5707b355e94337 100644
--- a/Lib/test/test_regrtest.py
+++ b/Lib/test/test_regrtest.py
@@ -2145,25 +2145,25 @@ def check_add_python_opts(self, option):
import unittest
from test import support
try:
- from _testinternalcapi import get_config
+ from _testcapi import config_get
except ImportError:
- get_config = None
+ config_get = None
# WASI/WASM buildbots don't use -E option
use_environment = (support.is_emscripten or support.is_wasi)
class WorkerTests(unittest.TestCase):
- @unittest.skipUnless(get_config is None, 'need get_config()')
+ @unittest.skipUnless(config_get is None, 'need config_get()')
def test_config(self):
- config = get_config()['config']
+ config = config_get()
# -u option
- self.assertEqual(config['buffered_stdio'], 0)
+ self.assertEqual(config_get('buffered_stdio'), 0)
# -W default option
- self.assertTrue(config['warnoptions'], ['default'])
+ self.assertTrue(config_get('warnoptions'), ['default'])
# -bb option
- self.assertTrue(config['bytes_warning'], 2)
+ self.assertTrue(config_get('bytes_warning'), 2)
# -E option
- self.assertTrue(config['use_environment'], use_environment)
+ self.assertTrue(config_get('use_environment'), use_environment)
def test_python_opts(self):
# -u option
diff --git a/Misc/NEWS.d/next/C_API/2025-01-20-10-40-11.gh-issue-129033.d1jltB.rst b/Misc/NEWS.d/next/C_API/2025-01-20-10-40-11.gh-issue-129033.d1jltB.rst
new file mode 100644
index 00000000000000..c0c109d5ce1ca2
--- /dev/null
+++ b/Misc/NEWS.d/next/C_API/2025-01-20-10-40-11.gh-issue-129033.d1jltB.rst
@@ -0,0 +1,4 @@
+Remove ``_PyInterpreterState_GetConfigCopy()`` and
+``_PyInterpreterState_SetConfig()`` private functions. Use instead
+:c:func:`PyConfig_Get` and :c:func:`PyConfig_Set`, public C API added by
+:pep:`741` "Python Configuration C API". Patch by Victor Stinner.
diff --git a/Modules/_testinternalcapi.c b/Modules/_testinternalcapi.c
index 98aea5b596e920..aae09f620b8898 100644
--- a/Modules/_testinternalcapi.c
+++ b/Modules/_testinternalcapi.c
@@ -25,7 +25,6 @@
#include "pycore_hashtable.h" // _Py_hashtable_new()
#include "pycore_initconfig.h" // _Py_GetConfigsAsDict()
#include "pycore_instruction_sequence.h" // _PyInstructionSequence_New()
-#include "pycore_interp.h" // _PyInterpreterState_GetConfigCopy()
#include "pycore_long.h" // _PyLong_Sign()
#include "pycore_object.h" // _PyObject_IsFreed()
#include "pycore_optimizer.h" // _Py_UopsSymbol, etc.
@@ -318,41 +317,6 @@ test_hashtable(PyObject *self, PyObject *Py_UNUSED(args))
}
-static PyObject *
-test_get_config(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(args))
-{
- PyConfig config;
- PyConfig_InitIsolatedConfig(&config);
- if (_PyInterpreterState_GetConfigCopy(&config) < 0) {
- PyConfig_Clear(&config);
- return NULL;
- }
- PyObject *dict = _PyConfig_AsDict(&config);
- PyConfig_Clear(&config);
- return dict;
-}
-
-
-static PyObject *
-test_set_config(PyObject *Py_UNUSED(self), PyObject *dict)
-{
- PyConfig config;
- PyConfig_InitIsolatedConfig(&config);
- if (_PyConfig_FromDict(&config, dict) < 0) {
- goto error;
- }
- if (_PyInterpreterState_SetConfig(&config) < 0) {
- goto error;
- }
- PyConfig_Clear(&config);
- Py_RETURN_NONE;
-
-error:
- PyConfig_Clear(&config);
- return NULL;
-}
-
-
static PyObject *
test_reset_path_config(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(arg))
{
@@ -2062,8 +2026,6 @@ static PyMethodDef module_functions[] = {
{"test_popcount", test_popcount, METH_NOARGS},
{"test_bit_length", test_bit_length, METH_NOARGS},
{"test_hashtable", test_hashtable, METH_NOARGS},
- {"get_config", test_get_config, METH_NOARGS},
- {"set_config", test_set_config, METH_O},
{"reset_path_config", test_reset_path_config, METH_NOARGS},
{"test_edit_cost", test_edit_cost, METH_NOARGS},
{"test_bytes_find", test_bytes_find, METH_NOARGS},
diff --git a/Programs/_testembed.c b/Programs/_testembed.c
index 3681a89376638a..6f6d0cae58010e 100644
--- a/Programs/_testembed.c
+++ b/Programs/_testembed.c
@@ -1791,48 +1791,6 @@ static int test_init_warnoptions(void)
}
-static int tune_config(void)
-{
- PyConfig config;
- PyConfig_InitPythonConfig(&config);
- if (_PyInterpreterState_GetConfigCopy(&config) < 0) {
- PyConfig_Clear(&config);
- PyErr_Print();
- return -1;
- }
-
- config.bytes_warning = 2;
-
- if (_PyInterpreterState_SetConfig(&config) < 0) {
- PyConfig_Clear(&config);
- return -1;
- }
- PyConfig_Clear(&config);
- return 0;
-}
-
-
-static int test_init_set_config(void)
-{
- // Initialize core
- PyConfig config;
- PyConfig_InitIsolatedConfig(&config);
- config_set_string(&config, &config.program_name, PROGRAM_NAME);
- config.bytes_warning = 0;
- init_from_config_clear(&config);
-
- // Tune the configuration using _PyInterpreterState_SetConfig()
- if (tune_config() < 0) {
- PyErr_Print();
- return 1;
- }
-
- dump_config();
- Py_Finalize();
- return 0;
-}
-
-
static int initconfig_getint(PyInitConfig *config, const char *name)
{
int64_t value;
@@ -2445,7 +2403,6 @@ static struct TestCase TestCases[] = {
{"test_init_setpythonhome", test_init_setpythonhome},
{"test_init_is_python_build", test_init_is_python_build},
{"test_init_warnoptions", test_init_warnoptions},
- {"test_init_set_config", test_init_set_config},
{"test_initconfig_api", test_initconfig_api},
{"test_initconfig_get_api", test_initconfig_get_api},
{"test_initconfig_exit", test_initconfig_exit},
diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c
index 8ec12b437f8298..ea8a291a8e5eb4 100644
--- a/Python/pylifecycle.c
+++ b/Python/pylifecycle.c
@@ -444,40 +444,6 @@ interpreter_update_config(PyThreadState *tstate, int only_update_path_config)
}
-int
-_PyInterpreterState_SetConfig(const PyConfig *src_config)
-{
- PyThreadState *tstate = _PyThreadState_GET();
- int res = -1;
-
- PyConfig config;
- PyConfig_InitPythonConfig(&config);
- PyStatus status = _PyConfig_Copy(&config, src_config);
- if (_PyStatus_EXCEPTION(status)) {
- _PyErr_SetFromPyStatus(status);
- goto done;
- }
-
- status = _PyConfig_Read(&config, 1);
- if (_PyStatus_EXCEPTION(status)) {
- _PyErr_SetFromPyStatus(status);
- goto done;
- }
-
- status = _PyConfig_Copy(&tstate->interp->config, &config);
- if (_PyStatus_EXCEPTION(status)) {
- _PyErr_SetFromPyStatus(status);
- goto done;
- }
-
- res = interpreter_update_config(tstate, 0);
-
-done:
- PyConfig_Clear(&config);
- return res;
-}
-
-
/* Global initializations. Can be undone by Py_Finalize(). Don't
call this twice without an intervening Py_Finalize() call.
diff --git a/Python/pystate.c b/Python/pystate.c
index 52703b048d6022..e5003021b83f00 100644
--- a/Python/pystate.c
+++ b/Python/pystate.c
@@ -2880,20 +2880,6 @@ _PyInterpreterState_GetConfig(PyInterpreterState *interp)
}
-int
-_PyInterpreterState_GetConfigCopy(PyConfig *config)
-{
- PyInterpreterState *interp = _PyInterpreterState_GET();
-
- PyStatus status = _PyConfig_Copy(config, &interp->config);
- if (PyStatus_Exception(status)) {
- _PyErr_SetFromPyStatus(status);
- return -1;
- }
- return 0;
-}
-
-
const PyConfig*
_Py_GetConfig(void)
{
1
0
Jan. 20, 2025
https://github.com/python/cpython/commit/573c1815028fa54cc8b581eccc719ab6a1…
commit: 573c1815028fa54cc8b581eccc719ab6a1247ff5
branch: main
author: Victor Stinner <vstinner(a)python.org>
committer: vstinner <vstinner(a)python.org>
date: 2025-01-20T15:46:45+01:00
summary:
Add Configuration Options table to PyInitConfig API doc (#129062)
Document PyConfig members:
* dump_refs_file
* stdlib_dir
* use_frozen_modules
* _pystats
files:
M Doc/c-api/init_config.rst
diff --git a/Doc/c-api/init_config.rst b/Doc/c-api/init_config.rst
index a549d4c55fc43d..b791d3cdc5d95c 100644
--- a/Doc/c-api/init_config.rst
+++ b/Doc/c-api/init_config.rst
@@ -130,8 +130,8 @@ Error Handling
Get Options
-----------
-The configuration option *name* parameter must be a non-NULL
-null-terminated UTF-8 encoded string.
+The configuration option *name* parameter must be a non-NULL null-terminated
+UTF-8 encoded string. See :ref:`Configuration Options <pyinitconfig-opts>`.
.. c:function:: int PyInitConfig_HasOption(PyInitConfig *config, const char *name)
@@ -185,7 +185,7 @@ Set Options
-----------
The configuration option *name* parameter must be a non-NULL null-terminated
-UTF-8 encoded string.
+UTF-8 encoded string. See :ref:`Configuration Options <pyinitconfig-opts>`.
Some configuration options have side effects on other options. This logic is
only implemented when ``Py_InitializeFromInitConfig()`` is called, not by the
@@ -253,6 +253,299 @@ Initialize Python
See ``PyInitConfig_GetExitcode()`` for the exit code case.
+.. _pyinitconfig-opts:
+
+Configuration Options
+=====================
+
+.. list-table::
+ :header-rows: 1
+
+ * - Option
+ - PyConfig/PyPreConfig member
+ - Type
+ - Visibility
+ * - ``"allocator"``
+ - :c:member:`allocator <PyPreConfig.allocator>`
+ - ``int``
+ - Read-only
+ * - ``"argv"``
+ - :c:member:`argv <PyConfig.argv>`
+ - ``list[str]``
+ - Public
+ * - ``"base_exec_prefix"``
+ - :c:member:`base_exec_prefix <PyConfig.base_exec_prefix>`
+ - ``str``
+ - Public
+ * - ``"base_executable"``
+ - :c:member:`base_executable <PyConfig.base_executable>`
+ - ``str``
+ - Public
+ * - ``"base_prefix"``
+ - :c:member:`base_prefix <PyConfig.base_prefix>`
+ - ``str``
+ - Public
+ * - ``"buffered_stdio"``
+ - :c:member:`buffered_stdio <PyConfig.buffered_stdio>`
+ - ``bool``
+ - Read-only
+ * - ``"bytes_warning"``
+ - :c:member:`bytes_warning <PyConfig.bytes_warning>`
+ - ``int``
+ - Public
+ * - ``"check_hash_pycs_mode"``
+ - :c:member:`check_hash_pycs_mode <PyConfig.check_hash_pycs_mode>`
+ - ``str``
+ - Read-only
+ * - ``"code_debug_ranges"``
+ - :c:member:`code_debug_ranges <PyConfig.code_debug_ranges>`
+ - ``bool``
+ - Read-only
+ * - ``"coerce_c_locale"``
+ - :c:member:`coerce_c_locale <PyPreConfig.coerce_c_locale>`
+ - ``bool``
+ - Read-only
+ * - ``"coerce_c_locale_warn"``
+ - :c:member:`coerce_c_locale_warn <PyPreConfig.coerce_c_locale_warn>`
+ - ``bool``
+ - Read-only
+ * - ``"configure_c_stdio"``
+ - :c:member:`configure_c_stdio <PyConfig.configure_c_stdio>`
+ - ``bool``
+ - Read-only
+ * - ``"configure_locale"``
+ - :c:member:`configure_locale <PyPreConfig.configure_locale>`
+ - ``bool``
+ - Read-only
+ * - ``"cpu_count"``
+ - :c:member:`cpu_count <PyConfig.cpu_count>`
+ - ``int``
+ - Read-only
+ * - ``"dev_mode"``
+ - :c:member:`dev_mode <PyConfig.dev_mode>`
+ - ``bool``
+ - Read-only
+ * - ``"dump_refs"``
+ - :c:member:`dump_refs <PyConfig.dump_refs>`
+ - ``bool``
+ - Read-only
+ * - ``"dump_refs_file"``
+ - :c:member:`dump_refs_file <PyConfig.dump_refs_file>`
+ - ``str``
+ - Read-only
+ * - ``"exec_prefix"``
+ - :c:member:`exec_prefix <PyConfig.exec_prefix>`
+ - ``str``
+ - Public
+ * - ``"executable"``
+ - :c:member:`executable <PyConfig.executable>`
+ - ``str``
+ - Public
+ * - ``"faulthandler"``
+ - :c:member:`faulthandler <PyConfig.faulthandler>`
+ - ``bool``
+ - Read-only
+ * - ``"filesystem_encoding"``
+ - :c:member:`filesystem_encoding <PyConfig.filesystem_encoding>`
+ - ``str``
+ - Read-only
+ * - ``"filesystem_errors"``
+ - :c:member:`filesystem_errors <PyConfig.filesystem_errors>`
+ - ``str``
+ - Read-only
+ * - ``"hash_seed"``
+ - :c:member:`hash_seed <PyConfig.hash_seed>`
+ - ``int``
+ - Read-only
+ * - ``"home"``
+ - :c:member:`home <PyConfig.home>`
+ - ``str``
+ - Read-only
+ * - ``"import_time"``
+ - :c:member:`import_time <PyConfig.import_time>`
+ - ``bool``
+ - Read-only
+ * - ``"inspect"``
+ - :c:member:`inspect <PyConfig.inspect>`
+ - ``bool``
+ - Public
+ * - ``"install_signal_handlers"``
+ - :c:member:`install_signal_handlers <PyConfig.install_signal_handlers>`
+ - ``bool``
+ - Read-only
+ * - ``"int_max_str_digits"``
+ - :c:member:`int_max_str_digits <PyConfig.int_max_str_digits>`
+ - ``int``
+ - Public
+ * - ``"interactive"``
+ - :c:member:`interactive <PyConfig.interactive>`
+ - ``bool``
+ - Public
+ * - ``"isolated"``
+ - :c:member:`isolated <PyConfig.isolated>`
+ - ``bool``
+ - Read-only
+ * - ``"legacy_windows_fs_encoding"``
+ - :c:member:`legacy_windows_fs_encoding <PyPreConfig.legacy_windows_fs_encoding>`
+ - ``bool``
+ - Read-only
+ * - ``"legacy_windows_stdio"``
+ - :c:member:`legacy_windows_stdio <PyConfig.legacy_windows_stdio>`
+ - ``bool``
+ - Read-only
+ * - ``"malloc_stats"``
+ - :c:member:`malloc_stats <PyConfig.malloc_stats>`
+ - ``bool``
+ - Read-only
+ * - ``"module_search_paths"``
+ - :c:member:`module_search_paths <PyConfig.module_search_paths>`
+ - ``list[str]``
+ - Public
+ * - ``"optimization_level"``
+ - :c:member:`optimization_level <PyConfig.optimization_level>`
+ - ``int``
+ - Public
+ * - ``"orig_argv"``
+ - :c:member:`orig_argv <PyConfig.orig_argv>`
+ - ``list[str]``
+ - Read-only
+ * - ``"parse_argv"``
+ - :c:member:`parse_argv <PyConfig.parse_argv>`
+ - ``bool``
+ - Read-only
+ * - ``"parser_debug"``
+ - :c:member:`parser_debug <PyConfig.parser_debug>`
+ - ``bool``
+ - Public
+ * - ``"pathconfig_warnings"``
+ - :c:member:`pathconfig_warnings <PyConfig.pathconfig_warnings>`
+ - ``bool``
+ - Read-only
+ * - ``"perf_profiling"``
+ - :c:member:`perf_profiling <PyConfig.perf_profiling>`
+ - ``bool``
+ - Read-only
+ * - ``"platlibdir"``
+ - :c:member:`platlibdir <PyConfig.platlibdir>`
+ - ``str``
+ - Public
+ * - ``"prefix"``
+ - :c:member:`prefix <PyConfig.prefix>`
+ - ``str``
+ - Public
+ * - ``"program_name"``
+ - :c:member:`program_name <PyConfig.program_name>`
+ - ``str``
+ - Read-only
+ * - ``"pycache_prefix"``
+ - :c:member:`pycache_prefix <PyConfig.pycache_prefix>`
+ - ``str``
+ - Public
+ * - ``"quiet"``
+ - :c:member:`quiet <PyConfig.quiet>`
+ - ``bool``
+ - Public
+ * - ``"run_command"``
+ - :c:member:`run_command <PyConfig.run_command>`
+ - ``str``
+ - Read-only
+ * - ``"run_filename"``
+ - :c:member:`run_filename <PyConfig.run_filename>`
+ - ``str``
+ - Read-only
+ * - ``"run_module"``
+ - :c:member:`run_module <PyConfig.run_module>`
+ - ``str``
+ - Read-only
+ * - ``"run_presite"``
+ - :c:member:`run_presite <PyConfig.run_presite>`
+ - ``str``
+ - Read-only
+ * - ``"safe_path"``
+ - :c:member:`safe_path <PyConfig.safe_path>`
+ - ``bool``
+ - Read-only
+ * - ``"show_ref_count"``
+ - :c:member:`show_ref_count <PyConfig.show_ref_count>`
+ - ``bool``
+ - Read-only
+ * - ``"site_import"``
+ - :c:member:`site_import <PyConfig.site_import>`
+ - ``bool``
+ - Read-only
+ * - ``"skip_source_first_line"``
+ - :c:member:`skip_source_first_line <PyConfig.skip_source_first_line>`
+ - ``bool``
+ - Read-only
+ * - ``"stdio_encoding"``
+ - :c:member:`stdio_encoding <PyConfig.stdio_encoding>`
+ - ``str``
+ - Read-only
+ * - ``"stdio_errors"``
+ - :c:member:`stdio_errors <PyConfig.stdio_errors>`
+ - ``str``
+ - Read-only
+ * - ``"stdlib_dir"``
+ - :c:member:`stdlib_dir <PyConfig.stdlib_dir>`
+ - ``str``
+ - Public
+ * - ``"tracemalloc"``
+ - :c:member:`tracemalloc <PyConfig.tracemalloc>`
+ - ``int``
+ - Read-only
+ * - ``"use_environment"``
+ - :c:member:`use_environment <PyConfig.use_environment>`
+ - ``bool``
+ - Public
+ * - ``"use_frozen_modules"``
+ - :c:member:`use_frozen_modules <PyConfig.use_frozen_modules>`
+ - ``bool``
+ - Read-only
+ * - ``"use_hash_seed"``
+ - :c:member:`use_hash_seed <PyConfig.use_hash_seed>`
+ - ``bool``
+ - Read-only
+ * - ``"user_site_directory"``
+ - :c:member:`user_site_directory <PyConfig.user_site_directory>`
+ - ``bool``
+ - Read-only
+ * - ``"utf8_mode"``
+ - :c:member:`utf8_mode <PyPreConfig.utf8_mode>`
+ - ``bool``
+ - Read-only
+ * - ``"verbose"``
+ - :c:member:`verbose <PyConfig.verbose>`
+ - ``int``
+ - Public
+ * - ``"warn_default_encoding"``
+ - :c:member:`warn_default_encoding <PyConfig.warn_default_encoding>`
+ - ``bool``
+ - Read-only
+ * - ``"warnoptions"``
+ - :c:member:`warnoptions <PyConfig.warnoptions>`
+ - ``list[str]``
+ - Public
+ * - ``"write_bytecode"``
+ - :c:member:`write_bytecode <PyConfig.write_bytecode>`
+ - ``bool``
+ - Public
+ * - ``"xoptions"``
+ - :c:member:`xoptions <PyConfig.xoptions>`
+ - ``dict[str, str]``
+ - Public
+ * - ``"_pystats"``
+ - :c:member:`_pystats <PyConfig._pystats>`
+ - ``bool``
+ - Read-only
+
+Visibility:
+
+* Public: Can by get by :c:func:`PyConfig_Get` and set by
+ :c:func:`PyConfig_Set`.
+* Read-only: Can by get by :c:func:`PyConfig_Get`, but cannot be set by
+ :c:func:`PyConfig_Set`.
+
+
Runtime Python configuration API
================================
@@ -260,7 +553,7 @@ At runtime, it's possible to get and set configuration options using
:c:func:`PyConfig_Get` and :c:func:`PyConfig_Set` functions.
The configuration option *name* parameter must be a non-NULL null-terminated
-UTF-8 encoded string.
+UTF-8 encoded string. See :ref:`Configuration Options <pyinitconfig-opts>`.
Some options are read from the :mod:`sys` attributes. For example, the option
``"argv"`` is read from :data:`sys.argv`.
@@ -1055,6 +1348,16 @@ PyConfig
Default: ``0``.
+ .. c:member:: wchar_t* dump_refs_file
+
+ Filename where to dump Python references.
+
+ Set by the :envvar:`PYTHONDUMPREFSFILE` environment variable.
+
+ Default: ``NULL``.
+
+ .. versionadded:: 3.11
+
.. c:member:: wchar_t* exec_prefix
The site-specific directory prefix where the platform-dependent Python
@@ -1133,6 +1436,15 @@ PyConfig
See also the :c:member:`~PyConfig.filesystem_encoding` member.
+ .. c:member:: int use_frozen_modules
+
+ If non-zero, use frozen modules.
+
+ Set by the :envvar:`PYTHON_FROZEN_MODULES` environment variable.
+
+ Default: ``1`` in a release build, or ``0`` in a :ref:`debug build
+ <debug-build>`.
+
.. c:member:: unsigned long hash_seed
.. c:member:: int use_hash_seed
@@ -1589,6 +1901,14 @@ PyConfig
.. versionadded:: 3.12
+ .. c:member:: wchar_t* stdlib_dir
+
+ Directory of the Python standard library.
+
+ Default: ``NULL``.
+
+ .. versionadded:: 3.11
+
.. c:member:: int use_environment
Use :ref:`environment variables <using-on-envvars>`?
@@ -1675,6 +1995,15 @@ PyConfig
Default: empty list.
+ .. c:member:: int _pystats
+
+ If non-zero, write performance statistics at Python exit.
+
+ Need a special build with the ``Py_STATS`` macro:
+ see :option:`--enable-pystats`.
+
+ Default: ``0``.
+
If :c:member:`~PyConfig.parse_argv` is non-zero, :c:member:`~PyConfig.argv`
arguments are parsed the same way the regular Python parses :ref:`command line
arguments <using-on-cmdline>`, and Python arguments are stripped from
1
0
[3.13] gh-128978: Fix a `NameError` in `sysconfig.expand_makefile_vars` (GH-128979) (#129065)
by picnixz Jan. 20, 2025
by picnixz Jan. 20, 2025
Jan. 20, 2025
https://github.com/python/cpython/commit/55d3d8165c0aa522d90fe92b92ade74beb…
commit: 55d3d8165c0aa522d90fe92b92ade74beb27d9f9
branch: 3.13
author: Miss Islington (bot) <31488909+miss-islington(a)users.noreply.github.com>
committer: picnixz <10796600+picnixz(a)users.noreply.github.com>
date: 2025-01-20T13:54:48Z
summary:
[3.13] gh-128978: Fix a `NameError` in `sysconfig.expand_makefile_vars` (GH-128979) (#129065)
gh-128978: Fix a `NameError` in `sysconfig.expand_makefile_vars` (GH-128979)
This fixes a regression introduced by 4a53a397c311567f05553bc25a28aebaba4f6f65.
(cherry picked from commit df66ff14b49f4388625212f6bc86b754cb51d4eb)
Co-authored-by: Bénédikt Tran <10796600+picnixz(a)users.noreply.github.com>
files:
A Misc/NEWS.d/next/Library/2025-01-18-11-04-44.gh-issue-128978.hwg7-w.rst
M Lib/sysconfig/__init__.py
diff --git a/Lib/sysconfig/__init__.py b/Lib/sysconfig/__init__.py
index ec3b638f00766d..43eda00ea92c6e 100644
--- a/Lib/sysconfig/__init__.py
+++ b/Lib/sysconfig/__init__.py
@@ -695,6 +695,9 @@ def expand_makefile_vars(s, vars):
"""
import re
+ _findvar1_rx = r"\$\(([A-Za-z][A-Za-z0-9_]*)\)"
+ _findvar2_rx = r"\${([A-Za-z][A-Za-z0-9_]*)}"
+
# This algorithm does multiple expansion, so if vars['foo'] contains
# "${bar}", it will expand ${foo} to ${bar}, and then expand
# ${bar}... and so forth. This is fine as long as 'vars' comes from
diff --git a/Misc/NEWS.d/next/Library/2025-01-18-11-04-44.gh-issue-128978.hwg7-w.rst b/Misc/NEWS.d/next/Library/2025-01-18-11-04-44.gh-issue-128978.hwg7-w.rst
new file mode 100644
index 00000000000000..521496d6a2f8c2
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2025-01-18-11-04-44.gh-issue-128978.hwg7-w.rst
@@ -0,0 +1,2 @@
+Fix a :exc:`NameError` in :func:`!sysconfig.expand_makefile_vars`. Patch by
+Bénédikt Tran.
1
0
Jan. 20, 2025
https://github.com/python/cpython/commit/38c3cf6320bfc15e6a69f73724a49df528…
commit: 38c3cf6320bfc15e6a69f73724a49df5280d8269
branch: main
author: Serhiy Storchaka <storchaka(a)gmail.com>
committer: serhiy-storchaka <storchaka(a)gmail.com>
date: 2025-01-20T13:30:00Z
summary:
gh-71339: Use new assertion methods in test_ctypes (GH-129054)
files:
M Lib/test/test_ctypes/test_c_simple_type_meta.py
M Lib/test/test_ctypes/test_loading.py
M Lib/test/test_ctypes/test_repr.py
diff --git a/Lib/test/test_ctypes/test_c_simple_type_meta.py b/Lib/test/test_ctypes/test_c_simple_type_meta.py
index eb77d6d7782478..e8f347a0d0c57b 100644
--- a/Lib/test/test_ctypes/test_c_simple_type_meta.py
+++ b/Lib/test/test_ctypes/test_c_simple_type_meta.py
@@ -54,9 +54,9 @@ class Sub2(Sub):
pass
self.assertIsInstance(POINTER(Sub2), p_meta)
- self.assertTrue(issubclass(POINTER(Sub2), Sub2))
- self.assertTrue(issubclass(POINTER(Sub2), POINTER(Sub)))
- self.assertTrue(issubclass(POINTER(Sub), POINTER(CtBase)))
+ self.assertIsSubclass(POINTER(Sub2), Sub2)
+ self.assertIsSubclass(POINTER(Sub2), POINTER(Sub))
+ self.assertIsSubclass(POINTER(Sub), POINTER(CtBase))
def test_creating_pointer_in_dunder_new_2(self):
# A simpler variant of the above, used in `CoClass` of the `comtypes`
@@ -84,7 +84,7 @@ class Sub(CtBase):
pass
self.assertIsInstance(POINTER(Sub), p_meta)
- self.assertTrue(issubclass(POINTER(Sub), Sub))
+ self.assertIsSubclass(POINTER(Sub), Sub)
def test_creating_pointer_in_dunder_init_1(self):
class ct_meta(type):
@@ -120,9 +120,9 @@ class Sub2(Sub):
pass
self.assertIsInstance(POINTER(Sub2), p_meta)
- self.assertTrue(issubclass(POINTER(Sub2), Sub2))
- self.assertTrue(issubclass(POINTER(Sub2), POINTER(Sub)))
- self.assertTrue(issubclass(POINTER(Sub), POINTER(CtBase)))
+ self.assertIsSubclass(POINTER(Sub2), Sub2)
+ self.assertIsSubclass(POINTER(Sub2), POINTER(Sub))
+ self.assertIsSubclass(POINTER(Sub), POINTER(CtBase))
def test_creating_pointer_in_dunder_init_2(self):
class ct_meta(type):
@@ -149,4 +149,4 @@ class Sub(CtBase):
pass
self.assertIsInstance(POINTER(Sub), p_meta)
- self.assertTrue(issubclass(POINTER(Sub), Sub))
+ self.assertIsSubclass(POINTER(Sub), Sub)
diff --git a/Lib/test/test_ctypes/test_loading.py b/Lib/test/test_ctypes/test_loading.py
index fc1eecb77e17e3..13ed813ad98c31 100644
--- a/Lib/test/test_ctypes/test_loading.py
+++ b/Lib/test/test_ctypes/test_loading.py
@@ -135,7 +135,7 @@ def test_1703286_B(self):
'test specific to Windows')
def test_load_hasattr(self):
# bpo-34816: shouldn't raise OSError
- self.assertFalse(hasattr(ctypes.windll, 'test'))
+ self.assertNotHasAttr(ctypes.windll, 'test')
@unittest.skipUnless(os.name == "nt",
'test specific to Windows')
diff --git a/Lib/test/test_ctypes/test_repr.py b/Lib/test/test_ctypes/test_repr.py
index e7587984a92c45..8c85e6cbe70cea 100644
--- a/Lib/test/test_ctypes/test_repr.py
+++ b/Lib/test/test_ctypes/test_repr.py
@@ -22,12 +22,12 @@ class ReprTest(unittest.TestCase):
def test_numbers(self):
for typ in subclasses:
base = typ.__bases__[0]
- self.assertTrue(repr(base(42)).startswith(base.__name__))
- self.assertEqual("<X object at", repr(typ(42))[:12])
+ self.assertStartsWith(repr(base(42)), base.__name__)
+ self.assertStartsWith(repr(typ(42)), "<X object at")
def test_char(self):
self.assertEqual("c_char(b'x')", repr(c_char(b'x')))
- self.assertEqual("<X object at", repr(X(b'x'))[:12])
+ self.assertStartsWith(repr(X(b'x')), "<X object at")
if __name__ == "__main__":
1
0
Jan. 20, 2025
https://github.com/python/cpython/commit/df66ff14b49f4388625212f6bc86b754cb…
commit: df66ff14b49f4388625212f6bc86b754cb51d4eb
branch: main
author: Bénédikt Tran <10796600+picnixz(a)users.noreply.github.com>
committer: picnixz <10796600+picnixz(a)users.noreply.github.com>
date: 2025-01-20T13:27:14Z
summary:
gh-128978: Fix a `NameError` in `sysconfig.expand_makefile_vars` (#128979)
This fixes a regression introduced by 4a53a397c311567f05553bc25a28aebaba4f6f65.
files:
A Misc/NEWS.d/next/Library/2025-01-18-11-04-44.gh-issue-128978.hwg7-w.rst
M Lib/sysconfig/__init__.py
diff --git a/Lib/sysconfig/__init__.py b/Lib/sysconfig/__init__.py
index 7a4a8f65a5eb3e..ec9bb705925cdb 100644
--- a/Lib/sysconfig/__init__.py
+++ b/Lib/sysconfig/__init__.py
@@ -718,6 +718,9 @@ def expand_makefile_vars(s, vars):
"""
import re
+ _findvar1_rx = r"\$\(([A-Za-z][A-Za-z0-9_]*)\)"
+ _findvar2_rx = r"\${([A-Za-z][A-Za-z0-9_]*)}"
+
# This algorithm does multiple expansion, so if vars['foo'] contains
# "${bar}", it will expand ${foo} to ${bar}, and then expand
# ${bar}... and so forth. This is fine as long as 'vars' comes from
diff --git a/Misc/NEWS.d/next/Library/2025-01-18-11-04-44.gh-issue-128978.hwg7-w.rst b/Misc/NEWS.d/next/Library/2025-01-18-11-04-44.gh-issue-128978.hwg7-w.rst
new file mode 100644
index 00000000000000..521496d6a2f8c2
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2025-01-18-11-04-44.gh-issue-128978.hwg7-w.rst
@@ -0,0 +1,2 @@
+Fix a :exc:`NameError` in :func:`!sysconfig.expand_makefile_vars`. Patch by
+Bénédikt Tran.
1
0
Jan. 20, 2025
https://github.com/python/cpython/commit/59fcae793f94be977c56c1f3c2988bd93d…
commit: 59fcae793f94be977c56c1f3c2988bd93d6b1564
branch: main
author: Bénédikt Tran <10796600+picnixz(a)users.noreply.github.com>
committer: picnixz <10796600+picnixz(a)users.noreply.github.com>
date: 2025-01-20T13:50:10+01:00
summary:
Remove duplicated dict keys in `test_{embed,long}.py` fixtures (#128727)
files:
M Lib/test/test_embed.py
M Lib/test/test_long.py
diff --git a/Lib/test/test_embed.py b/Lib/test/test_embed.py
index a2400aa96c3ddd..6d1b4cce498276 100644
--- a/Lib/test/test_embed.py
+++ b/Lib/test/test_embed.py
@@ -1049,7 +1049,6 @@ def test_init_compat_env(self):
'use_hash_seed': True,
'hash_seed': 42,
'tracemalloc': 2,
- 'perf_profiling': 0,
'import_time': True,
'code_debug_ranges': False,
'malloc_stats': True,
@@ -1086,7 +1085,6 @@ def test_init_python_env(self):
'use_hash_seed': True,
'hash_seed': 42,
'tracemalloc': 2,
- 'perf_profiling': 0,
'import_time': True,
'code_debug_ranges': False,
'malloc_stats': True,
diff --git a/Lib/test/test_long.py b/Lib/test/test_long.py
index 19978118c80dba..f336d49fa4f008 100644
--- a/Lib/test/test_long.py
+++ b/Lib/test/test_long.py
@@ -1470,7 +1470,6 @@ def equivalent_python(byte_array, byteorder, signed=False):
b'\x00': 0,
b'\x00\x00': 0,
b'\x01': 1,
- b'\x00\x01': 256,
b'\xff': -1,
b'\xff\xff': -1,
b'\x81': -127,
1
0