summaryrefslogtreecommitdiffstats
path: root/Include
diff options
context:
space:
mode:
authorMark Shannon <mark@hotpy.org>2024-02-02 12:14:34 (GMT)
committerGitHub <noreply@github.com>2024-02-02 12:14:34 (GMT)
commit0e71a295e9530c939a5efcb45db23cf31e0303b4 (patch)
treeba3a22d5bece296073aa250a04bc3f4192607281 /Include
parent2091fb2a85c1aa2d9b22c02736b07831bd875c2a (diff)
downloadcpython-0e71a295e9530c939a5efcb45db23cf31e0303b4.zip
cpython-0e71a295e9530c939a5efcb45db23cf31e0303b4.tar.gz
cpython-0e71a295e9530c939a5efcb45db23cf31e0303b4.tar.bz2
GH-113710: Add a "globals to constants" pass (GH-114592)
Converts specializations of `LOAD_GLOBAL` into constants during tier 2 optimization.
Diffstat (limited to 'Include')
-rw-r--r--Include/cpython/dictobject.h3
-rw-r--r--Include/cpython/optimizer.h8
-rw-r--r--Include/internal/pycore_dict.h6
-rw-r--r--Include/internal/pycore_dict_state.h1
-rw-r--r--Include/internal/pycore_interp.h2
-rw-r--r--Include/internal/pycore_optimizer.h5
-rw-r--r--Include/internal/pycore_uop_ids.h8
-rw-r--r--Include/internal/pycore_uop_metadata.h8
8 files changed, 32 insertions, 9 deletions
diff --git a/Include/cpython/dictobject.h b/Include/cpython/dictobject.h
index 944965f..1720fe6 100644
--- a/Include/cpython/dictobject.h
+++ b/Include/cpython/dictobject.h
@@ -17,6 +17,9 @@ typedef struct {
/* Dictionary version: globally unique, value change each time
the dictionary is modified */
#ifdef Py_BUILD_CORE
+ /* Bits 0-7 are for dict watchers.
+ * Bits 8-11 are for the watched mutation counter (used by tier2 optimization)
+ * The remaining bits (12-63) are the actual version tag. */
uint64_t ma_version_tag;
#else
Py_DEPRECATED(3.12) uint64_t ma_version_tag;
diff --git a/Include/cpython/optimizer.h b/Include/cpython/optimizer.h
index ecf3cae..5a9ccae 100644
--- a/Include/cpython/optimizer.h
+++ b/Include/cpython/optimizer.h
@@ -47,7 +47,10 @@ typedef struct _PyExecutorObject {
typedef struct _PyOptimizerObject _PyOptimizerObject;
/* Should return > 0 if a new executor is created. O if no executor is produced and < 0 if an error occurred. */
-typedef int (*optimize_func)(_PyOptimizerObject* self, PyCodeObject *code, _Py_CODEUNIT *instr, _PyExecutorObject **, int curr_stackentries);
+typedef int (*optimize_func)(
+ _PyOptimizerObject* self, struct _PyInterpreterFrame *frame,
+ _Py_CODEUNIT *instr, _PyExecutorObject **exec_ptr,
+ int curr_stackentries);
typedef struct _PyOptimizerObject {
PyObject_HEAD
@@ -94,6 +97,9 @@ PyAPI_FUNC(PyObject *)PyUnstable_Optimizer_NewUOpOptimizer(void);
/* Minimum of 16 additional executions before retry */
#define MINIMUM_TIER2_BACKOFF 4
+#define _Py_MAX_ALLOWED_BUILTINS_MODIFICATIONS 3
+#define _Py_MAX_ALLOWED_GLOBALS_MODIFICATIONS 6
+
#ifdef __cplusplus
}
#endif
diff --git a/Include/internal/pycore_dict.h b/Include/internal/pycore_dict.h
index 60acd89..233da05 100644
--- a/Include/internal/pycore_dict.h
+++ b/Include/internal/pycore_dict.h
@@ -207,8 +207,8 @@ static inline PyDictUnicodeEntry* DK_UNICODE_ENTRIES(PyDictKeysObject *dk) {
#define DK_IS_UNICODE(dk) ((dk)->dk_kind != DICT_KEYS_GENERAL)
-#define DICT_VERSION_INCREMENT (1 << DICT_MAX_WATCHERS)
-#define DICT_VERSION_MASK (DICT_VERSION_INCREMENT - 1)
+#define DICT_VERSION_INCREMENT (1 << (DICT_MAX_WATCHERS + DICT_WATCHED_MUTATION_BITS))
+#define DICT_WATCHER_MASK ((1 << DICT_MAX_WATCHERS) - 1)
#ifdef Py_GIL_DISABLED
#define DICT_NEXT_VERSION(INTERP) \
@@ -234,7 +234,7 @@ _PyDict_NotifyEvent(PyInterpreterState *interp,
PyObject *value)
{
assert(Py_REFCNT((PyObject*)mp) > 0);
- int watcher_bits = mp->ma_version_tag & DICT_VERSION_MASK;
+ int watcher_bits = mp->ma_version_tag & DICT_WATCHER_MASK;
if (watcher_bits) {
_PyDict_SendEvent(watcher_bits, event, mp, key, value);
return DICT_NEXT_VERSION(interp) | watcher_bits;
diff --git a/Include/internal/pycore_dict_state.h b/Include/internal/pycore_dict_state.h
index a6dd63d..1a44755 100644
--- a/Include/internal/pycore_dict_state.h
+++ b/Include/internal/pycore_dict_state.h
@@ -9,6 +9,7 @@ extern "C" {
#endif
#define DICT_MAX_WATCHERS 8
+#define DICT_WATCHED_MUTATION_BITS 4
struct _Py_dict_state {
/*Global counter used to set ma_version_tag field of dictionary.
diff --git a/Include/internal/pycore_interp.h b/Include/internal/pycore_interp.h
index c4732b1..f7c332e 100644
--- a/Include/internal/pycore_interp.h
+++ b/Include/internal/pycore_interp.h
@@ -72,7 +72,6 @@ typedef struct _rare_events {
uint8_t set_eval_frame_func;
/* Modifying the builtins, __builtins__.__dict__[var] = ... */
uint8_t builtin_dict;
- int builtins_dict_watcher_id;
/* Modifying a function, e.g. func.__defaults__ = ..., etc. */
uint8_t func_modification;
} _rare_events;
@@ -243,6 +242,7 @@ struct _is {
uint16_t optimizer_backedge_threshold;
uint32_t next_func_version;
_rare_events rare_events;
+ PyDict_WatchCallback builtins_dict_watcher;
_Py_GlobalMonitors monitors;
bool sys_profile_initialized;
diff --git a/Include/internal/pycore_optimizer.h b/Include/internal/pycore_optimizer.h
index 31f30c6..e21412f 100644
--- a/Include/internal/pycore_optimizer.h
+++ b/Include/internal/pycore_optimizer.h
@@ -8,8 +8,9 @@ extern "C" {
# error "this header requires Py_BUILD_CORE define"
#endif
-int _Py_uop_analyze_and_optimize(PyCodeObject *code,
- _PyUOpInstruction *trace, int trace_len, int curr_stackentries);
+int _Py_uop_analyze_and_optimize(_PyInterpreterFrame *frame,
+ _PyUOpInstruction *trace, int trace_len, int curr_stackentries,
+ _PyBloomFilter *dependencies);
extern PyTypeObject _PyCounterExecutor_Type;
extern PyTypeObject _PyCounterOptimizer_Type;
diff --git a/Include/internal/pycore_uop_ids.h b/Include/internal/pycore_uop_ids.h
index a705658..b2476e1 100644
--- a/Include/internal/pycore_uop_ids.h
+++ b/Include/internal/pycore_uop_ids.h
@@ -232,8 +232,12 @@ extern "C" {
#define _CHECK_VALIDITY 379
#define _LOAD_CONST_INLINE 380
#define _LOAD_CONST_INLINE_BORROW 381
-#define _INTERNAL_INCREMENT_OPT_COUNTER 382
-#define MAX_UOP_ID 382
+#define _LOAD_CONST_INLINE_WITH_NULL 382
+#define _LOAD_CONST_INLINE_BORROW_WITH_NULL 383
+#define _CHECK_GLOBALS 384
+#define _CHECK_BUILTINS 385
+#define _INTERNAL_INCREMENT_OPT_COUNTER 386
+#define MAX_UOP_ID 386
#ifdef __cplusplus
}
diff --git a/Include/internal/pycore_uop_metadata.h b/Include/internal/pycore_uop_metadata.h
index 14d3382..2b5b37e 100644
--- a/Include/internal/pycore_uop_metadata.h
+++ b/Include/internal/pycore_uop_metadata.h
@@ -204,6 +204,10 @@ const uint16_t _PyUop_Flags[MAX_UOP_ID+1] = {
[_CHECK_VALIDITY] = HAS_DEOPT_FLAG,
[_LOAD_CONST_INLINE] = 0,
[_LOAD_CONST_INLINE_BORROW] = 0,
+ [_LOAD_CONST_INLINE_WITH_NULL] = 0,
+ [_LOAD_CONST_INLINE_BORROW_WITH_NULL] = 0,
+ [_CHECK_GLOBALS] = HAS_DEOPT_FLAG,
+ [_CHECK_BUILTINS] = HAS_DEOPT_FLAG,
[_INTERNAL_INCREMENT_OPT_COUNTER] = 0,
};
@@ -250,10 +254,12 @@ const char *const _PyOpcode_uop_name[MAX_UOP_ID+1] = {
[_CHECK_ATTR_METHOD_LAZY_DICT] = "_CHECK_ATTR_METHOD_LAZY_DICT",
[_CHECK_ATTR_MODULE] = "_CHECK_ATTR_MODULE",
[_CHECK_ATTR_WITH_HINT] = "_CHECK_ATTR_WITH_HINT",
+ [_CHECK_BUILTINS] = "_CHECK_BUILTINS",
[_CHECK_CALL_BOUND_METHOD_EXACT_ARGS] = "_CHECK_CALL_BOUND_METHOD_EXACT_ARGS",
[_CHECK_EG_MATCH] = "_CHECK_EG_MATCH",
[_CHECK_EXC_MATCH] = "_CHECK_EXC_MATCH",
[_CHECK_FUNCTION_EXACT_ARGS] = "_CHECK_FUNCTION_EXACT_ARGS",
+ [_CHECK_GLOBALS] = "_CHECK_GLOBALS",
[_CHECK_MANAGED_OBJECT_HAS_VALUES] = "_CHECK_MANAGED_OBJECT_HAS_VALUES",
[_CHECK_PEP_523] = "_CHECK_PEP_523",
[_CHECK_STACK_SPACE] = "_CHECK_STACK_SPACE",
@@ -332,6 +338,8 @@ const char *const _PyOpcode_uop_name[MAX_UOP_ID+1] = {
[_LOAD_CONST] = "_LOAD_CONST",
[_LOAD_CONST_INLINE] = "_LOAD_CONST_INLINE",
[_LOAD_CONST_INLINE_BORROW] = "_LOAD_CONST_INLINE_BORROW",
+ [_LOAD_CONST_INLINE_BORROW_WITH_NULL] = "_LOAD_CONST_INLINE_BORROW_WITH_NULL",
+ [_LOAD_CONST_INLINE_WITH_NULL] = "_LOAD_CONST_INLINE_WITH_NULL",
[_LOAD_DEREF] = "_LOAD_DEREF",
[_LOAD_FAST] = "_LOAD_FAST",
[_LOAD_FAST_AND_CLEAR] = "_LOAD_FAST_AND_CLEAR",