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
February 2022
- 1 participants
- 473 discussions
28 Feb '22
https://github.com/python/cpython/commit/7d611b4cabaf7925f5f94daddf711d54ae…
commit: 7d611b4cabaf7925f5f94daddf711d54aeae2cf9
branch: main
author: Guido van Rossum <guido(a)python.org>
committer: gvanrossum <gvanrossum(a)gmail.com>
date: 2022-02-28T15:15:56-08:00
summary:
bpo-46771: Remove two controversial lines from Task.cancel() (GH-31623)
Also from the _asyncio C accelerator module,
and adjust one test that the change caused to fail.
For more discussion see the discussion starting here:
https://github.com/python/cpython/pull/31394#issuecomment-1053545331
(Basically, @asvetlov proposed to return False from cancel()
when there is already a pending cancellation, and I went along,
even though it wasn't necessary for the task group implementation,
and @agronholm has come up with a counterexample that fails
because of this change. So now I'm changing it back to the old
semantics (but still bumping the counter) until we can have a
proper discussion about this.)
files:
M Lib/asyncio/tasks.py
M Lib/test/test_asyncio/test_tasks.py
M Modules/_asynciomodule.c
diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py
index 38c23851102a8..059143fb9086f 100644
--- a/Lib/asyncio/tasks.py
+++ b/Lib/asyncio/tasks.py
@@ -205,8 +205,11 @@ def cancel(self, msg=None):
if self.done():
return False
self._num_cancels_requested += 1
- if self._num_cancels_requested > 1:
- return False
+ # These two lines are controversial. See discussion starting at
+ # https://github.com/python/cpython/pull/31394#issuecomment-1053545331
+ # Also remember that this is duplicated in _asynciomodule.c.
+ # if self._num_cancels_requested > 1:
+ # return False
if self._fut_waiter is not None:
if self._fut_waiter.cancel(msg=msg):
# Leave self._fut_waiter; it may be a Task that
diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py
index b30f8f56dfa72..950879204e703 100644
--- a/Lib/test/test_asyncio/test_tasks.py
+++ b/Lib/test/test_asyncio/test_tasks.py
@@ -514,7 +514,11 @@ async def task():
self.assertTrue(t.cancel())
self.assertTrue(t.cancelling())
self.assertIn(" cancelling ", repr(t))
- self.assertFalse(t.cancel())
+
+ # Since we commented out two lines from Task.cancel(),
+ # this t.cancel() call now returns True.
+ # self.assertFalse(t.cancel())
+ self.assertTrue(t.cancel())
with self.assertRaises(asyncio.CancelledError):
loop.run_until_complete(t)
diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c
index 88471239529a5..2a6c0b335ccfb 100644
--- a/Modules/_asynciomodule.c
+++ b/Modules/_asynciomodule.c
@@ -2206,9 +2206,13 @@ _asyncio_Task_cancel_impl(TaskObj *self, PyObject *msg)
}
self->task_num_cancels_requested += 1;
- if (self->task_num_cancels_requested > 1) {
- Py_RETURN_FALSE;
- }
+
+ // These three lines are controversial. See discussion starting at
+ // https://github.com/python/cpython/pull/31394#issuecomment-1053545331
+ // and corresponding code in tasks.py.
+ // if (self->task_num_cancels_requested > 1) {
+ // Py_RETURN_FALSE;
+ // }
if (self->task_fut_waiter) {
PyObject *res;
1
0
bpo-46753: Add the empty tuple to the _PyRuntimeState.global_objects. (gh-31345)
by ericsnowcurrently 28 Feb '22
by ericsnowcurrently 28 Feb '22
28 Feb '22
https://github.com/python/cpython/commit/08deed1af56bec8668c6cb4d5cfd89e393…
commit: 08deed1af56bec8668c6cb4d5cfd89e393e1fe5e
branch: main
author: Eric Snow <ericsnowcurrently(a)gmail.com>
committer: ericsnowcurrently <ericsnowcurrently(a)gmail.com>
date: 2022-02-28T15:15:48-07:00
summary:
bpo-46753: Add the empty tuple to the _PyRuntimeState.global_objects. (gh-31345)
https://bugs.python.org/issue46753
files:
M Include/internal/pycore_gc.h
M Include/internal/pycore_global_objects.h
M Include/internal/pycore_runtime_init.h
M Include/internal/pycore_tuple.h
M Objects/tupleobject.c
M Python/pylifecycle.c
M Tools/scripts/deepfreeze.py
M Tools/scripts/generate_global_objects.py
diff --git a/Include/internal/pycore_gc.h b/Include/internal/pycore_gc.h
index 56a23e9970752..16c1893639f35 100644
--- a/Include/internal/pycore_gc.h
+++ b/Include/internal/pycore_gc.h
@@ -20,6 +20,7 @@ typedef struct {
} PyGC_Head;
#define _Py_AS_GC(o) ((PyGC_Head *)(o)-1)
+#define _PyGC_Head_UNUSED PyGC_Head
/* True if the object is currently tracked by the GC. */
#define _PyObject_GC_IS_TRACKED(o) (_Py_AS_GC(o)->_gc_next != 0)
diff --git a/Include/internal/pycore_global_objects.h b/Include/internal/pycore_global_objects.h
index 2135fa3b5d79a..98673d4efcedc 100644
--- a/Include/internal/pycore_global_objects.h
+++ b/Include/internal/pycore_global_objects.h
@@ -8,6 +8,7 @@ extern "C" {
# error "this header requires Py_BUILD_CORE define"
#endif
+#include "pycore_gc.h" // PyGC_Head
#include "pycore_global_strings.h" // struct _Py_global_strings
@@ -40,6 +41,9 @@ struct _Py_global_objects {
} bytes_characters[256];
struct _Py_global_strings strings;
+
+ _PyGC_Head_UNUSED _tuple_empty_gc_not_used;
+ PyTupleObject tuple_empty;
} singletons;
};
diff --git a/Include/internal/pycore_runtime_init.h b/Include/internal/pycore_runtime_init.h
index 8f62343443351..2f2bc65cd7111 100644
--- a/Include/internal/pycore_runtime_init.h
+++ b/Include/internal/pycore_runtime_init.h
@@ -964,6 +964,10 @@ extern "C" {
INIT_ID(zipimporter), \
}, \
}, \
+ \
+ .tuple_empty = { \
+ .ob_base = _PyVarObject_IMMORTAL_INIT(&PyTuple_Type, 0) \
+ }, \
}, \
}
/* End auto-generated code */
diff --git a/Include/internal/pycore_tuple.h b/Include/internal/pycore_tuple.h
index 624c21caec1cc..1efe4fa2bdef9 100644
--- a/Include/internal/pycore_tuple.h
+++ b/Include/internal/pycore_tuple.h
@@ -20,30 +20,45 @@ extern void _PyTuple_Fini(PyInterpreterState *);
/* other API */
-#ifndef WITH_FREELISTS
-// without freelists
-// for tuples only store empty tuple singleton
-# define PyTuple_MAXSAVESIZE 1
-# define PyTuple_MAXFREELIST 1
-#endif
+// PyTuple_MAXSAVESIZE - largest tuple to save on free list
+// PyTuple_MAXFREELIST - maximum number of tuples of each size to save
-/* Speed optimization to avoid frequent malloc/free of small tuples */
-#ifndef PyTuple_MAXSAVESIZE
- // Largest tuple to save on free list
-# define PyTuple_MAXSAVESIZE 20
-#endif
-#ifndef PyTuple_MAXFREELIST
- // Maximum number of tuples of each size to save
-# define PyTuple_MAXFREELIST 2000
+#if defined(PyTuple_MAXSAVESIZE) && PyTuple_MAXSAVESIZE <= 0
+ // A build indicated that tuple freelists should not be used.
+# define PyTuple_NFREELISTS 0
+# undef PyTuple_MAXSAVESIZE
+# undef PyTuple_MAXFREELIST
+
+#elif !defined(WITH_FREELISTS)
+# define PyTuple_NFREELISTS 0
+# undef PyTuple_MAXSAVESIZE
+# undef PyTuple_MAXFREELIST
+
+#else
+ // We are using a freelist for tuples.
+# ifndef PyTuple_MAXSAVESIZE
+# define PyTuple_MAXSAVESIZE 20
+# endif
+# define PyTuple_NFREELISTS PyTuple_MAXSAVESIZE
+# ifndef PyTuple_MAXFREELIST
+# define PyTuple_MAXFREELIST 2000
+# endif
#endif
struct _Py_tuple_state {
-#if PyTuple_MAXSAVESIZE > 0
- /* Entries 1 up to PyTuple_MAXSAVESIZE are free lists,
- entry 0 is the empty tuple () of which at most one instance
- will be allocated. */
- PyTupleObject *free_list[PyTuple_MAXSAVESIZE];
- int numfree[PyTuple_MAXSAVESIZE];
+#if PyTuple_NFREELISTS > 0
+ /* There is one freelist for each size from 1 to PyTuple_MAXSAVESIZE.
+ The empty tuple is handled separately.
+
+ Each tuple stored in the array is the head of the linked list
+ (and the next available tuple) for that size. The actual tuple
+ object is used as the linked list node, with its first item
+ (ob_item[0]) pointing to the next node (i.e. the previous head).
+ Each linked list is initially NULL. */
+ PyTupleObject *free_list[PyTuple_NFREELISTS];
+ int numfree[PyTuple_NFREELISTS];
+#else
+ char _unused; // Empty structs are not allowed.
#endif
};
diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c
index ec9147cdcfedf..306a9112b0600 100644
--- a/Objects/tupleobject.c
+++ b/Objects/tupleobject.c
@@ -7,7 +7,6 @@
#include "pycore_initconfig.h" // _PyStatus_OK()
#include "pycore_object.h" // _PyObject_GC_TRACK()
#include "pycore_pyerrors.h" // _Py_FatalRefcountError()
-#include "pycore_tuple.h" // struct _Py_tuple_state()
/*[clinic input]
class tuple "PyTupleObject *" "&PyTuple_Type"
@@ -17,31 +16,9 @@ class tuple "PyTupleObject *" "&PyTuple_Type"
#include "clinic/tupleobject.c.h"
-#if PyTuple_MAXSAVESIZE > 0
-static struct _Py_tuple_state *
-get_tuple_state(void)
-{
- PyInterpreterState *interp = _PyInterpreterState_GET();
- return &interp->tuple;
-}
-#endif
-
+static inline PyTupleObject * maybe_freelist_pop(Py_ssize_t);
+static inline int maybe_freelist_push(PyTupleObject *);
-/* Print summary info about the state of the optimized allocator */
-void
-_PyTuple_DebugMallocStats(FILE *out)
-{
-#if PyTuple_MAXSAVESIZE > 0
- struct _Py_tuple_state *state = get_tuple_state();
- for (int i = 1; i < PyTuple_MAXSAVESIZE; i++) {
- char buf[128];
- PyOS_snprintf(buf, sizeof(buf),
- "free %d-sized PyTupleObject", i);
- _PyDebugAllocatorStats(out, buf, state->numfree[i],
- _PyObject_VAR_SIZE(&PyTuple_Type, i));
- }
-#endif
-}
/* Allocate an uninitialized tuple object. Before making it public, following
steps must be done:
@@ -56,38 +33,16 @@ _PyTuple_DebugMallocStats(FILE *out)
static PyTupleObject *
tuple_alloc(Py_ssize_t size)
{
- PyTupleObject *op;
-#if PyTuple_MAXSAVESIZE > 0
- // If Python is built with the empty tuple singleton,
- // tuple_alloc(0) must not be called.
- assert(size != 0);
-#endif
if (size < 0) {
PyErr_BadInternalCall();
return NULL;
}
-
-// Check for max save size > 1. Empty tuple singleton is special case.
-#if PyTuple_MAXSAVESIZE > 1
- struct _Py_tuple_state *state = get_tuple_state();
#ifdef Py_DEBUG
- // tuple_alloc() must not be called after _PyTuple_Fini()
- assert(state->numfree[0] != -1);
+ assert(size != 0); // The empty tuple is statically allocated.
#endif
- if (size < PyTuple_MAXSAVESIZE && (op = state->free_list[size]) != NULL) {
- assert(size != 0);
- state->free_list[size] = (PyTupleObject *) op->ob_item[0];
- state->numfree[size]--;
- /* Inlined _PyObject_InitVar() without _PyType_HasFeature() test */
-#ifdef Py_TRACE_REFS
- Py_SET_SIZE(op, size);
- Py_SET_TYPE(op, &PyTuple_Type);
-#endif
- _Py_NewReference((PyObject *)op);
- }
- else
-#endif
- {
+
+ PyTupleObject *op = maybe_freelist_pop(size);
+ if (op == NULL) {
/* Check for overflow */
if ((size_t)size > ((size_t)PY_SSIZE_T_MAX - (sizeof(PyTupleObject) -
sizeof(PyObject *))) / sizeof(PyObject *)) {
@@ -100,58 +55,24 @@ tuple_alloc(Py_ssize_t size)
return op;
}
-static int
-tuple_create_empty_tuple_singleton(struct _Py_tuple_state *state)
-{
-#if PyTuple_MAXSAVESIZE > 0
- assert(state->free_list[0] == NULL);
+// The empty tuple singleton is not tracked by the GC.
+// It does not contain any Python object.
+// Note that tuple subclasses have their own empty instances.
- PyTupleObject *op = PyObject_GC_NewVar(PyTupleObject, &PyTuple_Type, 0);
- if (op == NULL) {
- return -1;
- }
- // The empty tuple singleton is not tracked by the GC.
- // It does not contain any Python object.
-
- state->free_list[0] = op;
- state->numfree[0]++;
-
- assert(state->numfree[0] == 1);
-#endif
- return 0;
-}
-
-
-static PyObject *
+static inline PyObject *
tuple_get_empty(void)
{
-#if PyTuple_MAXSAVESIZE > 0
- struct _Py_tuple_state *state = get_tuple_state();
- PyTupleObject *op = state->free_list[0];
- // tuple_get_empty() must not be called before _PyTuple_Init()
- // or after _PyTuple_Fini()
- assert(op != NULL);
-#ifdef Py_DEBUG
- assert(state->numfree[0] != -1);
-#endif
-
- Py_INCREF(op);
- return (PyObject *) op;
-#else
- return PyTuple_New(0);
-#endif
+ Py_INCREF(&_Py_SINGLETON(tuple_empty));
+ return (PyObject *)&_Py_SINGLETON(tuple_empty);
}
-
PyObject *
PyTuple_New(Py_ssize_t size)
{
PyTupleObject *op;
-#if PyTuple_MAXSAVESIZE > 0
if (size == 0) {
return tuple_get_empty();
}
-#endif
op = tuple_alloc(size);
if (op == NULL) {
return NULL;
@@ -265,47 +186,33 @@ PyTuple_Pack(Py_ssize_t n, ...)
static void
tupledealloc(PyTupleObject *op)
{
- Py_ssize_t len = Py_SIZE(op);
- PyObject_GC_UnTrack(op);
- Py_TRASHCAN_BEGIN(op, tupledealloc)
- if (len > 0) {
- Py_ssize_t i = len;
- while (--i >= 0) {
- Py_XDECREF(op->ob_item[i]);
- }
-#if PyTuple_MAXSAVESIZE > 0
- struct _Py_tuple_state *state = get_tuple_state();
+ if (Py_SIZE(op) == 0) {
+ /* The empty tuple is statically allocated. */
+ if (op == &_Py_SINGLETON(tuple_empty)) {
#ifdef Py_DEBUG
- // tupledealloc() must not be called after _PyTuple_Fini()
- assert(state->numfree[0] != -1);
+ _Py_FatalRefcountError("deallocating the empty tuple singleton");
+#else
+ return;
#endif
- if (len < PyTuple_MAXSAVESIZE
- && state->numfree[len] < PyTuple_MAXFREELIST
- && Py_IS_TYPE(op, &PyTuple_Type))
- {
- op->ob_item[0] = (PyObject *) state->free_list[len];
- state->numfree[len]++;
- state->free_list[len] = op;
- goto done; /* return */
}
+#ifdef Py_DEBUG
+ /* tuple subclasses have their own empty instances. */
+ assert(!PyTuple_CheckExact(op));
#endif
}
-#if defined(Py_DEBUG) && PyTuple_MAXSAVESIZE > 0
- else {
- assert(len == 0);
- struct _Py_tuple_state *state = get_tuple_state();
- // The empty tuple singleton must only be deallocated by
- // _PyTuple_Fini(): not before, not after
- if (op == state->free_list[0] && state->numfree[0] != 0) {
- _Py_FatalRefcountError("deallocating the empty tuple singleton");
- }
+
+ PyObject_GC_UnTrack(op);
+ Py_TRASHCAN_BEGIN(op, tupledealloc)
+
+ Py_ssize_t i = Py_SIZE(op);
+ while (--i >= 0) {
+ Py_XDECREF(op->ob_item[i]);
+ }
+ // This will abort on the empty singleton (if there is one).
+ if (!maybe_freelist_push(op)) {
+ Py_TYPE(op)->tp_free((PyObject *)op);
}
-#endif
- Py_TYPE(op)->tp_free((PyObject *)op);
-#if PyTuple_MAXSAVESIZE > 0
-done:
-#endif
Py_TRASHCAN_END
}
@@ -838,6 +745,7 @@ tuple_subtype_new(PyTypeObject *type, PyObject *iterable)
if (tmp == NULL)
return NULL;
assert(PyTuple_Check(tmp));
+ /* This may allocate an empty tuple that is not the global one. */
newobj = type->tp_alloc(type, n = PyTuple_GET_SIZE(tmp));
if (newobj == NULL) {
Py_DECREF(tmp);
@@ -1020,14 +928,22 @@ _PyTuple_Resize(PyObject **pv, Py_ssize_t newsize)
PyErr_BadInternalCall();
return -1;
}
+
oldsize = Py_SIZE(v);
- if (oldsize == newsize)
+ if (oldsize == newsize) {
return 0;
-
+ }
+ if (newsize == 0) {
+ Py_DECREF(v);
+ *pv = tuple_get_empty();
+ return 0;
+ }
if (oldsize == 0) {
- /* Empty tuples are often shared, so we should never
- resize them in-place even if we do own the only
- (current) reference */
+#ifdef Py_DEBUG
+ assert(v == &_Py_SINGLETON(tuple_empty));
+#endif
+ /* The empty tuple is statically allocated so we never
+ resize it in-place. */
Py_DECREF(v);
*pv = PyTuple_New(newsize);
return *pv == NULL ? -1 : 0;
@@ -1063,36 +979,6 @@ _PyTuple_Resize(PyObject **pv, Py_ssize_t newsize)
return 0;
}
-void
-_PyTuple_ClearFreeList(PyInterpreterState *interp)
-{
-#if PyTuple_MAXSAVESIZE > 0
- struct _Py_tuple_state *state = &interp->tuple;
- for (Py_ssize_t i = 1; i < PyTuple_MAXSAVESIZE; i++) {
- PyTupleObject *p = state->free_list[i];
- state->free_list[i] = NULL;
- state->numfree[i] = 0;
- while (p) {
- PyTupleObject *q = p;
- p = (PyTupleObject *)(p->ob_item[0]);
- PyObject_GC_Del(q);
- }
- }
- // the empty tuple singleton is only cleared by _PyTuple_Fini()
-#endif
-}
-
-
-PyStatus
-_PyTuple_InitGlobalObjects(PyInterpreterState *interp)
-{
- struct _Py_tuple_state *state = &interp->tuple;
- if (tuple_create_empty_tuple_singleton(state) < 0) {
- return _PyStatus_NO_MEMORY();
- }
- return _PyStatus_OK();
-}
-
PyStatus
_PyTuple_InitTypes(PyInterpreterState *interp)
@@ -1112,24 +998,18 @@ _PyTuple_InitTypes(PyInterpreterState *interp)
return _PyStatus_OK();
}
+static void maybe_freelist_clear(PyInterpreterState *, int);
+
void
_PyTuple_Fini(PyInterpreterState *interp)
{
-#if PyTuple_MAXSAVESIZE > 0
- struct _Py_tuple_state *state = &interp->tuple;
- // The empty tuple singleton must not be tracked by the GC
- assert(!_PyObject_GC_IS_TRACKED(state->free_list[0]));
-
-#ifdef Py_DEBUG
- state->numfree[0] = 0;
-#endif
- Py_CLEAR(state->free_list[0]);
-#ifdef Py_DEBUG
- state->numfree[0] = -1;
-#endif
+ maybe_freelist_clear(interp, 1);
+}
- _PyTuple_ClearFreeList(interp);
-#endif
+void
+_PyTuple_ClearFreeList(PyInterpreterState *interp)
+{
+ maybe_freelist_clear(interp, 0);
}
/*********************** Tuple Iterator **************************/
@@ -1277,3 +1157,113 @@ tuple_iter(PyObject *seq)
_PyObject_GC_TRACK(it);
return (PyObject *)it;
}
+
+
+/*************
+ * freelists *
+ *************/
+
+#define STATE (interp->tuple)
+#define FREELIST_FINALIZED (STATE.numfree[0] < 0)
+
+static inline PyTupleObject *
+maybe_freelist_pop(Py_ssize_t size)
+{
+#if PyTuple_NFREELISTS > 0
+ PyInterpreterState *interp = _PyInterpreterState_GET();
+#ifdef Py_DEBUG
+ /* maybe_freelist_pop() must not be called after maybe_freelist_fini(). */
+ assert(!FREELIST_FINALIZED);
+#endif
+ if (size == 0) {
+ return NULL;
+ }
+ assert(size > 0);
+ if (size < PyTuple_MAXSAVESIZE) {
+ Py_ssize_t index = size - 1;
+ PyTupleObject *op = STATE.free_list[index];
+ if (op != NULL) {
+ /* op is the head of a linked list, with the first item
+ pointing to the next node. Here we pop off the old head. */
+ STATE.free_list[index] = (PyTupleObject *) op->ob_item[0];
+ STATE.numfree[index]--;
+ /* Inlined _PyObject_InitVar() without _PyType_HasFeature() test */
+#ifdef Py_TRACE_REFS
+ /* maybe_freelist_push() ensures these were already set. */
+ // XXX Can we drop these? See commit 68055ce6fe01 (GvR, Dec 1998).
+ Py_SET_SIZE(op, size);
+ Py_SET_TYPE(op, &PyTuple_Type);
+#endif
+ _Py_NewReference((PyObject *)op);
+ /* END inlined _PyObject_InitVar() */
+ return op;
+ }
+ }
+#endif
+ return NULL;
+}
+
+static inline int
+maybe_freelist_push(PyTupleObject *op)
+{
+#if PyTuple_NFREELISTS > 0
+ PyInterpreterState *interp = _PyInterpreterState_GET();
+#ifdef Py_DEBUG
+ /* maybe_freelist_push() must not be called after maybe_freelist_fini(). */
+ assert(!FREELIST_FINALIZED);
+#endif
+ if (Py_SIZE(op) == 0) {
+ return 0;
+ }
+ Py_ssize_t index = Py_SIZE(op) - 1;
+ if (index < PyTuple_NFREELISTS
+ && STATE.numfree[index] < PyTuple_MAXFREELIST
+ && Py_IS_TYPE(op, &PyTuple_Type))
+ {
+ /* op is the head of a linked list, with the first item
+ pointing to the next node. Here we set op as the new head. */
+ op->ob_item[0] = (PyObject *) STATE.free_list[index];
+ STATE.free_list[index] = op;
+ STATE.numfree[index]++;
+ return 1;
+ }
+#endif
+ return 0;
+}
+
+static void
+maybe_freelist_clear(PyInterpreterState *interp, int fini)
+{
+#if PyTuple_NFREELISTS > 0
+ for (Py_ssize_t i = 0; i < PyTuple_NFREELISTS; i++) {
+ PyTupleObject *p = STATE.free_list[i];
+ STATE.free_list[i] = NULL;
+ STATE.numfree[i] = fini ? -1 : 0;
+ while (p) {
+ PyTupleObject *q = p;
+ p = (PyTupleObject *)(p->ob_item[0]);
+ PyObject_GC_Del(q);
+ }
+ }
+#endif
+}
+
+/* Print summary info about the state of the optimized allocator */
+void
+_PyTuple_DebugMallocStats(FILE *out)
+{
+#if PyTuple_NFREELISTS > 0
+ PyInterpreterState *interp = _PyInterpreterState_GET();
+ for (int i = 0; i < PyTuple_NFREELISTS; i++) {
+ int len = i + 1;
+ char buf[128];
+ PyOS_snprintf(buf, sizeof(buf),
+ "free %d-sized PyTupleObject", len);
+ _PyDebugAllocatorStats(out, buf, STATE.numfree[i],
+ _PyObject_VAR_SIZE(&PyTuple_Type, len));
+ }
+#endif
+}
+
+#undef STATE
+#undef FREELIST_FINALIZED
diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c
index 61534742005a3..9228778d6bd04 100644
--- a/Python/pylifecycle.c
+++ b/Python/pylifecycle.c
@@ -682,11 +682,6 @@ pycore_init_global_objects(PyInterpreterState *interp)
_PyUnicode_InitState(interp);
- status = _PyTuple_InitGlobalObjects(interp);
- if (_PyStatus_EXCEPTION(status)) {
- return status;
- }
-
return _PyStatus_OK();
}
diff --git a/Tools/scripts/deepfreeze.py b/Tools/scripts/deepfreeze.py
index cdd34ddb8b1e8..954fca81b51e9 100644
--- a/Tools/scripts/deepfreeze.py
+++ b/Tools/scripts/deepfreeze.py
@@ -287,6 +287,8 @@ def generate_code(self, name: str, code: types.CodeType) -> str:
return f"& {name}.ob_base"
def generate_tuple(self, name: str, t: Tuple[object, ...]) -> str:
+ if len(t) == 0:
+ return f"(PyObject *)& _Py_SINGLETON(tuple_empty)"
items = [self.generate(f"{name}_{i}", it) for i, it in enumerate(t)]
self.write("static")
with self.indent():
diff --git a/Tools/scripts/generate_global_objects.py b/Tools/scripts/generate_global_objects.py
index 506aa86575c4e..639d8fa91c68b 100644
--- a/Tools/scripts/generate_global_objects.py
+++ b/Tools/scripts/generate_global_objects.py
@@ -252,6 +252,9 @@ def generate_runtime_init(identifiers, strings):
for name in sorted(identifiers):
assert name.isidentifier(), name
printer.write(f'INIT_ID({name}),')
+ printer.write('')
+ with printer.block('.tuple_empty =', ','):
+ printer.write('.ob_base = _PyVarObject_IMMORTAL_INIT(&PyTuple_Type, 0)')
printer.write(END)
printer.write(after)
1
0
Statistics internals: Make fewer calls to _coerce() when data types are mixed (GH-31619)
by rhettinger 28 Feb '22
by rhettinger 28 Feb '22
28 Feb '22
https://github.com/python/cpython/commit/d5b7bba43b7d9559e9894d263ece337084…
commit: d5b7bba43b7d9559e9894d263ece337084dc4b8d
branch: main
author: Raymond Hettinger <rhettinger(a)users.noreply.github.com>
committer: rhettinger <rhettinger(a)users.noreply.github.com>
date: 2022-02-28T11:43:52-06:00
summary:
Statistics internals: Make fewer calls to _coerce() when data types are mixed (GH-31619)
files:
M Lib/statistics.py
diff --git a/Lib/statistics.py b/Lib/statistics.py
index eef2453bc7394..f3bc9a1f34639 100644
--- a/Lib/statistics.py
+++ b/Lib/statistics.py
@@ -137,6 +137,7 @@
from itertools import groupby, repeat
from bisect import bisect_left, bisect_right
from math import hypot, sqrt, fabs, exp, erf, tau, log, fsum
+from functools import reduce
from operator import mul
from collections import Counter, namedtuple, defaultdict
@@ -183,11 +184,12 @@ def _sum(data):
allowed.
"""
count = 0
+ types = set()
+ types_add = types.add
partials = {}
partials_get = partials.get
- T = int
for typ, values in groupby(data, type):
- T = _coerce(T, typ) # or raise TypeError
+ types_add(typ)
for n, d in map(_exact_ratio, values):
count += 1
partials[d] = partials_get(d, 0) + n
@@ -199,6 +201,7 @@ def _sum(data):
else:
# Sum all the partial sums using builtin sum.
total = sum(Fraction(n, d) for d, n in partials.items())
+ T = reduce(_coerce, types, int) # or raise TypeError
return (T, total, count)
@@ -214,11 +217,12 @@ def _ss(data, c=None):
T, total, count = _sum((d := x - c) * d for x in data)
return (T, total, count)
count = 0
+ types = set()
+ types_add = types.add
sx_partials = defaultdict(int)
sxx_partials = defaultdict(int)
- T = int
for typ, values in groupby(data, type):
- T = _coerce(T, typ) # or raise TypeError
+ types_add(typ)
for n, d in map(_exact_ratio, values):
count += 1
sx_partials[d] += n
@@ -236,6 +240,7 @@ def _ss(data, c=None):
# This formula has poor numeric properties for floats,
# but with fractions it is exact.
total = (count * sxx - sx * sx) / count
+ T = reduce(_coerce, types, int) # or raise TypeError
return (T, total, count)
1
0
https://github.com/python/cpython/commit/7496f9587306772b56ed074092c020f3ef…
commit: 7496f9587306772b56ed074092c020f3ef16bf95
branch: main
author: Victor Stinner <vstinner(a)python.org>
committer: vstinner <vstinner(a)python.org>
date: 2022-02-28T16:03:57+01:00
summary:
bpo-45431: Rename CFrame to _PyCFrame in the C API (GH-31584)
Rename also struct _cframe to struct _PyCFrame.
Add a comment suggesting using public functions rather than using
directly the private _PyCFrame structure.
files:
M Include/cpython/pystate.h
M Include/internal/pycore_frame.h
M Python/ceval.c
diff --git a/Include/cpython/pystate.h b/Include/cpython/pystate.h
index 0d38604636b2b..26d6f7576e524 100644
--- a/Include/cpython/pystate.h
+++ b/Include/cpython/pystate.h
@@ -33,7 +33,9 @@ typedef struct {
PyCodeAddressRange bounds; // Only valid if code != NULL.
} PyTraceInfo;
-typedef struct _cframe {
+// Internal structure: you should not use it directly, but use public functions
+// like PyThreadState_EnterTracing() and PyThreadState_LeaveTracing().
+typedef struct _PyCFrame {
/* This struct will be threaded through the C stack
* allowing fast access to per-thread state that needs
* to be accessed quickly by the interpreter, but can
@@ -47,8 +49,8 @@ typedef struct _cframe {
int use_tracing;
/* Pointer to the currently executing frame (it can be NULL) */
struct _PyInterpreterFrame *current_frame;
- struct _cframe *previous;
-} CFrame;
+ struct _PyCFrame *previous;
+} _PyCFrame;
typedef struct _err_stackitem {
/* This struct represents a single execution context where we might
@@ -102,9 +104,9 @@ struct _ts {
the trace/profile. */
int tracing;
- /* Pointer to current CFrame in the C stack frame of the currently,
+ /* Pointer to current _PyCFrame in the C stack frame of the currently,
* or most recently, executing _PyEval_EvalFrameDefault. */
- CFrame *cframe;
+ _PyCFrame *cframe;
Py_tracefunc c_profilefunc;
Py_tracefunc c_tracefunc;
@@ -196,7 +198,7 @@ struct _ts {
_PyErr_StackItem exc_state;
/* The bottom-most frame on the stack. */
- CFrame root_cframe;
+ _PyCFrame root_cframe;
};
diff --git a/Include/internal/pycore_frame.h b/Include/internal/pycore_frame.h
index 20e81b7849b20..207983dcc22d7 100644
--- a/Include/internal/pycore_frame.h
+++ b/Include/internal/pycore_frame.h
@@ -59,7 +59,7 @@ typedef struct _PyInterpreterFrame {
int f_lasti; /* Last instruction if called */
int stacktop; /* Offset of TOS from localsplus */
PyFrameState f_state; /* What state the frame is in */
- bool is_entry; // Whether this is the "root" frame for the current CFrame.
+ bool is_entry; // Whether this is the "root" frame for the current _PyCFrame.
bool is_generator;
PyObject *localsplus[1];
} _PyInterpreterFrame;
diff --git a/Python/ceval.c b/Python/ceval.c
index 6f1165b768041..13866ba355e97 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -1616,15 +1616,15 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
int oparg; /* Current opcode argument, if any */
_Py_atomic_int * const eval_breaker = &tstate->interp->ceval.eval_breaker;
- CFrame cframe;
+ _PyCFrame cframe;
CallShape call_shape;
call_shape.kwnames = NULL; // Borrowed reference. Reset by CALL instructions.
- /* WARNING: Because the CFrame lives on the C stack,
+ /* WARNING: Because the _PyCFrame lives on the C stack,
* but can be accessed from a heap allocated object (tstate)
* strict stack discipline must be maintained.
*/
- CFrame *prev_cframe = tstate->cframe;
+ _PyCFrame *prev_cframe = tstate->cframe;
cframe.use_tracing = prev_cframe->use_tracing;
cframe.previous = prev_cframe;
tstate->cframe = &cframe;
1
0
https://github.com/python/cpython/commit/4558af5a8f8e56a9b0dc11f6e834c47e0f…
commit: 4558af5a8f8e56a9b0dc11f6e834c47e0fd05f9e
branch: main
author: Mark Shannon <mark(a)hotpy.org>
committer: markshannon <mark(a)hotpy.org>
date: 2022-02-28T12:56:29Z
summary:
bpo-46841: Move the cache for `LOAD_GLOBAL` inline. (GH-31575)
files:
A Misc/NEWS.d/next/Core and Builtins/2022-02-25-13-18-18.bpo-46841.86QiQu.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_dis.py
M Python/ceval.c
M Python/compile.c
M Python/specialize.c
M Tools/scripts/generate_opcode_h.py
diff --git a/Include/internal/pycore_code.h b/Include/internal/pycore_code.h
index 0e401d61f7673..dfa15b8cd61e4 100644
--- a/Include/internal/pycore_code.h
+++ b/Include/internal/pycore_code.h
@@ -26,11 +26,6 @@ typedef struct {
uint32_t dk_version;
} _PyAttrCache;
-typedef struct {
- uint32_t module_keys_version;
- uint32_t builtin_keys_version;
-} _PyLoadGlobalCache;
-
typedef struct {
/* Borrowed ref in LOAD_METHOD */
PyObject *obj;
@@ -57,23 +52,35 @@ typedef union {
_PyEntryZero zero;
_PyAdaptiveEntry adaptive;
_PyAttrCache attr;
- _PyLoadGlobalCache load_global;
_PyObjectCache obj;
_PyCallCache call;
} SpecializedCacheEntry;
#define INSTRUCTIONS_PER_ENTRY (sizeof(SpecializedCacheEntry)/sizeof(_Py_CODEUNIT))
+/* Inline caches */
+
+#define CACHE_ENTRIES(cache) (sizeof(cache)/sizeof(_Py_CODEUNIT))
+
+typedef struct {
+ _Py_CODEUNIT counter;
+ _Py_CODEUNIT index;
+ _Py_CODEUNIT module_keys_version;
+ _Py_CODEUNIT _m1;
+ _Py_CODEUNIT builtin_keys_version;
+} _PyLoadGlobalCache;
+
+#define INLINE_CACHE_ENTRIES_LOAD_GLOBAL CACHE_ENTRIES(_PyLoadGlobalCache)
+
typedef struct {
_Py_CODEUNIT counter;
} _PyBinaryOpCache;
+#define INLINE_CACHE_ENTRIES_BINARY_OP CACHE_ENTRIES(_PyBinaryOpCache)
typedef struct {
_Py_CODEUNIT counter;
} _PyUnpackSequenceCache;
-#define INLINE_CACHE_ENTRIES_BINARY_OP \
- (sizeof(_PyBinaryOpCache) / sizeof(_Py_CODEUNIT))
#define INLINE_CACHE_ENTRIES_UNPACK_SEQUENCE \
(sizeof(_PyUnpackSequenceCache) / sizeof(_Py_CODEUNIT))
@@ -307,7 +314,7 @@ cache_backoff(_PyAdaptiveEntry *entry) {
extern int _Py_Specialize_LoadAttr(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name, SpecializedCacheEntry *cache);
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, 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_StoreSubscr(PyObject *container, PyObject *sub, _Py_CODEUNIT *instr);
@@ -388,6 +395,38 @@ extern PyObject* _Py_GetSpecializationStats(void);
#define OBJECT_STAT_INC(name) ((void)0)
#endif
+// Cache values are only valid in memory, so use native endianness.
+#ifdef WORDS_BIGENDIAN
+
+static inline void
+write32(uint16_t *p, uint32_t val)
+{
+ p[0] = val >> 16;
+ p[1] = (uint16_t)val;
+}
+
+static inline uint32_t
+read32(uint16_t *p)
+{
+ return (p[0] << 16) | p[1];
+}
+
+#else
+
+static inline void
+write32(uint16_t *p, uint32_t val)
+{
+ p[0] = (uint16_t)val;
+ p[1] = val >> 16;
+}
+
+static inline uint32_t
+read32(uint16_t *p)
+{
+ return p[0] | (p[1] << 16);
+}
+
+#endif
#ifdef __cplusplus
}
diff --git a/Include/opcode.h b/Include/opcode.h
index ae21d92a865e5..99480def30da5 100644
--- a/Include/opcode.h
+++ b/Include/opcode.h
@@ -185,8 +185,11 @@ extern "C" {
#define STORE_FAST__STORE_FAST 175
#define LOAD_FAST__LOAD_ATTR_INSTANCE_VALUE 176
#define DO_TRACING 255
-#ifdef NEED_OPCODE_JUMP_TABLES
-static uint32_t _PyOpcode_RelativeJump[8] = {
+
+extern const uint8_t _PyOpcode_InlineCacheEntries[256];
+
+#ifdef NEED_OPCODE_TABLES
+static const uint32_t _PyOpcode_RelativeJump[8] = {
0U,
0U,
536870912U,
@@ -196,7 +199,7 @@ static uint32_t _PyOpcode_RelativeJump[8] = {
0U,
0U,
};
-static uint32_t _PyOpcode_Jump[8] = {
+static const uint32_t _PyOpcode_Jump[8] = {
0U,
0U,
536870912U,
@@ -206,6 +209,12 @@ static uint32_t _PyOpcode_Jump[8] = {
0U,
0U,
};
+
+const uint8_t _PyOpcode_InlineCacheEntries[256] = {
+ [UNPACK_SEQUENCE] = 1,
+ [LOAD_GLOBAL] = 5,
+ [BINARY_OP] = 1,
+};
#endif /* OPCODE_TABLES */
#define HAS_CONST(op) (false\
@@ -240,11 +249,6 @@ static uint32_t _PyOpcode_Jump[8] = {
#define NB_INPLACE_TRUE_DIVIDE 24
#define NB_INPLACE_XOR 25
-static const uint8_t _PyOpcode_InlineCacheEntries[256] = {
- [UNPACK_SEQUENCE] = 1,
- [BINARY_OP] = 1,
-};
-
#define HAS_ARG(op) ((op) >= HAVE_ARGUMENT)
/* Reserve some bytecodes for internal use in the compiler.
diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py
index be23eeed9df74..f051dfe9492f5 100644
--- a/Lib/importlib/_bootstrap_external.py
+++ b/Lib/importlib/_bootstrap_external.py
@@ -387,8 +387,8 @@ def _write_atomic(path, data, mode=0o666):
# Python 3.11a5 3478 (New CALL opcodes)
# Python 3.11a5 3479 (Add PUSH_NULL opcode)
# Python 3.11a5 3480 (New CALL opcodes, second iteration)
-# Python 3.11a5 3481 (Use inline CACHE instructions)
-# Python 3.11a5 3482 (Use inline caching for UNPACK_SEQUENCE)
+# 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.12 will start with magic number 3500
diff --git a/Lib/opcode.py b/Lib/opcode.py
index 8fa71bf4d180a..fb2d24fd1f007 100644
--- a/Lib/opcode.py
+++ b/Lib/opcode.py
@@ -135,7 +135,7 @@ def jabs_op(name, op, entries=0):
jabs_op('JUMP_ABSOLUTE', 113) # ""
jabs_op('POP_JUMP_IF_FALSE', 114) # ""
jabs_op('POP_JUMP_IF_TRUE', 115) # ""
-name_op('LOAD_GLOBAL', 116) # Index in name list
+name_op('LOAD_GLOBAL', 116, 5) # Index in name list
def_op('IS_OP', 117)
def_op('CONTAINS_OP', 118)
def_op('RERAISE', 119)
@@ -198,6 +198,7 @@ def jabs_op(name, op, entries=0):
def_op('KW_NAMES', 172)
hasconst.append(172)
+
del def_op, name_op, jrel_op, jabs_op
_nb_ops = [
diff --git a/Lib/test/test_dis.py b/Lib/test/test_dis.py
index e478ca966612b..a13e0f6edb874 100644
--- a/Lib/test/test_dis.py
+++ b/Lib/test/test_dis.py
@@ -149,10 +149,10 @@ def bug708901():
%3d PRECALL 2
CALL 2
GET_ITER
- >> FOR_ITER 2 (to 22)
+ >> FOR_ITER 2 (to 32)
STORE_FAST 0 (res)
-%3d JUMP_ABSOLUTE 8 (to 16)
+%3d JUMP_ABSOLUTE 13 (to 26)
%3d >> LOAD_CONST 0 (None)
RETURN_VALUE
@@ -375,7 +375,7 @@ def bug42562():
>> PUSH_EXC_INFO
%3d LOAD_GLOBAL 0 (Exception)
- JUMP_IF_NOT_EXC_MATCH 26 (to 52)
+ JUMP_IF_NOT_EXC_MATCH 31 (to 62)
STORE_FAST 0 (e)
%3d LOAD_FAST 0 (e)
@@ -1156,18 +1156,18 @@ def _prepare_test_cases():
Instruction(opname='STORE_FAST', opcode=125, arg=2, argval='f', argrepr='f', offset=18, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='PUSH_NULL', opcode=2, arg=None, argval=None, argrepr='', offset=20, starts_line=7, is_jump_target=False, positions=None),
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=0, argval='print', argrepr='print', offset=22, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_DEREF', opcode=137, arg=0, argval='a', argrepr='a', offset=24, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_DEREF', opcode=137, arg=1, argval='b', argrepr='b', offset=26, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_CONST', opcode=100, arg=4, argval='', argrepr="''", offset=28, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=30, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='BUILD_LIST', opcode=103, arg=0, argval=0, argrepr='', offset=32, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='BUILD_MAP', opcode=105, arg=0, argval=0, argrepr='', offset=34, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_CONST', opcode=100, arg=6, argval='Hello world!', argrepr="'Hello world!'", offset=36, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='PRECALL', opcode=166, arg=7, argval=7, argrepr='', offset=38, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='CALL', opcode=171, arg=7, argval=7, argrepr='', offset=40, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=42, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_FAST', opcode=124, arg=2, argval='f', argrepr='f', offset=44, starts_line=8, is_jump_target=False, positions=None),
- Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=46, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_DEREF', opcode=137, arg=0, argval='a', argrepr='a', offset=34, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_DEREF', opcode=137, arg=1, argval='b', argrepr='b', offset=36, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_CONST', opcode=100, arg=4, argval='', argrepr="''", offset=38, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=40, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='BUILD_LIST', opcode=103, arg=0, argval=0, argrepr='', offset=42, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='BUILD_MAP', opcode=105, arg=0, argval=0, argrepr='', offset=44, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_CONST', opcode=100, arg=6, argval='Hello world!', argrepr="'Hello world!'", offset=46, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='PRECALL', opcode=166, arg=7, argval=7, argrepr='', offset=48, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='CALL', opcode=171, arg=7, argval=7, argrepr='', offset=50, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=52, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_FAST', opcode=124, arg=2, argval='f', argrepr='f', offset=54, starts_line=8, is_jump_target=False, positions=None),
+ Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=56, starts_line=None, is_jump_target=False, positions=None),
]
expected_opinfo_f = [
@@ -1186,15 +1186,15 @@ def _prepare_test_cases():
Instruction(opname='STORE_FAST', opcode=125, arg=2, argval='inner', argrepr='inner', offset=24, starts_line=None, is_jump_target=False, positions=None),
Instruction(opname='PUSH_NULL', opcode=2, arg=None, argval=None, argrepr='', offset=26, starts_line=5, is_jump_target=False, positions=None),
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=0, argval='print', argrepr='print', offset=28, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_DEREF', opcode=137, arg=3, argval='a', argrepr='a', offset=30, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_DEREF', opcode=137, arg=4, argval='b', argrepr='b', offset=32, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_DEREF', opcode=137, arg=0, argval='c', argrepr='c', offset=34, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_DEREF', opcode=137, arg=1, argval='d', argrepr='d', offset=36, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='PRECALL', opcode=166, arg=4, argval=4, argrepr='', offset=38, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='CALL', opcode=171, arg=4, argval=4, argrepr='', offset=40, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=42, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_FAST', opcode=124, arg=2, argval='inner', argrepr='inner', offset=44, starts_line=6, is_jump_target=False, positions=None),
- Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=46, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_DEREF', opcode=137, arg=3, argval='a', argrepr='a', offset=40, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_DEREF', opcode=137, arg=4, argval='b', argrepr='b', offset=42, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_DEREF', opcode=137, arg=0, argval='c', argrepr='c', offset=44, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_DEREF', opcode=137, arg=1, argval='d', argrepr='d', offset=46, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='PRECALL', opcode=166, arg=4, argval=4, argrepr='', offset=48, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='CALL', opcode=171, arg=4, argval=4, argrepr='', offset=50, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=52, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_FAST', opcode=124, arg=2, argval='inner', argrepr='inner', offset=54, starts_line=6, is_jump_target=False, positions=None),
+ Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=56, starts_line=None, is_jump_target=False, positions=None),
]
expected_opinfo_inner = [
@@ -1202,160 +1202,160 @@ def _prepare_test_cases():
Instruction(opname='RESUME', opcode=151, arg=0, argval=0, argrepr='', offset=2, starts_line=3, is_jump_target=False, positions=None),
Instruction(opname='PUSH_NULL', opcode=2, arg=None, argval=None, argrepr='', offset=4, starts_line=4, is_jump_target=False, positions=None),
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=0, argval='print', argrepr='print', offset=6, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_DEREF', opcode=137, arg=2, argval='a', argrepr='a', offset=8, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_DEREF', opcode=137, arg=3, argval='b', argrepr='b', offset=10, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_DEREF', opcode=137, arg=4, argval='c', argrepr='c', offset=12, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_DEREF', opcode=137, arg=5, argval='d', argrepr='d', offset=14, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='e', argrepr='e', offset=16, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_FAST', opcode=124, arg=1, argval='f', argrepr='f', offset=18, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='PRECALL', opcode=166, arg=6, argval=6, argrepr='', offset=20, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='CALL', opcode=171, arg=6, argval=6, argrepr='', offset=22, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=24, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=26, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=28, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_DEREF', opcode=137, arg=2, argval='a', argrepr='a', offset=18, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_DEREF', opcode=137, arg=3, argval='b', argrepr='b', offset=20, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_DEREF', opcode=137, arg=4, argval='c', argrepr='c', offset=22, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_DEREF', opcode=137, arg=5, argval='d', argrepr='d', offset=24, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='e', argrepr='e', offset=26, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_FAST', opcode=124, arg=1, argval='f', argrepr='f', offset=28, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='PRECALL', opcode=166, arg=6, argval=6, argrepr='', offset=30, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='CALL', opcode=171, arg=6, argval=6, argrepr='', offset=32, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=34, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=36, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=38, starts_line=None, is_jump_target=False, positions=None),
]
expected_opinfo_jumpy = [
Instruction(opname='RESUME', opcode=151, arg=0, argval=0, argrepr='', offset=0, starts_line=1, is_jump_target=False, positions=None),
Instruction(opname='PUSH_NULL', opcode=2, arg=None, argval=None, argrepr='', offset=2, starts_line=3, is_jump_target=False, positions=None),
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=0, argval='range', argrepr='range', offset=4, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_CONST', opcode=100, arg=1, argval=10, argrepr='10', offset=6, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=8, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=10, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='GET_ITER', opcode=68, arg=None, argval=None, argrepr='', offset=12, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='FOR_ITER', opcode=93, arg=19, argval=54, argrepr='to 54', offset=14, starts_line=None, is_jump_target=True, positions=None),
- Instruction(opname='STORE_FAST', opcode=125, arg=0, argval='i', argrepr='i', offset=16, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='PUSH_NULL', opcode=2, arg=None, argval=None, argrepr='', offset=18, starts_line=4, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=20, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=22, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=24, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=26, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=28, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=30, starts_line=5, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval=4, argrepr='4', offset=32, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='COMPARE_OP', opcode=107, arg=0, argval='<', argrepr='<', offset=34, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=20, argval=40, argrepr='to 40', offset=36, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='JUMP_ABSOLUTE', opcode=113, arg=7, argval=14, argrepr='to 14', offset=38, starts_line=6, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=40, starts_line=7, is_jump_target=True, positions=None),
- Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=6, argrepr='6', offset=42, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='COMPARE_OP', opcode=107, arg=4, argval='>', argrepr='>', offset=44, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=26, argval=52, argrepr='to 52', offset=46, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=48, starts_line=8, is_jump_target=False, positions=None),
- Instruction(opname='JUMP_FORWARD', opcode=110, arg=7, argval=66, argrepr='to 66', offset=50, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='JUMP_ABSOLUTE', opcode=113, arg=7, argval=14, argrepr='to 14', offset=52, starts_line=7, is_jump_target=True, positions=None),
- Instruction(opname='PUSH_NULL', opcode=2, arg=None, argval=None, argrepr='', offset=54, starts_line=10, is_jump_target=True, positions=None),
- Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=56, 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=58, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=60, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=62, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=64, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=66, starts_line=11, is_jump_target=True, positions=None),
- Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=58, argval=116, argrepr='to 116', offset=68, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='PUSH_NULL', opcode=2, arg=None, argval=None, argrepr='', offset=70, starts_line=12, is_jump_target=True, positions=None),
- Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=72, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=74, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=76, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=78, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=80, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=82, starts_line=13, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=84, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='BINARY_OP', opcode=122, arg=23, argval=23, argrepr='-=', offset=86, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='STORE_FAST', opcode=125, arg=0, argval='i', argrepr='i', offset=90, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=92, starts_line=14, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=6, argrepr='6', offset=94, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='COMPARE_OP', opcode=107, arg=4, argval='>', argrepr='>', offset=96, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=51, argval=102, argrepr='to 102', offset=98, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='JUMP_ABSOLUTE', opcode=113, arg=33, argval=66, argrepr='to 66', offset=100, starts_line=15, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=102, starts_line=16, is_jump_target=True, positions=None),
- Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval=4, argrepr='4', offset=104, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='COMPARE_OP', opcode=107, arg=0, argval='<', argrepr='<', offset=106, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=56, argval=112, argrepr='to 112', offset=108, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='JUMP_FORWARD', opcode=110, arg=8, argval=128, argrepr='to 128', offset=110, starts_line=17, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=112, starts_line=11, is_jump_target=True, positions=None),
- Instruction(opname='POP_JUMP_IF_TRUE', opcode=115, arg=35, argval=70, argrepr='to 70', offset=114, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='PUSH_NULL', opcode=2, arg=None, argval=None, argrepr='', offset=116, starts_line=19, is_jump_target=True, positions=None),
- Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=118, 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=120, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=122, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=124, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=126, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='NOP', opcode=9, arg=None, argval=None, argrepr='', offset=128, starts_line=20, is_jump_target=True, positions=None),
- Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=130, starts_line=21, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_CONST', opcode=100, arg=7, argval=0, argrepr='0', offset=132, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='BINARY_OP', opcode=122, arg=11, argval=11, argrepr='/', offset=134, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', 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=25, is_jump_target=False, positions=None),
- Instruction(opname='BEFORE_WITH', opcode=53, arg=None, argval=None, argrepr='', offset=142, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='STORE_FAST', opcode=125, arg=1, argval='dodgy', argrepr='dodgy', offset=144, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='PUSH_NULL', opcode=2, arg=None, argval=None, argrepr='', offset=146, starts_line=26, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=148, 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=150, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=152, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=154, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=156, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=158, starts_line=25, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=160, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=162, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='PRECALL', opcode=166, arg=2, argval=2, argrepr='', offset=164, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='CALL', opcode=171, arg=2, argval=2, argrepr='', offset=166, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=168, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='JUMP_FORWARD', opcode=110, arg=11, argval=194, argrepr='to 194', offset=170, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=172, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='WITH_EXCEPT_START', opcode=49, arg=None, argval=None, argrepr='', offset=174, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_JUMP_IF_TRUE', opcode=115, arg=93, argval=186, argrepr='to 186', offset=176, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='RERAISE', opcode=119, arg=2, argval=2, argrepr='', offset=178, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='COPY', opcode=120, arg=3, argval=3, argrepr='', offset=180, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=182, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='RERAISE', opcode=119, arg=1, argval=1, argrepr='', offset=184, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=186, starts_line=None, is_jump_target=True, positions=None),
- Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=188, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, 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='JUMP_FORWARD', opcode=110, arg=16, argval=228, argrepr='to 228', offset=194, starts_line=None, is_jump_target=True, positions=None),
- Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=196, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_GLOBAL', opcode=116, arg=2, argval='ZeroDivisionError', argrepr='ZeroDivisionError', offset=198, starts_line=22, is_jump_target=False, positions=None),
- Instruction(opname='JUMP_IF_NOT_EXC_MATCH', opcode=121, arg=110, argval=220, argrepr='to 220', offset=200, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=202, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='PUSH_NULL', opcode=2, arg=None, argval=None, argrepr='', offset=204, starts_line=23, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=206, 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=208, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=210, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=212, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=214, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=216, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='JUMP_FORWARD', opcode=110, arg=12, argval=244, argrepr='to 244', offset=218, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=220, starts_line=22, is_jump_target=True, positions=None),
- Instruction(opname='COPY', opcode=120, arg=3, argval=3, argrepr='', offset=222, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=224, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='RERAISE', opcode=119, arg=1, argval=1, argrepr='', offset=226, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='PUSH_NULL', opcode=2, arg=None, argval=None, argrepr='', offset=228, starts_line=28, is_jump_target=True, positions=None),
- Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=230, 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=232, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=234, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=236, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=238, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=240, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=242, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='NOP', opcode=9, arg=None, argval=None, argrepr='', offset=244, starts_line=23, is_jump_target=True, positions=None),
- Instruction(opname='PUSH_NULL', opcode=2, arg=None, argval=None, argrepr='', offset=246, starts_line=28, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=248, 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=250, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=252, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=254, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=256, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=258, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=260, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=262, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='PUSH_NULL', opcode=2, arg=None, argval=None, argrepr='', offset=264, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=266, 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=268, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=270, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=272, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=274, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=276, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='COPY', opcode=120, arg=3, argval=3, argrepr='', offset=278, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=280, starts_line=None, is_jump_target=False, positions=None),
- Instruction(opname='RERAISE', opcode=119, arg=1, argval=1, argrepr='', offset=282, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='LOAD_CONST', opcode=100, arg=1, argval=10, argrepr='10', offset=16, starts_line=None, is_jump_target=False, positions=None),
+ 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='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),
+ Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=42, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='PRECALL', opcode=166, arg=1, argval=1, argrepr='', offset=44, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='CALL', opcode=171, arg=1, argval=1, argrepr='', offset=46, starts_line=None, is_jump_target=False, positions=None),
+ Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=48, starts_line=None, is_jump_target=False, positions=None),
+ 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),
]
# 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-25-13-18-18.bpo-46841.86QiQu.rst b/Misc/NEWS.d/next/Core and Builtins/2022-02-25-13-18-18.bpo-46841.86QiQu.rst
new file mode 100644
index 0000000000000..de8261fe4784e
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2022-02-25-13-18-18.bpo-46841.86QiQu.rst
@@ -0,0 +1 @@
+Use inline cache for :opcode:`LOAD_GLOBAL`.
diff --git a/Python/ceval.c b/Python/ceval.c
index fe75782972992..6f1165b768041 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -2993,25 +2993,26 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
}
}
}
+ /* Skip over inline cache */
+ JUMPBY(INLINE_CACHE_ENTRIES_LOAD_GLOBAL);
PUSH(v);
DISPATCH();
}
TARGET(LOAD_GLOBAL_ADAPTIVE) {
assert(cframe.use_tracing == 0);
- SpecializedCacheEntry *cache = GET_CACHE();
- if (cache->adaptive.counter == 0) {
- PyObject *name = GETITEM(names, cache->adaptive.original_oparg);
+ uint16_t counter = *next_instr;
+ if (counter == 0) {
+ PyObject *name = GETITEM(names, oparg);
next_instr--;
- if (_Py_Specialize_LoadGlobal(GLOBALS(), BUILTINS(), next_instr, name, cache) < 0) {
+ if (_Py_Specialize_LoadGlobal(GLOBALS(), BUILTINS(), next_instr, name) < 0) {
goto error;
}
DISPATCH();
}
else {
STAT_INC(LOAD_GLOBAL, deferred);
- cache->adaptive.counter--;
- oparg = cache->adaptive.original_oparg;
+ *next_instr = counter-1;
JUMP_TO_INSTRUCTION(LOAD_GLOBAL);
}
}
@@ -3020,13 +3021,13 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
assert(cframe.use_tracing == 0);
DEOPT_IF(!PyDict_CheckExact(GLOBALS()), LOAD_GLOBAL);
PyDictObject *dict = (PyDictObject *)GLOBALS();
- SpecializedCacheEntry *caches = GET_CACHE();
- _PyAdaptiveEntry *cache0 = &caches[0].adaptive;
- _PyLoadGlobalCache *cache1 = &caches[-1].load_global;
- DEOPT_IF(dict->ma_keys->dk_version != cache1->module_keys_version, LOAD_GLOBAL);
- PyDictKeyEntry *ep = DK_ENTRIES(dict->ma_keys) + cache0->index;
+ _PyLoadGlobalCache *cache = (_PyLoadGlobalCache *)next_instr;
+ uint32_t version = read32(&cache->module_keys_version);
+ DEOPT_IF(dict->ma_keys->dk_version != version, LOAD_GLOBAL);
+ PyDictKeyEntry *ep = DK_ENTRIES(dict->ma_keys) + cache->index;
PyObject *res = ep->me_value;
DEOPT_IF(res == NULL, LOAD_GLOBAL);
+ JUMPBY(INLINE_CACHE_ENTRIES_LOAD_GLOBAL);
STAT_INC(LOAD_GLOBAL, hit);
Py_INCREF(res);
PUSH(res);
@@ -3039,14 +3040,15 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
DEOPT_IF(!PyDict_CheckExact(BUILTINS()), LOAD_GLOBAL);
PyDictObject *mdict = (PyDictObject *)GLOBALS();
PyDictObject *bdict = (PyDictObject *)BUILTINS();
- SpecializedCacheEntry *caches = GET_CACHE();
- _PyAdaptiveEntry *cache0 = &caches[0].adaptive;
- _PyLoadGlobalCache *cache1 = &caches[-1].load_global;
- DEOPT_IF(mdict->ma_keys->dk_version != cache1->module_keys_version, LOAD_GLOBAL);
- DEOPT_IF(bdict->ma_keys->dk_version != cache1->builtin_keys_version, LOAD_GLOBAL);
- PyDictKeyEntry *ep = DK_ENTRIES(bdict->ma_keys) + cache0->index;
+ _PyLoadGlobalCache *cache = (_PyLoadGlobalCache *)next_instr;
+ uint32_t mod_version = read32(&cache->module_keys_version);
+ uint16_t bltn_version = cache->builtin_keys_version;
+ DEOPT_IF(mdict->ma_keys->dk_version != mod_version, LOAD_GLOBAL);
+ DEOPT_IF(bdict->ma_keys->dk_version != bltn_version, LOAD_GLOBAL);
+ PyDictKeyEntry *ep = DK_ENTRIES(bdict->ma_keys) + cache->index;
PyObject *res = ep->me_value;
DEOPT_IF(res == NULL, LOAD_GLOBAL);
+ JUMPBY(INLINE_CACHE_ENTRIES_LOAD_GLOBAL);
STAT_INC(LOAD_GLOBAL, hit);
Py_INCREF(res);
PUSH(res);
@@ -5594,7 +5596,7 @@ opname ## _miss: \
MISS_WITH_CACHE(LOAD_ATTR)
MISS_WITH_CACHE(STORE_ATTR)
-MISS_WITH_CACHE(LOAD_GLOBAL)
+MISS_WITH_INLINE_CACHE(LOAD_GLOBAL)
MISS_WITH_CACHE(LOAD_METHOD)
MISS_WITH_CACHE(PRECALL)
MISS_WITH_CACHE(CALL)
diff --git a/Python/compile.c b/Python/compile.c
index 8ae4d44e9c6f3..ea9c3c8d48269 100644
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -31,7 +31,7 @@
#include "pycore_long.h" // _PyLong_GetZero()
#include "pycore_symtable.h" // PySTEntryObject
-#define NEED_OPCODE_JUMP_TABLES
+#define NEED_OPCODE_TABLES
#include "opcode.h" // EXTENDED_ARG
@@ -108,7 +108,7 @@ typedef struct exceptstack {
#define MASK_LOW_LOG_BITS 31
static inline int
-is_bit_set_in_table(uint32_t *table, int bitindex) {
+is_bit_set_in_table(const uint32_t *table, int bitindex) {
/* Is the relevant bit set in the relevant word? */
/* 256 bits fit into 8 32-bits words.
* Word is indexed by (bitindex>>ln(size of int in bits)).
diff --git a/Python/specialize.c b/Python/specialize.c
index b88c5d517bd8f..38907f675e809 100644
--- a/Python/specialize.c
+++ b/Python/specialize.c
@@ -59,7 +59,6 @@ static uint8_t adaptive_opcodes[256] = {
/* The number of cache entries required for a "family" of instructions. */
static uint8_t cache_requirements[256] = {
[LOAD_ATTR] = 1, // _PyAdaptiveEntry
- [LOAD_GLOBAL] = 2, /* _PyAdaptiveEntry and _PyLoadGlobalCache */
[LOAD_METHOD] = 3, /* _PyAdaptiveEntry, _PyAttrCache and _PyObjectCache */
[BINARY_SUBSCR] = 2, /* _PyAdaptiveEntry, _PyObjectCache */
[STORE_SUBSCR] = 0,
@@ -1208,11 +1207,12 @@ _Py_Specialize_LoadMethod(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name,
int
_Py_Specialize_LoadGlobal(
PyObject *globals, PyObject *builtins,
- _Py_CODEUNIT *instr, PyObject *name,
- SpecializedCacheEntry *cache)
+ _Py_CODEUNIT *instr, PyObject *name)
{
- _PyAdaptiveEntry *cache0 = &cache->adaptive;
- _PyLoadGlobalCache *cache1 = &cache[-1].load_global;
+ assert(_PyOpcode_InlineCacheEntries[LOAD_GLOBAL] ==
+ INLINE_CACHE_ENTRIES_LOAD_GLOBAL);
+ /* Use inline cache */
+ _PyLoadGlobalCache *cache = (_PyLoadGlobalCache *)(instr + 1);
assert(PyUnicode_CheckExact(name));
if (!PyDict_CheckExact(globals)) {
goto fail;
@@ -1231,8 +1231,8 @@ _Py_Specialize_LoadGlobal(
if (keys_version == 0) {
goto fail;
}
- cache1->module_keys_version = keys_version;
- cache0->index = (uint16_t)index;
+ cache->index = (uint16_t)index;
+ write32(&cache->module_keys_version, keys_version);
*instr = _Py_MAKECODEUNIT(LOAD_GLOBAL_MODULE, _Py_OPARG(*instr));
goto success;
}
@@ -1258,20 +1258,24 @@ _Py_Specialize_LoadGlobal(
SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_OUT_OF_VERSIONS);
goto fail;
}
- cache1->module_keys_version = globals_version;
- cache1->builtin_keys_version = builtins_version;
- cache0->index = (uint16_t)index;
+ if (builtins_version > UINT16_MAX) {
+ SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_OUT_OF_RANGE);
+ goto fail;
+ }
+ cache->index = (uint16_t)index;
+ write32(&cache->module_keys_version, globals_version);
+ cache->builtin_keys_version = (uint16_t)builtins_version;
*instr = _Py_MAKECODEUNIT(LOAD_GLOBAL_BUILTIN, _Py_OPARG(*instr));
goto success;
fail:
STAT_INC(LOAD_GLOBAL, failure);
assert(!PyErr_Occurred());
- cache_backoff(cache0);
+ cache->counter = ADAPTIVE_CACHE_BACKOFF;
return 0;
success:
STAT_INC(LOAD_GLOBAL, success);
assert(!PyErr_Occurred());
- cache0->counter = initial_counter_value();
+ cache->counter = initial_counter_value();
return 0;
}
diff --git a/Tools/scripts/generate_opcode_h.py b/Tools/scripts/generate_opcode_h.py
index 1f21347935d83..75a9c3f3bfadb 100644
--- a/Tools/scripts/generate_opcode_h.py
+++ b/Tools/scripts/generate_opcode_h.py
@@ -36,7 +36,7 @@ def write_int_array_from_ops(name, ops, out):
bits = 0
for op in ops:
bits |= 1<<op
- out.write(f"static uint32_t {name}[8] = {{\n")
+ out.write(f"static const uint32_t {name}[8] = {{\n")
for i in range(8):
out.write(f" {bits & UINT32_MASK}U,\n")
bits >>= 32
@@ -75,9 +75,16 @@ def main(opcode_py, outfile='Include/opcode.h'):
fobj.write(DEFINE.format(name, next_op))
used[next_op] = True
fobj.write(DEFINE.format('DO_TRACING', 255))
- fobj.write("#ifdef NEED_OPCODE_JUMP_TABLES\n")
+ fobj.write("\nextern const uint8_t _PyOpcode_InlineCacheEntries[256];\n")
+ fobj.write("\n#ifdef NEED_OPCODE_TABLES\n")
write_int_array_from_ops("_PyOpcode_RelativeJump", opcode['hasjrel'], fobj)
write_int_array_from_ops("_PyOpcode_Jump", opcode['hasjrel'] + opcode['hasjabs'], fobj)
+
+ fobj.write("\nconst uint8_t _PyOpcode_InlineCacheEntries[256] = {\n")
+ for i, entries in enumerate(opcode["_inline_cache_entries"]):
+ if entries:
+ fobj.write(f" [{opname[i]}] = {entries},\n")
+ fobj.write("};\n")
fobj.write("#endif /* OPCODE_TABLES */\n")
fobj.write("\n")
@@ -90,12 +97,6 @@ def main(opcode_py, outfile='Include/opcode.h'):
for i, (op, _) in enumerate(opcode["_nb_ops"]):
fobj.write(DEFINE.format(op, i))
- fobj.write("\nstatic const uint8_t _PyOpcode_InlineCacheEntries[256] = {\n")
- for i, entries in enumerate(opcode["_inline_cache_entries"]):
- if entries:
- fobj.write(f" [{opname[i]}] = {entries},\n")
- fobj.write("};\n")
-
fobj.write(footer)
1
0
https://github.com/python/cpython/commit/da7d99a4de72aac8d436cecedf16ab2676…
commit: da7d99a4de72aac8d436cecedf16ab2676f9b785
branch: main
author: Steve Dower <steve.dower(a)python.org>
committer: zooba <steve.dower(a)microsoft.com>
date: 2022-02-28T12:06:43Z
summary:
bpo-46567: Add Tcl/Tk build for Windows ARM64 (GH-31574)
files:
A Misc/NEWS.d/next/Windows/2022-02-25-01-22-31.bpo-46567.37WEue.rst
M .azure-pipelines/tcltk-build.yml
M .azure-pipelines/windows-release/msi-steps.yml
M .azure-pipelines/windows-release/stage-build.yml
M .azure-pipelines/windows-release/stage-layout-full.yml
M .azure-pipelines/windows-release/stage-layout-msix.yml
M PCbuild/get_externals.bat
M PCbuild/pcbuild.proj
M PCbuild/prepare_tcltk.bat
M PCbuild/tcl.vcxproj
M PCbuild/tcltk.props
M PCbuild/tix.vcxproj
M PCbuild/tk.vcxproj
M Tools/msi/bundle/Default.ARM64.xsl
M Tools/msi/bundle/bundle.targets
M Tools/msi/bundle/bundle.wxs
diff --git a/.azure-pipelines/tcltk-build.yml b/.azure-pipelines/tcltk-build.yml
index 27968e886cc14..f9e50d3711a46 100644
--- a/.azure-pipelines/tcltk-build.yml
+++ b/.azure-pipelines/tcltk-build.yml
@@ -60,6 +60,12 @@ jobs:
& "$(msbuild)" PCbuild\tix.vcxproj "@msbuild.rsp" /p:Platform=x64 /p:tcltkDir="$(OutDir)\amd64"
displayName: 'Build for amd64'
+ - powershell: |
+ & "$(msbuild)" PCbuild\tcl.vcxproj "@msbuild.rsp" /p:Platform=ARM64 /p:tcltkDir="$(OutDir)\arm64"
+ & "$(msbuild)" PCbuild\tk.vcxproj "@msbuild.rsp" /p:Platform=ARM64 /p:tcltkDir="$(OutDir)\arm64"
+ & "$(msbuild)" PCbuild\tix.vcxproj "@msbuild.rsp" /p:Platform=ARM64 /p:tcltkDir="$(OutDir)\arm64"
+ displayName: 'Build for arm64'
+
- publish: '$(OutDir)'
artifact: 'tcltk'
displayName: 'Publishing tcltk'
diff --git a/.azure-pipelines/windows-release/msi-steps.yml b/.azure-pipelines/windows-release/msi-steps.yml
index ef98d56c78363..3c08a0660abe9 100644
--- a/.azure-pipelines/windows-release/msi-steps.yml
+++ b/.azure-pipelines/windows-release/msi-steps.yml
@@ -71,6 +71,13 @@ steps:
artifactName: tcltk_lib_amd64
targetPath: $(Build.BinariesDirectory)\tcltk_lib_amd64
+ - task: DownloadPipelineArtifact@1
+ displayName: 'Download artifact: tcltk_lib_arm64'
+ condition: and(succeeded(), eq(variables['PublishARM64'], 'true'))
+ inputs:
+ artifactName: tcltk_lib_arm64
+ targetPath: $(Build.BinariesDirectory)\tcltk_lib_arm64
+
- powershell: |
copy $(Build.BinariesDirectory)\amd64\Activate.ps1 Lib\venv\scripts\common\Activate.ps1 -Force
displayName: 'Copy signed files into sources'
@@ -107,7 +114,6 @@ steps:
PYTHONHOME: $(Build.SourcesDirectory)
TclTkLibraryDir: $(Build.BinariesDirectory)\tcltk_lib_win32
BuildForRelease: true
- SuppressMinGWLib: true
- script: |
%MSBUILD% Tools\msi\bundle\releaselocal.wixproj /t:Rebuild /p:RebuildAll=true
@@ -120,7 +126,6 @@ steps:
PYTHONHOME: $(Build.SourcesDirectory)
TclTkLibraryDir: $(Build.BinariesDirectory)\tcltk_lib_amd64
BuildForRelease: true
- SuppressMinGWLib: true
- script: |
%MSBUILD% Tools\msi\bundle\releaselocal.wixproj /t:Rebuild /p:RebuildAll=true
@@ -132,8 +137,8 @@ steps:
PYTHON: $(Build.BinariesDirectory)\win32\python.exe
PythonForBuild: $(Build.BinariesDirectory)\win32\python.exe
PYTHONHOME: $(Build.SourcesDirectory)
+ TclTkLibraryDir: $(Build.BinariesDirectory)\tcltk_lib_arm64
BuildForRelease: true
- SuppressMinGWLib: true
- task: CopyFiles@2
displayName: 'Assemble artifact: msi (win32)'
diff --git a/.azure-pipelines/windows-release/stage-build.yml b/.azure-pipelines/windows-release/stage-build.yml
index f70414ba21145..e45034f650fb9 100644
--- a/.azure-pipelines/windows-release/stage-build.yml
+++ b/.azure-pipelines/windows-release/stage-build.yml
@@ -166,6 +166,13 @@ jobs:
platform: x64
msbuildArguments: /t:CopyTclTkLib /p:OutDir="$(Build.ArtifactStagingDirectory)\tcl_amd64"
+ - task: MSBuild@1
+ displayName: 'Copy Tcl/Tk lib for publish'
+ inputs:
+ solution: PCbuild\tcltk.props
+ platform: ARM64
+ msbuildArguments: /t:CopyTclTkLib /p:OutDir="$(Build.ArtifactStagingDirectory)\tcl_arm64"
+
- task: PublishPipelineArtifact@0
displayName: 'Publish artifact: tcltk_lib_win32'
inputs:
@@ -177,3 +184,9 @@ jobs:
inputs:
targetPath: '$(Build.ArtifactStagingDirectory)\tcl_amd64'
artifactName: tcltk_lib_amd64
+
+ - task: PublishPipelineArtifact@0
+ displayName: 'Publish artifact: tcltk_lib_arm64'
+ inputs:
+ targetPath: '$(Build.ArtifactStagingDirectory)\tcl_arm64'
+ artifactName: tcltk_lib_arm64
diff --git a/.azure-pipelines/windows-release/stage-layout-full.yml b/.azure-pipelines/windows-release/stage-layout-full.yml
index 0ba2fc017d987..3546df60e4e03 100644
--- a/.azure-pipelines/windows-release/stage-layout-full.yml
+++ b/.azure-pipelines/windows-release/stage-layout-full.yml
@@ -26,6 +26,7 @@ jobs:
HostArch: amd64
Python: $(Build.BinariesDirectory)\bin_amd64\python.exe
PYTHONHOME: $(Build.SourcesDirectory)
+ TclLibrary: $(Build.BinariesDirectory)\tcltk_lib\tcl8
steps:
- template: ./checkout.yml
diff --git a/.azure-pipelines/windows-release/stage-layout-msix.yml b/.azure-pipelines/windows-release/stage-layout-msix.yml
index 6efd327bdb32e..913bfcd919704 100644
--- a/.azure-pipelines/windows-release/stage-layout-msix.yml
+++ b/.azure-pipelines/windows-release/stage-layout-msix.yml
@@ -25,6 +25,7 @@ jobs:
HostArch: amd64
Python: $(Build.BinariesDirectory)\bin_amd64\python.exe
PYTHONHOME: $(Build.SourcesDirectory)
+ TclLibrary: $(Build.BinariesDirectory)\tcltk_lib\tcl8
steps:
- template: ./checkout.yml
diff --git a/Misc/NEWS.d/next/Windows/2022-02-25-01-22-31.bpo-46567.37WEue.rst b/Misc/NEWS.d/next/Windows/2022-02-25-01-22-31.bpo-46567.37WEue.rst
new file mode 100644
index 0000000000000..10a2b764b7fce
--- /dev/null
+++ b/Misc/NEWS.d/next/Windows/2022-02-25-01-22-31.bpo-46567.37WEue.rst
@@ -0,0 +1,2 @@
+Adds Tcl and Tk support for Windows ARM64. This also adds IDLE to the
+installation.
diff --git a/PCbuild/get_externals.bat b/PCbuild/get_externals.bat
index 5b0fe640eb84e..d4e052ef32c82 100644
--- a/PCbuild/get_externals.bat
+++ b/PCbuild/get_externals.bat
@@ -55,8 +55,8 @@ set libraries=%libraries% bzip2-1.0.6
if NOT "%IncludeLibffiSrc%"=="false" set libraries=%libraries% libffi-3.4.2
if NOT "%IncludeSSLSrc%"=="false" set libraries=%libraries% openssl-1.1.1m
set libraries=%libraries% sqlite-3.37.2.0
-if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tcl-core-8.6.12.0
-if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tk-8.6.12.0
+if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tcl-core-8.6.12.1
+if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tk-8.6.12.1
if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tix-8.4.3.6
set libraries=%libraries% xz-5.2.2
set libraries=%libraries% zlib-1.2.11
@@ -78,7 +78,7 @@ echo.Fetching external binaries...
set binaries=
if NOT "%IncludeLibffi%"=="false" set binaries=%binaries% libffi-3.4.2
if NOT "%IncludeSSL%"=="false" set binaries=%binaries% openssl-bin-1.1.1m
-if NOT "%IncludeTkinter%"=="false" set binaries=%binaries% tcltk-8.6.12.0
+if NOT "%IncludeTkinter%"=="false" set binaries=%binaries% tcltk-8.6.12.1
if NOT "%IncludeSSLSrc%"=="false" set binaries=%binaries% nasm-2.11.06
for %%b in (%binaries%) do (
diff --git a/PCbuild/pcbuild.proj b/PCbuild/pcbuild.proj
index f32422a0acf44..2ba0627b83369 100644
--- a/PCbuild/pcbuild.proj
+++ b/PCbuild/pcbuild.proj
@@ -73,7 +73,7 @@
<!-- _ssl will build _socket as well, which may cause conflicts in parallel builds -->
<ExtensionModules Include="_socket" Condition="!$(IncludeSSL) or !$(IncludeExternals)" />
<ExternalModules Include="_ssl;_hashlib" Condition="$(IncludeSSL)" />
- <ExternalModules Include="_tkinter" Condition="$(IncludeTkinter) and $(Platform) != 'ARM' and $(Platform) != 'ARM64'" />
+ <ExternalModules Include="_tkinter" Condition="$(IncludeTkinter)" />
<ExtensionModules Include="@(ExternalModules->'%(Identity)')" Condition="$(IncludeExternals)" />
<Projects Include="@(ExtensionModules->'%(Identity).vcxproj')" Condition="$(IncludeExtensions)" />
<!-- Test modules -->
diff --git a/PCbuild/prepare_tcltk.bat b/PCbuild/prepare_tcltk.bat
index 77075af94f2c6..4a43ed1582ce3 100644
--- a/PCbuild/prepare_tcltk.bat
+++ b/PCbuild/prepare_tcltk.bat
@@ -53,3 +53,7 @@ call "%PCBUILD%\get_externals.bat" --tkinter-src %ORG_SETTING%
%MSBUILD% "%PCBUILD%\tcl.vcxproj" /p:Configuration=Release /p:Platform=x64
%MSBUILD% "%PCBUILD%\tk.vcxproj" /p:Configuration=Release /p:Platform=x64
%MSBUILD% "%PCBUILD%\tix.vcxproj" /p:Configuration=Release /p:Platform=x64
+
+%MSBUILD% "%PCBUILD%\tcl.vcxproj" /p:Configuration=Release /p:Platform=ARM64
+%MSBUILD% "%PCBUILD%\tk.vcxproj" /p:Configuration=Release /p:Platform=ARM64
+%MSBUILD% "%PCBUILD%\tix.vcxproj" /p:Configuration=Release /p:Platform=ARM64
diff --git a/PCbuild/tcl.vcxproj b/PCbuild/tcl.vcxproj
index 4536cbc925bd9..ab68db9210fbe 100644
--- a/PCbuild/tcl.vcxproj
+++ b/PCbuild/tcl.vcxproj
@@ -33,6 +33,10 @@
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
+ <ProjectConfiguration Include="Release|ARM64">
+ <Configuration>Release</Configuration>
+ <Platform>ARM64</Platform>
+ </ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{B5FD6F1D-129E-4BFF-9340-03606FAC7283}</ProjectGuid>
@@ -59,8 +63,8 @@
<NMakeBuildCommandLine>setlocal
set VCINSTALLDIR=$(VCInstallDir)
cd /D "$(tclDir)win"
-nmake -f makefile.vc MACHINE=$(TclMachine) OPTS=$(TclOpts) $(TclDirs) $(DebugFlags) $(WarningsFlags) core shell dlls
-nmake -f makefile.vc MACHINE=$(TclMachine) OPTS=$(TclOpts) $(TclDirs) $(DebugFlags) $(WarningsFlags) install-binaries install-libraries
+nmake -f makefile.vc MACHINE=$(TclMachine) OPTS=$(TclOpts) $(TclDirs) $(DebugFlags) $(WarningsFlags) TCLSH_NATIVE="$(tclWin32Exe)" core shell dlls
+nmake -f makefile.vc MACHINE=$(TclMachine) OPTS=$(TclOpts) $(TclDirs) $(DebugFlags) $(WarningsFlags) TCLSH_NATIVE="$(tclWin32Exe)" install-binaries install-libraries
copy /Y ..\license.terms "$(OutDir)\tcllicense.terms"
</NMakeBuildCommandLine>
</PropertyGroup>
diff --git a/PCbuild/tcltk.props b/PCbuild/tcltk.props
index 72cffc3ea1da6..7fd43e8279e8e 100644
--- a/PCbuild/tcltk.props
+++ b/PCbuild/tcltk.props
@@ -5,7 +5,7 @@
<TclMajorVersion>8</TclMajorVersion>
<TclMinorVersion>6</TclMinorVersion>
<TclPatchLevel>12</TclPatchLevel>
- <TclRevision>0</TclRevision>
+ <TclRevision>1</TclRevision>
<TkMajorVersion>$(TclMajorVersion)</TkMajorVersion>
<TkMinorVersion>$(TclMinorVersion)</TkMinorVersion>
<TkPatchLevel>$(TclPatchLevel)</TkPatchLevel>
@@ -18,6 +18,9 @@
<tkDir>$(ExternalsDir)tk-$(TkMajorVersion).$(TkMinorVersion).$(TkPatchLevel).$(TkRevision)\</tkDir>
<tixDir>$(ExternalsDir)tix-$(TixMajorVersion).$(TixMinorVersion).$(TixPatchLevel).$(TixRevision)\</tixDir>
<tcltkDir>$(ExternalsDir)tcltk-$(TclMajorVersion).$(TclMinorVersion).$(TclPatchLevel).$(TclRevision)\$(ArchName)\</tcltkDir>
+ <tclWin32Exe Condition="$(Platform) == 'Win32'">$(tcltkDir)\bin\tclsh$(TclMajorVersion)$(TclMinorVersion)t.exe</tclWin32Exe>
+ <tclWin32Exe Condition="$(Platform) != 'Win32'">$(tcltkDir)\..\win32\bin\tclsh$(TclMajorVersion)$(TclMinorVersion)t.exe</tclWin32Exe>
+
<!--<TclDebugExt Condition="'$(Configuration)' == 'Debug'">g</TclDebugExt>-->
<tclDLLName>tcl$(TclMajorVersion)$(TclMinorVersion)t$(TclDebugExt).dll</tclDLLName>
<tclLibName>tcl$(TclMajorVersion)$(TclMinorVersion)t$(TclDebugExt).lib</tclLibName>
diff --git a/PCbuild/tix.vcxproj b/PCbuild/tix.vcxproj
index 51682094cb844..48abcd27c8775 100644
--- a/PCbuild/tix.vcxproj
+++ b/PCbuild/tix.vcxproj
@@ -33,6 +33,10 @@
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
+ <ProjectConfiguration Include="Release|ARM64">
+ <Configuration>Release</Configuration>
+ <Platform>ARM64</Platform>
+ </ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{C5A3E7FB-9695-4B2E-960B-1D9F43F1E555}</ProjectGuid>
@@ -53,7 +57,7 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<PropertyGroup>
- <TixDirs>BUILDDIRTOP="$(BuildDirTop)" TCL_DIR="$(tclDir.TrimEnd(`\`))" TK_DIR="$(tkDir.TrimEnd(`\`))" INSTALL_DIR="$(OutDir.TrimEnd(`\`))"</TixDirs>
+ <TixDirs>BUILDDIRTOP="$(BuildDirTop)" TCL_DIR="$(tclDir.TrimEnd(`\`))" TK_DIR="$(tkDir.TrimEnd(`\`))" INSTALL_DIR="$(OutDir.TrimEnd(`\`))" TCLSH_EXE="$(tclWin32Exe)"</TixDirs>
<DebugFlags Condition="'$(Configuration)' == 'Debug'">DEBUG=1 NODEBUG=0 TCL_DBGX=g TK_DBGX=g</DebugFlags>
<DebugFlags Condition="'$(Configuration)' != 'Debug'">DEBUG=0 NODEBUG=1</DebugFlags>
<CFlags>-c -W3 -nologo -MD -wd4028 -wd4090 -wd4244 -wd4267 -wd4312</CFlags>
diff --git a/PCbuild/tk.vcxproj b/PCbuild/tk.vcxproj
index 70b5459a081c2..b111969ca5de6 100644
--- a/PCbuild/tk.vcxproj
+++ b/PCbuild/tk.vcxproj
@@ -32,6 +32,10 @@
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|ARM64">
+ <Configuration>Release</Configuration>
+ <Platform>ARM64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
@@ -60,8 +64,8 @@
<NMakeBuildCommandLine>setlocal
set VCINSTALLDIR=$(VCInstallDir)
cd /D "$(tkDir)win"
-nmake /nologo -f makefile.vc RC=rc MACHINE=$(TclMachine) OPTS=$(TkOpts) $(TkDirs) $(DebugFlags) $(WarningsFlags) all
-nmake /nologo -f makefile.vc RC=rc MACHINE=$(TclMachine) OPTS=$(TkOpts) $(TkDirs) $(DebugFlags) $(WarningsFlags) install-binaries install-libraries
+nmake /nologo -f makefile.vc RC=rc MACHINE=$(TclMachine) OPTS=$(TkOpts) $(TkDirs) $(DebugFlags) $(WarningsFlags) TCLSH_NATIVE="$(tclWin32Exe)" all
+nmake /nologo -f makefile.vc RC=rc MACHINE=$(TclMachine) OPTS=$(TkOpts) $(TkDirs) $(DebugFlags) $(WarningsFlags) TCLSH_NATIVE="$(tclWin32Exe)" install-binaries install-libraries
copy /Y ..\license.terms "$(OutDir)\tklicense.terms"
</NMakeBuildCommandLine>
</PropertyGroup>
diff --git a/Tools/msi/bundle/Default.ARM64.xsl b/Tools/msi/bundle/Default.ARM64.xsl
index 0dd1c9e6a3d52..f63da4e7274cb 100644
--- a/Tools/msi/bundle/Default.ARM64.xsl
+++ b/Tools/msi/bundle/Default.ARM64.xsl
@@ -13,14 +13,11 @@
<xsl:template match="*[local-name()='String' and @Id='InstallButtonNote']">
<String Id="InstallButtonNote">[TargetDir]
-Includes pip and documentation
+Includes IDLE, pip and documentation
Creates shortcuts but no file associations</String>
</xsl:template>
<xsl:template match="*[local-name()='String' and @Id='Include_launcherHelp']">
<String Id="Include_launcherHelp">(The 'py' launcher is currently unavailable on ARM64.)</String>
</xsl:template>
- <xsl:template match="*[local-name()='String' and @Id='Include_tcltkHelpLabel']">
- <String Id="Include_tcltkHelpLabel">(tcl/tk and IDLE are currently unavailable on ARM64.)</String>
- </xsl:template>
</xsl:stylesheet>
\ No newline at end of file
diff --git a/Tools/msi/bundle/bundle.targets b/Tools/msi/bundle/bundle.targets
index 4f4306f7b61f0..89a5960a50efe 100644
--- a/Tools/msi/bundle/bundle.targets
+++ b/Tools/msi/bundle/bundle.targets
@@ -69,7 +69,7 @@
<Package Include="..\path\path*.wixproj" />
<Package Include="..\appendpath\appendpath*.wixproj" />
<Package Include="..\pip\pip*.wixproj" />
- <Package Include="..\tcltk\tcltk*.wixproj" Condition="$(Platform) != 'ARM64'" />
+ <Package Include="..\tcltk\tcltk*.wixproj" />
<Package Include="..\test\test*.wixproj" />
<Package Include="..\tools\tools*.wixproj" />
<Package Include="..\ucrt\ucrt*.wixproj" Condition="$(Platform) != 'ARM64'" />
diff --git a/Tools/msi/bundle/bundle.wxs b/Tools/msi/bundle/bundle.wxs
index 5c9fd6dca394c..340c72acf408b 100644
--- a/Tools/msi/bundle/bundle.wxs
+++ b/Tools/msi/bundle/bundle.wxs
@@ -77,12 +77,7 @@
<Variable Name="Include_test" Value="1" bal:Overridable="yes" />
<Variable Name="Include_doc" Value="1" bal:Overridable="yes" />
<Variable Name="Include_tools" Value="1" bal:Overridable="yes" />
- <?if $(var.Platform)~="ARM64" ?>
- <Variable Name="Include_tcltk" Value="0" />
- <Variable Name="Include_tcltkState" Value="disable" />
- <?else ?>
<Variable Name="Include_tcltk" Value="1" bal:Overridable="yes" />
- <?endif ?>
<Variable Name="Include_pip" Value="1" bal:Overridable="yes" />
<?if $(var.Platform)~="ARM64" ?>
<Variable Name="Include_launcher" Value="0" bal:Overridable="yes" />
@@ -122,8 +117,8 @@
<PackageGroupRef Id="test" />
<PackageGroupRef Id="doc" />
<PackageGroupRef Id="tools" />
- <?if $(var.Platform)!="ARM64" ?>
<PackageGroupRef Id="tcltk" />
+ <?if $(var.Platform)!="ARM64" ?>
<PackageGroupRef Id="launcher" />
<?endif ?>
<PackageGroupRef Id="pip" />
1
0
https://github.com/python/cpython/commit/424ecab494d538650ba34937cdd710094c…
commit: 424ecab494d538650ba34937cdd710094ccb2275
branch: main
author: Brandt Bucher <brandtbucher(a)microsoft.com>
committer: markshannon <mark(a)hotpy.org>
date: 2022-02-28T11:54:14Z
summary:
bpo-46841: Use inline caching for `UNPACK_SEQUENCE` (GH-31591)
files:
A Misc/NEWS.d/next/Core and Builtins/2022-02-25-15-18-40.bpo-46841.tmLpgC.rst
M Include/internal/pycore_code.h
M Include/opcode.h
M Lib/importlib/_bootstrap_external.py
M Lib/opcode.py
M Python/ceval.c
M Python/specialize.c
diff --git a/Include/internal/pycore_code.h b/Include/internal/pycore_code.h
index 0c4850f98a318..0e401d61f7673 100644
--- a/Include/internal/pycore_code.h
+++ b/Include/internal/pycore_code.h
@@ -68,9 +68,16 @@ typedef struct {
_Py_CODEUNIT counter;
} _PyBinaryOpCache;
+typedef struct {
+ _Py_CODEUNIT counter;
+} _PyUnpackSequenceCache;
+
#define INLINE_CACHE_ENTRIES_BINARY_OP \
(sizeof(_PyBinaryOpCache) / sizeof(_Py_CODEUNIT))
+#define INLINE_CACHE_ENTRIES_UNPACK_SEQUENCE \
+ (sizeof(_PyUnpackSequenceCache) / sizeof(_Py_CODEUNIT))
+
/* Maximum size of code to quicken, in code units. */
#define MAX_SIZE_TO_QUICKEN 5000
@@ -312,7 +319,7 @@ extern void _Py_Specialize_BinaryOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *
int oparg);
extern void _Py_Specialize_CompareOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr, SpecializedCacheEntry *cache);
extern void _Py_Specialize_UnpackSequence(PyObject *seq, _Py_CODEUNIT *instr,
- SpecializedCacheEntry *cache);
+ int oparg);
/* Deallocator function for static codeobjects used in deepfreeze.py */
extern void _PyStaticCode_Dealloc(PyCodeObject *co);
diff --git a/Include/opcode.h b/Include/opcode.h
index 0862f96e7de9e..ae21d92a865e5 100644
--- a/Include/opcode.h
+++ b/Include/opcode.h
@@ -241,6 +241,7 @@ static uint32_t _PyOpcode_Jump[8] = {
#define NB_INPLACE_XOR 25
static const uint8_t _PyOpcode_InlineCacheEntries[256] = {
+ [UNPACK_SEQUENCE] = 1,
[BINARY_OP] = 1,
};
diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py
index 53fe1b8fc217a..be23eeed9df74 100644
--- a/Lib/importlib/_bootstrap_external.py
+++ b/Lib/importlib/_bootstrap_external.py
@@ -388,6 +388,7 @@ def _write_atomic(path, data, mode=0o666):
# Python 3.11a5 3479 (Add PUSH_NULL opcode)
# Python 3.11a5 3480 (New CALL opcodes, second iteration)
# Python 3.11a5 3481 (Use inline CACHE instructions)
+# Python 3.11a5 3482 (Use inline caching for UNPACK_SEQUENCE)
# Python 3.12 will start with magic number 3500
@@ -402,7 +403,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 = (3481).to_bytes(2, 'little') + b'\r\n'
+MAGIC_NUMBER = (3482).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 84ad002c8dde8..8fa71bf4d180a 100644
--- a/Lib/opcode.py
+++ b/Lib/opcode.py
@@ -109,7 +109,7 @@ def jabs_op(name, op, entries=0):
name_op('STORE_NAME', 90) # Index in name list
name_op('DELETE_NAME', 91) # ""
-def_op('UNPACK_SEQUENCE', 92) # Number of tuple items
+def_op('UNPACK_SEQUENCE', 92, 1) # Number of tuple items
jrel_op('FOR_ITER', 93)
def_op('UNPACK_EX', 94)
name_op('STORE_ATTR', 95) # Index in name list
diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-02-25-15-18-40.bpo-46841.tmLpgC.rst b/Misc/NEWS.d/next/Core and Builtins/2022-02-25-15-18-40.bpo-46841.tmLpgC.rst
new file mode 100644
index 0000000000000..fec18aa51369d
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2022-02-25-15-18-40.bpo-46841.tmLpgC.rst
@@ -0,0 +1 @@
+Use inline caching for :opcode:`UNPACK_SEQUENCE`.
diff --git a/Python/ceval.c b/Python/ceval.c
index 4c0a71b036e8b..fe75782972992 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -2758,22 +2758,22 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
}
STACK_GROW(oparg);
Py_DECREF(seq);
+ JUMPBY(INLINE_CACHE_ENTRIES_UNPACK_SEQUENCE);
DISPATCH();
}
TARGET(UNPACK_SEQUENCE_ADAPTIVE) {
assert(cframe.use_tracing == 0);
- SpecializedCacheEntry *cache = GET_CACHE();
- if (cache->adaptive.counter == 0) {
+ _PyUnpackSequenceCache *cache = (_PyUnpackSequenceCache *)next_instr;
+ if (cache->counter == 0) {
PyObject *seq = TOP();
next_instr--;
- _Py_Specialize_UnpackSequence(seq, next_instr, cache);
+ _Py_Specialize_UnpackSequence(seq, next_instr, oparg);
DISPATCH();
}
else {
STAT_INC(UNPACK_SEQUENCE, deferred);
- cache->adaptive.counter--;
- oparg = cache->adaptive.original_oparg;
+ cache->counter--;
JUMP_TO_INSTRUCTION(UNPACK_SEQUENCE);
}
}
@@ -2786,36 +2786,37 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
SET_TOP(Py_NewRef(PyTuple_GET_ITEM(seq, 1)));
PUSH(Py_NewRef(PyTuple_GET_ITEM(seq, 0)));
Py_DECREF(seq);
+ JUMPBY(INLINE_CACHE_ENTRIES_UNPACK_SEQUENCE);
NOTRACE_DISPATCH();
}
TARGET(UNPACK_SEQUENCE_TUPLE) {
PyObject *seq = TOP();
- int len = GET_CACHE()->adaptive.original_oparg;
DEOPT_IF(!PyTuple_CheckExact(seq), UNPACK_SEQUENCE);
- DEOPT_IF(PyTuple_GET_SIZE(seq) != len, UNPACK_SEQUENCE);
+ DEOPT_IF(PyTuple_GET_SIZE(seq) != oparg, UNPACK_SEQUENCE);
STAT_INC(UNPACK_SEQUENCE, hit);
STACK_SHRINK(1);
PyObject **items = _PyTuple_ITEMS(seq);
- while (len--) {
- PUSH(Py_NewRef(items[len]));
+ while (oparg--) {
+ PUSH(Py_NewRef(items[oparg]));
}
Py_DECREF(seq);
+ JUMPBY(INLINE_CACHE_ENTRIES_UNPACK_SEQUENCE);
NOTRACE_DISPATCH();
}
TARGET(UNPACK_SEQUENCE_LIST) {
PyObject *seq = TOP();
- int len = GET_CACHE()->adaptive.original_oparg;
DEOPT_IF(!PyList_CheckExact(seq), UNPACK_SEQUENCE);
- DEOPT_IF(PyList_GET_SIZE(seq) != len, UNPACK_SEQUENCE);
+ DEOPT_IF(PyList_GET_SIZE(seq) != oparg, UNPACK_SEQUENCE);
STAT_INC(UNPACK_SEQUENCE, hit);
STACK_SHRINK(1);
PyObject **items = _PyList_ITEMS(seq);
- while (len--) {
- PUSH(Py_NewRef(items[len]));
+ while (oparg--) {
+ PUSH(Py_NewRef(items[oparg]));
}
Py_DECREF(seq);
+ JUMPBY(INLINE_CACHE_ENTRIES_UNPACK_SEQUENCE);
NOTRACE_DISPATCH();
}
@@ -5600,7 +5601,7 @@ MISS_WITH_CACHE(CALL)
MISS_WITH_INLINE_CACHE(BINARY_OP)
MISS_WITH_CACHE(COMPARE_OP)
MISS_WITH_CACHE(BINARY_SUBSCR)
-MISS_WITH_CACHE(UNPACK_SEQUENCE)
+MISS_WITH_INLINE_CACHE(UNPACK_SEQUENCE)
MISS_WITH_OPARG_COUNTER(STORE_SUBSCR)
LOAD_ATTR_INSTANCE_VALUE_miss:
diff --git a/Python/specialize.c b/Python/specialize.c
index 1624f1955d42a..b88c5d517bd8f 100644
--- a/Python/specialize.c
+++ b/Python/specialize.c
@@ -67,7 +67,6 @@ static uint8_t cache_requirements[256] = {
[PRECALL] = 2, /* _PyAdaptiveEntry and _PyObjectCache/_PyCallCache */
[STORE_ATTR] = 1, // _PyAdaptiveEntry
[COMPARE_OP] = 1, /* _PyAdaptiveEntry */
- [UNPACK_SEQUENCE] = 1, // _PyAdaptiveEntry
};
Py_ssize_t _Py_QuickenedCount = 0;
@@ -2133,39 +2132,39 @@ unpack_sequence_fail_kind(PyObject *seq)
#endif
void
-_Py_Specialize_UnpackSequence(PyObject *seq, _Py_CODEUNIT *instr,
- SpecializedCacheEntry *cache)
+_Py_Specialize_UnpackSequence(PyObject *seq, _Py_CODEUNIT *instr, int oparg)
{
- _PyAdaptiveEntry *adaptive = &cache->adaptive;
+ assert(_PyOpcode_InlineCacheEntries[UNPACK_SEQUENCE] ==
+ INLINE_CACHE_ENTRIES_UNPACK_SEQUENCE);
+ _PyUnpackSequenceCache *cache = (_PyUnpackSequenceCache *)(instr + 1);
if (PyTuple_CheckExact(seq)) {
- if (PyTuple_GET_SIZE(seq) != adaptive->original_oparg) {
+ if (PyTuple_GET_SIZE(seq) != oparg) {
SPECIALIZATION_FAIL(UNPACK_SEQUENCE, SPEC_FAIL_EXPECTED_ERROR);
goto failure;
}
if (PyTuple_GET_SIZE(seq) == 2) {
- *instr = _Py_MAKECODEUNIT(UNPACK_SEQUENCE_TWO_TUPLE,
- _Py_OPARG(*instr));
+ *instr = _Py_MAKECODEUNIT(UNPACK_SEQUENCE_TWO_TUPLE, oparg);
goto success;
}
- *instr = _Py_MAKECODEUNIT(UNPACK_SEQUENCE_TUPLE, _Py_OPARG(*instr));
+ *instr = _Py_MAKECODEUNIT(UNPACK_SEQUENCE_TUPLE, oparg);
goto success;
}
if (PyList_CheckExact(seq)) {
- if (PyList_GET_SIZE(seq) != adaptive->original_oparg) {
+ if (PyList_GET_SIZE(seq) != oparg) {
SPECIALIZATION_FAIL(UNPACK_SEQUENCE, SPEC_FAIL_EXPECTED_ERROR);
goto failure;
}
- *instr = _Py_MAKECODEUNIT(UNPACK_SEQUENCE_LIST, _Py_OPARG(*instr));
+ *instr = _Py_MAKECODEUNIT(UNPACK_SEQUENCE_LIST, oparg);
goto success;
}
SPECIALIZATION_FAIL(UNPACK_SEQUENCE, unpack_sequence_fail_kind(seq));
failure:
STAT_INC(UNPACK_SEQUENCE, failure);
- cache_backoff(adaptive);
+ cache->counter = ADAPTIVE_CACHE_BACKOFF;
return;
success:
STAT_INC(UNPACK_SEQUENCE, success);
- adaptive->counter = initial_counter_value();
+ cache->counter = initial_counter_value();
}
#ifdef Py_STATS
1
0
https://github.com/python/cpython/commit/c32aef48533769161e1247927a5b418322…
commit: c32aef48533769161e1247927a5b418322e0860c
branch: main
author: Erlend Egeberg Aasland <erlend.aasland(a)innova.no>
committer: corona10 <donghee.na92(a)gmail.com>
date: 2022-02-28T18:07:40+09:00
summary:
bpo-46541: Remove unneeded visits from sqlite3 (GH-31609)
files:
M Modules/_sqlite/module.c
diff --git a/Modules/_sqlite/module.c b/Modules/_sqlite/module.c
index 35cdcbe0a5c38..70fde4910f6a4 100644
--- a/Modules/_sqlite/module.c
+++ b/Modules/_sqlite/module.c
@@ -590,13 +590,6 @@ module_traverse(PyObject *module, visitproc visit, void *arg)
Py_VISIT(state->lru_cache);
Py_VISIT(state->psyco_adapters);
- // Interned strings
- Py_VISIT(state->str___adapt__);
- Py_VISIT(state->str___conform__);
- Py_VISIT(state->str_executescript);
- Py_VISIT(state->str_finalize);
- Py_VISIT(state->str_upper);
-
return 0;
}
1
0
https://github.com/python/cpython/commit/088dd76dba68c2538776d9920607f81e54…
commit: 088dd76dba68c2538776d9920607f81e54544cbd
branch: main
author: Dong-hee Na <donghee.na(a)python.org>
committer: tiran <christian(a)python.org>
date: 2022-02-28T08:06:58+01:00
summary:
bpo-46541: Remove unnecessary Py_VISIT (GH-31608)
files:
M Modules/_csv.c
M Modules/arraymodule.c
diff --git a/Modules/_csv.c b/Modules/_csv.c
index ebc3328d0cf0d..991b623d6d6d3 100644
--- a/Modules/_csv.c
+++ b/Modules/_csv.c
@@ -60,7 +60,6 @@ _csv_traverse(PyObject *module, visitproc visit, void *arg)
Py_VISIT(module_state->dialect_type);
Py_VISIT(module_state->reader_type);
Py_VISIT(module_state->writer_type);
- Py_VISIT(module_state->str_write);
return 0;
}
diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c
index 2d6da1aaac85a..73104ce8f1787 100644
--- a/Modules/arraymodule.c
+++ b/Modules/arraymodule.c
@@ -3034,11 +3034,6 @@ array_traverse(PyObject *module, visitproc visit, void *arg)
array_state *state = get_array_state(module);
Py_VISIT(state->ArrayType);
Py_VISIT(state->ArrayIterType);
- Py_VISIT(state->str_read);
- Py_VISIT(state->str_write);
- Py_VISIT(state->str__array_reconstructor);
- Py_VISIT(state->str___dict__);
- Py_VISIT(state->str_iter);
return 0;
}
1
0
bpo-46786: Make ElementTree write the HTML tags embed, source, track, wbr as empty tags (GH-31406)
by scoder 27 Feb '22
by scoder 27 Feb '22
27 Feb '22
https://github.com/python/cpython/commit/345572a1a0263076081020524016eae867…
commit: 345572a1a0263076081020524016eae867677cac
branch: main
author: Jannis Vajen <jvajen(a)gmail.com>
committer: scoder <stefan_ml(a)behnel.de>
date: 2022-02-27T15:25:54+01:00
summary:
bpo-46786: Make ElementTree write the HTML tags embed, source, track, wbr as empty tags (GH-31406)
See https://html.spec.whatwg.org/multipage/syntax.html#void-elements
for reference.
files:
A Misc/NEWS.d/next/Library/2022-02-18-12-10-26.bpo-46786.P0xRvS.rst
M Lib/test/test_xml_etree.py
M Lib/xml/etree/ElementTree.py
diff --git a/Lib/test/test_xml_etree.py b/Lib/test/test_xml_etree.py
index c5292b5e9ef68..35d901f9d0824 100644
--- a/Lib/test/test_xml_etree.py
+++ b/Lib/test/test_xml_etree.py
@@ -1350,8 +1350,9 @@ def test_processinginstruction(self):
def test_html_empty_elems_serialization(self):
# issue 15970
# from http://www.w3.org/TR/html401/index/elements.html
- for element in ['AREA', 'BASE', 'BASEFONT', 'BR', 'COL', 'FRAME', 'HR',
- 'IMG', 'INPUT', 'ISINDEX', 'LINK', 'META', 'PARAM']:
+ for element in ['AREA', 'BASE', 'BASEFONT', 'BR', 'COL', 'EMBED', 'FRAME',
+ 'HR', 'IMG', 'INPUT', 'ISINDEX', 'LINK', 'META', 'PARAM',
+ 'SOURCE', 'TRACK', 'WBR']:
for elem in [element, element.lower()]:
expected = '<%s>' % elem
serialized = serialize(ET.XML('<%s />' % elem), method='html')
diff --git a/Lib/xml/etree/ElementTree.py b/Lib/xml/etree/ElementTree.py
index e9409fd29a115..6059e2f592d2d 100644
--- a/Lib/xml/etree/ElementTree.py
+++ b/Lib/xml/etree/ElementTree.py
@@ -918,13 +918,9 @@ def _serialize_xml(write, elem, qnames, namespaces,
if elem.tail:
write(_escape_cdata(elem.tail))
-HTML_EMPTY = ("area", "base", "basefont", "br", "col", "frame", "hr",
- "img", "input", "isindex", "link", "meta", "param")
-
-try:
- HTML_EMPTY = set(HTML_EMPTY)
-except NameError:
- pass
+HTML_EMPTY = {"area", "base", "basefont", "br", "col", "embed", "frame", "hr",
+ "img", "input", "isindex", "link", "meta", "param", "source",
+ "track", "wbr"}
def _serialize_html(write, elem, qnames, namespaces, **kwargs):
tag = elem.tag
diff --git a/Misc/NEWS.d/next/Library/2022-02-18-12-10-26.bpo-46786.P0xRvS.rst b/Misc/NEWS.d/next/Library/2022-02-18-12-10-26.bpo-46786.P0xRvS.rst
new file mode 100644
index 0000000000000..e0384a8558dee
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2022-02-18-12-10-26.bpo-46786.P0xRvS.rst
@@ -0,0 +1,2 @@
+The HTML serialisation in xml.etree.ElementTree now writes ``embed``,
+``source``, ``track`` and ``wbr`` as empty tags, as defined in HTML 5.
1
0