Skip to content

Commit

Permalink
gh-101799: implement PREP_RERAISE_STAR as an intrinsic function (#101800
Browse files Browse the repository at this point in the history
)
  • Loading branch information
iritkatriel authored Feb 14, 2023
1 parent 3690688 commit 81e3aa8
Show file tree
Hide file tree
Showing 13 changed files with 107 additions and 73 deletions.
26 changes: 15 additions & 11 deletions Doc/library/dis.rst
Original file line number Diff line number Diff line change
Expand Up @@ -768,16 +768,6 @@ iterations of the loop.

.. versionadded:: 3.11

.. opcode:: PREP_RERAISE_STAR

Combines the raised and reraised exceptions list from ``STACK[-1]``, into an
exception group to propagate from a try-except* block. Uses the original exception
group from ``STACK[-2]`` to reconstruct the structure of reraised exceptions. Pops
two items from the stack and pushes the exception to reraise or ``None``
if there isn't one.

.. versionadded:: 3.11

.. opcode:: WITH_EXCEPT_START

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

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

The operand determines which intrinsic function is called:

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

.. versionadded:: 3.12

.. opcode:: CALL_INTRINSIC_2

Calls an intrinsic function with two arguments. Passes ``STACK[-2]``, ``STACK[-1]`` as the
arguments and sets ``STACK[-1]`` to the result. Used to implement functionality that is
necessary but not performance critical.

The operand determines which intrinsic function is called:

* ``0`` Not valid
* ``1`` Calculates the :exc:`ExceptionGroup` to raise from a ``try-except*``.

.. versionadded:: 3.12


**Pseudo-instructions**

Expand Down
13 changes: 13 additions & 0 deletions Include/internal/pycore_intrinsics.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@

/* Unary Functions: */

#define INTRINSIC_PRINT 1
#define INTRINSIC_IMPORT_STAR 2
#define INTRINSIC_STOPITERATION_ERROR 3
Expand All @@ -8,6 +10,17 @@

#define MAX_INTRINSIC_1 6


/* Binary Functions: */

#define INTRINSIC_PREP_RERAISE_STAR 1

#define MAX_INTRINSIC_2 1


typedef PyObject *(*instrinsic_func1)(PyThreadState* tstate, PyObject *value);
typedef PyObject *(*instrinsic_func2)(PyThreadState* tstate, PyObject *value1, PyObject *value2);

extern instrinsic_func1 _PyIntrinsics_UnaryFunctions[];
extern instrinsic_func2 _PyIntrinsics_BinaryFunctions[];

18 changes: 9 additions & 9 deletions Include/internal/pycore_opcode.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 10 additions & 10 deletions Include/opcode.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Lib/importlib/_bootstrap_external.py
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,7 @@ def _write_atomic(path, data, mode=0o666):
# Python 3.12a5 3517 (Change YIELD_VALUE oparg to exception block depth)
# Python 3.12a5 3518 (Add RETURN_CONST instruction)
# Python 3.12a5 3519 (Modify SEND instruction)
# Python 3.12a5 3520 (Remove PREP_RERAISE_STAR, add CALL_INTRINSIC_2)

# Python 3.13 will start with 3550

Expand All @@ -445,7 +446,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 = (3519).to_bytes(2, 'little') + b'\r\n'
MAGIC_NUMBER = (3520).to_bytes(2, 'little') + b'\r\n'

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

Expand Down
2 changes: 1 addition & 1 deletion Lib/opcode.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,6 @@ def pseudo_op(name, op, real_ops):

def_op('SETUP_ANNOTATIONS', 85)

