Skip to content

Commit 517d7ef

Browse files
committed
Merge branch 'main' into optimize-unary-negate
2 parents 20ca87b + b150b6a commit 517d7ef

File tree

7 files changed

+56
-2
lines changed

7 files changed

+56
-2
lines changed

Doc/c-api/typeobj.rst

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -686,6 +686,26 @@ and :c:data:`PyType_Type` effectively act as defaults.)
686686
instance, and call the type's :c:member:`~PyTypeObject.tp_free` function to
687687
free the object itself.
688688

689+
If you may call functions that may set the error indicator, you must use
690+
:c:func:`PyErr_GetRaisedException` and :c:func:`PyErr_SetRaisedException`
691+
to ensure you don't clobber a preexisting error indicator (the deallocation
692+
could have occurred while processing a different error):
693+
694+
.. code-block:: c
695+
696+
static void
697+
foo_dealloc(foo_object *self)
698+
{
699+
PyObject *et, *ev, *etb;
700+
PyObject *exc = PyErr_GetRaisedException();
701+
...
702+
PyErr_SetRaisedException(exc);
703+
}
704+
705+
The dealloc handler itself must not raise an exception; if it hits an error
706+
case it should call :c:func:`PyErr_FormatUnraisable` to log (and clear) an
707+
unraisable exception.
708+
689709
No guarantees are made about when an object is destroyed, except:
690710

691711
* Python will destroy an object immediately or some time after the final

Lib/test/test_capi/test_opt.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2275,6 +2275,21 @@ def f(n):
22752275
self.assertIn("_UNPACK_SEQUENCE_TWO_TUPLE", uops)
22762276
self.assertNotIn("_GUARD_TOS_TUPLE", uops)
22772277

2278+
def test_unary_invert_long_type(self):
2279+
def testfunc(n):
2280+
for _ in range(n):
2281+
a = 9397
2282+
x = ~a + ~a
2283+
2284+
testfunc(TIER2_THRESHOLD)
2285+
2286+
ex = get_first_executor(testfunc)
2287+
self.assertIsNotNone(ex)
2288+
uops = get_opnames(ex)
2289+
2290+
self.assertNotIn("_GUARD_TOS_INT", uops)
2291+
self.assertNotIn("_GUARD_NOS_INT", uops)
2292+
22782293
def test_unary_negative_long_float_type(self):
22792294
def testfunc(n):
22802295
for _ in range(n):
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Optimize ``_UNARY_INVERT`` in JIT-compiled code.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Document that error indicator may be set in tp_dealloc, and how to avoid
2+
clobbering it.

Modules/md5module.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ MD5Type_copy_impl(MD5object *self, PyTypeObject *cls)
120120
newobj->hash_state = Hacl_Hash_MD5_copy(self->hash_state);
121121
LEAVE_HASHLIB(self);
122122
if (newobj->hash_state == NULL) {
123-
Py_DECREF(self);
123+
Py_DECREF(newobj);
124124
return PyErr_NoMemory();
125125
}
126126
return (PyObject *)newobj;

Python/optimizer_bytecodes.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -467,6 +467,15 @@ dummy_func(void) {
467467
res = sym_new_truthiness(ctx, value, false);
468468
}
469469

470+
op(_UNARY_INVERT, (value -- res)) {
471+
if (sym_matches_type(value, &PyLong_Type)) {
472+
res = sym_new_type(ctx, &PyLong_Type);
473+
}
474+
else {
475+
res = sym_new_not_null(ctx);
476+
}
477+
}
478+
470479
op(_UNARY_NEGATIVE, (value -- res)) {
471480
PyTypeObject *type = sym_get_type(value);
472481
if (type == &PyLong_Type || type == &PyFloat_Type) {

Python/optimizer_cases.c.h

Lines changed: 8 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)