mirror of
https://github.com/python/cpython.git
synced 2025-12-04 00:30:19 +00:00
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
This commit is contained in:
parent
73dc1c678e
commit
9cefcc0ee7
22 changed files with 663 additions and 651 deletions
39
Python/executor_cases.c.h
generated
39
Python/executor_cases.c.h
generated
|
|
@ -2883,23 +2883,45 @@
|
|||
break;
|
||||
}
|
||||
|
||||
/* _BEFORE_ASYNC_WITH is not a viable micro-op for tier 2 because it has both popping and not-popping errors */
|
||||
|
||||
/* _BEFORE_WITH is not a viable micro-op for tier 2 because it has both popping and not-popping errors */
|
||||
case _LOAD_SPECIAL: {
|
||||
PyObject *owner;
|
||||
PyObject *attr;
|
||||
PyObject *self_or_null;
|
||||
oparg = CURRENT_OPARG();
|
||||
owner = stack_pointer[-1];
|
||||
assert(oparg <= SPECIAL_MAX);
|
||||
PyObject *name = _Py_SpecialMethods[oparg].name;
|
||||
attr = _PyObject_LookupSpecialMethod(owner, name, &self_or_null);
|
||||
if (attr == NULL) {
|
||||
if (!_PyErr_Occurred(tstate)) {
|
||||
_PyErr_Format(tstate, PyExc_TypeError,
|
||||
_Py_SpecialMethods[oparg].error,
|
||||
Py_TYPE(owner)->tp_name);
|
||||
}
|
||||
}
|
||||
if (attr == NULL) JUMP_TO_ERROR();
|
||||
stack_pointer[-1] = attr;
|
||||
stack_pointer[0] = self_or_null;
|
||||
stack_pointer += 1;
|
||||
break;
|
||||
}
|
||||
|
||||
case _WITH_EXCEPT_START: {
|
||||
PyObject *val;
|
||||
PyObject *lasti;
|
||||
PyObject *exit_self;
|
||||
PyObject *exit_func;
|
||||
PyObject *res;
|
||||
val = stack_pointer[-1];
|
||||
lasti = stack_pointer[-3];
|
||||
exit_func = stack_pointer[-4];
|
||||
exit_self = stack_pointer[-4];
|
||||
exit_func = stack_pointer[-5];
|
||||
/* At the top of the stack are 4 values:
|
||||
- val: TOP = exc_info()
|
||||
- unused: SECOND = previous exception
|
||||
- lasti: THIRD = lasti of exception in exc_info()
|
||||
- exit_func: FOURTH = the context.__exit__ bound method
|
||||
- exit_self: FOURTH = the context or NULL
|
||||
- exit_func: FIFTH = the context.__exit__ function or context.__exit__ bound method
|
||||
We call FOURTH(type(TOP), TOP, GetTraceback(TOP)).
|
||||
Then we push the __exit__ return value.
|
||||
*/
|
||||
|
|
@ -2915,9 +2937,10 @@
|
|||
}
|
||||
assert(PyLong_Check(lasti));
|
||||
(void)lasti; // Shut up compiler warning if asserts are off
|
||||
PyObject *stack[4] = {NULL, exc, val, tb};
|
||||
res = PyObject_Vectorcall(exit_func, stack + 1,
|
||||
3 | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL);
|
||||
PyObject *stack[5] = {NULL, exit_self, exc, val, tb};
|
||||
int has_self = (exit_self != NULL);
|
||||
res = PyObject_Vectorcall(exit_func, stack + 2 - has_self,
|
||||
(3 + has_self) | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL);
|
||||
if (res == NULL) JUMP_TO_ERROR();
|
||||
stack_pointer[0] = res;
|
||||
stack_pointer += 1;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue