summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Include/internal/pycore_code.h6
-rw-r--r--Include/opcode.h1
-rw-r--r--Lib/importlib/_bootstrap_external.py3
-rw-r--r--Lib/opcode.py2
-rw-r--r--Misc/NEWS.d/next/Core and Builtins/2022-03-07-15-54-39.bpo-46841.7wG92r.rst2
-rw-r--r--Python/ceval.c29
-rw-r--r--Python/specialize.c14
7 files changed, 28 insertions, 29 deletions
diff --git a/Include/internal/pycore_code.h b/Include/internal/pycore_code.h
index 21c657a..0d324e9 100644
--- a/Include/internal/pycore_code.h
+++ b/Include/internal/pycore_code.h
@@ -86,6 +86,12 @@ typedef struct {
#define INLINE_CACHE_ENTRIES_PRECALL CACHE_ENTRIES(_PyPrecallCache)
+typedef struct {
+ _Py_CODEUNIT counter;
+} _PyStoreSubscrCache;
+
+#define INLINE_CACHE_ENTRIES_STORE_SUBSCR CACHE_ENTRIES(_PyStoreSubscrCache)
+
/* Maximum size of code to quicken, in code units. */
#define MAX_SIZE_TO_QUICKEN 10000
diff --git a/Include/opcode.h b/Include/opcode.h
index 930a975..7bf0ba7 100644
--- a/Include/opcode.h
+++ b/Include/opcode.h
@@ -211,6 +211,7 @@ static const uint32_t _PyOpcode_Jump[8] = {
const uint8_t _PyOpcode_InlineCacheEntries[256] = {
[BINARY_SUBSCR] = 4,
+ [STORE_SUBSCR] = 1,
[UNPACK_SEQUENCE] = 1,
[STORE_ATTR] = 4,
[LOAD_ATTR] = 4,
diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py
index 32a41f8..a6f0a1b 100644
--- a/Lib/importlib/_bootstrap_external.py
+++ b/Lib/importlib/_bootstrap_external.py
@@ -394,6 +394,7 @@ _code_type = type(_write_atomic.__code__)
# STORE_ATTR)
# Python 3.11a5 3485 (Add an oparg to GET_AWAITABLE)
# Python 3.11a6 3486 (Use inline caching for PRECALL and CALL)
+# Python 3.11a6 3487 (Remove the adaptive "oparg counter" mechanism)
# Python 3.12 will start with magic number 3500
@@ -408,7 +409,7 @@ _code_type = type(_write_atomic.__code__)
# Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array
# in PC/launcher.c must also be updated.
-MAGIC_NUMBER = (3486).to_bytes(2, 'little') + b'\r\n'
+MAGIC_NUMBER = (3487).to_bytes(2, 'little') + b'\r\n'
_RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c
_PYCACHE = '__pycache__'
diff --git a/Lib/opcode.py b/Lib/opcode.py
index a31a77a..eb9dd35 100644
--- a/Lib/opcode.py
+++ b/Lib/opcode.py
@@ -84,7 +84,7 @@ def_op('BEFORE_ASYNC_WITH', 52)
def_op('BEFORE_WITH', 53)
def_op('END_ASYNC_FOR', 54)
-def_op('STORE_SUBSCR', 60)
+def_op('STORE_SUBSCR', 60, 1)
def_op('DELETE_SUBSCR', 61)
def_op('GET_ITER', 68)
diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-03-07-15-54-39.bpo-46841.7wG92r.rst b/Misc/NEWS.d/next/Core and Builtins/2022-03-07-15-54-39.bpo-46841.7wG92r.rst
new file mode 100644
index 0000000..f863c75
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2022-03-07-15-54-39.bpo-46841.7wG92r.rst
@@ -0,0 +1,2 @@
+Modify :opcode:`STORE_SUBSCR` to use an inline cache entry (rather than its
+oparg) as an adaptive counter.
diff --git a/Python/ceval.c b/Python/ceval.c
index b15c101..83309e2 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -2267,13 +2267,16 @@ handle_eval_breaker:
Py_DECREF(v);
Py_DECREF(container);
Py_DECREF(sub);
- if (err != 0)
+ if (err != 0) {
goto error;
+ }
+ JUMPBY(INLINE_CACHE_ENTRIES_STORE_SUBSCR);
DISPATCH();
}
TARGET(STORE_SUBSCR_ADAPTIVE) {
- if (oparg == 0) {
+ _PyStoreSubscrCache *cache = (_PyStoreSubscrCache *)next_instr;
+ if (cache->counter == 0) {
PyObject *sub = TOP();
PyObject *container = SECOND();
next_instr--;
@@ -2284,8 +2287,7 @@ handle_eval_breaker:
}
else {
STAT_INC(STORE_SUBSCR, deferred);
- // oparg is the adaptive cache counter
- UPDATE_PREV_INSTR_OPARG(next_instr, oparg - 1);
+ cache->counter--;
JUMP_TO_INSTRUCTION(STORE_SUBSCR);
}
}
@@ -2312,6 +2314,7 @@ handle_eval_breaker:
Py_DECREF(old_value);
Py_DECREF(sub);
Py_DECREF(list);
+ JUMPBY(INLINE_CACHE_ENTRIES_STORE_SUBSCR);
NOTRACE_DISPATCH();
}
@@ -2328,6 +2331,7 @@ handle_eval_breaker:
if (err != 0) {
goto error;
}
+ JUMPBY(INLINE_CACHE_ENTRIES_STORE_SUBSCR);
DISPATCH();
}
@@ -5520,21 +5524,6 @@ opname ## _miss: \
JUMP_TO_INSTRUCTION(opname); \
}
-#define MISS_WITH_OPARG_COUNTER(opname) \
-opname ## _miss: \
- { \
- STAT_INC(opname, miss); \
- uint8_t oparg = _Py_OPARG(next_instr[-1])-1; \
- UPDATE_PREV_INSTR_OPARG(next_instr, oparg); \
- assert(_Py_OPARG(next_instr[-1]) == oparg); \
- if (oparg == 0) /* too many cache misses */ { \
- oparg = ADAPTIVE_CACHE_BACKOFF; \
- next_instr[-1] = _Py_MAKECODEUNIT(opname ## _ADAPTIVE, oparg); \
- STAT_INC(opname, deopt); \
- } \
- JUMP_TO_INSTRUCTION(opname); \
- }
-
MISS_WITH_INLINE_CACHE(LOAD_ATTR)
MISS_WITH_INLINE_CACHE(STORE_ATTR)
MISS_WITH_INLINE_CACHE(LOAD_GLOBAL)
@@ -5545,7 +5534,7 @@ MISS_WITH_INLINE_CACHE(BINARY_OP)
MISS_WITH_INLINE_CACHE(COMPARE_OP)
MISS_WITH_INLINE_CACHE(BINARY_SUBSCR)
MISS_WITH_INLINE_CACHE(UNPACK_SEQUENCE)
-MISS_WITH_OPARG_COUNTER(STORE_SUBSCR)
+MISS_WITH_INLINE_CACHE(STORE_SUBSCR)
binary_subscr_dict_error:
{
diff --git a/Python/specialize.c b/Python/specialize.c
index dae4e3f..a11a76c 100644
--- a/Python/specialize.c
+++ b/Python/specialize.c
@@ -301,12 +301,11 @@ optimize(_Py_CODEUNIT *instructions, int len)
uint8_t adaptive_opcode = adaptive_opcodes[opcode];
if (adaptive_opcode) {
instructions[i] = _Py_MAKECODEUNIT(adaptive_opcode, oparg);
- int caches = _PyOpcode_InlineCacheEntries[opcode];
// Make sure the adaptive counter is zero:
- assert((caches ? instructions[i + 1] : oparg) == 0);
+ assert(instructions[i + 1] == 0);
previous_opcode = -1;
previous_oparg = -1;
- i += caches;
+ i += _PyOpcode_InlineCacheEntries[opcode];
}
else {
assert(!_PyOpcode_InlineCacheEntries[opcode]);
@@ -1313,6 +1312,7 @@ success:
int
_Py_Specialize_StoreSubscr(PyObject *container, PyObject *sub, _Py_CODEUNIT *instr)
{
+ _PyStoreSubscrCache *cache = (_PyStoreSubscrCache *)(instr + 1);
PyTypeObject *container_type = Py_TYPE(container);
if (container_type == &PyList_Type) {
if (PyLong_CheckExact(sub)) {
@@ -1320,7 +1320,7 @@ _Py_Specialize_StoreSubscr(PyObject *container, PyObject *sub, _Py_CODEUNIT *ins
&& ((PyLongObject *)sub)->ob_digit[0] < (size_t)PyList_GET_SIZE(container))
{
*instr = _Py_MAKECODEUNIT(STORE_SUBSCR_LIST_INT,
- initial_counter_value());
+ _Py_OPARG(*instr));
goto success;
}
else {
@@ -1338,8 +1338,7 @@ _Py_Specialize_StoreSubscr(PyObject *container, PyObject *sub, _Py_CODEUNIT *ins
}
}
if (container_type == &PyDict_Type) {
- *instr = _Py_MAKECODEUNIT(STORE_SUBSCR_DICT,
- initial_counter_value());
+ *instr = _Py_MAKECODEUNIT(STORE_SUBSCR_DICT, _Py_OPARG(*instr));
goto success;
}
#ifdef Py_STATS
@@ -1406,11 +1405,12 @@ _Py_Specialize_StoreSubscr(PyObject *container, PyObject *sub, _Py_CODEUNIT *ins
fail:
STAT_INC(STORE_SUBSCR, failure);
assert(!PyErr_Occurred());
- *instr = _Py_MAKECODEUNIT(_Py_OPCODE(*instr), ADAPTIVE_CACHE_BACKOFF);
+ cache->counter = ADAPTIVE_CACHE_BACKOFF;
return 0;
success:
STAT_INC(STORE_SUBSCR, success);
assert(!PyErr_Occurred());
+ cache->counter = initial_counter_value();
return 0;
}