def_op('PREP_RERAISE_STAR', 88)
def_op('POP_EXCEPT', 89)

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

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

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Add :opcode:`CALL_INTRINSIC_2` and use it instead of
:opcode:`PREP_RERAISE_STAR`.
20 changes: 9 additions & 11 deletions Python/bytecodes.c
Original file line number Diff line number Diff line change
Expand Up @@ -501,7 +501,14 @@ dummy_func(
inst(CALL_INTRINSIC_1, (value -- res)) {
assert(oparg <= MAX_INTRINSIC_1);
res = _PyIntrinsics_UnaryFunctions[oparg](tstate, value);
Py_DECREF(value);
DECREF_INPUTS();
ERROR_IF(res == NULL, error);
}

inst(CALL_INTRINSIC_2, (value2, value1 -- res)) {
assert(oparg <= MAX_INTRINSIC_2);
res = _PyIntrinsics_BinaryFunctions[oparg](tstate, value2, value1);
DECREF_INPUTS();
ERROR_IF(res == NULL, error);
}

Expand Down Expand Up @@ -788,15 +795,6 @@ dummy_func(
goto exception_unwind;
}

inst(PREP_RERAISE_STAR, (orig, excs -- val)) {
assert(PyList_Check(excs));

val = _PyExc_PrepReraiseStar(orig, excs);
DECREF_INPUTS();

ERROR_IF(val == NULL, error);
}

inst(END_ASYNC_FOR, (awaitable, exc -- )) {
assert(exc && PyExceptionInstance_Check(exc));
if (PyErr_GivenExceptionMatches(exc, PyExc_StopAsyncIteration)) {
Expand Down Expand Up @@ -2383,7 +2381,7 @@ dummy_func(
}

// Cache layout: counter/1, func_version/2, min_args/1
// Neither CALL_INTRINSIC_1 nor CALL_FUNCTION_EX are members!
// Neither CALL_INTRINSIC_1/2 nor CALL_FUNCTION_EX are members!
family(call, INLINE_CACHE_ENTRIES_CALL) = {
CALL,
CALL_BOUND_METHOD_EXACT_ARGS,
Expand Down
4 changes: 2 additions & 2 deletions Python/compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -3431,7 +3431,7 @@ compiler_try_except(struct compiler *c, stmt_ty s)
[orig, res, rest] Ln+1: LIST_APPEND 1 ) add unhandled exc to res (could be None)
[orig, res] PREP_RERAISE_STAR
[orig, res] CALL_INTRINSIC_2 PREP_RERAISE_STAR
[exc] COPY 1
[exc, exc] POP_JUMP_IF_NOT_NONE RER
[exc] POP_TOP
Expand Down Expand Up @@ -3580,7 +3580,7 @@ compiler_try_star_except(struct compiler *c, stmt_ty s)
NEW_JUMP_TARGET_LABEL(c, reraise);

USE_LABEL(c, reraise_star);
ADDOP(c, NO_LOCATION, PREP_RERAISE_STAR);
ADDOP_I(c, NO_LOCATION, CALL_INTRINSIC_2, INTRINSIC_PREP_RERAISE_STAR);
ADDOP_I(c, NO_LOCATION, COPY, 1);
ADDOP_JUMP(c, NO_LOCATION, POP_JUMP_IF_NOT_NONE, reraise);

Expand Down
30 changes: 14 additions & 16 deletions Python/generated_cases.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 18 additions & 0 deletions Python/intrinsics.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "pycore_pyerrors.h"


/******** Unary functions ********/

static PyObject *
no_intrinsic(PyThreadState* tstate, PyObject *unused)
Expand Down Expand Up @@ -208,3 +209,20 @@ _PyIntrinsics_UnaryFunctions[] = {
[INTRINSIC_UNARY_POSITIVE] = unary_pos,
[INTRINSIC_LIST_TO_TUPLE] = list_to_tuple,
};


/******** Binary functions ********/


static PyObject *
prep_reraise_star(PyThreadState* unused, PyObject *orig, PyObject *excs)
{
assert(PyList_Check(excs));
return _PyExc_PrepReraiseStar(orig, excs);
}

instrinsic_func2
_PyIntrinsics_BinaryFunctions[] = {
[INTRINSIC_PREP_RERAISE_STAR] = prep_reraise_star,
};

Loading

0 comments on commit 81e3aa8

Please sign in to comment.