Skip to content

Commit 9cefcc0

Browse files
authored
GH-120507: Lower the BEFORE_WITH and BEFORE_ASYNC_WITH instructions. (#120640)
* Remove BEFORE_WITH and BEFORE_ASYNC_WITH instructions. * Add LOAD_SPECIAL instruction * Reimplement `with` and `async with` statements using LOAD_SPECIAL
1 parent 73dc1c6 commit 9cefcc0

22 files changed

+663
-651
lines changed

Doc/library/dis.rst

+11-22
Original file line numberDiff line numberDiff line change
@@ -780,16 +780,6 @@ not have to be) the original ``STACK[-2]``.
780780
.. versionadded:: 3.12
781781

782782

783-
.. opcode:: BEFORE_ASYNC_WITH
784-
785-
Resolves ``__aenter__`` and ``__aexit__`` from ``STACK[-1]``.
786-
Pushes ``__aexit__`` and result of ``__aenter__()`` to the stack::
787-
788-
STACK.extend((__aexit__, __aenter__())
789-
790-
.. versionadded:: 3.5
791-
792-
793783

794784
**Miscellaneous opcodes**
795785

@@ -944,18 +934,6 @@ iterations of the loop.
944934
Pushes :func:`!builtins.__build_class__` onto the stack. It is later called
945935
to construct a class.
946936

947-
948-
.. opcode:: BEFORE_WITH
949-
950-
This opcode performs several operations before a with block starts. First,
951-
it loads :meth:`~object.__exit__` from the context manager and pushes it onto
952-
the stack for later use by :opcode:`WITH_EXCEPT_START`. Then,
953-
:meth:`~object.__enter__` is called. Finally, the result of calling the
954-
``__enter__()`` method is pushed onto the stack.
955-
956-
.. versionadded:: 3.11
957-
958-
959937
.. opcode:: GET_LEN
960938

961939
Perform ``STACK.append(len(STACK[-1]))``.
@@ -1812,6 +1790,17 @@ iterations of the loop.
18121790
.. versionadded:: 3.12
18131791

18141792

1793+
.. opcode:: LOAD_SPECIAL
1794+
1795+
Performs special method lookup on ``STACK[-1]``.
1796+
If ``type(STACK[-1]).__xxx__`` is a method, leave
1797+
``type(STACK[-1]).__xxx__; STACK[-1]`` on the stack.
1798+
If ``type(STACK[-1]).__xxx__`` is not a method, leave
1799+
``STACK[-1].__xxx__; NULL`` on the stack.
1800+
1801+
.. versionadded:: 3.14
1802+
1803+
18151804
**Pseudo-instructions**
18161805

18171806
These opcodes do not appear in Python bytecode. They are used by the compiler

Include/ceval.h

+7
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,13 @@ PyAPI_FUNC(void) PyEval_ReleaseThread(PyThreadState *tstate);
133133
#define FVS_MASK 0x4
134134
#define FVS_HAVE_SPEC 0x4
135135

136+
/* Special methods used by LOAD_SPECIAL */
137+
#define SPECIAL___ENTER__ 0
138+
#define SPECIAL___EXIT__ 1
139+
#define SPECIAL___AENTER__ 2
140+
#define SPECIAL___AEXIT__ 3
141+
#define SPECIAL_MAX 3
142+
136143
#ifndef Py_LIMITED_API
137144
# define Py_CPYTHON_CEVAL_H
138145
# include "cpython/ceval.h"

Include/internal/pycore_ceval.h

+7
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,13 @@ typedef PyObject *(*conversion_func)(PyObject *);
245245
PyAPI_DATA(const binaryfunc) _PyEval_BinaryOps[];
246246
PyAPI_DATA(const conversion_func) _PyEval_ConversionFuncs[];
247247

248+
typedef struct _special_method {
249+
PyObject *name;
250+
const char *error;
251+
} _Py_SpecialMethod;
252+
253+
PyAPI_DATA(const _Py_SpecialMethod) _Py_SpecialMethods[];
254+
248255
PyAPI_FUNC(int) _PyEval_CheckExceptStarTypeValid(PyThreadState *tstate, PyObject* right);
249256
PyAPI_FUNC(int) _PyEval_CheckExceptTypeValid(PyThreadState *tstate, PyObject* right);
250257
PyAPI_FUNC(int) _PyEval_ExceptionGroupMatch(PyObject* exc_value, PyObject *match_type, PyObject **match, PyObject **rest);

Include/internal/pycore_object.h

+1
Original file line numberDiff line numberDiff line change
@@ -709,6 +709,7 @@ extern int _PyObject_IsInstanceDictEmpty(PyObject *);
709709

710710
// Export for 'math' shared extension
711711
PyAPI_FUNC(PyObject*) _PyObject_LookupSpecial(PyObject *, PyObject *);
712+
PyAPI_FUNC(PyObject*) _PyObject_LookupSpecialMethod(PyObject *self, PyObject *attr, PyObject **self_or_null);
712713

713714
extern int _PyObject_IsAbstract(PyObject *);
714715

Include/internal/pycore_opcode_metadata.h

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

Include/internal/pycore_uop_ids.h

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

Include/internal/pycore_uop_metadata.h

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

0 commit comments

Comments
 (0)