Skip to content

Commit 81e3aa8

Browse files
authored
gh-101799: implement PREP_RERAISE_STAR as an intrinsic function (#101800)
1 parent 3690688 commit 81e3aa8

13 files changed

+107
-73
lines changed

Doc/library/dis.rst

+15-11
Original file line numberDiff line numberDiff line change
@@ -768,16 +768,6 @@ iterations of the loop.
768768

769769
.. versionadded:: 3.11
770770

771-
.. opcode:: PREP_RERAISE_STAR
772-
773-
Combines the raised and reraised exceptions list from ``STACK[-1]``, into an
774-
exception group to propagate from a try-except* block. Uses the original exception
775-
group from ``STACK[-2]`` to reconstruct the structure of reraised exceptions. Pops
776-
two items from the stack and pushes the exception to reraise or ``None``
777-
if there isn't one.
778-
779-
.. versionadded:: 3.11
780-
781771
.. opcode:: WITH_EXCEPT_START
782772

783773
Calls the function in position 4 on the stack with arguments (type, val, tb)
@@ -1515,7 +1505,8 @@ iterations of the loop.
15151505
.. opcode:: CALL_INTRINSIC_1
15161506

15171507
Calls an intrinsic function with one argument. Passes ``STACK[-1]`` as the
1518-
argument and sets ``STACK[-1]`` to the result. Used to implement functionality that is necessary but not performance critical.
1508+
argument and sets ``STACK[-1]`` to the result. Used to implement
1509+
functionality that is necessary but not performance critical.
15191510

15201511
The operand determines which intrinsic function is called:
15211512

@@ -1529,6 +1520,19 @@ iterations of the loop.
15291520

15301521
.. versionadded:: 3.12
15311522

1523+
.. opcode:: CALL_INTRINSIC_2
1524+
1525+
Calls an intrinsic function with two arguments. Passes ``STACK[-2]``, ``STACK[-1]`` as the
1526+
arguments and sets ``STACK[-1]`` to the result. Used to implement functionality that is
1527+
necessary but not performance critical.
1528+
1529+
The operand determines which intrinsic function is called:
1530+
1531+
* ``0`` Not valid
1532+
* ``1`` Calculates the :exc:`ExceptionGroup` to raise from a ``try-except*``.
1533+
1534+
.. versionadded:: 3.12
1535+
15321536

15331537
**Pseudo-instructions**
15341538

Include/internal/pycore_intrinsics.h

+13
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11

2+
/* Unary Functions: */
3+
24
#define INTRINSIC_PRINT 1
35
#define INTRINSIC_IMPORT_STAR 2
46
#define INTRINSIC_STOPITERATION_ERROR 3
@@ -8,6 +10,17 @@
810

911
#define MAX_INTRINSIC_1 6
1012

13+
14+
/* Binary Functions: */
15+
16+
#define INTRINSIC_PREP_RERAISE_STAR 1
17+
18+
#define MAX_INTRINSIC_2 1
19+
20+
1121
typedef PyObject *(*instrinsic_func1)(PyThreadState* tstate, PyObject *value);
22+
typedef PyObject *(*instrinsic_func2)(PyThreadState* tstate, PyObject *value1, PyObject *value2);
1223

1324
extern instrinsic_func1 _PyIntrinsics_UnaryFunctions[];
25+
extern instrinsic_func2 _PyIntrinsics_BinaryFunctions[];
26+

Include/internal/pycore_opcode.h

+9-9
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Include/opcode.h

+10-10
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Lib/importlib/_bootstrap_external.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,7 @@ def _write_atomic(path, data, mode=0o666):
433433
# Python 3.12a5 3517 (Change YIELD_VALUE oparg to exception block depth)
434434
# Python 3.12a5 3518 (Add RETURN_CONST instruction)
435435
# Python 3.12a5 3519 (Modify SEND instruction)
436+
# Python 3.12a5 3520 (Remove PREP_RERAISE_STAR, add CALL_INTRINSIC_2)
436437

437438
# Python 3.13 will start with 3550
438439

@@ -445,7 +446,7 @@ def _write_atomic(path, data, mode=0o666):
445446
# Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array
446447
# in PC/launcher.c must also be updated.
447448

448-
MAGIC_NUMBER = (3519).to_bytes(2, 'little') + b'\r\n'
449+
MAGIC_NUMBER = (3520).to_bytes(2, 'little') + b'\r\n'
449450

450451
_RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c
451452

Lib/opcode.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,6 @@ def pseudo_op(name, op, real_ops):
127127

128128
def_op('SETUP_ANNOTATIONS', 85)
129129

130-
def_op('PREP_RERAISE_STAR', 88)
131130
def_op('POP_EXCEPT', 89)
132131

133132
HAVE_ARGUMENT = 90 # real opcodes from here have an argument:
@@ -224,6 +223,7 @@ def pseudo_op(name, op, real_ops):
224223
def_op('KW_NAMES', 172)
225224
hasconst.append(172)
226225
def_op('CALL_INTRINSIC_1', 173)
226+
def_op('CALL_INTRINSIC_2', 174)
227227

228228
hasarg.extend([op for op in opmap.values() if op >= HAVE_ARGUMENT])
229229

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Add :opcode:`CALL_INTRINSIC_2` and use it instead of
2+
:opcode:`PREP_RERAISE_STAR`.

Python/bytecodes.c

+9-11
Original file line numberDiff line numberDiff line change
@@ -501,7 +501,14 @@ dummy_func(
501501
inst(CALL_INTRINSIC_1, (value -- res)) {
502502
assert(oparg <= MAX_INTRINSIC_1);
503503
res = _PyIntrinsics_UnaryFunctions[oparg](tstate, value);
504-
Py_DECREF(value);
504+
DECREF_INPUTS();
505+
ERROR_IF(res == NULL, error);
506+
}
507+
508+
inst(CALL_INTRINSIC_2, (value2, value1 -- res)) {
509+
assert(oparg <= MAX_INTRINSIC_2);
510+
res = _PyIntrinsics_BinaryFunctions[oparg](tstate, value2, value1);
511+
DECREF_INPUTS();
505512
ERROR_IF(res == NULL, error);
506513
}
507514

@@ -788,15 +795,6 @@ dummy_func(
788795
goto exception_unwind;
789796
}
790797

791-
inst(PREP_RERAISE_STAR, (orig, excs -- val)) {
792-
assert(PyList_Check(excs));
793-
794-
val = _PyExc_PrepReraiseStar(orig, excs);
795-
DECREF_INPUTS();
796-
797-
ERROR_IF(val == NULL, error);
798-
}
799-
800798
inst(END_ASYNC_FOR, (awaitable, exc -- )) {
801799
assert(exc && PyExceptionInstance_Check(exc));
802800
if (PyErr_GivenExceptionMatches(exc, PyExc_StopAsyncIteration)) {
@@ -2383,7 +2381,7 @@ dummy_func(
23832381
}
23842382

23852383
// Cache layout: counter/1, func_version/2, min_args/1
2386-
// Neither CALL_INTRINSIC_1 nor CALL_FUNCTION_EX are members!
2384+
// Neither CALL_INTRINSIC_1/2 nor CALL_FUNCTION_EX are members!
23872385
family(call, INLINE_CACHE_ENTRIES_CALL) = {
23882386
CALL,
23892387
CALL_BOUND_METHOD_EXACT_ARGS,

Python/compile.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -3431,7 +3431,7 @@ compiler_try_except(struct compiler *c, stmt_ty s)
34313431
34323432
[orig, res, rest] Ln+1: LIST_APPEND 1 ) add unhandled exc to res (could be None)
34333433
3434-
[orig, res] PREP_RERAISE_STAR
3434+
[orig, res] CALL_INTRINSIC_2 PREP_RERAISE_STAR
34353435
[exc] COPY 1
34363436
[exc, exc] POP_JUMP_IF_NOT_NONE RER
34373437
[exc] POP_TOP
@@ -3580,7 +3580,7 @@ compiler_try_star_except(struct compiler *c, stmt_ty s)
35803580
NEW_JUMP_TARGET_LABEL(c, reraise);
35813581

35823582
USE_LABEL(c, reraise_star);
3583-
ADDOP(c, NO_LOCATION, PREP_RERAISE_STAR);
3583+
ADDOP_I(c, NO_LOCATION, CALL_INTRINSIC_2, INTRINSIC_PREP_RERAISE_STAR);
35843584
ADDOP_I(c, NO_LOCATION, COPY, 1);
35853585
ADDOP_JUMP(c, NO_LOCATION, POP_JUMP_IF_NOT_NONE, reraise);
35863586

Python/generated_cases.c.h

+14-16
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Python/intrinsics.c

+18
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "pycore_pyerrors.h"
1010

1111

12+
/******** Unary functions ********/
1213

1314
static PyObject *
1415
no_intrinsic(PyThreadState* tstate, PyObject *unused)
@@ -208,3 +209,20 @@ _PyIntrinsics_UnaryFunctions[] = {
208209
[INTRINSIC_UNARY_POSITIVE] = unary_pos,
209210
[INTRINSIC_LIST_TO_TUPLE] = list_to_tuple,
210211
};
212+
213+
214+
/******** Binary functions ********/
215+
216+
217+
static PyObject *
218+
prep_reraise_star(PyThreadState* unused, PyObject *orig, PyObject *excs)
219+
{
220+
assert(PyList_Check(excs));
221+
return _PyExc_PrepReraiseStar(orig, excs);
222+
}
223+
224+
instrinsic_func2
225+
_PyIntrinsics_BinaryFunctions[] = {
226+
[INTRINSIC_PREP_RERAISE_STAR] = prep_reraise_star,
227+
};
228+

0 commit comments

Comments
 (0)