[Python-checkins] gh-121459: Deferred LOAD_GLOBAL (GH-123128)

2024-09-13 Thread Fidget-Spinner
https://github.com/python/cpython/commit/8810e286fa48876422d1b230208911decbead294
commit: 8810e286fa48876422d1b230208911decbead294
branch: main
author: Ken Jin 
committer: Fidget-Spinner 
date: 2024-09-14T00:23:51+08:00
summary:

gh-121459: Deferred LOAD_GLOBAL (GH-123128)

Co-authored-by: Bénédikt Tran <10796600+picn...@users.noreply.github.com>
Co-authored-by: Sam Gross <655866+colesb...@users.noreply.github.com>

files:
M Include/internal/pycore_ceval.h
M Include/internal/pycore_dict.h
M Objects/dictobject.c
M Python/bytecodes.c
M Python/ceval.c
M Python/executor_cases.c.h
M Python/generated_cases.c.h
M Python/optimizer_cases.c.h

diff --git a/Include/internal/pycore_ceval.h b/Include/internal/pycore_ceval.h
index e4af731be0e87f..a97b53028c8f59 100644
--- a/Include/internal/pycore_ceval.h
+++ b/Include/internal/pycore_ceval.h
@@ -271,7 +271,7 @@ PyAPI_FUNC(PyObject **) 
_PyObjectArray_FromStackRefArray(_PyStackRef *input, Py_
 PyAPI_FUNC(void) _PyObjectArray_Free(PyObject **array, PyObject **scratch);
 
 PyAPI_FUNC(PyObject *) _PyEval_GetANext(PyObject *aiter);
-PyAPI_FUNC(PyObject *) _PyEval_LoadGlobal(PyObject *globals, PyObject 
*builtins, PyObject *name);
+PyAPI_FUNC(void) _PyEval_LoadGlobalStackRef(PyObject *globals, PyObject 
*builtins, PyObject *name, _PyStackRef *writeto);
 PyAPI_FUNC(PyObject *) _PyEval_GetAwaitable(PyObject *iterable, int oparg);
 PyAPI_FUNC(PyObject *) _PyEval_LoadName(PyThreadState *tstate, 
_PyInterpreterFrame *frame, PyObject *name);
 
diff --git a/Include/internal/pycore_dict.h b/Include/internal/pycore_dict.h
index 100250928d2064..f9a043b0208c8f 100644
--- a/Include/internal/pycore_dict.h
+++ b/Include/internal/pycore_dict.h
@@ -10,6 +10,7 @@ extern "C" {
 
 #include "pycore_object.h"   // PyManagedDictPointer
 #include "pycore_pyatomic_ft_wrappers.h" // FT_ATOMIC_LOAD_SSIZE_ACQUIRE
+#include "pycore_stackref.h" // _PyStackRef
 
 // Unsafe flavor of PyDict_GetItemWithError(): no error checking
 extern PyObject* _PyDict_GetItemWithError(PyObject *dp, PyObject *key);
@@ -100,10 +101,12 @@ extern void _PyDictKeys_DecRef(PyDictKeysObject *keys);
  */
 extern Py_ssize_t _Py_dict_lookup(PyDictObject *mp, PyObject *key, Py_hash_t 
hash, PyObject **value_addr);
 extern Py_ssize_t _Py_dict_lookup_threadsafe(PyDictObject *mp, PyObject *key, 
Py_hash_t hash, PyObject **value_addr);
+extern Py_ssize_t _Py_dict_lookup_threadsafe_stackref(PyDictObject *mp, 
PyObject *key, Py_hash_t hash, _PyStackRef *value_addr);
 
 extern Py_ssize_t _PyDict_LookupIndex(PyDictObject *, PyObject *);
 extern Py_ssize_t _PyDictKeys_StringLookup(PyDictKeysObject* dictkeys, 
PyObject *key);
 PyAPI_FUNC(PyObject *)_PyDict_LoadGlobal(PyDictObject *, PyDictObject *, 
PyObject *);
+PyAPI_FUNC(void) _PyDict_LoadGlobalStackRef(PyDictObject *, PyDictObject *, 
PyObject *, _PyStackRef *);
 
 /* Consumes references to key and value */
 PyAPI_FUNC(int) _PyDict_SetItem_Take2(PyDictObject *op, PyObject *key, 
PyObject *value);
diff --git a/Objects/dictobject.c b/Objects/dictobject.c
index b81ed189456ec1..006bc593c2a754 100644
--- a/Objects/dictobject.c
+++ b/Objects/dictobject.c
@@ -1496,6 +1496,45 @@ _Py_dict_lookup_threadsafe(PyDictObject *mp, PyObject 
*key, Py_hash_t hash, PyOb
 return ix;
 }
 
+Py_ssize_t
+_Py_dict_lookup_threadsafe_stackref(PyDictObject *mp, PyObject *key, Py_hash_t 
hash, _PyStackRef *value_addr)
+{
+PyDictKeysObject *dk = _Py_atomic_load_ptr(&mp->ma_keys);
+if (dk->dk_kind == DICT_KEYS_UNICODE && PyUnicode_CheckExact(key)) {
+Py_ssize_t ix = unicodekeys_lookup_unicode_threadsafe(dk, key, hash);
+if (ix == DKIX_EMPTY) {
+*value_addr = PyStackRef_NULL;
+return ix;
+}
+else if (ix >= 0) {
+PyObject **addr_of_value = &DK_UNICODE_ENTRIES(dk)[ix].me_value;
+PyObject *value = _Py_atomic_load_ptr(addr_of_value);
+if (value == NULL) {
+*value_addr = PyStackRef_NULL;
+return DKIX_EMPTY;
+}
+if (_Py_IsImmortal(value) || _PyObject_HasDeferredRefcount(value)) 
{
+*value_addr =  (_PyStackRef){ .bits = (uintptr_t)value | 
Py_TAG_DEFERRED };
+return ix;
+}
+if (_Py_TryIncrefCompare(addr_of_value, value)) {
+*value_addr = PyStackRef_FromPyObjectSteal(value);
+return ix;
+}
+}
+}
+
+PyObject *obj;
+Py_ssize_t ix = _Py_dict_lookup_threadsafe(mp, key, hash, &obj);
+if (ix >= 0 && obj != NULL) {
+*value_addr = PyStackRef_FromPyObjectSteal(obj);
+}
+else {
+*value_addr = PyStackRef_NULL;
+}
+return ix;
+}
+
 #else   // Py_GIL_DISABLED
 
 Py_ssize_t
@@ -1506,6 +1545,15 @@ _Py_dict_lookup_threadsafe(PyDictObject *mp, PyObject 
*key, Py_hash_t hash, PyOb
 return ix;
 }
 
+Py_ssize_t
+_Py_d

[Python-checkins] gh-119258: Eliminate Type Guards in Tier 2 Optimizer with Watcher (GH-119365)

2024-06-08 Thread Fidget-Spinner
https://github.com/python/cpython/commit/55402d3232ca400ebafe4fe3bd70f252304ebe07
commit: 55402d3232ca400ebafe4fe3bd70f252304ebe07
branch: main
author: Saul Shanabrook 
committer: Fidget-Spinner 
date: 2024-06-08T17:41:45+08:00
summary:

gh-119258: Eliminate Type Guards in Tier 2 Optimizer with Watcher (GH-119365)

Co-authored-by: parmeggiani 
Co-authored-by: dpdani 
Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com>
Co-authored-by: Brandt Bucher 
Co-authored-by: Ken Jin 

files:
A Misc/NEWS.d/next/Core and 
Builtins/2024-05-23-20-17-37.gh-issue-119258.wZFIpt.rst
M Include/internal/pycore_optimizer.h
M Include/internal/pycore_typeobject.h
M Lib/test/test_capi/test_opt.py
M Lib/test/test_capi/test_watchers.py
M Lib/test/test_type_cache.py
M Modules/_testcapimodule.c
M Modules/_testinternalcapi.c
M Objects/typeobject.c
M Python/optimizer_analysis.c
M Python/optimizer_bytecodes.c
M Python/optimizer_cases.c.h
M Python/optimizer_symbols.c

diff --git a/Include/internal/pycore_optimizer.h 
b/Include/internal/pycore_optimizer.h
index 76123987ac99f5..fd7833fd231299 100644
--- a/Include/internal/pycore_optimizer.h
+++ b/Include/internal/pycore_optimizer.h
@@ -33,6 +33,7 @@ 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
@@ -123,9 +124,11 @@ extern _Py_UopsSymbol 
*_Py_uop_sym_new_const(_Py_UOpsContext *ctx, PyObject *con
 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);
@@ -138,9 +141,9 @@ extern void _Py_uop_abstractcontext_fini(_Py_UOpsContext 
*ctx);
 extern _Py_UOpsAbstractFrame *_Py_uop_frame_new(
 _Py_UOpsContext *ctx,
 PyCodeObject *co,
-_Py_UopsSymbol **localsplus_start,
-int n_locals_already_filled,
-int curr_stackentries);
+int curr_stackentries,
+_Py_UopsSymbol **args,
+int arg_len);
 extern int _Py_uop_frame_pop(_Py_UOpsContext *ctx);
 
 PyAPI_FUNC(PyObject *) _Py_uop_symbols_test(PyObject *self, PyObject *ignored);
diff --git a/Include/internal/pycore_typeobject.h 
b/Include/internal/pycore_typeobject.h
index 8664ae0e44533f..bc295b1b066bd1 100644
--- a/Include/internal/pycore_typeobject.h
+++ b/Include/internal/pycore_typeobject.h
@@ -63,6 +63,8 @@ typedef struct {
 PyObject *tp_weaklist;
 } managed_static_type_state;
 
+#define TYPE_VERSION_CACHE_SIZE (1<<12)  /* Must be a power of 2 */
+
 struct types_state {
 /* Used to set PyTypeObject.tp_version_tag.
It starts at _Py_MAX_GLOBAL_TYPE_VERSION_TAG + 1,
@@ -118,6 +120,12 @@ struct types_state {
 managed_static_type_state 
initialized[_Py_MAX_MANAGED_STATIC_EXT_TYPES];
 } for_extensions;
 PyMutex mutex;
+
+// Borrowed references to type objects whose
+// tp_version_tag % TYPE_VERSION_CACHE_SIZE
+// once was equal to the index in the table.
+// They are cleared when the type object is deallocated.
+PyTypeObject *type_version_cache[TYPE_VERSION_CACHE_SIZE];
 };
 
 
@@ -230,6 +238,9 @@ extern void _PyType_SetFlags(PyTypeObject *self, unsigned 
long mask,
 extern void _PyType_SetFlagsRecursive(PyTypeObject *self, unsigned long mask,
   unsigned long flags);
 
+extern unsigned int _PyType_GetVersionForCurrentState(PyTypeObject *tp);
+PyAPI_FUNC(void) _PyType_SetVersion(PyTypeObject *tp, unsigned int version);
+PyTypeObject *_PyType_LookupByVersion(unsigned int version);
 
 #ifdef __cplusplus
 }
diff --git a/Lib/test/test_capi/test_opt.py b/Lib/test/test_capi/test_opt.py
index 0491ff9b84d486..fc6d8b0a3f01d2 100644
--- a/Lib/test/test_capi/test_opt.py
+++ b/Lib/test/test_capi/test_opt.py
@@ -1333,6 +1333,153 @@ def test_modified_local_is_seen_by_optimized_code(self):
 self.assertIs(type(s), float)
 self.assertEqual(s, 1024.0)
 
+def test_guard_type_version_removed(self):
+def thing(a):
+x = 0
+for _ in range(100):
+x += a.attr
+x += a.attr
+return x
+
+ 

[Python-checkins] gh-117657: Make Py_TYPE and Py_SET_TYPE thread safe (GH-120165)

2024-06-12 Thread Fidget-Spinner
https://github.com/python/cpython/commit/e16aed63f64b18a26859eff3de976ded373e66b8
commit: e16aed63f64b18a26859eff3de976ded373e66b8
branch: main
author: Ken Jin 
committer: Fidget-Spinner 
date: 2024-06-12T20:41:07+08:00
summary:

gh-117657: Make Py_TYPE and Py_SET_TYPE thread safe (GH-120165)

Co-authored-by: Bénédikt Tran <10796600+picn...@users.noreply.github.com>
Co-authored-by: Nadeshiko Manju 

files:
M Include/internal/pycore_interp.h
M Include/object.h
M Lib/test/test_free_threading/test_type.py
M Objects/typeobject.c
M Tools/tsan/suppressions_free_threading.txt

diff --git a/Include/internal/pycore_interp.h b/Include/internal/pycore_interp.h
index 86dada5061e7b5..6b5f50b88f7b85 100644
--- a/Include/internal/pycore_interp.h
+++ b/Include/internal/pycore_interp.h
@@ -401,7 +401,10 @@ PyAPI_FUNC(PyStatus) _PyInterpreterState_New(
 #define RARE_EVENT_INTERP_INC(interp, name) \
 do { \
 /* saturating add */ \
-if (interp->rare_events.name < UINT8_MAX) interp->rare_events.name++; \
+int val = FT_ATOMIC_LOAD_UINT8_RELAXED(interp->rare_events.name); \
+if (val < UINT8_MAX) { \
+FT_ATOMIC_STORE_UINT8(interp->rare_events.name, val + 1); \
+} \
 RARE_EVENT_STAT_INC(name); \
 } while (0); \
 
diff --git a/Include/object.h b/Include/object.h
index c8c63b9b2b1450..4a39ada8c7daa4 100644
--- a/Include/object.h
+++ b/Include/object.h
@@ -246,7 +246,11 @@ _Py_IsOwnedByCurrentThread(PyObject *ob)
 
 // bpo-39573: The Py_SET_TYPE() function must be used to set an object type.
 static inline PyTypeObject* Py_TYPE(PyObject *ob) {
+#ifdef Py_GIL_DISABLED
+return (PyTypeObject *)_Py_atomic_load_ptr_relaxed(&ob->ob_type);
+#else
 return ob->ob_type;
+#endif
 }
 #if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b
 #  define Py_TYPE(ob) Py_TYPE(_PyObject_CAST(ob))
@@ -274,7 +278,11 @@ static inline int Py_IS_TYPE(PyObject *ob, PyTypeObject 
*type) {
 
 
 static inline void Py_SET_TYPE(PyObject *ob, PyTypeObject *type) {
+#ifdef Py_GIL_DISABLED
+_Py_atomic_store_ptr(&ob->ob_type, type);
+#else
 ob->ob_type = type;
+#endif
 }
 #if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b
 #  define Py_SET_TYPE(ob, type) Py_SET_TYPE(_PyObject_CAST(ob), type)
diff --git a/Lib/test/test_free_threading/test_type.py 
b/Lib/test/test_free_threading/test_type.py
index 786336fa0cddce..1e84b2db2d4882 100644
--- a/Lib/test/test_free_threading/test_type.py
+++ b/Lib/test/test_free_threading/test_type.py
@@ -96,6 +96,32 @@ def reader_func():
 
 self.run_one(writer_func, reader_func)
 
+def test___class___modification(self):
+class Foo:
+pass
+
+class Bar:
+pass
+
+thing = Foo()
+def work():
+foo = thing
+for _ in range(1):
+foo.__class__ = Bar
+type(foo)
+foo.__class__ = Foo
+type(foo)
+
+
+threads = []
+for i in range(NTHREADS):
+thread = threading.Thread(target=work)
+thread.start()
+threads.append(thread)
+
+for thread in threads:
+thread.join()
+
 def run_one(self, writer_func, reader_func):
 writer = Thread(target=writer_func)
 readers = []
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index 070e3d2f7bf2b4..8ecab555454cdc 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -6633,9 +6633,15 @@ object_set_class(PyObject *self, PyObject *value, void 
*closure)
 if (newto->tp_flags & Py_TPFLAGS_HEAPTYPE) {
 Py_INCREF(newto);
 }
+Py_BEGIN_CRITICAL_SECTION(self);
+// The real Py_TYPE(self) (`oldto`) may have changed from
+// underneath us in another thread, so we re-fetch it here.
+oldto = Py_TYPE(self);
 Py_SET_TYPE(self, newto);
-if (oldto->tp_flags & Py_TPFLAGS_HEAPTYPE)
+Py_END_CRITICAL_SECTION();
+if (oldto->tp_flags & Py_TPFLAGS_HEAPTYPE) {
 Py_DECREF(oldto);
+}
 
 RARE_EVENT_INC(set_class);
 return 0;
diff --git a/Tools/tsan/suppressions_free_threading.txt 
b/Tools/tsan/suppressions_free_threading.txt
index cb48a30751ac7b..b10b297f50da81 100644
--- a/Tools/tsan/suppressions_free_threading.txt
+++ b/Tools/tsan/suppressions_free_threading.txt
@@ -37,7 +37,6 @@ race_top:set_contains_key
 # https://gist.github.com/colesbury/d13d033f413b4ad07929d044bed86c35
 race_top:set_discard_entry
 race_top:set_inheritable
-race_top:Py_SET_TYPE
 race_top:_PyDict_CheckConsistency
 race_top:_Py_dict_lookup_threadsafe
 race_top:_multiprocessing_SemLock_acquire_impl
@@ -58,7 +57,6 @@ race_top:_PyFrame_Initialize
 race_top:PyInterpreterState_ThreadHead
 race_top:_PyObject_TryGetInstanceAttribute
 race_top:PyThreadState_Next
-race_top:Py_TYPE
 race_top:PyUnstable_Inter

[Python-checkins] [3.13] gh-117657: Make Py_TYPE and Py_SET_TYPE thread safe (GH-120165) (GH-120403)

2024-06-12 Thread Fidget-Spinner
https://github.com/python/cpython/commit/91cd22a36119c83c9a21bfe0efe39d745086
commit: 91cd22a36119c83c9a21bfe0efe39d745086
branch: 3.13
author: Miss Islington (bot) <31488909+miss-isling...@users.noreply.github.com>
committer: Fidget-Spinner 
date: 2024-06-12T21:37:26+08:00
summary:

[3.13] gh-117657: Make Py_TYPE and Py_SET_TYPE thread safe (GH-120165) 
(GH-120403)

gh-117657: Make Py_TYPE and Py_SET_TYPE thread safe (GH-120165)
(cherry picked from commit e16aed63f64b18a26859eff3de976ded373e66b8)

Co-authored-by: Ken Jin 
Co-authored-by: Bénédikt Tran <10796600+picn...@users.noreply.github.com>
Co-authored-by: Nadeshiko Manju 

files:
M Include/internal/pycore_interp.h
M Include/object.h
M Lib/test/test_free_threading/test_type.py
M Objects/typeobject.c
M Tools/tsan/suppressions_free_threading.txt

diff --git a/Include/internal/pycore_interp.h b/Include/internal/pycore_interp.h
index 86dada5061e7b5..6b5f50b88f7b85 100644
--- a/Include/internal/pycore_interp.h
+++ b/Include/internal/pycore_interp.h
@@ -401,7 +401,10 @@ PyAPI_FUNC(PyStatus) _PyInterpreterState_New(
 #define RARE_EVENT_INTERP_INC(interp, name) \
 do { \
 /* saturating add */ \
-if (interp->rare_events.name < UINT8_MAX) interp->rare_events.name++; \
+int val = FT_ATOMIC_LOAD_UINT8_RELAXED(interp->rare_events.name); \
+if (val < UINT8_MAX) { \
+FT_ATOMIC_STORE_UINT8(interp->rare_events.name, val + 1); \
+} \
 RARE_EVENT_STAT_INC(name); \
 } while (0); \
 
diff --git a/Include/object.h b/Include/object.h
index 9132784628a501..a687bf2f7cdd74 100644
--- a/Include/object.h
+++ b/Include/object.h
@@ -331,7 +331,11 @@ static inline Py_ssize_t Py_REFCNT(PyObject *ob) {
 
 // bpo-39573: The Py_SET_TYPE() function must be used to set an object type.
 static inline PyTypeObject* Py_TYPE(PyObject *ob) {
+#ifdef Py_GIL_DISABLED
+return (PyTypeObject *)_Py_atomic_load_ptr_relaxed(&ob->ob_type);
+#else
 return ob->ob_type;
+#endif
 }
 #if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b
 #  define Py_TYPE(ob) Py_TYPE(_PyObject_CAST(ob))
@@ -421,7 +425,11 @@ static inline void Py_SET_REFCNT(PyObject *ob, Py_ssize_t 
refcnt) {
 
 
 static inline void Py_SET_TYPE(PyObject *ob, PyTypeObject *type) {
+#ifdef Py_GIL_DISABLED
+_Py_atomic_store_ptr(&ob->ob_type, type);
+#else
 ob->ob_type = type;
+#endif
 }
 #if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b
 #  define Py_SET_TYPE(ob, type) Py_SET_TYPE(_PyObject_CAST(ob), type)
diff --git a/Lib/test/test_free_threading/test_type.py 
b/Lib/test/test_free_threading/test_type.py
index 786336fa0cddce..1e84b2db2d4882 100644
--- a/Lib/test/test_free_threading/test_type.py
+++ b/Lib/test/test_free_threading/test_type.py
@@ -96,6 +96,32 @@ def reader_func():
 
 self.run_one(writer_func, reader_func)
 
+def test___class___modification(self):
+class Foo:
+pass
+
+class Bar:
+pass
+
+thing = Foo()
+def work():
+foo = thing
+for _ in range(1):
+foo.__class__ = Bar
+type(foo)
+foo.__class__ = Foo
+type(foo)
+
+
+threads = []
+for i in range(NTHREADS):
+thread = threading.Thread(target=work)
+thread.start()
+threads.append(thread)
+
+for thread in threads:
+thread.join()
+
 def run_one(self, writer_func, reader_func):
 writer = Thread(target=writer_func)
 readers = []
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index 2d001b76e09775..eec25b0afaa86d 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -6474,9 +6474,15 @@ object_set_class(PyObject *self, PyObject *value, void 
*closure)
 if (newto->tp_flags & Py_TPFLAGS_HEAPTYPE) {
 Py_INCREF(newto);
 }
+Py_BEGIN_CRITICAL_SECTION(self);
+// The real Py_TYPE(self) (`oldto`) may have changed from
+// underneath us in another thread, so we re-fetch it here.
+oldto = Py_TYPE(self);
 Py_SET_TYPE(self, newto);
-if (oldto->tp_flags & Py_TPFLAGS_HEAPTYPE)
+Py_END_CRITICAL_SECTION();
+if (oldto->tp_flags & Py_TPFLAGS_HEAPTYPE) {
 Py_DECREF(oldto);
+}
 
 RARE_EVENT_INC(set_class);
 return 0;
diff --git a/Tools/tsan/suppressions_free_threading.txt 
b/Tools/tsan/suppressions_free_threading.txt
index cb48a30751ac7b..b10b297f50da81 100644
--- a/Tools/tsan/suppressions_free_threading.txt
+++ b/Tools/tsan/suppressions_free_threading.txt
@@ -37,7 +37,6 @@ race_top:set_contains_key
 # https://gist.github.com/colesbury/d13d033f413b4ad07929d044bed86c35
 race_top:set_discard_entry
 race_top:set_inheritable
-race_top:Py_SET_TYPE
 race_top:_PyDict_CheckConsistency
 race_top:_Py_dict_lookup_threadsafe
 race_top:_multip

[Python-checkins] gh-117657: Fix some simple races in instrumentation.c (GH-120118)

2024-06-13 Thread Fidget-Spinner
https://github.com/python/cpython/commit/b1b61dc4cee43920ef2b08d5ac94ddf08119c507
commit: b1b61dc4cee43920ef2b08d5ac94ddf08119c507
branch: main
author: Ken Jin 
committer: Fidget-Spinner 
date: 2024-06-13T17:31:21+08:00
summary:

gh-117657: Fix some simple races in instrumentation.c (GH-120118)

* stop the world when setting local events

files:
M Python/instrumentation.c

diff --git a/Python/instrumentation.c b/Python/instrumentation.c
index a5211ee5428cf8..ae790a1441b933 100644
--- a/Python/instrumentation.c
+++ b/Python/instrumentation.c
@@ -1977,7 +1977,7 @@ _PyMonitoring_SetLocalEvents(PyCodeObject *code, int 
tool_id, _PyMonitoringEvent
 }
 
 int res;
-LOCK_CODE(code);
+_PyEval_StopTheWorld(interp);
 if (allocate_instrumentation_data(code)) {
 res = -1;
 goto done;
@@ -1994,7 +1994,7 @@ _PyMonitoring_SetLocalEvents(PyCodeObject *code, int 
tool_id, _PyMonitoringEvent
 res = force_instrument_lock_held(code, interp);
 
 done:
-UNLOCK_CODE();
+_PyEval_StartTheWorld(interp);
 return res;
 }
 

___
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com


[Python-checkins] gh-117657: Make PyType_HasFeature atomic (GH-120210)

2024-06-13 Thread Fidget-Spinner
https://github.com/python/cpython/commit/eebae2c460dabdc70dc0d9b6e189368eb1abb716
commit: eebae2c460dabdc70dc0d9b6e189368eb1abb716
branch: main
author: Ken Jin 
committer: Fidget-Spinner 
date: 2024-06-13T17:29:19+08:00
summary:

gh-117657: Make PyType_HasFeature atomic (GH-120210)

Make PyType_HasFeature atomic

files:
M Include/internal/pycore_object.h
M Include/internal/pycore_pyatomic_ft_wrappers.h
M Tools/tsan/suppressions_free_threading.txt

diff --git a/Include/internal/pycore_object.h b/Include/internal/pycore_object.h
index 6f133014ce06e2..d1e2773a2473b0 100644
--- a/Include/internal/pycore_object.h
+++ b/Include/internal/pycore_object.h
@@ -262,7 +262,7 @@ extern int _PyTraceMalloc_TraceRef(PyObject *op, 
PyRefTracerEvent event, void*);
 // Fast inlined version of PyType_HasFeature()
 static inline int
 _PyType_HasFeature(PyTypeObject *type, unsigned long feature) {
-return ((type->tp_flags & feature) != 0);
+return ((FT_ATOMIC_LOAD_ULONG_RELAXED(type->tp_flags) & feature) != 0);
 }
 
 extern void _PyType_InitCache(PyInterpreterState *interp);
diff --git a/Include/internal/pycore_pyatomic_ft_wrappers.h 
b/Include/internal/pycore_pyatomic_ft_wrappers.h
index bc6aba56cf9fc7..a1bb383bcd22e9 100644
--- a/Include/internal/pycore_pyatomic_ft_wrappers.h
+++ b/Include/internal/pycore_pyatomic_ft_wrappers.h
@@ -45,6 +45,8 @@ extern "C" {
 _Py_atomic_load_uint16_relaxed(&value)
 #define FT_ATOMIC_LOAD_UINT32_RELAXED(value) \
 _Py_atomic_load_uint32_relaxed(&value)
+#define FT_ATOMIC_LOAD_ULONG_RELAXED(value) \
+_Py_atomic_load_ulong_relaxed(&value)
 #define FT_ATOMIC_STORE_PTR_RELAXED(value, new_value) \
 _Py_atomic_store_ptr_relaxed(&value, new_value)
 #define FT_ATOMIC_STORE_PTR_RELEASE(value, new_value) \
@@ -75,6 +77,7 @@ extern "C" {
 #define FT_ATOMIC_LOAD_UINT8_RELAXED(value) value
 #define FT_ATOMIC_LOAD_UINT16_RELAXED(value) value
 #define FT_ATOMIC_LOAD_UINT32_RELAXED(value) value
+#define FT_ATOMIC_LOAD_ULONG_RELAXED(value) value
 #define FT_ATOMIC_STORE_PTR_RELAXED(value, new_value) value = new_value
 #define FT_ATOMIC_STORE_PTR_RELEASE(value, new_value) value = new_value
 #define FT_ATOMIC_STORE_UINTPTR_RELEASE(value, new_value) value = new_value
diff --git a/Tools/tsan/suppressions_free_threading.txt 
b/Tools/tsan/suppressions_free_threading.txt
index b10b297f50da81..05ceaf438b6353 100644
--- a/Tools/tsan/suppressions_free_threading.txt
+++ b/Tools/tsan/suppressions_free_threading.txt
@@ -26,7 +26,6 @@ race:free_threadstate
 race_top:_add_to_weak_set
 race_top:_in_weak_set
 race_top:_PyEval_EvalFrameDefault
-race_top:_PyType_HasFeature
 race_top:assign_version_tag
 race_top:insertdict
 race_top:lookup_tp_dict

___
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com


[Python-checkins] [3.13] gh-117657: Fix some simple races in instrumentation.c (GH-120118) (#120444)

2024-06-13 Thread Fidget-Spinner
https://github.com/python/cpython/commit/17188270b6e6671ab721235745ad9f3ab0a7a8d8
commit: 17188270b6e6671ab721235745ad9f3ab0a7a8d8
branch: 3.13
author: Miss Islington (bot) <31488909+miss-isling...@users.noreply.github.com>
committer: Fidget-Spinner 
date: 2024-06-13T18:23:19+08:00
summary:

[3.13] gh-117657: Fix some simple races in instrumentation.c (GH-120118) 
(#120444)

gh-117657: Fix some simple races in instrumentation.c (GH-120118)

* stop the world when setting local events
(cherry picked from commit b1b61dc4cee43920ef2b08d5ac94ddf08119c507)

Co-authored-by: Ken Jin 

files:
M Python/instrumentation.c

diff --git a/Python/instrumentation.c b/Python/instrumentation.c
index a5211ee5428cf8..ae790a1441b933 100644
--- a/Python/instrumentation.c
+++ b/Python/instrumentation.c
@@ -1977,7 +1977,7 @@ _PyMonitoring_SetLocalEvents(PyCodeObject *code, int 
tool_id, _PyMonitoringEvent
 }
 
 int res;
-LOCK_CODE(code);
+_PyEval_StopTheWorld(interp);
 if (allocate_instrumentation_data(code)) {
 res = -1;
 goto done;
@@ -1994,7 +1994,7 @@ _PyMonitoring_SetLocalEvents(PyCodeObject *code, int 
tool_id, _PyMonitoringEvent
 res = force_instrument_lock_held(code, interp);
 
 done:
-UNLOCK_CODE();
+_PyEval_StartTheWorld(interp);
 return res;
 }
 

___
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com


[Python-checkins] [3.13] gh-117657: Make PyType_HasFeature atomic (GH-120210) (#120443)

2024-06-13 Thread Fidget-Spinner
https://github.com/python/cpython/commit/3067c62a34eb0a99a01af3e9edaaf082fb7fa0a2
commit: 3067c62a34eb0a99a01af3e9edaaf082fb7fa0a2
branch: 3.13
author: Miss Islington (bot) <31488909+miss-isling...@users.noreply.github.com>
committer: Fidget-Spinner 
date: 2024-06-13T18:06:04+08:00
summary:

[3.13] gh-117657: Make PyType_HasFeature atomic (GH-120210) (#120443)

gh-117657: Make PyType_HasFeature atomic (GH-120210)

Make PyType_HasFeature atomic
(cherry picked from commit eebae2c460dabdc70dc0d9b6e189368eb1abb716)

Co-authored-by: Ken Jin 

files:
M Include/internal/pycore_object.h
M Include/internal/pycore_pyatomic_ft_wrappers.h
M Tools/tsan/suppressions_free_threading.txt

diff --git a/Include/internal/pycore_object.h b/Include/internal/pycore_object.h
index 6f133014ce06e2..d1e2773a2473b0 100644
--- a/Include/internal/pycore_object.h
+++ b/Include/internal/pycore_object.h
@@ -262,7 +262,7 @@ extern int _PyTraceMalloc_TraceRef(PyObject *op, 
PyRefTracerEvent event, void*);
 // Fast inlined version of PyType_HasFeature()
 static inline int
 _PyType_HasFeature(PyTypeObject *type, unsigned long feature) {
-return ((type->tp_flags & feature) != 0);
+return ((FT_ATOMIC_LOAD_ULONG_RELAXED(type->tp_flags) & feature) != 0);
 }
 
 extern void _PyType_InitCache(PyInterpreterState *interp);
diff --git a/Include/internal/pycore_pyatomic_ft_wrappers.h 
b/Include/internal/pycore_pyatomic_ft_wrappers.h
index bc6aba56cf9fc7..a1bb383bcd22e9 100644
--- a/Include/internal/pycore_pyatomic_ft_wrappers.h
+++ b/Include/internal/pycore_pyatomic_ft_wrappers.h
@@ -45,6 +45,8 @@ extern "C" {
 _Py_atomic_load_uint16_relaxed(&value)
 #define FT_ATOMIC_LOAD_UINT32_RELAXED(value) \
 _Py_atomic_load_uint32_relaxed(&value)
+#define FT_ATOMIC_LOAD_ULONG_RELAXED(value) \
+_Py_atomic_load_ulong_relaxed(&value)
 #define FT_ATOMIC_STORE_PTR_RELAXED(value, new_value) \
 _Py_atomic_store_ptr_relaxed(&value, new_value)
 #define FT_ATOMIC_STORE_PTR_RELEASE(value, new_value) \
@@ -75,6 +77,7 @@ extern "C" {
 #define FT_ATOMIC_LOAD_UINT8_RELAXED(value) value
 #define FT_ATOMIC_LOAD_UINT16_RELAXED(value) value
 #define FT_ATOMIC_LOAD_UINT32_RELAXED(value) value
+#define FT_ATOMIC_LOAD_ULONG_RELAXED(value) value
 #define FT_ATOMIC_STORE_PTR_RELAXED(value, new_value) value = new_value
 #define FT_ATOMIC_STORE_PTR_RELEASE(value, new_value) value = new_value
 #define FT_ATOMIC_STORE_UINTPTR_RELEASE(value, new_value) value = new_value
diff --git a/Tools/tsan/suppressions_free_threading.txt 
b/Tools/tsan/suppressions_free_threading.txt
index b10b297f50da81..05ceaf438b6353 100644
--- a/Tools/tsan/suppressions_free_threading.txt
+++ b/Tools/tsan/suppressions_free_threading.txt
@@ -26,7 +26,6 @@ race:free_threadstate
 race_top:_add_to_weak_set
 race_top:_in_weak_set
 race_top:_PyEval_EvalFrameDefault
-race_top:_PyType_HasFeature
 race_top:assign_version_tag
 race_top:insertdict
 race_top:lookup_tp_dict

___
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com


[Python-checkins] gh-117657: Add TSAN suppression for set_default_allocator_unlocked (#120500)

2024-06-14 Thread Fidget-Spinner
https://github.com/python/cpython/commit/2bacc2343c24c49292dea3461f6b7664fc2d33e2
commit: 2bacc2343c24c49292dea3461f6b7664fc2d33e2
branch: main
author: AN Long 
committer: Fidget-Spinner 
date: 2024-06-15T00:10:18+08:00
summary:

gh-117657: Add TSAN suppression for set_default_allocator_unlocked (#120500)

Add TSAN suppression for set_default_allocator_unlocked

files:
M Tools/tsan/suppressions_free_threading.txt

diff --git a/Tools/tsan/suppressions_free_threading.txt 
b/Tools/tsan/suppressions_free_threading.txt
index 05ceaf438b6353..4c8b0b8abd2963 100644
--- a/Tools/tsan/suppressions_free_threading.txt
+++ b/Tools/tsan/suppressions_free_threading.txt
@@ -63,6 +63,8 @@ race_top:tstate_is_freed
 race_top:type_modified_unlocked
 race_top:write_thread_id
 race_top:PyThreadState_Clear
+# Only seen on macOS, sample: 
https://gist.github.com/aisk/dda53f5d494a4556c35dde1fce03259c
+race_top:set_default_allocator_unlocked
 
 # https://gist.github.com/mpage/6962e8870606cfc960e159b407a0cb40
 thread:pthread_create

___
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com


[Python-checkins] [3.13] gh-117657: Add TSAN suppression for set_default_allocator_unlocked (GH-120500) (#120510)

2024-06-14 Thread Fidget-Spinner
https://github.com/python/cpython/commit/6e3e1124287858b6e22d10ac912e9b76afa3e41b
commit: 6e3e1124287858b6e22d10ac912e9b76afa3e41b
branch: 3.13
author: Miss Islington (bot) <31488909+miss-isling...@users.noreply.github.com>
committer: Fidget-Spinner 
date: 2024-06-14T16:34:07Z
summary:

[3.13] gh-117657: Add TSAN suppression for set_default_allocator_unlocked 
(GH-120500) (#120510)

gh-117657: Add TSAN suppression for set_default_allocator_unlocked (GH-120500)

Add TSAN suppression for set_default_allocator_unlocked
(cherry picked from commit 2bacc2343c24c49292dea3461f6b7664fc2d33e2)

Co-authored-by: AN Long 

files:
M Tools/tsan/suppressions_free_threading.txt

diff --git a/Tools/tsan/suppressions_free_threading.txt 
b/Tools/tsan/suppressions_free_threading.txt
index 05ceaf438b6353..4c8b0b8abd2963 100644
--- a/Tools/tsan/suppressions_free_threading.txt
+++ b/Tools/tsan/suppressions_free_threading.txt
@@ -63,6 +63,8 @@ race_top:tstate_is_freed
 race_top:type_modified_unlocked
 race_top:write_thread_id
 race_top:PyThreadState_Clear
+# Only seen on macOS, sample: 
https://gist.github.com/aisk/dda53f5d494a4556c35dde1fce03259c
+race_top:set_default_allocator_unlocked
 
 # https://gist.github.com/mpage/6962e8870606cfc960e159b407a0cb40
 thread:pthread_create

___
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com


[Python-checkins] gh-117657: Make PyType_HasFeature (exported version) atomic (#120484)

2024-06-15 Thread Fidget-Spinner
https://github.com/python/cpython/commit/6f63dfff6f493b405f3422210a168369e1e7a35d
commit: 6f63dfff6f493b405f3422210a168369e1e7a35d
branch: main
author: Ken Jin 
committer: Fidget-Spinner 
date: 2024-06-15T22:39:22+08:00
summary:

gh-117657: Make PyType_HasFeature (exported version) atomic (#120484)

Make PyType_HasFeature (exported version) atomic

files:
M Include/object.h
M Objects/typeobject.c

diff --git a/Include/object.h b/Include/object.h
index 4a39ada8c7daa4..f71aaee7efe6ee 100644
--- a/Include/object.h
+++ b/Include/object.h
@@ -756,7 +756,11 @@ PyType_HasFeature(PyTypeObject *type, unsigned long 
feature)
 // PyTypeObject is opaque in the limited C API
 flags = PyType_GetFlags(type);
 #else
-flags = type->tp_flags;
+#   ifdef Py_GIL_DISABLED
+flags = _Py_atomic_load_ulong_relaxed(&type->tp_flags);
+#   else
+flags = type->tp_flags;
+#   endif
 #endif
 return ((flags & feature) != 0);
 }
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index 98e00bd25c3205..eb296414bb7bef 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -3599,7 +3599,7 @@ type_init(PyObject *cls, PyObject *args, PyObject *kwds)
 unsigned long
 PyType_GetFlags(PyTypeObject *type)
 {
-return type->tp_flags;
+return FT_ATOMIC_LOAD_ULONG_RELAXED(type->tp_flags);
 }
 
 

___
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com


[Python-checkins] [3.13] gh-117657: Make PyType_HasFeature (exported version) atomic (GH-120484) (#120554)

2024-06-15 Thread Fidget-Spinner
https://github.com/python/cpython/commit/cbcb5265bfaf80af386faa8858359bb6f15cb77d
commit: cbcb5265bfaf80af386faa8858359bb6f15cb77d
branch: 3.13
author: Miss Islington (bot) <31488909+miss-isling...@users.noreply.github.com>
committer: Fidget-Spinner 
date: 2024-06-15T15:06:54Z
summary:

[3.13] gh-117657: Make PyType_HasFeature (exported version) atomic (GH-120484) 
(#120554)

gh-117657: Make PyType_HasFeature (exported version) atomic (GH-120484)

Make PyType_HasFeature (exported version) atomic
(cherry picked from commit 6f63dfff6f493b405f3422210a168369e1e7a35d)

Co-authored-by: Ken Jin 

files:
M Include/object.h
M Objects/typeobject.c

diff --git a/Include/object.h b/Include/object.h
index a687bf2f7cdd74..7aaa8da8e8d154 100644
--- a/Include/object.h
+++ b/Include/object.h
@@ -1238,7 +1238,11 @@ PyType_HasFeature(PyTypeObject *type, unsigned long 
feature)
 // PyTypeObject is opaque in the limited C API
 flags = PyType_GetFlags(type);
 #else
-flags = type->tp_flags;
+#   ifdef Py_GIL_DISABLED
+flags = _Py_atomic_load_ulong_relaxed(&type->tp_flags);
+#   else
+flags = type->tp_flags;
+#   endif
 #endif
 return ((flags & feature) != 0);
 }
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index 1f6c2828f1c697..1123ef6eb3d9b2 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -3435,7 +3435,7 @@ type_init(PyObject *cls, PyObject *args, PyObject *kwds)
 unsigned long
 PyType_GetFlags(PyTypeObject *type)
 {
-return type->tp_flags;
+return FT_ATOMIC_LOAD_ULONG_RELAXED(type->tp_flags);
 }
 
 

___
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com


[Python-checkins] gh-120437: Fix `_CHECK_STACK_SPACE` optimization problems introduced in gh-118322 (GH-120712)

2024-06-19 Thread Fidget-Spinner
https://github.com/python/cpython/commit/f385d99f57773e48285e0bcdbcd66dcbfdc647b3
commit: f385d99f57773e48285e0bcdbcd66dcbfdc647b3
branch: main
author: Nadeshiko Manju 
committer: Fidget-Spinner 
date: 2024-06-19T23:34:39+08:00
summary:

gh-120437: Fix `_CHECK_STACK_SPACE` optimization problems introduced in 
gh-118322 (GH-120712)


Co-authored-by: Ken Jin 

files:
A Misc/NEWS.d/next/Core and 
Builtins/2024-06-19-01-58-54.gh-issue-120437.nCkIoI.rst
M Python/optimizer_bytecodes.c
M Python/optimizer_cases.c.h

diff --git a/Misc/NEWS.d/next/Core and 
Builtins/2024-06-19-01-58-54.gh-issue-120437.nCkIoI.rst b/Misc/NEWS.d/next/Core 
and Builtins/2024-06-19-01-58-54.gh-issue-120437.nCkIoI.rst
new file mode 100644
index 00..8923f3fcefe3c1
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and 
Builtins/2024-06-19-01-58-54.gh-issue-120437.nCkIoI.rst 
@@ -0,0 +1 @@
+Fix ``_CHECK_STACK_SPACE`` optimization problems introduced in :gh:`118322`.
diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c
index 35463f25246803..2ea839f5d6dc97 100644
--- a/Python/optimizer_bytecodes.c
+++ b/Python/optimizer_bytecodes.c
@@ -601,7 +601,6 @@ dummy_func(void) {
 (void)callable;
 (void)self_or_null;
 (void)args;
-first_valid_check_stack = NULL;
 new_frame = NULL;
 ctx->done = true;
 }
diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h
index 46501862ff2fb3..7274bd2a6fc02b 100644
--- a/Python/optimizer_cases.c.h
+++ b/Python/optimizer_cases.c.h
@@ -1492,7 +1492,6 @@
 (void)callable;
 (void)self_or_null;
 (void)args;
-first_valid_check_stack = NULL;
 new_frame = NULL;
 ctx->done = true;
 stack_pointer[-2 - oparg] = (_Py_UopsSymbol *)new_frame;

___
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com


[Python-checkins] [3.13] gh-120437: Fix `_CHECK_STACK_SPACE` optimization problems introduced in gh-118322 (GH-120712) (#120747)

2024-06-19 Thread Fidget-Spinner
https://github.com/python/cpython/commit/ae04b6f63640606a3212c9da21b87ebc374136e1
commit: ae04b6f63640606a3212c9da21b87ebc374136e1
branch: 3.13
author: Nadeshiko Manju 
committer: Fidget-Spinner 
date: 2024-06-20T01:40:48+08:00
summary:

 [3.13] gh-120437: Fix `_CHECK_STACK_SPACE` optimization problems introduced in 
gh-118322 (GH-120712) (#120747)

[3.13] gh-120437: Fix `_CHECK_STACK_SPACE` optimization problems introduced in 
gh-118322 (GH-120712)

Signed-off-by: Manjusaka 
Co-authored-by: Ken Jin 

files:
A Misc/NEWS.d/next/Core and 
Builtins/2024-06-19-01-58-54.gh-issue-120437.nCkIoI.rst
M Python/optimizer_bytecodes.c
M Python/optimizer_cases.c.h

diff --git a/Misc/NEWS.d/next/Core and 
Builtins/2024-06-19-01-58-54.gh-issue-120437.nCkIoI.rst b/Misc/NEWS.d/next/Core 
and Builtins/2024-06-19-01-58-54.gh-issue-120437.nCkIoI.rst
new file mode 100644
index 00..8923f3fcefe3c1
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and 
Builtins/2024-06-19-01-58-54.gh-issue-120437.nCkIoI.rst 
@@ -0,0 +1 @@
+Fix ``_CHECK_STACK_SPACE`` optimization problems introduced in :gh:`118322`.
diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c
index 928bc03382b8fb..2d61fa3b8257f4 100644
--- a/Python/optimizer_bytecodes.c
+++ b/Python/optimizer_bytecodes.c
@@ -634,7 +634,6 @@ dummy_func(void) {
 (void)callable;
 (void)self_or_null;
 (void)args;
-first_valid_check_stack = NULL;
 goto done;
 }
 
diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h
index 6c2480d4fdfe89..621a48f2fc9105 100644
--- a/Python/optimizer_cases.c.h
+++ b/Python/optimizer_cases.c.h
@@ -1565,7 +1565,6 @@
 (void)callable;
 (void)self_or_null;
 (void)args;
-first_valid_check_stack = NULL;
 goto done;
 stack_pointer[-2 - oparg] = (_Py_UopsSymbol *)new_frame;
 stack_pointer += -1 - oparg;

___
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com


[Python-checkins] [3.13] gh-119258: Backport optimizer frame fixes in GH-119365 (GH-120699)

2024-06-20 Thread Fidget-Spinner
https://github.com/python/cpython/commit/7c7aa5a99cce256ff726654038092a333a1f0531
commit: 7c7aa5a99cce256ff726654038092a333a1f0531
branch: 3.13
author: Ken Jin 
committer: Fidget-Spinner 
date: 2024-06-20T23:55:20+08:00
summary:

[3.13] gh-119258: Backport optimizer frame fixes in GH-119365 (GH-120699)

(cherry picked from commit 55402d3)

files:
M Include/internal/pycore_optimizer.h
M Python/optimizer_analysis.c
M Python/optimizer_bytecodes.c
M Python/optimizer_cases.c.h
M Python/optimizer_symbols.c

diff --git a/Include/internal/pycore_optimizer.h 
b/Include/internal/pycore_optimizer.h
index c0a76e85350541..c422e2f113d15d 100644
--- a/Include/internal/pycore_optimizer.h
+++ b/Include/internal/pycore_optimizer.h
@@ -107,9 +107,9 @@ extern void _Py_uop_abstractcontext_fini(_Py_UOpsContext 
*ctx);
 extern _Py_UOpsAbstractFrame *_Py_uop_frame_new(
 _Py_UOpsContext *ctx,
 PyCodeObject *co,
-_Py_UopsSymbol **localsplus_start,
-int n_locals_already_filled,
-int curr_stackentries);
+int curr_stackentries,
+_Py_UopsSymbol **args,
+int arg_len);
 extern int _Py_uop_frame_pop(_Py_UOpsContext *ctx);
 
 PyAPI_FUNC(PyObject *) _Py_uop_symbols_test(PyObject *self, PyObject *ignored);
diff --git a/Python/optimizer_analysis.c b/Python/optimizer_analysis.c
index 842b2e489239af..03148c23a82c46 100644
--- a/Python/optimizer_analysis.c
+++ b/Python/optimizer_analysis.c
@@ -411,7 +411,7 @@ optimize_uops(
 if (_Py_uop_abstractcontext_init(ctx) < 0) {
 goto out_of_space;
 }
-_Py_UOpsAbstractFrame *frame = _Py_uop_frame_new(ctx, co, ctx->n_consumed, 
0, curr_stacklen);
+_Py_UOpsAbstractFrame *frame = _Py_uop_frame_new(ctx, co, curr_stacklen, 
NULL, 0);
 if (frame == NULL) {
 return -1;
 }
diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c
index 2d61fa3b8257f4..690c9b8bced984 100644
--- a/Python/optimizer_bytecodes.c
+++ b/Python/optimizer_bytecodes.c
@@ -616,17 +616,12 @@ dummy_func(void) {
 argcount++;
 }
 
-_Py_UopsSymbol **localsplus_start = ctx->n_consumed;
-int n_locals_already_filled = 0;
-// Can determine statically, so we interleave the new locals
-// and make the current stack the new locals.
-// This also sets up for true call inlining.
+
 if (sym_is_null(self_or_null) || sym_is_not_null(self_or_null)) {
-localsplus_start = args;
-n_locals_already_filled = argcount;
+OUT_OF_SPACE_IF_NULL(new_frame = frame_new(ctx, co, 0, args, 
argcount));
+} else {
+OUT_OF_SPACE_IF_NULL(new_frame = frame_new(ctx, co, 0, NULL, 0));
 }
-OUT_OF_SPACE_IF_NULL(new_frame =
- frame_new(ctx, co, localsplus_start, 
n_locals_already_filled, 0));
 }
 
 op(_PY_FRAME_GENERAL, (callable, self_or_null, args[oparg] -- new_frame: 
_Py_UOpsAbstractFrame *)) {
diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h
index 621a48f2fc9105..fb7f1edf498705 100644
--- a/Python/optimizer_cases.c.h
+++ b/Python/optimizer_cases.c.h
@@ -1696,17 +1696,11 @@
 args--;
 argcount++;
 }
-_Py_UopsSymbol **localsplus_start = ctx->n_consumed;
-int n_locals_already_filled = 0;
-// Can determine statically, so we interleave the new locals
-// and make the current stack the new locals.
-// This also sets up for true call inlining.
 if (sym_is_null(self_or_null) || sym_is_not_null(self_or_null)) {
-localsplus_start = args;
-n_locals_already_filled = argcount;
+OUT_OF_SPACE_IF_NULL(new_frame = frame_new(ctx, co, 0, args, 
argcount));
+} else {
+OUT_OF_SPACE_IF_NULL(new_frame = frame_new(ctx, co, 0, NULL, 
0));
 }
-OUT_OF_SPACE_IF_NULL(new_frame =
- frame_new(ctx, co, localsplus_start, 
n_locals_already_filled, 0));
 stack_pointer[-2 - oparg] = (_Py_UopsSymbol *)new_frame;
 stack_pointer += -1 - oparg;
 break;
diff --git a/Python/optimizer_symbols.c b/Python/optimizer_symbols.c
index 4aeb04fe0405d2..e80d15b200d2f3 100644
--- a/Python/optimizer_symbols.c
+++ b/Python/optimizer_symbols.c
@@ -303,9 +303,9 @@ _Py_UOpsAbstractFrame *
 _Py_uop_frame_new(
 _Py_UOpsContext *ctx,
 PyCodeObject *co,
-_Py_UopsSymbol **localsplus_start,
-int n_locals_already_filled,
-int curr_stackentries)
+int curr_stackentries,
+_Py_UopsSymbol **args,
+int arg_len)
 {
 assert(ctx->curr_frame_depth < MAX_ABSTRACT_FRAME_DEPTH);
 _Py_UOpsAbstractFrame *frame = &ctx->frames[ctx->curr_frame_depth];
@@ -313,21 +313,21 @@ _Py_uop_frame_new(
 frame->stack_len = co->co_stacksize;
 frame->locals_len = co->co_nlocalsplus;
 
-frame->locals = localsplus_start;
+

[Python-checkins] gh-121082: Fix build failure when the developer use `--enable-pystats` arguments in configuration command after #118450 (#121083)

2024-06-27 Thread Fidget-Spinner
https://github.com/python/cpython/commit/223c03a43c010cf4404f2a42efafe587646a0619
commit: 223c03a43c010cf4404f2a42efafe587646a0619
branch: main
author: Nadeshiko Manju 
committer: Fidget-Spinner 
date: 2024-06-27T19:35:25+08:00
summary:

gh-121082: Fix build failure when the developer use `--enable-pystats` 
arguments in configuration command after #118450 (#121083)



Signed-off-by: Manjusaka 
Co-authored-by: Ken Jin 

files:
A Misc/NEWS.d/next/Build/2024-06-27-18-03-20.gh-issue-121082.w3AfRx.rst
M Python/specialize.c

diff --git 
a/Misc/NEWS.d/next/Build/2024-06-27-18-03-20.gh-issue-121082.w3AfRx.rst 
b/Misc/NEWS.d/next/Build/2024-06-27-18-03-20.gh-issue-121082.w3AfRx.rst
new file mode 100644
index 00..7657672ba880c8
--- /dev/null
+++ b/Misc/NEWS.d/next/Build/2024-06-27-18-03-20.gh-issue-121082.w3AfRx.rst
@@ -0,0 +1 @@
+Fix build failure when the developer use ``--enable-pystats`` arguments in 
configuration command after #118450.
diff --git a/Python/specialize.c b/Python/specialize.c
index dc0e319880b976..497feca06e4c7f 100644
--- a/Python/specialize.c
+++ b/Python/specialize.c
@@ -2364,7 +2364,8 @@ _Py_Specialize_ForIter(_PyStackRef iter, _Py_CODEUNIT 
*instr, int oparg)
 assert(ENABLE_SPECIALIZATION);
 assert(_PyOpcode_Caches[FOR_ITER] == INLINE_CACHE_ENTRIES_FOR_ITER);
 _PyForIterCache *cache = (_PyForIterCache *)(instr + 1);
-PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(iter));
+PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter);
+PyTypeObject *tp = Py_TYPE(iter_o);
 if (tp == &PyListIter_Type) {
 instr->op.code = FOR_ITER_LIST;
 goto success;
@@ -2389,7 +2390,7 @@ _Py_Specialize_ForIter(_PyStackRef iter, _Py_CODEUNIT 
*instr, int oparg)
 goto success;
 }
 SPECIALIZATION_FAIL(FOR_ITER,
-_PySpecialization_ClassifyIterator(iter));
+_PySpecialization_ClassifyIterator(iter_o));
 failure:
 STAT_INC(FOR_ITER, failure);
 instr->op.code = FOR_ITER;

___
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com


[Python-checkins] gh-117139: Fix a few wrong steals in bytecodes.c (GH-121127)

2024-06-28 Thread Fidget-Spinner
https://github.com/python/cpython/commit/e6543daf12051e9c660a5c0437683e8d2706a3c7
commit: e6543daf12051e9c660a5c0437683e8d2706a3c7
branch: main
author: Ken Jin 
committer: Fidget-Spinner 
date: 2024-06-29T02:14:48+08:00
summary:

gh-117139: Fix a few wrong steals in bytecodes.c (GH-121127)

Fix a few wrong steals in bytecodes.c

files:
M Python/bytecodes.c
M Python/ceval.c
M Python/executor_cases.c.h
M Python/generated_cases.c.h

diff --git a/Python/bytecodes.c b/Python/bytecodes.c
index 8dfce77dfca297..50978a0dc87694 100644
--- a/Python/bytecodes.c
+++ b/Python/bytecodes.c
@@ -230,7 +230,7 @@ dummy_func(
 }
 
 replicate(8) pure inst(LOAD_FAST, (-- value)) {
-assert(PyStackRef_AsPyObjectBorrow(GETLOCAL(oparg)) != NULL);
+assert(!PyStackRef_IsNull(GETLOCAL(oparg)));
 value = PyStackRef_DUP(GETLOCAL(oparg));
 }
 
@@ -673,7 +673,7 @@ dummy_func(
 err = 1;
 }
 else {
-err = PyObject_SetItem(PyStackRef_AsPyObjectBorrow(container), 
slice, PyStackRef_AsPyObjectSteal(v));
+err = PyObject_SetItem(PyStackRef_AsPyObjectBorrow(container), 
slice, PyStackRef_AsPyObjectBorrow(v));
 Py_DECREF(slice);
 }
 PyStackRef_CLOSE(v);
@@ -789,7 +789,7 @@ dummy_func(
 
 inst(SET_ADD, (set, unused[oparg-1], v -- set, unused[oparg-1])) {
 int err = PySet_Add(PyStackRef_AsPyObjectBorrow(set),
-PyStackRef_AsPyObjectSteal(v));
+PyStackRef_AsPyObjectBorrow(v));
 DECREF_INPUTS();
 ERROR_IF(err, error);
 }
@@ -813,7 +813,7 @@ dummy_func(
 
 op(_STORE_SUBSCR, (v, container, sub -- )) {
 /* container[sub] = v */
-int err = PyObject_SetItem(PyStackRef_AsPyObjectBorrow(container), 
PyStackRef_AsPyObjectSteal(sub), PyStackRef_AsPyObjectSteal(v));
+int err = PyObject_SetItem(PyStackRef_AsPyObjectBorrow(container), 
PyStackRef_AsPyObjectBorrow(sub), PyStackRef_AsPyObjectBorrow(v));
 DECREF_INPUTS();
 ERROR_IF(err, error);
 }
@@ -1235,7 +1235,7 @@ dummy_func(
 inst(POP_EXCEPT, (exc_value -- )) {
 _PyErr_StackItem *exc_info = tstate->exc_info;
 Py_XSETREF(exc_info->exc_value,
-PyStackRef_AsPyObjectBorrow(exc_value) == Py_None
+   PyStackRef_Is(exc_value, PyStackRef_None)
 ? NULL : PyStackRef_AsPyObjectSteal(exc_value));
 }
 
@@ -1330,9 +1330,9 @@ dummy_func(
 ERROR_IF(true, error);
 }
 if (PyDict_CheckExact(ns))
-err = PyDict_SetItem(ns, name, PyStackRef_AsPyObjectSteal(v));
+err = PyDict_SetItem(ns, name, PyStackRef_AsPyObjectBorrow(v));
 else
-err = PyObject_SetItem(ns, name, 
PyStackRef_AsPyObjectSteal(v));
+err = PyObject_SetItem(ns, name, 
PyStackRef_AsPyObjectBorrow(v));
 DECREF_INPUTS();
 ERROR_IF(err, error);
 }
@@ -1450,7 +1450,7 @@ dummy_func(
 op(_STORE_ATTR, (v, owner --)) {
 PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
 int err = PyObject_SetAttr(PyStackRef_AsPyObjectBorrow(owner),
-   name, PyStackRef_AsPyObjectSteal(v));
+   name, PyStackRef_AsPyObjectBorrow(v));
 DECREF_INPUTS();
 ERROR_IF(err, error);
 }
diff --git a/Python/ceval.c b/Python/ceval.c
index 2412256ace8c8d..f4b3a417025c14 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -1619,7 +1619,7 @@ initialize_locals(PyThreadState *tstate, PyFunctionObject 
*func,
 goto kw_fail;
 }
 
-if (PyDict_SetItem(kwdict, keyword, 
PyStackRef_AsPyObjectSteal(value_stackref)) == -1) {
+if (PyDict_SetItem(kwdict, keyword, 
PyStackRef_AsPyObjectBorrow(value_stackref)) == -1) {
 goto kw_fail;
 }
 PyStackRef_CLOSE(value_stackref);
diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h
index 38437c6f2c087c..76b7a9b4b15ae9 100644
--- a/Python/executor_cases.c.h
+++ b/Python/executor_cases.c.h
@@ -54,7 +54,7 @@
 _PyStackRef value;
 oparg = 0;
 assert(oparg == CURRENT_OPARG());
-assert(PyStackRef_AsPyObjectBorrow(GETLOCAL(oparg)) != NULL);
+assert(!PyStackRef_IsNull(GETLOCAL(oparg)));
 value = PyStackRef_DUP(GETLOCAL(oparg));
 stack_pointer[0] = value;
 stack_pointer += 1;
@@ -66,7 +66,7 @@
 _PyStackRef value;
 oparg = 1;
 assert(oparg == CURRENT_OPARG());
-assert(PyStackRef_AsPyObjectBorrow(GETLOCAL(oparg)) != NULL);
+assert(!PyStackRef_IsNull(GETLOCAL(oparg)));
 value = PyStackRef_DUP(GE

[Python-checkins] gh-121263: Macro-ify most stackref functions for MSVC (GH-121270)

2024-07-03 Thread Fidget-Spinner
https://github.com/python/cpython/commit/79e5dc1e499664966e50bb98065670033300
commit: 79e5dc1e499664966e50bb98065670033300
branch: main
author: Ken Jin 
committer: Fidget-Spinner 
date: 2024-07-03T17:49:31+08:00
summary:

gh-121263: Macro-ify most stackref functions for MSVC (GH-121270)

Macro-ify most stackref functions for MSVC

files:
M Include/internal/pycore_stackref.h

diff --git a/Include/internal/pycore_stackref.h 
b/Include/internal/pycore_stackref.h
index 4301c6a7cb40b0..8d3d559814bfd9 100644
--- a/Include/internal/pycore_stackref.h
+++ b/Include/internal/pycore_stackref.h
@@ -85,81 +85,67 @@ typedef union _PyStackRef {
 #   define PyStackRef_None ((_PyStackRef){.bits = ((uintptr_t)&_Py_NoneStruct) 
})
 #endif
 
+// Note: the following are all macros because MSVC (Windows) has trouble 
inlining them.
 
-static inline int
-PyStackRef_Is(_PyStackRef a, _PyStackRef b) {
-return a.bits == b.bits;
-}
+#define PyStackRef_Is(a, b) ((a).bits == (b).bits)
+
+#define PyStackRef_IsDeferred(ref) (((ref).bits & Py_TAG_BITS) == 
Py_TAG_DEFERRED)
 
-static inline int
-PyStackRef_IsDeferred(_PyStackRef ref)
-{
-return ((ref.bits & Py_TAG_BITS) == Py_TAG_DEFERRED);
-}
 
+#ifdef Py_GIL_DISABLED
 // Gets a PyObject * from a _PyStackRef
 static inline PyObject *
 PyStackRef_AsPyObjectBorrow(_PyStackRef stackref)
 {
-#ifdef Py_GIL_DISABLED
 PyObject *cleared = ((PyObject *)((stackref).bits & (~Py_TAG_BITS)));
 return cleared;
+}
 #else
-return ((PyObject *)(stackref).bits);
+#   define PyStackRef_AsPyObjectBorrow(stackref) ((PyObject *)(stackref).bits)
 #endif
-}
 
 // Converts a PyStackRef back to a PyObject *, stealing the
 // PyStackRef.
+#ifdef Py_GIL_DISABLED
 static inline PyObject *
 PyStackRef_AsPyObjectSteal(_PyStackRef stackref)
 {
-#ifdef Py_GIL_DISABLED
 if (!PyStackRef_IsNull(stackref) && PyStackRef_IsDeferred(stackref)) {
 return Py_NewRef(PyStackRef_AsPyObjectBorrow(stackref));
 }
 return PyStackRef_AsPyObjectBorrow(stackref);
+}
 #else
-return PyStackRef_AsPyObjectBorrow(stackref);
+#   define PyStackRef_AsPyObjectSteal(stackref) 
PyStackRef_AsPyObjectBorrow(stackref)
 #endif
-}
 
 // Converts a PyStackRef back to a PyObject *, converting the
 // stackref to a new reference.
-static inline PyObject *
-PyStackRef_AsPyObjectNew(_PyStackRef stackref)
-{
-return Py_NewRef(PyStackRef_AsPyObjectBorrow(stackref));
-}
+#define PyStackRef_AsPyObjectNew(stackref) 
Py_NewRef(PyStackRef_AsPyObjectBorrow(stackref))
 
-static inline PyTypeObject *
-PyStackRef_TYPE(_PyStackRef stackref)
-{
-return Py_TYPE(PyStackRef_AsPyObjectBorrow(stackref));
-}
+#define PyStackRef_TYPE(stackref) 
Py_TYPE(PyStackRef_AsPyObjectBorrow(stackref))
 
 // Converts a PyObject * to a PyStackRef, stealing the reference
+#ifdef Py_GIL_DISABLED
 static inline _PyStackRef
 _PyStackRef_FromPyObjectSteal(PyObject *obj)
 {
-#ifdef Py_GIL_DISABLED
 // Make sure we don't take an already tagged value.
 assert(((uintptr_t)obj & Py_TAG_BITS) == 0);
 int tag = (obj == NULL || _Py_IsImmortal(obj)) ? (Py_TAG_DEFERRED) : 
Py_TAG_PTR;
 return ((_PyStackRef){.bits = ((uintptr_t)(obj)) | tag});
+}
+#   define PyStackRef_FromPyObjectSteal(obj) 
_PyStackRef_FromPyObjectSteal(_PyObject_CAST(obj))
 #else
-return ((_PyStackRef){.bits = ((uintptr_t)(obj))});
+#   define PyStackRef_FromPyObjectSteal(obj) ((_PyStackRef){.bits = 
((uintptr_t)(obj))})
 #endif
-}
-
-#define PyStackRef_FromPyObjectSteal(obj) 
_PyStackRef_FromPyObjectSteal(_PyObject_CAST(obj))
 
 
 // Converts a PyObject * to a PyStackRef, with a new reference
+#ifdef Py_GIL_DISABLED
 static inline _PyStackRef
 PyStackRef_FromPyObjectNew(PyObject *obj)
 {
-#ifdef Py_GIL_DISABLED
 // Make sure we don't take an already tagged value.
 assert(((uintptr_t)obj & Py_TAG_BITS) == 0);
 assert(obj != NULL);
@@ -170,30 +156,27 @@ PyStackRef_FromPyObjectNew(PyObject *obj)
 else {
 return (_PyStackRef){ .bits = (uintptr_t)(Py_NewRef(obj)) | Py_TAG_PTR 
};
 }
+}
+#   define PyStackRef_FromPyObjectNew(obj) 
PyStackRef_FromPyObjectNew(_PyObject_CAST(obj))
 #else
-return ((_PyStackRef){ .bits = (uintptr_t)(Py_NewRef(obj)) });
+#   define PyStackRef_FromPyObjectNew(obj) ((_PyStackRef){ .bits = 
(uintptr_t)(Py_NewRef(obj)) })
 #endif
-}
-
-#define PyStackRef_FromPyObjectNew(obj) 
PyStackRef_FromPyObjectNew(_PyObject_CAST(obj))
 
+#ifdef Py_GIL_DISABLED
 // Same as PyStackRef_FromPyObjectNew but only for immortal objects.
 static inline _PyStackRef
 PyStackRef_FromPyObjectImmortal(PyObject *obj)
 {
-#ifdef Py_GIL_DISABLED
 // Make sure we don't take an already tagged value.
 assert(((uintptr_t)obj & Py_TAG_BITS) == 0);
 assert(obj != NULL);
 assert(_Py_IsImmortal(obj));
 return (_PyStackRef){ .bits = (uintptr_t)obj | Py_TAG_DEFERRED };
+}
+#   define PyStackRef_FromPyObjectImmortal(obj) 
PyStackRef_FromPyObjectImmortal(_PyObject_CAST(obj))
 

[Python-checkins] Add Fidget-Spinner to stackrefs CODEOWNERS (GH-121455)

2024-07-07 Thread Fidget-Spinner
https://github.com/python/cpython/commit/3bddd07c2ada7cdadb55ea23a15037bd650e20ef
commit: 3bddd07c2ada7cdadb55ea23a15037bd650e20ef
branch: main
author: Ken Jin 
committer: Fidget-Spinner 
date: 2024-07-07T21:45:06+08:00
summary:

Add Fidget-Spinner to stackrefs CODEOWNERS (GH-121455)

files:
M .github/CODEOWNERS

diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index e8f4a4693a814c..95e30ac3001c9c 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -72,6 +72,7 @@ Include/internal/pycore_freelist.h  @ericsnowcurrently
 Include/internal/pycore_global_objects.h  @ericsnowcurrently
 Include/internal/pycore_obmalloc.h  @ericsnowcurrently
 Include/internal/pycore_pymem.h @ericsnowcurrently
+Include/internal/pycore_stackref.h  @Fidget-Spinner
 Modules/main.c@ericsnowcurrently
 Programs/_bootstrap_python.c  @ericsnowcurrently
 Programs/python.c @ericsnowcurrently

___
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com


[Python-checkins] gh-120198: Stop the world when setting __class__ on free-threaded build (GH-120672)

2024-07-10 Thread Fidget-Spinner
https://github.com/python/cpython/commit/3bfc9c831ad9a3dcf4457e842f1e612e93014a17
commit: 3bfc9c831ad9a3dcf4457e842f1e612e93014a17
branch: main
author: Ken Jin 
committer: Fidget-Spinner 
date: 2024-07-11T02:02:08+08:00
summary:

gh-120198: Stop the world when setting __class__ on free-threaded build 
(GH-120672)

files:
M Include/internal/pycore_dict.h
M Include/object.h
M Lib/test/test_free_threading/test_type.py
M Objects/dictobject.c
M Objects/typeobject.c

diff --git a/Include/internal/pycore_dict.h b/Include/internal/pycore_dict.h
index 9e0e1237915e82..56cc49432cc61e 100644
--- a/Include/internal/pycore_dict.h
+++ b/Include/internal/pycore_dict.h
@@ -322,6 +322,8 @@ _PyInlineValuesSize(PyTypeObject *tp)
 int
 _PyDict_DetachFromObject(PyDictObject *dict, PyObject *obj);
 
+PyDictObject *_PyObject_MaterializeManagedDict_LockHeld(PyObject *);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/Include/object.h b/Include/object.h
index a1e5b33b0fdaae..abfdb6ce24df21 100644
--- a/Include/object.h
+++ b/Include/object.h
@@ -249,11 +249,7 @@ PyAPI_FUNC(PyTypeObject*) Py_TYPE(PyObject *ob);
 #else
 static inline PyTypeObject* _Py_TYPE(PyObject *ob)
 {
-#if defined(Py_GIL_DISABLED)
-return (PyTypeObject *)_Py_atomic_load_ptr_relaxed(&ob->ob_type);
-#else
 return ob->ob_type;
-#endif
 }
 #if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b
 #   define Py_TYPE(ob) _Py_TYPE(_PyObject_CAST(ob))
@@ -284,11 +280,7 @@ static inline int Py_IS_TYPE(PyObject *ob, PyTypeObject 
*type) {
 
 
 static inline void Py_SET_TYPE(PyObject *ob, PyTypeObject *type) {
-#ifdef Py_GIL_DISABLED
-_Py_atomic_store_ptr(&ob->ob_type, type);
-#else
 ob->ob_type = type;
-#endif
 }
 #if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b
 #  define Py_SET_TYPE(ob, type) Py_SET_TYPE(_PyObject_CAST(ob), type)
diff --git a/Lib/test/test_free_threading/test_type.py 
b/Lib/test/test_free_threading/test_type.py
index 75259795e81bcb..649676db9c08a5 100644
--- a/Lib/test/test_free_threading/test_type.py
+++ b/Lib/test/test_free_threading/test_type.py
@@ -106,7 +106,7 @@ class Bar:
 thing = Foo()
 def work():
 foo = thing
-for _ in range(1):
+for _ in range(5000):
 foo.__class__ = Bar
 type(foo)
 foo.__class__ = Foo
diff --git a/Objects/dictobject.c b/Objects/dictobject.c
index 2b11a01595b0bc..989c7bb624f488 100644
--- a/Objects/dictobject.c
+++ b/Objects/dictobject.c
@@ -158,6 +158,10 @@ ASSERT_DICT_LOCKED(PyObject *op)
 if (!_PyInterpreterState_GET()->stoptheworld.world_stopped) {   \
 ASSERT_DICT_LOCKED(op); \
 }
+#define ASSERT_WORLD_STOPPED_OR_OBJ_LOCKED(op) \
+if (!_PyInterpreterState_GET()->stoptheworld.world_stopped) {  \
+_Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(op); \
+}
 
 #define IS_DICT_SHARED(mp) _PyObject_GC_IS_SHARED(mp)
 #define SET_DICT_SHARED(mp) _PyObject_GC_SET_SHARED(mp)
@@ -227,6 +231,7 @@ static inline void split_keys_entry_added(PyDictKeysObject 
*keys)
 
 #define ASSERT_DICT_LOCKED(op)
 #define ASSERT_WORLD_STOPPED_OR_DICT_LOCKED(op)
+#define ASSERT_WORLD_STOPPED_OR_OBJ_LOCKED(op)
 #define LOCK_KEYS(keys)
 #define UNLOCK_KEYS(keys)
 #define ASSERT_KEYS_LOCKED(keys)
@@ -6667,10 +6672,10 @@ make_dict_from_instance_attributes(PyInterpreterState 
*interp,
 return res;
 }
 
-static PyDictObject *
-materialize_managed_dict_lock_held(PyObject *obj)
+PyDictObject *
+_PyObject_MaterializeManagedDict_LockHeld(PyObject *obj)
 {
-_Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(obj);
+ASSERT_WORLD_STOPPED_OR_OBJ_LOCKED(obj);
 
 PyDictValues *values = _PyObject_InlineValues(obj);
 PyInterpreterState *interp = _PyInterpreterState_GET();
@@ -6699,7 +6704,7 @@ _PyObject_MaterializeManagedDict(PyObject *obj)
 goto exit;
 }
 #endif
-dict = materialize_managed_dict_lock_held(obj);
+dict = _PyObject_MaterializeManagedDict_LockHeld(obj);
 
 #ifdef Py_GIL_DISABLED
 exit:
@@ -7132,7 +7137,7 @@ PyObject_ClearManagedDict(PyObject *obj)
 int
 _PyDict_DetachFromObject(PyDictObject *mp, PyObject *obj)
 {
-_Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(obj);
+ASSERT_WORLD_STOPPED_OR_OBJ_LOCKED(obj);
 assert(_PyObject_ManagedDictPointer(obj)->dict == mp);
 assert(_PyObject_InlineValuesConsistencyCheck(obj));
 
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index df895bc65983c0..587632cecfba9d 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -6540,28 +6540,11 @@ compatible_for_assignment(PyTypeObject* oldto, 
PyTypeObject* newto, const char*
 return 0;
 }
 
-static int
-object_set_class(PyObject *self, PyObject *value, void *closure)
-{
-
-if (value == NULL) {
-PyErr_SetString(PyExc_TypeError,
-"can't del

[Python-checkins] [3.13] gh-120198: Stop the world when setting __class__ on free-threaded build (#121591)

2024-07-12 Thread Fidget-Spinner
https://github.com/python/cpython/commit/cd74ed0a71f57e96bcd6c2a996587c58ef5da82d
commit: cd74ed0a71f57e96bcd6c2a996587c58ef5da82d
branch: 3.13
author: Ken Jin 
committer: Fidget-Spinner 
date: 2024-07-12T19:35:53+08:00
summary:

[3.13] gh-120198: Stop the world when setting __class__ on free-threaded build 
(#121591)

(cherry-picked from commit 3bfc9c8)

files:
M Include/internal/pycore_dict.h
M Include/object.h
M Lib/test/test_free_threading/test_type.py
M Objects/dictobject.c
M Objects/typeobject.c

diff --git a/Include/internal/pycore_dict.h b/Include/internal/pycore_dict.h
index 8d8d3748edaea8..01f80e21ba2797 100644
--- a/Include/internal/pycore_dict.h
+++ b/Include/internal/pycore_dict.h
@@ -323,6 +323,8 @@ _PyInlineValuesSize(PyTypeObject *tp)
 int
 _PyDict_DetachFromObject(PyDictObject *dict, PyObject *obj);
 
+PyDictObject *_PyObject_MaterializeManagedDict_LockHeld(PyObject *);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/Include/object.h b/Include/object.h
index fa9c2a51a95e0d..b4db7fb204fd7d 100644
--- a/Include/object.h
+++ b/Include/object.h
@@ -327,11 +327,7 @@ static inline Py_ssize_t Py_REFCNT(PyObject *ob) {
 
 // bpo-39573: The Py_SET_TYPE() function must be used to set an object type.
 static inline PyTypeObject* Py_TYPE(PyObject *ob) {
-#ifdef Py_GIL_DISABLED
-return (PyTypeObject *)_Py_atomic_load_ptr_relaxed(&ob->ob_type);
-#else
 return ob->ob_type;
-#endif
 }
 #if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b
 #  define Py_TYPE(ob) Py_TYPE(_PyObject_CAST(ob))
@@ -421,11 +417,7 @@ static inline void Py_SET_REFCNT(PyObject *ob, Py_ssize_t 
refcnt) {
 
 
 static inline void Py_SET_TYPE(PyObject *ob, PyTypeObject *type) {
-#ifdef Py_GIL_DISABLED
-_Py_atomic_store_ptr(&ob->ob_type, type);
-#else
 ob->ob_type = type;
-#endif
 }
 #if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b
 #  define Py_SET_TYPE(ob, type) Py_SET_TYPE(_PyObject_CAST(ob), type)
diff --git a/Lib/test/test_free_threading/test_type.py 
b/Lib/test/test_free_threading/test_type.py
index 1e84b2db2d4882..29ca929994cb79 100644
--- a/Lib/test/test_free_threading/test_type.py
+++ b/Lib/test/test_free_threading/test_type.py
@@ -106,7 +106,7 @@ class Bar:
 thing = Foo()
 def work():
 foo = thing
-for _ in range(1):
+for _ in range(5000):
 foo.__class__ = Bar
 type(foo)
 foo.__class__ = Foo
diff --git a/Objects/dictobject.c b/Objects/dictobject.c
index 3cd267556342ec..48aed1e4da8ffc 100644
--- a/Objects/dictobject.c
+++ b/Objects/dictobject.c
@@ -158,6 +158,10 @@ ASSERT_DICT_LOCKED(PyObject *op)
 if (!_PyInterpreterState_GET()->stoptheworld.world_stopped) {   \
 ASSERT_DICT_LOCKED(op); \
 }
+#define ASSERT_WORLD_STOPPED_OR_OBJ_LOCKED(op) \
+if (!_PyInterpreterState_GET()->stoptheworld.world_stopped) {  \
+_Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(op); \
+}
 
 #define IS_DICT_SHARED(mp) _PyObject_GC_IS_SHARED(mp)
 #define SET_DICT_SHARED(mp) _PyObject_GC_SET_SHARED(mp)
@@ -226,6 +230,7 @@ static inline void split_keys_entry_added(PyDictKeysObject 
*keys)
 
 #define ASSERT_DICT_LOCKED(op)
 #define ASSERT_WORLD_STOPPED_OR_DICT_LOCKED(op)
+#define ASSERT_WORLD_STOPPED_OR_OBJ_LOCKED(op)
 #define LOCK_KEYS(keys)
 #define UNLOCK_KEYS(keys)
 #define ASSERT_KEYS_LOCKED(keys)
@@ -6673,10 +6678,10 @@ make_dict_from_instance_attributes(PyInterpreterState 
*interp,
 return res;
 }
 
-static PyDictObject *
-materialize_managed_dict_lock_held(PyObject *obj)
+PyDictObject *
+_PyObject_MaterializeManagedDict_LockHeld(PyObject *obj)
 {
-_Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(obj);
+ASSERT_WORLD_STOPPED_OR_OBJ_LOCKED(obj);
 
 PyDictValues *values = _PyObject_InlineValues(obj);
 PyInterpreterState *interp = _PyInterpreterState_GET();
@@ -6705,7 +6710,7 @@ _PyObject_MaterializeManagedDict(PyObject *obj)
 goto exit;
 }
 #endif
-dict = materialize_managed_dict_lock_held(obj);
+dict = _PyObject_MaterializeManagedDict_LockHeld(obj);
 
 #ifdef Py_GIL_DISABLED
 exit:
@@ -7138,7 +7143,7 @@ PyObject_ClearManagedDict(PyObject *obj)
 int
 _PyDict_DetachFromObject(PyDictObject *mp, PyObject *obj)
 {
-_Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(obj);
+ASSERT_WORLD_STOPPED_OR_OBJ_LOCKED(obj);
 assert(_PyObject_ManagedDictPointer(obj)->dict == mp);
 assert(_PyObject_InlineValuesConsistencyCheck(obj));
 
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index edcdc6e9c4f5c2..1227f524a587bb 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -6378,28 +6378,11 @@ compatible_for_assignment(PyTypeObject* oldto, 
PyTypeObject* newto, const char*
 return 0;
 }
 
-static int
-object_set_class(PyObject *self, PyObject *value, void *closure)
-{
-
-if (value == NULL) {
-

[Python-checkins] gh-121546: Disable contextvar caching on free-threading build (GH-121740)

2024-07-15 Thread Fidget-Spinner
https://github.com/python/cpython/commit/e904300882055bed71cae59f8ca9161066659b7c
commit: e904300882055bed71cae59f8ca9161066659b7c
branch: main
author: Ken Jin 
committer: Fidget-Spinner 
date: 2024-07-16T02:57:58+08:00
summary:

gh-121546: Disable contextvar caching on free-threading build (GH-121740)

files:
M Include/internal/pycore_context.h
M Python/context.c

diff --git a/Include/internal/pycore_context.h 
b/Include/internal/pycore_context.h
index ae5c47f195eb7f..10c1f1e52be040 100644
--- a/Include/internal/pycore_context.h
+++ b/Include/internal/pycore_context.h
@@ -35,9 +35,11 @@ struct _pycontextvarobject {
 PyObject_HEAD
 PyObject *var_name;
 PyObject *var_default;
+#ifndef Py_GIL_DISABLED
 PyObject *var_cached;
 uint64_t var_cached_tsid;
 uint64_t var_cached_tsver;
+#endif
 Py_hash_t var_hash;
 };
 
diff --git a/Python/context.c b/Python/context.c
index a3830be17908fe..c32c15f5562f24 100644
--- a/Python/context.c
+++ b/Python/context.c
@@ -203,6 +203,7 @@ PyContextVar_Get(PyObject *ovar, PyObject *def, PyObject 
**val)
 goto not_found;
 }
 
+#ifndef Py_GIL_DISABLED
 if (var->var_cached != NULL &&
 var->var_cached_tsid == ts->id &&
 var->var_cached_tsver == ts->context_ver)
@@ -210,6 +211,7 @@ PyContextVar_Get(PyObject *ovar, PyObject *def, PyObject 
**val)
 *val = var->var_cached;
 goto found;
 }
+#endif
 
 assert(PyContext_CheckExact(ts->context));
 PyHamtObject *vars = ((PyContext *)ts->context)->ctx_vars;
@@ -221,9 +223,11 @@ PyContextVar_Get(PyObject *ovar, PyObject *def, PyObject 
**val)
 }
 if (res == 1) {
 assert(found != NULL);
+#ifndef Py_GIL_DISABLED
 var->var_cached = found;  /* borrow */
 var->var_cached_tsid = ts->id;
 var->var_cached_tsver = ts->context_ver;
+#endif
 
 *val = found;
 goto found;
@@ -723,8 +727,10 @@ PyTypeObject PyContext_Type = {
 static int
 contextvar_set(PyContextVar *var, PyObject *val)
 {
+#ifndef Py_GIL_DISABLED
 var->var_cached = NULL;
 PyThreadState *ts = _PyThreadState_GET();
+#endif
 
 PyContext *ctx = context_get();
 if (ctx == NULL) {
@@ -739,16 +745,20 @@ contextvar_set(PyContextVar *var, PyObject *val)
 
 Py_SETREF(ctx->ctx_vars, new_vars);
 
+#ifndef Py_GIL_DISABLED
 var->var_cached = val;  /* borrow */
 var->var_cached_tsid = ts->id;
 var->var_cached_tsver = ts->context_ver;
+#endif
 return 0;
 }
 
 static int
 contextvar_del(PyContextVar *var)
 {
+#ifndef Py_GIL_DISABLED
 var->var_cached = NULL;
+#endif
 
 PyContext *ctx = context_get();
 if (ctx == NULL) {
@@ -823,9 +833,11 @@ contextvar_new(PyObject *name, PyObject *def)
 
 var->var_default = Py_XNewRef(def);
 
+#ifndef Py_GIL_DISABLED
 var->var_cached = NULL;
 var->var_cached_tsid = 0;
 var->var_cached_tsver = 0;
+#endif
 
 if (_PyObject_GC_MAY_BE_TRACKED(name) ||
 (def != NULL && _PyObject_GC_MAY_BE_TRACKED(def)))
@@ -863,9 +875,11 @@ contextvar_tp_clear(PyContextVar *self)
 {
 Py_CLEAR(self->var_name);
 Py_CLEAR(self->var_default);
+#ifndef Py_GIL_DISABLED
 self->var_cached = NULL;
 self->var_cached_tsid = 0;
 self->var_cached_tsver = 0;
+#endif
 return 0;
 }
 

___
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com


[Python-checkins] gh-121621: Move asyncio running loop to thread state (GH-121695)

2024-07-16 Thread Fidget-Spinner
https://github.com/python/cpython/commit/69c68de43aef03dd52fabd21f99cb3b0f9329201
commit: 69c68de43aef03dd52fabd21f99cb3b0f9329201
branch: main
author: Ken Jin 
committer: Fidget-Spinner 
date: 2024-07-17T01:09:58+08:00
summary:

gh-121621: Move asyncio running loop to thread state (GH-121695)

files:
M Include/cpython/pystate.h
M Include/internal/pycore_global_objects_fini_generated.h
M Include/internal/pycore_global_strings.h
M Include/internal/pycore_runtime_init_generated.h
M Include/internal/pycore_unicodeobject_generated.h
M Modules/_asynciomodule.c
M Python/pystate.c

diff --git a/Include/cpython/pystate.h b/Include/cpython/pystate.h
index bb2af78a376d75..ce050424cccd49 100644
--- a/Include/cpython/pystate.h
+++ b/Include/cpython/pystate.h
@@ -68,6 +68,8 @@ struct _ts {
pycore_ceval.h. */
 uintptr_t eval_breaker;
 
+PyObject *asyncio_running_loop; // Strong reference
+
 struct {
 /* Has been initialized to a safe state.
 
diff --git a/Include/internal/pycore_global_objects_fini_generated.h 
b/Include/internal/pycore_global_objects_fini_generated.h
index c0840f9eb7eca2..d9b46df507dfd7 100644
--- a/Include/internal/pycore_global_objects_fini_generated.h
+++ b/Include/internal/pycore_global_objects_fini_generated.h
@@ -588,7 +588,6 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) {
 _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__annotate__));
 _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__annotations__));
 _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__args__));
-_PyStaticObject_CheckRefcnt((PyObject 
*)&_Py_ID(__asyncio_running_event_loop__));
 _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__await__));
 _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__bases__));
 _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__bool__));
diff --git a/Include/internal/pycore_global_strings.h 
b/Include/internal/pycore_global_strings.h
index 51735a8a726e11..10773d7a6c7e3f 100644
--- a/Include/internal/pycore_global_strings.h
+++ b/Include/internal/pycore_global_strings.h
@@ -77,7 +77,6 @@ struct _Py_global_strings {
 STRUCT_FOR_ID(__annotate__)
 STRUCT_FOR_ID(__annotations__)
 STRUCT_FOR_ID(__args__)
-STRUCT_FOR_ID(__asyncio_running_event_loop__)
 STRUCT_FOR_ID(__await__)
 STRUCT_FOR_ID(__bases__)
 STRUCT_FOR_ID(__bool__)
diff --git a/Include/internal/pycore_runtime_init_generated.h 
b/Include/internal/pycore_runtime_init_generated.h
index c5be67c6d80b9d..618f8d0a36b6c3 100644
--- a/Include/internal/pycore_runtime_init_generated.h
+++ b/Include/internal/pycore_runtime_init_generated.h
@@ -586,7 +586,6 @@ extern "C" {
 INIT_ID(__annotate__), \
 INIT_ID(__annotations__), \
 INIT_ID(__args__), \
-INIT_ID(__asyncio_running_event_loop__), \
 INIT_ID(__await__), \
 INIT_ID(__bases__), \
 INIT_ID(__bool__), \
diff --git a/Include/internal/pycore_unicodeobject_generated.h 
b/Include/internal/pycore_unicodeobject_generated.h
index 0e0ad6518771e9..f848a002c3b5d1 100644
--- a/Include/internal/pycore_unicodeobject_generated.h
+++ b/Include/internal/pycore_unicodeobject_generated.h
@@ -108,10 +108,6 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) {
 _PyUnicode_InternStatic(interp, &string);
 assert(_PyUnicode_CheckConsistency(string, 1));
 assert(PyUnicode_GET_LENGTH(string) != 1);
-string = &_Py_ID(__asyncio_running_event_loop__);
-_PyUnicode_InternStatic(interp, &string);
-assert(_PyUnicode_CheckConsistency(string, 1));
-assert(PyUnicode_GET_LENGTH(string) != 1);
 string = &_Py_ID(__await__);
 _PyUnicode_InternStatic(interp, &string);
 assert(_PyUnicode_CheckConsistency(string, 1));
diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c
index 5824c470699d88..31a45f8169be88 100644
--- a/Modules/_asynciomodule.c
+++ b/Modules/_asynciomodule.c
@@ -135,9 +135,6 @@ typedef struct {
 /* Imports from traceback. */
 PyObject *traceback_extract_stack;
 
-PyObject *cached_running_loop; // Borrowed reference
-volatile uint64_t cached_running_loop_tsid;
-
 /* Counter for autogenerated Task names */
 uint64_t task_name_counter;
 
@@ -321,101 +318,15 @@ get_future_loop(asyncio_state *state, PyObject *fut)
 return PyObject_GetAttr(fut, &_Py_ID(_loop));
 }
 
-
-static int
-get_running_loop(asyncio_state *state, PyObject **loop)
-{
-PyObject *rl;
-
-PyThreadState *ts = _PyThreadState_GET();
-uint64_t ts_id = PyThreadState_GetID(ts);
-if (state->cached_running_loop_tsid == ts_id &&
-state->cached_running_loop != NULL)
-{
-// Fast path, check the cache.
-rl = state->cached_running_loop;
-}
-else {
-PyObject *ts_dict = _PyThreadState_GetDict(ts);  // borrowed
-if (ts_dict == NULL) {
-goto not_found;
-}
-
-rl = PyDict

[Python-checkins] [3.13] gh-121621: Move asyncio running loop to thread state (GH-121695) (GH-121864)

2024-07-16 Thread Fidget-Spinner
https://github.com/python/cpython/commit/06d76c4b94f87b0785a96dbfa0904afc0b459cb7
commit: 06d76c4b94f87b0785a96dbfa0904afc0b459cb7
branch: 3.13
author: Miss Islington (bot) <31488909+miss-isling...@users.noreply.github.com>
committer: Fidget-Spinner 
date: 2024-07-17T01:57:37+08:00
summary:

[3.13] gh-121621: Move asyncio running loop to thread state (GH-121695) 
(GH-121864)

gh-121621: Move asyncio running loop to thread state (GH-121695)
(cherry picked from commit 69c68de43aef03dd52fabd21f99cb3b0f9329201)

Co-authored-by: Ken Jin 

files:
M Include/cpython/pystate.h
M Include/internal/pycore_global_objects_fini_generated.h
M Include/internal/pycore_global_strings.h
M Include/internal/pycore_runtime_init_generated.h
M Include/internal/pycore_unicodeobject_generated.h
M Modules/_asynciomodule.c
M Python/pystate.c

diff --git a/Include/cpython/pystate.h b/Include/cpython/pystate.h
index bb2af78a376d75..ce050424cccd49 100644
--- a/Include/cpython/pystate.h
+++ b/Include/cpython/pystate.h
@@ -68,6 +68,8 @@ struct _ts {
pycore_ceval.h. */
 uintptr_t eval_breaker;
 
+PyObject *asyncio_running_loop; // Strong reference
+
 struct {
 /* Has been initialized to a safe state.
 
diff --git a/Include/internal/pycore_global_objects_fini_generated.h 
b/Include/internal/pycore_global_objects_fini_generated.h
index 16cb4793ad1d08..006dd911b5a8ef 100644
--- a/Include/internal/pycore_global_objects_fini_generated.h
+++ b/Include/internal/pycore_global_objects_fini_generated.h
@@ -586,7 +586,6 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) {
 _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__anext__));
 _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__annotations__));
 _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__args__));
-_PyStaticObject_CheckRefcnt((PyObject 
*)&_Py_ID(__asyncio_running_event_loop__));
 _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__await__));
 _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__bases__));
 _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__bool__));
diff --git a/Include/internal/pycore_global_strings.h 
b/Include/internal/pycore_global_strings.h
index 1e76853297150b..a5436b6d689612 100644
--- a/Include/internal/pycore_global_strings.h
+++ b/Include/internal/pycore_global_strings.h
@@ -75,7 +75,6 @@ struct _Py_global_strings {
 STRUCT_FOR_ID(__anext__)
 STRUCT_FOR_ID(__annotations__)
 STRUCT_FOR_ID(__args__)
-STRUCT_FOR_ID(__asyncio_running_event_loop__)
 STRUCT_FOR_ID(__await__)
 STRUCT_FOR_ID(__bases__)
 STRUCT_FOR_ID(__bool__)
diff --git a/Include/internal/pycore_runtime_init_generated.h 
b/Include/internal/pycore_runtime_init_generated.h
index f4d0ee4122ea2f..6e62ecd4b3a815 100644
--- a/Include/internal/pycore_runtime_init_generated.h
+++ b/Include/internal/pycore_runtime_init_generated.h
@@ -584,7 +584,6 @@ extern "C" {
 INIT_ID(__anext__), \
 INIT_ID(__annotations__), \
 INIT_ID(__args__), \
-INIT_ID(__asyncio_running_event_loop__), \
 INIT_ID(__await__), \
 INIT_ID(__bases__), \
 INIT_ID(__bool__), \
diff --git a/Include/internal/pycore_unicodeobject_generated.h 
b/Include/internal/pycore_unicodeobject_generated.h
index e1bc9cf1c7bd6e..5337390309548b 100644
--- a/Include/internal/pycore_unicodeobject_generated.h
+++ b/Include/internal/pycore_unicodeobject_generated.h
@@ -104,10 +104,6 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) {
 _PyUnicode_InternStatic(interp, &string);
 assert(_PyUnicode_CheckConsistency(string, 1));
 assert(PyUnicode_GET_LENGTH(string) != 1);
-string = &_Py_ID(__asyncio_running_event_loop__);
-_PyUnicode_InternStatic(interp, &string);
-assert(_PyUnicode_CheckConsistency(string, 1));
-assert(PyUnicode_GET_LENGTH(string) != 1);
 string = &_Py_ID(__await__);
 _PyUnicode_InternStatic(interp, &string);
 assert(_PyUnicode_CheckConsistency(string, 1));
diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c
index 92d0e6de0dfb93..ab72cc2fe55637 100644
--- a/Modules/_asynciomodule.c
+++ b/Modules/_asynciomodule.c
@@ -68,9 +68,6 @@ typedef struct {
 /* Imports from traceback. */
 PyObject *traceback_extract_stack;
 
-PyObject *cached_running_loop; // Borrowed reference
-volatile uint64_t cached_running_loop_tsid;
-
 /* Counter for autogenerated Task names */
 uint64_t task_name_counter;
 
@@ -262,101 +259,15 @@ get_future_loop(asyncio_state *state, PyObject *fut)
 return PyObject_GetAttr(fut, &_Py_ID(_loop));
 }
 
-
-static int
-get_running_loop(asyncio_state *state, PyObject **loop)
-{
-PyObject *rl;
-
-PyThreadState *ts = _PyThreadState_GET();
-uint64_t ts_id = PyThreadState_GetID(ts);
-if (state->cached_running_loop_tsid == ts_id &&
-state->cached_running_loop != NULL)
-{
-// Fast path, check the cac

[Python-checkins] [3.12] Check for valid tp_version_tag in specializer (gh-89811) (gh-114216)

2024-01-19 Thread Fidget-Spinner
https://github.com/python/cpython/commit/ae2a25bf607410bb87d0b0c556adc7f56ec73fa9
commit: ae2a25bf607410bb87d0b0c556adc7f56ec73fa9
branch: 3.12
author: Peter Lazorchak 
committer: Fidget-Spinner 
date: 2024-01-20T04:45:33+08:00
summary:

[3.12] Check for valid tp_version_tag in specializer (gh-89811) (gh-114216)

files:
A Misc/NEWS.d/next/Core and 
Builtins/2024-01-03-12-19-37.gh-issue-89811.cZOj6d.rst
M Lib/test/test_type_cache.py
M Modules/_testcapimodule.c
M Python/specialize.c

diff --git a/Lib/test/test_type_cache.py b/Lib/test/test_type_cache.py
index 72587ecc11b6f3..2ebaa47fd03a08 100644
--- a/Lib/test/test_type_cache.py
+++ b/Lib/test/test_type_cache.py
@@ -1,5 +1,6 @@
 """ Tests for the internal type cache in CPython. """
 import unittest
+import dis
 from test import support
 from test.support import import_helper
 try:
@@ -8,8 +9,11 @@
 _clear_type_cache = None
 
 # Skip this test if the _testcapi module isn't available.
-type_get_version = import_helper.import_module('_testcapi').type_get_version
-type_assign_version = 
import_helper.import_module('_testcapi').type_assign_version
+_testcapi = import_helper.import_module("_testcapi")
+type_get_version = _testcapi.type_get_version
+type_assign_specific_version_unsafe = 
_testcapi.type_assign_specific_version_unsafe
+type_assign_version = _testcapi.type_assign_version
+type_modified = _testcapi.type_modified
 
 
 @support.cpython_only
@@ -56,6 +60,144 @@ class C:
 self.assertNotEqual(type_get_version(C), 0)
 self.assertNotEqual(type_get_version(C), c_ver)
 
+def test_type_assign_specific_version(self):
+"""meta-test for type_assign_specific_version_unsafe"""
+class C:
+pass
+
+type_assign_version(C)
+orig_version = type_get_version(C)
+if orig_version == 0:
+self.skipTest("Could not assign a valid type version")
+
+type_modified(C)
+type_assign_specific_version_unsafe(C, orig_version + 5)
+type_assign_version(C)  # this should do nothing
+
+new_version = type_get_version(C)
+self.assertEqual(new_version, orig_version + 5)
+
+_clear_type_cache()
+
+
+@support.cpython_only
+class TypeCacheWithSpecializationTests(unittest.TestCase):
+def tearDown(self):
+_clear_type_cache()
+
+def _assign_valid_version_or_skip(self, type_):
+type_modified(type_)
+type_assign_version(type_)
+if type_get_version(type_) == 0:
+self.skipTest("Could not assign valid type version")
+
+def _assign_and_check_version_0(self, user_type):
+type_modified(user_type)
+type_assign_specific_version_unsafe(user_type, 0)
+self.assertEqual(type_get_version(user_type), 0)
+
+def _all_opnames(self, func):
+return set(instr.opname for instr in dis.Bytecode(func, adaptive=True))
+
+def _check_specialization(self, func, arg, opname, *, should_specialize):
+for _ in range(100):
+func(arg)
+
+if should_specialize:
+self.assertNotIn(opname, self._all_opnames(func))
+else:
+self.assertIn(opname, self._all_opnames(func))
+
+def test_class_load_attr_specialization_user_type(self):
+class A:
+def foo(self):
+pass
+
+self._assign_valid_version_or_skip(A)
+
+def load_foo_1(type_):
+type_.foo
+
+self._check_specialization(load_foo_1, A, "LOAD_ATTR", 
should_specialize=True)
+del load_foo_1
+
+self._assign_and_check_version_0(A)
+
+def load_foo_2(type_):
+return type_.foo
+
+self._check_specialization(load_foo_2, A, "LOAD_ATTR", 
should_specialize=False)
+
+def test_class_load_attr_specialization_static_type(self):
+self._assign_valid_version_or_skip(str)
+self._assign_valid_version_or_skip(bytes)
+
+def get_capitalize_1(type_):
+return type_.capitalize
+
+self._check_specialization(get_capitalize_1, str, "LOAD_ATTR", 
should_specialize=True)
+self.assertEqual(get_capitalize_1(str)('hello'), 'Hello')
+self.assertEqual(get_capitalize_1(bytes)(b'hello'), b'Hello')
+del get_capitalize_1
+
+# Permanently overflow the static type version counter, and force str 
and bytes
+# to have tp_version_tag == 0
+for _ in range(2**16):
+type_modified(str)
+type_assign_version(str)
+type_modified(bytes)
+type_assign_version(bytes)
+
+self.assertEqual(type_get_version(str), 0)
+self.assertEqual(type_get_version(bytes), 0)
+
+def get_capitalize_2(type_):
+return type_.capitalize
+
+self._check_specialization(get_capitalize_2, str, &q

[Python-checkins] [3.11] gh-89811: Check for valid tp_version_tag in specializer (GH-115045)

2024-02-06 Thread Fidget-Spinner
https://github.com/python/cpython/commit/a11312456d05a06feed00ee9e530e50fcadb7011
commit: a11312456d05a06feed00ee9e530e50fcadb7011
branch: 3.11
author: Peter Lazorchak 
committer: Fidget-Spinner 
date: 2024-02-06T21:58:30+08:00
summary:

[3.11] gh-89811: Check for valid tp_version_tag in specializer (GH-115045)

* gh-89811: Check for valid tp_version_tag in specializer (GH-113558)

* gh-113937 Fix failures in type cache tests due to re-running (GH-113953)

* Update backported code for 3.11 specifically

files:
A Misc/NEWS.d/next/Core and 
Builtins/2024-01-03-12-19-37.gh-issue-89811.cZOj6d.rst
M Lib/test/test_type_cache.py
M Modules/_testcapimodule.c
M Python/specialize.c

diff --git a/Lib/test/test_type_cache.py b/Lib/test/test_type_cache.py
index 9dc91dc93448ad..11158f9c565c46 100644
--- a/Lib/test/test_type_cache.py
+++ b/Lib/test/test_type_cache.py
@@ -1,5 +1,6 @@
 """ Tests for the internal type cache in CPython. """
 import unittest
+import dis
 from test import support
 from test.support import import_helper
 try:
@@ -8,7 +9,17 @@
 _clear_type_cache = None
 
 # Skip this test if the _testcapi module isn't available.
-type_get_version = import_helper.import_module('_testcapi').type_get_version
+_testcapi = import_helper.import_module("_testcapi")
+type_get_version = _testcapi.type_get_version
+type_assign_specific_version_unsafe = 
_testcapi.type_assign_specific_version_unsafe
+type_modified = _testcapi.type_modified
+
+
+def type_assign_version(type_):
+try:
+type_.x
+except AttributeError:
+pass
 
 
 @support.cpython_only
@@ -42,6 +53,151 @@ def test_tp_version_tag_unique(self):
 self.assertEqual(len(set(all_version_tags)), 30,
  msg=f"{all_version_tags} contains non-unique 
versions")
 
+def test_type_assign_specific_version(self):
+"""meta-test for type_assign_specific_version_unsafe"""
+class C:
+pass
+
+type_assign_version(C)
+orig_version = type_get_version(C)
+if orig_version == 0:
+self.skipTest("Could not assign a valid type version")
+
+type_modified(C)
+type_assign_specific_version_unsafe(C, orig_version + 5)
+type_assign_version(C)  # this should do nothing
+
+new_version = type_get_version(C)
+self.assertEqual(new_version, orig_version + 5)
+
+_clear_type_cache()
+
+
+@support.cpython_only
+class TypeCacheWithSpecializationTests(unittest.TestCase):
+def tearDown(self):
+_clear_type_cache()
+
+def _assign_valid_version_or_skip(self, type_):
+type_modified(type_)
+type_assign_version(type_)
+if type_get_version(type_) == 0:
+self.skipTest("Could not assign valid type version")
+
+def _assign_and_check_version_0(self, user_type):
+type_modified(user_type)
+type_assign_specific_version_unsafe(user_type, 0)
+self.assertEqual(type_get_version(user_type), 0)
+
+def _all_opnames(self, func):
+return set(instr.opname for instr in dis.Bytecode(func, adaptive=True))
+
+def _check_specialization(self, func, arg, opname, *, should_specialize):
+for _ in range(100):
+func(arg)
+
+if should_specialize:
+self.assertNotIn(opname, self._all_opnames(func))
+else:
+self.assertIn(opname, self._all_opnames(func))
+
+def test_load_method_specialization_user_type(self):
+class A:
+def foo(self):
+pass
+
+self._assign_valid_version_or_skip(A)
+
+def load_foo_1(instance):
+instance.foo()
+
+self._check_specialization(
+load_foo_1, A(), "LOAD_METHOD_ADAPTIVE", should_specialize=True
+)
+del load_foo_1
+
+self._assign_and_check_version_0(A)
+
+def load_foo_2(instance):
+instance.foo()
+
+self._check_specialization(
+load_foo_2, A(), "LOAD_METHOD_ADAPTIVE", should_specialize=False
+)
+
+def test_store_attr_specialization_user_type(self):
+class B:
+__slots__ = ("bar",)
+
+self._assign_valid_version_or_skip(B)
+
+def store_bar_1(instance):
+instance.bar = 10
+
+self._check_specialization(
+store_bar_1, B(), "STORE_ATTR_ADAPTIVE", should_specialize=True
+)
+del store_bar_1
+
+self._assign_and_check_version_0(B)
+
+def store_bar_2(instance):
+instance.bar = 10
+
+self._check_specialization(
+store_bar_2, B(), "STORE_ATTR_ADAPTIVE", should_specialize=False
+)
+
+def test_load_attr_specialization_user_type(self):
+class C:
+__slots__ = ("biz",)
+def __init__(self):
+self.b

[Python-checkins] Add Peter L to ACKS (GH-115222)

2024-02-09 Thread Fidget-Spinner
https://github.com/python/cpython/commit/5a173efa693a053bf4a059c82c1c06c82a9fa8fb
commit: 5a173efa693a053bf4a059c82c1c06c82a9fa8fb
branch: main
author: Peter Lazorchak 
committer: Fidget-Spinner 
date: 2024-02-10T01:06:14+08:00
summary:

Add Peter L to ACKS (GH-115222)

files:
M Misc/ACKS

diff --git a/Misc/ACKS b/Misc/ACKS
index 466023f390a421..8a80e02ecba26a 100644
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -1051,6 +1051,7 @@ Mark Lawrence
 Chris Laws
 Michael Layzell
 Michael Lazar
+Peter Lazorchak
 Brian Leair
 Mathieu Leduc-Hamel
 Amandine Lee

___
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com


[Python-checkins] gh-114058: Foundations of the Tier2 redundancy eliminator (GH-115085)

2024-02-13 Thread Fidget-Spinner
https://github.com/python/cpython/commit/7cce8576226249461baa91c4a89770a1823b44a4
commit: 7cce8576226249461baa91c4a89770a1823b44a4
branch: main
author: Ken Jin 
committer: Fidget-Spinner 
date: 2024-02-13T21:24:48+08:00
summary:

gh-114058: Foundations of the Tier2 redundancy eliminator (GH-115085)

-

Co-authored-by: Mark Shannon <9448417+markshan...@users.noreply.github.com>
Co-authored-by: Jules <57632293+julia...@users.noreply.github.com>
Co-authored-by: Guido van Rossum 

files:
A Misc/NEWS.d/next/Core and 
Builtins/2024-01-16-14-41-54.gh-issue-114058.Cb2b8h.rst
A Python/tier2_redundancy_eliminator_bytecodes.c
A Python/tier2_redundancy_eliminator_cases.c.h
A Tools/cases_generator/tier2_abstract_generator.py
M .gitattributes
M Include/cpython/pystats.h
M Include/internal/pycore_opcode_metadata.h
M Include/internal/pycore_optimizer.h
M Include/internal/pycore_uop_metadata.h
M Lib/test/test_capi/test_opt.py
M Lib/test/test_generated_cases.py
M Makefile.pre.in
M Python/bytecodes.c
M Python/executor_cases.c.h
M Python/generated_cases.c.h
M Python/optimizer.c
M Python/optimizer_analysis.c
M Python/specialize.c
M Tools/c-analyzer/cpython/_parser.py
M Tools/c-analyzer/cpython/ignored.tsv
M Tools/cases_generator/README.md
M Tools/cases_generator/analyzer.py
M Tools/cases_generator/interpreter_definition.md
M Tools/cases_generator/parsing.py
M Tools/cases_generator/stack.py

diff --git a/.gitattributes b/.gitattributes
index 2a48df079e1aeb..07d877027b09f6 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -94,6 +94,7 @@ Programs/test_frozenmain.h  generated
 Python/Python-ast.c generated
 Python/executor_cases.c.h   generated
 Python/generated_cases.c.h  generated
+Python/tier2_redundancy_eliminator_bytecodes.c.hgenerated
 Python/opcode_targets.h generated
 Python/stdlib_module_names.hgenerated
 Tools/peg_generator/pegen/grammar_parser.py generated
diff --git a/Include/cpython/pystats.h b/Include/cpython/pystats.h
index 0f50439b73848e..db9aaedec950e4 100644
--- a/Include/cpython/pystats.h
+++ b/Include/cpython/pystats.h
@@ -120,6 +120,9 @@ typedef struct _optimization_stats {
 uint64_t trace_length_hist[_Py_UOP_HIST_SIZE];
 uint64_t trace_run_length_hist[_Py_UOP_HIST_SIZE];
 uint64_t optimized_trace_length_hist[_Py_UOP_HIST_SIZE];
+uint64_t optimizer_attempts;
+uint64_t optimizer_successes;
+uint64_t optimizer_failure_reason_no_memory;
 } OptimizationStats;
 
 typedef struct _rare_event_stats {
diff --git a/Include/internal/pycore_opcode_metadata.h 
b/Include/internal/pycore_opcode_metadata.h
index 75d7f44025328e..6b60a6fbffdc5e 100644
--- a/Include/internal/pycore_opcode_metadata.h
+++ b/Include/internal/pycore_opcode_metadata.h
@@ -1094,7 +1094,7 @@ const struct opcode_metadata 
_PyOpcode_opcode_metadata[268] = {
 [MATCH_KEYS] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
 [MATCH_MAPPING] = { true, INSTR_FMT_IX, 0 },
 [MATCH_SEQUENCE] = { true, INSTR_FMT_IX, 0 },
-[NOP] = { true, INSTR_FMT_IX, 0 },
+[NOP] = { true, INSTR_FMT_IX, HAS_PURE_FLAG },
 [POP_EXCEPT] = { true, INSTR_FMT_IX, HAS_ESCAPES_FLAG },
 [POP_JUMP_IF_FALSE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG 
},
 [POP_JUMP_IF_NONE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG },
@@ -1156,10 +1156,10 @@ const struct opcode_metadata 
_PyOpcode_opcode_metadata[268] = {
 [LOAD_SUPER_METHOD] = { true, -1, HAS_ARG_FLAG | HAS_NAME_FLAG | 
HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
 [LOAD_ZERO_SUPER_ATTR] = { true, -1, HAS_ARG_FLAG | HAS_NAME_FLAG | 
HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
 [LOAD_ZERO_SUPER_METHOD] = { true, -1, HAS_ARG_FLAG | HAS_NAME_FLAG | 
HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
-[POP_BLOCK] = { true, -1, 0 },
-[SETUP_CLEANUP] = { true, -1, HAS_ARG_FLAG },
-[SETUP_FINALLY] = { true, -1, HAS_ARG_FLAG },
-[SETUP_WITH] = { true, -1, HAS_ARG_FLAG },
+[POP_BLOCK] = { true, -1, HAS_PURE_FLAG },
+[SETUP_CLEANUP] = { true, -1, HAS_PURE_FLAG | HAS_ARG_FLAG },
+[SETUP_FINALLY] = { true, -1, HAS_PURE_FLAG | HAS_ARG_FLAG },
+[SETUP_WITH] = { true, -1, HAS_PURE_FLAG | HAS_ARG_FLAG },
 [STORE_FAST_MAYBE_NULL] = { true, -1, HAS_ARG_FLAG | HAS_LOCAL_FLAG },
 };
 #endif
diff --git a/Include/internal/pycore_optimizer.h 
b/Include/internal/pycore_optimizer.h
index e21412fc815540..eee71c700d4904 100644
--- a/Include/internal/pycore_optimizer.h
+++ b/Include/internal/pycore_optimizer.h
@@ -8,6 +8,13 @@ extern "C" {
 #  error "this header requires Py_BUILD_CORE define"
 #endif
 
+#include "pycore_uop_ids.h"
+
+// This is the length of the trace we project initially.
+#define UOP_MAX_TRACE_LENGTH 512
+
+#define TRACE_STACK_SIZE 5
+
 int _Py_uop_analyze_and_optimize(_PyInterpreterFrame *frame,
 _PyUOpInstruction *t

[Python-checkins] Add myself to various CODEOWNERS (GH-115481)

2024-02-14 Thread Fidget-Spinner
https://github.com/python/cpython/commit/d9f4cbe5e1e3c31518724d87d0d379d7ce6823ca
commit: d9f4cbe5e1e3c31518724d87d0d379d7ce6823ca
branch: main
author: Ken Jin 
committer: Fidget-Spinner 
date: 2024-02-15T03:48:11+08:00
summary:

Add myself to various CODEOWNERS (GH-115481)

files:
M .github/CODEOWNERS

diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index 7933d319550576..5dbfbbb8ebaf7e 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -37,6 +37,8 @@ Python/flowgraph.c@markshannon @iritkatriel
 Python/ast_opt.c  @isidentical
 Python/bytecodes.c@markshannon @gvanrossum
 Python/optimizer*.c   @markshannon @gvanrossum
+Python/optimizer_analysis.c   @Fidget-Spinner
+Python/tier2_redundancy_eliminator_bytecodes.c  @Fidget-Spinner
 Lib/test/test_patma.py@brandtbucher
 Lib/test/test_type_*.py   @JelleZijlstra
 Lib/test/test_capi/test_misc.py  @markshannon @gvanrossum

___
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com


[Python-checkins] Trigger JIT CI with optimizer files (#115483)

2024-02-14 Thread Fidget-Spinner
https://github.com/python/cpython/commit/ed23839dc5ce21ea9ca087fac170fa1412005210
commit: ed23839dc5ce21ea9ca087fac170fa1412005210
branch: main
author: Ken Jin 
committer: Fidget-Spinner 
date: 2024-02-15T14:01:24+08:00
summary:

Trigger JIT CI with optimizer files (#115483)

* Trigger JIT CI with optimizer files

files:
M .github/workflows/jit.yml

diff --git a/.github/workflows/jit.yml b/.github/workflows/jit.yml
index 69648d87947ad6..69c7b45376a411 100644
--- a/.github/workflows/jit.yml
+++ b/.github/workflows/jit.yml
@@ -4,10 +4,14 @@ on:
 paths:
   - '**jit**'
   - 'Python/bytecodes.c'
+  - 'Python/optimizer*.c'
+  - 'Python/tier2_redundancy_eliminator_bytecodes.c'
   push:
 paths:
   - '**jit**'
   - 'Python/bytecodes.c'
+  - 'Python/optimizer*.c'
+  - 'Python/tier2_redundancy_eliminator_bytecodes.c'
   workflow_dispatch:
 
 concurrency:

___
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com


[Python-checkins] gh-115480: Type and constant propagation for int BINARY_OPs (GH-115478)

2024-02-14 Thread Fidget-Spinner
https://github.com/python/cpython/commit/4ebf8fbdab1c64041ff0ea54b3d15624f6e01511
commit: 4ebf8fbdab1c64041ff0ea54b3d15624f6e01511
branch: main
author: Ken Jin 
committer: Fidget-Spinner 
date: 2024-02-15T14:02:18+08:00
summary:

gh-115480: Type and constant propagation for int BINARY_OPs (GH-115478)

files:
M Python/optimizer_analysis.c
M Python/tier2_redundancy_eliminator_bytecodes.c
M Python/tier2_redundancy_eliminator_cases.c.h

diff --git a/Python/optimizer_analysis.c b/Python/optimizer_analysis.c
index 49974520de924d..d73bc310345f41 100644
--- a/Python/optimizer_analysis.c
+++ b/Python/optimizer_analysis.c
@@ -341,6 +341,18 @@ sym_new_const(_Py_UOpsAbstractInterpContext *ctx, PyObject 
*const_val)
 return temp;
 }
 
+static inline bool
+is_const(_Py_UOpsSymType *sym)
+{
+return sym->const_val != NULL;
+}
+
+static inline PyObject *
+get_const(_Py_UOpsSymType *sym)
+{
+return sym->const_val;
+}
+
 static _Py_UOpsSymType*
 sym_new_null(_Py_UOpsAbstractInterpContext *ctx)
 {
diff --git a/Python/tier2_redundancy_eliminator_bytecodes.c 
b/Python/tier2_redundancy_eliminator_bytecodes.c
index 3272b187f20d0e..39ea0eef627632 100644
--- a/Python/tier2_redundancy_eliminator_bytecodes.c
+++ b/Python/tier2_redundancy_eliminator_bytecodes.c
@@ -81,12 +81,62 @@ dummy_func(void) {
 
 
 op(_BINARY_OP_ADD_INT, (left, right -- res)) {
-// TODO constant propagation
-(void)left;
-(void)right;
-res = sym_new_known_type(ctx, &PyLong_Type);
-if (res == NULL) {
-goto out_of_space;
+if (is_const(left) && is_const(right)) {
+assert(PyLong_CheckExact(get_const(left)));
+assert(PyLong_CheckExact(get_const(right)));
+PyObject *temp = _PyLong_Add((PyLongObject *)get_const(left),
+ (PyLongObject *)get_const(right));
+if (temp == NULL) {
+goto error;
+}
+res = sym_new_const(ctx, temp);
+// TODO replace opcode with constant propagated one and add tests!
+}
+else {
+res = sym_new_known_type(ctx, &PyLong_Type);
+if (res == NULL) {
+goto out_of_space;
+}
+}
+}
+
+op(_BINARY_OP_SUBTRACT_INT, (left, right -- res)) {
+if (is_const(left) && is_const(right)) {
+assert(PyLong_CheckExact(get_const(left)));
+assert(PyLong_CheckExact(get_const(right)));
+PyObject *temp = _PyLong_Subtract((PyLongObject *)get_const(left),
+  (PyLongObject 
*)get_const(right));
+if (temp == NULL) {
+goto error;
+}
+res = sym_new_const(ctx, temp);
+// TODO replace opcode with constant propagated one and add tests!
+}
+else {
+res = sym_new_known_type(ctx, &PyLong_Type);
+if (res == NULL) {
+goto out_of_space;
+}
+}
+}
+
+op(_BINARY_OP_MULTIPLY_INT, (left, right -- res)) {
+if (is_const(left) && is_const(right)) {
+assert(PyLong_CheckExact(get_const(left)));
+assert(PyLong_CheckExact(get_const(right)));
+PyObject *temp = _PyLong_Multiply((PyLongObject *)get_const(left),
+  (PyLongObject 
*)get_const(right));
+if (temp == NULL) {
+goto error;
+}
+res = sym_new_const(ctx, temp);
+// TODO replace opcode with constant propagated one and add tests!
+}
+else {
+res = sym_new_known_type(ctx, &PyLong_Type);
+if (res == NULL) {
+goto out_of_space;
+}
 }
 }
 
diff --git a/Python/tier2_redundancy_eliminator_cases.c.h 
b/Python/tier2_redundancy_eliminator_cases.c.h
index c2b7bbaf1c4481..a9617f51ef4615 100644
--- a/Python/tier2_redundancy_eliminator_cases.c.h
+++ b/Python/tier2_redundancy_eliminator_cases.c.h
@@ -180,9 +180,28 @@
 }
 
 case _BINARY_OP_MULTIPLY_INT: {
+_Py_UOpsSymType *right;
+_Py_UOpsSymType *left;
 _Py_UOpsSymType *res;
-res = sym_new_unknown(ctx);
-if (res == NULL) goto out_of_space;
+right = stack_pointer[-1];
+left = stack_pointer[-2];
+if (is_const(left) && is_const(right)) {
+assert(PyLong_CheckExact(get_const(left)));
+assert(PyLong_CheckExact(get_const(right)));
+PyObject *temp = _PyLong_Multiply((PyLongObject 
*)get_const(left),
+(PyLongObject *)get_const(right));
+if (temp == NULL) {
+goto error;
+}
+res = sym_new_const(ctx, temp);
+// TODO replace opcode with constant propagate

[Python-checkins] gh-115480: Minor fixups in int constant propagation (GH-115507)

2024-02-16 Thread Fidget-Spinner
https://github.com/python/cpython/commit/f92857a93016aa26ba93959d2bdb690ef52e7f07
commit: f92857a93016aa26ba93959d2bdb690ef52e7f07
branch: main
author: Ken Jin 
committer: Fidget-Spinner 
date: 2024-02-16T22:59:43+08:00
summary:

gh-115480: Minor fixups in int constant propagation (GH-115507)

files:
M Python/optimizer_analysis.c
M Python/tier2_redundancy_eliminator_bytecodes.c
M Python/tier2_redundancy_eliminator_cases.c.h

diff --git a/Python/optimizer_analysis.c b/Python/optimizer_analysis.c
index d73bc310345f41..b104d2fa7baec9 100644
--- a/Python/optimizer_analysis.c
+++ b/Python/optimizer_analysis.c
@@ -588,16 +588,17 @@ remove_globals(_PyInterpreterFrame *frame, 
_PyUOpInstruction *buffer,
 INST->oparg = ARG;\
 INST->operand = OPERAND;
 
+#define OUT_OF_SPACE_IF_NULL(EXPR) \
+do {   \
+if ((EXPR) == NULL) {  \
+goto out_of_space; \
+}  \
+} while (0);
+
 #define _LOAD_ATTR_NOT_NULL \
 do {\
-attr = sym_new_known_notnull(ctx); \
-if (attr == NULL) { \
-goto error; \
-} \
-null = sym_new_null(ctx); \
-if (null == NULL) { \
-goto error; \
-} \
+OUT_OF_SPACE_IF_NULL(attr = sym_new_known_notnull(ctx)); \
+OUT_OF_SPACE_IF_NULL(null = sym_new_null(ctx)); \
 } while (0);
 
 
diff --git a/Python/tier2_redundancy_eliminator_bytecodes.c 
b/Python/tier2_redundancy_eliminator_bytecodes.c
index 39ea0eef627632..6aae590a8e51e4 100644
--- a/Python/tier2_redundancy_eliminator_bytecodes.c
+++ b/Python/tier2_redundancy_eliminator_bytecodes.c
@@ -43,10 +43,8 @@ dummy_func(void) {
 
 op(_LOAD_FAST_AND_CLEAR, (-- value)) {
 value = GETLOCAL(oparg);
-_Py_UOpsSymType *temp = sym_new_null(ctx);
-if (temp == NULL) {
-goto out_of_space;
-}
+_Py_UOpsSymType *temp;
+OUT_OF_SPACE_IF_NULL(temp = sym_new_null(ctx));
 GETLOCAL(oparg) = temp;
 }
 
@@ -89,14 +87,12 @@ dummy_func(void) {
 if (temp == NULL) {
 goto error;
 }
-res = sym_new_const(ctx, temp);
-// TODO replace opcode with constant propagated one and add tests!
+OUT_OF_SPACE_IF_NULL(res = sym_new_const(ctx, temp));
+// TODO gh-115506:
+// replace opcode with constant propagated one and add tests!
 }
 else {
-res = sym_new_known_type(ctx, &PyLong_Type);
-if (res == NULL) {
-goto out_of_space;
-}
+OUT_OF_SPACE_IF_NULL(res = sym_new_known_type(ctx, &PyLong_Type));
 }
 }
 
@@ -109,14 +105,12 @@ dummy_func(void) {
 if (temp == NULL) {
 goto error;
 }
-res = sym_new_const(ctx, temp);
-// TODO replace opcode with constant propagated one and add tests!
+OUT_OF_SPACE_IF_NULL(res = sym_new_const(ctx, temp));
+// TODO gh-115506:
+// replace opcode with constant propagated one and add tests!
 }
 else {
-res = sym_new_known_type(ctx, &PyLong_Type);
-if (res == NULL) {
-goto out_of_space;
-}
+OUT_OF_SPACE_IF_NULL(res = sym_new_known_type(ctx, &PyLong_Type));
 }
 }
 
@@ -129,14 +123,12 @@ dummy_func(void) {
 if (temp == NULL) {
 goto error;
 }
-res = sym_new_const(ctx, temp);
-// TODO replace opcode with constant propagated one and add tests!
+OUT_OF_SPACE_IF_NULL(res = sym_new_const(ctx, temp));
+// TODO gh-115506:
+// replace opcode with constant propagated one and add tests!
 }
 else {
-res = sym_new_known_type(ctx, &PyLong_Type);
-if (res == NULL) {
-goto out_of_space;
-}
+OUT_OF_SPACE_IF_NULL(res = sym_new_known_type(ctx, &PyLong_Type));
 }
 }
 
@@ -147,39 +139,21 @@ dummy_func(void) {
 }
 
 op(_LOAD_CONST_INLINE, (ptr/4 -- value)) {
-value = sym_new_const(ctx, ptr);
-if (value == NULL) {
-goto out_of_space;
-}
+OUT_OF_SPACE_IF_NULL(value = sym_new_const(ctx, ptr));
 }
 
 op(_LOAD_CONST_INLINE_BORROW, (ptr/4 -- value)) {
-value = sym_new_const(ctx, ptr);
-if (value == NULL) {
-goto out_of_space;
-}
+OUT_OF_SPACE_IF_NULL(value = sym_new_const(ctx, ptr));
 }
 
 op(_LOAD_CONST_INLINE_WITH_NULL, (ptr/4 -- value, null)) {
-value = sym_new_const(ctx, ptr);
-if (value == NULL) {
-goto out_of_space;
-}
-null = sym_new_null(ctx);
-if (null == NULL) {
-goto out_of_space;
-}
+OUT_OF_SPACE_IF_NULL(value = sym_new_const(ctx, ptr));

[Python-checkins] gh-115480: Type / constant propagation for float binary uops (GH-115550)

2024-02-16 Thread Fidget-Spinner
https://github.com/python/cpython/commit/13addd2bbdcbf96c5ea26a0f425c049f1b71e945
commit: 13addd2bbdcbf96c5ea26a0f425c049f1b71e945
branch: main
author: Peter Lazorchak 
committer: Fidget-Spinner 
date: 2024-02-17T02:02:48+08:00
summary:

gh-115480: Type / constant propagation for float binary uops (GH-115550)

Co-authored-by: Ken Jin 

files:
M Lib/test/test_capi/test_opt.py
M Python/tier2_redundancy_eliminator_bytecodes.c
M Python/tier2_redundancy_eliminator_cases.c.h

diff --git a/Lib/test/test_capi/test_opt.py b/Lib/test/test_capi/test_opt.py
index 1a8ed3441fa855..66860c67966859 100644
--- a/Lib/test/test_capi/test_opt.py
+++ b/Lib/test/test_capi/test_opt.py
@@ -561,6 +561,16 @@ def testfunc(n):
 
 class TestUopsOptimization(unittest.TestCase):
 
+def _run_with_optimizer(self, testfunc, arg):
+res = None
+opt = _testinternalcapi.get_uop_optimizer()
+with temporary_optimizer(opt):
+res = testfunc(arg)
+
+ex = get_first_executor(testfunc)
+return res, ex
+
+
 def test_int_type_propagation(self):
 def testfunc(loops):
 num = 0
@@ -570,12 +580,7 @@ def testfunc(loops):
 num += 1
 return a
 
-opt = _testinternalcapi.get_uop_optimizer()
-res = None
-with temporary_optimizer(opt):
-res = testfunc(32)
-
-ex = get_first_executor(testfunc)
+res, ex = self._run_with_optimizer(testfunc, 32)
 self.assertIsNotNone(ex)
 self.assertEqual(res, 63)
 binop_count = [opname for opname, _, _ in ex if opname == 
"_BINARY_OP_ADD_INT"]
@@ -642,12 +647,7 @@ def testfunc(loops):
 num += 1
 return a
 
-opt = _testinternalcapi.get_uop_optimizer()
-res = None
-with temporary_optimizer(opt):
-res = testfunc(64)
-
-ex = get_first_executor(testfunc)
+res, ex = self._run_with_optimizer(testfunc, 64)
 self.assertIsNotNone(ex)
 binop_count = [opname for opname, _, _ in ex if opname == 
"_BINARY_OP_ADD_INT"]
 self.assertGreaterEqual(len(binop_count), 3)
@@ -659,11 +659,7 @@ def dummy(x):
 for i in range(n):
 dummy(i)
 
-opt = _testinternalcapi.get_uop_optimizer()
-with temporary_optimizer(opt):
-testfunc(32)
-
-ex = get_first_executor(testfunc)
+res, ex = self._run_with_optimizer(testfunc, 32)
 self.assertIsNotNone(ex)
 uops = {opname for opname, _, _ in ex}
 self.assertIn("_PUSH_FRAME", uops)
@@ -677,11 +673,7 @@ def testfunc(n):
 x = i + i
 return x
 
-opt = _testinternalcapi.get_uop_optimizer()
-with temporary_optimizer(opt):
-res = testfunc(32)
-
-ex = get_first_executor(testfunc)
+res, ex = self._run_with_optimizer(testfunc, 32)
 self.assertEqual(res, 62)
 self.assertIsNotNone(ex)
 uops = {opname for opname, _, _ in ex}
@@ -699,11 +691,7 @@ def testfunc(n):
 res = x + z + a + b
 return res
 
-opt = _testinternalcapi.get_uop_optimizer()
-with temporary_optimizer(opt):
-res = testfunc(32)
-
-ex = get_first_executor(testfunc)
+res, ex = self._run_with_optimizer(testfunc, 32)
 self.assertEqual(res, 4)
 self.assertIsNotNone(ex)
 uops = {opname for opname, _, _ in ex}
@@ -716,11 +704,8 @@ def testfunc(n):
 for _ in range(n):
 return [i for i in range(n)]
 
-opt = _testinternalcapi.get_uop_optimizer()
-with temporary_optimizer(opt):
-testfunc(32)
-
-ex = get_first_executor(testfunc)
+res, ex = self._run_with_optimizer(testfunc, 32)
+self.assertEqual(res, list(range(32)))
 self.assertIsNotNone(ex)
 uops = {opname for opname, _, _ in ex}
 self.assertNotIn("_BINARY_OP_ADD_INT", uops)
@@ -785,6 +770,56 @@ def testfunc(n):
 """))
 self.assertEqual(result[0].rc, 0, result)
 
+def test_float_add_constant_propagation(self):
+def testfunc(n):
+a = 1.0
+for _ in range(n):
+a = a + 0.1
+return a
+
+res, ex = self._run_with_optimizer(testfunc, 32)
+self.assertAlmostEqual(res, 4.2)
+self.assertIsNotNone(ex)
+uops = {opname for opname, _, _ in ex}
+guard_both_float_count = [opname for opname, _, _ in ex if opname == 
"_GUARD_BOTH_FLOAT"]
+self.assertLessEqual(len(guard_both_float_count), 1)
+# TODO gh-115506: this assertion may change after propagating 
constants.
+# We'll also need to verify that propagation actually occurs.
+self.assertIn("_BINARY_OP_ADD_FLOAT", uops)
+
+def test_float_subtract_constant_propagation(self):
+def testfunc(n):
+

[Python-checkins] gh-115700: Add target `_RegenCases` in Windows build for cases regeneration. (GH-115708)

2024-02-20 Thread Fidget-Spinner
https://github.com/python/cpython/commit/a2bb8ad14409c7ecb8dea437b0e281eb1f65b5d8
commit: a2bb8ad14409c7ecb8dea437b0e281eb1f65b5d8
branch: main
author: Kirill Podoprigora 
committer: Fidget-Spinner 
date: 2024-02-20T19:10:47+08:00
summary:

gh-115700: Add target `_RegenCases` in Windows build for cases regeneration. 
(GH-115708)

files:
A Misc/NEWS.d/next/Core and 
Builtins/2024-02-20-12-46-20.gh-issue-115700.KLJ5r4.rst
M PCbuild/regen.targets

diff --git a/Misc/NEWS.d/next/Core and 
Builtins/2024-02-20-12-46-20.gh-issue-115700.KLJ5r4.rst b/Misc/NEWS.d/next/Core 
and Builtins/2024-02-20-12-46-20.gh-issue-115700.KLJ5r4.rst
new file mode 100644
index 00..5b7b8e410b5063
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and 
Builtins/2024-02-20-12-46-20.gh-issue-115700.KLJ5r4.rst 
@@ -0,0 +1 @@
+The regen-cases build stage now works on Windows.
diff --git a/PCbuild/regen.targets b/PCbuild/regen.targets
index a90620d6ca8b7d..8f31803dbb752a 100644
--- a/PCbuild/regen.targets
+++ b/PCbuild/regen.targets
@@ -31,11 +31,13 @@
 
 <_JITSources 
Include="$(PySourcePath)Python\executor_cases.c.h;$(GeneratedPyConfigDir)pyconfig.h;$(PySourcePath)Tools\jit\**"/>
 <_JITOutputs Include="$(GeneratedPyConfigDir)jit_stencils.h"/>
+<_CasesSources 
Include="$(PySourcePath)Python\bytecodes.c;$(PySourcePath)Python\tier2_redundancy_eliminator_bytecodes.c;"/>
+<_CasesOutputs 
Include="$(PySourcePath)Python\generated_cases.c.h;$(PySourcePath)Include\opcode_ids.h;$(PySourcePath)Include\internal\pycore_uop_ids.h;$(PySourcePath)Python\opcode_targets.h;$(PySourcePath)Include\internal\pycore_opcode_metadata.h;$(PySourcePath)Include\internal\pycore_uop_metadata.h;$(PySourcePath)Python\tier2_redundancy_eliminator_cases.c.h;$(PySourcePath)Lib\_opcode_metadata.py"/>
   
 
   
 
-
   
 
@@ -79,7 +81,31 @@
 
   
-  
+
+  
+
+
+
+
+
+
+
+
+
+
+  
+
   
   
 
-  
+  
 
   
 

___
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com


[Python-checkins] gh-115687: Split up guards from COMPARE_OP (GH-115688)

2024-02-20 Thread Fidget-Spinner
https://github.com/python/cpython/commit/dcba21f905ef170b2cd0a6433b6fe6bcb4316a67
commit: dcba21f905ef170b2cd0a6433b6fe6bcb4316a67
branch: main
author: Ken Jin 
committer: Fidget-Spinner 
date: 2024-02-20T11:30:49Z
summary:

gh-115687: Split up guards from COMPARE_OP (GH-115688)

files:
M Include/internal/pycore_opcode_metadata.h
M Include/internal/pycore_uop_ids.h
M Include/internal/pycore_uop_metadata.h
M Lib/test/test_capi/test_opt.py
M Python/bytecodes.c
M Python/executor_cases.c.h
M Python/generated_cases.c.h
M Python/tier2_redundancy_eliminator_bytecodes.c
M Python/tier2_redundancy_eliminator_cases.c.h

diff --git a/Include/internal/pycore_opcode_metadata.h 
b/Include/internal/pycore_opcode_metadata.h
index f45e5f1901b0af..ab34366ab1066c 100644
--- a/Include/internal/pycore_opcode_metadata.h
+++ b/Include/internal/pycore_opcode_metadata.h
@@ -999,9 +999,9 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[268] 
= {
 [CHECK_EXC_MATCH] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | 
HAS_ESCAPES_FLAG },
 [CLEANUP_THROW] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG 
},
 [COMPARE_OP] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_ERROR_FLAG | 
HAS_ESCAPES_FLAG },
-[COMPARE_OP_FLOAT] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG 
| HAS_ESCAPES_FLAG },
-[COMPARE_OP_INT] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG | 
HAS_ESCAPES_FLAG },
-[COMPARE_OP_STR] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG | 
HAS_ESCAPES_FLAG },
+[COMPARE_OP_FLOAT] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG 
| HAS_EXIT_FLAG | HAS_ESCAPES_FLAG },
+[COMPARE_OP_INT] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG | 
HAS_EXIT_FLAG | HAS_ESCAPES_FLAG },
+[COMPARE_OP_STR] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG | 
HAS_EXIT_FLAG | HAS_ESCAPES_FLAG },
 [CONTAINS_OP] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | 
HAS_ESCAPES_FLAG },
 [CONVERT_VALUE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG },
 [COPY] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_PURE_FLAG },
@@ -1221,9 +1221,9 @@ _PyOpcode_macro_expansion[256] = {
 [CHECK_EG_MATCH] = { .nuops = 1, .uops = { { _CHECK_EG_MATCH, 0, 0 } } },
 [CHECK_EXC_MATCH] = { .nuops = 1, .uops = { { _CHECK_EXC_MATCH, 0, 0 } } },
 [COMPARE_OP] = { .nuops = 1, .uops = { { _COMPARE_OP, 0, 0 } } },
-[COMPARE_OP_FLOAT] = { .nuops = 1, .uops = { { _COMPARE_OP_FLOAT, 0, 0 } } 
},
-[COMPARE_OP_INT] = { .nuops = 1, .uops = { { _COMPARE_OP_INT, 0, 0 } } },
-[COMPARE_OP_STR] = { .nuops = 1, .uops = { { _COMPARE_OP_STR, 0, 0 } } },
+[COMPARE_OP_FLOAT] = { .nuops = 2, .uops = { { _GUARD_BOTH_FLOAT, 0, 0 }, 
{ _COMPARE_OP_FLOAT, 0, 0 } } },
+[COMPARE_OP_INT] = { .nuops = 2, .uops = { { _GUARD_BOTH_INT, 0, 0 }, { 
_COMPARE_OP_INT, 0, 0 } } },
+[COMPARE_OP_STR] = { .nuops = 2, .uops = { { _GUARD_BOTH_UNICODE, 0, 0 }, 
{ _COMPARE_OP_STR, 0, 0 } } },
 [CONTAINS_OP] = { .nuops = 1, .uops = { { _CONTAINS_OP, 0, 0 } } },
 [CONVERT_VALUE] = { .nuops = 1, .uops = { { _CONVERT_VALUE, 0, 0 } } },
 [COPY] = { .nuops = 1, .uops = { { _COPY, 0, 0 } } },
diff --git a/Include/internal/pycore_uop_ids.h 
b/Include/internal/pycore_uop_ids.h
index e098852d941f18..3c133d97b2f03e 100644
--- a/Include/internal/pycore_uop_ids.h
+++ b/Include/internal/pycore_uop_ids.h
@@ -72,9 +72,9 @@ extern "C" {
 #define _CHECK_VALIDITY_AND_SET_IP 324
 #define _COLD_EXIT 325
 #define _COMPARE_OP 326
-#define _COMPARE_OP_FLOAT COMPARE_OP_FLOAT
-#define _COMPARE_OP_INT COMPARE_OP_INT
-#define _COMPARE_OP_STR COMPARE_OP_STR
+#define _COMPARE_OP_FLOAT 327
+#define _COMPARE_OP_INT 328
+#define _COMPARE_OP_STR 329
 #define _CONTAINS_OP CONTAINS_OP
 #define _CONVERT_VALUE CONVERT_VALUE
 #define _COPY COPY
@@ -89,41 +89,41 @@ extern "C" {
 #define _DICT_UPDATE DICT_UPDATE
 #define _END_SEND END_SEND
 #define _EXIT_INIT_CHECK EXIT_INIT_CHECK
-#define _FATAL_ERROR 327
+#define _FATAL_ERROR 330
 #define _FORMAT_SIMPLE FORMAT_SIMPLE
 #define _FORMAT_WITH_SPEC FORMAT_WITH_SPEC
-#define _FOR_ITER 328
+#define _FOR_ITER 331
 #define _FOR_ITER_GEN FOR_ITER_GEN
-#define _FOR_ITER_TIER_TWO 329
+#define _FOR_ITER_TIER_TWO 332
 #define _GET_AITER GET_AITER
 #define _GET_ANEXT GET_ANEXT
 #define _GET_AWAITABLE GET_AWAITABLE
 #define _GET_ITER GET_ITER
 #define _GET_LEN GET_LEN
 #define _GET_YIELD_FROM_ITER GET_YIELD_FROM_ITER
-#define _GUARD_BOTH_FLOAT 330
-#define _GUARD_BOTH_INT 331
-#define _GUARD_BOTH_UNICODE 332
-#define _GUARD_BUILTINS_VERSION 333
-#define _GUARD_DORV_VALUES 334
-#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT 335
-#define _GUARD_GLOBALS_VERSION 336
-#define _GUARD_IS_FALSE_POP 337
-#define _GUARD_IS_NONE_POP 338
-#define _GUARD_IS_NOT_NONE_POP 339
-#define _GUARD_IS_TRUE_POP 340
-#define _GUARD_KEYS_VERSION 341
-#define _GUARD_NOT_EXHAUSTED_LIST 342
-#define _GUARD_NOT_EXHAUSTED_RANGE 343
-#define _GUARD_NOT_EXHAUSTED_TUPLE 344
-#define _GUARD_TYPE_

[Python-checkins] gh-114058: More robust method handling in redundancy eliminator (GH-115779)

2024-02-22 Thread Fidget-Spinner
https://github.com/python/cpython/commit/a33ffe4785f90f68227ddf2ec3e06d5ceaf76cec
commit: a33ffe4785f90f68227ddf2ec3e06d5ceaf76cec
branch: main
author: Ken Jin 
committer: Fidget-Spinner 
date: 2024-02-23T15:42:03+08:00
summary:

gh-114058: More robust method handling in redundancy eliminator (GH-115779)

files:
M Python/optimizer_analysis.c
M Python/tier2_redundancy_eliminator_bytecodes.c
M Python/tier2_redundancy_eliminator_cases.c.h

diff --git a/Python/optimizer_analysis.c b/Python/optimizer_analysis.c
index 68ef8254b494a4..9503dcc74656cd 100644
--- a/Python/optimizer_analysis.c
+++ b/Python/optimizer_analysis.c
@@ -315,6 +315,7 @@ sym_new_known_notnull(_Py_UOpsAbstractInterpContext *ctx)
 if (res == NULL) {
 return NULL;
 }
+sym_set_flag(res, KNOWN);
 sym_set_flag(res, NOT_NULL);
 return res;
 }
diff --git a/Python/tier2_redundancy_eliminator_bytecodes.c 
b/Python/tier2_redundancy_eliminator_bytecodes.c
index ff2b9a42272863..ef7b43d53539ce 100644
--- a/Python/tier2_redundancy_eliminator_bytecodes.c
+++ b/Python/tier2_redundancy_eliminator_bytecodes.c
@@ -295,6 +295,27 @@ dummy_func(void) {
 (void)owner;
 }
 
+op(_LOAD_ATTR_METHOD_WITH_VALUES, (descr/4, owner -- attr, self if (1))) {
+OUT_OF_SPACE_IF_NULL(attr = sym_new_known_notnull(ctx));
+OUT_OF_SPACE_IF_NULL(self = sym_new_known_notnull(ctx));
+}
+
+op(_LOAD_ATTR_METHOD_NO_DICT, (descr/4, owner -- attr, self if (1))) {
+OUT_OF_SPACE_IF_NULL(attr = sym_new_known_notnull(ctx));
+OUT_OF_SPACE_IF_NULL(self = sym_new_known_notnull(ctx));
+}
+
+op(_LOAD_ATTR_METHOD_LAZY_DICT, (descr/4, owner -- attr, self if (1))) {
+OUT_OF_SPACE_IF_NULL(attr = sym_new_known_notnull(ctx));
+OUT_OF_SPACE_IF_NULL(self = sym_new_known_notnull(ctx));
+}
+
+op(_INIT_CALL_BOUND_METHOD_EXACT_ARGS, (callable, unused, unused[oparg] -- 
func, self, unused[oparg])) {
+OUT_OF_SPACE_IF_NULL(func = sym_new_known_notnull(ctx));
+OUT_OF_SPACE_IF_NULL(self = sym_new_known_notnull(ctx));
+}
+
+
 op(_CHECK_FUNCTION_EXACT_ARGS, (func_version/2, callable, self_or_null, 
unused[oparg] -- callable, self_or_null, unused[oparg])) {
 sym_set_type(callable, &PyFunction_Type);
 (void)self_or_null;
diff --git a/Python/tier2_redundancy_eliminator_cases.c.h 
b/Python/tier2_redundancy_eliminator_cases.c.h
index 58c11b7a1c87e0..ca9b5953d21012 100644
--- a/Python/tier2_redundancy_eliminator_cases.c.h
+++ b/Python/tier2_redundancy_eliminator_cases.c.h
@@ -1300,12 +1300,13 @@
 }
 
 case _LOAD_ATTR_METHOD_WITH_VALUES: {
+_Py_UOpsSymType *owner;
 _Py_UOpsSymType *attr;
 _Py_UOpsSymType *self = NULL;
-attr = sym_new_unknown(ctx);
-if (attr == NULL) goto out_of_space;
-self = sym_new_unknown(ctx);
-if (self == NULL) goto out_of_space;
+owner = stack_pointer[-1];
+PyObject *descr = (PyObject *)this_instr->operand;
+OUT_OF_SPACE_IF_NULL(attr = sym_new_known_notnull(ctx));
+OUT_OF_SPACE_IF_NULL(self = sym_new_known_notnull(ctx));
 stack_pointer[-1] = attr;
 stack_pointer[0] = self;
 stack_pointer += 1;
@@ -1313,12 +1314,13 @@
 }
 
 case _LOAD_ATTR_METHOD_NO_DICT: {
+_Py_UOpsSymType *owner;
 _Py_UOpsSymType *attr;
 _Py_UOpsSymType *self = NULL;
-attr = sym_new_unknown(ctx);
-if (attr == NULL) goto out_of_space;
-self = sym_new_unknown(ctx);
-if (self == NULL) goto out_of_space;
+owner = stack_pointer[-1];
+PyObject *descr = (PyObject *)this_instr->operand;
+OUT_OF_SPACE_IF_NULL(attr = sym_new_known_notnull(ctx));
+OUT_OF_SPACE_IF_NULL(self = sym_new_known_notnull(ctx));
 stack_pointer[-1] = attr;
 stack_pointer[0] = self;
 stack_pointer += 1;
@@ -1346,12 +1348,13 @@
 }
 
 case _LOAD_ATTR_METHOD_LAZY_DICT: {
+_Py_UOpsSymType *owner;
 _Py_UOpsSymType *attr;
 _Py_UOpsSymType *self = NULL;
-attr = sym_new_unknown(ctx);
-if (attr == NULL) goto out_of_space;
-self = sym_new_unknown(ctx);
-if (self == NULL) goto out_of_space;
+owner = stack_pointer[-1];
+PyObject *descr = (PyObject *)this_instr->operand;
+OUT_OF_SPACE_IF_NULL(attr = sym_new_known_notnull(ctx));
+OUT_OF_SPACE_IF_NULL(self = sym_new_known_notnull(ctx));
 stack_pointer[-1] = attr;
 stack_pointer[0] = self;
 stack_pointer += 1;
@@ -1373,12 +1376,12 @@
 }
 
 case _INIT_CALL_BOUND_METHOD_EXACT_ARGS: {
+_Py_UOpsSymType *callable;
 _Py_UOpsSymType *func;
 _Py_UOpsSymType *self;
-func = sy

[Python-checkins] gh-114058: Improve method information in redundancy eliminator (GH-115848)

2024-02-23 Thread Fidget-Spinner
https://github.com/python/cpython/commit/2ec50b4a66de6be418bfad058117249d4775df0f
commit: 2ec50b4a66de6be418bfad058117249d4775df0f
branch: main
author: Ken Jin 
committer: Fidget-Spinner 
date: 2024-02-23T23:41:10+08:00
summary:

gh-114058: Improve method information in redundancy eliminator (GH-115848)

files:
M Python/tier2_redundancy_eliminator_bytecodes.c
M Python/tier2_redundancy_eliminator_cases.c.h

diff --git a/Python/tier2_redundancy_eliminator_bytecodes.c 
b/Python/tier2_redundancy_eliminator_bytecodes.c
index ef7b43d53539ce..b9afd3089e1077 100644
--- a/Python/tier2_redundancy_eliminator_bytecodes.c
+++ b/Python/tier2_redundancy_eliminator_bytecodes.c
@@ -296,21 +296,25 @@ dummy_func(void) {
 }
 
 op(_LOAD_ATTR_METHOD_WITH_VALUES, (descr/4, owner -- attr, self if (1))) {
+(void)descr;
 OUT_OF_SPACE_IF_NULL(attr = sym_new_known_notnull(ctx));
-OUT_OF_SPACE_IF_NULL(self = sym_new_known_notnull(ctx));
+self = owner;
 }
 
 op(_LOAD_ATTR_METHOD_NO_DICT, (descr/4, owner -- attr, self if (1))) {
+(void)descr;
 OUT_OF_SPACE_IF_NULL(attr = sym_new_known_notnull(ctx));
-OUT_OF_SPACE_IF_NULL(self = sym_new_known_notnull(ctx));
+self = owner;
 }
 
 op(_LOAD_ATTR_METHOD_LAZY_DICT, (descr/4, owner -- attr, self if (1))) {
+(void)descr;
 OUT_OF_SPACE_IF_NULL(attr = sym_new_known_notnull(ctx));
-OUT_OF_SPACE_IF_NULL(self = sym_new_known_notnull(ctx));
+self = owner;
 }
 
 op(_INIT_CALL_BOUND_METHOD_EXACT_ARGS, (callable, unused, unused[oparg] -- 
func, self, unused[oparg])) {
+(void)callable;
 OUT_OF_SPACE_IF_NULL(func = sym_new_known_notnull(ctx));
 OUT_OF_SPACE_IF_NULL(self = sym_new_known_notnull(ctx));
 }
diff --git a/Python/tier2_redundancy_eliminator_cases.c.h 
b/Python/tier2_redundancy_eliminator_cases.c.h
index ca9b5953d21012..ca341e4dde5d93 100644
--- a/Python/tier2_redundancy_eliminator_cases.c.h
+++ b/Python/tier2_redundancy_eliminator_cases.c.h
@@ -1305,8 +1305,9 @@
 _Py_UOpsSymType *self = NULL;
 owner = stack_pointer[-1];
 PyObject *descr = (PyObject *)this_instr->operand;
+(void)descr;
 OUT_OF_SPACE_IF_NULL(attr = sym_new_known_notnull(ctx));
-OUT_OF_SPACE_IF_NULL(self = sym_new_known_notnull(ctx));
+self = owner;
 stack_pointer[-1] = attr;
 stack_pointer[0] = self;
 stack_pointer += 1;
@@ -1319,8 +1320,9 @@
 _Py_UOpsSymType *self = NULL;
 owner = stack_pointer[-1];
 PyObject *descr = (PyObject *)this_instr->operand;
+(void)descr;
 OUT_OF_SPACE_IF_NULL(attr = sym_new_known_notnull(ctx));
-OUT_OF_SPACE_IF_NULL(self = sym_new_known_notnull(ctx));
+self = owner;
 stack_pointer[-1] = attr;
 stack_pointer[0] = self;
 stack_pointer += 1;
@@ -1353,8 +1355,9 @@
 _Py_UOpsSymType *self = NULL;
 owner = stack_pointer[-1];
 PyObject *descr = (PyObject *)this_instr->operand;
+(void)descr;
 OUT_OF_SPACE_IF_NULL(attr = sym_new_known_notnull(ctx));
-OUT_OF_SPACE_IF_NULL(self = sym_new_known_notnull(ctx));
+self = owner;
 stack_pointer[-1] = attr;
 stack_pointer[0] = self;
 stack_pointer += 1;
@@ -1380,6 +1383,7 @@
 _Py_UOpsSymType *func;
 _Py_UOpsSymType *self;
 callable = stack_pointer[-2 - oparg];
+(void)callable;
 OUT_OF_SPACE_IF_NULL(func = sym_new_known_notnull(ctx));
 OUT_OF_SPACE_IF_NULL(self = sym_new_known_notnull(ctx));
 stack_pointer[-2 - oparg] = func;

___
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com


[Python-checkins] gh-115859: Disable the tier 2 redundancy eliminator by default (GH-115860)

2024-02-23 Thread Fidget-Spinner
https://github.com/python/cpython/commit/3d8fc06d4f8dc1e7be2455a7e89b37285fa89112
commit: 3d8fc06d4f8dc1e7be2455a7e89b37285fa89112
branch: main
author: Ken Jin 
committer: Fidget-Spinner 
date: 2024-02-23T18:43:52Z
summary:

gh-115859: Disable the tier 2 redundancy eliminator by default (GH-115860)

files:
M Lib/test/test_capi/test_opt.py
M Python/optimizer_analysis.c

diff --git a/Lib/test/test_capi/test_opt.py b/Lib/test/test_capi/test_opt.py
index 38c6fa4b47d0c9..25fc36dec93ddc 100644
--- a/Lib/test/test_capi/test_opt.py
+++ b/Lib/test/test_capi/test_opt.py
@@ -4,6 +4,7 @@
 import textwrap
 import unittest
 import gc
+import os
 
 import _testinternalcapi
 
@@ -568,6 +569,8 @@ def testfunc(n):
 count = ops.count("_GUARD_IS_TRUE_POP") + 
ops.count("_GUARD_IS_FALSE_POP")
 self.assertLessEqual(count, 2)
 
+
+@unittest.skipIf(os.getenv("PYTHONUOPSOPTIMIZE", default=0) == 0, "Needs uop 
optimizer to run.")
 class TestUopsOptimization(unittest.TestCase):
 
 def _run_with_optimizer(self, testfunc, arg):
diff --git a/Python/optimizer_analysis.c b/Python/optimizer_analysis.c
index 9503dcc74656cd..47bfc8cf1061d9 100644
--- a/Python/optimizer_analysis.c
+++ b/Python/optimizer_analysis.c
@@ -810,9 +810,12 @@ _Py_uop_analyze_and_optimize(
 
 peephole_opt(frame, buffer, buffer_size);
 
-err = uop_redundancy_eliminator(
-(PyCodeObject *)frame->f_executable, buffer,
-buffer_size, curr_stacklen, dependencies);
+char *uop_optimize = Py_GETENV("PYTHONUOPSOPTIMIZE");
+if (uop_optimize != NULL && *uop_optimize > '0') {
+err = uop_redundancy_eliminator(
+(PyCodeObject *)frame->f_executable, buffer,
+buffer_size, curr_stacklen, dependencies);
+}
 
 if (err == 0) {
 goto not_ready;

___
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com


[Python-checkins] gh-115168: Add pystats counter for invalidated executors (GH-115169)

2024-02-26 Thread Fidget-Spinner
https://github.com/python/cpython/commit/b05afdd5ec325bdb4cc89bb3be177ed577bea41f
commit: b05afdd5ec325bdb4cc89bb3be177ed577bea41f
branch: main
author: Michael Droettboom 
committer: Fidget-Spinner 
date: 2024-02-26T17:51:47Z
summary:

gh-115168: Add pystats counter for invalidated executors (GH-115169)

files:
M Include/cpython/optimizer.h
M Include/cpython/pystats.h
M Modules/_testinternalcapi.c
M Python/instrumentation.c
M Python/optimizer.c
M Python/optimizer_analysis.c
M Python/pylifecycle.c
M Python/pystate.c
M Python/specialize.c
M Python/sysmodule.c
M Tools/scripts/summarize_stats.py

diff --git a/Include/cpython/optimizer.h b/Include/cpython/optimizer.h
index fe54d1ddfe6129..8fc9fb62aebdb4 100644
--- a/Include/cpython/optimizer.h
+++ b/Include/cpython/optimizer.h
@@ -100,8 +100,8 @@ void _Py_ExecutorClear(_PyExecutorObject *);
 void _Py_BloomFilter_Init(_PyBloomFilter *);
 void _Py_BloomFilter_Add(_PyBloomFilter *bloom, void *obj);
 PyAPI_FUNC(void) _Py_Executor_DependsOn(_PyExecutorObject *executor, void 
*obj);
-PyAPI_FUNC(void) _Py_Executors_InvalidateDependency(PyInterpreterState 
*interp, void *obj);
-extern void _Py_Executors_InvalidateAll(PyInterpreterState *interp);
+PyAPI_FUNC(void) _Py_Executors_InvalidateDependency(PyInterpreterState 
*interp, void *obj, int is_invalidation);
+extern void _Py_Executors_InvalidateAll(PyInterpreterState *interp, int 
is_invalidation);
 
 /* For testing */
 PyAPI_FUNC(PyObject *)PyUnstable_Optimizer_NewCounter(void);
diff --git a/Include/cpython/pystats.h b/Include/cpython/pystats.h
index db9aaedec950e4..887fbbedf88502 100644
--- a/Include/cpython/pystats.h
+++ b/Include/cpython/pystats.h
@@ -115,6 +115,7 @@ typedef struct _optimization_stats {
 uint64_t inner_loop;
 uint64_t recursive_call;
 uint64_t low_confidence;
+uint64_t executors_invalidated;
 UOpStats opcode[512];
 uint64_t unsupported_opcode[256];
 uint64_t trace_length_hist[_Py_UOP_HIST_SIZE];
diff --git a/Modules/_testinternalcapi.c b/Modules/_testinternalcapi.c
index 0d23b1899f22e4..5b714ca3f3dc33 100644
--- a/Modules/_testinternalcapi.c
+++ b/Modules/_testinternalcapi.c
@@ -1035,7 +1035,7 @@ static PyObject *
 invalidate_executors(PyObject *self, PyObject *obj)
 {
 PyInterpreterState *interp = PyInterpreterState_Get();
-_Py_Executors_InvalidateDependency(interp, obj);
+_Py_Executors_InvalidateDependency(interp, obj, 1);
 Py_RETURN_NONE;
 }
 
diff --git a/Python/instrumentation.c b/Python/instrumentation.c
index 878d19f0552bf5..6f1bc2e0a107df 100644
--- a/Python/instrumentation.c
+++ b/Python/instrumentation.c
@@ -1599,7 +1599,7 @@ _Py_Instrument(PyCodeObject *code, PyInterpreterState 
*interp)
 if (code->co_executors != NULL) {
 _PyCode_Clear_Executors(code);
 }
-_Py_Executors_InvalidateDependency(interp, code);
+_Py_Executors_InvalidateDependency(interp, code, 1);
 int code_len = (int)Py_SIZE(code);
 /* Exit early to avoid creating instrumentation
  * data for potential statically allocated code
@@ -1820,7 +1820,7 @@ _PyMonitoring_SetEvents(int tool_id, 
_PyMonitoringEventSet events)
 return -1;
 }
 set_global_version(tstate, new_version);
-_Py_Executors_InvalidateAll(interp);
+_Py_Executors_InvalidateAll(interp, 1);
 return instrument_all_executing_code_objects(interp);
 }
 
@@ -1850,7 +1850,7 @@ _PyMonitoring_SetLocalEvents(PyCodeObject *code, int 
tool_id, _PyMonitoringEvent
 /* Force instrumentation update */
 code->_co_instrumentation_version -= MONITORING_VERSION_INCREMENT;
 }
-_Py_Executors_InvalidateDependency(interp, code);
+_Py_Executors_InvalidateDependency(interp, code, 1);
 if (_Py_Instrument(code, interp)) {
 return -1;
 }
diff --git a/Python/optimizer.c b/Python/optimizer.c
index 6b2ba3addefc95..c04ee17ee2171d 100644
--- a/Python/optimizer.c
+++ b/Python/optimizer.c
@@ -1348,7 +1348,7 @@ _Py_Executor_DependsOn(_PyExecutorObject *executor, void 
*obj)
  * May cause other executors to be invalidated as well
  */
 void
-_Py_Executors_InvalidateDependency(PyInterpreterState *interp, void *obj)
+_Py_Executors_InvalidateDependency(PyInterpreterState *interp, void *obj, int 
is_invalidation)
 {
 _PyBloomFilter obj_filter;
 _Py_BloomFilter_Init(&obj_filter);
@@ -1360,6 +1360,9 @@ _Py_Executors_InvalidateDependency(PyInterpreterState 
*interp, void *obj)
 _PyExecutorObject *next = exec->vm_data.links.next;
 if (bloom_filter_may_contain(&exec->vm_data.bloom, &obj_filter)) {
 _Py_ExecutorClear(exec);
+if (is_invalidation) {
+OPT_STAT_INC(executors_invalidated);
+}
 }
 exec = next;
 }
@@ -1367,7 +1370,7 @@ _Py_Executors_InvalidateDependency(PyInterpreterState 
*interp, void *obj)
 
 /* Invalidate all executors */
 void
-_Py_Executors_InvalidateAll(PyInterpreterState *interp)
+_Py_Executors_InvalidateAll(PyInter

[Python-checkins] gh-115685: Type/values propagate for TO_BOOL in tier 2 (GH-115686)

2024-02-29 Thread Fidget-Spinner
https://github.com/python/cpython/commit/d01886c5c9e3a62921b304ba7e5145daaa56d3cf
commit: d01886c5c9e3a62921b304ba7e5145daaa56d3cf
branch: main
author: Ken Jin 
committer: Fidget-Spinner 
date: 2024-03-01T06:13:38+08:00
summary:

gh-115685: Type/values propagate for TO_BOOL in tier 2 (GH-115686)

files:
M Include/internal/pycore_uop_ids.h
M Include/internal/pycore_uop_metadata.h
M Python/bytecodes.c
M Python/executor_cases.c.h
M Python/optimizer_bytecodes.c
M Python/optimizer_cases.c.h

diff --git a/Include/internal/pycore_uop_ids.h 
b/Include/internal/pycore_uop_ids.h
index 3c133d97b2f03e..8f71eab44d914d 100644
--- a/Include/internal/pycore_uop_ids.h
+++ b/Include/internal/pycore_uop_ids.h
@@ -216,42 +216,43 @@ extern "C" {
 #define _POP_JUMP_IF_FALSE 402
 #define _POP_JUMP_IF_TRUE 403
 #define _POP_TOP POP_TOP
+#define _POP_TOP_LOAD_CONST_INLINE_BORROW 404
 #define _PUSH_EXC_INFO PUSH_EXC_INFO
-#define _PUSH_FRAME 404
+#define _PUSH_FRAME 405
 #define _PUSH_NULL PUSH_NULL
 #define _RESUME_CHECK RESUME_CHECK
-#define _SAVE_RETURN_OFFSET 405
-#define _SEND 406
+#define _SAVE_RETURN_OFFSET 406
+#define _SEND 407
 #define _SEND_GEN SEND_GEN
 #define _SETUP_ANNOTATIONS SETUP_ANNOTATIONS
 #define _SET_ADD SET_ADD
 #define _SET_FUNCTION_ATTRIBUTE SET_FUNCTION_ATTRIBUTE
 #define _SET_UPDATE SET_UPDATE
-#define _START_EXECUTOR 407
-#define _STORE_ATTR 408
-#define _STORE_ATTR_INSTANCE_VALUE 409
-#define _STORE_ATTR_SLOT 410
+#define _START_EXECUTOR 408
+#define _STORE_ATTR 409
+#define _STORE_ATTR_INSTANCE_VALUE 410
+#define _STORE_ATTR_SLOT 411
 #define _STORE_ATTR_WITH_HINT STORE_ATTR_WITH_HINT
 #define _STORE_DEREF STORE_DEREF
-#define _STORE_FAST 411
-#define _STORE_FAST_0 412
-#define _STORE_FAST_1 413
-#define _STORE_FAST_2 414
-#define _STORE_FAST_3 415
-#define _STORE_FAST_4 416
-#define _STORE_FAST_5 417
-#define _STORE_FAST_6 418
-#define _STORE_FAST_7 419
+#define _STORE_FAST 412
+#define _STORE_FAST_0 413
+#define _STORE_FAST_1 414
+#define _STORE_FAST_2 415
+#define _STORE_FAST_3 416
+#define _STORE_FAST_4 417
+#define _STORE_FAST_5 418
+#define _STORE_FAST_6 419
+#define _STORE_FAST_7 420
 #define _STORE_FAST_LOAD_FAST STORE_FAST_LOAD_FAST
 #define _STORE_FAST_STORE_FAST STORE_FAST_STORE_FAST
 #define _STORE_GLOBAL STORE_GLOBAL
 #define _STORE_NAME STORE_NAME
 #define _STORE_SLICE STORE_SLICE
-#define _STORE_SUBSCR 420
+#define _STORE_SUBSCR 421
 #define _STORE_SUBSCR_DICT STORE_SUBSCR_DICT
 #define _STORE_SUBSCR_LIST_INT STORE_SUBSCR_LIST_INT
 #define _SWAP SWAP
-#define _TO_BOOL 421
+#define _TO_BOOL 422
 #define _TO_BOOL_ALWAYS_TRUE TO_BOOL_ALWAYS_TRUE
 #define _TO_BOOL_BOOL TO_BOOL_BOOL
 #define _TO_BOOL_INT TO_BOOL_INT
@@ -262,12 +263,12 @@ extern "C" {
 #define _UNARY_NEGATIVE UNARY_NEGATIVE
 #define _UNARY_NOT UNARY_NOT
 #define _UNPACK_EX UNPACK_EX
-#define _UNPACK_SEQUENCE 422
+#define _UNPACK_SEQUENCE 423
 #define _UNPACK_SEQUENCE_LIST UNPACK_SEQUENCE_LIST
 #define _UNPACK_SEQUENCE_TUPLE UNPACK_SEQUENCE_TUPLE
 #define _UNPACK_SEQUENCE_TWO_TUPLE UNPACK_SEQUENCE_TWO_TUPLE
 #define _WITH_EXCEPT_START WITH_EXCEPT_START
-#define MAX_UOP_ID 422
+#define MAX_UOP_ID 423
 
 #ifdef __cplusplus
 }
diff --git a/Include/internal/pycore_uop_metadata.h 
b/Include/internal/pycore_uop_metadata.h
index 35340fe9ee1b63..7f921a6cd3f4c8 100644
--- a/Include/internal/pycore_uop_metadata.h
+++ b/Include/internal/pycore_uop_metadata.h
@@ -232,6 +232,7 @@ const uint16_t _PyUop_Flags[MAX_UOP_ID+1] = {
 [_CHECK_VALIDITY] = HAS_DEOPT_FLAG,
 [_LOAD_CONST_INLINE] = HAS_PURE_FLAG,
 [_LOAD_CONST_INLINE_BORROW] = HAS_PURE_FLAG,
+[_POP_TOP_LOAD_CONST_INLINE_BORROW] = HAS_PURE_FLAG,
 [_LOAD_CONST_INLINE_WITH_NULL] = HAS_PURE_FLAG,
 [_LOAD_CONST_INLINE_BORROW_WITH_NULL] = HAS_PURE_FLAG,
 [_CHECK_GLOBALS] = HAS_DEOPT_FLAG,
@@ -425,6 +426,7 @@ const char *const _PyOpcode_uop_name[MAX_UOP_ID+1] = {
 [_POP_EXCEPT] = "_POP_EXCEPT",
 [_POP_FRAME] = "_POP_FRAME",
 [_POP_TOP] = "_POP_TOP",
+[_POP_TOP_LOAD_CONST_INLINE_BORROW] = "_POP_TOP_LOAD_CONST_INLINE_BORROW",
 [_PUSH_EXC_INFO] = "_PUSH_EXC_INFO",
 [_PUSH_FRAME] = "_PUSH_FRAME",
 [_PUSH_NULL] = "_PUSH_NULL",
diff --git a/Python/bytecodes.c b/Python/bytecodes.c
index 1d515098f6c7e9..095982d64f34d0 100644
--- a/Python/bytecodes.c
+++ b/Python/bytecodes.c
@@ -4043,6 +4043,11 @@ dummy_func(
 value = ptr;
 }
 
+tier2 pure op (_POP_TOP_LOAD_CONST_INLINE_BORROW, (ptr/4, pop -- 
value)) {
+Py_DECREF(pop);
+value = ptr;
+}
+
 tier2 pure op(_LOAD_CONST_INLINE_WITH_NULL, (ptr/4 -- value, null)) {
 value = Py_NewRef(ptr);
 null = NULL;
diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h
index 9ec1be9076a5a0..e84c33281ee640 100644
--- a/Python/executor_cases.c.h
+++ b/Python/executor_cases.c.h
@@ -3759,6 +3759,17 @@
 break;

[Python-checkins] gh-115480: Type propagate _BINARY_OP_ADD_UNICODE (GH-115710)

2024-03-01 Thread Fidget-Spinner
https://github.com/python/cpython/commit/ff96b81d78c4a52fb1eb8384300af3dd0dd2db0d
commit: ff96b81d78c4a52fb1eb8384300af3dd0dd2db0d
branch: main
author: Ken Jin 
committer: Fidget-Spinner 
date: 2024-03-02T03:40:04+08:00
summary:

gh-115480: Type propagate _BINARY_OP_ADD_UNICODE (GH-115710)

files:
M Lib/test/test_capi/test_opt.py
M Python/optimizer_bytecodes.c
M Python/optimizer_cases.c.h

diff --git a/Lib/test/test_capi/test_opt.py b/Lib/test/test_capi/test_opt.py
index f4fcdea05e96bf..a0a19225b79433 100644
--- a/Lib/test/test_capi/test_opt.py
+++ b/Lib/test/test_capi/test_opt.py
@@ -795,11 +795,14 @@ def test_float_add_constant_propagation(self):
 def testfunc(n):
 a = 1.0
 for _ in range(n):
-a = a + 0.1
+a = a + 0.25
+a = a + 0.25
+a = a + 0.25
+a = a + 0.25
 return a
 
 res, ex = self._run_with_optimizer(testfunc, 32)
-self.assertAlmostEqual(res, 4.2)
+self.assertAlmostEqual(res, 33.0)
 self.assertIsNotNone(ex)
 uops = get_opnames(ex)
 guard_both_float_count = [opname for opname in iter_opnames(ex) if 
opname == "_GUARD_BOTH_FLOAT"]
@@ -812,11 +815,14 @@ def test_float_subtract_constant_propagation(self):
 def testfunc(n):
 a = 1.0
 for _ in range(n):
-a = a - 0.1
+a = a - 0.25
+a = a - 0.25
+a = a - 0.25
+a = a - 0.25
 return a
 
 res, ex = self._run_with_optimizer(testfunc, 32)
-self.assertAlmostEqual(res, -2.2)
+self.assertAlmostEqual(res, -31.0)
 self.assertIsNotNone(ex)
 uops = get_opnames(ex)
 guard_both_float_count = [opname for opname in iter_opnames(ex) if 
opname == "_GUARD_BOTH_FLOAT"]
@@ -829,11 +835,14 @@ def test_float_multiply_constant_propagation(self):
 def testfunc(n):
 a = 1.0
 for _ in range(n):
-a = a * 2.0
+a = a * 1.0
+a = a * 1.0
+a = a * 1.0
+a = a * 1.0
 return a
 
 res, ex = self._run_with_optimizer(testfunc, 32)
-self.assertAlmostEqual(res, 2 ** 32)
+self.assertAlmostEqual(res, 1.0)
 self.assertIsNotNone(ex)
 uops = get_opnames(ex)
 guard_both_float_count = [opname for opname in iter_opnames(ex) if 
opname == "_GUARD_BOTH_FLOAT"]
@@ -842,6 +851,24 @@ def testfunc(n):
 # We'll also need to verify that propagation actually occurs.
 self.assertIn("_BINARY_OP_MULTIPLY_FLOAT", uops)
 
+def test_add_unicode_propagation(self):
+def testfunc(n):
+a = ""
+for _ in range(n):
+a + a
+a + a
+a + a
+a + a
+return a
+
+res, ex = self._run_with_optimizer(testfunc, 32)
+self.assertEqual(res, "")
+self.assertIsNotNone(ex)
+uops = get_opnames(ex)
+guard_both_unicode_count = [opname for opname in iter_opnames(ex) if 
opname == "_GUARD_BOTH_UNICODE"]
+self.assertLessEqual(len(guard_both_unicode_count), 1)
+self.assertIn("_BINARY_OP_ADD_UNICODE", uops)
+
 def test_compare_op_type_propagation_float(self):
 def testfunc(n):
 a = 1.0
diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c
index 2b47381ec76db4..786d884fc5a1a8 100644
--- a/Python/optimizer_bytecodes.c
+++ b/Python/optimizer_bytecodes.c
@@ -254,6 +254,22 @@ dummy_func(void) {
 }
 }
 
+op(_BINARY_OP_ADD_UNICODE, (left, right -- 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));
+if (temp == NULL) {
+goto error;
+}
+res = sym_new_const(ctx, temp);
+Py_DECREF(temp);
+OUT_OF_SPACE_IF_NULL(res);
+}
+else {
+OUT_OF_SPACE_IF_NULL(res = sym_new_type(ctx, &PyUnicode_Type));
+}
+}
+
 op(_TO_BOOL, (value -- res)) {
 (void)value;
 res = sym_new_type(ctx, &PyBool_Type);
diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h
index 9d7ebb80f62857..6d3488f2118589 100644
--- a/Python/optimizer_cases.c.h
+++ b/Python/optimizer_cases.c.h
@@ -446,9 +446,24 @@
 }
 
 case _BINARY_OP_ADD_UNICODE: {
+_Py_UopsSymbol *right;
+_Py_UopsSymbol *left;
 _Py_UopsSymbol *res;
-res = sym_new_unknown(ctx);
-if (res == NULL) goto out_of_space;
+  

[Python-checkins] gh-116381: Specialize CONTAINS_OP (GH-116385)

2024-03-06 Thread Fidget-Spinner
https://github.com/python/cpython/commit/7114cf20c015b99123b32c1ba4f5475b7a6c3a13
commit: 7114cf20c015b99123b32c1ba4f5475b7a6c3a13
branch: main
author: Ken Jin 
committer: Fidget-Spinner 
date: 2024-03-07T03:30:11+08:00
summary:

gh-116381: Specialize CONTAINS_OP (GH-116385)

* Specialize CONTAINS_OP

* 📜🤖 Added by blurb_it.

* Add PyAPI_FUNC for JIT

-

Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com>

files:
A Misc/NEWS.d/next/Core and 
Builtins/2024-03-05-22-00-58.gh-issue-116381.0Nq9iO.rst
M Include/internal/pycore_code.h
M Include/internal/pycore_list.h
M Include/internal/pycore_opcode_metadata.h
M Include/internal/pycore_setobject.h
M Include/internal/pycore_tuple.h
M Include/internal/pycore_uop_ids.h
M Include/internal/pycore_uop_metadata.h
M Include/opcode_ids.h
M Lib/_opcode_metadata.py
M Lib/importlib/_bootstrap_external.py
M Lib/opcode.py
M Objects/listobject.c
M Objects/setobject.c
M Objects/tupleobject.c
M Python/bytecodes.c
M Python/executor_cases.c.h
M Python/generated_cases.c.h
M Python/opcode_targets.h
M Python/optimizer_cases.c.h
M Python/specialize.c

diff --git a/Include/internal/pycore_code.h b/Include/internal/pycore_code.h
index a4e64825743ada..8eabd49a18afa9 100644
--- a/Include/internal/pycore_code.h
+++ b/Include/internal/pycore_code.h
@@ -121,6 +121,12 @@ typedef struct {
 
 #define INLINE_CACHE_ENTRIES_TO_BOOL CACHE_ENTRIES(_PyToBoolCache)
 
+typedef struct {
+uint16_t counter;
+} _PyContainsOpCache;
+
+#define INLINE_CACHE_ENTRIES_CONTAINS_OP CACHE_ENTRIES(_PyContainsOpCache)
+
 // Borrowed references to common callables:
 struct callable_cache {
 PyObject *isinstance;
@@ -277,6 +283,7 @@ extern void _Py_Specialize_UnpackSequence(PyObject *seq, 
_Py_CODEUNIT *instr,
 extern void _Py_Specialize_ForIter(PyObject *iter, _Py_CODEUNIT *instr, int 
oparg);
 extern void _Py_Specialize_Send(PyObject *receiver, _Py_CODEUNIT *instr);
 extern void _Py_Specialize_ToBool(PyObject *value, _Py_CODEUNIT *instr);
+extern void _Py_Specialize_ContainsOp(PyObject *value, _Py_CODEUNIT *instr);
 
 /* Finalizer function for static codeobjects used in deepfreeze.py */
 extern void _PyStaticCode_Fini(PyCodeObject *co);
diff --git a/Include/internal/pycore_list.h b/Include/internal/pycore_list.h
index 2a82912e41d557..92cab731bc253b 100644
--- a/Include/internal/pycore_list.h
+++ b/Include/internal/pycore_list.h
@@ -56,6 +56,8 @@ typedef struct {
 
 PyAPI_FUNC(PyObject *)_PyList_FromArraySteal(PyObject *const *src, Py_ssize_t 
n);
 
+PyAPI_FUNC(int) _PyList_Contains(PyObject *aa, PyObject *el);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/Include/internal/pycore_opcode_metadata.h 
b/Include/internal/pycore_opcode_metadata.h
index f355a496cf2e70..4c691d6a922862 100644
--- a/Include/internal/pycore_opcode_metadata.h
+++ b/Include/internal/pycore_opcode_metadata.h
@@ -151,6 +151,16 @@ int _PyOpcode_num_popped(int opcode, int oparg)  {
 return 2;
 case CONTAINS_OP:
 return 2;
+case CONTAINS_OP_DICT:
+return 2;
+case CONTAINS_OP_LIST:
+return 2;
+case CONTAINS_OP_SET:
+return 2;
+case CONTAINS_OP_STR:
+return 2;
+case CONTAINS_OP_TUPLE:
+return 2;
 case CONVERT_VALUE:
 return 1;
 case COPY:
@@ -576,6 +586,16 @@ int _PyOpcode_num_pushed(int opcode, int oparg)  {
 return 1;
 case CONTAINS_OP:
 return 1;
+case CONTAINS_OP_DICT:
+return 1;
+case CONTAINS_OP_LIST:
+return 1;
+case CONTAINS_OP_SET:
+return 1;
+case CONTAINS_OP_STR:
+return 1;
+case CONTAINS_OP_TUPLE:
+return 1;
 case CONVERT_VALUE:
 return 1;
 case COPY:
@@ -1002,7 +1022,12 @@ const struct opcode_metadata 
_PyOpcode_opcode_metadata[268] = {
 [COMPARE_OP_FLOAT] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG 
| HAS_EXIT_FLAG | HAS_ESCAPES_FLAG },
 [COMPARE_OP_INT] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG | 
HAS_EXIT_FLAG | HAS_ESCAPES_FLAG },
 [COMPARE_OP_STR] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG | 
HAS_EXIT_FLAG | HAS_ESCAPES_FLAG },
-[CONTAINS_OP] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | 
HAS_ESCAPES_FLAG },
+[CONTAINS_OP] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_ERROR_FLAG | 
HAS_ESCAPES_FLAG },
+[CONTAINS_OP_DICT] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG 
| HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
+[CONTAINS_OP_LIST] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG 
| HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
+[CONTAINS_OP_SET] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG | 
HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
+[CONTAINS_OP_STR] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG | 
HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
+[CONTAINS_OP_TUPLE] = 

[Python-checkins] gh-116420: Fix unused var compilation warnings (GH-116466)

2024-03-07 Thread Fidget-Spinner
https://github.com/python/cpython/commit/4298d69d4b2f7d0e9d93ad325238930bd6235dbf
commit: 4298d69d4b2f7d0e9d93ad325238930bd6235dbf
branch: main
author: Ken Jin 
committer: Fidget-Spinner 
date: 2024-03-08T00:19:59+08:00
summary:

gh-116420: Fix unused var compilation warnings (GH-116466)

Fix unused var compilation warnings

files:
M Python/optimizer_bytecodes.c
M Python/optimizer_cases.c.h

diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c
index 07a1adb8cb8a78..e3f7c9822103e6 100644
--- a/Python/optimizer_bytecodes.c
+++ b/Python/optimizer_bytecodes.c
@@ -352,6 +352,8 @@ dummy_func(void) {
 }
 
 op(_COMPARE_OP, (left, right -- res)) {
+(void)left;
+(void)right;
 if (oparg & 16) {
 OUT_OF_SPACE_IF_NULL(res = sym_new_type(ctx, &PyBool_Type));
 }
@@ -361,22 +363,32 @@ dummy_func(void) {
 }
 
 op(_COMPARE_OP_INT, (left, right -- res)) {
+(void)left;
+(void)right;
 OUT_OF_SPACE_IF_NULL(res = sym_new_type(ctx, &PyBool_Type));
 }
 
 op(_COMPARE_OP_FLOAT, (left, right -- res)) {
+(void)left;
+(void)right;
 OUT_OF_SPACE_IF_NULL(res = sym_new_type(ctx, &PyBool_Type));
 }
 
 op(_COMPARE_OP_STR, (left, right -- res)) {
+(void)left;
+(void)right;
 OUT_OF_SPACE_IF_NULL(res = sym_new_type(ctx, &PyBool_Type));
 }
 
 op(_IS_OP, (left, right -- res)) {
+(void)left;
+(void)right;
 OUT_OF_SPACE_IF_NULL(res = sym_new_type(ctx, &PyBool_Type));
 }
 
 op(_CONTAINS_OP, (left, right -- res)) {
+(void)left;
+(void)right;
 OUT_OF_SPACE_IF_NULL(res = sym_new_type(ctx, &PyBool_Type));
 }
 
diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h
index a19010cc403681..e4384975643ecd 100644
--- a/Python/optimizer_cases.c.h
+++ b/Python/optimizer_cases.c.h
@@ -1135,6 +1135,8 @@
 _Py_UopsSymbol *res;
 right = stack_pointer[-1];
 left = stack_pointer[-2];
+(void)left;
+(void)right;
 if (oparg & 16) {
 OUT_OF_SPACE_IF_NULL(res = sym_new_type(ctx, &PyBool_Type));
 }
@@ -1152,6 +1154,8 @@
 _Py_UopsSymbol *res;
 right = stack_pointer[-1];
 left = stack_pointer[-2];
+(void)left;
+(void)right;
 OUT_OF_SPACE_IF_NULL(res = sym_new_type(ctx, &PyBool_Type));
 stack_pointer[-2] = res;
 stack_pointer += -1;
@@ -1164,6 +1168,8 @@
 _Py_UopsSymbol *res;
 right = stack_pointer[-1];
 left = stack_pointer[-2];
+(void)left;
+(void)right;
 OUT_OF_SPACE_IF_NULL(res = sym_new_type(ctx, &PyBool_Type));
 stack_pointer[-2] = res;
 stack_pointer += -1;
@@ -1176,6 +1182,8 @@
 _Py_UopsSymbol *res;
 right = stack_pointer[-1];
 left = stack_pointer[-2];
+(void)left;
+(void)right;
 OUT_OF_SPACE_IF_NULL(res = sym_new_type(ctx, &PyBool_Type));
 stack_pointer[-2] = res;
 stack_pointer += -1;
@@ -1188,6 +1196,8 @@
 _Py_UopsSymbol *res;
 right = stack_pointer[-1];
 left = stack_pointer[-2];
+(void)left;
+(void)right;
 OUT_OF_SPACE_IF_NULL(res = sym_new_type(ctx, &PyBool_Type));
 stack_pointer[-2] = res;
 stack_pointer += -1;
@@ -1200,6 +1210,8 @@
 _Py_UopsSymbol *res;
 right = stack_pointer[-1];
 left = stack_pointer[-2];
+(void)left;
+(void)right;
 OUT_OF_SPACE_IF_NULL(res = sym_new_type(ctx, &PyBool_Type));
 stack_pointer[-2] = res;
 stack_pointer += -1;

___
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com


[Python-checkins] gh-116381: Remove bad specializations, add fail stats (GH-116464)

2024-03-07 Thread Fidget-Spinner
https://github.com/python/cpython/commit/41457c7fdb04819d04a528b8dfa72c1aa5745cc9
commit: 41457c7fdb04819d04a528b8dfa72c1aa5745cc9
branch: main
author: Ken Jin 
committer: Fidget-Spinner 
date: 2024-03-08T00:21:21+08:00
summary:

gh-116381: Remove bad specializations, add fail stats (GH-116464)

* Remove bad specializations, add fail stats

files:
M Include/internal/pycore_list.h
M Include/internal/pycore_opcode_metadata.h
M Include/internal/pycore_tuple.h
M Include/internal/pycore_uop_ids.h
M Include/internal/pycore_uop_metadata.h
M Include/opcode_ids.h
M Lib/_opcode_metadata.py
M Objects/listobject.c
M Objects/tupleobject.c
M Python/bytecodes.c
M Python/executor_cases.c.h
M Python/generated_cases.c.h
M Python/opcode_targets.h
M Python/optimizer_cases.c.h
M Python/specialize.c
M Tools/jit/template.c

diff --git a/Include/internal/pycore_list.h b/Include/internal/pycore_list.h
index 92cab731bc253b..2a82912e41d557 100644
--- a/Include/internal/pycore_list.h
+++ b/Include/internal/pycore_list.h
@@ -56,8 +56,6 @@ typedef struct {
 
 PyAPI_FUNC(PyObject *)_PyList_FromArraySteal(PyObject *const *src, Py_ssize_t 
n);
 
-PyAPI_FUNC(int) _PyList_Contains(PyObject *aa, PyObject *el);
-
 #ifdef __cplusplus
 }
 #endif
diff --git a/Include/internal/pycore_opcode_metadata.h 
b/Include/internal/pycore_opcode_metadata.h
index 4c691d6a922862..efb731f1863283 100644
--- a/Include/internal/pycore_opcode_metadata.h
+++ b/Include/internal/pycore_opcode_metadata.h
@@ -153,14 +153,8 @@ int _PyOpcode_num_popped(int opcode, int oparg)  {
 return 2;
 case CONTAINS_OP_DICT:
 return 2;
-case CONTAINS_OP_LIST:
-return 2;
 case CONTAINS_OP_SET:
 return 2;
-case CONTAINS_OP_STR:
-return 2;
-case CONTAINS_OP_TUPLE:
-return 2;
 case CONVERT_VALUE:
 return 1;
 case COPY:
@@ -588,14 +582,8 @@ int _PyOpcode_num_pushed(int opcode, int oparg)  {
 return 1;
 case CONTAINS_OP_DICT:
 return 1;
-case CONTAINS_OP_LIST:
-return 1;
 case CONTAINS_OP_SET:
 return 1;
-case CONTAINS_OP_STR:
-return 1;
-case CONTAINS_OP_TUPLE:
-return 1;
 case CONVERT_VALUE:
 return 1;
 case COPY:
@@ -1024,10 +1012,7 @@ const struct opcode_metadata 
_PyOpcode_opcode_metadata[268] = {
 [COMPARE_OP_STR] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG | 
HAS_EXIT_FLAG | HAS_ESCAPES_FLAG },
 [CONTAINS_OP] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_ERROR_FLAG | 
HAS_ESCAPES_FLAG },
 [CONTAINS_OP_DICT] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG 
| HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
-[CONTAINS_OP_LIST] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG 
| HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
 [CONTAINS_OP_SET] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG | 
HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
-[CONTAINS_OP_STR] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG | 
HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
-[CONTAINS_OP_TUPLE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG 
| HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
 [CONVERT_VALUE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG },
 [COPY] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_PURE_FLAG },
 [COPY_FREE_VARS] = { true, INSTR_FMT_IB, HAS_ARG_FLAG },
@@ -1251,10 +1236,7 @@ _PyOpcode_macro_expansion[256] = {
 [COMPARE_OP_STR] = { .nuops = 2, .uops = { { _GUARD_BOTH_UNICODE, 0, 0 }, 
{ _COMPARE_OP_STR, 0, 0 } } },
 [CONTAINS_OP] = { .nuops = 1, .uops = { { _CONTAINS_OP, 0, 0 } } },
 [CONTAINS_OP_DICT] = { .nuops = 1, .uops = { { _CONTAINS_OP_DICT, 0, 0 } } 
},
-[CONTAINS_OP_LIST] = { .nuops = 1, .uops = { { _CONTAINS_OP_LIST, 0, 0 } } 
},
 [CONTAINS_OP_SET] = { .nuops = 1, .uops = { { _CONTAINS_OP_SET, 0, 0 } } },
-[CONTAINS_OP_STR] = { .nuops = 1, .uops = { { _CONTAINS_OP_STR, 0, 0 } } },
-[CONTAINS_OP_TUPLE] = { .nuops = 1, .uops = { { _CONTAINS_OP_TUPLE, 0, 0 } 
} },
 [CONVERT_VALUE] = { .nuops = 1, .uops = { { _CONVERT_VALUE, 0, 0 } } },
 [COPY] = { .nuops = 1, .uops = { { _COPY, 0, 0 } } },
 [COPY_FREE_VARS] = { .nuops = 1, .uops = { { _COPY_FREE_VARS, 0, 0 } } },
@@ -1429,10 +1411,7 @@ const char *_PyOpcode_OpName[268] = {
 [COMPARE_OP_STR] = "COMPARE_OP_STR",
 [CONTAINS_OP] = "CONTAINS_OP",
 [CONTAINS_OP_DICT] = "CONTAINS_OP_DICT",
-[CONTAINS_OP_LIST] = "CONTAINS_OP_LIST",
 [CONTAINS_OP_SET] = "CONTAINS_OP_SET",
-[CONTAINS_OP_STR] = "CONTAINS_OP_STR",
-[CONTAINS_OP_TUPLE] = "CONTAINS_OP_TUPLE",
 [CONVERT_VALUE] = "CONVERT_VALUE",
 [COPY] = "COPY",
 [COPY_FREE_VARS] = "COPY_FREE_VARS",
@@ -1685,10 +1664,7 @@ const uint8_t _PyOpcode_Deopt[256] = {
 [COMPARE_OP_STR] = COMPARE

[Python-checkins] gh-115419: Change default sym to not_null (GH-116562)

2024-03-13 Thread Fidget-Spinner
https://github.com/python/cpython/commit/617aca9e745b3dfb5e6bc8cda07632d2f716426d
commit: 617aca9e745b3dfb5e6bc8cda07632d2f716426d
branch: main
author: Ken Jin 
committer: Fidget-Spinner 
date: 2024-03-13T20:57:48+08:00
summary:

gh-115419: Change default sym to not_null (GH-116562)

files:
M Lib/test/test_generated_cases.py
M Python/optimizer_bytecodes.c
M Python/optimizer_cases.c.h
M Tools/cases_generator/optimizer_generator.py

diff --git a/Lib/test/test_generated_cases.py b/Lib/test/test_generated_cases.py
index 32c2c2fca05c4e..7b9dd36f85454f 100644
--- a/Lib/test/test_generated_cases.py
+++ b/Lib/test/test_generated_cases.py
@@ -908,7 +908,7 @@ def test_overridden_abstract_args(self):
 
 case OP2: {
 _Py_UopsSymbol *out;
-out = sym_new_unknown(ctx);
+out = sym_new_not_null(ctx);
 if (out == NULL) goto out_of_space;
 stack_pointer[-1] = out;
 break;
@@ -933,7 +933,7 @@ def test_no_overridden_case(self):
 output = """
 case OP: {
 _Py_UopsSymbol *out;
-out = sym_new_unknown(ctx);
+out = sym_new_not_null(ctx);
 if (out == NULL) goto out_of_space;
 stack_pointer[-1] = out;
 break;
diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c
index e3f7c9822103e6..54abbcd74d7934 100644
--- a/Python/optimizer_bytecodes.c
+++ b/Python/optimizer_bytecodes.c
@@ -449,6 +449,14 @@ dummy_func(void) {
 }
 }
 
+op(_LOAD_ATTR, (owner -- attr, self_or_null if (oparg & 1))) {
+(void)owner;
+OUT_OF_SPACE_IF_NULL(attr = sym_new_not_null(ctx));
+if (oparg & 1) {
+OUT_OF_SPACE_IF_NULL(self_or_null = sym_new_unknown(ctx));
+}
+}
+
 op(_LOAD_ATTR_MODULE, (index/1, owner -- attr, null if (oparg & 1))) {
 (void)index;
 OUT_OF_SPACE_IF_NULL(null = sym_new_null(ctx));
@@ -513,7 +521,6 @@ dummy_func(void) {
 OUT_OF_SPACE_IF_NULL(self = sym_new_not_null(ctx));
 }
 
-
 op(_CHECK_FUNCTION_EXACT_ARGS, (func_version/2, callable, self_or_null, 
unused[oparg] -- callable, self_or_null, unused[oparg])) {
 if (!sym_set_type(callable, &PyFunction_Type)) {
 goto hit_bottom;
diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h
index fed5730d2e50c1..7e4214cc9acf39 100644
--- a/Python/optimizer_cases.c.h
+++ b/Python/optimizer_cases.c.h
@@ -80,7 +80,7 @@
 
 case _END_SEND: {
 _Py_UopsSymbol *value;
-value = sym_new_unknown(ctx);
+value = sym_new_not_null(ctx);
 if (value == NULL) goto out_of_space;
 stack_pointer[-2] = value;
 stack_pointer += -1;
@@ -89,7 +89,7 @@
 
 case _UNARY_NEGATIVE: {
 _Py_UopsSymbol *res;
-res = sym_new_unknown(ctx);
+res = sym_new_not_null(ctx);
 if (res == NULL) goto out_of_space;
 stack_pointer[-1] = res;
 break;
@@ -97,7 +97,7 @@
 
 case _UNARY_NOT: {
 _Py_UopsSymbol *res;
-res = sym_new_unknown(ctx);
+res = sym_new_not_null(ctx);
 if (res == NULL) goto out_of_space;
 stack_pointer[-1] = res;
 break;
@@ -205,7 +205,7 @@
 
 case _REPLACE_WITH_TRUE: {
 _Py_UopsSymbol *res;
-res = sym_new_unknown(ctx);
+res = sym_new_not_null(ctx);
 if (res == NULL) goto out_of_space;
 stack_pointer[-1] = res;
 break;
@@ -213,7 +213,7 @@
 
 case _UNARY_INVERT: {
 _Py_UopsSymbol *res;
-res = sym_new_unknown(ctx);
+res = sym_new_not_null(ctx);
 if (res == NULL) goto out_of_space;
 stack_pointer[-1] = res;
 break;
@@ -482,7 +482,7 @@
 
 case _BINARY_SUBSCR: {
 _Py_UopsSymbol *res;
-res = sym_new_unknown(ctx);
+res = sym_new_not_null(ctx);
 if (res == NULL) goto out_of_space;
 stack_pointer[-2] = res;
 stack_pointer += -1;
@@ -491,7 +491,7 @@
 
 case _BINARY_SLICE: {
 _Py_UopsSymbol *res;
-res = sym_new_unknown(ctx);
+res = sym_new_not_null(ctx);
 if (res == NULL) goto out_of_space;
 stack_pointer[-3] = res;
 stack_pointer += -2;
@@ -505,7 +505,7 @@
 
 case _BINARY_SUBSCR_LIST_INT: {
 _Py_UopsSymbol *res;
-res = sym_new_unknown(ctx);
+res = sym_new_not_null(ctx);
 if (res == NULL) goto out_of_space;
 stack_pointer[-2] = res;
 stack_pointer += -1;
@@ -514,7 +514,7 @@
 
 case _BINARY_SUBSCR_STR_INT: {
 _Py_UopsSymbol *res;
-res = sym_new_unknown(ctx);
+res = sym_new_not_null(ctx);
 if (res == NULL) goto out_of_space

[Python-checkins] gh-116760: Fix pystats for trace attempts (GH-116761)

2024-03-13 Thread Fidget-Spinner
https://github.com/python/cpython/commit/cef0ec1a3ca40db69b56bcd736c1b3bb05a1cf48
commit: cef0ec1a3ca40db69b56bcd736c1b3bb05a1cf48
branch: main
author: Michael Droettboom 
committer: Fidget-Spinner 
date: 2024-03-13T22:13:33Z
summary:

gh-116760: Fix pystats for trace attempts (GH-116761)

There are now at least two bytecodes that may attempt to optimize,
JUMP_BACK, and more recently, COLD_EXIT.

Only the JUMP_BACK was counting the attempt in the stats.
This moves that counter to uop_optimize itself so it should
always happen no matter where it is called from.

files:
M Python/bytecodes.c
M Python/generated_cases.c.h
M Python/optimizer.c

diff --git a/Python/bytecodes.c b/Python/bytecodes.c
index ec05e40bd23fcb..af2e2c8f52ee29 100644
--- a/Python/bytecodes.c
+++ b/Python/bytecodes.c
@@ -2349,7 +2349,6 @@ dummy_func(
 // Use '>=' not '>' so that the optimizer/backoff bits do not 
effect the result.
 // Double-check that the opcode isn't instrumented or something:
 if (offset_counter >= threshold && this_instr->op.code == 
JUMP_BACKWARD) {
-OPT_STAT_INC(attempts);
 _Py_CODEUNIT *start = this_instr;
 /* Back up over EXTENDED_ARGs so optimizer sees the whole 
instruction */
 while (oparg > 255) {
diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h
index 72892725fb25d8..7d02e49d040c23 100644
--- a/Python/generated_cases.c.h
+++ b/Python/generated_cases.c.h
@@ -3371,7 +3371,6 @@
 // Use '>=' not '>' so that the optimizer/backoff bits do not 
effect the result.
 // Double-check that the opcode isn't instrumented or something:
 if (offset_counter >= threshold && this_instr->op.code == 
JUMP_BACKWARD) {
-OPT_STAT_INC(attempts);
 _Py_CODEUNIT *start = this_instr;
 /* Back up over EXTENDED_ARGs so optimizer sees the whole 
instruction */
 while (oparg > 255) {
diff --git a/Python/optimizer.c b/Python/optimizer.c
index aaf75b2339cd2e..88c45f2e73c682 100644
--- a/Python/optimizer.c
+++ b/Python/optimizer.c
@@ -1003,6 +1003,7 @@ uop_optimize(
 _PyBloomFilter dependencies;
 _Py_BloomFilter_Init(&dependencies);
 _PyUOpInstruction buffer[UOP_MAX_TRACE_LENGTH];
+OPT_STAT_INC(attempts);
 int err = translate_bytecode_to_trace(frame, instr, buffer, 
UOP_MAX_TRACE_LENGTH, &dependencies);
 if (err <= 0) {
 // Error or nothing translated

___
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com


[Python-checkins] gh-116879: Add new optimizer pystats to tables (GH-116880)

2024-03-16 Thread Fidget-Spinner
https://github.com/python/cpython/commit/1a33513f99bf4a9e5122b9cd82945879e73ff44c
commit: 1a33513f99bf4a9e5122b9cd82945879e73ff44c
branch: main
author: Michael Droettboom 
committer: Fidget-Spinner 
date: 2024-03-16T23:10:43+08:00
summary:

gh-116879: Add new optimizer pystats to tables (GH-116880)

files:
M Tools/scripts/summarize_stats.py

diff --git a/Tools/scripts/summarize_stats.py b/Tools/scripts/summarize_stats.py
index 2925e096f4d95e..6af14e1b769b80 100644
--- a/Tools/scripts/summarize_stats.py
+++ b/Tools/scripts/summarize_stats.py
@@ -459,10 +459,7 @@ def get_optimization_stats(self) -> dict[str, tuple[int, 
int | None]]:
 "The number of times a potential trace is identified.  
Specifically, this "
 "occurs in the JUMP BACKWARD instruction when the counter 
reaches a "
 "threshold.",
-): (
-attempts,
-None,
-),
+): (attempts, None),
 Doc(
 "Traces created", "The number of traces that were successfully 
created."
 ): (created, attempts),
@@ -512,6 +509,26 @@ def get_optimization_stats(self) -> dict[str, tuple[int, 
int | None]]:
 ),
 }
 
+def get_optimizer_stats(self) -> dict[str, tuple[int, int | None]]:
+attempts = self._data["Optimization optimizer attempts"]
+successes = self._data["Optimization optimizer successes"]
+no_memory = self._data["Optimization optimizer failure no memory"]
+
+return {
+Doc(
+"Optimizer attempts",
+"The number of times the trace optimizer 
(_Py_uop_analyze_and_optimize) was run.",
+): (attempts, None),
+Doc(
+"Optimizer successes",
+"The number of traces that were successfully optimized.",
+): (successes, attempts),
+Doc(
+"Optimizer no memory",
+"The number of optimizations that failed due to no memory.",
+): (no_memory, attempts),
+}
+
 def get_histogram(self, prefix: str) -> list[tuple[int, int]]:
 rows = []
 for k, v in self._data.items():
@@ -1118,6 +1135,14 @@ def calc_optimization_table(stats: Stats) -> Rows:
 for label, (value, den) in optimization_stats.items()
 ]
 
+def calc_optimizer_table(stats: Stats) -> Rows:
+optimizer_stats = stats.get_optimizer_stats()
+
+return [
+(label, Count(value), Ratio(value, den))
+for label, (value, den) in optimizer_stats.items()
+]
+
 def calc_histogram_table(key: str, den: str) -> RowCalculator:
 def calc(stats: Stats) -> Rows:
 histogram = stats.get_histogram(key)
@@ -1159,6 +1184,7 @@ def iter_optimization_tables(base_stats: Stats, 
head_stats: Stats | None = None)
 return
 
 yield Table(("", "Count:", "Ratio:"), calc_optimization_table, 
JoinMode.CHANGE)
+yield Table(("", "Count:", "Ratio:"), calc_optimizer_table, 
JoinMode.CHANGE)
 for name, den in [
 ("Trace length", "Optimization traces created"),
 ("Optimized trace length", "Optimization traces created"),

___
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com


[Python-checkins] gh-116996: Add pystats about _Py_uop_analyse_and_optimize (GH-116997)

2024-03-21 Thread Fidget-Spinner
https://github.com/python/cpython/commit/50369e6c34d05222e5a0ec9443a9f7b230e83112
commit: 50369e6c34d05222e5a0ec9443a9f7b230e83112
branch: main
author: Michael Droettboom 
committer: Fidget-Spinner 
date: 2024-03-22T01:27:46+08:00
summary:

gh-116996: Add pystats about _Py_uop_analyse_and_optimize (GH-116997)

files:
M Include/cpython/pystats.h
M Include/internal/pycore_code.h
M Python/optimizer_analysis.c
M Python/specialize.c
M Tools/scripts/summarize_stats.py

diff --git a/Include/cpython/pystats.h b/Include/cpython/pystats.h
index 887fbbedf88502..5bf7bacd514699 100644
--- a/Include/cpython/pystats.h
+++ b/Include/cpython/pystats.h
@@ -19,6 +19,8 @@
 // Define _PY_INTERPRETER macro to increment interpreter_increfs and
 // interpreter_decrefs. Otherwise, increment increfs and decrefs.
 
+#include "pycore_uop_ids.h"
+
 #ifndef Py_CPYTHON_PYSTATS_H
 #  error "this header file must not be included directly"
 #endif
@@ -116,7 +118,7 @@ typedef struct _optimization_stats {
 uint64_t recursive_call;
 uint64_t low_confidence;
 uint64_t executors_invalidated;
-UOpStats opcode[512];
+UOpStats opcode[MAX_UOP_ID];
 uint64_t unsupported_opcode[256];
 uint64_t trace_length_hist[_Py_UOP_HIST_SIZE];
 uint64_t trace_run_length_hist[_Py_UOP_HIST_SIZE];
@@ -124,6 +126,9 @@ typedef struct _optimization_stats {
 uint64_t optimizer_attempts;
 uint64_t optimizer_successes;
 uint64_t optimizer_failure_reason_no_memory;
+uint64_t remove_globals_builtins_changed;
+uint64_t remove_globals_incorrect_keys;
+uint64_t error_in_opcode[MAX_UOP_ID];
 } OptimizationStats;
 
 typedef struct _rare_event_stats {
diff --git a/Include/internal/pycore_code.h b/Include/internal/pycore_code.h
index 8eabd49a18afa9..e004783ee48198 100644
--- a/Include/internal/pycore_code.h
+++ b/Include/internal/pycore_code.h
@@ -308,6 +308,7 @@ extern int _PyStaticCode_Init(PyCodeObject *co);
 #define OPT_STAT_INC(name) do { if (_Py_stats) 
_Py_stats->optimization_stats.name++; } while (0)
 #define UOP_STAT_INC(opname, name) do { if (_Py_stats) { assert(opname < 512); 
_Py_stats->optimization_stats.opcode[opname].name++; } } while (0)
 #define OPT_UNSUPPORTED_OPCODE(opname) do { if (_Py_stats) 
_Py_stats->optimization_stats.unsupported_opcode[opname]++; } while (0)
+#define OPT_ERROR_IN_OPCODE(opname) do { if (_Py_stats) 
_Py_stats->optimization_stats.error_in_opcode[opname]++; } while (0)
 #define OPT_HIST(length, name) \
 do { \
 if (_Py_stats) { \
@@ -334,6 +335,7 @@ PyAPI_FUNC(PyObject*) _Py_GetSpecializationStats(void);
 #define OPT_STAT_INC(name) ((void)0)
 #define UOP_STAT_INC(opname, name) ((void)0)
 #define OPT_UNSUPPORTED_OPCODE(opname) ((void)0)
+#define OPT_ERROR_IN_OPCODE(opname) ((void)0)
 #define OPT_HIST(length, name) ((void)0)
 #define RARE_EVENT_STAT_INC(name) ((void)0)
 #endif  // !Py_STATS
diff --git a/Python/optimizer_analysis.c b/Python/optimizer_analysis.c
index 603ac6815665ca..6c460c5359d71e 100644
--- a/Python/optimizer_analysis.c
+++ b/Python/optimizer_analysis.c
@@ -139,6 +139,7 @@ remove_globals(_PyInterpreterFrame *frame, 
_PyUOpInstruction *buffer,
 PyInterpreterState *interp = _PyInterpreterState_GET();
 PyObject *builtins = frame->f_builtins;
 if (builtins != interp->builtins) {
+OPT_STAT_INC(remove_globals_builtins_changed);
 return 1;
 }
 PyObject *globals = frame->f_globals;
@@ -170,6 +171,7 @@ remove_globals(_PyInterpreterFrame *frame, 
_PyUOpInstruction *buffer,
 switch(opcode) {
 case _GUARD_BUILTINS_VERSION:
 if (incorrect_keys(inst, builtins)) {
+OPT_STAT_INC(remove_globals_incorrect_keys);
 return 0;
 }
 if (interp->rare_events.builtin_dict >= 
_Py_MAX_ALLOWED_BUILTINS_MODIFICATIONS) {
@@ -190,6 +192,7 @@ remove_globals(_PyInterpreterFrame *frame, 
_PyUOpInstruction *buffer,
 break;
 case _GUARD_GLOBALS_VERSION:
 if (incorrect_keys(inst, globals)) {
+OPT_STAT_INC(remove_globals_incorrect_keys);
 return 0;
 }
 uint64_t watched_mutations = get_mutations(globals);
@@ -238,6 +241,7 @@ remove_globals(_PyInterpreterFrame *frame, 
_PyUOpInstruction *buffer,
 globals = func->func_globals;
 builtins = func->func_builtins;
 if (builtins != interp->builtins) {
+OPT_STAT_INC(remove_globals_builtins_changed);
 return 1;
 }
 break;
@@ -358,6 +362,7 @@ optimize_uops(
 
 _Py_UOpsContext context;
 _Py_UOpsContext *ctx = &context;
+uint32_t opcode = UINT16_MAX;
 
 if (_Py_uop_abstractcontext_init(ctx) < 0) {
 goto out_of_space;
@@ -374,8 +379,7 @@ optimize_uops(
  this_instr++) {
 
 int oparg 

[Python-checkins] gh-117180: Complete call sequence when trace stack overflow (GH-117184)

2024-03-23 Thread Fidget-Spinner
https://github.com/python/cpython/commit/6c83352bfe78a7d567c8d76257df6eb91d5a7245
commit: 6c83352bfe78a7d567c8d76257df6eb91d5a7245
branch: main
author: Ken Jin 
committer: Fidget-Spinner 
date: 2024-03-24T06:19:17+08:00
summary:

gh-117180: Complete call sequence when trace stack overflow (GH-117184)


-

Co-authored-by: Peter Lazorchak 
Co-authored-by: Guido van Rossum 
Co-authored-by: Guido van Rossum 

files:
M Lib/test/test_capi/test_opt.py
M Python/optimizer.c

diff --git a/Lib/test/test_capi/test_opt.py b/Lib/test/test_capi/test_opt.py
index b0859a382de523..a1dc03dd3b651b 100644
--- a/Lib/test/test_capi/test_opt.py
+++ b/Lib/test/test_capi/test_opt.py
@@ -955,6 +955,32 @@ def testfunc(n):
 _, ex = self._run_with_optimizer(testfunc, 16)
 self.assertIsNone(ex)
 
+def test_many_nested(self):
+# overflow the trace_stack
+def dummy_a(x):
+return x
+def dummy_b(x):
+return dummy_a(x)
+def dummy_c(x):
+return dummy_b(x)
+def dummy_d(x):
+return dummy_c(x)
+def dummy_e(x):
+return dummy_d(x)
+def dummy_f(x):
+return dummy_e(x)
+def dummy_g(x):
+return dummy_f(x)
+def dummy_h(x):
+return dummy_g(x)
+def testfunc(n):
+a = 0
+for _ in range(n):
+a += dummy_h(n)
+return a
+
+self._run_with_optimizer(testfunc, 32)
+
 
 if __name__ == "__main__":
 unittest.main()
diff --git a/Python/optimizer.c b/Python/optimizer.c
index 177ad343618c37..f8c1390a061650 100644
--- a/Python/optimizer.c
+++ b/Python/optimizer.c
@@ -476,6 +476,7 @@ BRANCH_TO_GUARD[4][2] = {
 if (trace_stack_depth >= TRACE_STACK_SIZE) { \
 DPRINTF(2, "Trace stack overflow\n"); \
 OPT_STAT_INC(trace_stack_overflow); \
+ADD_TO_TRACE(uop, oparg, operand, target); \
 ADD_TO_TRACE(_EXIT_TRACE, 0, 0, 0); \
 goto done; \
 } \

___
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com


[Python-checkins] gh-117339: Use NULL instead of None for LOAD_SUPER_ATTR in dis docs (GH-117343)

2024-03-28 Thread Fidget-Spinner
https://github.com/python/cpython/commit/a17f313e3958e825db9a83594c8471a984316536
commit: a17f313e3958e825db9a83594c8471a984316536
branch: main
author: Christopher Chianelli 
committer: Fidget-Spinner 
date: 2024-03-29T06:26:56+08:00
summary:

gh-117339: Use NULL instead of None for LOAD_SUPER_ATTR in dis docs (GH-117343)

files:
M Doc/library/dis.rst

diff --git a/Doc/library/dis.rst b/Doc/library/dis.rst
index 190e994a12cc71..21ac2c87a1859e 100644
--- a/Doc/library/dis.rst
+++ b/Doc/library/dis.rst
@@ -1224,7 +1224,7 @@ iterations of the loop.
except that ``namei`` is shifted left by 2 bits instead of 1.
 
The low bit of ``namei`` signals to attempt a method load, as with
-   :opcode:`LOAD_ATTR`, which results in pushing ``None`` and the loaded 
method.
+   :opcode:`LOAD_ATTR`, which results in pushing ``NULL`` and the loaded 
method.
When it is unset a single value is pushed to the stack.
 
The second-low bit of ``namei``, if set, means that this was a two-argument

___
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com


[Python-checkins] [3.12] gh-117339: Use NULL instead of None for LOAD_SUPER_ATTR in dis docs (GH-117343) (GH-117345)

2024-03-28 Thread Fidget-Spinner
https://github.com/python/cpython/commit/655c4255fcb8ff73a720db7d5aa4dbb9b2e809e6
commit: 655c4255fcb8ff73a720db7d5aa4dbb9b2e809e6
branch: 3.12
author: Christopher Chianelli 
committer: Fidget-Spinner 
date: 2024-03-29T06:27:16+08:00
summary:

[3.12] gh-117339: Use NULL instead of None for LOAD_SUPER_ATTR in dis docs 
(GH-117343) (GH-117345)

files:
M Doc/library/dis.rst

diff --git a/Doc/library/dis.rst b/Doc/library/dis.rst
index abcc3cde23526c..2dd11e03894f99 100644
--- a/Doc/library/dis.rst
+++ b/Doc/library/dis.rst
@@ -1116,7 +1116,7 @@ iterations of the loop.
except that ``namei`` is shifted left by 2 bits instead of 1.
 
The low bit of ``namei`` signals to attempt a method load, as with
-   :opcode:`LOAD_ATTR`, which results in pushing ``None`` and the loaded 
method.
+   :opcode:`LOAD_ATTR`, which results in pushing ``NULL`` and the loaded 
method.
When it is unset a single value is pushed to the stack.
 
The second-low bit of ``namei``, if set, means that this was a two-argument

___
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com


[Python-checkins] Cases generator: Remove type_prop and passthrough (#117614)

2024-04-07 Thread Fidget-Spinner
https://github.com/python/cpython/commit/375425abd17310480988c48fba57b01e8c979e07
commit: 375425abd17310480988c48fba57b01e8c979e07
branch: main
author: Ken Jin 
committer: Fidget-Spinner 
date: 2024-04-08T06:26:52+08:00
summary:

Cases generator: Remove type_prop and passthrough (#117614)

files:
M Include/internal/pycore_uop_metadata.h
M Tools/cases_generator/analyzer.py
M Tools/cases_generator/generators_common.py

diff --git a/Include/internal/pycore_uop_metadata.h 
b/Include/internal/pycore_uop_metadata.h
index 111824a938f6cc..e5a99421c241e0 100644
--- a/Include/internal/pycore_uop_metadata.h
+++ b/Include/internal/pycore_uop_metadata.h
@@ -51,22 +51,22 @@ const uint16_t _PyUop_Flags[MAX_UOP_ID+1] = {
 [_UNARY_NEGATIVE] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG,
 [_UNARY_NOT] = HAS_PURE_FLAG,
 [_TO_BOOL] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG,
-[_TO_BOOL_BOOL] = HAS_EXIT_FLAG | HAS_PASSTHROUGH_FLAG,
+[_TO_BOOL_BOOL] = HAS_EXIT_FLAG,
 [_TO_BOOL_INT] = HAS_EXIT_FLAG,
 [_TO_BOOL_LIST] = HAS_EXIT_FLAG,
 [_TO_BOOL_NONE] = HAS_EXIT_FLAG,
 [_TO_BOOL_STR] = HAS_EXIT_FLAG,
 [_REPLACE_WITH_TRUE] = 0,
 [_UNARY_INVERT] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG,
-[_GUARD_BOTH_INT] = HAS_EXIT_FLAG | HAS_PASSTHROUGH_FLAG,
+[_GUARD_BOTH_INT] = HAS_EXIT_FLAG,
 [_BINARY_OP_MULTIPLY_INT] = HAS_ERROR_FLAG | HAS_PURE_FLAG,
 [_BINARY_OP_ADD_INT] = HAS_ERROR_FLAG | HAS_PURE_FLAG,
 [_BINARY_OP_SUBTRACT_INT] = HAS_ERROR_FLAG | HAS_PURE_FLAG,
-[_GUARD_BOTH_FLOAT] = HAS_EXIT_FLAG | HAS_PASSTHROUGH_FLAG,
+[_GUARD_BOTH_FLOAT] = HAS_EXIT_FLAG,
 [_BINARY_OP_MULTIPLY_FLOAT] = HAS_PURE_FLAG,
 [_BINARY_OP_ADD_FLOAT] = HAS_PURE_FLAG,
 [_BINARY_OP_SUBTRACT_FLOAT] = HAS_PURE_FLAG,
-[_GUARD_BOTH_UNICODE] = HAS_EXIT_FLAG | HAS_PASSTHROUGH_FLAG,
+[_GUARD_BOTH_UNICODE] = HAS_EXIT_FLAG,
 [_BINARY_OP_ADD_UNICODE] = HAS_ERROR_FLAG | HAS_PURE_FLAG,
 [_BINARY_SUBSCR] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG,
 [_BINARY_SLICE] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG,
@@ -129,23 +129,23 @@ const uint16_t _PyUop_Flags[MAX_UOP_ID+1] = {
 [_LOAD_SUPER_ATTR_ATTR] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_DEOPT_FLAG | 
HAS_ERROR_FLAG | HAS_ESCAPES_FLAG,
 [_LOAD_SUPER_ATTR_METHOD] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_DEOPT_FLAG 
| HAS_ERROR_FLAG | HAS_ESCAPES_FLAG,
 [_LOAD_ATTR] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | 
HAS_ESCAPES_FLAG,
-[_GUARD_TYPE_VERSION] = HAS_EXIT_FLAG | HAS_PASSTHROUGH_FLAG,
-[_CHECK_MANAGED_OBJECT_HAS_VALUES] = HAS_DEOPT_FLAG | HAS_PASSTHROUGH_FLAG,
+[_GUARD_TYPE_VERSION] = HAS_EXIT_FLAG,
+[_CHECK_MANAGED_OBJECT_HAS_VALUES] = HAS_DEOPT_FLAG,
 [_LOAD_ATTR_INSTANCE_VALUE_0] = HAS_DEOPT_FLAG,
 [_LOAD_ATTR_INSTANCE_VALUE_1] = HAS_DEOPT_FLAG,
 [_LOAD_ATTR_INSTANCE_VALUE] = HAS_ARG_FLAG | HAS_DEOPT_FLAG | 
HAS_OPARG_AND_1_FLAG,
-[_CHECK_ATTR_MODULE] = HAS_DEOPT_FLAG | HAS_PASSTHROUGH_FLAG,
+[_CHECK_ATTR_MODULE] = HAS_DEOPT_FLAG,
 [_LOAD_ATTR_MODULE] = HAS_ARG_FLAG | HAS_DEOPT_FLAG,
-[_CHECK_ATTR_WITH_HINT] = HAS_DEOPT_FLAG | HAS_PASSTHROUGH_FLAG,
+[_CHECK_ATTR_WITH_HINT] = HAS_DEOPT_FLAG,
 [_LOAD_ATTR_WITH_HINT] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_DEOPT_FLAG,
 [_LOAD_ATTR_SLOT_0] = HAS_DEOPT_FLAG,
 [_LOAD_ATTR_SLOT_1] = HAS_DEOPT_FLAG,
 [_LOAD_ATTR_SLOT] = HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_OPARG_AND_1_FLAG,
-[_CHECK_ATTR_CLASS] = HAS_DEOPT_FLAG | HAS_PASSTHROUGH_FLAG,
+[_CHECK_ATTR_CLASS] = HAS_DEOPT_FLAG,
 [_LOAD_ATTR_CLASS_0] = 0,
 [_LOAD_ATTR_CLASS_1] = 0,
 [_LOAD_ATTR_CLASS] = HAS_ARG_FLAG | HAS_OPARG_AND_1_FLAG,
-[_GUARD_DORV_NO_DICT] = HAS_DEOPT_FLAG | HAS_PASSTHROUGH_FLAG,
+[_GUARD_DORV_NO_DICT] = HAS_DEOPT_FLAG,
 [_STORE_ATTR_INSTANCE_VALUE] = 0,
 [_STORE_ATTR_SLOT] = HAS_ESCAPES_FLAG,
 [_COMPARE_OP] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG,
@@ -167,31 +167,31 @@ const uint16_t _PyUop_Flags[MAX_UOP_ID+1] = {
 [_GET_ITER] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG,
 [_GET_YIELD_FROM_ITER] = HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | 
HAS_ESCAPES_FLAG,
 [_FOR_ITER_TIER_TWO] = HAS_DEOPT_FLAG | HAS_ERROR_FLAG | 
HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG,
-[_ITER_CHECK_LIST] = HAS_DEOPT_FLAG | HAS_PASSTHROUGH_FLAG,
-[_GUARD_NOT_EXHAUSTED_LIST] = HAS_DEOPT_FLAG | HAS_PASSTHROUGH_FLAG,
+[_ITER_CHECK_LIST] = HAS_DEOPT_FLAG,
+[_GUARD_NOT_EXHAUSTED_LIST] = HAS_DEOPT_FLAG,
 [_ITER_NEXT_LIST] = 0,
-[_ITER_CHECK_TUPLE] = HAS_DEOPT_FLAG | HAS_PASSTHROUGH_FLAG,
-[_GUARD_NOT_EXHAUSTED_TUPLE] = HAS_DEOPT_FLAG | HAS_PASSTHROUGH_FLAG,
+[_ITER_CHECK_TUPLE] = HAS_DEOPT_FLAG,
+[_GUARD_NOT_EXHAUSTED_TUPLE] = HAS_DEOPT_FLAG,
 [_ITER_NEXT_TUPLE] = 0,
-[_ITER_CHECK_RANGE] = HAS_DEOPT_FLAG | HAS_PASSTHROUGH_FLAG,
-[_GUARD_NOT_EXHAUSTED_RANGE] = HAS_DEOPT_FLAG | HAS_PASSTHROUGH_FLAG,
+[_ITER_CHECK_RANGE] = HAS_DEOPT_FLAG,
+[_GUARD_NOT_EXHAUSTED_RANGE] = HAS_DEOPT_FLAG

[Python-checkins] gh-117139: Add header for tagged pointers (GH-118330)

2024-04-30 Thread Fidget-Spinner
https://github.com/python/cpython/commit/dc6b12d1b2ea26bb0323d932fa7b1a337eaca562
commit: dc6b12d1b2ea26bb0323d932fa7b1a337eaca562
branch: main
author: Ken Jin 
committer: Fidget-Spinner 
date: 2024-05-01T04:46:13+08:00
summary:

gh-117139: Add header for tagged pointers (GH-118330)



-

Co-authored-by: Sam Gross <655866+colesb...@users.noreply.github.com>

files:
A Include/internal/pycore_stackref.h
M Makefile.pre.in
M PCbuild/pythoncore.vcxproj
M PCbuild/pythoncore.vcxproj.filters

diff --git a/Include/internal/pycore_stackref.h 
b/Include/internal/pycore_stackref.h
new file mode 100644
index 00..fd929cd4873a8b
--- /dev/null
+++ b/Include/internal/pycore_stackref.h
@@ -0,0 +1,195 @@
+#ifndef Py_INTERNAL_STACKREF_H
+#define Py_INTERNAL_STACKREF_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef Py_BUILD_CORE
+#  error "this header requires Py_BUILD_CORE define"
+#endif
+
+#include 
+
+typedef union {
+uintptr_t bits;
+} _PyStackRef;
+
+static const _PyStackRef Py_STACKREF_NULL = { .bits = 0 };
+
+#define Py_TAG_DEFERRED (1)
+
+// Gets a PyObject * from a _PyStackRef
+#if defined(Py_GIL_DISABLED)
+static inline PyObject *
+PyStackRef_Get(_PyStackRef tagged)
+{
+PyObject *cleared = ((PyObject *)((tagged).bits & (~Py_TAG_DEFERRED)));
+return cleared;
+}
+#else
+#   define PyStackRef_Get(tagged) ((PyObject *)((tagged).bits))
+#endif
+
+// Converts a PyObject * to a PyStackRef, stealing the reference.
+#if defined(Py_GIL_DISABLED)
+static inline _PyStackRef
+_PyStackRef_StealRef(PyObject *obj)
+{
+// Make sure we don't take an already tagged value.
+assert(((uintptr_t)obj & Py_TAG_DEFERRED) == 0);
+return ((_PyStackRef){.bits = ((uintptr_t)(obj))});
+}
+#   define PyStackRef_StealRef(obj) _PyStackRef_StealRef(_PyObject_CAST(obj))
+#else
+#   define PyStackRef_StealRef(obj) ((_PyStackRef){.bits = ((uintptr_t)(obj))})
+#endif
+
+// Converts a PyObject * to a PyStackRef, with a new reference
+#if defined(Py_GIL_DISABLED)
+static inline _PyStackRef
+_PyStackRef_NewRefDeferred(PyObject *obj)
+{
+// Make sure we don't take an already tagged value.
+assert(((uintptr_t)obj & Py_TAG_DEFERRED) == 0);
+assert(obj != NULL);
+if (_PyObject_HasDeferredRefcount(obj)) {
+return (_PyStackRef){ .bits = (uintptr_t)obj | Py_TAG_DEFERRED };
+}
+else {
+return (_PyStackRef){ .bits = (uintptr_t)Py_NewRef(obj) };
+}
+}
+#   define PyStackRef_NewRefDeferred(obj) 
_PyStackRef_NewRefDeferred(_PyObject_CAST(obj))
+#else
+#   define PyStackRef_NewRefDeferred(obj) 
PyStackRef_NewRef(((_PyStackRef){.bits = ((uintptr_t)(obj))}))
+#endif
+
+#if defined(Py_GIL_DISABLED)
+static inline _PyStackRef
+_PyStackRef_XNewRefDeferred(PyObject *obj)
+{
+// Make sure we don't take an already tagged value.
+assert(((uintptr_t)obj & Py_TAG_DEFERRED) == 0);
+if (obj == NULL) {
+return Py_STACKREF_NULL;
+}
+return _PyStackRef_NewRefDeferred(obj);
+}
+#   define PyStackRef_XNewRefDeferred(obj) 
_PyStackRef_XNewRefDeferred(_PyObject_CAST(obj))
+#else
+#   define PyStackRef_XNewRefDeferred(obj) 
PyStackRef_XNewRef(((_PyStackRef){.bits = ((uintptr_t)(obj))}))
+#endif
+
+// Converts a PyStackRef back to a PyObject *.
+#if defined(Py_GIL_DISABLED)
+static inline PyObject *
+PyStackRef_StealObject(_PyStackRef tagged)
+{
+if ((tagged.bits & Py_TAG_DEFERRED) == Py_TAG_DEFERRED) {
+assert(_PyObject_HasDeferredRefcount(PyStackRef_Get(tagged)));
+return Py_NewRef(PyStackRef_Get(tagged));
+}
+return PyStackRef_Get(tagged);
+}
+#else
+#   define PyStackRef_StealObject(tagged) PyStackRef_Get(tagged)
+#endif
+
+static inline void
+_Py_untag_stack_borrowed(PyObject **dst, const _PyStackRef *src, size_t length)
+{
+for (size_t i = 0; i < length; i++) {
+dst[i] = PyStackRef_Get(src[i]);
+}
+}
+
+static inline void
+_Py_untag_stack_steal(PyObject **dst, const _PyStackRef *src, size_t length)
+{
+for (size_t i = 0; i < length; i++) {
+dst[i] = PyStackRef_StealObject(src[i]);
+}
+}
+
+
+#define PyStackRef_XSETREF(dst, src) \
+do { \
+_PyStackRef *_tmp_dst_ptr = &(dst) \
+_PyStackRef _tmp_old_dst = (*_tmp_dst_ptr); \
+*_tmp_dst_ptr = (src); \
+PyStackRef_XDECREF(_tmp_old_dst); \
+} while (0)
+
+#define PyStackRef_SETREF(dst, src) \
+do { \
+_PyStackRef *_tmp_dst_ptr = &(dst); \
+_PyStackRef _tmp_old_dst = (*_tmp_dst_ptr); \
+*_tmp_dst_ptr = (src); \
+PyStackRef_DECREF(_tmp_old_dst); \
+} while (0)
+
+#define PyStackRef_CLEAR(op) \
+do { \
+_PyStackRef *_tmp_op_ptr = &(op); \
+_PyStackRef _tmp_old_op = (*_tmp_op_ptr); \
+if (_tmp_old_op.bits != Py_STACKREF_NULL.bits) { \
+*_tmp_op_ptr = Py_STACKREF_NULL; \
+PyStackRef_DECREF(_tmp_old_op); \
+} \
+} while (0)
+
+#if defined(Py_GIL_

[Python-checkins] gh-117657: Don't specialize RESUME_CHECK when specialization is disabled (GH-118349)

2024-04-30 Thread Fidget-Spinner
https://github.com/python/cpython/commit/7fabcc727dee52a3e0dfe4f903ad414e93cf2dc9
commit: 7fabcc727dee52a3e0dfe4f903ad414e93cf2dc9
branch: main
author: Ken Jin 
committer: Fidget-Spinner 
date: 2024-04-30T21:51:59Z
summary:

gh-117657: Don't specialize RESUME_CHECK when specialization is disabled 
(GH-118349)

files:
M Python/bytecodes.c
M Python/generated_cases.c.h

diff --git a/Python/bytecodes.c b/Python/bytecodes.c
index 5bb7e1211385a5..18837aef74d78e 100644
--- a/Python/bytecodes.c
+++ b/Python/bytecodes.c
@@ -163,7 +163,9 @@ dummy_func(
 if ((oparg & RESUME_OPARG_LOCATION_MASK) < 
RESUME_AFTER_YIELD_FROM) {
 CHECK_EVAL_BREAKER();
 }
+#if ENABLE_SPECIALIZATION
 FT_ATOMIC_STORE_UINT8_RELAXED(this_instr->op.code, 
RESUME_CHECK);
+#endif  /* ENABLE_SPECIALIZATION */
 }
 }
 
diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h
index a5bb29385844d8..1444f5cdebba4b 100644
--- a/Python/generated_cases.c.h
+++ b/Python/generated_cases.c.h
@@ -4955,7 +4955,9 @@
 if ((oparg & RESUME_OPARG_LOCATION_MASK) < 
RESUME_AFTER_YIELD_FROM) {
 CHECK_EVAL_BREAKER();
 }
+#if ENABLE_SPECIALIZATION
 FT_ATOMIC_STORE_UINT8_RELAXED(this_instr->op.code, 
RESUME_CHECK);
+#endif  /* ENABLE_SPECIALIZATION */
 }
 DISPATCH();
 }

___
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com


[Python-checkins] gh-117139: Fix missing semicolon (GH-118573)

2024-05-04 Thread Fidget-Spinner
https://github.com/python/cpython/commit/978fba58aef347de4a1376e525df2dacc7b2fff3
commit: 978fba58aef347de4a1376e525df2dacc7b2fff3
branch: main
author: Ken Jin 
committer: Fidget-Spinner 
date: 2024-05-04T15:45:49Z
summary:

gh-117139: Fix missing semicolon (GH-118573)

files:
M Include/internal/pycore_stackref.h

diff --git a/Include/internal/pycore_stackref.h 
b/Include/internal/pycore_stackref.h
index fd929cd4873a8b..93898174789f7b 100644
--- a/Include/internal/pycore_stackref.h
+++ b/Include/internal/pycore_stackref.h
@@ -114,7 +114,7 @@ _Py_untag_stack_steal(PyObject **dst, const _PyStackRef 
*src, size_t length)
 
 #define PyStackRef_XSETREF(dst, src) \
 do { \
-_PyStackRef *_tmp_dst_ptr = &(dst) \
+_PyStackRef *_tmp_dst_ptr = &(dst); \
 _PyStackRef _tmp_old_dst = (*_tmp_dst_ptr); \
 *_tmp_dst_ptr = (src); \
 PyStackRef_XDECREF(_tmp_old_dst); \

___
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com


[Python-checkins] gh-89811: Check for valid tp_version_tag in specializer (GH-113558)

2024-01-10 Thread Fidget-Spinner
https://github.com/python/cpython/commit/f653caa5a88d3b5027a8f286ff3a3ccd9e6fe4ed
commit: f653caa5a88d3b5027a8f286ff3a3ccd9e6fe4ed
branch: main
author: Peter Lazorchak 
committer: Fidget-Spinner 
date: 2024-01-11T13:33:05+08:00
summary:

gh-89811: Check for valid tp_version_tag in specializer (GH-113558)

files:
A Misc/NEWS.d/next/Core and 
Builtins/2024-01-03-12-19-37.gh-issue-89811.cZOj6d.rst
M Lib/test/test_type_cache.py
M Modules/_testcapimodule.c
M Python/specialize.c

diff --git a/Lib/test/test_type_cache.py b/Lib/test/test_type_cache.py
index 72587ecc11b6f3..95b55009c7187d 100644
--- a/Lib/test/test_type_cache.py
+++ b/Lib/test/test_type_cache.py
@@ -1,5 +1,6 @@
 """ Tests for the internal type cache in CPython. """
 import unittest
+import dis
 from test import support
 from test.support import import_helper
 try:
@@ -8,8 +9,11 @@
 _clear_type_cache = None
 
 # Skip this test if the _testcapi module isn't available.
-type_get_version = import_helper.import_module('_testcapi').type_get_version
-type_assign_version = 
import_helper.import_module('_testcapi').type_assign_version
+_testcapi = import_helper.import_module("_testcapi")
+type_get_version = _testcapi.type_get_version
+type_assign_specific_version_unsafe = 
_testcapi.type_assign_specific_version_unsafe
+type_assign_version = _testcapi.type_assign_version
+type_modified = _testcapi.type_modified
 
 
 @support.cpython_only
@@ -56,6 +60,183 @@ class C:
 self.assertNotEqual(type_get_version(C), 0)
 self.assertNotEqual(type_get_version(C), c_ver)
 
+def test_type_assign_specific_version(self):
+"""meta-test for type_assign_specific_version_unsafe"""
+class C:
+pass
+
+type_assign_version(C)
+orig_version = type_get_version(C)
+self.assertNotEqual(orig_version, 0)
+
+type_modified(C)
+type_assign_specific_version_unsafe(C, orig_version + 5)
+type_assign_version(C)  # this should do nothing
+
+new_version = type_get_version(C)
+self.assertEqual(new_version, orig_version + 5)
+
+_clear_type_cache()
+
+
+@support.cpython_only
+class TypeCacheWithSpecializationTests(unittest.TestCase):
+def tearDown(self):
+_clear_type_cache()
+
+def _assign_and_check_valid_version(self, user_type):
+type_modified(user_type)
+type_assign_version(user_type)
+self.assertNotEqual(type_get_version(user_type), 0)
+
+def _assign_and_check_version_0(self, user_type):
+type_modified(user_type)
+type_assign_specific_version_unsafe(user_type, 0)
+self.assertEqual(type_get_version(user_type), 0)
+
+def _all_opnames(self, func):
+return set(instr.opname for instr in dis.Bytecode(func, adaptive=True))
+
+def _check_specialization(self, func, arg, opname, *, should_specialize):
+self.assertIn(opname, self._all_opnames(func))
+
+for _ in range(100):
+func(arg)
+
+if should_specialize:
+self.assertNotIn(opname, self._all_opnames(func))
+else:
+self.assertIn(opname, self._all_opnames(func))
+
+def test_class_load_attr_specialization_user_type(self):
+class A:
+def foo(self):
+pass
+
+self._assign_and_check_valid_version(A)
+
+def load_foo_1(type_):
+type_.foo
+
+self._check_specialization(load_foo_1, A, "LOAD_ATTR", 
should_specialize=True)
+del load_foo_1
+
+self._assign_and_check_version_0(A)
+
+def load_foo_2(type_):
+return type_.foo
+
+self._check_specialization(load_foo_2, A, "LOAD_ATTR", 
should_specialize=False)
+
+def test_class_load_attr_specialization_static_type(self):
+self._assign_and_check_valid_version(str)
+self._assign_and_check_valid_version(bytes)
+
+def get_capitalize_1(type_):
+return type_.capitalize
+
+self._check_specialization(get_capitalize_1, str, "LOAD_ATTR", 
should_specialize=True)
+self.assertEqual(get_capitalize_1(str)('hello'), 'Hello')
+self.assertEqual(get_capitalize_1(bytes)(b'hello'), b'Hello')
+del get_capitalize_1
+
+# Permanently overflow the static type version counter, and force str 
and bytes
+# to have tp_version_tag == 0
+for _ in range(2**16):
+type_modified(str)
+type_assign_version(str)
+type_modified(bytes)
+type_assign_version(bytes)
+
+self.assertEqual(type_get_version(str), 0)
+self.assertEqual(type_get_version(bytes), 0)
+
+def get_capitalize_2(type_):
+return type_.capitalize
+
+self._check_specialization(get_capitalize_2, str, "LOAD_ATTR",

[Python-checkins] gh-113937 Fix failures in type cache tests due to re-running (GH-113953)

2024-01-11 Thread Fidget-Spinner
https://github.com/python/cpython/commit/e58334e4c9ccbebce6858da1985c1f75a6063d05
commit: e58334e4c9ccbebce6858da1985c1f75a6063d05
branch: main
author: Peter Lazorchak 
committer: Fidget-Spinner 
date: 2024-01-12T13:18:19+08:00
summary:

gh-113937 Fix failures in type cache tests due to re-running (GH-113953)

files:
M Lib/test/test_type_cache.py

diff --git a/Lib/test/test_type_cache.py b/Lib/test/test_type_cache.py
index 95b55009c7187d..295df78a17374a 100644
--- a/Lib/test/test_type_cache.py
+++ b/Lib/test/test_type_cache.py
@@ -67,7 +67,8 @@ class C:
 
 type_assign_version(C)
 orig_version = type_get_version(C)
-self.assertNotEqual(orig_version, 0)
+if orig_version == 0:
+self.skipTest("Could not assign a valid type version")
 
 type_modified(C)
 type_assign_specific_version_unsafe(C, orig_version + 5)
@@ -84,10 +85,11 @@ class TypeCacheWithSpecializationTests(unittest.TestCase):
 def tearDown(self):
 _clear_type_cache()
 
-def _assign_and_check_valid_version(self, user_type):
-type_modified(user_type)
-type_assign_version(user_type)
-self.assertNotEqual(type_get_version(user_type), 0)
+def _assign_valid_version_or_skip(self, type_):
+type_modified(type_)
+type_assign_version(type_)
+if type_get_version(type_) == 0:
+self.skipTest("Could not assign valid type version")
 
 def _assign_and_check_version_0(self, user_type):
 type_modified(user_type)
@@ -98,8 +100,6 @@ def _all_opnames(self, func):
 return set(instr.opname for instr in dis.Bytecode(func, adaptive=True))
 
 def _check_specialization(self, func, arg, opname, *, should_specialize):
-self.assertIn(opname, self._all_opnames(func))
-
 for _ in range(100):
 func(arg)
 
@@ -113,7 +113,7 @@ class A:
 def foo(self):
 pass
 
-self._assign_and_check_valid_version(A)
+self._assign_valid_version_or_skip(A)
 
 def load_foo_1(type_):
 type_.foo
@@ -129,8 +129,8 @@ def load_foo_2(type_):
 self._check_specialization(load_foo_2, A, "LOAD_ATTR", 
should_specialize=False)
 
 def test_class_load_attr_specialization_static_type(self):
-self._assign_and_check_valid_version(str)
-self._assign_and_check_valid_version(bytes)
+self._assign_valid_version_or_skip(str)
+self._assign_valid_version_or_skip(bytes)
 
 def get_capitalize_1(type_):
 return type_.capitalize
@@ -164,7 +164,7 @@ class G:
 def x(self):
 return 9
 
-self._assign_and_check_valid_version(G)
+self._assign_valid_version_or_skip(G)
 
 def load_x_1(instance):
 instance.x
@@ -183,7 +183,7 @@ def test_store_attr_specialization_user_type(self):
 class B:
 __slots__ = ("bar",)
 
-self._assign_and_check_valid_version(B)
+self._assign_valid_version_or_skip(B)
 
 def store_bar_1(type_):
 type_.bar = 10
@@ -203,7 +203,7 @@ class F:
 def __init__(self):
 pass
 
-self._assign_and_check_valid_version(F)
+self._assign_valid_version_or_skip(F)
 
 def call_class_1(type_):
 type_()
@@ -222,7 +222,7 @@ def test_to_bool_specialization_user_type(self):
 class H:
 pass
 
-self._assign_and_check_valid_version(H)
+self._assign_valid_version_or_skip(H)
 
 def to_bool_1(instance):
 not instance

___
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com


[Python-checkins] gh-113710: Add types to the interpreter DSL (#113711)

2024-01-12 Thread Fidget-Spinner
https://github.com/python/cpython/commit/ac92527c08d917dffdb9c0a218d06f21114614a2
commit: ac92527c08d917dffdb9c0a218d06f21114614a2
branch: main
author: Ken Jin 
committer: Fidget-Spinner 
date: 2024-01-13T01:30:27+08:00
summary:

gh-113710: Add types to the interpreter DSL (#113711)

Co-authored-by: Jules <57632293+julia...@users.noreply.github.com>
Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com>

files:
A Misc/NEWS.d/next/Core and 
Builtins/2024-01-09-23-01-00.gh-issue-113710.pe3flY.rst
M Include/internal/pycore_opcode_metadata.h
M Include/internal/pycore_uop_ids.h
M Include/internal/pycore_uop_metadata.h
M Lib/test/test_generated_cases.py
M Python/bytecodes.c
M Python/executor_cases.c.h
M Tools/cases_generator/analyzer.py
M Tools/cases_generator/generators_common.py
M Tools/cases_generator/interpreter_definition.md
M Tools/cases_generator/lexer.py
M Tools/cases_generator/opcode_metadata_generator.py
M Tools/cases_generator/parsing.py
M Tools/cases_generator/stack.py

diff --git a/Include/internal/pycore_opcode_metadata.h 
b/Include/internal/pycore_opcode_metadata.h
index a9d698da25a1db..fbb448f663369a 100644
--- a/Include/internal/pycore_opcode_metadata.h
+++ b/Include/internal/pycore_opcode_metadata.h
@@ -909,6 +909,8 @@ enum InstructionFormat {
 #define HAS_DEOPT_FLAG (128)
 #define HAS_ERROR_FLAG (256)
 #define HAS_ESCAPES_FLAG (512)
+#define HAS_PURE_FLAG (1024)
+#define HAS_PASSTHROUGH_FLAG (2048)
 #define OPCODE_HAS_ARG(OP) (_PyOpcode_opcode_metadata[OP].flags & 
(HAS_ARG_FLAG))
 #define OPCODE_HAS_CONST(OP) (_PyOpcode_opcode_metadata[OP].flags & 
(HAS_CONST_FLAG))
 #define OPCODE_HAS_NAME(OP) (_PyOpcode_opcode_metadata[OP].flags & 
(HAS_NAME_FLAG))
@@ -919,6 +921,8 @@ enum InstructionFormat {
 #define OPCODE_HAS_DEOPT(OP) (_PyOpcode_opcode_metadata[OP].flags & 
(HAS_DEOPT_FLAG))
 #define OPCODE_HAS_ERROR(OP) (_PyOpcode_opcode_metadata[OP].flags & 
(HAS_ERROR_FLAG))
 #define OPCODE_HAS_ESCAPES(OP) (_PyOpcode_opcode_metadata[OP].flags & 
(HAS_ESCAPES_FLAG))
+#define OPCODE_HAS_PURE(OP) (_PyOpcode_opcode_metadata[OP].flags & 
(HAS_PURE_FLAG))
+#define OPCODE_HAS_PASSTHROUGH(OP) (_PyOpcode_opcode_metadata[OP].flags & 
(HAS_PASSTHROUGH_FLAG))
 
 #define OPARG_FULL 0
 #define OPARG_CACHE_1 1
@@ -996,7 +1000,7 @@ const struct opcode_metadata 
_PyOpcode_opcode_metadata[268] = {
 [COMPARE_OP_STR] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG | 
HAS_ESCAPES_FLAG },
 [CONTAINS_OP] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | 
HAS_ESCAPES_FLAG },
 [CONVERT_VALUE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG },
-[COPY] = { true, INSTR_FMT_IB, HAS_ARG_FLAG },
+[COPY] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_PURE_FLAG },
 [COPY_FREE_VARS] = { true, INSTR_FMT_IB, HAS_ARG_FLAG },
 [DELETE_ATTR] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_NAME_FLAG | 
HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
 [DELETE_DEREF] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_FREE_FLAG | 
HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
@@ -1007,8 +1011,8 @@ const struct opcode_metadata 
_PyOpcode_opcode_metadata[268] = {
 [DICT_MERGE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | 
HAS_ESCAPES_FLAG },
 [DICT_UPDATE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | 
HAS_ESCAPES_FLAG },
 [END_ASYNC_FOR] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG 
},
-[END_FOR] = { true, INSTR_FMT_IX, 0 },
-[END_SEND] = { true, INSTR_FMT_IX, 0 },
+[END_FOR] = { true, INSTR_FMT_IX, HAS_PURE_FLAG },
+[END_SEND] = { true, INSTR_FMT_IX, HAS_PURE_FLAG },
 [ENTER_EXECUTOR] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | 
HAS_EVAL_BREAK_FLAG },
 [EXIT_INIT_CHECK] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | 
HAS_ESCAPES_FLAG },
 [EXTENDED_ARG] = { true, INSTR_FMT_IB, HAS_ARG_FLAG },
@@ -1067,9 +1071,9 @@ const struct opcode_metadata 
_PyOpcode_opcode_metadata[268] = {
 [LOAD_ATTR_SLOT] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | 
HAS_DEOPT_FLAG },
 [LOAD_ATTR_WITH_HINT] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | 
HAS_NAME_FLAG | HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG },
 [LOAD_BUILD_CLASS] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | 
HAS_ESCAPES_FLAG },
-[LOAD_CONST] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_CONST_FLAG },
+[LOAD_CONST] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_CONST_FLAG | 
HAS_PURE_FLAG },
 [LOAD_DEREF] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_FREE_FLAG | 
HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
-[LOAD_FAST] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_LOCAL_FLAG },
+[LOAD_FAST] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_LOCAL_FLAG | 
HAS_PURE_FLAG },
 [LOAD_FAST_AND_CLEAR] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | 
HAS_LOCAL_FLAG },
 [LOAD_FAST_CHECK] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_LOCAL_FLAG | 
HAS_ERROR_FLAG },
 [LOAD_FAST_LOAD_FAST] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | 
HAS_LOCAL_FLAG },
@@ -10

[Python-checkins] gh-120619: Optimize through `_Py_FRAME_GENERAL` (GH-124518)

2024-10-02 Thread Fidget-Spinner
https://github.com/python/cpython/commit/b84a763dca412e8dbbc9cf7c6273c11d6c2220a7
commit: b84a763dca412e8dbbc9cf7c6273c11d6c2220a7
branch: main
author: Ken Jin 
committer: Fidget-Spinner 
date: 2024-10-03T01:10:51+08:00
summary:

gh-120619: Optimize through `_Py_FRAME_GENERAL` (GH-124518)

* Optimize through _Py_FRAME_GENERAL

* refactor

files:
M Python/optimizer_analysis.c
M Python/optimizer_bytecodes.c
M Python/optimizer_cases.c.h

diff --git a/Python/optimizer_analysis.c b/Python/optimizer_analysis.c
index f30e873605d858..06826ff942a761 100644
--- a/Python/optimizer_analysis.c
+++ b/Python/optimizer_analysis.c
@@ -385,6 +385,30 @@ get_code(_PyUOpInstruction *op)
 return co;
 }
 
+static PyCodeObject *
+get_code_with_logging(_PyUOpInstruction *op)
+{
+PyCodeObject *co = NULL;
+uint64_t push_operand = op->operand;
+if (push_operand & 1) {
+co = (PyCodeObject *)(push_operand & ~1);
+DPRINTF(3, "code=%p ", co);
+assert(PyCode_Check(co));
+}
+else {
+PyFunctionObject *func = (PyFunctionObject *)push_operand;
+DPRINTF(3, "func=%p ", func);
+if (func == NULL) {
+DPRINTF(3, "\n");
+DPRINTF(1, "Missing function\n");
+return NULL;
+}
+co = (PyCodeObject *)func->func_code;
+DPRINTF(3, "code=%p ", co);
+}
+return co;
+}
+
 /* 1 for success, 0 for not ready, cannot error at the moment. */
 static int
 optimize_uops(
diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c
index 9a1b9da52f4bb5..bf8f0753f800c0 100644
--- a/Python/optimizer_bytecodes.c
+++ b/Python/optimizer_bytecodes.c
@@ -575,25 +575,13 @@ dummy_func(void) {
 
 PyCodeObject *co = NULL;
 assert((this_instr + 2)->opcode == _PUSH_FRAME);
-uint64_t push_operand = (this_instr + 2)->operand;
-if (push_operand & 1) {
-co = (PyCodeObject *)(push_operand & ~1);
-DPRINTF(3, "code=%p ", co);
-assert(PyCode_Check(co));
-}
-else {
-PyFunctionObject *func = (PyFunctionObject *)push_operand;
-DPRINTF(3, "func=%p ", func);
-if (func == NULL) {
-DPRINTF(3, "\n");
-DPRINTF(1, "Missing function\n");
-ctx->done = true;
-break;
-}
-co = (PyCodeObject *)func->func_code;
-DPRINTF(3, "code=%p ", co);
+co = get_code_with_logging((this_instr + 2));
+if (co == NULL) {
+ctx->done = true;
+break;
 }
 
+
 assert(self_or_null != NULL);
 assert(args != NULL);
 if (sym_is_not_null(self_or_null)) {
@@ -619,12 +607,17 @@ dummy_func(void) {
 }
 
 op(_PY_FRAME_GENERAL, (callable, self_or_null, args[oparg] -- new_frame: 
_Py_UOpsAbstractFrame *)) {
-/* The _Py_UOpsAbstractFrame design assumes that we can copy arguments 
across directly */
-(void)callable;
-(void)self_or_null;
-(void)args;
-new_frame = NULL;
-ctx->done = true;
+(void)(self_or_null);
+(void)(callable);
+PyCodeObject *co = NULL;
+assert((this_instr + 2)->opcode == _PUSH_FRAME);
+co = get_code_with_logging((this_instr + 2));
+if (co == NULL) {
+ctx->done = true;
+break;
+}
+
+new_frame = frame_new(ctx, co, 0, NULL, 0);
 }
 
 op(_PY_FRAME_KW, (callable, self_or_null, args[oparg], kwnames -- 
new_frame: _Py_UOpsAbstractFrame *)) {
diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h
index 4d172e3c762704..fc0c0eff01d4c1 100644
--- a/Python/optimizer_cases.c.h
+++ b/Python/optimizer_cases.c.h
@@ -1663,15 +1663,18 @@
 _Py_UopsSymbol *self_or_null;
 _Py_UopsSymbol *callable;
 _Py_UOpsAbstractFrame *new_frame;
-args = &stack_pointer[-oparg];
 self_or_null = stack_pointer[-1 - oparg];
 callable = stack_pointer[-2 - oparg];
-/* The _Py_UOpsAbstractFrame design assumes that we can copy 
arguments across directly */
-(void)callable;
-(void)self_or_null;
-(void)args;
-new_frame = NULL;
-ctx->done = true;
+(void)(self_or_null);
+(void)(callable);
+PyCodeObject *co = NULL;
+assert((this_instr + 2)->opcode == _PUSH_FRAME);
+co = get_code_with_logging((this_instr + 2));
+if (co == NULL) {
+ctx->done = true;
+break;
+}
+new_frame = frame_new(ctx, co, 0, NULL, 0);
 stack_pointer[-2 - oparg] = (_Py_UopsSymbol *)new_frame;
 stack_pointer += -1 - oparg;
 assert(WITHIN_STACK_BO

[Python-checkins] gh-120619: Strength reduce function guards, support 2-operand uop forms (GH-124846)

2024-11-08 Thread Fidget-Spinner
https://github.com/python/cpython/commit/6293d00e7201f3f28b1f4512e57dc4f03855cabd
commit: 6293d00e7201f3f28b1f4512e57dc4f03855cabd
branch: main
author: Ken Jin 
committer: Fidget-Spinner 
date: 2024-11-09T11:35:33+08:00
summary:

gh-120619: Strength reduce function guards, support 2-operand uop forms 
(GH-124846)

Co-authored-by: Brandt Bucher 

files:
M Include/internal/pycore_optimizer.h
M Include/internal/pycore_uop_ids.h
M Include/internal/pycore_uop_metadata.h
M Lib/test/test_capi/test_opt.py
M Python/bytecodes.c
M Python/ceval_macros.h
M Python/executor_cases.c.h
M Python/generated_cases.c.h
M Python/optimizer.c
M Python/optimizer_analysis.c
M Python/optimizer_bytecodes.c
M Python/optimizer_cases.c.h
M Tools/cases_generator/analyzer.py
M Tools/cases_generator/optimizer_generator.py
M Tools/cases_generator/tier2_generator.py
M Tools/jit/_stencils.py
M Tools/jit/template.c

diff --git a/Include/internal/pycore_optimizer.h 
b/Include/internal/pycore_optimizer.h
index f92c0a0cddf906..6d70b42f708854 100644
--- a/Include/internal/pycore_optimizer.h
+++ b/Include/internal/pycore_optimizer.h
@@ -58,7 +58,8 @@ typedef struct {
 uint16_t error_target;
 };
 };
-uint64_t operand;  // A cache entry
+uint64_t operand0;  // A cache entry
+uint64_t operand1;
 } _PyUOpInstruction;
 
 typedef struct {
diff --git a/Include/internal/pycore_uop_ids.h 
b/Include/internal/pycore_uop_ids.h
index 55416d2aae1e1a..fab4ce6a25b347 100644
--- a/Include/internal/pycore_uop_ids.h
+++ b/Include/internal/pycore_uop_ids.h
@@ -63,90 +63,91 @@ extern "C" {
 #define _CHECK_FUNCTION 333
 #define _CHECK_FUNCTION_EXACT_ARGS 334
 #define _CHECK_FUNCTION_VERSION 335
-#define _CHECK_FUNCTION_VERSION_KW 336
-#define _CHECK_IS_NOT_PY_CALLABLE 337
-#define _CHECK_IS_NOT_PY_CALLABLE_KW 338
-#define _CHECK_MANAGED_OBJECT_HAS_VALUES 339
-#define _CHECK_METHOD_VERSION 340
-#define _CHECK_METHOD_VERSION_KW 341
-#define _CHECK_PEP_523 342
-#define _CHECK_PERIODIC 343
-#define _CHECK_PERIODIC_IF_NOT_YIELD_FROM 344
-#define _CHECK_STACK_SPACE 345
-#define _CHECK_STACK_SPACE_OPERAND 346
-#define _CHECK_VALIDITY 347
-#define _CHECK_VALIDITY_AND_SET_IP 348
-#define _COMPARE_OP 349
-#define _COMPARE_OP_FLOAT 350
-#define _COMPARE_OP_INT 351
-#define _COMPARE_OP_STR 352
-#define _CONTAINS_OP 353
+#define _CHECK_FUNCTION_VERSION_INLINE 336
+#define _CHECK_FUNCTION_VERSION_KW 337
+#define _CHECK_IS_NOT_PY_CALLABLE 338
+#define _CHECK_IS_NOT_PY_CALLABLE_KW 339
+#define _CHECK_MANAGED_OBJECT_HAS_VALUES 340
+#define _CHECK_METHOD_VERSION 341
+#define _CHECK_METHOD_VERSION_KW 342
+#define _CHECK_PEP_523 343
+#define _CHECK_PERIODIC 344
+#define _CHECK_PERIODIC_IF_NOT_YIELD_FROM 345
+#define _CHECK_STACK_SPACE 346
+#define _CHECK_STACK_SPACE_OPERAND 347
+#define _CHECK_VALIDITY 348
+#define _CHECK_VALIDITY_AND_SET_IP 349
+#define _COMPARE_OP 350
+#define _COMPARE_OP_FLOAT 351
+#define _COMPARE_OP_INT 352
+#define _COMPARE_OP_STR 353
+#define _CONTAINS_OP 354
 #define _CONTAINS_OP_DICT CONTAINS_OP_DICT
 #define _CONTAINS_OP_SET CONTAINS_OP_SET
 #define _CONVERT_VALUE CONVERT_VALUE
 #define _COPY COPY
 #define _COPY_FREE_VARS COPY_FREE_VARS
-#define _CREATE_INIT_FRAME 354
+#define _CREATE_INIT_FRAME 355
 #define _DELETE_ATTR DELETE_ATTR
 #define _DELETE_DEREF DELETE_DEREF
 #define _DELETE_FAST DELETE_FAST
 #define _DELETE_GLOBAL DELETE_GLOBAL
 #define _DELETE_NAME DELETE_NAME
 #define _DELETE_SUBSCR DELETE_SUBSCR
-#define _DEOPT 355
+#define _DEOPT 356
 #define _DICT_MERGE DICT_MERGE
 #define _DICT_UPDATE DICT_UPDATE
-#define _DO_CALL 356
-#define _DO_CALL_FUNCTION_EX 357
-#define _DO_CALL_KW 358
-#define _DYNAMIC_EXIT 359
+#define _DO_CALL 357
+#define _DO_CALL_FUNCTION_EX 358
+#define _DO_CALL_KW 359
+#define _DYNAMIC_EXIT 360
 #define _END_SEND END_SEND
-#define _ERROR_POP_N 360
+#define _ERROR_POP_N 361
 #define _EXIT_INIT_CHECK EXIT_INIT_CHECK
-#define _EXPAND_METHOD 361
-#define _EXPAND_METHOD_KW 362
-#define _FATAL_ERROR 363
+#define _EXPAND_METHOD 362
+#define _EXPAND_METHOD_KW 363
+#define _FATAL_ERROR 364
 #define _FORMAT_SIMPLE FORMAT_SIMPLE
 #define _FORMAT_WITH_SPEC FORMAT_WITH_SPEC
-#define _FOR_ITER 364
-#define _FOR_ITER_GEN_FRAME 365
-#define _FOR_ITER_TIER_TWO 366
+#define _FOR_ITER 365
+#define _FOR_ITER_GEN_FRAME 366
+#define _FOR_ITER_TIER_TWO 367
 #define _GET_AITER GET_AITER
 #define _GET_ANEXT GET_ANEXT
 #define _GET_AWAITABLE GET_AWAITABLE
 #define _GET_ITER GET_ITER
 #define _GET_LEN GET_LEN
 #define _GET_YIELD_FROM_ITER GET_YIELD_FROM_ITER
-#define _GUARD_BOTH_FLOAT 367
-#define _GUARD_BOTH_INT 368
-#define _GUARD_BOTH_UNICODE 369
-#define _GUARD_BUILTINS_VERSION_PUSH_KEYS 370
-#define _GUARD_DORV_NO_DICT 371
-#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT 372
-#define _GUARD_GLOBALS_VERSION 373
-#define _GUARD_GLOBALS_VERSION_PUSH_KEYS 374
-#define _GUARD_IS_FALSE_POP 375
-#define _GUARD_IS_NONE_POP 376
-#define _GUARD_IS_NOT_NONE_POP 377
-#define _GUARD_IS_TRUE_POP 378
-#define _GUARD_KEYS_V

[Python-checkins] gh-117376: Fix off-by-ones in conversion functions (GH-124301)

2024-09-25 Thread Fidget-Spinner
https://github.com/python/cpython/commit/198756b0f653e9f487076df2c6f943e374def6cb
commit: 198756b0f653e9f487076df2c6f943e374def6cb
branch: main
author: Ken Jin 
committer: Fidget-Spinner 
date: 2024-09-26T02:41:07+08:00
summary:

gh-117376: Fix off-by-ones in conversion functions (GH-124301)

Fix off-by-ones in conversion function

files:
M Python/bytecodes.c
M Python/executor_cases.c.h
M Python/generated_cases.c.h

diff --git a/Python/bytecodes.c b/Python/bytecodes.c
index bf8f6af83fc56e..0fd396f1319e78 100644
--- a/Python/bytecodes.c
+++ b/Python/bytecodes.c
@@ -3928,7 +3928,7 @@ dummy_func(
 PyCFunctionFastWithKeywords cfunc =
 (PyCFunctionFastWithKeywords)(void(*)(void))meth->ml_meth;
 
-STACKREFS_TO_PYOBJECTS(args, nargs, args_o);
+STACKREFS_TO_PYOBJECTS(args, total_args, args_o);
 if (CONVERSION_FAILED(args_o)) {
 DECREF_INPUTS();
 ERROR_IF(true, error);
@@ -4009,7 +4009,7 @@ dummy_func(
 (PyCFunctionFast)(void(*)(void))meth->ml_meth;
 int nargs = total_args - 1;
 
-STACKREFS_TO_PYOBJECTS(args, nargs, args_o);
+STACKREFS_TO_PYOBJECTS(args, total_args, args_o);
 if (CONVERSION_FAILED(args_o)) {
 DECREF_INPUTS();
 ERROR_IF(true, error);
diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h
index 7285acec0bacaf..7a9c6ab89c38cc 100644
--- a/Python/executor_cases.c.h
+++ b/Python/executor_cases.c.h
@@ -4596,7 +4596,7 @@
 int nargs = total_args - 1;
 PyCFunctionFastWithKeywords cfunc =
 (PyCFunctionFastWithKeywords)(void(*)(void))meth->ml_meth;
-STACKREFS_TO_PYOBJECTS(args, nargs, args_o);
+STACKREFS_TO_PYOBJECTS(args, total_args, args_o);
 if (CONVERSION_FAILED(args_o)) {
 PyStackRef_CLOSE(callable);
 PyStackRef_CLOSE(self_or_null[0]);
@@ -4713,7 +4713,7 @@
 PyCFunctionFast cfunc =
 (PyCFunctionFast)(void(*)(void))meth->ml_meth;
 int nargs = total_args - 1;
-STACKREFS_TO_PYOBJECTS(args, nargs, args_o);
+STACKREFS_TO_PYOBJECTS(args, total_args, args_o);
 if (CONVERSION_FAILED(args_o)) {
 PyStackRef_CLOSE(callable);
 PyStackRef_CLOSE(self_or_null[0]);
diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h
index 58792a2101ab28..1201fe82efb919 100644
--- a/Python/generated_cases.c.h
+++ b/Python/generated_cases.c.h
@@ -2252,7 +2252,7 @@
 PyCFunctionFast cfunc =
 (PyCFunctionFast)(void(*)(void))meth->ml_meth;
 int nargs = total_args - 1;
-STACKREFS_TO_PYOBJECTS(args, nargs, args_o);
+STACKREFS_TO_PYOBJECTS(args, total_args, args_o);
 if (CONVERSION_FAILED(args_o)) {
 PyStackRef_CLOSE(callable);
 PyStackRef_CLOSE(self_or_null[0]);
@@ -2333,7 +2333,7 @@
 int nargs = total_args - 1;
 PyCFunctionFastWithKeywords cfunc =
 (PyCFunctionFastWithKeywords)(void(*)(void))meth->ml_meth;
-STACKREFS_TO_PYOBJECTS(args, nargs, args_o);
+STACKREFS_TO_PYOBJECTS(args, total_args, args_o);
 if (CONVERSION_FAILED(args_o)) {
 PyStackRef_CLOSE(callable);
 PyStackRef_CLOSE(self_or_null[0]);

___
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com


[Python-checkins] gh-103951: enable optimization for fast attribute access on module subclasses (GH-126264)

2024-11-15 Thread Fidget-Spinner
https://github.com/python/cpython/commit/d9e251223e8314ca726fc0be8b834362184b0aad
commit: d9e251223e8314ca726fc0be8b834362184b0aad
branch: main
author: Sergey B Kirpichev 
committer: Fidget-Spinner 
date: 2024-11-15T16:03:38+08:00
summary:

gh-103951: enable optimization for fast attribute access on module subclasses 
(GH-126264)

Co-authored-by: Nicolas Tessore 

files:
A 
Misc/NEWS.d/next/Core_and_Builtins/2024-11-01-09-58-06.gh-issue-103951.6qduwj.rst
M Python/bytecodes.c
M Python/executor_cases.c.h
M Python/generated_cases.c.h
M Python/specialize.c

diff --git 
a/Misc/NEWS.d/next/Core_and_Builtins/2024-11-01-09-58-06.gh-issue-103951.6qduwj.rst
 
b/Misc/NEWS.d/next/Core_and_Builtins/2024-11-01-09-58-06.gh-issue-103951.6qduwj.rst
new file mode 100644
index 00..39b54e0b72556e
--- /dev/null
+++ 
b/Misc/NEWS.d/next/Core_and_Builtins/2024-11-01-09-58-06.gh-issue-103951.6qduwj.rst
@@ -0,0 +1,2 @@
+Relax optimization requirements to allow fast attribute access to module
+subclasses.
diff --git a/Python/bytecodes.c b/Python/bytecodes.c
index 04983fd861ec59..c85b49842daf44 100644
--- a/Python/bytecodes.c
+++ b/Python/bytecodes.c
@@ -2132,7 +2132,7 @@ dummy_func(
 
 op(_CHECK_ATTR_MODULE, (dict_version/2, owner -- owner)) {
 PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner);
-DEOPT_IF(!PyModule_CheckExact(owner_o));
+DEOPT_IF(Py_TYPE(owner_o)->tp_getattro != 
PyModule_Type.tp_getattro);
 PyDictObject *dict = (PyDictObject *)((PyModuleObject 
*)owner_o)->md_dict;
 assert(dict != NULL);
 DEOPT_IF(dict->ma_keys->dk_version != dict_version);
diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h
index 494ace1bd85822..2c2a09adf281a7 100644
--- a/Python/executor_cases.c.h
+++ b/Python/executor_cases.c.h
@@ -2602,7 +2602,7 @@
 owner = stack_pointer[-1];
 uint32_t dict_version = (uint32_t)CURRENT_OPERAND0();
 PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner);
-if (!PyModule_CheckExact(owner_o)) {
+if (Py_TYPE(owner_o)->tp_getattro != PyModule_Type.tp_getattro) {
 UOP_STAT_INC(uopcode, miss);
 JUMP_TO_JUMP_TARGET();
 }
diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h
index 77bf6ad3781f17..15308d6f1f7146 100644
--- a/Python/generated_cases.c.h
+++ b/Python/generated_cases.c.h
@@ -5561,7 +5561,7 @@
 owner = stack_pointer[-1];
 uint32_t dict_version = read_u32(&this_instr[2].cache);
 PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner);
-DEOPT_IF(!PyModule_CheckExact(owner_o), LOAD_ATTR);
+DEOPT_IF(Py_TYPE(owner_o)->tp_getattro != 
PyModule_Type.tp_getattro, LOAD_ATTR);
 PyDictObject *dict = (PyDictObject *)((PyModuleObject 
*)owner_o)->md_dict;
 assert(dict != NULL);
 DEOPT_IF(dict->ma_keys->dk_version != dict_version, LOAD_ATTR);
diff --git a/Python/specialize.c b/Python/specialize.c
index 0699e7be5e6b9c..4c8cf8534b3dc7 100644
--- a/Python/specialize.c
+++ b/Python/specialize.c
@@ -1219,7 +1219,7 @@ _Py_Specialize_LoadAttr(_PyStackRef owner_st, 
_Py_CODEUNIT *instr, PyObject *nam
 SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OTHER);
 fail = true;
 }
-else if (PyModule_CheckExact(owner)) {
+else if (Py_TYPE(owner)->tp_getattro == PyModule_Type.tp_getattro) {
 fail = specialize_module_load_attr(owner, instr, name);
 }
 else if (PyType_Check(owner)) {

___
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com


[Python-checkins] gh-128262: Allow specialization of calls to classes with __slots__ (GH-128263)

2024-12-30 Thread Fidget-Spinner
https://github.com/python/cpython/commit/7ef49074123511003c8b7f7f3ba2a4e05285e8dc
commit: 7ef49074123511003c8b7f7f3ba2a4e05285e8dc
branch: main
author: Ken Jin 
committer: Fidget-Spinner 
date: 2024-12-31T12:24:17+08:00
summary:

gh-128262: Allow specialization of calls to classes with __slots__ (GH-128263)

files:
M Include/internal/pycore_uop_metadata.h
M Python/bytecodes.c
M Python/executor_cases.c.h
M Python/generated_cases.c.h
M Python/specialize.c

diff --git a/Include/internal/pycore_uop_metadata.h 
b/Include/internal/pycore_uop_metadata.h
index e71194b116e020..73fc29eb78a7a4 100644
--- a/Include/internal/pycore_uop_metadata.h
+++ b/Include/internal/pycore_uop_metadata.h
@@ -234,7 +234,7 @@ const uint16_t _PyUop_Flags[MAX_UOP_ID+1] = {
 [_CALL_TYPE_1] = HAS_ARG_FLAG | HAS_DEOPT_FLAG,
 [_CALL_STR_1] = HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | 
HAS_ESCAPES_FLAG,
 [_CALL_TUPLE_1] = HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | 
HAS_ESCAPES_FLAG,
-[_CHECK_AND_ALLOCATE_OBJECT] = HAS_ARG_FLAG | HAS_DEOPT_FLAG | 
HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG,
+[_CHECK_AND_ALLOCATE_OBJECT] = HAS_ARG_FLAG | HAS_DEOPT_FLAG | 
HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG,
 [_CREATE_INIT_FRAME] = HAS_ARG_FLAG | HAS_ERROR_FLAG | 
HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG,
 [_EXIT_INIT_CHECK] = HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | 
HAS_ESCAPES_FLAG,
 [_CALL_BUILTIN_CLASS] = HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | 
HAS_ESCAPES_FLAG,
diff --git a/Python/bytecodes.c b/Python/bytecodes.c
index 63cf1978e8abe5..602cf7f47b812b 100644
--- a/Python/bytecodes.c
+++ b/Python/bytecodes.c
@@ -3765,13 +3765,15 @@ dummy_func(
 DEOPT_IF(!PyType_Check(callable_o));
 PyTypeObject *tp = (PyTypeObject *)callable_o;
 DEOPT_IF(FT_ATOMIC_LOAD_UINT32_RELAXED(tp->tp_version_tag) != 
type_version);
-assert(tp->tp_flags & Py_TPFLAGS_INLINE_VALUES);
+assert(tp->tp_new == PyBaseObject_Type.tp_new);
+assert(tp->tp_flags & Py_TPFLAGS_HEAPTYPE);
+assert(tp->tp_alloc == PyType_GenericAlloc);
 PyHeapTypeObject *cls = (PyHeapTypeObject *)callable_o;
 PyFunctionObject *init_func = (PyFunctionObject 
*)FT_ATOMIC_LOAD_PTR_ACQUIRE(cls->_spec_cache.init);
 PyCodeObject *code = (PyCodeObject *)init_func->func_code;
 DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize 
+ _Py_InitCleanup.co_framesize));
 STAT_INC(CALL, hit);
-PyObject *self_o = _PyType_NewManagedObject(tp);
+PyObject *self_o = PyType_GenericAlloc(tp, 0);
 if (self_o == NULL) {
 ERROR_NO_POP();
 }
diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h
index 22335021faaa6d..f7374d52705960 100644
--- a/Python/executor_cases.c.h
+++ b/Python/executor_cases.c.h
@@ -4572,7 +4572,9 @@
 UOP_STAT_INC(uopcode, miss);
 JUMP_TO_JUMP_TARGET();
 }
-assert(tp->tp_flags & Py_TPFLAGS_INLINE_VALUES);
+assert(tp->tp_new == PyBaseObject_Type.tp_new);
+assert(tp->tp_flags & Py_TPFLAGS_HEAPTYPE);
+assert(tp->tp_alloc == PyType_GenericAlloc);
 PyHeapTypeObject *cls = (PyHeapTypeObject *)callable_o;
 PyFunctionObject *init_func = (PyFunctionObject 
*)FT_ATOMIC_LOAD_PTR_ACQUIRE(cls->_spec_cache.init);
 PyCodeObject *code = (PyCodeObject *)init_func->func_code;
@@ -4581,7 +4583,9 @@
 JUMP_TO_JUMP_TARGET();
 }
 STAT_INC(CALL, hit);
-PyObject *self_o = _PyType_NewManagedObject(tp);
+_PyFrame_SetStackPointer(frame, stack_pointer);
+PyObject *self_o = PyType_GenericAlloc(tp, 0);
+stack_pointer = _PyFrame_GetStackPointer(frame);
 if (self_o == NULL) {
 JUMP_TO_ERROR();
 }
diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h
index bed16b60b76a2f..98743c27c38524 100644
--- a/Python/generated_cases.c.h
+++ b/Python/generated_cases.c.h
@@ -1048,13 +1048,17 @@
 DEOPT_IF(!PyType_Check(callable_o), CALL);
 PyTypeObject *tp = (PyTypeObject *)callable_o;
 DEOPT_IF(FT_ATOMIC_LOAD_UINT32_RELAXED(tp->tp_version_tag) != 
type_version, CALL);
-assert(tp->tp_flags & Py_TPFLAGS_INLINE_VALUES);
+assert(tp->tp_new == PyBaseObject_Type.tp_new);
+assert(tp->tp_flags & Py_TPFLAGS_HEAPTYPE);
+assert(tp->tp_alloc == PyType_GenericAlloc);
 PyHeapTypeObject *cls = (PyHeapTypeObject *)callable_o;
 PyFunctionObject *init_func = (PyFunctionObject 
*)FT_ATOMIC_LOAD_PTR_ACQUIRE(cls->_spec_cache.init);
 PyCodeObject *code = (PyCodeObject *)init_fu

[Python-checkins] Docs: more explanation of the implications of new tail-call interpreter (GH-129863)

2025-02-08 Thread Fidget-Spinner
https://github.com/python/cpython/commit/f2ae79d29e5e0bd24ad1300cb44e3a99104755c7
commit: f2ae79d29e5e0bd24ad1300cb44e3a99104755c7
branch: main
author: Ned Batchelder 
committer: Fidget-Spinner 
date: 2025-02-08T19:28:35Z
summary:

Docs: more explanation of the implications of new tail-call interpreter 
(GH-129863)


Co-authored-by: Ken Jin 

files:
M Doc/whatsnew/3.14.rst

diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst
index 9c4922308b7f2d..ba7e8b42ef1f24 100644
--- a/Doc/whatsnew/3.14.rst
+++ b/Doc/whatsnew/3.14.rst
@@ -235,9 +235,13 @@ For further information on how to build Python, see
This is not to be confused with `tail call optimization`__ of Python
functions, which is currently not implemented in CPython.
 
+   This new interpreter type is an internal implementation detail of the 
CPython
+   interpreter.  It doesn't change the visible behavior of Python programs at
+   all.  It can improve their performance, but doesn't change anything else.
+
__ https://en.wikipedia.org/wiki/Tail_call
 
-(Contributed by Ken Jin in :gh:`128718`, with ideas on how to implement this
+(Contributed by Ken Jin in :gh:`128563`, with ideas on how to implement this
 in CPython by Mark Shannon, Garrett Gu, Haoran Xu, and Josh Haberman.)
 
 

___
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com


[Python-checkins] Fix link in 3.14 whatsnew (#129828)

2025-02-07 Thread Fidget-Spinner
https://github.com/python/cpython/commit/e4a00f70b176c3182aad3904f94c69a7fb733cd9
commit: e4a00f70b176c3182aad3904f94c69a7fb733cd9
branch: main
author: Ken Jin 
committer: Fidget-Spinner 
date: 2025-02-07T19:30:23Z
summary:

Fix link in 3.14 whatsnew (#129828)

files:
M Doc/whatsnew/3.14.rst

diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst
index 2bdc3cabcfbc03..6eb256586e71d8 100644
--- a/Doc/whatsnew/3.14.rst
+++ b/Doc/whatsnew/3.14.rst
@@ -68,7 +68,7 @@ Summary -- release highlights
 * :ref:`PEP 649: deferred evaluation of annotations `
 * :ref:`PEP 741: Python Configuration C API `
 * :ref:`PEP 761: Discontinuation of PGP signatures `
-* :ref:`A new tail-calling interpreter  `
+* :ref:`A new type of interpreter  `
 
 
 New features

___
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com


[Python-checkins] Remove tail-calling wording as it is confusing (GH-129823)

2025-02-07 Thread Fidget-Spinner
https://github.com/python/cpython/commit/7b2e01bb555359913939d7ff168363f1760d3f8e
commit: 7b2e01bb555359913939d7ff168363f1760d3f8e
branch: main
author: Ken Jin 
committer: Fidget-Spinner 
date: 2025-02-07T18:49:28Z
summary:

Remove tail-calling wording as it is confusing (GH-129823)

files:
M Doc/whatsnew/3.14.rst

diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst
index 52d6e963a4a835..2bdc3cabcfbc03 100644
--- a/Doc/whatsnew/3.14.rst
+++ b/Doc/whatsnew/3.14.rst
@@ -211,8 +211,8 @@ configuration mechanisms).
 
 .. _whatsnew314-tail-call:
 
-A new tail-calling interpreter
---
+A new type of interpreter
+-
 
 A new type of interpreter based on tail calls has been added to CPython.
 For certain newer compilers, this interpreter provides

___
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com


[Python-checkins] Fix Garrett Gu name misspelling in 3.14 whatsnew (GH-129822)

2025-02-07 Thread Fidget-Spinner
https://github.com/python/cpython/commit/662e88db642899bcbc28ef142361d5f315a46901
commit: 662e88db642899bcbc28ef142361d5f315a46901
branch: main
author: Garrett Gu 
committer: Fidget-Spinner 
date: 2025-02-07T17:56:46Z
summary:

Fix Garrett Gu name misspelling in 3.14 whatsnew (GH-129822)

Update 3.14.rst to fix typo

files:
M Doc/whatsnew/3.14.rst

diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst
index 1e469e8738bfcb..52d6e963a4a835 100644
--- a/Doc/whatsnew/3.14.rst
+++ b/Doc/whatsnew/3.14.rst
@@ -238,7 +238,7 @@ For further information on how to build Python, see
__ https://en.wikipedia.org/wiki/Tail_call
 
 (Contributed by Ken Jin in :gh:`128718`, with ideas on how to implement this
-in CPython by Mark Shannon, Garret Gu, Haoran Xu, and Josh Haberman.)
+in CPython by Mark Shannon, Garrett Gu, Haoran Xu, and Josh Haberman.)
 
 
 Other language changes

___
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com


[Python-checkins] gh-129737: Fix help message for tail calling interpreter configuration (GH-129754)

2025-02-06 Thread Fidget-Spinner
https://github.com/python/cpython/commit/43e024021392c8c70e5a56cdf7428ced45d73688
commit: 43e024021392c8c70e5a56cdf7428ced45d73688
branch: main
author: Pieter Eendebak 
committer: Fidget-Spinner 
date: 2025-02-07T08:47:13+08:00
summary:

gh-129737: Fix help message for tail calling interpreter configuration 
(GH-129754)

files:
M configure
M configure.ac

diff --git a/configure b/configure
index 22456959add174..65b8e711cdccae 100755
--- a/configure
+++ b/configure
@@ -1930,7 +1930,7 @@ Optional Packages:
   use libedit for backend or disable readline module
   --with-computed-gotos   enable computed gotos in evaluation loop (enabled by
   default on supported compilers)
-  --tail-call-interp  enable tail-calling interpreter in evaluation loop
+  --with-tail-call-interp enable tail-calling interpreter in evaluation loop
   and rest of CPython
   --with-ensurepip[=install|upgrade|no]
   "install" or "upgrade" using bundled pip (default is
diff --git a/configure.ac b/configure.ac
index cf16e77f0a1503..0c6063d87d654a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -7022,7 +7022,7 @@ AC_MSG_CHECKING([for --with-tail-call-interp])
 AC_ARG_WITH(
   [tail-call-interp],
   [AS_HELP_STRING(
-[--tail-call-interp],
+[--with-tail-call-interp],
 [enable tail-calling interpreter in evaluation loop and rest of CPython]
   )],
 [

___
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com


[Python-checkins] gh-128563: Document the tail-calling interpreter (GH-129728)

2025-02-07 Thread Fidget-Spinner
https://github.com/python/cpython/commit/3d3a4beefed46df7aa3a477f2e511459ce06c4b0
commit: 3d3a4beefed46df7aa3a477f2e511459ce06c4b0
branch: main
author: Ken Jin 
committer: Fidget-Spinner 
date: 2025-02-07T20:18:15+08:00
summary:

gh-128563: Document the tail-calling interpreter (GH-129728)

Co-authored-by: Hugo van Kemenade <1324225+hug...@users.noreply.github.com>

files:
M Doc/using/configure.rst
M Doc/whatsnew/3.14.rst

diff --git a/Doc/using/configure.rst b/Doc/using/configure.rst
index 629859e36cb654..101c43576b0314 100644
--- a/Doc/using/configure.rst
+++ b/Doc/using/configure.rst
@@ -618,6 +618,16 @@ also be used to improve performance.
Enable computed gotos in evaluation loop (enabled by default on supported
compilers).
 
+.. option:: --with-tail-call-interp
+
+   Enable interpreters using tail calls in CPython. If enabled, enabling PGO
+   (:option:`--enable-optimizations`) is highly recommended. This option 
specifically
+   requires a C compiler with proper tail call support, and the
+   `preserve_none 
<https://clang.llvm.org/docs/AttributeReference.html#preserve-none>`_
+   calling convention. For example, Clang 19 and newer supports this feature.
+
+   .. versionadded:: next
+
 .. option:: --without-mimalloc
 
Disable the fast :ref:`mimalloc ` allocator
diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst
index a95fc7a4b6a9fa..c788db31fc27ed 100644
--- a/Doc/whatsnew/3.14.rst
+++ b/Doc/whatsnew/3.14.rst
@@ -68,6 +68,7 @@ Summary -- release highlights
 * :ref:`PEP 649: deferred evaluation of annotations `
 * :ref:`PEP 741: Python Configuration C API `
 * :ref:`PEP 761: Discontinuation of PGP signatures `
+* :ref:`A new tail-calling interpreter  `
 
 
 New features
@@ -208,6 +209,30 @@ configuration mechanisms).
 .. seealso::
:pep:`741`.
 
+.. _whatsnew314-tail-call:
+
+A new tail-calling interpreter
+--
+
+A new type of interpreter based on tail calls has been added to CPython.
+For certain newer compilers, this interpreter provides
+significantly better performance. Preliminary numbers on our machines suggest
+anywhere from -3% to 30% faster Python code, and a geometric mean of 9-15%
+faster on ``pyperformance`` depending on platform and architecture.
+
+This interpreter currently only works with Clang 19 and newer
+on x86-64 and AArch64 architectures. However, we expect
+that a future release of GCC will support this as well.
+
+This feature is opt-in for now. We highly recommend enabling profile-guided
+optimization with the new interpreter as it is the only configuration we have
+tested and can validate its improved performance.
+For further information on how to build Python, see
+:option:`--with-tail-call-interp`.
+
+(Contributed by Ken Jin in :gh:`128718`, with ideas on how to implement this
+in CPython by Mark Shannon, Garret Gu, Haoran Xu, and Josh Haberman.)
+
 
 Other language changes
 ==

___
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com


[Python-checkins] gh-128563: Move assignment of opcode into ifdef (GH-129803)

2025-02-07 Thread Fidget-Spinner
https://github.com/python/cpython/commit/175844713af383c9e4dd60166d1d7407c80a1949
commit: 175844713af383c9e4dd60166d1d7407c80a1949
branch: main
author: Ken Jin 
committer: Fidget-Spinner 
date: 2025-02-07T21:11:57+08:00
summary:

gh-128563: Move assignment of opcode into ifdef (GH-129803)

files:
M Lib/test/test_generated_cases.py
M Python/generated_cases.c.h
M Tools/cases_generator/tier1_generator.py

diff --git a/Lib/test/test_generated_cases.py b/Lib/test/test_generated_cases.py
index 35ad9ebbe5a1a9..0e0f28be6b2af0 100644
--- a/Lib/test/test_generated_cases.py
+++ b/Lib/test/test_generated_cases.py
@@ -305,10 +305,9 @@ def test_inst_no_args(self):
 output = """
 TARGET(OP) {
 #if defined(Py_TAIL_CALL_INTERP)
-int opcode;
-#endif
-opcode = OP;
+int opcode = OP;
 (void)(opcode);
+#endif
 frame->instr_ptr = next_instr;
 next_instr += 1;
 INSTRUCTION_STATS(OP);
@@ -328,10 +327,9 @@ def test_inst_one_pop(self):
 output = """
 TARGET(OP) {
 #if defined(Py_TAIL_CALL_INTERP)
-int opcode;
-#endif
-opcode = OP;
+int opcode = OP;
 (void)(opcode);
+#endif
 frame->instr_ptr = next_instr;
 next_instr += 1;
 INSTRUCTION_STATS(OP);
@@ -354,10 +352,9 @@ def test_inst_one_push(self):
 output = """
 TARGET(OP) {
 #if defined(Py_TAIL_CALL_INTERP)
-int opcode;
-#endif
-opcode = OP;
+int opcode = OP;
 (void)(opcode);
+#endif
 frame->instr_ptr = next_instr;
 next_instr += 1;
 INSTRUCTION_STATS(OP);
@@ -381,10 +378,9 @@ def test_inst_one_push_one_pop(self):
 output = """
 TARGET(OP) {
 #if defined(Py_TAIL_CALL_INTERP)
-int opcode;
-#endif
-opcode = OP;
+int opcode = OP;
 (void)(opcode);
+#endif
 frame->instr_ptr = next_instr;
 next_instr += 1;
 INSTRUCTION_STATS(OP);
@@ -409,10 +405,9 @@ def test_binary_op(self):
 output = """
 TARGET(OP) {
 #if defined(Py_TAIL_CALL_INTERP)
-int opcode;
-#endif
-opcode = OP;
+int opcode = OP;
 (void)(opcode);
+#endif
 frame->instr_ptr = next_instr;
 next_instr += 1;
 INSTRUCTION_STATS(OP);
@@ -440,10 +435,9 @@ def test_overlap(self):
 output = """
 TARGET(OP) {
 #if defined(Py_TAIL_CALL_INTERP)
-int opcode;
-#endif
-opcode = OP;
+int opcode = OP;
 (void)(opcode);
+#endif
 frame->instr_ptr = next_instr;
 next_instr += 1;
 INSTRUCTION_STATS(OP);
@@ -473,10 +467,9 @@ def test_predictions(self):
 output = """
 TARGET(OP1) {
 #if defined(Py_TAIL_CALL_INTERP)
-int opcode;
-#endif
-opcode = OP1;
+int opcode = OP1;
 (void)(opcode);
+#endif
 frame->instr_ptr = next_instr;
 next_instr += 1;
 INSTRUCTION_STATS(OP1);
@@ -489,10 +482,9 @@ def test_predictions(self):
 
 TARGET(OP3) {
 #if defined(Py_TAIL_CALL_INTERP)
-int opcode;
-#endif
-opcode = OP3;
+int opcode = OP3;
 (void)(opcode);
+#endif
 _Py_CODEUNIT* const this_instr = next_instr;
 (void)this_instr;
 frame->instr_ptr = next_instr;
@@ -528,10 +520,9 @@ def test_sync_sp(self):
 output = """
 TARGET(A) {
 #if defined(Py_TAIL_CALL_INTERP)
-int opcode;
-#endif
-opcode = A;
+int opcode = A;
 (void)(opcode);
+#endif
 frame->instr_ptr = next_instr;
 next_instr += 1;
 INSTRUCTION_STATS(A);
@@ -550,10 +541,9 @@ def test_sync_sp(self):
 
 TARGET(B) {
 #if defined(Py_TAIL_CALL_INTERP)
-int opcode;
-#endif
-opcode = B;
+int opcode = B;
 (void)(opcode);
+#endif
 frame->instr_ptr = next_instr;
 next_instr += 1;
 INSTRUCTION_STATS(B);
@@ -592,10 +582,9 @@ def test_error_if_plain(self):
 output = """
 TARGET(OP) {
 #if defined(Py_TAIL_CALL_INTERP)
-int opcode;
-#endif
-opcode = OP;
+int opcode = OP;

[Python-checkins] Clarify baseline for new interpreter (GH-129972)

2025-02-10 Thread Fidget-Spinner
https://github.com/python/cpython/commit/516c70d4dd39e02bb365729a4b8aa93f9e6a3e82
commit: 516c70d4dd39e02bb365729a4b8aa93f9e6a3e82
branch: main
author: Ken Jin 
committer: Fidget-Spinner 
date: 2025-02-10T19:07:24Z
summary:

Clarify baseline for new interpreter (GH-129972)

files:
M Doc/whatsnew/3.14.rst

diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst
index f8df4c52a36147..28e3e2dbbe28e6 100644
--- a/Doc/whatsnew/3.14.rst
+++ b/Doc/whatsnew/3.14.rst
@@ -218,7 +218,8 @@ A new type of interpreter based on tail calls has been 
added to CPython.
 For certain newer compilers, this interpreter provides
 significantly better performance. Preliminary numbers on our machines suggest
 anywhere from -3% to 30% faster Python code, and a geometric mean of 9-15%
-faster on ``pyperformance`` depending on platform and architecture.
+faster on ``pyperformance`` depending on platform and architecture. The
+baseline is Python 3.14 built with Clang 19 without this new interpreter.
 
 This interpreter currently only works with Clang 19 and newer
 on x86-64 and AArch64 architectures. However, we expect

___
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com


[Python-checkins] gh-130004: Disable PGO for ceval.c on MSVC for default build (GH-130009)

2025-02-11 Thread Fidget-Spinner
https://github.com/python/cpython/commit/5cdd6e5e758a3fc0a5daac80753bf611b3e23c2d
commit: 5cdd6e5e758a3fc0a5daac80753bf611b3e23c2d
branch: main
author: Ken Jin 
committer: Fidget-Spinner 
date: 2025-02-12T01:13:05+08:00
summary:

gh-130004: Disable PGO for ceval.c on MSVC for default build (GH-130009)

Disable PGO for ceval.c on MSVC on default build

files:
M Python/ceval.c

diff --git a/Python/ceval.c b/Python/ceval.c
index c6a7a0f841f027..5f8f0ae69ef31b 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -764,15 +764,10 @@ _PyObjectArray_Free(PyObject **array, PyObject **scratch)
 #define PY_EVAL_C_STACK_UNITS 2
 
 
-/* _PyEval_EvalFrameDefault is too large to optimize for speed with PGO on MSVC
-   when the JIT is enabled or GIL is disabled. Disable that optimization around
-   this function only. If this is fixed upstream, we should gate this on the
-   version of MSVC.
+/* _PyEval_EvalFrameDefault is too large to optimize for speed with PGO on 
MSVC.
  */
 #if (defined(_MSC_VER) && \
- defined(_Py_USING_PGO) && \
- (defined(_Py_JIT) || \
-  defined(Py_GIL_DISABLED)))
+ defined(_Py_USING_PGO))
 #define DO_NOT_OPTIMIZE_INTERP_LOOP
 #endif
 

___
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com


[Python-checkins] gh-130004: Revert commit 9e52e55 (GH-130005)

2025-02-11 Thread Fidget-Spinner
https://github.com/python/cpython/commit/247b50dec8af47ed8a80069117e07b7139f9d54f
commit: 247b50dec8af47ed8a80069117e07b7139f9d54f
branch: main
author: Ken Jin 
committer: Fidget-Spinner 
date: 2025-02-11T23:23:58+08:00
summary:

gh-130004: Revert commit 9e52e55 (GH-130005)

Revert commit 9e52e55

files:
M PCbuild/pyproject.props
M Python/ceval.c

diff --git a/PCbuild/pyproject.props b/PCbuild/pyproject.props
index dbdb6b743bea37..17abfa85201a90 100644
--- a/PCbuild/pyproject.props
+++ b/PCbuild/pyproject.props
@@ -53,6 +53,7 @@
 
   
$(PySourcePath)Include;$(PySourcePath)Include\internal;$(PySourcePath)Include\internal\mimalloc;$(GeneratedPyConfigDir);$(PySourcePath)PC;%(AdditionalIncludeDirectories)
   
WIN32;$(_Py3NamePreprocessorDefinition);$(_PlatformPreprocessorDefinition)$(_DebugPreprocessorDefinition)$(_PyStatsPreprocessorDefinition)$(_PydPreprocessorDefinition)%(PreprocessorDefinitions)
+  _Py_USING_PGO=1;%(PreprocessorDefinitions)
 
   MaxSpeed
   true
diff --git a/Python/ceval.c b/Python/ceval.c
index 1e4f1f3af20aca..c6a7a0f841f027 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -764,6 +764,23 @@ _PyObjectArray_Free(PyObject **array, PyObject **scratch)
 #define PY_EVAL_C_STACK_UNITS 2
 
 
+/* _PyEval_EvalFrameDefault is too large to optimize for speed with PGO on MSVC
+   when the JIT is enabled or GIL is disabled. Disable that optimization around
+   this function only. If this is fixed upstream, we should gate this on the
+   version of MSVC.
+ */
+#if (defined(_MSC_VER) && \
+ defined(_Py_USING_PGO) && \
+ (defined(_Py_JIT) || \
+  defined(Py_GIL_DISABLED)))
+#define DO_NOT_OPTIMIZE_INTERP_LOOP
+#endif
+
+#ifdef DO_NOT_OPTIMIZE_INTERP_LOOP
+#  pragma optimize("t", off)
+/* This setting is reversed below following _PyEval_EvalFrameDefault */
+#endif
+
 #ifdef Py_TAIL_CALL_INTERP
 #include "opcode_targets.h"
 #include "generated_cases.c.h"
@@ -986,6 +1003,10 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, 
_PyInterpreterFrame *frame, int
 return NULL;
 }
 
+#ifdef DO_NOT_OPTIMIZE_INTERP_LOOP
+#  pragma optimize("", on)
+#endif
+
 #if defined(__GNUC__)
 #  pragma GCC diagnostic pop
 #elif defined(_MSC_VER) /* MS_WINDOWS */

___
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com


[Python-checkins] gh-128563: Move lltrace into the frame struct (GH-129113)

2025-01-21 Thread Fidget-Spinner
https://github.com/python/cpython/commit/5809b2590956d51ce805f877e4708d21f59fb222
commit: 5809b2590956d51ce805f877e4708d21f59fb222
branch: main
author: Ken Jin 
committer: Fidget-Spinner 
date: 2025-01-21T22:17:15+08:00
summary:

gh-128563: Move lltrace into the frame struct (GH-129113)

files:
M Include/internal/pycore_frame.h
M Python/bytecodes.c
M Python/ceval.c
M Python/ceval_macros.h
M Python/executor_cases.c.h

diff --git a/Include/internal/pycore_frame.h b/Include/internal/pycore_frame.h
index 77a922630cde08..14dc91e54298ce 100644
--- a/Include/internal/pycore_frame.h
+++ b/Include/internal/pycore_frame.h
@@ -76,7 +76,12 @@ typedef struct _PyInterpreterFrame {
 _PyStackRef *stackpointer;
 uint16_t return_offset;  /* Only relevant during a function call */
 char owner;
-char visited;
+#ifdef Py_DEBUG
+uint8_t visited:1;
+uint8_t lltrace:7;
+#else
+uint8_t visited;
+#endif
 /* Locals and stack */
 _PyStackRef localsplus[1];
 } _PyInterpreterFrame;
diff --git a/Python/bytecodes.c b/Python/bytecodes.c
index 8bda4501df5f74..8bed29ca2c8fc7 100644
--- a/Python/bytecodes.c
+++ b/Python/bytecodes.c
@@ -4990,7 +4990,7 @@ dummy_func(
 _Py_CODEUNIT *target = _PyFrame_GetBytecode(frame) + exit->target;
 #if defined(Py_DEBUG) && !defined(_Py_JIT)
 OPT_HIST(trace_uop_execution_counter, trace_run_length_hist);
-if (lltrace >= 2) {
+if (frame->lltrace >= 2) {
 printf("SIDE EXIT: [UOp ");
 _PyUOpPrint(&next_uop[-1]);
 printf(", exit %u, temp %d, target %d -> %s]\n",
@@ -5108,7 +5108,7 @@ dummy_func(
 _Py_CODEUNIT *target = frame->instr_ptr;
 #if defined(Py_DEBUG) && !defined(_Py_JIT)
 OPT_HIST(trace_uop_execution_counter, trace_run_length_hist);
-if (lltrace >= 2) {
+if (frame->lltrace >= 2) {
 printf("DYNAMIC EXIT: [UOp ");
 _PyUOpPrint(&next_uop[-1]);
 printf(", exit %u, temp %d, target %d -> %s]\n",
diff --git a/Python/ceval.c b/Python/ceval.c
index 813d980acf5aab..58a54467f06bb0 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -799,9 +799,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, 
_PyInterpreterFrame *frame, int
 #endif
 uint8_t opcode;/* Current opcode */
 int oparg; /* Current opcode argument, if any */
-#ifdef LLTRACE
-int lltrace = 0;
-#endif
 
 _PyInterpreterFrame  entry_frame;
 
@@ -821,6 +818,9 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, 
_PyInterpreterFrame *frame, int
 entry_frame.owner = FRAME_OWNED_BY_INTERPRETER;
 entry_frame.visited = 0;
 entry_frame.return_offset = 0;
+#ifdef LLTRACE
+entry_frame.lltrace = 0;
+#endif
 /* Push frame */
 entry_frame.previous = tstate->current_frame;
 frame->previous = &entry_frame;
@@ -880,9 +880,12 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, 
_PyInterpreterFrame *frame, int
 stack_pointer = _PyFrame_GetStackPointer(frame);
 
 #ifdef LLTRACE
-lltrace = maybe_lltrace_resume_frame(frame, GLOBALS());
-if (lltrace < 0) {
-goto exit_unwind;
+{
+int lltrace = maybe_lltrace_resume_frame(frame, GLOBALS());
+frame->lltrace = lltrace;
+if (lltrace < 0) {
+goto exit_unwind;
+}
 }
 #endif
 
@@ -1002,7 +1005,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, 
_PyInterpreterFrame *frame, int
 }
 /* Resume normal execution */
 #ifdef LLTRACE
-if (lltrace >= 5) {
+if (frame->lltrace >= 5) {
 lltrace_resume_frame(frame);
 }
 #endif
@@ -1079,7 +1082,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, 
_PyInterpreterFrame *frame, int
 for (;;) {
 uopcode = next_uop->opcode;
 #ifdef Py_DEBUG
-if (lltrace >= 3) {
+if (frame->lltrace >= 3) {
 dump_stack(frame, stack_pointer);
 if (next_uop->opcode == _START_EXECUTOR) {
 printf("%4d uop: ", 0);
@@ -1121,7 +1124,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, 
_PyInterpreterFrame *frame, int
 
 jump_to_error_target:
 #ifdef Py_DEBUG
-if (lltrace >= 2) {
+if (frame->lltrace >= 2) {
 printf("Error: [UOp ");
 _PyUOpPrint(&next_uop[-1]);
 printf(" @ %d -> %s]\n",
@@ -1157,7 +1160,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, 
_PyInterpreterFrame *frame, int
 next_instr = next_uop[-1].target + _PyFrame_GetBytecode(frame);
 goto_to_tier1:
 #ifdef Py_DEBUG
-if (lltrace >= 2) {
+if (frame->lltrace >= 2) {
 printf("DEOPT: [UOp ");
 _PyUOpPrint(&next_uop[-1]);
 printf(" -> %s]\n",
diff --git a/Python/ceval_macros.h b

[Python-checkins] Remove unused DPRINTF in ceval.c (GH-129282)

2025-01-25 Thread Fidget-Spinner
https://github.com/python/cpython/commit/8fecb9fa0b42f7dc18bd58b1bef56f967612e088
commit: 8fecb9fa0b42f7dc18bd58b1bef56f967612e088
branch: main
author: Chris Eibl <138194463+chris-e...@users.noreply.github.com>
committer: Fidget-Spinner 
date: 2025-01-25T18:33:26+08:00
summary:

Remove unused DPRINTF in ceval.c (GH-129282)

remove unused DPRINTF in ceval.c

files:
M Python/ceval.c

diff --git a/Python/ceval.c b/Python/ceval.c
index 171b383d547e35..1bdae338845758 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -1063,13 +1063,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, 
_PyInterpreterFrame *frame, int
 #undef ENABLE_SPECIALIZATION_FT
 #define ENABLE_SPECIALIZATION_FT 0
 
-#ifdef Py_DEBUG
-#define DPRINTF(level, ...) \
-if (lltrace >= (level)) { printf(__VA_ARGS__); }
-#else
-#define DPRINTF(level, ...)
-#endif
-
 ; // dummy statement after a label, before a declaration
 uint16_t uopcode;
 #ifdef Py_STATS

___
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com


[Python-checkins] gh-128563: Move labels in ceval.c to bytecodes.c (GH-129112)

2025-01-27 Thread Fidget-Spinner
https://github.com/python/cpython/commit/87fb8b198c1633d9ce0b542eda230575892f416e
commit: 87fb8b198c1633d9ce0b542eda230575892f416e
branch: main
author: Ken Jin 
committer: Fidget-Spinner 
date: 2025-01-27T18:30:20+08:00
summary:

gh-128563: Move labels in ceval.c to bytecodes.c (GH-129112)

files:
M Lib/test/test_generated_cases.py
M Python/bytecodes.c
M Python/ceval.c
M Python/generated_cases.c.h
M Tools/cases_generator/analyzer.py
M Tools/cases_generator/lexer.py
M Tools/cases_generator/parser.py
M Tools/cases_generator/parsing.py
M Tools/cases_generator/tier1_generator.py

diff --git a/Lib/test/test_generated_cases.py b/Lib/test/test_generated_cases.py
index b5367a0f3ca367..bb78dd9af83b62 100644
--- a/Lib/test/test_generated_cases.py
+++ b/Lib/test/test_generated_cases.py
@@ -281,12 +281,12 @@ def run_cases_test(self, input: str, expected: str):
 )
 
 with open(self.temp_output_filename) as temp_output:
-lines = temp_output.readlines()
-while lines and lines[0].startswith(("// ", "#", "#", "\n")):
-lines.pop(0)
-while lines and lines[-1].startswith(("#", "\n")):
-lines.pop(-1)
-actual = "".join(lines)
+lines = temp_output.read()
+_, rest = lines.split(tier1_generator.INSTRUCTION_START_MARKER)
+instructions, labels_with_prelude_and_postlude = 
rest.split(tier1_generator.INSTRUCTION_END_MARKER)
+_, labels_with_postlude = 
labels_with_prelude_and_postlude.split(tier1_generator.LABEL_START_MARKER)
+labels, _ = 
labels_with_postlude.split(tier1_generator.LABEL_END_MARKER)
+actual = instructions + labels
 # if actual.strip() != expected.strip():
 # print("Actual:")
 # print(actual)
@@ -1756,6 +1756,61 @@ def test_kill_in_wrong_order(self):
 with self.assertRaises(SyntaxError):
 self.run_cases_test(input, "")
 
+def test_complex_label(self):
+input = """
+label(my_label) {
+// Comment
+do_thing()
+if (complex) {
+goto other_label;
+}
+goto other_label2;
+}
+"""
+
+output = """
+my_label:
+{
+// Comment
+do_thing()
+if (complex) {
+goto other_label;
+}
+goto other_label2;
+}
+"""
+self.run_cases_test(input, output)
+
+def test_multiple_labels(self):
+input = """
+label(my_label_1) {
+// Comment
+do_thing1();
+goto my_label_2;
+}
+
+label(my_label_2) {
+// Comment
+do_thing2();
+goto my_label_3;
+}
+"""
+
+output = """
+my_label_1:
+{
+// Comment
+do_thing1();
+goto my_label_2;
+}
+
+my_label_2:
+{
+// Comment
+do_thing2();
+goto my_label_3;
+}
+"""
 
 class TestGeneratedAbstractCases(unittest.TestCase):
 def setUp(self) -> None:
diff --git a/Python/bytecodes.c b/Python/bytecodes.c
index 12aae969340cbd..940ea9d4da6e41 100644
--- a/Python/bytecodes.c
+++ b/Python/bytecodes.c
@@ -53,6 +53,7 @@
 #define super(name) static int SUPER_##name
 #define family(name, ...) static int family_##name
 #define pseudo(name) static int pseudo_##name
+#define label(name) name:
 
 /* Annotations */
 #define guard
@@ -103,7 +104,6 @@ dummy_func(
 PyObject *codeobj;
 PyObject *cond;
 PyObject *descr;
-_PyInterpreterFrame  entry_frame;
 PyObject *exc;
 PyObject *exit;
 PyObject *fget;
@@ -5167,6 +5167,125 @@ dummy_func(
 assert(tstate->tracing || eval_breaker == 
FT_ATOMIC_LOAD_UINTPTR_ACQUIRE(_PyFrame_GetCode(frame)->_co_instrumentation_version));
 }
 
+label(pop_4_error) {
+STACK_SHRINK(1);
+goto pop_3_error;
+}
+
+label(pop_3_error) {
+STACK_SHRINK(1);
+goto pop_2_error;
+}
+
+label(pop_2_error) {
+STACK_SHRINK(1);
+goto pop_1_error;
+}
+
+label(pop_1_error) {
+STACK_SHRINK(1);
+goto error;
+}
+
+label(error) {
+/* Double-check exception status. */
+#ifdef NDEBUG
+if (!_PyErr_Occurred(tstate)) {
+_PyErr_SetString(tstate, PyExc_SystemError,
+ "error return without exception set");
+}
+#else
+assert(_PyErr_Occurred(tstate));
+#endif
+
+/* Log traceback info. */
+assert(frame-&

[Python-checkins] gh-128563: Move GO_TO_INSTRUCTION and PREDICT to cases generator (GH-129115)

2025-01-21 Thread Fidget-Spinner
https://github.com/python/cpython/commit/86c1a60d5a28cfb51f8843b307f8969c40e3bbec
commit: 86c1a60d5a28cfb51f8843b307f8969c40e3bbec
branch: main
author: Ken Jin 
committer: Fidget-Spinner 
date: 2025-01-22T09:22:25+08:00
summary:

gh-128563: Move GO_TO_INSTRUCTION and PREDICT to cases generator (GH-129115)

files:
M Lib/test/test_generated_cases.py
M Python/ceval_macros.h
M Python/generated_cases.c.h
M Tools/cases_generator/generators_common.py
M Tools/cases_generator/tier1_generator.py

diff --git a/Lib/test/test_generated_cases.py b/Lib/test/test_generated_cases.py
index 4b17bd5c797375..c93d6fc3d237a2 100644
--- a/Lib/test/test_generated_cases.py
+++ b/Lib/test/test_generated_cases.py
@@ -412,7 +412,7 @@ def test_predictions(self):
 frame->instr_ptr = next_instr;
 next_instr += 1;
 INSTRUCTION_STATS(OP1);
-PREDICTED(OP1);
+PREDICTED_OP1:;
 _PyStackRef res;
 res = Py_None;
 stack_pointer[-1] = res;
@@ -646,7 +646,7 @@ def test_macro_instruction(self):
 frame->instr_ptr = next_instr;
 next_instr += 6;
 INSTRUCTION_STATS(OP);
-PREDICTED(OP);
+PREDICTED_OP:;
 _Py_CODEUNIT* const this_instr = next_instr - 6;
 (void)this_instr;
 _PyStackRef left;
diff --git a/Python/ceval_macros.h b/Python/ceval_macros.h
index feaac07fe435b6..62c80c96e422fd 100644
--- a/Python/ceval_macros.h
+++ b/Python/ceval_macros.h
@@ -166,35 +166,6 @@ GETITEM(PyObject *v, Py_ssize_t i) {
 #define JUMPBY(x)   (next_instr += (x))
 #define SKIP_OVER(x)(next_instr += (x))
 
-/* OpCode prediction macros
-Some opcodes tend to come in pairs thus making it possible to
-predict the second code when the first is run.  For example,
-COMPARE_OP is often followed by POP_JUMP_IF_FALSE or POP_JUMP_IF_TRUE.
-
-Verifying the prediction costs a single high-speed test of a register
-variable against a constant.  If the pairing was good, then the
-processor's own internal branch predication has a high likelihood of
-success, resulting in a nearly zero-overhead transition to the
-next opcode.  A successful prediction saves a trip through the eval-loop
-including its unpredictable switch-case branch.  Combined with the
-processor's internal branch prediction, a successful PREDICT has the
-effect of making the two opcodes run as if they were a single new opcode
-with the bodies combined.
-
-If collecting opcode statistics, your choices are to either keep the
-predictions turned-on and interpret the results as if some opcodes
-had been combined or turn-off predictions so that the opcode frequency
-counter updates for both opcodes.
-
-Opcode prediction is disabled with threaded code, since the latter allows
-the CPU to record separate branch prediction information for each
-opcode.
-
-*/
-
-#define PREDICT_ID(op)  PRED_##op
-#define PREDICTED(op)   PREDICT_ID(op):
-
 
 /* Stack manipulation macros */
 
@@ -260,8 +231,6 @@ GETITEM(PyObject *v, Py_ssize_t i) {
  GETLOCAL(i) = value; \
  PyStackRef_XCLOSE(tmp); } while (0)
 
-#define GO_TO_INSTRUCTION(op) goto PREDICT_ID(op)
-
 #ifdef Py_STATS
 #define UPDATE_MISS_STATS(INSTNAME)  \
 do { \
@@ -281,7 +250,7 @@ GETITEM(PyObject *v, Py_ssize_t i) {
 /* This is only a single jump on release builds! */ \
 UPDATE_MISS_STATS((INSTNAME));  \
 assert(_PyOpcode_Deopt[opcode] == (INSTNAME));  \
-GO_TO_INSTRUCTION(INSTNAME);\
+goto PREDICTED_##INSTNAME;  \
 }
 
 
diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h
index a8dbcabde538d5..d0ab667a8bc8ab 100644
--- a/Python/generated_cases.c.h
+++ b/Python/generated_cases.c.h
@@ -13,7 +13,7 @@
 frame->instr_ptr = next_instr;
 next_instr += 6;
 INSTRUCTION_STATS(BINARY_OP);
-PREDICTED(BINARY_OP);
+PREDICTED_BINARY_OP:;
 _Py_CODEUNIT* const this_instr = next_instr - 6;
 (void)this_instr;
 _PyStackRef lhs;
@@ -484,7 +484,7 @@
 frame->instr_ptr = next_instr;
 next_instr += 2;
 INSTRUCTION_STATS(BINARY_SUBSCR);
-PREDICTED(BINARY_SUBSCR);
+PREDICTED_BINARY_SUBSCR:;
 _Py_CODEUNIT* const this_instr = next_instr - 2;
 (void)this_instr;
 _PyStackRef container;
@@ -931,7 +931,7 @@
 frame->instr_ptr = next_instr;
 next_instr += 4;
 INSTRUCTION_STATS(CALL);
-PREDICTED(CALL);
+PREDICTED_CALL:;
 _Py_CODEUNIT* const this_instr = next_inst

[Python-checkins] gh-128195: Add `_REPLACE_WITH_TRUE` to the tier2 optimizer (GH-128203)

2024-12-23 Thread Fidget-Spinner
https://github.com/python/cpython/commit/30efede33ca1fe32debbae93cc40b0e7e0b133b3
commit: 30efede33ca1fe32debbae93cc40b0e7e0b133b3
branch: main
author: Yan Yanchii 
committer: Fidget-Spinner 
date: 2024-12-24T05:17:47+08:00
summary:

gh-128195: Add `_REPLACE_WITH_TRUE` to the tier2 optimizer (GH-128203)

Add `_REPLACE_WITH_TRUE` to the tier2 optimizer

files:
M Python/optimizer_bytecodes.c
M Python/optimizer_cases.c.h

diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c
index e60c0d38425bfe..a14d119b7a1dec 100644
--- a/Python/optimizer_bytecodes.c
+++ b/Python/optimizer_bytecodes.c
@@ -899,6 +899,10 @@ dummy_func(void) {
 (void)version;
 }
 
+op(_REPLACE_WITH_TRUE, (value -- res)) {
+res = sym_new_const(ctx, Py_True);
+}
+
 // END BYTECODES //
 
 }
diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h
index b46079ec8a1992..0fcf5e18ed5808 100644
--- a/Python/optimizer_cases.c.h
+++ b/Python/optimizer_cases.c.h
@@ -211,7 +211,7 @@
 
 case _REPLACE_WITH_TRUE: {
 _Py_UopsSymbol *res;
-res = sym_new_not_null(ctx);
+res = sym_new_const(ctx, Py_True);
 stack_pointer[-1] = res;
 break;
 }

___
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com


[Python-checkins] gh-129819: Allow tier2/JIT and tailcall (GH-129820)

2025-02-12 Thread Fidget-Spinner
https://github.com/python/cpython/commit/1b27f36eb0ef146aa60b261a1cffcc6fd55c0e88
commit: 1b27f36eb0ef146aa60b261a1cffcc6fd55c0e88
branch: main
author: Ken Jin 
committer: Fidget-Spinner 
date: 2025-02-13T02:18:36+08:00
summary:

gh-129819: Allow tier2/JIT and tailcall (GH-129820)

files:
A Misc/NEWS.d/next/Build/2025-02-11-08-06-44.gh-issue-129819.7rn4dY.rst
M Python/ceval_macros.h
M configure
M configure.ac
M pyconfig.h.in

diff --git 
a/Misc/NEWS.d/next/Build/2025-02-11-08-06-44.gh-issue-129819.7rn4dY.rst 
b/Misc/NEWS.d/next/Build/2025-02-11-08-06-44.gh-issue-129819.7rn4dY.rst
new file mode 100644
index 00..2463e4dba24ae9
--- /dev/null
+++ b/Misc/NEWS.d/next/Build/2025-02-11-08-06-44.gh-issue-129819.7rn4dY.rst
@@ -0,0 +1 @@
+Allow building the JIT with the tailcall interpreter.
diff --git a/Python/ceval_macros.h b/Python/ceval_macros.h
index 50e940c19732ad..2cb78fa80b4658 100644
--- a/Python/ceval_macros.h
+++ b/Python/ceval_macros.h
@@ -397,7 +397,7 @@ do {   \
 stack_pointer = _PyFrame_GetStackPointer(frame);   \
 if (next_instr == NULL) {  \
 next_instr = frame->instr_ptr; \
-goto error;\
+JUMP_TO_LABEL(error);  \
 }  \
 DISPATCH();\
 } while (0)
diff --git a/configure b/configure
index d46bc563a67245..453b0123ded0a4 100755
--- a/configure
+++ b/configure
@@ -29284,18 +29284,6 @@ esac
 fi
 
 
-# Do not enable tail-calling interpreter if tier 2 is enabled.
-if ${tier2_flags:+false} :
-then :
-
-case "$ac_cv_tail_call" in yes*)
-
-printf "%s\n" "#define Py_TAIL_CALL_INTERP 1" >>confdefs.h
-
-esac
-
-fi
-
 
 case $ac_sys_system in
 AIX*)
diff --git a/configure.ac b/configure.ac
index faa8909530389d..234ae90616af62 100644
--- a/configure.ac
+++ b/configure.ac
@@ -7033,19 +7033,6 @@ fi
 ],
 [AC_MSG_RESULT([no value specified])])
 
-# Do not enable tail-calling interpreter if tier 2 is enabled.
-AS_VAR_IF(
-  [tier2_flags],
-  [],
-  [
-case "$ac_cv_tail_call" in yes*)
-  AC_DEFINE([Py_TAIL_CALL_INTERP], [1],
-  [Define if the C compiler supports efficient proper tail calls.])
-esac
-  ],
-  []
-)
-
 
 case $ac_sys_system in
 AIX*)
diff --git a/pyconfig.h.in b/pyconfig.h.in
index 9ea01ad3fc0a31..4295b4f5ea5fbd 100644
--- a/pyconfig.h.in
+++ b/pyconfig.h.in
@@ -1718,7 +1718,7 @@
 /* The version of SunOS/Solaris as reported by `uname -r' without the dot. */
 #undef Py_SUNOS_VERSION
 
-/* Define if the C compiler supports efficient proper tail calls. */
+/* Define if you want to use tail-calling interpreters in CPython. */
 #undef Py_TAIL_CALL_INTERP
 
 /* Define if you want to enable tracing references for debugging purpose */

___
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com


[Python-checkins] gh-130048: Reintroduce full LTO as default on Clang (GH-130049)

2025-02-13 Thread Fidget-Spinner
https://github.com/python/cpython/commit/34c06ccc4c6c21935b46302935f3df24b00daa2c
commit: 34c06ccc4c6c21935b46302935f3df24b00daa2c
branch: main
author: Ken Jin 
committer: Fidget-Spinner 
date: 2025-02-13T22:06:00+08:00
summary:

gh-130048: Reintroduce full LTO as default on Clang (GH-130049)

files:
A Misc/NEWS.d/next/Build/2025-02-12-19-51-19.gh-issue-130048.kHNkzP.rst
M Doc/using/configure.rst
M Doc/whatsnew/3.14.rst
M configure
M configure.ac

diff --git a/Doc/using/configure.rst b/Doc/using/configure.rst
index 72912cea2f0c28..e7116d55815679 100644
--- a/Doc/using/configure.rst
+++ b/Doc/using/configure.rst
@@ -575,6 +575,9 @@ also be used to improve performance.
.. versionchanged:: 3.12
   Use ThinLTO as the default optimization policy on Clang if the compiler 
accepts the flag.
 
+   .. versionchanged:: next
+  Revert to using full LTO as the default optimization policy on Clang.
+
 .. option:: --enable-bolt
 
Enable usage of the `BOLT post-link binary optimizer
diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst
index ece5afd4597ab8..8e4b617181fd99 100644
--- a/Doc/whatsnew/3.14.rst
+++ b/Doc/whatsnew/3.14.rst
@@ -1279,6 +1279,10 @@ Build changes
 * GNU Autoconf 2.72 is now required to generate :file:`configure`.
   (Contributed by Erlend Aasland in :gh:`115765`.)
 
+* CPython now uses Full LTO as the default link time optimization policy
+  on Clang. This reverts an earlier change in CPython 3.12.
+  (Contributed by Ken Jin in :gh:`130049`.)
+
 .. _whatsnew314-pep761:
 
 PEP 761: Discontinuation of PGP signatures
diff --git 
a/Misc/NEWS.d/next/Build/2025-02-12-19-51-19.gh-issue-130048.kHNkzP.rst 
b/Misc/NEWS.d/next/Build/2025-02-12-19-51-19.gh-issue-130048.kHNkzP.rst
new file mode 100644
index 00..2344325e689f34
--- /dev/null
+++ b/Misc/NEWS.d/next/Build/2025-02-12-19-51-19.gh-issue-130048.kHNkzP.rst
@@ -0,0 +1 @@
+CPython now uses Full LTO as the default link time optimization policy on 
Clang. This reverts an earlier change in CPython 3.12.
diff --git a/configure b/configure
index 453b0123ded0a4..bebc8bc1a34f9b 100755
--- a/configure
+++ b/configure
@@ -8766,55 +8766,8 @@ printf "%s\n" "$as_me: llvm-ar found via xcrun: 
${LLVM_AR}" >&6;}
   # Any changes made here should be reflected in the GCC+Darwin case 
below
   if test $Py_LTO_POLICY = default
   then
-# Check that ThinLTO is accepted.
-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether C 
compiler accepts -flto=thin" >&5
-printf %s "checking whether C compiler accepts -flto=thin... " >&6; }
-if test ${ax_cv_check_cflags___flto_thin+y}
-then :
-  printf %s "(cached) " >&6
-else case e in #(
-  e)
-  ax_check_save_flags=$CFLAGS
-  CFLAGS="$CFLAGS  -flto=thin"
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-int
-main (void)
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"
-then :
-  ax_cv_check_cflags___flto_thin=yes
-else case e in #(
-  e) ax_cv_check_cflags___flto_thin=no ;;
-esac
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
-  CFLAGS=$ax_check_save_flags ;;
-esac
-fi
-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: 
$ax_cv_check_cflags___flto_thin" >&5
-printf "%s\n" "$ax_cv_check_cflags___flto_thin" >&6; }
-if test "x$ax_cv_check_cflags___flto_thin" = xyes
-then :
-
-  LTOFLAGS="-flto=thin -Wl,-export_dynamic 
-Wl,-object_path_lto,\"\$@\".lto"
-  LTOCFLAGS="-flto=thin"
-
-else case e in #(
-  e)
-  LTOFLAGS="-flto -Wl,-export_dynamic 
-Wl,-object_path_lto,\"\$@\".lto"
-  LTOCFLAGS="-flto"
-
- ;;
-esac
-fi
-
+LTOFLAGS="-flto -Wl,-export_dynamic 
-Wl,-object_path_lto,\"\$@\".lto"
+LTOCFLAGS="-flto"
   else
 LTOFLAGS="-flto=${Py_LTO_POLICY} -Wl,-export_dynamic 
-Wl,-object_path_lto,\"\$@\".lto"
 LTOCFLAGS="-flto=${Py_LTO_POLICY}"
@@ -8823,48 +8776,7 @@ fi
 *)
   if test $Py_LTO_POLICY = default
   then
-# Check that ThinLTO is accepted
-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether C 
compiler accepts -flto=thin" >&5
-printf %s "checking whether C compiler accepts -flto=thin... " >&6; }
-if test ${ax_cv_check_cflags___flto_thin+y}
-then :
-  printf %s "(cached) " >&6
-else case e in #(
-  e)
-  ax_check_save_flags=$CFLAGS
-  CFLAGS="$CFLAGS  -flto=thin"
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-int
-main (void)
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINEN

[Python-checkins] Trigger tail call CI on more files (GH-129906)

2025-02-09 Thread Fidget-Spinner
https://github.com/python/cpython/commit/8f9c6fa0773cff586d127d1b77b158edd4718035
commit: 8f9c6fa0773cff586d127d1b77b158edd4718035
branch: main
author: Ken Jin 
committer: Fidget-Spinner 
date: 2025-02-10T00:52:58+08:00
summary:

Trigger tail call CI on more files (GH-129906)

files:
M .github/workflows/tail-call.yml

diff --git a/.github/workflows/tail-call.yml b/.github/workflows/tail-call.yml
index 37df21af02e919..4c2516c517b3a9 100644
--- a/.github/workflows/tail-call.yml
+++ b/.github/workflows/tail-call.yml
@@ -5,11 +5,13 @@ on:
   - 'Python/bytecodes.c'
   - 'Python/ceval.c'
   - 'Python/ceval_macros.h'
+  - 'Python/generated_cases.c.h'
   push:
 paths:
   - 'Python/bytecodes.c'
   - 'Python/ceval.c'
   - 'Python/ceval_macros.h'
+  - 'Python/generated_cases.c.h'
   workflow_dispatch:
 
 permissions:

___
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com


[Python-checkins] gh-129989: Properly disable tailcall interp in configure (GH-129991)

2025-02-15 Thread Fidget-Spinner
https://github.com/python/cpython/commit/359c7dde3bb074e029686913f531457eb121d1dd
commit: 359c7dde3bb074e029686913f531457eb121d1dd
branch: main
author: Ken Jin 
committer: Fidget-Spinner 
date: 2025-02-16T03:01:24+08:00
summary:

gh-129989: Properly disable tailcall interp in configure (GH-129991)

Co-authored-by: Zanie Blue 

files:
A Misc/NEWS.d/next/Build/2025-02-11-07-55-28.gh-issue-129989.kaSKlD.rst
M Lib/test/test_generated_cases.py
M Python/bytecodes.c
M Python/ceval.c
M Python/ceval_macros.h
M Python/generated_cases.c.h
M Python/opcode_targets.h
M Tools/cases_generator/target_generator.py
M Tools/cases_generator/tier1_generator.py

diff --git a/Lib/test/test_generated_cases.py b/Lib/test/test_generated_cases.py
index f9a54f3b412b4a..ff6b566faa4a23 100644
--- a/Lib/test/test_generated_cases.py
+++ b/Lib/test/test_generated_cases.py
@@ -304,7 +304,7 @@ def test_inst_no_args(self):
 """
 output = """
 TARGET(OP) {
-#if defined(Py_TAIL_CALL_INTERP)
+#if Py_TAIL_CALL_INTERP
 int opcode = OP;
 (void)(opcode);
 #endif
@@ -326,7 +326,7 @@ def test_inst_one_pop(self):
 """
 output = """
 TARGET(OP) {
-#if defined(Py_TAIL_CALL_INTERP)
+#if Py_TAIL_CALL_INTERP
 int opcode = OP;
 (void)(opcode);
 #endif
@@ -351,7 +351,7 @@ def test_inst_one_push(self):
 """
 output = """
 TARGET(OP) {
-#if defined(Py_TAIL_CALL_INTERP)
+#if Py_TAIL_CALL_INTERP
 int opcode = OP;
 (void)(opcode);
 #endif
@@ -377,7 +377,7 @@ def test_inst_one_push_one_pop(self):
 """
 output = """
 TARGET(OP) {
-#if defined(Py_TAIL_CALL_INTERP)
+#if Py_TAIL_CALL_INTERP
 int opcode = OP;
 (void)(opcode);
 #endif
@@ -404,7 +404,7 @@ def test_binary_op(self):
 """
 output = """
 TARGET(OP) {
-#if defined(Py_TAIL_CALL_INTERP)
+#if Py_TAIL_CALL_INTERP
 int opcode = OP;
 (void)(opcode);
 #endif
@@ -434,7 +434,7 @@ def test_overlap(self):
 """
 output = """
 TARGET(OP) {
-#if defined(Py_TAIL_CALL_INTERP)
+#if Py_TAIL_CALL_INTERP
 int opcode = OP;
 (void)(opcode);
 #endif
@@ -466,7 +466,7 @@ def test_predictions(self):
 """
 output = """
 TARGET(OP1) {
-#if defined(Py_TAIL_CALL_INTERP)
+#if Py_TAIL_CALL_INTERP
 int opcode = OP1;
 (void)(opcode);
 #endif
@@ -481,7 +481,7 @@ def test_predictions(self):
 }
 
 TARGET(OP3) {
-#if defined(Py_TAIL_CALL_INTERP)
+#if Py_TAIL_CALL_INTERP
 int opcode = OP3;
 (void)(opcode);
 #endif
@@ -519,7 +519,7 @@ def test_sync_sp(self):
 """
 output = """
 TARGET(A) {
-#if defined(Py_TAIL_CALL_INTERP)
+#if Py_TAIL_CALL_INTERP
 int opcode = A;
 (void)(opcode);
 #endif
@@ -540,7 +540,7 @@ def test_sync_sp(self):
 }
 
 TARGET(B) {
-#if defined(Py_TAIL_CALL_INTERP)
+#if Py_TAIL_CALL_INTERP
 int opcode = B;
 (void)(opcode);
 #endif
@@ -581,7 +581,7 @@ def test_error_if_plain(self):
 """
 output = """
 TARGET(OP) {
-#if defined(Py_TAIL_CALL_INTERP)
+#if Py_TAIL_CALL_INTERP
 int opcode = OP;
 (void)(opcode);
 #endif
@@ -604,7 +604,7 @@ def test_error_if_plain_with_comment(self):
 """
 output = """
 TARGET(OP) {
-#if defined(Py_TAIL_CALL_INTERP)
+#if Py_TAIL_CALL_INTERP
 int opcode = OP;
 (void)(opcode);
 #endif
@@ -631,7 +631,7 @@ def test_error_if_pop(self):
 """
 output = """
 TARGET(OP) {
-#if defined(Py_TAIL_CALL_INTERP)
+#if Py_TAIL_CALL_INTERP
 int opcode = OP;
 (void)(opcode);
 #endif
@@ -666,7 +666,7 @@ def test_error_if_pop_with_result(self):
 """
 output = """
 TARGET(OP) {
-#if defined(Py_TAIL_CALL_INTERP)
+#if Py_TAIL_CALL_INTERP
 int opcode = OP;
 (void)(opcode);
 #endif
@@ -697,7 +697,7 @@ def test_cache_effect(self):
 """
 output = &q

[Python-checkins] Add Neil's suggestions to whatsnew wording for tailcall (#130155)

2025-02-15 Thread Fidget-Spinner
https://github.com/python/cpython/commit/a13460ac4427892be613bf0e2988f5a2b2364602
commit: a13460ac4427892be613bf0e2988f5a2b2364602
branch: main
author: Ken Jin 
committer: Fidget-Spinner 
date: 2025-02-15T21:09:37+08:00
summary:

Add Neil's suggestions to whatsnew wording for tailcall (#130155)

Add Neil's suggestions

Co-authored-by: Neil Schemenauer <690853+nasch...@users.noreply.github.com>

files:
M Doc/whatsnew/3.14.rst

diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst
index ece5afd4597ab8..c42a5a022b7e43 100644
--- a/Doc/whatsnew/3.14.rst
+++ b/Doc/whatsnew/3.14.rst
@@ -224,7 +224,9 @@ configuration mechanisms).
 A new type of interpreter
 -
 
-A new type of interpreter based on tail calls has been added to CPython.
+A new type of interpreter has been added to CPython.
+It uses tail calls between small C functions that implement individual
+Python opcodes, rather than one large C case statement.
 For certain newer compilers, this interpreter provides
 significantly better performance. Preliminary numbers on our machines suggest
 anywhere from -3% to 30% faster Python code, and a geometric mean of 9-15%

___
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com


[Python-checkins] gh-132132: Upgrade LLVM on tail calling CI (GH-132098)

2025-04-05 Thread Fidget-Spinner
https://github.com/python/cpython/commit/92fb949eac22d1e058906123a21791ba55876090
commit: 92fb949eac22d1e058906123a21791ba55876090
branch: main
author: Ken Jin 
committer: Fidget-Spinner 
date: 2025-04-06T00:58:23+08:00
summary:

gh-132132: Upgrade LLVM on tail calling CI (GH-132098)

files:
M .github/workflows/tail-call.yml

diff --git a/.github/workflows/tail-call.yml b/.github/workflows/tail-call.yml
index 572ff45e51ef00..4636372e26c41b 100644
--- a/.github/workflows/tail-call.yml
+++ b/.github/workflows/tail-call.yml
@@ -45,7 +45,7 @@ jobs:
   - aarch64-unknown-linux-gnu/gcc
   - free-threading
 llvm:
-  - 19
+  - 20
 include:
 #  - target: i686-pc-windows-msvc/msvc
 #architecture: Win32
@@ -83,9 +83,9 @@ jobs:
 if: runner.os == 'Windows' && matrix.architecture != 'ARM64'
 shell: cmd
 run: |
-  choco install llvm --allow-downgrade --no-progress --version ${{ 
matrix.llvm }}.1.5
+  choco install llvm --allow-downgrade --no-progress --version ${{ 
matrix.llvm }}.1.0
   set PlatformToolset=clangcl
-  set LLVMToolsVersion=${{ matrix.llvm }}.1.5
+  set LLVMToolsVersion=${{ matrix.llvm }}.1.0
   set LLVMInstallDir=C:\Program Files\LLVM
   call ./PCbuild/build.bat --tail-call-interp -d -p ${{ 
matrix.architecture }}
   call ./PCbuild/rt.bat -d -p ${{ matrix.architecture }} -q 
--multiprocess 0 --timeout 4500 --verbose2 --verbose3
@@ -95,9 +95,9 @@ jobs:
 if: runner.os == 'Windows' && matrix.architecture == 'ARM64'
 shell: cmd
 run: |
-  choco install llvm --allow-downgrade --no-progress --version ${{ 
matrix.llvm }}.1.5
+  choco install llvm --allow-downgrade --no-progress --version ${{ 
matrix.llvm }}.1.0
   set PlatformToolset=clangcl
-  set LLVMToolsVersion=${{ matrix.llvm }}.1.5
+  set LLVMToolsVersion=${{ matrix.llvm }}.1.0
   set LLVMInstallDir=C:\Program Files\LLVM
   ./PCbuild/build.bat --tail-call-interp -p ${{ matrix.architecture }}
 
@@ -105,6 +105,8 @@ jobs:
 # This is a bug in the macOS runner image where the pre-installed 
Python is installed in the same
 # directory as the Homebrew Python, which causes the build to fail for 
macos-13. This line removes
 # the symlink to the pre-installed Python so that the Homebrew Python 
is used instead.
+# Note: when a new LLVM is released, the homebrew installation 
directory changes, so the builds will fail.
+# We either need to upgrade LLVM or change the directory being pointed 
to.
   - name: Native macOS (release)
 if: runner.os == 'macOS'
 run: |
@@ -112,9 +114,9 @@ jobs:
   find /usr/local/bin -lname '*/Library/Frameworks/Python.framework/*' 
-delete
   brew install llvm@${{ matrix.llvm }}
   export SDKROOT="$(xcrun --show-sdk-path)"
-  export PATH="/opt/homebrew/opt/llvm@${{ matrix.llvm }}/bin:$PATH"
-  export PATH="/usr/local/opt/llvm@${{ matrix.llvm }}/bin:$PATH"
-  CC=clang-19 ./configure --with-tail-call-interp
+  export PATH="/usr/local/opt/llvm/bin:$PATH"
+  export PATH="/opt/homebrew/opt/llvm/bin:$PATH"
+  CC=clang-20 ./configure --with-tail-call-interp
   make all --jobs 4
   ./python.exe -m test --multiprocess 0 --timeout 4500 --verbose2 
--verbose3
 
@@ -123,7 +125,7 @@ jobs:
 run: |
   sudo bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)" ./llvm.sh 
${{ matrix.llvm }}
   export PATH="$(llvm-config-${{ matrix.llvm }} --bindir):$PATH"
-  CC=clang-19 ./configure --with-tail-call-interp --with-pydebug
+  CC=clang-20 ./configure --with-tail-call-interp --with-pydebug
   make all --jobs 4
   ./python -m test --multiprocess 0 --timeout 4500 --verbose2 
--verbose3
 
@@ -132,7 +134,7 @@ jobs:
 run: |
   sudo bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)" ./llvm.sh 
${{ matrix.llvm }}
   export PATH="$(llvm-config-${{ matrix.llvm }} --bindir):$PATH"
-  CC=clang-19 ./configure --with-tail-call-interp --disable-gil
+  CC=clang-20 ./configure --with-tail-call-interp --disable-gil
   make all --jobs 4
   ./python -m test --multiprocess 0 --timeout 4500 --verbose2 
--verbose3
 

___
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com


[Python-checkins] gh-126703: Add PyCFunction freelist (GH-128692)

2025-04-05 Thread Fidget-Spinner
https://github.com/python/cpython/commit/29772b0647519254b94bdf82df1666e98c3de3a2
commit: 29772b0647519254b94bdf82df1666e98c3de3a2
branch: main
author: Pieter Eendebak 
committer: Fidget-Spinner 
date: 2025-04-05T23:51:05+08:00
summary:

gh-126703: Add PyCFunction freelist (GH-128692)

files:
A 
Misc/NEWS.d/next/Core_and_Builtins/2025-01-09-22-12-03.gh-issue-126703.6rAxZ7.rst
M Include/internal/pycore_freelist_state.h
M Objects/methodobject.c
M Objects/object.c

diff --git a/Include/internal/pycore_freelist_state.h 
b/Include/internal/pycore_freelist_state.h
index 7c252f5b570c13..54415b22fd41ef 100644
--- a/Include/internal/pycore_freelist_state.h
+++ b/Include/internal/pycore_freelist_state.h
@@ -24,6 +24,8 @@ extern "C" {
 #  define Py_futureiters_MAXFREELIST 255
 #  define Py_object_stack_chunks_MAXFREELIST 4
 #  define Py_unicode_writers_MAXFREELIST 1
+#  define Py_pycfunctionobject_MAXFREELIST 16
+#  define Py_pycmethodobject_MAXFREELIST 16
 #  define Py_pymethodobjects_MAXFREELIST 20
 
 // A generic freelist of either PyObjects or other data structures.
@@ -53,6 +55,8 @@ struct _Py_freelists {
 struct _Py_freelist futureiters;
 struct _Py_freelist object_stack_chunks;
 struct _Py_freelist unicode_writers;
+struct _Py_freelist pycfunctionobject;
+struct _Py_freelist pycmethodobject;
 struct _Py_freelist pymethodobjects;
 };
 
diff --git 
a/Misc/NEWS.d/next/Core_and_Builtins/2025-01-09-22-12-03.gh-issue-126703.6rAxZ7.rst
 
b/Misc/NEWS.d/next/Core_and_Builtins/2025-01-09-22-12-03.gh-issue-126703.6rAxZ7.rst
new file mode 100644
index 00..6dc04135c7879e
--- /dev/null
+++ 
b/Misc/NEWS.d/next/Core_and_Builtins/2025-01-09-22-12-03.gh-issue-126703.6rAxZ7.rst
@@ -0,0 +1 @@
+Improve performance of builtin methods by using a freelist.
diff --git a/Objects/methodobject.c b/Objects/methodobject.c
index ecec0f7205a11d..1f459dea44192c 100644
--- a/Objects/methodobject.c
+++ b/Objects/methodobject.c
@@ -4,6 +4,7 @@
 #include "Python.h"
 #include "pycore_call.h"  // _Py_CheckFunctionResult()
 #include "pycore_ceval.h" // _Py_EnterRecursiveCallTstate()
+#include "pycore_freelist.h"
 #include "pycore_object.h"
 #include "pycore_pyerrors.h"
 #include "pycore_pystate.h"   // _PyThreadState_GET()
@@ -85,9 +86,12 @@ PyCMethod_New(PyMethodDef *ml, PyObject *self, PyObject 
*module, PyTypeObject *c
 "flag but no class");
 return NULL;
 }
-PyCMethodObject *om = PyObject_GC_New(PyCMethodObject, 
&PyCMethod_Type);
+PyCMethodObject *om = _Py_FREELIST_POP(PyCMethodObject, 
pycmethodobject);
 if (om == NULL) {
-return NULL;
+om = PyObject_GC_New(PyCMethodObject, &PyCMethod_Type);
+if (om == NULL) {
+return NULL;
+}
 }
 om->mm_class = (PyTypeObject*)Py_NewRef(cls);
 op = (PyCFunctionObject *)om;
@@ -98,9 +102,12 @@ PyCMethod_New(PyMethodDef *ml, PyObject *self, PyObject 
*module, PyTypeObject *c
 "but no METH_METHOD flag");
 return NULL;
 }
-op = PyObject_GC_New(PyCFunctionObject, &PyCFunction_Type);
+op = _Py_FREELIST_POP(PyCFunctionObject, pycfunctionobject);
 if (op == NULL) {
-return NULL;
+op = PyObject_GC_New(PyCFunctionObject, &PyCFunction_Type);
+if (op == NULL) {
+return NULL;
+}
 }
 }
 
@@ -171,7 +178,14 @@ meth_dealloc(PyObject *self)
 Py_XDECREF(PyCFunction_GET_CLASS(m));
 Py_XDECREF(m->m_self);
 Py_XDECREF(m->m_module);
-PyObject_GC_Del(m);
+if (m->m_ml->ml_flags & METH_METHOD) {
+assert(Py_IS_TYPE(self, &PyCMethod_Type));
+_Py_FREELIST_FREE(pycmethodobject, m, PyObject_GC_Del);
+}
+else {
+assert(Py_IS_TYPE(self, &PyCFunction_Type));
+_Py_FREELIST_FREE(pycfunctionobject, m, PyObject_GC_Del);
+}
 Py_TRASHCAN_END;
 }
 
diff --git a/Objects/object.c b/Objects/object.c
index 457ff17b980e75..42ac3a1c2baa7b 100644
--- a/Objects/object.c
+++ b/Objects/object.c
@@ -942,6 +942,8 @@ _PyObject_ClearFreeLists(struct _Py_freelists *freelists, 
int is_finalization)
 }
 clear_freelist(&freelists->unicode_writers, is_finalization, PyMem_Free);
 clear_freelist(&freelists->ints, is_finalization, free_object);
+clear_freelist(&freelists->pycfunctionobject, is_finalization, 
PyObject_GC_Del);
+clear_freelist(&freelists->pycmethodobject, is_finalization, 
PyObject_GC_Del);
 clear_freelist(&freelists->pymethodobjects, is_finalization, free_object);
 }
 

___
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com


[Python-checkins] gh-131591: Fix GENERATE_DEBUG_SECTION for clangcl on Windows (GH-132112)

2025-04-05 Thread Fidget-Spinner
https://github.com/python/cpython/commit/d827d4d0184f8832075c6b75120892439a1d97ee
commit: d827d4d0184f8832075c6b75120892439a1d97ee
branch: main
author: Chris Eibl <138194463+chris-e...@users.noreply.github.com>
committer: Fidget-Spinner 
date: 2025-04-06T00:00:54+08:00
summary:

gh-131591: Fix GENERATE_DEBUG_SECTION for clangcl on Windows (GH-132112)

files:
M Include/internal/pycore_debug_offsets.h
M Modules/_asynciomodule.c
M Tools/c-analyzer/cpython/ignored.tsv

diff --git a/Include/internal/pycore_debug_offsets.h 
b/Include/internal/pycore_debug_offsets.h
index 124b104e4ba8ae..b280633c9ef679 100644
--- a/Include/internal/pycore_debug_offsets.h
+++ b/Include/internal/pycore_debug_offsets.h
@@ -23,7 +23,9 @@ extern "C" {
declaration  \
_GENERATE_DEBUG_SECTION_LINUX(name)
 
-#if defined(MS_WINDOWS) && !defined(__clang__)
+// Please note that section names are truncated to eight bytes
+// on Windows!
+#if defined(MS_WINDOWS)
 #define _GENERATE_DEBUG_SECTION_WINDOWS(name)   \
_Pragma(Py_STRINGIFY(section(Py_STRINGIFY(name), read, write))) \
__declspec(allocate(Py_STRINGIFY(name)))
diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c
index d938955e8cb0e3..b32db3a277cf4a 100644
--- a/Modules/_asynciomodule.c
+++ b/Modules/_asynciomodule.c
@@ -116,7 +116,7 @@ typedef struct _Py_AsyncioModuleDebugOffsets {
 } asyncio_thread_state;
 } Py_AsyncioModuleDebugOffsets;
 
-GENERATE_DEBUG_SECTION(AsyncioDebug, Py_AsyncioModuleDebugOffsets AsyncioDebug)
+GENERATE_DEBUG_SECTION(AsyncioDebug, Py_AsyncioModuleDebugOffsets 
_AsyncioDebug)
 = {.asyncio_task_object = {
.size = sizeof(TaskObj),
.task_name = offsetof(TaskObj, task_name),
diff --git a/Tools/c-analyzer/cpython/ignored.tsv 
b/Tools/c-analyzer/cpython/ignored.tsv
index 18e543ab33bb16..14dc5007b65861 100644
--- a/Tools/c-analyzer/cpython/ignored.tsv
+++ b/Tools/c-analyzer/cpython/ignored.tsv
@@ -56,7 +56,7 @@ Python/pyhash.c   -   _Py_HashSecret  -
 Python/parking_lot.c   -   buckets -
 
 ## data needed for introspecting asyncio state from debuggers and profilers
-Modules/_asynciomodule.c   -   AsyncioDebug-
+Modules/_asynciomodule.c   -   _AsyncioDebug   -
 
 
 ##

___
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com


[Python-checkins] gh-126703: Add freelist for range and range_iter objects (GH-128619)

2025-04-06 Thread Fidget-Spinner
https://github.com/python/cpython/commit/dff8bcfa3cb2daf0aa0d3f4717fd77948d3b2b2f
commit: dff8bcfa3cb2daf0aa0d3f4717fd77948d3b2b2f
branch: main
author: Pieter Eendebak 
committer: Fidget-Spinner 
date: 2025-04-07T04:40:52+08:00
summary:

gh-126703: Add freelist for range and range_iter objects (GH-128619)

files:
A 
Misc/NEWS.d/next/Core_and_Builtins/2025-01-08-09-41-25.gh-issue-126703.djs9e_.rst
M Include/internal/pycore_freelist_state.h
M Objects/object.c
M Objects/rangeobject.c

diff --git a/Include/internal/pycore_freelist_state.h 
b/Include/internal/pycore_freelist_state.h
index 54415b22fd41ef..4828dfd948f70a 100644
--- a/Include/internal/pycore_freelist_state.h
+++ b/Include/internal/pycore_freelist_state.h
@@ -18,6 +18,8 @@ extern "C" {
 #  define Py_floats_MAXFREELIST 100
 #  define Py_ints_MAXFREELIST 100
 #  define Py_slices_MAXFREELIST 1
+#  define Py_ranges_MAXFREELIST 6
+#  define Py_range_iters_MAXFREELIST 6
 #  define Py_contexts_MAXFREELIST 255
 #  define Py_async_gens_MAXFREELIST 80
 #  define Py_async_gen_asends_MAXFREELIST 80
@@ -49,6 +51,8 @@ struct _Py_freelists {
 struct _Py_freelist dicts;
 struct _Py_freelist dictkeys;
 struct _Py_freelist slices;
+struct _Py_freelist ranges;
+struct _Py_freelist range_iters;
 struct _Py_freelist contexts;
 struct _Py_freelist async_gens;
 struct _Py_freelist async_gen_asends;
diff --git 
a/Misc/NEWS.d/next/Core_and_Builtins/2025-01-08-09-41-25.gh-issue-126703.djs9e_.rst
 
b/Misc/NEWS.d/next/Core_and_Builtins/2025-01-08-09-41-25.gh-issue-126703.djs9e_.rst
new file mode 100644
index 00..2fb44568b12168
--- /dev/null
+++ 
b/Misc/NEWS.d/next/Core_and_Builtins/2025-01-08-09-41-25.gh-issue-126703.djs9e_.rst
@@ -0,0 +1 @@
+Improve performance of  :class:`range` by using a freelist.
diff --git a/Objects/object.c b/Objects/object.c
index 42ac3a1c2baa7b..99bb1d9c0bfad5 100644
--- a/Objects/object.c
+++ b/Objects/object.c
@@ -931,6 +931,8 @@ _PyObject_ClearFreeLists(struct _Py_freelists *freelists, 
int is_finalization)
 clear_freelist(&freelists->dicts, is_finalization, free_object);
 clear_freelist(&freelists->dictkeys, is_finalization, PyMem_Free);
 clear_freelist(&freelists->slices, is_finalization, free_object);
+clear_freelist(&freelists->ranges, is_finalization, free_object);
+clear_freelist(&freelists->range_iters, is_finalization, free_object);
 clear_freelist(&freelists->contexts, is_finalization, free_object);
 clear_freelist(&freelists->async_gens, is_finalization, free_object);
 clear_freelist(&freelists->async_gen_asends, is_finalization, free_object);
diff --git a/Objects/rangeobject.c b/Objects/rangeobject.c
index 24f9ce807fd24e..f8cdfe68a6435e 100644
--- a/Objects/rangeobject.c
+++ b/Objects/rangeobject.c
@@ -3,6 +3,7 @@
 #include "Python.h"
 #include "pycore_abstract.h"  // _PyIndex_Check()
 #include "pycore_ceval.h" // _PyEval_GetBuiltin()
+#include "pycore_freelist.h"
 #include "pycore_long.h"  // _PyLong_GetZero()
 #include "pycore_modsupport.h"// _PyArg_NoKwnames()
 #include "pycore_range.h"
@@ -51,16 +52,18 @@ static rangeobject *
 make_range_object(PyTypeObject *type, PyObject *start,
   PyObject *stop, PyObject *step)
 {
-rangeobject *obj = NULL;
 PyObject *length;
 length = compute_range_length(start, stop, step);
 if (length == NULL) {
 return NULL;
 }
-obj = PyObject_New(rangeobject, type);
+rangeobject *obj = _Py_FREELIST_POP(rangeobject, ranges);
 if (obj == NULL) {
-Py_DECREF(length);
-return NULL;
+obj = PyObject_New(rangeobject, type);
+if (obj == NULL) {
+Py_DECREF(length);
+return NULL;
+}
 }
 obj->start = start;
 obj->stop = stop;
@@ -171,7 +174,7 @@ range_dealloc(PyObject *op)
 Py_DECREF(r->stop);
 Py_DECREF(r->step);
 Py_DECREF(r->length);
-PyObject_Free(r);
+_Py_FREELIST_FREE(ranges, r, PyObject_Free);
 }
 
 static unsigned long
@@ -895,6 +898,12 @@ rangeiter_setstate(PyObject *op, PyObject *state)
 Py_RETURN_NONE;
 }
 
+static void
+rangeiter_dealloc(PyObject *self)
+{
+_Py_FREELIST_FREE(range_iters, (_PyRangeIterObject *)self, PyObject_Free);
+}
+
 PyDoc_STRVAR(reduce_doc, "Return state information for pickling.");
 PyDoc_STRVAR(setstate_doc, "Set state information for unpickling.");
 
@@ -911,7 +920,7 @@ PyTypeObject PyRangeIter_Type = {
 sizeof(_PyRangeIterObject), /* tp_basicsize */
 0,  /* tp_itemsize */
 /* methods */
-0,  /* tp_dealloc */
+rangeiter_dealloc,  /* tp_dealloc */
 0,  /* tp_vectorcall_offset *

[Python-checkins] gh-126703: Fix possible use after free in pycfunction freelist (GH-132319)

2025-04-09 Thread Fidget-Spinner
https://github.com/python/cpython/commit/bd3aa0b9f736164277a5bcd0a54f5f9beddbf11c
commit: bd3aa0b9f736164277a5bcd0a54f5f9beddbf11c
branch: main
author: Ken Jin 
committer: Fidget-Spinner 
date: 2025-04-09T22:49:33+08:00
summary:

gh-126703: Fix possible use after free in pycfunction freelist (GH-132319)

files:
A 
Misc/NEWS.d/next/Core_and_Builtins/2025-04-09-13-47-33.gh-issue-126703.kXiQHj.rst
M Objects/methodobject.c

diff --git 
a/Misc/NEWS.d/next/Core_and_Builtins/2025-04-09-13-47-33.gh-issue-126703.kXiQHj.rst
 
b/Misc/NEWS.d/next/Core_and_Builtins/2025-04-09-13-47-33.gh-issue-126703.kXiQHj.rst
new file mode 100644
index 00..d0461e17d0fa95
--- /dev/null
+++ 
b/Misc/NEWS.d/next/Core_and_Builtins/2025-04-09-13-47-33.gh-issue-126703.kXiQHj.rst
@@ -0,0 +1 @@
+Fix possible use after free in cases where a method's definition has the same 
lifetime as its ``self``.
diff --git a/Objects/methodobject.c b/Objects/methodobject.c
index 1f459dea44192c..189b026ab33559 100644
--- a/Objects/methodobject.c
+++ b/Objects/methodobject.c
@@ -173,12 +173,16 @@ meth_dealloc(PyObject *self)
 if (m->m_weakreflist != NULL) {
 PyObject_ClearWeakRefs((PyObject*) m);
 }
+// We need to access ml_flags here rather than later.
+// `m->m_ml` might have the same lifetime
+// as `m_self` when it's dynamically allocated.
+int ml_flags = m->m_ml->ml_flags;
 // Dereference class before m_self: PyCFunction_GET_CLASS accesses
 // PyMethodDef m_ml, which could be kept alive by m_self
 Py_XDECREF(PyCFunction_GET_CLASS(m));
 Py_XDECREF(m->m_self);
 Py_XDECREF(m->m_module);
-if (m->m_ml->ml_flags & METH_METHOD) {
+if (ml_flags & METH_METHOD) {
 assert(Py_IS_TYPE(self, &PyCMethod_Type));
 _Py_FREELIST_FREE(pycmethodobject, m, PyObject_GC_Del);
 }

___
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com


[Python-checkins] GH-131678: fix Windows tail-call CI does not run the test cases (GH-131690)

2025-03-28 Thread Fidget-Spinner
https://github.com/python/cpython/commit/ce77da5871334bffea722984cb705fd20a763a1f
commit: ce77da5871334bffea722984cb705fd20a763a1f
branch: main
author: Chris Eibl <138194463+chris-e...@users.noreply.github.com>
committer: Fidget-Spinner 
date: 2025-03-28T23:00:36+08:00
summary:

GH-131678: fix Windows tail-call CI does not run the test cases (GH-131690)

files:
M .github/workflows/tail-call.yml

diff --git a/.github/workflows/tail-call.yml b/.github/workflows/tail-call.yml
index 3bee758e2ad2cf..3c9098b88ee3b1 100644
--- a/.github/workflows/tail-call.yml
+++ b/.github/workflows/tail-call.yml
@@ -87,8 +87,8 @@ jobs:
   set PlatformToolset=clangcl
   set LLVMToolsVersion=${{ matrix.llvm }}.1.5
   set LLVMInstallDir=C:\Program Files\LLVM
-  ./PCbuild/build.bat --tail-call-interp -d -p ${{ matrix.architecture 
}}
-  ./PCbuild/rt.bat -d -p ${{ matrix.architecture }} -q --multiprocess 
0 --timeout 4500 --verbose2 --verbose3
+  call ./PCbuild/build.bat --tail-call-interp -d -p ${{ 
matrix.architecture }}
+  call ./PCbuild/rt.bat -d -p ${{ matrix.architecture }} -q 
--multiprocess 0 --timeout 4500 --verbose2 --verbose3
 
   # No tests (yet):
   - name: Emulated Windows (release)

___
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com


[Python-checkins] gh-131281: fix compile error due to `BINARY_SUBSCR` (GH-131283)

2025-03-15 Thread Fidget-Spinner
https://github.com/python/cpython/commit/1821f8f10c7a4a43a4fb55fe4e3da4cadfec699d
commit: 1821f8f10c7a4a43a4fb55fe4e3da4cadfec699d
branch: main
author: Xuanteng Huang <44627253+xuante...@users.noreply.github.com>
committer: Fidget-Spinner 
date: 2025-03-15T23:38:46+08:00
summary:

gh-131281: fix compile error due to `BINARY_SUBSCR` (GH-131283)

* fix compile error due to `BINARY_SUBSCR`

* replace stat_inc with `BINARY_OP`

files:
M Python/bytecodes.c
M Python/executor_cases.c.h
M Python/generated_cases.c.h

diff --git a/Python/bytecodes.c b/Python/bytecodes.c
index aaa25161d0943f..7af4d642edb919 100644
--- a/Python/bytecodes.c
+++ b/Python/bytecodes.c
@@ -878,7 +878,7 @@ dummy_func(
 assert(res_o != NULL);
 res = PyStackRef_FromPyObjectNew(res_o);
 #endif
-STAT_INC(BINARY_SUBSCR, hit);
+STAT_INC(BINARY_OP, hit);
 DECREF_INPUTS();
 }
 
diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h
index fb5b2240436f1c..ff9f33b6db0187 100644
--- a/Python/executor_cases.c.h
+++ b/Python/executor_cases.c.h
@@ -1253,7 +1253,7 @@
 assert(res_o != NULL);
 res = PyStackRef_FromPyObjectNew(res_o);
 #endif
-STAT_INC(BINARY_SUBSCR, hit);
+STAT_INC(BINARY_OP, hit);
 _PyFrame_SetStackPointer(frame, stack_pointer);
 _PyStackRef tmp = list_st;
 list_st = res;
diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h
index 8cdbaf1a4d5761..558b0b48ceaa71 100644
--- a/Python/generated_cases.c.h
+++ b/Python/generated_cases.c.h
@@ -702,7 +702,7 @@
 assert(res_o != NULL);
 res = PyStackRef_FromPyObjectNew(res_o);
 #endif
-STAT_INC(BINARY_SUBSCR, hit);
+STAT_INC(BINARY_OP, hit);
 _PyFrame_SetStackPointer(frame, stack_pointer);
 _PyStackRef tmp = list_st;
 list_st = res;

___
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com


[Python-checkins] gh-131281: Add include for pystats builds (#131369)

2025-03-17 Thread Fidget-Spinner
https://github.com/python/cpython/commit/b2ed7a6d6aae9860110f6ec495dc88dde670cfe4
commit: b2ed7a6d6aae9860110f6ec495dc88dde670cfe4
branch: main
author: Ken Jin 
committer: Fidget-Spinner 
date: 2025-03-18T00:36:06+08:00
summary:

gh-131281: Add include for pystats builds (#131369)

Add include to for pystats builds

files:
M Python/specialize.c

diff --git a/Python/specialize.c b/Python/specialize.c
index 07c49140446c12..4aa2fb9f7359f9 100644
--- a/Python/specialize.c
+++ b/Python/specialize.c
@@ -18,6 +18,7 @@
 #include "pycore_opcode_utils.h"  // RESUME_AT_FUNC_START
 #include "pycore_pylifecycle.h"   // _PyOS_URandomNonblock()
 #include "pycore_runtime.h"   // _Py_ID()
+#include "pycore_unicodeobject.h" // _PyUnicodeASCIIIter_Type
 
 #include  // rand()
 

___
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com


[Python-checkins] gh-132257: Remove -flto-partition=none for Linux LTO builds (GH-132258)

2025-04-11 Thread Fidget-Spinner
https://github.com/python/cpython/commit/bc0b94b30c9d65ba550daee2c2ef20035defd980
commit: bc0b94b30c9d65ba550daee2c2ef20035defd980
branch: main
author: Ken Jin 
committer: Fidget-Spinner 
date: 2025-04-11T16:06:05+08:00
summary:

gh-132257: Remove -flto-partition=none for Linux LTO builds (GH-132258)

Change the default LTO flags on GCC to not pass -flto-partition=none, and allow 
parallelization of LTO. This has a multiple factor speedup for LTO build times 
on GCC, with no noticeable loss in performance.

On newer make and newer GCC, this passes the jobserver automatically to GCC (or 
more like GCC grabs it from the env vars).

On older make, this will have benign warnings about serial compilation. It's 
safe to ignore them.

files:
A Misc/NEWS.d/next/Build/2025-04-08-09-11-32.gh-issue-132257.oZWBV-.rst
M configure
M configure.ac

diff --git 
a/Misc/NEWS.d/next/Build/2025-04-08-09-11-32.gh-issue-132257.oZWBV-.rst 
b/Misc/NEWS.d/next/Build/2025-04-08-09-11-32.gh-issue-132257.oZWBV-.rst
new file mode 100644
index 00..5bf20d2f1d0d22
--- /dev/null
+++ b/Misc/NEWS.d/next/Build/2025-04-08-09-11-32.gh-issue-132257.oZWBV-.rst
@@ -0,0 +1 @@
+Change the default LTO flags on GCC to not pass ``-flto-partition=none``, and 
allow parallelization of LTO. For newer GNU makes and GCC, this has a multiple 
factor speedup for LTO build times, with no noticeable loss in performance.
diff --git a/configure b/configure
index 24a7d1d43f0467..decb8f2449d162 100755
--- a/configure
+++ b/configure
@@ -8894,7 +8894,7 @@ fi
   LTOCFLAGS="-flto"
   ;;
 *)
-  LTOFLAGS="-flto -fuse-linker-plugin -ffat-lto-objects 
-flto-partition=none"
+  LTOFLAGS="-flto -fuse-linker-plugin -ffat-lto-objects"
   ;;
   esac
   ;;
diff --git a/configure.ac b/configure.ac
index bc6479c048f745..004797b5233c20 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2031,7 +2031,7 @@ if test "$Py_LTO" = 'true' ; then
   LTOCFLAGS="-flto"
   ;;
 *)
-  LTOFLAGS="-flto -fuse-linker-plugin -ffat-lto-objects 
-flto-partition=none"
+  LTOFLAGS="-flto -fuse-linker-plugin -ffat-lto-objects"
   ;;
   esac
   ;;

___
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com


[Python-checkins] gh-132386: Fix a crash when passing a dict subclass to `exec` (GH-132412)

2025-04-11 Thread Fidget-Spinner
https://github.com/python/cpython/commit/e6ef47ac229b5c4a62b9c907e4232e350db77ce3
commit: e6ef47ac229b5c4a62b9c907e4232e350db77ce3
branch: main
author: Tomas R. 
committer: Fidget-Spinner 
date: 2025-04-12T05:05:03+08:00
summary:

gh-132386: Fix a crash when passing a dict subclass to `exec` (GH-132412)

* Fix crash when passing a dict subclass to exec

* Add news entry

files:
A 
Misc/NEWS.d/next/Core_and_Builtins/2025-04-11-18-46-37.gh-issue-132386.pMBFTe.rst
M Lib/test/test_compile.py
M Python/ceval.c

diff --git a/Lib/test/test_compile.py b/Lib/test/test_compile.py
index ce9c060641d6c5..9cc025d85e168a 100644
--- a/Lib/test/test_compile.py
+++ b/Lib/test/test_compile.py
@@ -1636,6 +1636,16 @@ async def name_4():
 pass
 [[]]
 
+def test_globals_dict_subclass(self):
+# gh-132386
+class WeirdDict(dict):
+pass
+
+ns = {}
+exec('def foo(): return a', WeirdDict(), ns)
+
+self.assertRaises(NameError, ns['foo'])
+
 class TestBooleanExpression(unittest.TestCase):
 class Value:
 def __init__(self):
diff --git 
a/Misc/NEWS.d/next/Core_and_Builtins/2025-04-11-18-46-37.gh-issue-132386.pMBFTe.rst
 
b/Misc/NEWS.d/next/Core_and_Builtins/2025-04-11-18-46-37.gh-issue-132386.pMBFTe.rst
new file mode 100644
index 00..65ba7fc182b674
--- /dev/null
+++ 
b/Misc/NEWS.d/next/Core_and_Builtins/2025-04-11-18-46-37.gh-issue-132386.pMBFTe.rst
@@ -0,0 +1,2 @@
+Fix crash when passing a dict subclass as the ``globals`` parameter to
+:func:`exec`.
diff --git a/Python/ceval.c b/Python/ceval.c
index 8ab0c6318c1c91..e4a63ad9287783 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -3312,6 +3312,8 @@ _PyEval_LoadGlobalStackRef(PyObject *globals, PyObject 
*builtins, PyObject *name
 _PyEval_FormatExcCheckArg(
 PyThreadState_GET(), PyExc_NameError,
 NAME_ERROR_MSG, name);
+*writeto = PyStackRef_NULL;
+return;
 }
 }
 *writeto = PyStackRef_FromPyObjectSteal(res);

___
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com


[Python-checkins] gh-131798: JIT - Use `sym_new_type` instead of `sym_new_not_null` for _BUILD_STRING, _BUILD_SET (GH-132564)

2025-04-27 Thread Fidget-Spinner
https://github.com/python/cpython/commit/614d79231d1e60d31b9452ea2afbc2a7d2f0034b
commit: 614d79231d1e60d31b9452ea2afbc2a7d2f0034b
branch: main
author: Nadeshiko Manju 
committer: Fidget-Spinner 
date: 2025-04-27T20:30:28+08:00
summary:

gh-131798: JIT - Use `sym_new_type` instead of `sym_new_not_null` for 
_BUILD_STRING, _BUILD_SET (GH-132564)

Signed-off-by: Manjusaka 

files:
A 
Misc/NEWS.d/next/Core_and_Builtins/2025-04-26-18-43-31.gh-issue-131798.FsIypo.rst
M Python/optimizer_bytecodes.c
M Python/optimizer_cases.c.h

diff --git 
a/Misc/NEWS.d/next/Core_and_Builtins/2025-04-26-18-43-31.gh-issue-131798.FsIypo.rst
 
b/Misc/NEWS.d/next/Core_and_Builtins/2025-04-26-18-43-31.gh-issue-131798.FsIypo.rst
new file mode 100644
index 00..a252d2b69fc020
--- /dev/null
+++ 
b/Misc/NEWS.d/next/Core_and_Builtins/2025-04-26-18-43-31.gh-issue-131798.FsIypo.rst
@@ -0,0 +1,2 @@
+Use ``sym_new_type`` instead of ``sym_new_not_null`` for _BUILD_STRING,
+_BUILD_SET
diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c
index f862c9c8c6a840..567caad22554ea 100644
--- a/Python/optimizer_bytecodes.c
+++ b/Python/optimizer_bytecodes.c
@@ -977,6 +977,14 @@ dummy_func(void) {
 map = sym_new_type(ctx, &PyDict_Type);
 }
 
+op(_BUILD_STRING, (values[oparg] -- str)) {
+str = sym_new_type(ctx, &PyUnicode_Type);
+}
+
+op(_BUILD_SET, (values[oparg] -- set)) {
+set = sym_new_type(ctx, &PySet_Type);
+}
+
 op(_UNPACK_SEQUENCE_TWO_TUPLE, (seq -- val1, val0)) {
 val0 = sym_tuple_getitem(ctx, seq, 0);
 val1 = sym_tuple_getitem(ctx, seq, 1);
diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h
index c92b036eb56463..679240b6efa315 100644
--- a/Python/optimizer_cases.c.h
+++ b/Python/optimizer_cases.c.h
@@ -1032,7 +1032,7 @@
 
 case _BUILD_STRING: {
 JitOptSymbol *str;
-str = sym_new_not_null(ctx);
+str = sym_new_type(ctx, &PyUnicode_Type);
 stack_pointer[-oparg] = str;
 stack_pointer += 1 - oparg;
 assert(WITHIN_STACK_BOUNDS());
@@ -1073,7 +1073,7 @@
 
 case _BUILD_SET: {
 JitOptSymbol *set;
-set = sym_new_not_null(ctx);
+set = sym_new_type(ctx, &PySet_Type);
 stack_pointer[-oparg] = set;
 stack_pointer += 1 - oparg;
 assert(WITHIN_STACK_BOUNDS());

___
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com


[Python-checkins] gh-132758: Fix tail call and pystats builds (GH-132759)

2025-04-23 Thread Fidget-Spinner
https://github.com/python/cpython/commit/6430c634da4332550744fe8f50b12c927b8382f6
commit: 6430c634da4332550744fe8f50b12c927b8382f6
branch: main
author: Ken Jin 
committer: Fidget-Spinner 
date: 2025-04-23T18:17:35+08:00
summary:

gh-132758: Fix tail call and pystats builds (GH-132759)

files:
A Misc/NEWS.d/next/Build/2025-04-20-20-07-44.gh-issue-132758.N2a3wp.rst
M Python/ceval.c
M Python/ceval_macros.h

diff --git 
a/Misc/NEWS.d/next/Build/2025-04-20-20-07-44.gh-issue-132758.N2a3wp.rst 
b/Misc/NEWS.d/next/Build/2025-04-20-20-07-44.gh-issue-132758.N2a3wp.rst
new file mode 100644
index 00..0645c35c18c133
--- /dev/null
+++ b/Misc/NEWS.d/next/Build/2025-04-20-20-07-44.gh-issue-132758.N2a3wp.rst
@@ -0,0 +1 @@
+Fix building with tail call interpreter and pystats.
diff --git a/Python/ceval.c b/Python/ceval.c
index 17e28439872ba2..fb72fd49811e2d 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -1071,7 +1071,11 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, 
_PyInterpreterFrame *frame, int
 monitor_throw(tstate, frame, next_instr);
 stack_pointer = _PyFrame_GetStackPointer(frame);
 #if Py_TAIL_CALL_INTERP
-return _TAIL_CALL_error(frame, stack_pointer, tstate, next_instr, 0);
+#   if Py_STATS
+return _TAIL_CALL_error(frame, stack_pointer, tstate, next_instr, 
0, lastopcode);
+#   else
+return _TAIL_CALL_error(frame, stack_pointer, tstate, next_instr, 
0);
+#   endif
 #else
 goto error;
 #endif
@@ -1083,7 +1087,11 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, 
_PyInterpreterFrame *frame, int
 const _PyUOpInstruction *next_uop = NULL;
 #endif
 #if Py_TAIL_CALL_INTERP
-return _TAIL_CALL_start_frame(frame, NULL, tstate, NULL, 0);
+#   if Py_STATS
+return _TAIL_CALL_start_frame(frame, NULL, tstate, NULL, 0, 
lastopcode);
+#   else
+return _TAIL_CALL_start_frame(frame, NULL, tstate, NULL, 0);
+#   endif
 #else
 goto start_frame;
 #   include "generated_cases.c.h"
diff --git a/Python/ceval_macros.h b/Python/ceval_macros.h
index 3dca4e46ee75e4..e1d2673848cc69 100644
--- a/Python/ceval_macros.h
+++ b/Python/ceval_macros.h
@@ -70,8 +70,13 @@
 #define INSTRUCTION_STATS(op) ((void)0)
 #endif
 
-#define TAIL_CALL_PARAMS _PyInterpreterFrame *frame, _PyStackRef 
*stack_pointer, PyThreadState *tstate, _Py_CODEUNIT *next_instr, int oparg
-#define TAIL_CALL_ARGS frame, stack_pointer, tstate, next_instr, oparg
+#ifdef Py_STATS
+#   define TAIL_CALL_PARAMS _PyInterpreterFrame *frame, _PyStackRef 
*stack_pointer, PyThreadState *tstate, _Py_CODEUNIT *next_instr, int oparg, int 
lastopcode
+#   define TAIL_CALL_ARGS frame, stack_pointer, tstate, next_instr, oparg, 
lastopcode
+#else
+#   define TAIL_CALL_PARAMS _PyInterpreterFrame *frame, _PyStackRef 
*stack_pointer, PyThreadState *tstate, _Py_CODEUNIT *next_instr, int oparg
+#   define TAIL_CALL_ARGS frame, stack_pointer, tstate, next_instr, oparg
+#endif
 
 #if Py_TAIL_CALL_INTERP
 // Note: [[clang::musttail]] works for GCC 15, but not 
__attribute__((musttail)) at the moment.
@@ -88,10 +93,17 @@
 do { \
 Py_MUSTTAIL return (_TAIL_CALL_##name)(TAIL_CALL_ARGS); \
 } while (0)
-#   define JUMP_TO_PREDICTED(name) \
-do { \
-Py_MUSTTAIL return (_TAIL_CALL_##name)(frame, stack_pointer, 
tstate, this_instr, oparg); \
-} while (0)
+#   ifdef Py_STATS
+#   define JUMP_TO_PREDICTED(name) \
+do { \
+Py_MUSTTAIL return (_TAIL_CALL_##name)(frame, stack_pointer, 
tstate, this_instr, oparg, lastopcode); \
+} while (0)
+#   else
+#   define JUMP_TO_PREDICTED(name) \
+do { \
+Py_MUSTTAIL return (_TAIL_CALL_##name)(frame, stack_pointer, 
tstate, this_instr, oparg); \
+} while (0)
+#   endif
 #define LABEL(name) TARGET(name)
 #elif USE_COMPUTED_GOTOS
 #  define TARGET(op) TARGET_##op:

___
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com


[Python-checkins] gh-131798: Use `sym_new_type` instead of `sym_new_not_null` for `_BUILD_LIST`, `_BUILD_SLICE`, and `_BUILD_MAP` (GH-132434)

2025-04-16 Thread Fidget-Spinner
https://github.com/python/cpython/commit/b9e88ff4cbf6481578421d58acf2455647cefeb4
commit: b9e88ff4cbf6481578421d58acf2455647cefeb4
branch: main
author: Nadeshiko Manju 
committer: Fidget-Spinner 
date: 2025-04-17T01:17:48+08:00
summary:

gh-131798: Use `sym_new_type` instead of `sym_new_not_null` for `_BUILD_LIST`, 
`_BUILD_SLICE`, and `_BUILD_MAP` (GH-132434)

-

Signed-off-by: Manjusaka 

files:
A 
Misc/NEWS.d/next/Core_and_Builtins/2025-04-12-19-41-16.gh-issue-131798.JkSocg.rst
M Lib/test/test_capi/test_opt.py
M Python/optimizer_bytecodes.c
M Python/optimizer_cases.c.h

diff --git a/Lib/test/test_capi/test_opt.py b/Lib/test/test_capi/test_opt.py
index c0e771a0d59c4f..34b7c5982245c7 100644
--- a/Lib/test/test_capi/test_opt.py
+++ b/Lib/test/test_capi/test_opt.py
@@ -1678,7 +1678,7 @@ def f(n):
 x = 0
 for _ in range(n):
 d = {}
-d["Spam"] = 1  # Guarded...
+d["Spam"] = 1  # unguarded!
 x += d["Spam"]  # ...unguarded!
 return x
 
@@ -1686,7 +1686,7 @@ def f(n):
 self.assertEqual(res, TIER2_THRESHOLD)
 self.assertIsNotNone(ex)
 uops = get_opnames(ex)
-self.assertEqual(uops.count("_GUARD_NOS_DICT"), 1)
+self.assertEqual(uops.count("_GUARD_NOS_DICT"), 0)
 self.assertEqual(uops.count("_STORE_SUBSCR_DICT"), 1)
 self.assertEqual(uops.count("_BINARY_OP_SUBSCR_DICT"), 1)
 
@@ -1695,7 +1695,7 @@ def f(n):
 x = 0
 for _ in range(n):
 l = [0]
-l[0] = 1  # Guarded...
+l[0] = 1  # unguarded!
 [a] = l  # ...unguarded!
 b = l[0]  # ...unguarded!
 if l:  # ...unguarded!
@@ -1706,7 +1706,7 @@ def f(n):
 self.assertEqual(res, 2 * TIER2_THRESHOLD)
 self.assertIsNotNone(ex)
 uops = get_opnames(ex)
-self.assertEqual(uops.count("_GUARD_NOS_LIST"), 1)
+self.assertEqual(uops.count("_GUARD_NOS_LIST"), 0)
 self.assertEqual(uops.count("_STORE_SUBSCR_LIST_INT"), 1)
 self.assertEqual(uops.count("_GUARD_TOS_LIST"), 0)
 self.assertEqual(uops.count("_UNPACK_SEQUENCE_LIST"), 1)
diff --git 
a/Misc/NEWS.d/next/Core_and_Builtins/2025-04-12-19-41-16.gh-issue-131798.JkSocg.rst
 
b/Misc/NEWS.d/next/Core_and_Builtins/2025-04-12-19-41-16.gh-issue-131798.JkSocg.rst
new file mode 100644
index 00..5a9c0cde35fffb
--- /dev/null
+++ 
b/Misc/NEWS.d/next/Core_and_Builtins/2025-04-12-19-41-16.gh-issue-131798.JkSocg.rst
@@ -0,0 +1,2 @@
+Use ``sym_new_type`` instead of ``sym_new_not_null`` for _BUILD_LIST,
+_BUILD_SET, _BUILD_MAP
diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c
index 8e1eacfec83e95..43fe2107bf998a 100644
--- a/Python/optimizer_bytecodes.c
+++ b/Python/optimizer_bytecodes.c
@@ -919,6 +919,18 @@ dummy_func(void) {
 tup = sym_new_tuple(ctx, oparg, values);
 }
 
+op(_BUILD_LIST, (values[oparg] -- list)) {
+list = sym_new_type(ctx, &PyList_Type);
+}
+
+op(_BUILD_SLICE, (values[oparg] -- slice)) {
+slice = sym_new_type(ctx, &PySlice_Type);
+}
+
+op(_BUILD_MAP, (values[oparg*2] -- map)) {
+map = sym_new_type(ctx, &PyDict_Type);
+}
+
 op(_UNPACK_SEQUENCE_TWO_TUPLE, (seq -- val1, val0)) {
 val0 = sym_tuple_getitem(ctx, seq, 0);
 val1 = sym_tuple_getitem(ctx, seq, 1);
diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h
index 6a20cef906242b..f51b00d25fe506 100644
--- a/Python/optimizer_cases.c.h
+++ b/Python/optimizer_cases.c.h
@@ -1031,7 +1031,7 @@
 
 case _BUILD_LIST: {
 JitOptSymbol *list;
-list = sym_new_not_null(ctx);
+list = sym_new_type(ctx, &PyList_Type);
 stack_pointer[-oparg] = list;
 stack_pointer += 1 - oparg;
 assert(WITHIN_STACK_BOUNDS());
@@ -1061,7 +1061,7 @@
 
 case _BUILD_MAP: {
 JitOptSymbol *map;
-map = sym_new_not_null(ctx);
+map = sym_new_type(ctx, &PyDict_Type);
 stack_pointer[-oparg*2] = map;
 stack_pointer += 1 - oparg*2;
 assert(WITHIN_STACK_BOUNDS());
@@ -2092,7 +2092,7 @@
 
 case _BUILD_SLICE: {
 JitOptSymbol *slice;
-slice = sym_new_not_null(ctx);
+slice = sym_new_type(ctx, &PySlice_Type);
 stack_pointer[-oparg] = slice;
 stack_pointer += 1 - oparg;
 assert(WITHIN_STACK_BOUNDS());

___
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com


[Python-checkins] gh-131798: JIT: Narrow the return type of _CALL_LEN to int (#132940)

2025-04-25 Thread Fidget-Spinner
https://github.com/python/cpython/commit/4c20f46fa011df57190cc19b21bafde1f65e73a7
commit: 4c20f46fa011df57190cc19b21bafde1f65e73a7
branch: main
author: Diego Russo 
committer: Fidget-Spinner 
date: 2025-04-26T02:57:42+08:00
summary:

gh-131798: JIT: Narrow the return type of _CALL_LEN to int (#132940)

Reduce unnecessary guards whenever `len()` is called and used
after.

Co-authored-by: Max Bernstein 

files:
A 
Misc/NEWS.d/next/Core_and_Builtins/2025-04-25-14-56-45.gh-issue-131798.NpcKub.rst
M Lib/test/test_capi/test_opt.py
M Python/optimizer_bytecodes.c
M Python/optimizer_cases.c.h

diff --git a/Lib/test/test_capi/test_opt.py b/Lib/test/test_capi/test_opt.py
index 0fb2d78a87ecf1..0047306ae422db 100644
--- a/Lib/test/test_capi/test_opt.py
+++ b/Lib/test/test_capi/test_opt.py
@@ -1911,6 +1911,18 @@ def testfunc(n):
 self.assertNotIn("_COMPARE_OP_INT", uops)
 self.assertNotIn("_GUARD_IS_TRUE_POP", uops)
 
+def test_call_len(self):
+def testfunc(n):
+a = [1, 2, 3, 4]
+for _ in range(n):
+_ = len(a) - 1
+
+_, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD)
+uops = get_opnames(ex)
+self.assertNotIn("_GUARD_NOS_INT", uops)
+self.assertNotIn("_GUARD_TOS_INT", uops)
+self.assertIn("_CALL_LEN", uops)
+
 
 def global_identity(x):
 return x
diff --git 
a/Misc/NEWS.d/next/Core_and_Builtins/2025-04-25-14-56-45.gh-issue-131798.NpcKub.rst
 
b/Misc/NEWS.d/next/Core_and_Builtins/2025-04-25-14-56-45.gh-issue-131798.NpcKub.rst
new file mode 100644
index 00..8214870284ed93
--- /dev/null
+++ 
b/Misc/NEWS.d/next/Core_and_Builtins/2025-04-25-14-56-45.gh-issue-131798.NpcKub.rst
@@ -0,0 +1 @@
+Allow the JIT to remove int guards after ``_CALL_LEN`` by setting the return 
type to int. Patch by Diego Russo
diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c
index ff2830d3003c61..040e54479b722a 100644
--- a/Python/optimizer_bytecodes.c
+++ b/Python/optimizer_bytecodes.c
@@ -1055,6 +1055,10 @@ dummy_func(void) {
 sym_set_const(callable, (PyObject *)&PyUnicode_Type);
 }
 
+op(_CALL_LEN, (callable[1], self_or_null[1], args[oparg] -- res)) {
+res = sym_new_type(ctx, &PyLong_Type);
+}
+
 // END BYTECODES //
 
 }
diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h
index 303e402b759530..9a5a362ec199a9 100644
--- a/Python/optimizer_cases.c.h
+++ b/Python/optimizer_cases.c.h
@@ -2014,7 +2014,7 @@
 
 case _CALL_LEN: {
 JitOptSymbol *res;
-res = sym_new_not_null(ctx);
+res = sym_new_type(ctx, &PyLong_Type);
 stack_pointer[-2 - oparg] = res;
 stack_pointer += -1 - oparg;
 assert(WITHIN_STACK_BOUNDS());

___
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com


[Python-checkins] update comment about LLVM bug relevant for `--with-tail-call-interp` performance (#132297)

2025-04-10 Thread Fidget-Spinner
https://github.com/python/cpython/commit/67ded6a4faae29edff8e4f7886978e71ce116e33
commit: 67ded6a4faae29edff8e4f7886978e71ce116e33
branch: main
author: h-vetinari 
committer: Fidget-Spinner 
date: 2025-04-09T22:50:38+08:00
summary:

update comment about LLVM bug relevant for `--with-tail-call-interp` 
performance (#132297)

files:
M Doc/whatsnew/3.14.rst

diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst
index 5f84d8ba8b02c2..0f15a2a8a8f6af 100644
--- a/Doc/whatsnew/3.14.rst
+++ b/Doc/whatsnew/3.14.rst
@@ -390,8 +390,9 @@ For further information on how to build Python, see
 `compiler bug <https://github.com/llvm/llvm-project/issues/106846>`_ found 
in
 Clang/LLVM 19, which causes the normal interpreter to be slower. We were 
unaware of this bug,
 resulting in inaccurate results. We sincerely apologize for
-communicating results that were only accurate for certain versions of LLVM 
19
-and 20. At the time of writing, this bug has not yet been fixed in LLVM 
19-21. Thus
+communicating results that were only accurate for LLVM v19.1.x and 
v20.1.0. In the meantime,
+the bug has been fixed in LLVM v20.1.1 and for the upcoming v21.1, but it 
will remain
+unfixed for LLVM v19.1.x and v20.1.0. Thus
 any benchmarks with those versions of LLVM may produce inaccurate numbers.
 (Thanks to Nelson Elhage for bringing this to light.)
 

___
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com


[Python-checkins] gh-131798: JIT: Propagate the result in `_BINARY_OP_SUBSCR_TUPLE_INT` (GH-133003)

2025-04-26 Thread Fidget-Spinner
https://github.com/python/cpython/commit/5e96e4fca80a8cd25da6b469b25f8f5a514de8be
commit: 5e96e4fca80a8cd25da6b469b25f8f5a514de8be
branch: main
author: Tomas R. 
committer: Fidget-Spinner 
date: 2025-04-27T02:47:55+08:00
summary:

gh-131798: JIT: Propagate the result in `_BINARY_OP_SUBSCR_TUPLE_INT` 
(GH-133003)

files:
A 
Misc/NEWS.d/next/Core_and_Builtins/2025-04-26-13-57-13.gh-issue-131798.Gt8CGE.rst
M Lib/test/test_capi/test_opt.py
M Python/optimizer_bytecodes.c
M Python/optimizer_cases.c.h

diff --git a/Lib/test/test_capi/test_opt.py b/Lib/test/test_capi/test_opt.py
index 0047306ae422db..7e0c60d5522402 100644
--- a/Lib/test/test_capi/test_opt.py
+++ b/Lib/test/test_capi/test_opt.py
@@ -1923,6 +1923,23 @@ def testfunc(n):
 self.assertNotIn("_GUARD_TOS_INT", uops)
 self.assertIn("_CALL_LEN", uops)
 
+def test_binary_op_subscr_tuple_int(self):
+def testfunc(n):
+x = 0
+for _ in range(n):
+y = (1, 2)
+if y[0] == 1:  # _COMPARE_OP_INT + _GUARD_IS_TRUE_POP are 
removed
+x += 1
+return x
+
+res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD)
+self.assertEqual(res, TIER2_THRESHOLD)
+self.assertIsNotNone(ex)
+uops = get_opnames(ex)
+self.assertIn("_BINARY_OP_SUBSCR_TUPLE_INT", uops)
+self.assertNotIn("_COMPARE_OP_INT", uops)
+self.assertNotIn("_GUARD_IS_TRUE_POP", uops)
+
 
 def global_identity(x):
 return x
diff --git 
a/Misc/NEWS.d/next/Core_and_Builtins/2025-04-26-13-57-13.gh-issue-131798.Gt8CGE.rst
 
b/Misc/NEWS.d/next/Core_and_Builtins/2025-04-26-13-57-13.gh-issue-131798.Gt8CGE.rst
new file mode 100644
index 00..f4049240f7d15c
--- /dev/null
+++ 
b/Misc/NEWS.d/next/Core_and_Builtins/2025-04-26-13-57-13.gh-issue-131798.Gt8CGE.rst
@@ -0,0 +1,2 @@
+Propagate the return type of ``_BINARY_OP_SUBSCR_TUPLE_INT`` in JIT. Patch
+by Tomas Roun
diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c
index 040e54479b722a..f862c9c8c6a840 100644
--- a/Python/optimizer_bytecodes.c
+++ b/Python/optimizer_bytecodes.c
@@ -370,6 +370,27 @@ dummy_func(void) {
 res = sym_new_type(ctx, &PyUnicode_Type);
 }
 
+op(_BINARY_OP_SUBSCR_TUPLE_INT, (tuple_st, sub_st -- res)) {
+assert(sym_matches_type(tuple_st, &PyTuple_Type));
+if (sym_is_const(ctx, sub_st)) {
+assert(PyLong_CheckExact(sym_get_const(ctx, sub_st)));
+long index = PyLong_AsLong(sym_get_const(ctx, sub_st));
+assert(index >= 0);
+int tuple_length = sym_tuple_length(tuple_st);
+if (tuple_length == -1) {
+// Unknown length
+res = sym_new_not_null(ctx);
+}
+else {
+assert(index < tuple_length);
+res = sym_tuple_getitem(ctx, tuple_st, index);
+}
+}
+else {
+res = sym_new_not_null(ctx);
+}
+}
+
 op(_TO_BOOL, (value -- res)) {
 int already_bool = optimize_to_bool(this_instr, ctx, value, &res);
 if (!already_bool) {
diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h
index 9a5a362ec199a9..c92b036eb56463 100644
--- a/Python/optimizer_cases.c.h
+++ b/Python/optimizer_cases.c.h
@@ -617,8 +617,28 @@
 }
 
 case _BINARY_OP_SUBSCR_TUPLE_INT: {
+JitOptSymbol *sub_st;
+JitOptSymbol *tuple_st;
 JitOptSymbol *res;
-res = sym_new_not_null(ctx);
+sub_st = stack_pointer[-1];
+tuple_st = stack_pointer[-2];
+assert(sym_matches_type(tuple_st, &PyTuple_Type));
+if (sym_is_const(ctx, sub_st)) {
+assert(PyLong_CheckExact(sym_get_const(ctx, sub_st)));
+long index = PyLong_AsLong(sym_get_const(ctx, sub_st));
+assert(index >= 0);
+int tuple_length = sym_tuple_length(tuple_st);
+if (tuple_length == -1) {
+res = sym_new_not_null(ctx);
+}
+else {
+assert(index < tuple_length);
+res = sym_tuple_getitem(ctx, tuple_st, index);
+}
+}
+else {
+res = sym_new_not_null(ctx);
+}
 stack_pointer[-2] = res;
 stack_pointer += -1;
 assert(WITHIN_STACK_BOUNDS());

___
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com


[Python-checkins] gh-129989: Change Py_TAIL_CALL_INTERP ifndef to ! (#130269)

2025-02-18 Thread Fidget-Spinner
https://github.com/python/cpython/commit/46ac85e4d9fcffe1a8f921989414a89648b5501a
commit: 46ac85e4d9fcffe1a8f921989414a89648b5501a
branch: main
author: Ken Jin 
committer: Fidget-Spinner 
date: 2025-02-18T15:48:49Z
summary:

gh-129989: Change Py_TAIL_CALL_INTERP ifndef to ! (#130269)

Change Py_TAIL_CALL_INTERP ifndef to !

files:
M Python/bytecodes.c
M Python/ceval.c
M Python/generated_cases.c.h
M Tools/cases_generator/tier1_generator.py

diff --git a/Python/bytecodes.c b/Python/bytecodes.c
index 3f8f711c55956f..1c5fdf847b62c2 100644
--- a/Python/bytecodes.c
+++ b/Python/bytecodes.c
@@ -1358,7 +1358,7 @@ dummy_func(
 
 tier1 inst(CLEANUP_THROW, (sub_iter, last_sent_val, exc_value_st -- 
none, value)) {
 PyObject *exc_value = PyStackRef_AsPyObjectBorrow(exc_value_st);
-#ifndef Py_TAIL_CALL_INTERP
+#if !Py_TAIL_CALL_INTERP
 assert(throwflag);
 #endif
 assert(exc_value && PyExceptionInstance_Check(exc_value));
diff --git a/Python/ceval.c b/Python/ceval.c
index 28b26ffb5de43d..cf9a8713ed9803 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -798,7 +798,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, 
_PyInterpreterFrame *frame, int
 #ifdef Py_STATS
 int lastopcode = 0;
 #endif
-#ifndef Py_TAIL_CALL_INTERP
+#if !Py_TAIL_CALL_INTERP
 uint8_t opcode;/* Current opcode */
 int oparg; /* Current opcode argument, if any */
 assert(tstate->current_frame == NULL || 
tstate->current_frame->stackpointer != NULL);
diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h
index e7f8fdce41b58a..01fa857b96ac3b 100644
--- a/Python/generated_cases.c.h
+++ b/Python/generated_cases.c.h
@@ -8,7 +8,7 @@
 #endif
 #define TIER_ONE 1
 
-#ifndef Py_TAIL_CALL_INTERP
+#if !Py_TAIL_CALL_INTERP
 #if !USE_COMPUTED_GOTOS
 dispatch_opcode:
 switch (opcode)
@@ -4409,7 +4409,7 @@
 last_sent_val = stack_pointer[-2];
 sub_iter = stack_pointer[-3];
 PyObject *exc_value = PyStackRef_AsPyObjectBorrow(exc_value_st);
-#ifndef Py_TAIL_CALL_INTERP
+#if !Py_TAIL_CALL_INTERP
 assert(throwflag);
 #endif
 assert(exc_value && PyExceptionInstance_Check(exc_value));
@@ -11929,7 +11929,7 @@
 }
 
 /* END INSTRUCTIONS */
-#ifndef Py_TAIL_CALL_INTERP
+#if !Py_TAIL_CALL_INTERP
 #if USE_COMPUTED_GOTOS
 _unknown_opcode:
 #else
diff --git a/Tools/cases_generator/tier1_generator.py 
b/Tools/cases_generator/tier1_generator.py
index dd9faa3587e32b..83ac8b92ee 100644
--- a/Tools/cases_generator/tier1_generator.py
+++ b/Tools/cases_generator/tier1_generator.py
@@ -160,7 +160,7 @@ def generate_tier1(
 #define TIER_ONE 1
 """)
 outfile.write(f"""
-#ifndef Py_TAIL_CALL_INTERP
+#if !Py_TAIL_CALL_INTERP
 #if !USE_COMPUTED_GOTOS
 dispatch_opcode:
 switch (opcode)
@@ -173,7 +173,7 @@ def generate_tier1(
 generate_tier1_cases(analysis, outfile, lines)
 outfile.write(f"""
 {INSTRUCTION_END_MARKER}
-#ifndef Py_TAIL_CALL_INTERP
+#if !Py_TAIL_CALL_INTERP
 #if USE_COMPUTED_GOTOS
 _unknown_opcode:
 #else

___
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com


  1   2   >