mirror of
https://github.com/python/cpython.git
synced 2025-10-21 14:12:27 +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
|
@ -2814,79 +2814,27 @@ dummy_func(
|
|||
_FOR_ITER_GEN_FRAME +
|
||||
_PUSH_FRAME;
|
||||
|
||||
inst(BEFORE_ASYNC_WITH, (mgr -- exit, res)) {
|
||||
PyObject *enter = _PyObject_LookupSpecial(mgr, &_Py_ID(__aenter__));
|
||||
if (enter == NULL) {
|
||||
inst(LOAD_SPECIAL, (owner -- attr, self_or_null)) {
|
||||
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,
|
||||
"'%.200s' object does not support the "
|
||||
"asynchronous context manager protocol",
|
||||
Py_TYPE(mgr)->tp_name);
|
||||
_Py_SpecialMethods[oparg].error,
|
||||
Py_TYPE(owner)->tp_name);
|
||||
}
|
||||
ERROR_NO_POP();
|
||||
}
|
||||
exit = _PyObject_LookupSpecial(mgr, &_Py_ID(__aexit__));
|
||||
if (exit == NULL) {
|
||||
if (!_PyErr_Occurred(tstate)) {
|
||||
_PyErr_Format(tstate, PyExc_TypeError,
|
||||
"'%.200s' object does not support the "
|
||||
"asynchronous context manager protocol "
|
||||
"(missed __aexit__ method)",
|
||||
Py_TYPE(mgr)->tp_name);
|
||||
}
|
||||
Py_DECREF(enter);
|
||||
ERROR_NO_POP();
|
||||
}
|
||||
DECREF_INPUTS();
|
||||
res = PyObject_CallNoArgs(enter);
|
||||
Py_DECREF(enter);
|
||||
if (res == NULL) {
|
||||
Py_DECREF(exit);
|
||||
ERROR_IF(true, error);
|
||||
}
|
||||
ERROR_IF(attr == NULL, error);
|
||||
}
|
||||
|
||||
inst(BEFORE_WITH, (mgr -- exit, res)) {
|
||||
/* pop the context manager, push its __exit__ and the
|
||||
* value returned from calling its __enter__
|
||||
*/
|
||||
PyObject *enter = _PyObject_LookupSpecial(mgr, &_Py_ID(__enter__));
|
||||
if (enter == NULL) {
|
||||
if (!_PyErr_Occurred(tstate)) {
|
||||
_PyErr_Format(tstate, PyExc_TypeError,
|
||||
"'%.200s' object does not support the "
|
||||
"context manager protocol",
|
||||
Py_TYPE(mgr)->tp_name);
|
||||
}
|
||||
ERROR_NO_POP();
|
||||
}
|
||||
exit = _PyObject_LookupSpecial(mgr, &_Py_ID(__exit__));
|
||||
if (exit == NULL) {
|
||||
if (!_PyErr_Occurred(tstate)) {
|
||||
_PyErr_Format(tstate, PyExc_TypeError,
|
||||
"'%.200s' object does not support the "
|
||||
"context manager protocol "
|
||||
"(missed __exit__ method)",
|
||||
Py_TYPE(mgr)->tp_name);
|
||||
}
|
||||
Py_DECREF(enter);
|
||||
ERROR_NO_POP();
|
||||
}
|
||||
DECREF_INPUTS();
|
||||
res = PyObject_CallNoArgs(enter);
|
||||
Py_DECREF(enter);
|
||||
if (res == NULL) {
|
||||
Py_DECREF(exit);
|
||||
ERROR_IF(true, error);
|
||||
}
|
||||
}
|
||||
|
||||
inst(WITH_EXCEPT_START, (exit_func, lasti, unused, val -- exit_func, lasti, unused, val, res)) {
|
||||
inst(WITH_EXCEPT_START, (exit_func, exit_self, lasti, unused, val -- exit_func, exit_self, lasti, unused, val, res)) {
|
||||
/* 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.
|
||||
*/
|
||||
|
@ -2903,9 +2851,10 @@ dummy_func(
|
|||
}
|
||||
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);
|
||||
ERROR_IF(res == NULL, error);
|
||||
}
|
||||
|
||||
|
|
|
@ -343,6 +343,29 @@ const conversion_func _PyEval_ConversionFuncs[4] = {
|
|||
[FVC_ASCII] = PyObject_ASCII
|
||||
};
|
||||
|
||||
const _Py_SpecialMethod _Py_SpecialMethods[] = {
|
||||
[SPECIAL___ENTER__] = {
|
||||
.name = &_Py_ID(__enter__),
|
||||
.error = "'%.200s' object does not support the "
|
||||
"context manager protocol (missed __enter__ method)",
|
||||
},
|
||||
[SPECIAL___EXIT__] = {
|
||||
.name = &_Py_ID(__exit__),
|
||||
.error = "'%.200s' object does not support the "
|
||||
"context manager protocol (missed __exit__ method)",
|
||||
},
|
||||
[SPECIAL___AENTER__] = {
|
||||
.name = &_Py_ID(__aenter__),
|
||||
.error = "'%.200s' object does not support the asynchronous "
|
||||
"context manager protocol (missed __aenter__ method)",
|
||||
},
|
||||
[SPECIAL___AEXIT__] = {
|
||||
.name = &_Py_ID(__aexit__),
|
||||
.error = "'%.200s' object does not support the asynchronous "
|
||||
"context manager protocol (missed __aexit__ method)",
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// PEP 634: Structural Pattern Matching
|
||||
|
||||
|
|
|
@ -1260,7 +1260,7 @@ compiler_call_exit_with_nones(struct compiler *c, location loc)
|
|||
ADDOP_LOAD_CONST(c, loc, Py_None);
|
||||
ADDOP_LOAD_CONST(c, loc, Py_None);
|
||||
ADDOP_LOAD_CONST(c, loc, Py_None);
|
||||
ADDOP_I(c, loc, CALL, 2);
|
||||
ADDOP_I(c, loc, CALL, 3);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -1369,6 +1369,7 @@ compiler_unwind_fblock(struct compiler *c, location *ploc,
|
|||
*ploc = LOC((stmt_ty)info->fb_datum);
|
||||
ADDOP(c, *ploc, POP_BLOCK);
|
||||
if (preserve_tos) {
|
||||
ADDOP_I(c, *ploc, SWAP, 3);
|
||||
ADDOP_I(c, *ploc, SWAP, 2);
|
||||
}
|
||||
RETURN_IF_ERROR(compiler_call_exit_with_nones(c, *ploc));
|
||||
|
@ -5897,6 +5898,7 @@ compiler_with_except_finish(struct compiler *c, jump_target_label cleanup) {
|
|||
ADDOP(c, NO_LOCATION, POP_EXCEPT);
|
||||
ADDOP(c, NO_LOCATION, POP_TOP);
|
||||
ADDOP(c, NO_LOCATION, POP_TOP);
|
||||
ADDOP(c, NO_LOCATION, POP_TOP);
|
||||
NEW_JUMP_TARGET_LABEL(c, exit);
|
||||
ADDOP_JUMP(c, NO_LOCATION, JUMP_NO_INTERRUPT, exit);
|
||||
|
||||
|
@ -5952,7 +5954,12 @@ compiler_async_with(struct compiler *c, stmt_ty s, int pos)
|
|||
/* Evaluate EXPR */
|
||||
VISIT(c, expr, item->context_expr);
|
||||
loc = LOC(item->context_expr);
|
||||
ADDOP(c, loc, BEFORE_ASYNC_WITH);
|
||||
ADDOP_I(c, loc, COPY, 1);
|
||||
ADDOP_I(c, loc, LOAD_SPECIAL, SPECIAL___AEXIT__);
|
||||
ADDOP_I(c, loc, SWAP, 2);
|
||||
ADDOP_I(c, loc, SWAP, 3);
|
||||
ADDOP_I(c, loc, LOAD_SPECIAL, SPECIAL___AENTER__);
|
||||
ADDOP_I(c, loc, CALL, 0);
|
||||
ADDOP_I(c, loc, GET_AWAITABLE, 1);
|
||||
ADDOP_LOAD_CONST(c, loc, Py_None);
|
||||
ADD_YIELD_FROM(c, loc, 1);
|
||||
|
@ -6050,7 +6057,12 @@ compiler_with(struct compiler *c, stmt_ty s, int pos)
|
|||
VISIT(c, expr, item->context_expr);
|
||||
/* Will push bound __exit__ */
|
||||
location loc = LOC(item->context_expr);
|
||||
ADDOP(c, loc, BEFORE_WITH);
|
||||
ADDOP_I(c, loc, COPY, 1);
|
||||
ADDOP_I(c, loc, LOAD_SPECIAL, SPECIAL___EXIT__);
|
||||
ADDOP_I(c, loc, SWAP, 2);
|
||||
ADDOP_I(c, loc, SWAP, 3);
|
||||
ADDOP_I(c, loc, LOAD_SPECIAL, SPECIAL___ENTER__);
|
||||
ADDOP_I(c, loc, CALL, 0);
|
||||
ADDOP_JUMP(c, loc, SETUP_WITH, final);
|
||||
|
||||
/* SETUP_WITH pushes a finally block. */
|
||||
|
|
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;
|
||||
|
|
128
Python/generated_cases.c.h
generated
128
Python/generated_cases.c.h
generated
|
@ -9,95 +9,6 @@
|
|||
#define TIER_ONE 1
|
||||
|
||||
|
||||
TARGET(BEFORE_ASYNC_WITH) {
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 1;
|
||||
INSTRUCTION_STATS(BEFORE_ASYNC_WITH);
|
||||
PyObject *mgr;
|
||||
PyObject *exit;
|
||||
PyObject *res;
|
||||
mgr = stack_pointer[-1];
|
||||
PyObject *enter = _PyObject_LookupSpecial(mgr, &_Py_ID(__aenter__));
|
||||
if (enter == NULL) {
|
||||
if (!_PyErr_Occurred(tstate)) {
|
||||
_PyErr_Format(tstate, PyExc_TypeError,
|
||||
"'%.200s' object does not support the "
|
||||
"asynchronous context manager protocol",
|
||||
Py_TYPE(mgr)->tp_name);
|
||||
}
|
||||
goto error;
|
||||
}
|
||||
exit = _PyObject_LookupSpecial(mgr, &_Py_ID(__aexit__));
|
||||
if (exit == NULL) {
|
||||
if (!_PyErr_Occurred(tstate)) {
|
||||
_PyErr_Format(tstate, PyExc_TypeError,
|
||||
"'%.200s' object does not support the "
|
||||
"asynchronous context manager protocol "
|
||||
"(missed __aexit__ method)",
|
||||
Py_TYPE(mgr)->tp_name);
|
||||
}
|
||||
Py_DECREF(enter);
|
||||
goto error;
|
||||
}
|
||||
Py_DECREF(mgr);
|
||||
res = PyObject_CallNoArgs(enter);
|
||||
Py_DECREF(enter);
|
||||
if (res == NULL) {
|
||||
Py_DECREF(exit);
|
||||
if (true) goto pop_1_error;
|
||||
}
|
||||
stack_pointer[-1] = exit;
|
||||
stack_pointer[0] = res;
|
||||
stack_pointer += 1;
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
TARGET(BEFORE_WITH) {
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 1;
|
||||
INSTRUCTION_STATS(BEFORE_WITH);
|
||||
PyObject *mgr;
|
||||
PyObject *exit;
|
||||
PyObject *res;
|
||||
mgr = stack_pointer[-1];
|
||||
/* pop the context manager, push its __exit__ and the
|
||||
* value returned from calling its __enter__
|
||||
*/
|
||||
PyObject *enter = _PyObject_LookupSpecial(mgr, &_Py_ID(__enter__));
|
||||
if (enter == NULL) {
|
||||
if (!_PyErr_Occurred(tstate)) {
|
||||
_PyErr_Format(tstate, PyExc_TypeError,
|
||||
"'%.200s' object does not support the "
|
||||
"context manager protocol",
|
||||
Py_TYPE(mgr)->tp_name);
|
||||
}
|
||||
goto error;
|
||||
}
|
||||
exit = _PyObject_LookupSpecial(mgr, &_Py_ID(__exit__));
|
||||
if (exit == NULL) {
|
||||
if (!_PyErr_Occurred(tstate)) {
|
||||
_PyErr_Format(tstate, PyExc_TypeError,
|
||||
"'%.200s' object does not support the "
|
||||
"context manager protocol "
|
||||
"(missed __exit__ method)",
|
||||
Py_TYPE(mgr)->tp_name);
|
||||
}
|
||||
Py_DECREF(enter);
|
||||
goto error;
|
||||
}
|
||||
Py_DECREF(mgr);
|
||||
res = PyObject_CallNoArgs(enter);
|
||||
Py_DECREF(enter);
|
||||
if (res == NULL) {
|
||||
Py_DECREF(exit);
|
||||
if (true) goto pop_1_error;
|
||||
}
|
||||
stack_pointer[-1] = exit;
|
||||
stack_pointer[0] = res;
|
||||
stack_pointer += 1;
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
TARGET(BINARY_OP) {
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 2;
|
||||
|
@ -4635,6 +4546,31 @@
|
|||
DISPATCH();
|
||||
}
|
||||
|
||||
TARGET(LOAD_SPECIAL) {
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 1;
|
||||
INSTRUCTION_STATS(LOAD_SPECIAL);
|
||||
PyObject *owner;
|
||||
PyObject *attr;
|
||||
PyObject *self_or_null;
|
||||
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) goto pop_1_error;
|
||||
stack_pointer[-1] = attr;
|
||||
stack_pointer[0] = self_or_null;
|
||||
stack_pointer += 1;
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
TARGET(LOAD_SUPER_ATTR) {
|
||||
frame->instr_ptr = next_instr;
|
||||
next_instr += 2;
|
||||
|
@ -6210,16 +6146,19 @@
|
|||
INSTRUCTION_STATS(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.
|
||||
*/
|
||||
|
@ -6235,9 +6174,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) goto error;
|
||||
stack_pointer[0] = res;
|
||||
stack_pointer += 1;
|
||||
|
|
8
Python/opcode_targets.h
generated
8
Python/opcode_targets.h
generated
|
@ -1,10 +1,8 @@
|
|||
static void *opcode_targets[256] = {
|
||||
&&TARGET_CACHE,
|
||||
&&TARGET_BEFORE_ASYNC_WITH,
|
||||
&&TARGET_BEFORE_WITH,
|
||||
&&TARGET_BINARY_OP_INPLACE_ADD_UNICODE,
|
||||
&&TARGET_BINARY_SLICE,
|
||||
&&TARGET_BINARY_SUBSCR,
|
||||
&&TARGET_BINARY_OP_INPLACE_ADD_UNICODE,
|
||||
&&TARGET_CHECK_EG_MATCH,
|
||||
&&TARGET_CHECK_EXC_MATCH,
|
||||
&&TARGET_CLEANUP_THROW,
|
||||
|
@ -16,9 +14,9 @@ static void *opcode_targets[256] = {
|
|||
&&TARGET_FORMAT_SIMPLE,
|
||||
&&TARGET_FORMAT_WITH_SPEC,
|
||||
&&TARGET_GET_AITER,
|
||||
&&TARGET_RESERVED,
|
||||
&&TARGET_GET_ANEXT,
|
||||
&&TARGET_GET_ITER,
|
||||
&&TARGET_RESERVED,
|
||||
&&TARGET_GET_LEN,
|
||||
&&TARGET_GET_YIELD_FROM_ITER,
|
||||
&&TARGET_INTERPRETER_EXIT,
|
||||
|
@ -92,6 +90,7 @@ static void *opcode_targets[256] = {
|
|||
&&TARGET_LOAD_FROM_DICT_OR_GLOBALS,
|
||||
&&TARGET_LOAD_GLOBAL,
|
||||
&&TARGET_LOAD_NAME,
|
||||
&&TARGET_LOAD_SPECIAL,
|
||||
&&TARGET_LOAD_SUPER_ATTR,
|
||||
&&TARGET_MAKE_CELL,
|
||||
&&TARGET_MAP_ADD,
|
||||
|
@ -148,6 +147,7 @@ static void *opcode_targets[256] = {
|
|||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&TARGET_RESUME,
|
||||
&&TARGET_BINARY_OP_ADD_FLOAT,
|
||||
&&TARGET_BINARY_OP_ADD_INT,
|
||||
|
|
|
@ -774,6 +774,12 @@ dummy_func(void) {
|
|||
}
|
||||
}
|
||||
|
||||
op(_LOAD_SPECIAL, (owner -- attr, self_or_null)) {
|
||||
(void)owner;
|
||||
attr = sym_new_not_null(ctx);
|
||||
self_or_null = sym_new_unknown(ctx);
|
||||
}
|
||||
|
||||
op(_JUMP_TO_TOP, (--)) {
|
||||
ctx->done = true;
|
||||
}
|
||||
|
@ -782,7 +788,6 @@ dummy_func(void) {
|
|||
ctx->done = true;
|
||||
}
|
||||
|
||||
|
||||
// END BYTECODES //
|
||||
|
||||
}
|
||||
|
|
16
Python/optimizer_cases.c.h
generated
16
Python/optimizer_cases.c.h
generated
|
@ -1368,9 +1368,19 @@
|
|||
break;
|
||||
}
|
||||
|
||||
/* _BEFORE_ASYNC_WITH is not a viable micro-op for tier 2 */
|
||||
|
||||
/* _BEFORE_WITH is not a viable micro-op for tier 2 */
|
||||
case _LOAD_SPECIAL: {
|
||||
_Py_UopsSymbol *owner;
|
||||
_Py_UopsSymbol *attr;
|
||||
_Py_UopsSymbol *self_or_null;
|
||||
owner = stack_pointer[-1];
|
||||
(void)owner;
|
||||
attr = sym_new_not_null(ctx);
|
||||
self_or_null = sym_new_unknown(ctx);
|
||||
stack_pointer[-1] = attr;
|
||||
stack_pointer[0] = self_or_null;
|
||||
stack_pointer += 1;
|
||||
break;
|
||||
}
|
||||
|
||||
case _WITH_EXCEPT_START: {
|
||||
_Py_UopsSymbol *res;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue