Python-checkins
Threads by month
- ----- 2024 -----
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
March 2022
- 1 participants
- 509 discussions
https://github.com/python/cpython/commit/3b0f1c5a710eff289dc44bec972dbaea35…
commit: 3b0f1c5a710eff289dc44bec972dbaea353cc54f
branch: main
author: Mark Shannon <mark(a)hotpy.org>
committer: markshannon <mark(a)hotpy.org>
date: 2022-03-01T16:00:34Z
summary:
bpo-46841: Use inline cache for `BINARY_SUBSCR`. (GH-31618)
files:
A Misc/NEWS.d/next/Core and Builtins/2022-02-28-15-46-36.bpo-46841.MDQoty.rst
M Include/cpython/object.h
M Include/internal/pycore_code.h
M Include/opcode.h
M Lib/importlib/_bootstrap_external.py
M Lib/opcode.py
M Lib/test/test_capi.py
M Lib/test/test_sys.py
M Programs/test_frozenmain.h
M Python/ceval.c
M Python/specialize.c
diff --git a/Include/cpython/object.h b/Include/cpython/object.h
index 5f978eec46580..b018dabf9d862 100644
--- a/Include/cpython/object.h
+++ b/Include/cpython/object.h
@@ -229,6 +229,13 @@ struct _typeobject {
vectorcallfunc tp_vectorcall;
};
+/* This struct is used by the specializer
+ * It should should be treated as an opaque blob
+ * by code other than the specializer and interpreter. */
+struct _specialization_cache {
+ PyObject *getitem;
+};
+
/* The *real* layout of a type object when allocated on the heap */
typedef struct _heaptypeobject {
/* Note: there's a dependency on the order of these members
@@ -247,6 +254,7 @@ typedef struct _heaptypeobject {
struct _dictkeysobject *ht_cached_keys;
PyObject *ht_module;
char *_ht_tpname; // Storage for "tp_name"; see PyType_FromModuleAndSpec
+ struct _specialization_cache _spec_cache; // For use by the specializer.
/* here are optional user slots, followed by the members. */
} PyHeapTypeObject;
diff --git a/Include/internal/pycore_code.h b/Include/internal/pycore_code.h
index 47c1998c88d21..b9671d0ec32bb 100644
--- a/Include/internal/pycore_code.h
+++ b/Include/internal/pycore_code.h
@@ -92,6 +92,15 @@ typedef struct {
#define INLINE_CACHE_ENTRIES_COMPARE_OP CACHE_ENTRIES(_PyCompareOpCache)
+typedef struct {
+ _Py_CODEUNIT counter;
+ _Py_CODEUNIT type_version;
+ _Py_CODEUNIT _t1;
+ _Py_CODEUNIT func_version;
+} _PyBinarySubscrCache;
+
+#define INLINE_CACHE_ENTRIES_BINARY_SUBSCR CACHE_ENTRIES(_PyBinarySubscrCache)
+
/* Maximum size of code to quicken, in code units. */
#define MAX_SIZE_TO_QUICKEN 5000
@@ -323,7 +332,7 @@ extern int _Py_Specialize_LoadAttr(PyObject *owner, _Py_CODEUNIT *instr, PyObjec
extern int _Py_Specialize_StoreAttr(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name, SpecializedCacheEntry *cache);
extern int _Py_Specialize_LoadGlobal(PyObject *globals, PyObject *builtins, _Py_CODEUNIT *instr, PyObject *name);
extern int _Py_Specialize_LoadMethod(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name, SpecializedCacheEntry *cache);
-extern int _Py_Specialize_BinarySubscr(PyObject *sub, PyObject *container, _Py_CODEUNIT *instr, SpecializedCacheEntry *cache);
+extern int _Py_Specialize_BinarySubscr(PyObject *sub, PyObject *container, _Py_CODEUNIT *instr);
extern int _Py_Specialize_StoreSubscr(PyObject *container, PyObject *sub, _Py_CODEUNIT *instr);
extern int _Py_Specialize_Call(PyObject *callable, _Py_CODEUNIT *instr, int nargs,
PyObject *kwnames, SpecializedCacheEntry *cache);
diff --git a/Include/opcode.h b/Include/opcode.h
index ba85b7ff75fcd..f6330d9056aa1 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,
[UNPACK_SEQUENCE] = 1,
[COMPARE_OP] = 2,
[LOAD_GLOBAL] = 5,
diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py
index c69c0c73e7a27..dd1f6ffd64cee 100644
--- a/Lib/importlib/_bootstrap_external.py
+++ b/Lib/importlib/_bootstrap_external.py
@@ -389,7 +389,7 @@ def _write_atomic(path, data, mode=0o666):
# Python 3.11a5 3480 (New CALL opcodes, second iteration)
# Python 3.11a5 3481 (Use inline cache for BINARY_OP)
# Python 3.11a5 3482 (Use inline caching for UNPACK_SEQUENCE and LOAD_GLOBAL)
-# Python 3.11a5 3483 (Use inline caching for COMPARE_OP)
+# Python 3.11a5 3483 (Use inline caching for COMPARE_OP and BINARY_SUBSCR)
# Python 3.12 will start with magic number 3500
diff --git a/Lib/opcode.py b/Lib/opcode.py
index dc45cff3017a6..9b08562cd04f6 100644
--- a/Lib/opcode.py
+++ b/Lib/opcode.py
@@ -68,7 +68,7 @@ def jabs_op(name, op, entries=0):
def_op('UNARY_INVERT', 15)
-def_op('BINARY_SUBSCR', 25)
+def_op('BINARY_SUBSCR', 25, 4)
def_op('GET_LEN', 30)
def_op('MATCH_MAPPING', 31)
diff --git a/Lib/test/test_capi.py b/Lib/test/test_capi.py
index 8832292a9991a..d9615430327a4 100644
--- a/Lib/test/test_capi.py
+++ b/Lib/test/test_capi.py
@@ -335,7 +335,7 @@ class C(): pass
*_, count = line.split(b' ')
count = int(count)
self.assertLessEqual(count, i*5)
- self.assertGreaterEqual(count, i*5-1)
+ self.assertGreaterEqual(count, i*5-2)
def test_mapping_keys_values_items(self):
class Mapping1(dict):
diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py
index f828d1b15d286..70768f56fa9f1 100644
--- a/Lib/test/test_sys.py
+++ b/Lib/test/test_sys.py
@@ -1501,7 +1501,9 @@ def delx(self): del self.__x
'3P' # PyMappingMethods
'10P' # PySequenceMethods
'2P' # PyBufferProcs
- '6P')
+ '6P'
+ '1P' # Specializer cache
+ )
class newstyleclass(object): pass
# Separate block for PyDictKeysObject with 8 keys and 5 entries
check(newstyleclass, s + calcsize(DICT_KEY_STRUCT_FORMAT) + 64 + 42*calcsize("n2P"))
diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-02-28-15-46-36.bpo-46841.MDQoty.rst b/Misc/NEWS.d/next/Core and Builtins/2022-02-28-15-46-36.bpo-46841.MDQoty.rst
new file mode 100644
index 0000000000000..97b03debcf092
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2022-02-28-15-46-36.bpo-46841.MDQoty.rst
@@ -0,0 +1 @@
+Use inline cache for :opcode:`BINARY_SUBSCR`.
diff --git a/Programs/test_frozenmain.h b/Programs/test_frozenmain.h
index 11593a9ba3d68..3fef981e42ff9 100644
--- a/Programs/test_frozenmain.h
+++ b/Programs/test_frozenmain.h
@@ -1,13 +1,14 @@
// Auto-generated by Programs/freeze_test_frozenmain.py
unsigned char M_test_frozenmain[] = {
227,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,
- 0,0,0,0,0,115,104,0,0,0,151,0,100,0,100,1,
+ 0,0,0,0,0,115,120,0,0,0,151,0,100,0,100,1,
108,0,90,0,100,0,100,1,108,1,90,1,2,0,101,2,
100,2,166,1,171,1,1,0,2,0,101,2,100,3,101,0,
106,3,166,2,171,2,1,0,2,0,101,1,106,4,166,0,
- 171,0,100,4,25,0,90,5,100,5,68,0,93,16,90,6,
- 2,0,101,2,100,6,101,6,155,0,100,7,101,5,101,6,
- 25,0,155,0,157,4,166,1,171,1,1,0,113,33,100,1,
+ 171,0,100,4,25,0,3,0,3,0,3,0,3,0,90,5,
+ 100,5,68,0,93,20,90,6,2,0,101,2,100,6,101,6,
+ 155,0,100,7,101,5,101,6,25,0,3,0,3,0,3,0,
+ 3,0,155,0,157,4,166,1,171,1,1,0,113,37,100,1,
83,0,41,8,233,0,0,0,0,78,122,18,70,114,111,122,
101,110,32,72,101,108,108,111,32,87,111,114,108,100,122,8,
115,121,115,46,97,114,103,118,218,6,99,111,110,102,105,103,
@@ -24,14 +25,15 @@ unsigned char M_test_frozenmain[] = {
0,0,250,18,116,101,115,116,95,102,114,111,122,101,110,109,
97,105,110,46,112,121,250,8,60,109,111,100,117,108,101,62,
114,11,0,0,0,1,0,0,0,115,18,0,0,0,2,128,
- 8,3,8,1,12,2,16,1,16,1,8,1,30,7,4,249,
- 115,20,0,0,0,2,128,8,3,8,1,12,2,16,1,16,
- 1,2,7,4,1,2,249,34,7,115,104,0,0,0,0,0,
+ 8,3,8,1,12,2,16,1,24,1,8,1,38,7,4,249,
+ 115,20,0,0,0,2,128,8,3,8,1,12,2,16,1,24,
+ 1,2,7,4,1,2,249,42,7,115,120,0,0,0,0,0,
1,11,1,11,1,11,1,11,1,25,1,25,1,25,1,25,
1,6,1,6,7,27,1,28,1,28,1,28,1,6,1,6,
7,17,19,22,19,27,1,28,1,28,1,28,10,39,10,27,
- 10,39,10,41,10,41,42,50,10,51,1,7,12,2,1,42,
- 1,42,5,8,5,10,5,10,11,41,21,24,11,41,11,41,
- 28,34,35,38,28,39,11,41,11,41,5,42,5,42,5,42,
+ 10,39,10,41,10,41,42,50,10,51,10,51,10,51,10,51,
+ 10,51,1,7,12,2,1,42,1,42,5,8,5,10,5,10,
+ 11,41,21,24,11,41,11,41,28,34,35,38,28,39,28,39,
+ 28,39,28,39,28,39,11,41,11,41,5,42,5,42,5,42,
5,42,1,42,1,42,114,9,0,0,0,
};
diff --git a/Python/ceval.c b/Python/ceval.c
index 0f57e7dc94a04..b3673d7d04ab2 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -2102,25 +2102,24 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
SET_TOP(res);
if (res == NULL)
goto error;
+ JUMPBY(INLINE_CACHE_ENTRIES_BINARY_SUBSCR);
DISPATCH();
}
TARGET(BINARY_SUBSCR_ADAPTIVE) {
- SpecializedCacheEntry *cache = GET_CACHE();
- if (cache->adaptive.counter == 0) {
+ _PyBinarySubscrCache *cache = (_PyBinarySubscrCache *)next_instr;
+ if (cache->counter == 0) {
PyObject *sub = TOP();
PyObject *container = SECOND();
next_instr--;
- if (_Py_Specialize_BinarySubscr(container, sub, next_instr, cache) < 0) {
+ if (_Py_Specialize_BinarySubscr(container, sub, next_instr) < 0) {
goto error;
}
DISPATCH();
}
else {
STAT_INC(BINARY_SUBSCR, deferred);
- cache->adaptive.counter--;
- assert(cache->adaptive.original_oparg == 0);
- /* No need to set oparg here; it isn't used by BINARY_SUBSCR */
+ cache->counter--;
JUMP_TO_INSTRUCTION(BINARY_SUBSCR);
}
}
@@ -2146,6 +2145,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
Py_DECREF(sub);
SET_TOP(res);
Py_DECREF(list);
+ JUMPBY(INLINE_CACHE_ENTRIES_BINARY_SUBSCR);
NOTRACE_DISPATCH();
}
@@ -2170,6 +2170,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
Py_DECREF(sub);
SET_TOP(res);
Py_DECREF(tuple);
+ JUMPBY(INLINE_CACHE_ENTRIES_BINARY_SUBSCR);
NOTRACE_DISPATCH();
}
@@ -2188,18 +2189,22 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
Py_DECREF(sub);
SET_TOP(res);
Py_DECREF(dict);
+ JUMPBY(INLINE_CACHE_ENTRIES_BINARY_SUBSCR);
DISPATCH();
}
TARGET(BINARY_SUBSCR_GETITEM) {
PyObject *sub = TOP();
PyObject *container = SECOND();
- SpecializedCacheEntry *caches = GET_CACHE();
- _PyAdaptiveEntry *cache0 = &caches[0].adaptive;
- _PyObjectCache *cache1 = &caches[-1].obj;
- PyFunctionObject *getitem = (PyFunctionObject *)cache1->obj;
- DEOPT_IF(Py_TYPE(container)->tp_version_tag != cache0->version, BINARY_SUBSCR);
- DEOPT_IF(getitem->func_version != cache0->index, BINARY_SUBSCR);
+ _PyBinarySubscrCache *cache = (_PyBinarySubscrCache *)next_instr;
+ uint32_t type_version = read32(&cache->type_version);
+ PyTypeObject *tp = Py_TYPE(container);
+ DEOPT_IF(tp->tp_version_tag != type_version, BINARY_SUBSCR);
+ assert(tp->tp_flags & Py_TPFLAGS_HEAPTYPE);
+ PyObject *cached = ((PyHeapTypeObject *)tp)->_spec_cache.getitem;
+ assert(PyFunction_Check(cached));
+ PyFunctionObject *getitem = (PyFunctionObject *)cached;
+ DEOPT_IF(getitem->func_version != cache->func_version, BINARY_SUBSCR);
PyCodeObject *code = (PyCodeObject *)getitem->func_code;
size_t size = code->co_nlocalsplus + code->co_stacksize + FRAME_SPECIALS_SIZE;
assert(code->co_argcount == 2);
@@ -2218,6 +2223,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
new_frame->localsplus[i] = NULL;
}
_PyFrame_SetStackPointer(frame, stack_pointer);
+ frame->f_lasti += INLINE_CACHE_ENTRIES_BINARY_SUBSCR;
new_frame->previous = frame;
frame = cframe.current_frame = new_frame;
CALL_STAT_INC(inlined_py_calls);
@@ -5605,7 +5611,7 @@ MISS_WITH_CACHE(PRECALL)
MISS_WITH_CACHE(CALL)
MISS_WITH_INLINE_CACHE(BINARY_OP)
MISS_WITH_INLINE_CACHE(COMPARE_OP)
-MISS_WITH_CACHE(BINARY_SUBSCR)
+MISS_WITH_INLINE_CACHE(BINARY_SUBSCR)
MISS_WITH_INLINE_CACHE(UNPACK_SEQUENCE)
MISS_WITH_OPARG_COUNTER(STORE_SUBSCR)
diff --git a/Python/specialize.c b/Python/specialize.c
index 925edf3f88d5f..5486b5b1f65dc 100644
--- a/Python/specialize.c
+++ b/Python/specialize.c
@@ -60,7 +60,6 @@ static uint8_t adaptive_opcodes[256] = {
static uint8_t cache_requirements[256] = {
[LOAD_ATTR] = 1, // _PyAdaptiveEntry
[LOAD_METHOD] = 3, /* _PyAdaptiveEntry, _PyAttrCache and _PyObjectCache */
- [BINARY_SUBSCR] = 2, /* _PyAdaptiveEntry, _PyObjectCache */
[STORE_SUBSCR] = 0,
[CALL] = 2, /* _PyAdaptiveEntry and _PyObjectCache/_PyCallCache */
[PRECALL] = 2, /* _PyAdaptiveEntry and _PyObjectCache/_PyCallCache */
@@ -385,6 +384,8 @@ optimize(SpecializedCacheOrInstruction *quickened, int len)
if (adaptive_opcode) {
if (_PyOpcode_InlineCacheEntries[opcode]) {
instructions[i] = _Py_MAKECODEUNIT(adaptive_opcode, oparg);
+ previous_opcode = -1;
+ i += _PyOpcode_InlineCacheEntries[opcode];
}
else if (previous_opcode != EXTENDED_ARG) {
int new_oparg = oparg_from_instruction_and_update_offset(
@@ -553,6 +554,7 @@ initial_counter_value(void) {
#define SPEC_FAIL_SUBSCR_PY_SIMPLE 20
#define SPEC_FAIL_SUBSCR_PY_OTHER 21
#define SPEC_FAIL_SUBSCR_DICT_SUBCLASS_NO_OVERRIDE 22
+#define SPEC_FAIL_SUBSCR_NOT_HEAP_TYPE 23
/* Binary op */
@@ -1335,9 +1337,11 @@ function_kind(PyCodeObject *code) {
int
_Py_Specialize_BinarySubscr(
- PyObject *container, PyObject *sub, _Py_CODEUNIT *instr, SpecializedCacheEntry *cache)
+ PyObject *container, PyObject *sub, _Py_CODEUNIT *instr)
{
- _PyAdaptiveEntry *cache0 = &cache->adaptive;
+ assert(_PyOpcode_InlineCacheEntries[BINARY_SUBSCR] ==
+ INLINE_CACHE_ENTRIES_BINARY_SUBSCR);
+ _PyBinarySubscrCache *cache = (_PyBinarySubscrCache *)(instr + 1);
PyTypeObject *container_type = Py_TYPE(container);
if (container_type == &PyList_Type) {
if (PyLong_CheckExact(sub)) {
@@ -1364,26 +1368,30 @@ _Py_Specialize_BinarySubscr(
PyTypeObject *cls = Py_TYPE(container);
PyObject *descriptor = _PyType_Lookup(cls, &_Py_ID(__getitem__));
if (descriptor && Py_TYPE(descriptor) == &PyFunction_Type) {
+ if (!(container_type->tp_flags & Py_TPFLAGS_HEAPTYPE)) {
+ SPECIALIZATION_FAIL(BINARY_SUBSCR, SPEC_FAIL_SUBSCR_NOT_HEAP_TYPE);
+ goto fail;
+ }
PyFunctionObject *func = (PyFunctionObject *)descriptor;
- PyCodeObject *code = (PyCodeObject *)func->func_code;
- int kind = function_kind(code);
+ PyCodeObject *fcode = (PyCodeObject *)func->func_code;
+ int kind = function_kind(fcode);
if (kind != SIMPLE_FUNCTION) {
SPECIALIZATION_FAIL(BINARY_SUBSCR, kind);
goto fail;
}
- if (code->co_argcount != 2) {
+ if (fcode->co_argcount != 2) {
SPECIALIZATION_FAIL(BINARY_SUBSCR, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS);
goto fail;
}
assert(cls->tp_version_tag != 0);
- cache0->version = cls->tp_version_tag;
+ write32(&cache->type_version, cls->tp_version_tag);
int version = _PyFunction_GetVersionForCurrentState(func);
if (version == 0 || version != (uint16_t)version) {
SPECIALIZATION_FAIL(BINARY_SUBSCR, SPEC_FAIL_OUT_OF_VERSIONS);
goto fail;
}
- cache0->index = version;
- cache[-1].obj.obj = descriptor;
+ cache->func_version = version;
+ ((PyHeapTypeObject *)container_type)->_spec_cache.getitem = descriptor;
*instr = _Py_MAKECODEUNIT(BINARY_SUBSCR_GETITEM, _Py_OPARG(*instr));
goto success;
}
@@ -1392,12 +1400,12 @@ _Py_Specialize_BinarySubscr(
fail:
STAT_INC(BINARY_SUBSCR, failure);
assert(!PyErr_Occurred());
- cache_backoff(cache0);
+ cache->counter = ADAPTIVE_CACHE_BACKOFF;
return 0;
success:
STAT_INC(BINARY_SUBSCR, success);
assert(!PyErr_Occurred());
- cache0->counter = initial_counter_value();
+ cache->counter = initial_counter_value();
return 0;
}
1
0
01 Mar '22
https://github.com/python/cpython/commit/e91b0a7139d4a4cbd2351ccb5cd021a100…
commit: e91b0a7139d4a4cbd2351ccb5cd021a100cf42d2
branch: main
author: Kumar Aditya <59607654+kumaraditya303(a)users.noreply.github.com>
committer: corona10 <donghee.na92(a)gmail.com>
date: 2022-03-02T00:38:21+09:00
summary:
bpo-46541: remove usage of _Py_IDENTIFIER from _ssl module (GH-31599)
files:
M Modules/_ssl.c
M Modules/_ssl.h
diff --git a/Modules/_ssl.c b/Modules/_ssl.c
index 312b2eabe3db5..e67ab42050b26 100644
--- a/Modules/_ssl.c
+++ b/Modules/_ssl.c
@@ -22,7 +22,6 @@
#define OPENSSL_NO_DEPRECATED 1
#define PY_SSIZE_T_CLEAN
-#define NEEDS_PY_IDENTIFIER
#include "Python.h"
@@ -447,10 +446,6 @@ fill_and_set_sslerror(_sslmodulestate *state,
PyObject *err_value = NULL, *reason_obj = NULL, *lib_obj = NULL;
PyObject *verify_obj = NULL, *verify_code_obj = NULL;
PyObject *init_value, *msg, *key;
- _Py_IDENTIFIER(reason);
- _Py_IDENTIFIER(library);
- _Py_IDENTIFIER(verify_message);
- _Py_IDENTIFIER(verify_code);
if (errcode != 0) {
int lib, reason;
@@ -544,20 +539,20 @@ fill_and_set_sslerror(_sslmodulestate *state,
if (reason_obj == NULL)
reason_obj = Py_None;
- if (_PyObject_SetAttrId(err_value, &PyId_reason, reason_obj))
+ if (PyObject_SetAttr(err_value, state->str_reason, reason_obj))
goto fail;
if (lib_obj == NULL)
lib_obj = Py_None;
- if (_PyObject_SetAttrId(err_value, &PyId_library, lib_obj))
+ if (PyObject_SetAttr(err_value, state->str_library, lib_obj))
goto fail;
if ((sslsock != NULL) && (type == state->PySSLCertVerificationErrorObject)) {
/* Only set verify code / message for SSLCertVerificationError */
- if (_PyObject_SetAttrId(err_value, &PyId_verify_code,
+ if (PyObject_SetAttr(err_value, state->str_verify_code,
verify_code_obj))
goto fail;
- if (_PyObject_SetAttrId(err_value, &PyId_verify_message, verify_obj))
+ if (PyObject_SetAttr(err_value, state->str_verify_message, verify_obj))
goto fail;
}
@@ -6158,6 +6153,29 @@ sslmodule_init_types(PyObject *module)
return 0;
}
+static int
+sslmodule_init_strings(PyObject *module)
+{
+ _sslmodulestate *state = get_ssl_state(module);
+ state->str_library = PyUnicode_InternFromString("library");
+ if (state->str_library == NULL) {
+ return -1;
+ }
+ state->str_reason = PyUnicode_InternFromString("reason");
+ if (state->str_reason == NULL) {
+ return -1;
+ }
+ state->str_verify_message = PyUnicode_InternFromString("verify_message");
+ if (state->str_verify_message == NULL) {
+ return -1;
+ }
+ state->str_verify_code = PyUnicode_InternFromString("verify_code");
+ if (state->str_verify_code == NULL) {
+ return -1;
+ }
+ return 0;
+}
+
static PyModuleDef_Slot sslmodule_slots[] = {
{Py_mod_exec, sslmodule_init_types},
{Py_mod_exec, sslmodule_init_exceptions},
@@ -6165,6 +6183,7 @@ static PyModuleDef_Slot sslmodule_slots[] = {
{Py_mod_exec, sslmodule_init_errorcodes},
{Py_mod_exec, sslmodule_init_constants},
{Py_mod_exec, sslmodule_init_versioninfo},
+ {Py_mod_exec, sslmodule_init_strings},
{0, NULL}
};
@@ -6214,7 +6233,10 @@ sslmodule_clear(PyObject *m)
Py_CLEAR(state->err_names_to_codes);
Py_CLEAR(state->lib_codes_to_names);
Py_CLEAR(state->Sock_Type);
-
+ Py_CLEAR(state->str_library);
+ Py_CLEAR(state->str_reason);
+ Py_CLEAR(state->str_verify_code);
+ Py_CLEAR(state->str_verify_message);
return 0;
}
diff --git a/Modules/_ssl.h b/Modules/_ssl.h
index 5593a455de4dc..d68ccdec5e88c 100644
--- a/Modules/_ssl.h
+++ b/Modules/_ssl.h
@@ -29,6 +29,11 @@ typedef struct {
PyObject *lib_codes_to_names;
/* socket type from module CAPI */
PyTypeObject *Sock_Type;
+ /* Interned strings */
+ PyObject *str_library;
+ PyObject *str_reason;
+ PyObject *str_verify_code;
+ PyObject *str_verify_message;
} _sslmodulestate;
static struct PyModuleDef _sslmodule_def;
1
0
https://github.com/python/cpython/commit/9204bb72a2da5885facc747e63d2bd2d65…
commit: 9204bb72a2da5885facc747e63d2bd2d654606fe
branch: main
author: Victor Stinner <vstinner(a)python.org>
committer: vstinner <vstinner(a)python.org>
date: 2022-03-01T15:44:08+01:00
summary:
bpo-46633: Skip tests on ASAN and/or MSAN builds (GH-31632)
Skip tests on ASAN and/or MSAN builds:
* multiprocessing tests
* test___all__
* test_concurrent_futures
* test_decimal
* test_peg_generator
* test_tools
The ASAN job of GitHub Actions no longer excludes these tests.
files:
M .github/workflows/build.yml
M Lib/test/_test_multiprocessing.py
M Lib/test/test___all__.py
M Lib/test/test_concurrent_futures.py
M Lib/test/test_decimal.py
M Lib/test/test_peg_generator/__init__.py
M Lib/test/test_tools/__init__.py
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 5d36dffa80108..f6df74357d2f5 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -306,12 +306,4 @@ jobs:
- name: Display build info
run: make pythoninfo
- name: Tests
- # Skip test_tools test_peg_generator test_concurrent_futures because
- # there are too slow: between 5 and 20 minutes on this CI.
- #
- # Skip multiprocessing and concurrent.futures tests which are affected by
- # bpo-45200 bug: libasan dead lock in pthread_create().
- #
- # test___all__ is skipped because importing some modules directly can trigger
- # known problems with ASAN (like tk or crypt).
- run: xvfb-run make buildbottest TESTOPTS="-j4 -uall,-cpu -x test___all__ test_multiprocessing_fork test_multiprocessing_forkserver test_multiprocessing_spawn test_tools test_peg_generator test_concurrent_futures"
+ run: xvfb-run make buildbottest TESTOPTS="-j4 -uall,-cpu"
diff --git a/Lib/test/_test_multiprocessing.py b/Lib/test/_test_multiprocessing.py
index 6b1b1677910d1..bb73d9e7cc75e 100644
--- a/Lib/test/_test_multiprocessing.py
+++ b/Lib/test/_test_multiprocessing.py
@@ -73,6 +73,12 @@
msvcrt = None
+if support.check_sanitizer(address=True):
+ # bpo-45200: Skip multiprocessing tests if Python is built with ASAN to
+ # work around a libasan race condition: dead lock in pthread_create().
+ raise unittest.SkipTest("libasan has a pthread_create() dead lock")
+
+
def latin(s):
return s.encode('latin')
diff --git a/Lib/test/test___all__.py b/Lib/test/test___all__.py
index 81293e15f8163..a1a3d899e4e03 100644
--- a/Lib/test/test___all__.py
+++ b/Lib/test/test___all__.py
@@ -11,6 +11,13 @@
_multiprocessing = None
+if support.check_sanitizer(address=True, memory=True):
+ # bpo-46633: test___all__ is skipped because importing some modules
+ # directly can trigger known problems with ASAN (like tk or crypt).
+ raise unittest.SkipTest("workaround ASAN build issues on loading tests "
+ "like tk or crypt")
+
+
class NoAll(RuntimeError):
pass
diff --git a/Lib/test/test_concurrent_futures.py b/Lib/test/test_concurrent_futures.py
index 71c88a3cadd25..8adba36a387ad 100644
--- a/Lib/test/test_concurrent_futures.py
+++ b/Lib/test/test_concurrent_futures.py
@@ -32,6 +32,12 @@
import multiprocessing.util
+if support.check_sanitizer(address=True, memory=True):
+ # bpo-46633: Skip the test because it is too slow when Python is built
+ # with ASAN/MSAN: between 5 and 20 minutes on GitHub Actions.
+ raise unittest.SkipTest("test too slow on ASAN/MSAN build")
+
+
def create_future(state=PENDING, exception=None, result=None):
f = Future()
f._state = state
diff --git a/Lib/test/test_decimal.py b/Lib/test/test_decimal.py
index 9ced801afc2e9..b68cfbef23f16 100644
--- a/Lib/test/test_decimal.py
+++ b/Lib/test/test_decimal.py
@@ -34,7 +34,7 @@
import locale
from test.support import (run_unittest, run_doctest, is_resource_enabled,
requires_IEEE_754, requires_docstrings,
- requires_legacy_unicode_capi)
+ requires_legacy_unicode_capi, check_sanitizer)
from test.support import (TestFailed,
run_with_locale, cpython_only,
darwin_malloc_err_warning)
@@ -43,17 +43,6 @@
import random
import inspect
import threading
-import sysconfig
-_cflags = sysconfig.get_config_var('CFLAGS') or ''
-_config_args = sysconfig.get_config_var('CONFIG_ARGS') or ''
-MEMORY_SANITIZER = (
- '-fsanitize=memory' in _cflags or
- '--with-memory-sanitizer' in _config_args
-)
-
-ADDRESS_SANITIZER = (
- '-fsanitize=address' in _cflags
-)
if sys.platform == 'darwin':
@@ -5518,7 +5507,8 @@ def __abs__(self):
# Issue 41540:
@unittest.skipIf(sys.platform.startswith("aix"),
"AIX: default ulimit: test is flaky because of extreme over-allocation")
- @unittest.skipIf(MEMORY_SANITIZER or ADDRESS_SANITIZER, "sanitizer defaults to crashing "
+ @unittest.skipIf(check_sanitizer(address=True, memory=True),
+ "ASAN/MSAN sanitizer defaults to crashing "
"instead of returning NULL for malloc failure.")
def test_maxcontext_exact_arith(self):
diff --git a/Lib/test/test_peg_generator/__init__.py b/Lib/test/test_peg_generator/__init__.py
index fa855f2104c58..77f72fcc7c6e3 100644
--- a/Lib/test/test_peg_generator/__init__.py
+++ b/Lib/test/test_peg_generator/__init__.py
@@ -1,7 +1,15 @@
-import os
-
+import os.path
+import unittest
+from test import support
from test.support import load_package_tests
+
+if support.check_sanitizer(address=True, memory=True):
+ # bpo-46633: Skip the test because it is too slow when Python is built
+ # with ASAN/MSAN: between 5 and 20 minutes on GitHub Actions.
+ raise unittest.SkipTest("test too slow on ASAN/MSAN build")
+
+
# Load all tests in package
def load_tests(*args):
return load_package_tests(os.path.dirname(__file__), *args)
diff --git a/Lib/test/test_tools/__init__.py b/Lib/test/test_tools/__init__.py
index 61af6578e0953..34b0d3b8fb3eb 100644
--- a/Lib/test/test_tools/__init__.py
+++ b/Lib/test/test_tools/__init__.py
@@ -6,6 +6,13 @@
from test import support
from test.support import import_helper
+
+if support.check_sanitizer(address=True, memory=True):
+ # bpo-46633: Skip the test because it is too slow when Python is built
+ # with ASAN/MSAN: between 5 and 20 minutes on GitHub Actions.
+ raise unittest.SkipTest("test too slow on ASAN/MSAN build")
+
+
basepath = os.path.normpath(
os.path.dirname( # <src/install dir>
os.path.dirname( # Lib
1
0
01 Mar '22
https://github.com/python/cpython/commit/0cc63641859b2f60ea65bb7c0b6d1cfcec…
commit: 0cc63641859b2f60ea65bb7c0b6d1cfcec1e2f1a
branch: main
author: Dong-hee Na <donghee.na(a)python.org>
committer: corona10 <donghee.na92(a)gmail.com>
date: 2022-03-01T23:35:43+09:00
summary:
bpo-46541: Remove usage of _Py_IDENTIFIER from multibytecodec (GH-31475)
files:
M Modules/cjkcodecs/clinic/multibytecodec.c.h
M Modules/cjkcodecs/multibytecodec.c
diff --git a/Modules/cjkcodecs/clinic/multibytecodec.c.h b/Modules/cjkcodecs/clinic/multibytecodec.c.h
index 563888370d06c..1dfb9a1224827 100644
--- a/Modules/cjkcodecs/clinic/multibytecodec.c.h
+++ b/Modules/cjkcodecs/clinic/multibytecodec.c.h
@@ -481,7 +481,30 @@ PyDoc_STRVAR(_multibytecodec_MultibyteStreamWriter_write__doc__,
"\n");
#define _MULTIBYTECODEC_MULTIBYTESTREAMWRITER_WRITE_METHODDEF \
- {"write", (PyCFunction)_multibytecodec_MultibyteStreamWriter_write, METH_O, _multibytecodec_MultibyteStreamWriter_write__doc__},
+ {"write", (PyCFunction)(void(*)(void))_multibytecodec_MultibyteStreamWriter_write, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _multibytecodec_MultibyteStreamWriter_write__doc__},
+
+static PyObject *
+_multibytecodec_MultibyteStreamWriter_write_impl(MultibyteStreamWriterObject *self,
+ PyTypeObject *cls,
+ PyObject *strobj);
+
+static PyObject *
+_multibytecodec_MultibyteStreamWriter_write(MultibyteStreamWriterObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
+{
+ PyObject *return_value = NULL;
+ static const char * const _keywords[] = {"", NULL};
+ static _PyArg_Parser _parser = {"O:write", _keywords, 0};
+ PyObject *strobj;
+
+ if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
+ &strobj)) {
+ goto exit;
+ }
+ return_value = _multibytecodec_MultibyteStreamWriter_write_impl(self, cls, strobj);
+
+exit:
+ return return_value;
+}
PyDoc_STRVAR(_multibytecodec_MultibyteStreamWriter_writelines__doc__,
"writelines($self, lines, /)\n"
@@ -489,7 +512,30 @@ PyDoc_STRVAR(_multibytecodec_MultibyteStreamWriter_writelines__doc__,
"\n");
#define _MULTIBYTECODEC_MULTIBYTESTREAMWRITER_WRITELINES_METHODDEF \
- {"writelines", (PyCFunction)_multibytecodec_MultibyteStreamWriter_writelines, METH_O, _multibytecodec_MultibyteStreamWriter_writelines__doc__},
+ {"writelines", (PyCFunction)(void(*)(void))_multibytecodec_MultibyteStreamWriter_writelines, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _multibytecodec_MultibyteStreamWriter_writelines__doc__},
+
+static PyObject *
+_multibytecodec_MultibyteStreamWriter_writelines_impl(MultibyteStreamWriterObject *self,
+ PyTypeObject *cls,
+ PyObject *lines);
+
+static PyObject *
+_multibytecodec_MultibyteStreamWriter_writelines(MultibyteStreamWriterObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
+{
+ PyObject *return_value = NULL;
+ static const char * const _keywords[] = {"", NULL};
+ static _PyArg_Parser _parser = {"O:writelines", _keywords, 0};
+ PyObject *lines;
+
+ if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
+ &lines)) {
+ goto exit;
+ }
+ return_value = _multibytecodec_MultibyteStreamWriter_writelines_impl(self, cls, lines);
+
+exit:
+ return return_value;
+}
PyDoc_STRVAR(_multibytecodec_MultibyteStreamWriter_reset__doc__,
"reset($self, /)\n"
@@ -497,15 +543,27 @@ PyDoc_STRVAR(_multibytecodec_MultibyteStreamWriter_reset__doc__,
"\n");
#define _MULTIBYTECODEC_MULTIBYTESTREAMWRITER_RESET_METHODDEF \
- {"reset", (PyCFunction)_multibytecodec_MultibyteStreamWriter_reset, METH_NOARGS, _multibytecodec_MultibyteStreamWriter_reset__doc__},
+ {"reset", (PyCFunction)(void(*)(void))_multibytecodec_MultibyteStreamWriter_reset, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _multibytecodec_MultibyteStreamWriter_reset__doc__},
static PyObject *
-_multibytecodec_MultibyteStreamWriter_reset_impl(MultibyteStreamWriterObject *self);
+_multibytecodec_MultibyteStreamWriter_reset_impl(MultibyteStreamWriterObject *self,
+ PyTypeObject *cls);
static PyObject *
-_multibytecodec_MultibyteStreamWriter_reset(MultibyteStreamWriterObject *self, PyObject *Py_UNUSED(ignored))
+_multibytecodec_MultibyteStreamWriter_reset(MultibyteStreamWriterObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
- return _multibytecodec_MultibyteStreamWriter_reset_impl(self);
+ PyObject *return_value = NULL;
+ static const char * const _keywords[] = { NULL};
+ static _PyArg_Parser _parser = {":reset", _keywords, 0};
+
+ if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser
+ )) {
+ goto exit;
+ }
+ return_value = _multibytecodec_MultibyteStreamWriter_reset_impl(self, cls);
+
+exit:
+ return return_value;
}
PyDoc_STRVAR(_multibytecodec___create_codec__doc__,
@@ -515,4 +573,4 @@ PyDoc_STRVAR(_multibytecodec___create_codec__doc__,
#define _MULTIBYTECODEC___CREATE_CODEC_METHODDEF \
{"__create_codec", (PyCFunction)_multibytecodec___create_codec, METH_O, _multibytecodec___create_codec__doc__},
-/*[clinic end generated code: output=5c0f74129db07c87 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=8813c05077580bda input=a9049054013a1b77]*/
diff --git a/Modules/cjkcodecs/multibytecodec.c b/Modules/cjkcodecs/multibytecodec.c
index acfe96654a226..4769ab26b1b9e 100644
--- a/Modules/cjkcodecs/multibytecodec.c
+++ b/Modules/cjkcodecs/multibytecodec.c
@@ -5,7 +5,6 @@
*/
#define PY_SSIZE_T_CLEAN
-#define NEEDS_PY_IDENTIFIER
#include "Python.h"
#include "structmember.h" // PyMemberDef
#include "multibytecodec.h"
@@ -19,6 +18,7 @@ typedef struct {
PyTypeObject *reader_type;
PyTypeObject *writer_type;
PyTypeObject *multibytecodec_type;
+ PyObject *str_write;
} _multibytecodec_state;
static _multibytecodec_state *
@@ -72,8 +72,6 @@ static PyObject *multibytecodec_encode(MultibyteCodec *,
#define MBENC_RESET MBENC_MAX<<1 /* reset after an encoding session */
-_Py_IDENTIFIER(write);
-
static PyObject *
make_tuple(PyObject *object, Py_ssize_t len)
{
@@ -1715,7 +1713,7 @@ static PyType_Spec reader_spec = {
static int
mbstreamwriter_iwrite(MultibyteStreamWriterObject *self,
- PyObject *unistr)
+ PyObject *unistr, PyObject *str_write)
{
PyObject *str, *wr;
@@ -1723,7 +1721,7 @@ mbstreamwriter_iwrite(MultibyteStreamWriterObject *self,
if (str == NULL)
return -1;
- wr = _PyObject_CallMethodIdOneArg(self->stream, &PyId_write, str);
+ wr = _PyObject_CallMethodOneArg(self->stream, str_write, str);
Py_DECREF(str);
if (wr == NULL)
return -1;
@@ -1735,32 +1733,38 @@ mbstreamwriter_iwrite(MultibyteStreamWriterObject *self,
/*[clinic input]
_multibytecodec.MultibyteStreamWriter.write
+ cls: defining_class
strobj: object
/
[clinic start generated code]*/
static PyObject *
-_multibytecodec_MultibyteStreamWriter_write(MultibyteStreamWriterObject *self,
- PyObject *strobj)
-/*[clinic end generated code: output=e13ae841c895251e input=551dc4c018c10a2b]*/
+_multibytecodec_MultibyteStreamWriter_write_impl(MultibyteStreamWriterObject *self,
+ PyTypeObject *cls,
+ PyObject *strobj)
+/*[clinic end generated code: output=68ade3aea26410ac input=199f26f68bd8425a]*/
{
- if (mbstreamwriter_iwrite(self, strobj))
+ _multibytecodec_state *state = PyType_GetModuleState(cls);
+ assert(state != NULL);
+ if (mbstreamwriter_iwrite(self, strobj, state->str_write)) {
return NULL;
- else
- Py_RETURN_NONE;
+ }
+ Py_RETURN_NONE;
}
/*[clinic input]
_multibytecodec.MultibyteStreamWriter.writelines
+ cls: defining_class
lines: object
/
[clinic start generated code]*/
static PyObject *
-_multibytecodec_MultibyteStreamWriter_writelines(MultibyteStreamWriterObject *self,
- PyObject *lines)
-/*[clinic end generated code: output=e5c4285ac8e7d522 input=57797fe7008d4e96]*/
+_multibytecodec_MultibyteStreamWriter_writelines_impl(MultibyteStreamWriterObject *self,
+ PyTypeObject *cls,
+ PyObject *lines)
+/*[clinic end generated code: output=b4c99d2cf23ffb88 input=a6d5fe7c74972a34]*/
{
PyObject *strobj;
int i, r;
@@ -1771,13 +1775,15 @@ _multibytecodec_MultibyteStreamWriter_writelines(MultibyteStreamWriterObject *se
return NULL;
}
+ _multibytecodec_state *state = PyType_GetModuleState(cls);
+ assert(state != NULL);
for (i = 0; i < PySequence_Length(lines); i++) {
/* length can be changed even within this loop */
strobj = PySequence_GetItem(lines, i);
if (strobj == NULL)
return NULL;
- r = mbstreamwriter_iwrite(self, strobj);
+ r = mbstreamwriter_iwrite(self, strobj, state->str_write);
Py_DECREF(strobj);
if (r == -1)
return NULL;
@@ -1791,11 +1797,16 @@ _multibytecodec_MultibyteStreamWriter_writelines(MultibyteStreamWriterObject *se
/*[clinic input]
_multibytecodec.MultibyteStreamWriter.reset
+
+ cls: defining_class
+ /
+
[clinic start generated code]*/
static PyObject *
-_multibytecodec_MultibyteStreamWriter_reset_impl(MultibyteStreamWriterObject *self)
-/*[clinic end generated code: output=8f54a4d9b03db5ff input=b56dbcbaf35cc10c]*/
+_multibytecodec_MultibyteStreamWriter_reset_impl(MultibyteStreamWriterObject *self,
+ PyTypeObject *cls)
+/*[clinic end generated code: output=32ef224c2a38aa3d input=28af6a9cd38d1979]*/
{
PyObject *pwrt;
@@ -1814,10 +1825,14 @@ _multibytecodec_MultibyteStreamWriter_reset_impl(MultibyteStreamWriterObject *se
return NULL;
assert(PyBytes_Check(pwrt));
+
+ _multibytecodec_state *state = PyType_GetModuleState(cls);
+ assert(state != NULL);
+
if (PyBytes_Size(pwrt) > 0) {
PyObject *wr;
- wr = _PyObject_CallMethodIdOneArg(self->stream, &PyId_write, pwrt);
+ wr = _PyObject_CallMethodOneArg(self->stream, state->str_write, pwrt);
if (wr == NULL) {
Py_DECREF(pwrt);
return NULL;
@@ -1989,6 +2004,7 @@ _multibytecodec_clear(PyObject *mod)
Py_CLEAR(state->decoder_type);
Py_CLEAR(state->reader_type);
Py_CLEAR(state->writer_type);
+ Py_CLEAR(state->str_write);
return 0;
}
@@ -2017,6 +2033,10 @@ static int
_multibytecodec_exec(PyObject *mod)
{
_multibytecodec_state *state = _multibytecodec_get_state(mod);
+ state->str_write = PyUnicode_InternFromString("write");
+ if (state->str_write == NULL) {
+ return -1;
+ }
CREATE_TYPE(mod, state->multibytecodec_type, &multibytecodec_spec);
CREATE_TYPE(mod, state->encoder_type, &encoder_spec);
CREATE_TYPE(mod, state->decoder_type, &decoder_spec);
1
0
01 Mar '22
https://github.com/python/cpython/commit/c60e6b6ad7aaf9c72035ff9fb1575e2710…
commit: c60e6b6ad7aaf9c72035ff9fb1575e2710aeb4b4
branch: main
author: Mark Dickinson <mdickinson(a)enthought.com>
committer: markshannon <mark(a)hotpy.org>
date: 2022-03-01T14:20:52Z
summary:
bpo-46311: Clean up PyLong_FromLong and PyLong_FromLongLong (GH-30496)
files:
A Misc/NEWS.d/next/Core and Builtins/2022-01-09-11-59-04.bpo-30496.KvuuGT.rst
M Objects/longobject.c
diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-01-09-11-59-04.bpo-30496.KvuuGT.rst b/Misc/NEWS.d/next/Core and Builtins/2022-01-09-11-59-04.bpo-30496.KvuuGT.rst
new file mode 100644
index 0000000000000..cc296841c4a4b
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2022-01-09-11-59-04.bpo-30496.KvuuGT.rst
@@ -0,0 +1,3 @@
+Fixed a minor portability issue in the implementation of
+:c:func:`PyLong_FromLong`, and added a fast path for single-digit integers
+to :c:func:`PyLong_FromLongLong`.
diff --git a/Objects/longobject.c b/Objects/longobject.c
index 3438906d84275..f85ef241a445d 100644
--- a/Objects/longobject.c
+++ b/Objects/longobject.c
@@ -272,44 +272,40 @@ _PyLong_Negate(PyLongObject **x_p)
}
/* Create a new int object from a C long int */
+
PyObject *
PyLong_FromLong(long ival)
{
+ PyLongObject *v;
+ unsigned long abs_ival, t;
+ int ndigits;
+
+ /* Handle small and medium cases. */
if (IS_SMALL_INT(ival)) {
return get_small_int((sdigit)ival);
}
- unsigned long abs_ival;
- int sign;
- if (ival < 0) {
- /* negate: can't write this as abs_ival = -ival since that
- invokes undefined behaviour when ival is LONG_MIN */
- abs_ival = 0U-(twodigits)ival;
- sign = -1;
- }
- else {
- abs_ival = (unsigned long)ival;
- sign = 1;
- }
- /* Fast path for single-digit ints */
- if (!(abs_ival >> PyLong_SHIFT)) {
+ if (-(long)PyLong_MASK <= ival && ival <= (long)PyLong_MASK) {
return _PyLong_FromMedium((sdigit)ival);
}
- /* Must be at least two digits.
- * Do shift in two steps to avoid undefined behavior. */
- unsigned long t = (abs_ival >> PyLong_SHIFT) >> PyLong_SHIFT;
- Py_ssize_t ndigits = 2;
+
+ /* Count digits (at least two - smaller cases were handled above). */
+ abs_ival = ival < 0 ? 0U-(unsigned long)ival : (unsigned long)ival;
+ /* Do shift in two steps to avoid possible undefined behavior. */
+ t = abs_ival >> PyLong_SHIFT >> PyLong_SHIFT;
+ ndigits = 2;
while (t) {
++ndigits;
t >>= PyLong_SHIFT;
}
- PyLongObject *v = _PyLong_New(ndigits);
+
+ /* Construct output value. */
+ v = _PyLong_New(ndigits);
if (v != NULL) {
digit *p = v->ob_digit;
- Py_SET_SIZE(v, ndigits * sign);
+ Py_SET_SIZE(v, ival < 0 ? -ndigits : ndigits);
t = abs_ival;
while (t) {
- *p++ = Py_SAFE_DOWNCAST(
- t & PyLong_MASK, unsigned long, digit);
+ *p++ = (digit)(t & PyLong_MASK);
t >>= PyLong_SHIFT;
}
}
@@ -1105,38 +1101,32 @@ PyObject *
PyLong_FromLongLong(long long ival)
{
PyLongObject *v;
- unsigned long long abs_ival;
- unsigned long long t; /* unsigned so >> doesn't propagate sign bit */
- int ndigits = 0;
- int negative = 0;
+ unsigned long long abs_ival, t;
+ int ndigits;
+ /* Handle small and medium cases. */
if (IS_SMALL_INT(ival)) {
return get_small_int((sdigit)ival);
}
-
- if (ival < 0) {
- /* avoid signed overflow on negation; see comments
- in PyLong_FromLong above. */
- abs_ival = (unsigned long long)(-1-ival) + 1;
- negative = 1;
- }
- else {
- abs_ival = (unsigned long long)ival;
+ if (-(long long)PyLong_MASK <= ival && ival <= (long long)PyLong_MASK) {
+ return _PyLong_FromMedium((sdigit)ival);
}
- /* Count the number of Python digits.
- We used to pick 5 ("big enough for anything"), but that's a
- waste of time and space given that 5*15 = 75 bits are rarely
- needed. */
- t = abs_ival;
+ /* Count digits (at least two - smaller cases were handled above). */
+ abs_ival = ival < 0 ? 0U-(unsigned long long)ival : (unsigned long long)ival;
+ /* Do shift in two steps to avoid possible undefined behavior. */
+ t = abs_ival >> PyLong_SHIFT >> PyLong_SHIFT;
+ ndigits = 2;
while (t) {
++ndigits;
t >>= PyLong_SHIFT;
}
+
+ /* Construct output value. */
v = _PyLong_New(ndigits);
if (v != NULL) {
digit *p = v->ob_digit;
- Py_SET_SIZE(v, negative ? -ndigits : ndigits);
+ Py_SET_SIZE(v, ival < 0 ? -ndigits : ndigits);
t = abs_ival;
while (t) {
*p++ = (digit)(t & PyLong_MASK);
1
0
https://github.com/python/cpython/commit/7820a5897e7762df23bff1cbe749652130…
commit: 7820a5897e7762df23bff1cbe749652130654a08
branch: main
author: Brandt Bucher <brandtbucher(a)microsoft.com>
committer: markshannon <mark(a)hotpy.org>
date: 2022-03-01T13:53:13Z
summary:
bpo-46841: Use inline caching for `COMPARE_OP` (GH-31622)
files:
A Misc/NEWS.d/next/Core and Builtins/2022-02-28-12-01-04.bpo-46841.r60AMJ.rst
M Include/internal/pycore_code.h
M Include/opcode.h
M Lib/importlib/_bootstrap_external.py
M Lib/opcode.py
M Lib/test/test_compile.py
M Lib/test/test_dis.py
M Python/ceval.c
M Python/specialize.c
diff --git a/Include/internal/pycore_code.h b/Include/internal/pycore_code.h
index dfa15b8cd61e4..47c1998c88d21 100644
--- a/Include/internal/pycore_code.h
+++ b/Include/internal/pycore_code.h
@@ -77,13 +77,20 @@ typedef struct {
} _PyBinaryOpCache;
#define INLINE_CACHE_ENTRIES_BINARY_OP CACHE_ENTRIES(_PyBinaryOpCache)
+
typedef struct {
_Py_CODEUNIT counter;
} _PyUnpackSequenceCache;
-
#define INLINE_CACHE_ENTRIES_UNPACK_SEQUENCE \
- (sizeof(_PyUnpackSequenceCache) / sizeof(_Py_CODEUNIT))
+ CACHE_ENTRIES(_PyUnpackSequenceCache)
+
+typedef struct {
+ _Py_CODEUNIT counter;
+ _Py_CODEUNIT mask;
+} _PyCompareOpCache;
+
+#define INLINE_CACHE_ENTRIES_COMPARE_OP CACHE_ENTRIES(_PyCompareOpCache)
/* Maximum size of code to quicken, in code units. */
#define MAX_SIZE_TO_QUICKEN 5000
@@ -323,8 +330,9 @@ extern int _Py_Specialize_Call(PyObject *callable, _Py_CODEUNIT *instr, int narg
extern int _Py_Specialize_Precall(PyObject *callable, _Py_CODEUNIT *instr, int nargs,
PyObject *kwnames, SpecializedCacheEntry *cache, PyObject *builtins);
extern void _Py_Specialize_BinaryOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr,
- int oparg);
-extern void _Py_Specialize_CompareOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr, SpecializedCacheEntry *cache);
+ int oparg);
+extern void _Py_Specialize_CompareOp(PyObject *lhs, PyObject *rhs,
+ _Py_CODEUNIT *instr, int oparg);
extern void _Py_Specialize_UnpackSequence(PyObject *seq, _Py_CODEUNIT *instr,
int oparg);
diff --git a/Include/opcode.h b/Include/opcode.h
index 99480def30da5..ba85b7ff75fcd 100644
--- a/Include/opcode.h
+++ b/Include/opcode.h
@@ -212,6 +212,7 @@ static const uint32_t _PyOpcode_Jump[8] = {
const uint8_t _PyOpcode_InlineCacheEntries[256] = {
[UNPACK_SEQUENCE] = 1,
+ [COMPARE_OP] = 2,
[LOAD_GLOBAL] = 5,
[BINARY_OP] = 1,
};
diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py
index f051dfe9492f5..c69c0c73e7a27 100644
--- a/Lib/importlib/_bootstrap_external.py
+++ b/Lib/importlib/_bootstrap_external.py
@@ -389,6 +389,7 @@ def _write_atomic(path, data, mode=0o666):
# Python 3.11a5 3480 (New CALL opcodes, second iteration)
# Python 3.11a5 3481 (Use inline cache for BINARY_OP)
# Python 3.11a5 3482 (Use inline caching for UNPACK_SEQUENCE and LOAD_GLOBAL)
+# Python 3.11a5 3483 (Use inline caching for COMPARE_OP)
# Python 3.12 will start with magic number 3500
@@ -403,7 +404,7 @@ def _write_atomic(path, data, mode=0o666):
# Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array
# in PC/launcher.c must also be updated.
-MAGIC_NUMBER = (3482).to_bytes(2, 'little') + b'\r\n'
+MAGIC_NUMBER = (3483).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 fb2d24fd1f007..dc45cff3017a6 100644
--- a/Lib/opcode.py
+++ b/Lib/opcode.py
@@ -125,7 +125,7 @@ def jabs_op(name, op, entries=0):
def_op('BUILD_SET', 104) # Number of set items
def_op('BUILD_MAP', 105) # Number of dict entries
name_op('LOAD_ATTR', 106) # Index in name list
-def_op('COMPARE_OP', 107) # Comparison operator
+def_op('COMPARE_OP', 107, 2) # Comparison operator
hascompare.append(107)
name_op('IMPORT_NAME', 108) # Index in name list
name_op('IMPORT_FROM', 109) # Index in name list
diff --git a/Lib/test/test_compile.py b/Lib/test/test_compile.py
index 5268192b7cd97..79046b8615e3e 100644
--- a/Lib/test/test_compile.py
+++ b/Lib/test/test_compile.py
@@ -1002,7 +1002,9 @@ def if_else_break():
'JUMP_FORWARD',
)
- for line, instr in enumerate(dis.Bytecode(if_else_break)):
+ for line, instr in enumerate(
+ dis.Bytecode(if_else_break, show_caches=True)
+ ):
if instr.opname == 'JUMP_FORWARD':
self.assertNotEqual(instr.arg, 0)
elif instr.opname in HANDLED_JUMPS:
diff --git a/Lib/test/test_dis.py b/Lib/test/test_dis.py
index a13e0f6edb874..8de2ed09e8352 100644
--- a/Lib/test/test_dis.py
+++ b/Lib/test/test_dis.py
@@ -1223,7 +1223,7 @@ def _prepare_test_cases():
Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=18, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=20, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='GET_ITER', opcode=68, arg=None, argval=None, argrepr='', offset=22, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='FOR_ITER', opcode=93, arg=24, argval=74, argrepr='to 74', offset=24, starts_line=None, is_jump_target=True, positions=None),
+ Instruction(opname='FOR_ITER', opcode=93, arg=28, argval=82, argrepr='to 82', offset=24, starts_line=None, is_jump_target=True, positions=None),
Instruction(opname='STORE_FAST', opcode=125, arg=0, argval='i', argrepr='i', offset=26, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='PUSH_NULL', opcode=2, arg=None, argval=None, argrepr='', offset=28, starts_line=4, is_jump_target=False, positions=None),
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=30, starts_line=None, is_jump_target=False, positions=None),
@@ -1234,128 +1234,128 @@ def _prepare_test_cases():
Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=50, starts_line=5, is_jump_target=False, positions=None),
Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval=4, argrepr='4', offset=52, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='COMPARE_OP', opcode=107, arg=0, argval='<', argrepr='<', offset=54, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=30, argval=60, argrepr='to 60', offset=56, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='JUMP_ABSOLUTE', opcode=113, arg=12, argval=24, argrepr='to 24', offset=58, starts_line=6, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=60, starts_line=7, is_jump_target=True, positions=None),
- Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=6, argrepr='6', offset=62, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='COMPARE_OP', opcode=107, arg=4, argval='>', argrepr='>', offset=64, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=36, argval=72, argrepr='to 72', offset=66, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=68, starts_line=8, is_jump_target=False, positions=None),
- Instruction(opname='JUMP_FORWARD', opcode=110, arg=12, argval=96, argrepr='to 96', offset=70, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='JUMP_ABSOLUTE', opcode=113, arg=12, argval=24, argrepr='to 24', offset=72, starts_line=7, is_jump_target=True, positions=None),
- Instruction(opname='PUSH_NULL', opcode=2, arg=None, argval=None, argrepr='', offset=74, starts_line=10, is_jump_target=True, positions=None),
- Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=76, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_CONST', opcode=100, arg=4, argval='I can haz else clause?', argrepr="'I can haz else clause?'", offset=88, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=90, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=92, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=94, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=96, starts_line=11, is_jump_target=True, positions=None),
- Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=78, argval=156, argrepr='to 156', offset=98, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='PUSH_NULL', opcode=2, arg=None, argval=None, argrepr='', offset=100, starts_line=12, is_jump_target=True, positions=None),
- Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=102, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=114, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=116, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=118, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=120, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=122, starts_line=13, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=124, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='BINARY_OP', opcode=122, arg=23, argval=23, argrepr='-=', offset=126, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='STORE_FAST', opcode=125, arg=0, argval='i', argrepr='i', offset=130, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=132, starts_line=14, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=6, argrepr='6', offset=134, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='COMPARE_OP', opcode=107, arg=4, argval='>', argrepr='>', offset=136, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=71, argval=142, argrepr='to 142', offset=138, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='JUMP_ABSOLUTE', opcode=113, arg=48, argval=96, argrepr='to 96', offset=140, starts_line=15, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=142, starts_line=16, is_jump_target=True, positions=None),
- Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval=4, argrepr='4', offset=144, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='COMPARE_OP', opcode=107, arg=0, argval='<', argrepr='<', offset=146, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=76, argval=152, argrepr='to 152', offset=148, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='JUMP_FORWARD', opcode=110, arg=13, argval=178, argrepr='to 178', offset=150, starts_line=17, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=152, starts_line=11, is_jump_target=True, positions=None),
- Instruction(opname='POP_JUMP_IF_TRUE', opcode=115, arg=50, argval=100, argrepr='to 100', offset=154, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='PUSH_NULL', opcode=2, arg=None, argval=None, argrepr='', offset=156, starts_line=19, is_jump_target=True, positions=None),
- Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=158, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_CONST', opcode=100, arg=6, argval='Who let lolcatz into this test suite?', argrepr="'Who let lolcatz into this test suite?'", offset=170, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=172, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=174, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=176, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='NOP', opcode=9, arg=None, argval=None, argrepr='', offset=178, starts_line=20, is_jump_target=True, positions=None),
- Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=180, starts_line=21, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_CONST', opcode=100, arg=7, argval=0, argrepr='0', offset=182, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='BINARY_OP', opcode=122, arg=11, argval=11, argrepr='/', offset=184, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=188, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=190, starts_line=25, is_jump_target=False, positions=None),
- Instruction(opname='BEFORE_WITH', opcode=53, arg=None, argval=None, argrepr='', offset=192, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='STORE_FAST', opcode=125, arg=1, argval='dodgy', argrepr='dodgy', offset=194, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='PUSH_NULL', opcode=2, arg=None, argval=None, argrepr='', offset=196, starts_line=26, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=198, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_CONST', opcode=100, arg=8, argval='Never reach this', argrepr="'Never reach this'", offset=210, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=212, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=214, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=216, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=218, starts_line=25, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=220, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=222, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='PRECALL', opcode=166, arg=2, argval=2, argrepr='', offset=224, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='CALL', opcode=171, arg=2, argval=2, argrepr='', offset=226, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=228, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='JUMP_FORWARD', opcode=110, arg=11, argval=254, argrepr='to 254', offset=230, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=232, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='WITH_EXCEPT_START', opcode=49, arg=None, argval=None, argrepr='', offset=234, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_JUMP_IF_TRUE', opcode=115, arg=123, argval=246, argrepr='to 246', offset=236, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='RERAISE', opcode=119, arg=2, argval=2, argrepr='', offset=238, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='COPY', opcode=120, arg=3, argval=3, argrepr='', offset=240, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=242, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='RERAISE', opcode=119, arg=1, argval=1, argrepr='', offset=244, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=246, starts_line=None, is_jump_target=True, positions=None),
- Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=248, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=250, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=252, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='JUMP_FORWARD', opcode=110, arg=26, argval=308, argrepr='to 308', offset=254, starts_line=None, is_jump_target=True, positions=None),
- Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=256, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_GLOBAL', opcode=116, arg=2, argval='ZeroDivisionError', argrepr='ZeroDivisionError', offset=258, starts_line=22, is_jump_target=False, positions=None),
- Instruction(opname='JUMP_IF_NOT_EXC_MATCH', opcode=121, arg=150, argval=300, argrepr='to 300', offset=270, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=272, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='PUSH_NULL', opcode=2, arg=None, argval=None, argrepr='', offset=274, starts_line=23, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=276, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_CONST', opcode=100, arg=9, argval='Here we go, here we go, here we go...', argrepr="'Here we go, here we go, here we go...'", offset=288, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=290, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=292, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=294, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=296, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='JUMP_FORWARD', opcode=110, arg=17, argval=334, argrepr='to 334', offset=298, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=300, starts_line=22, is_jump_target=True, positions=None),
- Instruction(opname='COPY', opcode=120, arg=3, argval=3, argrepr='', offset=302, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=304, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='RERAISE', opcode=119, arg=1, argval=1, argrepr='', offset=306, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='PUSH_NULL', opcode=2, arg=None, argval=None, argrepr='', offset=308, starts_line=28, is_jump_target=True, positions=None),
- Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=310, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=322, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=324, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=326, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=328, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=330, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=332, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='NOP', opcode=9, arg=None, argval=None, argrepr='', offset=334, starts_line=23, is_jump_target=True, positions=None),
- Instruction(opname='PUSH_NULL', opcode=2, arg=None, argval=None, argrepr='', offset=336, starts_line=28, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=338, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=350, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=352, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=354, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=356, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=358, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=360, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=362, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='PUSH_NULL', opcode=2, arg=None, argval=None, argrepr='', offset=364, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=366, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=378, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=380, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=382, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=384, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=386, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='COPY', opcode=120, arg=3, argval=3, argrepr='', offset=388, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=390, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='RERAISE', opcode=119, arg=1, argval=1, argrepr='', offset=392, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=32, argval=64, argrepr='to 64', offset=60, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='JUMP_ABSOLUTE', opcode=113, arg=12, argval=24, argrepr='to 24', offset=62, starts_line=6, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=64, starts_line=7, is_jump_target=True, positions=None),
+ Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=6, argrepr='6', offset=66, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='COMPARE_OP', opcode=107, arg=4, argval='>', argrepr='>', offset=68, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=40, argval=80, argrepr='to 80', offset=74, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=76, starts_line=8, is_jump_target=False, positions=None),
+ Instruction(opname='JUMP_FORWARD', opcode=110, arg=12, argval=104, argrepr='to 104', offset=78, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='JUMP_ABSOLUTE', opcode=113, arg=12, argval=24, argrepr='to 24', offset=80, starts_line=7, is_jump_target=True, positions=None),
+ Instruction(opname='PUSH_NULL', opcode=2, arg=None, argval=None, argrepr='', offset=82, starts_line=10, is_jump_target=True, positions=None),
+ Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=84, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_CONST', opcode=100, arg=4, argval='I can haz else clause?', argrepr="'I can haz else clause?'", offset=96, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=98, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=100, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=102, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=104, starts_line=11, is_jump_target=True, positions=None),
+ Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=86, argval=172, argrepr='to 172', offset=106, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='PUSH_NULL', opcode=2, arg=None, argval=None, argrepr='', offset=108, starts_line=12, is_jump_target=True, positions=None),
+ Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=110, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=122, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=124, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=126, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=128, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=130, starts_line=13, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=132, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='BINARY_OP', opcode=122, arg=23, argval=23, argrepr='-=', offset=134, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='STORE_FAST', opcode=125, arg=0, argval='i', argrepr='i', offset=138, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=140, starts_line=14, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=6, argrepr='6', offset=142, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='COMPARE_OP', opcode=107, arg=4, argval='>', argrepr='>', offset=144, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=77, argval=154, argrepr='to 154', offset=150, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='JUMP_ABSOLUTE', opcode=113, arg=52, argval=104, argrepr='to 104', offset=152, starts_line=15, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=154, starts_line=16, is_jump_target=True, positions=None),
+ Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval=4, argrepr='4', offset=156, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='COMPARE_OP', opcode=107, arg=0, argval='<', argrepr='<', offset=158, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=84, argval=168, argrepr='to 168', offset=164, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='JUMP_FORWARD', opcode=110, arg=13, argval=194, argrepr='to 194', offset=166, starts_line=17, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=168, starts_line=11, is_jump_target=True, positions=None),
+ Instruction(opname='POP_JUMP_IF_TRUE', opcode=115, arg=54, argval=108, argrepr='to 108', offset=170, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='PUSH_NULL', opcode=2, arg=None, argval=None, argrepr='', offset=172, starts_line=19, is_jump_target=True, positions=None),
+ Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=174, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_CONST', opcode=100, arg=6, argval='Who let lolcatz into this test suite?', argrepr="'Who let lolcatz into this test suite?'", offset=186, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=188, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=190, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=192, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='NOP', opcode=9, arg=None, argval=None, argrepr='', offset=194, starts_line=20, is_jump_target=True, positions=None),
+ Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=196, starts_line=21, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_CONST', opcode=100, arg=7, argval=0, argrepr='0', offset=198, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='BINARY_OP', opcode=122, arg=11, argval=11, argrepr='/', offset=200, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=204, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=206, starts_line=25, is_jump_target=False, positions=None),
+ Instruction(opname='BEFORE_WITH', opcode=53, arg=None, argval=None, argrepr='', offset=208, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='STORE_FAST', opcode=125, arg=1, argval='dodgy', argrepr='dodgy', offset=210, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='PUSH_NULL', opcode=2, arg=None, argval=None, argrepr='', offset=212, starts_line=26, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=214, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_CONST', opcode=100, arg=8, argval='Never reach this', argrepr="'Never reach this'", offset=226, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=228, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=230, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=232, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=234, starts_line=25, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=236, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=238, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='PRECALL', opcode=166, arg=2, argval=2, argrepr='', offset=240, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='CALL', opcode=171, arg=2, argval=2, argrepr='', offset=242, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=244, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='JUMP_FORWARD', opcode=110, arg=11, argval=270, argrepr='to 270', offset=246, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=248, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='WITH_EXCEPT_START', opcode=49, arg=None, argval=None, argrepr='', offset=250, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_JUMP_IF_TRUE', opcode=115, arg=131, argval=262, argrepr='to 262', offset=252, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='RERAISE', opcode=119, arg=2, argval=2, argrepr='', offset=254, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='COPY', opcode=120, arg=3, argval=3, argrepr='', offset=256, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=258, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='RERAISE', opcode=119, arg=1, argval=1, argrepr='', offset=260, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=262, starts_line=None, is_jump_target=True, positions=None),
+ Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=264, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=266, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=268, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='JUMP_FORWARD', opcode=110, arg=26, argval=324, argrepr='to 324', offset=270, starts_line=None, is_jump_target=True, positions=None),
+ Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=272, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_GLOBAL', opcode=116, arg=2, argval='ZeroDivisionError', argrepr='ZeroDivisionError', offset=274, starts_line=22, is_jump_target=False, positions=None),
+ Instruction(opname='JUMP_IF_NOT_EXC_MATCH', opcode=121, arg=158, argval=316, argrepr='to 316', offset=286, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=288, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='PUSH_NULL', opcode=2, arg=None, argval=None, argrepr='', offset=290, starts_line=23, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=292, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_CONST', opcode=100, arg=9, argval='Here we go, here we go, here we go...', argrepr="'Here we go, here we go, here we go...'", offset=304, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=306, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=308, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=310, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=312, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='JUMP_FORWARD', opcode=110, arg=17, argval=350, argrepr='to 350', offset=314, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=316, starts_line=22, is_jump_target=True, positions=None),
+ Instruction(opname='COPY', opcode=120, arg=3, argval=3, argrepr='', offset=318, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=320, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='RERAISE', opcode=119, arg=1, argval=1, argrepr='', offset=322, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='PUSH_NULL', opcode=2, arg=None, argval=None, argrepr='', offset=324, starts_line=28, is_jump_target=True, positions=None),
+ Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=326, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=338, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=340, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=342, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=344, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=346, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=348, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='NOP', opcode=9, arg=None, argval=None, argrepr='', offset=350, starts_line=23, is_jump_target=True, positions=None),
+ Instruction(opname='PUSH_NULL', opcode=2, arg=None, argval=None, argrepr='', offset=352, starts_line=28, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=354, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=366, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=368, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=370, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=372, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=374, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=376, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=378, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='PUSH_NULL', opcode=2, arg=None, argval=None, argrepr='', offset=380, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=382, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=394, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=396, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=398, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=400, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=402, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='COPY', opcode=120, arg=3, argval=3, argrepr='', offset=404, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=406, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='RERAISE', opcode=119, arg=1, argval=1, argrepr='', offset=408, starts_line=None, is_jump_target=False, positions=None),
]
# One last piece of inspect fodder to check the default line number handling
diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-02-28-12-01-04.bpo-46841.r60AMJ.rst b/Misc/NEWS.d/next/Core and Builtins/2022-02-28-12-01-04.bpo-46841.r60AMJ.rst
new file mode 100644
index 0000000000000..bc885be5174e8
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2022-02-28-12-01-04.bpo-46841.r60AMJ.rst
@@ -0,0 +1 @@
+Use inline caching for :opcode:`COMPARE_OP`.
diff --git a/Python/ceval.c b/Python/ceval.c
index 13866ba355e97..0f57e7dc94a04 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -3671,8 +3671,10 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
SET_TOP(res);
Py_DECREF(left);
Py_DECREF(right);
- if (res == NULL)
+ if (res == NULL) {
goto error;
+ }
+ JUMPBY(INLINE_CACHE_ENTRIES_COMPARE_OP);
PREDICT(POP_JUMP_IF_FALSE);
PREDICT(POP_JUMP_IF_TRUE);
DISPATCH();
@@ -3680,18 +3682,17 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
TARGET(COMPARE_OP_ADAPTIVE) {
assert(cframe.use_tracing == 0);
- SpecializedCacheEntry *cache = GET_CACHE();
- if (cache->adaptive.counter == 0) {
+ _PyCompareOpCache *cache = (_PyCompareOpCache *)next_instr;
+ if (cache->counter == 0) {
PyObject *right = TOP();
PyObject *left = SECOND();
next_instr--;
- _Py_Specialize_CompareOp(left, right, next_instr, cache);
+ _Py_Specialize_CompareOp(left, right, next_instr, oparg);
DISPATCH();
}
else {
STAT_INC(COMPARE_OP, deferred);
- cache->adaptive.counter--;
- oparg = cache->adaptive.original_oparg;
+ cache->counter--;
JUMP_TO_INSTRUCTION(COMPARE_OP);
}
}
@@ -3699,8 +3700,8 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
TARGET(COMPARE_OP_FLOAT_JUMP) {
assert(cframe.use_tracing == 0);
// Combined: COMPARE_OP (float ? float) + POP_JUMP_IF_(true/false)
- SpecializedCacheEntry *caches = GET_CACHE();
- int when_to_jump_mask = caches[0].adaptive.index;
+ _PyCompareOpCache *cache = (_PyCompareOpCache *)next_instr;
+ int when_to_jump_mask = cache->mask;
PyObject *right = TOP();
PyObject *left = SECOND();
DEOPT_IF(!PyFloat_CheckExact(left), COMPARE_OP);
@@ -3711,6 +3712,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
DEOPT_IF(isnan(dleft), COMPARE_OP);
DEOPT_IF(isnan(dright), COMPARE_OP);
STAT_INC(COMPARE_OP, hit);
+ JUMPBY(INLINE_CACHE_ENTRIES_COMPARE_OP);
NEXTOPARG();
STACK_SHRINK(2);
Py_DECREF(left);
@@ -3731,8 +3733,8 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
TARGET(COMPARE_OP_INT_JUMP) {
assert(cframe.use_tracing == 0);
// Combined: COMPARE_OP (int ? int) + POP_JUMP_IF_(true/false)
- SpecializedCacheEntry *caches = GET_CACHE();
- int when_to_jump_mask = caches[0].adaptive.index;
+ _PyCompareOpCache *cache = (_PyCompareOpCache *)next_instr;
+ int when_to_jump_mask = cache->mask;
PyObject *right = TOP();
PyObject *left = SECOND();
DEOPT_IF(!PyLong_CheckExact(left), COMPARE_OP);
@@ -3744,6 +3746,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
Py_ssize_t ileft = Py_SIZE(left) * ((PyLongObject *)left)->ob_digit[0];
Py_ssize_t iright = Py_SIZE(right) * ((PyLongObject *)right)->ob_digit[0];
int sign = (ileft > iright) - (ileft < iright);
+ JUMPBY(INLINE_CACHE_ENTRIES_COMPARE_OP);
NEXTOPARG();
STACK_SHRINK(2);
Py_DECREF(left);
@@ -3764,8 +3767,8 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
TARGET(COMPARE_OP_STR_JUMP) {
assert(cframe.use_tracing == 0);
// Combined: COMPARE_OP (str == str or str != str) + POP_JUMP_IF_(true/false)
- SpecializedCacheEntry *caches = GET_CACHE();
- int invert = caches[0].adaptive.index;
+ _PyCompareOpCache *cache = (_PyCompareOpCache *)next_instr;
+ int invert = cache->mask;
PyObject *right = TOP();
PyObject *left = SECOND();
DEOPT_IF(!PyUnicode_CheckExact(left), COMPARE_OP);
@@ -3775,8 +3778,8 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
if (res < 0) {
goto error;
}
- assert(caches[0].adaptive.original_oparg == Py_EQ ||
- caches[0].adaptive.original_oparg == Py_NE);
+ assert(oparg == Py_EQ || oparg == Py_NE);
+ JUMPBY(INLINE_CACHE_ENTRIES_COMPARE_OP);
NEXTOPARG();
assert(opcode == POP_JUMP_IF_TRUE || opcode == POP_JUMP_IF_FALSE);
STACK_SHRINK(2);
@@ -5601,7 +5604,7 @@ MISS_WITH_CACHE(LOAD_METHOD)
MISS_WITH_CACHE(PRECALL)
MISS_WITH_CACHE(CALL)
MISS_WITH_INLINE_CACHE(BINARY_OP)
-MISS_WITH_CACHE(COMPARE_OP)
+MISS_WITH_INLINE_CACHE(COMPARE_OP)
MISS_WITH_CACHE(BINARY_SUBSCR)
MISS_WITH_INLINE_CACHE(UNPACK_SEQUENCE)
MISS_WITH_OPARG_COUNTER(STORE_SUBSCR)
diff --git a/Python/specialize.c b/Python/specialize.c
index 38907f675e809..925edf3f88d5f 100644
--- a/Python/specialize.c
+++ b/Python/specialize.c
@@ -65,7 +65,6 @@ static uint8_t cache_requirements[256] = {
[CALL] = 2, /* _PyAdaptiveEntry and _PyObjectCache/_PyCallCache */
[PRECALL] = 2, /* _PyAdaptiveEntry and _PyObjectCache/_PyCallCache */
[STORE_ATTR] = 1, // _PyAdaptiveEntry
- [COMPARE_OP] = 1, /* _PyAdaptiveEntry */
};
Py_ssize_t _Py_QuickenedCount = 0;
@@ -2057,26 +2056,27 @@ static int compare_masks[] = {
};
void
-_Py_Specialize_CompareOp(PyObject *lhs, PyObject *rhs,
- _Py_CODEUNIT *instr, SpecializedCacheEntry *cache)
+_Py_Specialize_CompareOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr,
+ int oparg)
{
- _PyAdaptiveEntry *adaptive = &cache->adaptive;
- int op = adaptive->original_oparg;
- int next_opcode = _Py_OPCODE(instr[1]);
+ assert(_PyOpcode_InlineCacheEntries[COMPARE_OP] ==
+ INLINE_CACHE_ENTRIES_COMPARE_OP);
+ _PyCompareOpCache *cache = (_PyCompareOpCache *)(instr + 1);
+ int next_opcode = _Py_OPCODE(instr[INLINE_CACHE_ENTRIES_COMPARE_OP + 1]);
if (next_opcode != POP_JUMP_IF_FALSE && next_opcode != POP_JUMP_IF_TRUE) {
// Can't ever combine, so don't don't bother being adaptive (unless
// we're collecting stats, where it's more important to get accurate hit
// counts for the unadaptive version and each of the different failure
// types):
#ifndef Py_STATS
- *instr = _Py_MAKECODEUNIT(COMPARE_OP, adaptive->original_oparg);
+ *instr = _Py_MAKECODEUNIT(COMPARE_OP, oparg);
return;
#endif
SPECIALIZATION_FAIL(COMPARE_OP, SPEC_FAIL_COMPARE_OP_NOT_FOLLOWED_BY_COND_JUMP);
goto failure;
}
- assert(op <= Py_GE);
- int when_to_jump_mask = compare_masks[op];
+ assert(oparg <= Py_GE);
+ int when_to_jump_mask = compare_masks[oparg];
if (next_opcode == POP_JUMP_IF_FALSE) {
when_to_jump_mask = (1 | 2 | 4) & ~when_to_jump_mask;
}
@@ -2085,14 +2085,14 @@ _Py_Specialize_CompareOp(PyObject *lhs, PyObject *rhs,
goto failure;
}
if (PyFloat_CheckExact(lhs)) {
- *instr = _Py_MAKECODEUNIT(COMPARE_OP_FLOAT_JUMP, _Py_OPARG(*instr));
- adaptive->index = when_to_jump_mask;
+ *instr = _Py_MAKECODEUNIT(COMPARE_OP_FLOAT_JUMP, oparg);
+ cache->mask = when_to_jump_mask;
goto success;
}
if (PyLong_CheckExact(lhs)) {
if (Py_ABS(Py_SIZE(lhs)) <= 1 && Py_ABS(Py_SIZE(rhs)) <= 1) {
- *instr = _Py_MAKECODEUNIT(COMPARE_OP_INT_JUMP, _Py_OPARG(*instr));
- adaptive->index = when_to_jump_mask;
+ *instr = _Py_MAKECODEUNIT(COMPARE_OP_INT_JUMP, oparg);
+ cache->mask = when_to_jump_mask;
goto success;
}
else {
@@ -2101,24 +2101,24 @@ _Py_Specialize_CompareOp(PyObject *lhs, PyObject *rhs,
}
}
if (PyUnicode_CheckExact(lhs)) {
- if (op != Py_EQ && op != Py_NE) {
+ if (oparg != Py_EQ && oparg != Py_NE) {
SPECIALIZATION_FAIL(COMPARE_OP, SPEC_FAIL_COMPARE_OP_STRING);
goto failure;
}
else {
- *instr = _Py_MAKECODEUNIT(COMPARE_OP_STR_JUMP, _Py_OPARG(*instr));
- adaptive->index = (when_to_jump_mask & 2) == 0;
+ *instr = _Py_MAKECODEUNIT(COMPARE_OP_STR_JUMP, oparg);
+ cache->mask = (when_to_jump_mask & 2) == 0;
goto success;
}
}
SPECIALIZATION_FAIL(COMPARE_OP, compare_op_fail_kind(lhs, rhs));
failure:
STAT_INC(COMPARE_OP, failure);
- cache_backoff(adaptive);
+ cache->counter = ADAPTIVE_CACHE_BACKOFF;
return;
success:
STAT_INC(COMPARE_OP, success);
- adaptive->counter = initial_counter_value();
+ cache->counter = initial_counter_value();
}
#ifdef Py_STATS
1
0
https://github.com/python/cpython/commit/98e2ee60bd7f66be18fee3f5b9c47c473b…
commit: 98e2ee60bd7f66be18fee3f5b9c47c473bbb160c
branch: 3.10
author: Miss Islington (bot) <31488909+miss-islington(a)users.noreply.github.com>
committer: miss-islington <31488909+miss-islington(a)users.noreply.github.com>
date: 2022-02-28T17:45:26-08:00
summary:
Add missing "to" to two tp_flags notes (GH-31624)
(cherry picked from commit 422fdb37172c145043d4f1276adad43ff375f0d5)
Co-authored-by: Brandt Bucher <brandtbucher(a)microsoft.com>
files:
M Doc/c-api/typeobj.rst
diff --git a/Doc/c-api/typeobj.rst b/Doc/c-api/typeobj.rst
index f0dd3923e8085..93492200ea44e 100644
--- a/Doc/c-api/typeobj.rst
+++ b/Doc/c-api/typeobj.rst
@@ -1232,7 +1232,7 @@ and :c:type:`PyType_Type` effectively act as defaults.)
.. note::
:const:`Py_TPFLAGS_MAPPING` and :const:`Py_TPFLAGS_SEQUENCE` are
- mutually exclusive; it is an error enable both flags simultaneously.
+ mutually exclusive; it is an error to enable both flags simultaneously.
**Inheritance:**
@@ -1254,7 +1254,7 @@ and :c:type:`PyType_Type` effectively act as defaults.)
.. note::
:const:`Py_TPFLAGS_MAPPING` and :const:`Py_TPFLAGS_SEQUENCE` are
- mutually exclusive; it is an error enable both flags simultaneously.
+ mutually exclusive; it is an error to enable both flags simultaneously.
**Inheritance:**
1
0
https://github.com/python/cpython/commit/df9f7597559b6256924fcd3a1c3dc24cd5…
commit: df9f7597559b6256924fcd3a1c3dc24cd5c5edaf
branch: main
author: Inada Naoki <songofacandy(a)gmail.com>
committer: methane <songofacandy(a)gmail.com>
date: 2022-03-01T10:27:20+09:00
summary:
compiler: Merge except_table and cnotab (GH-31614)
files:
M Python/compile.c
diff --git a/Python/compile.c b/Python/compile.c
index ea9c3c8d48269..3609ff8f4fb9e 100644
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -8272,6 +8272,9 @@ assemble(struct compiler *c, int addNone)
if (_PyBytes_Resize(&a.a_except_table, a.a_except_table_off) < 0) {
goto error;
}
+ if (!merge_const_one(c, &a.a_except_table)) {
+ goto error;
+ }
if (!assemble_start_line_range(&a)) {
return 0;
}
@@ -8293,6 +8296,9 @@ assemble(struct compiler *c, int addNone)
if (_PyBytes_Resize(&a.a_cnotab, a.a_cnotab_off) < 0) {
goto error;
}
+ if (!merge_const_one(c, &a.a_cnotab)) {
+ goto error;
+ }
if (_PyBytes_Resize(&a.a_bytecode, a.a_offset * sizeof(_Py_CODEUNIT)) < 0) {
goto error;
}
1
0
https://github.com/python/cpython/commit/422fdb37172c145043d4f1276adad43ff3…
commit: 422fdb37172c145043d4f1276adad43ff375f0d5
branch: main
author: Brandt Bucher <brandtbucher(a)microsoft.com>
committer: brandtbucher <brandtbucher(a)gmail.com>
date: 2022-02-28T17:20:14-08:00
summary:
Add missing "to" to two tp_flags notes (GH-31624)
files:
M Doc/c-api/typeobj.rst
diff --git a/Doc/c-api/typeobj.rst b/Doc/c-api/typeobj.rst
index 3630990368cdf..4a54139c5d498 100644
--- a/Doc/c-api/typeobj.rst
+++ b/Doc/c-api/typeobj.rst
@@ -1233,7 +1233,7 @@ and :c:type:`PyType_Type` effectively act as defaults.)
.. note::
:const:`Py_TPFLAGS_MAPPING` and :const:`Py_TPFLAGS_SEQUENCE` are
- mutually exclusive; it is an error enable both flags simultaneously.
+ mutually exclusive; it is an error to enable both flags simultaneously.
**Inheritance:**
@@ -1255,7 +1255,7 @@ and :c:type:`PyType_Type` effectively act as defaults.)
.. note::
:const:`Py_TPFLAGS_MAPPING` and :const:`Py_TPFLAGS_SEQUENCE` are
- mutually exclusive; it is an error enable both flags simultaneously.
+ mutually exclusive; it is an error to enable both flags simultaneously.
**Inheritance:**
1
0