diff options
Diffstat (limited to 'Python')
-rw-r--r-- | Python/bytecodes.c | 8 | ||||
-rw-r--r-- | Python/executor_cases.c.h | 184 | ||||
-rw-r--r-- | Python/generated_cases.c.h | 350 | ||||
-rw-r--r-- | Python/optimizer_bytecodes.c | 18 | ||||
-rw-r--r-- | Python/optimizer_cases.c.h | 153 |
5 files changed, 131 insertions, 582 deletions
diff --git a/Python/bytecodes.c b/Python/bytecodes.c index 8d7e137c829..b2900ba951a 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -163,7 +163,7 @@ dummy_func( op(_CHECK_PERIODIC_IF_NOT_YIELD_FROM, (--)) { if ((oparg & RESUME_OPARG_LOCATION_MASK) < RESUME_AFTER_YIELD_FROM) { _Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY(); - QSBR_QUIESCENT_STATE(tstate); \ + QSBR_QUIESCENT_STATE(tstate); if (_Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) & _PY_EVAL_EVENTS_MASK) { int err = _Py_HandlePending(tstate); ERROR_IF(err != 0, error); @@ -2245,7 +2245,8 @@ dummy_func( PyObject *attr_o = FT_ATOMIC_LOAD_PTR_ACQUIRE(*value_ptr); DEOPT_IF(attr_o == NULL); #ifdef Py_GIL_DISABLED - if (!_Py_TryIncrefCompareStackRef(value_ptr, attr_o, &attr)) { + int increfed = _Py_TryIncrefCompareStackRef(value_ptr, attr_o, &attr); + if (!increfed) { DEOPT_IF(true); } #else @@ -2322,7 +2323,8 @@ dummy_func( } STAT_INC(LOAD_ATTR, hit); #ifdef Py_GIL_DISABLED - if (!_Py_TryIncrefCompareStackRef(&ep->me_value, attr_o, &attr)) { + int increfed = _Py_TryIncrefCompareStackRef(&ep->me_value, attr_o, &attr); + if (!increfed) { DEOPT_IF(true); } #else diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h index ca64d7557e3..ccdf74a575b 100644 --- a/Python/executor_cases.c.h +++ b/Python/executor_cases.c.h @@ -30,7 +30,7 @@ oparg = CURRENT_OPARG(); if ((oparg & RESUME_OPARG_LOCATION_MASK) < RESUME_AFTER_YIELD_FROM) { _Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY(); - QSBR_QUIESCENT_STATE(tstate); \ + QSBR_QUIESCENT_STATE(tstate); if (_Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) & _PY_EVAL_EVENTS_MASK) { _PyFrame_SetStackPointer(frame, stack_pointer); int err = _Py_HandlePending(tstate); @@ -601,11 +601,6 @@ case _END_FOR: { _PyStackRef value; value = stack_pointer[-1]; - /* Don't update instr_ptr, so that POP_ITER sees - * the FOR_ITER as the previous instruction. - * This has the benign side effect that if value is - * finalized it will see the location as the FOR_ITER's. - */ stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); _PyFrame_SetStackPointer(frame, stack_pointer); @@ -749,7 +744,6 @@ _PyStackRef value; _PyStackRef res; value = stack_pointer[-1]; - // This one is a bit weird, because we expect *some* failures: if (!PyStackRef_IsNone(value)) { UOP_STAT_INC(uopcode, miss); JUMP_TO_JUMP_TARGET(); @@ -1111,17 +1105,6 @@ JUMP_TO_JUMP_TARGET(); } STAT_INC(BINARY_OP, hit); - /* Handle `left = left + right` or `left += right` for str. - * - * When possible, extend `left` in place rather than - * allocating a new PyUnicodeObject. This attempts to avoid - * quadratic behavior when one neglects to use str.join(). - * - * If `left` has only two references remaining (one from - * the stack, one in the locals), DECREFing `left` leaves - * only the locals reference, so PyUnicode_Append knows - * that the string is safe to mutate. - */ assert(Py_REFCNT(left_o) >= 2 || !PyStackRef_IsHeapSafe(left)); PyStackRef_CLOSE_SPECIALIZED(left, _PyUnicode_ExactDealloc); PyObject *temp = PyStackRef_AsPyObjectSteal(*target_local); @@ -1139,8 +1122,7 @@ JUMP_TO_ERROR(); } #if TIER_ONE - // The STORE_FAST is already done. This is done here in tier one, - // and during trace projection in tier two: + assert(next_instr->op.code == STORE_FAST); SKIP_OVER(1); #endif @@ -1213,8 +1195,6 @@ PyStackRef_AsPyObjectSteal(stop)); stack_pointer = _PyFrame_GetStackPointer(frame); PyObject *res_o; - // Can't use ERROR_IF() here, because we haven't - // DECREF'ed container yet, and we still own slice. if (slice == NULL) { res_o = NULL; } @@ -1303,7 +1283,6 @@ UOP_STAT_INC(uopcode, miss); JUMP_TO_JUMP_TARGET(); } - // Deopt unless 0 <= sub < PyList_Size(list) if (!_PyLong_IsNonNegativeCompact((PyLongObject *)sub)) { UOP_STAT_INC(uopcode, miss); JUMP_TO_JUMP_TARGET(); @@ -1364,7 +1343,6 @@ UOP_STAT_INC(uopcode, miss); JUMP_TO_JUMP_TARGET(); } - // Specialize for reading an ASCII character from any string: Py_UCS4 c = PyUnicode_READ_CHAR(str, index); if (Py_ARRAY_LENGTH(_Py_SINGLETON(strings).ascii) <= c) { UOP_STAT_INC(uopcode, miss); @@ -1398,7 +1376,6 @@ UOP_STAT_INC(uopcode, miss); JUMP_TO_JUMP_TARGET(); } - // Deopt unless 0 <= sub < PyTuple_Size(list) if (!_PyLong_IsNonNegativeCompact((PyLongObject *)sub)) { UOP_STAT_INC(uopcode, miss); JUMP_TO_JUMP_TARGET(); @@ -1461,7 +1438,6 @@ if (rc <= 0) { JUMP_TO_ERROR(); } - // not found or error res = PyStackRef_FromPyObjectSteal(res_o); stack_pointer[0] = res; stack_pointer += 1; @@ -1567,7 +1543,6 @@ sub = stack_pointer[-1]; container = stack_pointer[-2]; v = stack_pointer[-3]; - /* container[sub] = v */ _PyFrame_SetStackPointer(frame, stack_pointer); int err = PyObject_SetItem(PyStackRef_AsPyObjectBorrow(container), PyStackRef_AsPyObjectBorrow(sub), PyStackRef_AsPyObjectBorrow(v)); _PyStackRef tmp = sub; @@ -1605,7 +1580,6 @@ UOP_STAT_INC(uopcode, miss); JUMP_TO_JUMP_TARGET(); } - // Ensure nonnegative, zero-or-one-digit ints. if (!_PyLong_IsNonNegativeCompact((PyLongObject *)sub)) { UOP_STAT_INC(uopcode, miss); JUMP_TO_JUMP_TARGET(); @@ -1615,7 +1589,6 @@ UOP_STAT_INC(uopcode, miss); JUMP_TO_JUMP_TARGET(); } - // Ensure index < len(list) if (index >= PyList_GET_SIZE(list)) { UNLOCK_OBJECT(list); if (true) { @@ -1628,7 +1601,7 @@ FT_ATOMIC_STORE_PTR_RELEASE(_PyList_ITEMS(list)[index], PyStackRef_AsPyObjectSteal(value)); assert(old_value != NULL); - UNLOCK_OBJECT(list); // unlock before decrefs! + UNLOCK_OBJECT(list); PyStackRef_CLOSE_SPECIALIZED(sub_st, _PyLong_ExactDealloc); stack_pointer += -3; assert(WITHIN_STACK_BOUNDS()); @@ -1673,7 +1646,6 @@ _PyStackRef container; sub = stack_pointer[-1]; container = stack_pointer[-2]; - /* del container[sub] */ _PyFrame_SetStackPointer(frame, stack_pointer); int err = PyObject_DelItem(PyStackRef_AsPyObjectBorrow(container), PyStackRef_AsPyObjectBorrow(sub)); @@ -1762,7 +1734,6 @@ _PyFrame_SetStackPointer(frame, stack_pointer); assert(EMPTY()); _Py_LeaveRecursiveCallPy(tstate); - // GH-99729: We need to unlink the frame *before* clearing it: _PyInterpreterFrame *dying = frame; frame = tstate->current_frame = dying->previous; _PyEval_FrameClearAndPop(tstate, dying); @@ -1906,9 +1877,6 @@ _PyStackRef value; oparg = CURRENT_OPARG(); retval = stack_pointer[-1]; - // NOTE: It's important that YIELD_VALUE never raises an exception! - // The compiler treats any exception raised here as a failed close() - // or throw() call. assert(frame->owner != FRAME_OWNED_BY_INTERPRETER); frame->instr_ptr++; PyGenObject *gen = _PyGen_GetGeneratorFromFrame(frame); @@ -1925,7 +1893,6 @@ _PyInterpreterFrame *gen_frame = frame; frame = tstate->current_frame = frame->previous; gen_frame->previous = NULL; - /* We don't know which of these is relevant here, so keep them equal */ assert(INLINE_CACHE_ENTRIES_SEND == INLINE_CACHE_ENTRIES_FOR_ITER); #if TIER_ONE assert(frame->instr_ptr->op.code == INSTRUMENTED_LINE || @@ -1962,7 +1929,6 @@ case _LOAD_COMMON_CONSTANT: { _PyStackRef value; oparg = CURRENT_OPARG(); - // Keep in sync with _common_constants in opcode.py assert(oparg < NUM_COMMON_CONSTANTS); value = PyStackRef_FromPyObjectNew(tstate->interp->common_consts[oparg]); stack_pointer[0] = value; @@ -2049,7 +2015,6 @@ _PyFrame_SetStackPointer(frame, stack_pointer); err = PyObject_DelItem(ns, name); stack_pointer = _PyFrame_GetStackPointer(frame); - // Can't use ERROR_IF here. if (err != 0) { _PyFrame_SetStackPointer(frame, stack_pointer); _PyEval_FormatExcCheckArg(tstate, PyExc_NameError, @@ -2268,7 +2233,6 @@ _PyFrame_SetStackPointer(frame, stack_pointer); int err = PyDict_Pop(GLOBALS(), name, NULL); stack_pointer = _PyFrame_GetStackPointer(frame); - // Can't use ERROR_IF here. if (err < 0) { JUMP_TO_ERROR(); } @@ -2459,8 +2423,6 @@ case _MAKE_CELL: { oparg = CURRENT_OPARG(); - // "initial" is probably NULL but not if it's an arg (or set - // via the f_locals proxy before MAKE_CELL has run). PyObject *initial = PyStackRef_AsPyObjectBorrow(GETLOCAL(oparg)); PyObject *cell = PyCell_New(initial); if (cell == NULL) { @@ -2477,8 +2439,6 @@ case _DELETE_DEREF: { oparg = CURRENT_OPARG(); PyObject *cell = PyStackRef_AsPyObjectBorrow(GETLOCAL(oparg)); - // Can't use ERROR_IF here. - // Fortunately we don't need its superpower. PyObject *oldobj = PyCell_SwapTakeRef((PyCellObject *)cell, NULL); if (oldobj == NULL) { _PyFrame_SetStackPointer(frame, stack_pointer); @@ -2568,7 +2528,6 @@ case _COPY_FREE_VARS: { oparg = CURRENT_OPARG(); - /* Copy closure variables to free variables */ PyCodeObject *co = _PyFrame_GetCode(frame); assert(PyStackRef_FunctionCheck(frame->f_funcobj)); PyFunctionObject *func = (PyFunctionObject *)PyStackRef_AsPyObjectBorrow(frame->f_funcobj); @@ -2825,7 +2784,6 @@ stack_pointer = _PyFrame_GetStackPointer(frame); JUMP_TO_ERROR(); } - /* check if __annotations__ in locals()... */ _PyFrame_SetStackPointer(frame, stack_pointer); int err = PyMapping_GetOptionalItem(LOCALS(), &_Py_ID(__annotations__), &ann_dict); stack_pointer = _PyFrame_GetStackPointer(frame); @@ -2936,8 +2894,6 @@ dict_st = stack_pointer[-3 - (oparg - 1)]; PyObject *dict = PyStackRef_AsPyObjectBorrow(dict_st); assert(PyDict_CheckExact(dict)); - /* dict[key] = value */ - // Do not DECREF INPUTS because the function steals the references _PyFrame_SetStackPointer(frame, stack_pointer); int err = _PyDict_SetItem_Take2( (PyDictObject *)dict, @@ -3039,7 +2995,7 @@ JUMP_TO_ERROR(); } if (method_found) { - self_or_null = self_st; // transfer ownership + self_or_null = self_st; } else { stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); @@ -3082,26 +3038,15 @@ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 1); PyObject *attr_o; if (oparg & 1) { - /* Designed to work in tandem with CALL, pushes two values. */ attr_o = NULL; _PyFrame_SetStackPointer(frame, stack_pointer); int is_meth = _PyObject_GetMethod(PyStackRef_AsPyObjectBorrow(owner), name, &attr_o); stack_pointer = _PyFrame_GetStackPointer(frame); if (is_meth) { - /* We can bypass temporary bound method object. - meth is unbound method and obj is self. - meth | self | arg1 | ... | argN - */ - assert(attr_o != NULL); // No errors on this branch - self_or_null[0] = owner; // Transfer ownership + assert(attr_o != NULL); + self_or_null[0] = owner; } else { - /* meth is not an unbound method (but a regular attr, or - something was returned by a descriptor protocol). Set - the second element of the stack to NULL, to signal - CALL that it's not a method call. - meth | NULL | arg1 | ... | argN - */ stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); _PyFrame_SetStackPointer(frame, stack_pointer); @@ -3116,7 +3061,6 @@ } } else { - /* Classic, pushes one value. */ _PyFrame_SetStackPointer(frame, stack_pointer); attr_o = PyObject_GetAttr(PyStackRef_AsPyObjectBorrow(owner), name); stack_pointer = _PyFrame_GetStackPointer(frame); @@ -3198,7 +3142,8 @@ JUMP_TO_JUMP_TARGET(); } #ifdef Py_GIL_DISABLED - if (!_Py_TryIncrefCompareStackRef(value_ptr, attr_o, &attr)) { + int increfed = _Py_TryIncrefCompareStackRef(value_ptr, attr_o, &attr); + if (!increfed) { if (true) { UOP_STAT_INC(uopcode, miss); JUMP_TO_JUMP_TARGET(); @@ -3311,7 +3256,8 @@ } STAT_INC(LOAD_ATTR, hit); #ifdef Py_GIL_DISABLED - if (!_Py_TryIncrefCompareStackRef(&ep->me_value, attr_o, &attr)) { + int increfed = _Py_TryIncrefCompareStackRef(&ep->me_value, attr_o, &attr); + if (!increfed) { if (true) { UOP_STAT_INC(uopcode, miss); JUMP_TO_JUMP_TARGET(); @@ -3529,8 +3475,6 @@ stack_pointer = _PyFrame_GetStackPointer(frame); FT_ATOMIC_STORE_PTR_RELEASE(ep->me_value, PyStackRef_AsPyObjectSteal(value)); UNLOCK_OBJECT(dict); - // old_value should be DECREFed after GC track checking is done, if not, it could raise a segmentation fault, - // when dict only holds the strong reference to value in ep->me_value. STAT_INC(STORE_ATTR, hit); stack_pointer += -2; assert(WITHIN_STACK_BOUNDS()); @@ -3623,12 +3567,10 @@ STAT_INC(COMPARE_OP, hit); double dleft = PyFloat_AS_DOUBLE(left_o); double dright = PyFloat_AS_DOUBLE(right_o); - // 1 if NaN, 2 if <, 4 if >, 8 if ==; this matches low four bits of the oparg int sign_ish = COMPARISON_BIT(dleft, dright); PyStackRef_CLOSE_SPECIALIZED(left, _PyFloat_ExactDealloc); PyStackRef_CLOSE_SPECIALIZED(right, _PyFloat_ExactDealloc); res = (sign_ish & oparg) ? PyStackRef_True : PyStackRef_False; - // It's always a bool, so we don't care about oparg & 16. stack_pointer[-2] = res; stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); @@ -3657,12 +3599,10 @@ _PyLong_DigitCount((PyLongObject *)right_o) <= 1); Py_ssize_t ileft = _PyLong_CompactValue((PyLongObject *)left_o); Py_ssize_t iright = _PyLong_CompactValue((PyLongObject *)right_o); - // 2 if <, 4 if >, 8 if ==; this matches the low 4 bits of the oparg int sign_ish = COMPARISON_BIT(ileft, iright); PyStackRef_CLOSE_SPECIALIZED(left, _PyLong_ExactDealloc); PyStackRef_CLOSE_SPECIALIZED(right, _PyLong_ExactDealloc); res = (sign_ish & oparg) ? PyStackRef_True : PyStackRef_False; - // It's always a bool, so we don't care about oparg & 16. stack_pointer[-2] = res; stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); @@ -3687,7 +3627,6 @@ assert((oparg & 0xf) == COMPARISON_NOT_EQUALS || (oparg & 0xf) == COMPARISON_EQUALS); assert(COMPARISON_NOT_EQUALS + 1 == COMPARISON_EQUALS); res = ((COMPARISON_NOT_EQUALS + eq) & oparg) ? PyStackRef_True : PyStackRef_False; - // It's always a bool, so we don't care about oparg & 16. stack_pointer[-2] = res; stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); @@ -3767,7 +3706,6 @@ JUMP_TO_JUMP_TARGET(); } STAT_INC(CONTAINS_OP, hit); - // Note: both set and frozenset use the same seq_contains method! _PyFrame_SetStackPointer(frame, stack_pointer); int res = _PySet_Contains((PySetObject *)right_o, left_o); _PyStackRef tmp = right; @@ -4002,7 +3940,6 @@ _PyStackRef obj; _PyStackRef len; obj = stack_pointer[-1]; - // PUSH(len(TOS)) _PyFrame_SetStackPointer(frame, stack_pointer); Py_ssize_t len_i = PyObject_Length(PyStackRef_AsPyObjectBorrow(obj)); stack_pointer = _PyFrame_GetStackPointer(frame); @@ -4029,8 +3966,6 @@ names = stack_pointer[-1]; type = stack_pointer[-2]; subject = stack_pointer[-3]; - // Pop TOS and TOS1. Set TOS to a tuple of attributes on success, or - // None on failure. assert(PyTuple_CheckExact(PyStackRef_AsPyObjectBorrow(names))); _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *attrs_o = _PyEval_MatchClass(tstate, @@ -4053,15 +3988,14 @@ stack_pointer += -3; assert(WITHIN_STACK_BOUNDS()); if (attrs_o) { - assert(PyTuple_CheckExact(attrs_o)); // Success! + assert(PyTuple_CheckExact(attrs_o)); attrs = PyStackRef_FromPyObjectSteal(attrs_o); } else { if (_PyErr_Occurred(tstate)) { JUMP_TO_ERROR(); } - // Error! - attrs = PyStackRef_None; // Failure! + attrs = PyStackRef_None; } stack_pointer[0] = attrs; stack_pointer += 1; @@ -4099,7 +4033,6 @@ _PyStackRef values_or_none; keys = stack_pointer[-1]; subject = stack_pointer[-2]; - // On successful match, PUSH(values). Otherwise, PUSH(None). _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *values_or_none_o = _PyEval_MatchKeys(tstate, PyStackRef_AsPyObjectBorrow(subject), PyStackRef_AsPyObjectBorrow(keys)); @@ -4118,7 +4051,6 @@ _PyStackRef iterable; _PyStackRef iter; iterable = stack_pointer[-1]; - /* before: [obj]; after [getiter(obj)] */ _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *iter_o = PyObject_GetIter(PyStackRef_AsPyObjectBorrow(iterable)); stack_pointer = _PyFrame_GetStackPointer(frame); @@ -4141,13 +4073,9 @@ _PyStackRef iterable; _PyStackRef iter; iterable = stack_pointer[-1]; - /* before: [obj]; after [getiter(obj)] */ PyObject *iterable_o = PyStackRef_AsPyObjectBorrow(iterable); if (PyCoro_CheckExact(iterable_o)) { - /* `iterable` is a coroutine */ if (!(_PyFrame_GetCode(frame)->co_flags & (CO_COROUTINE | CO_ITERABLE_COROUTINE))) { - /* and it is used in a 'yield from' expression of a - regular generator. */ _PyFrame_SetStackPointer(frame, stack_pointer); _PyErr_SetString(tstate, PyExc_TypeError, "cannot 'yield from' a coroutine object " @@ -4157,26 +4085,23 @@ } iter = iterable; } + else if (PyGen_CheckExact(iterable_o)) { + iter = iterable; + } else { - if (PyGen_CheckExact(iterable_o)) { - iter = iterable; - } - else { - /* `iterable` is not a generator. */ - _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *iter_o = PyObject_GetIter(iterable_o); - stack_pointer = _PyFrame_GetStackPointer(frame); - if (iter_o == NULL) { - JUMP_TO_ERROR(); - } - iter = PyStackRef_FromPyObjectSteal(iter_o); - _PyFrame_SetStackPointer(frame, stack_pointer); - _PyStackRef tmp = iterable; - iterable = iter; - stack_pointer[-1] = iterable; - PyStackRef_CLOSE(tmp); - stack_pointer = _PyFrame_GetStackPointer(frame); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyObject *iter_o = PyObject_GetIter(iterable_o); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (iter_o == NULL) { + JUMP_TO_ERROR(); } + iter = PyStackRef_FromPyObjectSteal(iter_o); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp = iterable; + iterable = iter; + stack_pointer[-1] = iterable; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); } stack_pointer[-1] = iter; break; @@ -4188,7 +4113,6 @@ _PyStackRef iter; _PyStackRef next; iter = stack_pointer[-1]; - /* before: [iter]; after: [iter, iter()] *or* [] (and jump over END_FOR.) */ PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter); _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *next_o = (*Py_TYPE(iter_o)->tp_iternext)(iter_o); @@ -4206,15 +4130,12 @@ _PyErr_Clear(tstate); stack_pointer = _PyFrame_GetStackPointer(frame); } - /* iterator ended normally */ - /* The translator sets the deopt target just past the matching END_FOR */ if (true) { UOP_STAT_INC(uopcode, miss); JUMP_TO_JUMP_TARGET(); } } next = PyStackRef_FromPyObjectSteal(next_o); - // Common case: no jump, leave it to the code generator stack_pointer[0] = next; stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); @@ -4290,8 +4211,6 @@ _PyFrame_SetStackPointer(frame, stack_pointer); int result = _PyList_GetItemRefNoLock(seq, it->it_index, &next); stack_pointer = _PyFrame_GetStackPointer(frame); - // A negative result means we lost a race with another thread - // and we need to take the slow path. if (result < 0) { UOP_STAT_INC(uopcode, miss); JUMP_TO_JUMP_TARGET(); @@ -4440,10 +4359,7 @@ JUMP_TO_JUMP_TARGET(); } #ifdef Py_GIL_DISABLED - // Since generators can't be used by multiple threads anyway we - // don't need to deopt here, but this lets us work on making - // generators thread-safe without necessarily having to - // specialize them thread-safely as well. + if (!_PyObject_IsUniquelyReferenced((PyObject *)gen)) { UOP_STAT_INC(uopcode, miss); JUMP_TO_JUMP_TARGET(); @@ -4460,7 +4376,6 @@ gen->gi_exc_state.previous_item = tstate->exc_info; tstate->exc_info = &gen->gi_exc_state; gen_frame->previous = frame; - // oparg is the return offset from the next instruction. frame->return_offset = (uint16_t)( 2 + oparg); stack_pointer[0].bits = (uintptr_t)gen_frame; stack_pointer += 1; @@ -4513,15 +4428,6 @@ lasti = stack_pointer[-3]; 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_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. - */ PyObject *exc, *tb; PyObject *val_o = PyStackRef_AsPyObjectBorrow(val); PyObject *exit_func_o = PyStackRef_AsPyObjectBorrow(exit_func); @@ -4532,7 +4438,7 @@ tb = Py_None; } assert(PyStackRef_LongCheck(lasti)); - (void)lasti; // Shut up compiler warning if asserts are off + (void)lasti; PyObject *stack[5] = {NULL, PyStackRef_AsPyObjectBorrow(exit_self), exc, val_o, tb}; int has_self = !PyStackRef_IsNull(exit_self); _PyFrame_SetStackPointer(frame, stack_pointer); @@ -4607,7 +4513,6 @@ owner = stack_pointer[-1]; PyObject *descr = (PyObject *)CURRENT_OPERAND0(); assert(oparg & 1); - /* Cached method object */ STAT_INC(LOAD_ATTR, hit); assert(descr != NULL); assert(_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR)); @@ -4690,7 +4595,6 @@ uint16_t dictoffset = (uint16_t)CURRENT_OPERAND0(); char *ptr = ((char *)PyStackRef_AsPyObjectBorrow(owner)) + MANAGED_DICT_OFFSET + dictoffset; PyObject *dict = FT_ATOMIC_LOAD_PTR_ACQUIRE(*(PyObject **)ptr); - /* This object has a __dict__, just not yet created */ if (dict != NULL) { UOP_STAT_INC(uopcode, miss); JUMP_TO_JUMP_TARGET(); @@ -4755,7 +4659,6 @@ self_or_null = &stack_pointer[-1 - oparg]; callable = &stack_pointer[-2 - oparg]; PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); - // oparg counts all of the args, but *not* self: int total_args = oparg; if (!PyStackRef_IsNull(self_or_null[0])) { args--; @@ -4770,7 +4673,6 @@ args, total_args, NULL, frame ); stack_pointer = _PyFrame_GetStackPointer(frame); - // The frame has stolen all the arguments from the stack. stack_pointer += -2 - oparg; assert(WITHIN_STACK_BOUNDS()); if (temp == NULL) { @@ -4895,7 +4797,6 @@ arguments--; total_args++; } - /* Callable is not a normal Python function */ STACKREFS_TO_PYOBJECTS(arguments, total_args, args_o); if (CONVERSION_FAILED(args_o)) { _PyFrame_SetStackPointer(frame, stack_pointer); @@ -5174,8 +5075,6 @@ case _PUSH_FRAME: { _PyInterpreterFrame *new_frame; new_frame = (_PyInterpreterFrame *)stack_pointer[-1].bits; - // Write it out explicitly because it's subtly different. - // Eventually this should be the only occurrence of this code. assert(tstate->interp->eval_frame == NULL); _PyInterpreterFrame *temp = new_frame; stack_pointer += -1; @@ -5365,7 +5264,6 @@ stack_pointer = _PyFrame_GetStackPointer(frame); assert(_PyFrame_GetBytecode(shim)[0].op.code == EXIT_INIT_CHECK); assert(_PyFrame_GetBytecode(shim)[1].op.code == RETURN_VALUE); - /* Push self onto stack of shim */ shim->localsplus[0] = PyStackRef_DUP(self[0]); _PyFrame_SetStackPointer(frame, stack_pointer); _PyInterpreterFrame *temp = _PyEvalFramePushAndInit( @@ -5381,9 +5279,6 @@ } init_frame = temp; frame->return_offset = 1 + INLINE_CACHE_ENTRIES_CALL; - /* Account for pushing the extra frame. - * We don't check recursion depth here, - * as it will be checked after start_frame */ tstate->py_recursion_remaining--; stack_pointer[0].bits = (uintptr_t)init_frame; stack_pointer += 1; @@ -5493,7 +5388,6 @@ args = &stack_pointer[-oparg]; self_or_null = &stack_pointer[-1 - oparg]; callable = &stack_pointer[-2 - oparg]; - /* Builtin METH_O functions */ PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); int total_args = oparg; if (!PyStackRef_IsNull(self_or_null[0])) { @@ -5512,7 +5406,6 @@ UOP_STAT_INC(uopcode, miss); JUMP_TO_JUMP_TARGET(); } - // CPython promises to check all non-vectorcall function calls. if (_Py_ReachedRecursionLimit(tstate)) { UOP_STAT_INC(uopcode, miss); JUMP_TO_JUMP_TARGET(); @@ -5552,7 +5445,6 @@ args = &stack_pointer[-oparg]; self_or_null = &stack_pointer[-1 - oparg]; callable = &stack_pointer[-2 - oparg]; - /* Builtin METH_FASTCALL functions, without keywords */ PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); int total_args = oparg; _PyStackRef *arguments = args; @@ -5570,7 +5462,6 @@ } STAT_INC(CALL, hit); PyCFunction cfunc = PyCFunction_GET_FUNCTION(callable_o); - /* res = func(self, args, nargs) */ STACKREFS_TO_PYOBJECTS(arguments, total_args, args_o); if (CONVERSION_FAILED(args_o)) { _PyFrame_SetStackPointer(frame, stack_pointer); @@ -5634,7 +5525,6 @@ args = &stack_pointer[-oparg]; self_or_null = &stack_pointer[-1 - oparg]; callable = &stack_pointer[-2 - oparg]; - /* Builtin METH_FASTCALL | METH_KEYWORDS functions */ PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); int total_args = oparg; _PyStackRef *arguments = args; @@ -5651,7 +5541,6 @@ JUMP_TO_JUMP_TARGET(); } STAT_INC(CALL, hit); - /* res = func(self, arguments, nargs, kwnames) */ _PyFrame_SetStackPointer(frame, stack_pointer); PyCFunctionFastWithKeywords cfunc = (PyCFunctionFastWithKeywords)(void(*)(void)) @@ -5717,7 +5606,6 @@ args = &stack_pointer[-oparg]; self_or_null = &stack_pointer[-1 - oparg]; callable = &stack_pointer[-2 - oparg]; - /* len(o) */ PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); int total_args = oparg; if (!PyStackRef_IsNull(self_or_null[0])) { @@ -5771,7 +5659,6 @@ args = &stack_pointer[-oparg]; self_or_null = &stack_pointer[-1 - oparg]; callable = stack_pointer[-2 - oparg]; - /* isinstance(o, o2) */ PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); int total_args = oparg; _PyStackRef *arguments = args; @@ -5860,8 +5747,7 @@ JUMP_TO_ERROR(); } #if TIER_ONE - // Skip the following POP_TOP. This is done here in tier one, and - // during trace projection in tier two: + assert(next_instr->op.code == POP_TOP); SKIP_OVER(1); #endif @@ -5898,7 +5784,6 @@ UOP_STAT_INC(uopcode, miss); JUMP_TO_JUMP_TARGET(); } - // CPython promises to check all non-vectorcall function calls. if (_Py_ReachedRecursionLimit(tstate)) { UOP_STAT_INC(uopcode, miss); JUMP_TO_JUMP_TARGET(); @@ -6068,7 +5953,6 @@ UOP_STAT_INC(uopcode, miss); JUMP_TO_JUMP_TARGET(); } - // CPython promises to check all non-vectorcall function calls. if (_Py_ReachedRecursionLimit(tstate)) { UOP_STAT_INC(uopcode, miss); JUMP_TO_JUMP_TARGET(); @@ -6115,7 +5999,6 @@ total_args++; } PyMethodDescrObject *method = (PyMethodDescrObject *)callable_o; - /* Builtin METH_FASTCALL methods, without keywords */ if (!Py_IS_TYPE(method, &PyMethodDescr_Type)) { UOP_STAT_INC(uopcode, miss); JUMP_TO_JUMP_TARGET(); @@ -6229,7 +6112,6 @@ self_or_null = &stack_pointer[-2 - oparg]; callable = &stack_pointer[-3 - oparg]; PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); - // oparg counts all of the args, but *not* self: int total_args = oparg; _PyStackRef *arguments = args; if (!PyStackRef_IsNull(self_or_null[0])) { @@ -6252,8 +6134,6 @@ _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(kwnames); stack_pointer = _PyFrame_GetStackPointer(frame); - // The frame has stolen all the arguments from the stack, - // so there is no need to clean them up. stack_pointer += -2 - oparg; assert(WITHIN_STACK_BOUNDS()); if (temp == NULL) { @@ -6368,7 +6248,6 @@ arguments--; total_args++; } - /* Callable is not a normal Python function */ STACKREFS_TO_PYOBJECTS(arguments, total_args, args_o); if (CONVERSION_FAILED(args_o)) { _PyFrame_SetStackPointer(frame, stack_pointer); @@ -6617,8 +6496,6 @@ _PyStackRef res; value = stack_pointer[-1]; PyObject *value_o = PyStackRef_AsPyObjectBorrow(value); - /* If value is a unicode object, then we know the result - * of format(value) is value itself. */ if (!PyUnicode_CheckExact(value_o)) { _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *res_o = PyObject_Format(value_o, NULL); @@ -7012,7 +6889,6 @@ case _MAKE_WARM: { current_executor->vm_data.warm = true; - // It's okay if this ends up going negative. if (--tstate->interp->trace_run_counter == 0) { _Py_set_eval_breaker_bit(tstate, _PY_EVAL_JIT_INVALIDATE_COLD_BIT); } diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index 41ea054d3f5..c75371d12b0 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -389,17 +389,6 @@ JUMP_TO_PREDICTED(BINARY_OP); } STAT_INC(BINARY_OP, hit); - /* Handle `left = left + right` or `left += right` for str. - * - * When possible, extend `left` in place rather than - * allocating a new PyUnicodeObject. This attempts to avoid - * quadratic behavior when one neglects to use str.join(). - * - * If `left` has only two references remaining (one from - * the stack, one in the locals), DECREFing `left` leaves - * only the locals reference, so PyUnicode_Append knows - * that the string is safe to mutate. - */ assert(Py_REFCNT(left_o) >= 2 || !PyStackRef_IsHeapSafe(left)); PyStackRef_CLOSE_SPECIALIZED(left, _PyUnicode_ExactDealloc); PyObject *temp = PyStackRef_AsPyObjectSteal(*target_local); @@ -417,8 +406,7 @@ JUMP_TO_LABEL(error); } #if TIER_ONE - // The STORE_FAST is already done. This is done here in tier one, - // and during trace projection in tier two: + assert(next_instr->op.code == STORE_FAST); SKIP_OVER(1); #endif @@ -595,7 +583,6 @@ if (rc <= 0) { JUMP_TO_LABEL(error); } - // not found or error res = PyStackRef_FromPyObjectSteal(res_o); stack_pointer[0] = res; stack_pointer += 1; @@ -670,8 +657,6 @@ } // _PUSH_FRAME { - // Write it out explicitly because it's subtly different. - // Eventually this should be the only occurrence of this code. assert(tstate->interp->eval_frame == NULL); _PyInterpreterFrame *temp = new_frame; stack_pointer += -2; @@ -726,7 +711,6 @@ assert(_PyOpcode_Deopt[opcode] == (BINARY_OP)); JUMP_TO_PREDICTED(BINARY_OP); } - // Deopt unless 0 <= sub < PyList_Size(list) if (!_PyLong_IsNonNegativeCompact((PyLongObject *)sub)) { UPDATE_MISS_STATS(BINARY_OP); assert(_PyOpcode_Deopt[opcode] == (BINARY_OP)); @@ -831,7 +815,6 @@ assert(_PyOpcode_Deopt[opcode] == (BINARY_OP)); JUMP_TO_PREDICTED(BINARY_OP); } - // Specialize for reading an ASCII character from any string: Py_UCS4 c = PyUnicode_READ_CHAR(str, index); if (Py_ARRAY_LENGTH(_Py_SINGLETON(strings).ascii) <= c) { UPDATE_MISS_STATS(BINARY_OP); @@ -892,7 +875,6 @@ assert(_PyOpcode_Deopt[opcode] == (BINARY_OP)); JUMP_TO_PREDICTED(BINARY_OP); } - // Deopt unless 0 <= sub < PyTuple_Size(list) if (!_PyLong_IsNonNegativeCompact((PyLongObject *)sub)) { UPDATE_MISS_STATS(BINARY_OP); assert(_PyOpcode_Deopt[opcode] == (BINARY_OP)); @@ -1055,7 +1037,6 @@ _PyStackRef res; // _SPECIALIZE_BINARY_SLICE { - // Placeholder until we implement BINARY_SLICE specialization #if ENABLE_SPECIALIZATION OPCODE_DEFERRED_INC(BINARY_SLICE); #endif /* ENABLE_SPECIALIZATION */ @@ -1070,8 +1051,6 @@ PyStackRef_AsPyObjectSteal(stop)); stack_pointer = _PyFrame_GetStackPointer(frame); PyObject *res_o; - // Can't use ERROR_IF() here, because we haven't - // DECREF'ed container yet, and we still own slice. if (slice == NULL) { res_o = NULL; } @@ -1406,14 +1385,12 @@ { args = &stack_pointer[-oparg]; PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); - // oparg counts all of the args, but *not* self: int total_args = oparg; _PyStackRef *arguments = args; if (!PyStackRef_IsNull(self_or_null[0])) { arguments--; total_args++; } - // Check if the call can be inlined or not if (Py_TYPE(callable_o) == &PyFunction_Type && tstate->interp->eval_frame == NULL && ((PyFunctionObject *)callable_o)->vectorcall == _PyFunction_Vectorcall) @@ -1426,18 +1403,14 @@ arguments, total_args, NULL, frame ); stack_pointer = _PyFrame_GetStackPointer(frame); - // Manipulate stack directly since we leave using DISPATCH_INLINED(). stack_pointer += -2 - oparg; assert(WITHIN_STACK_BOUNDS()); - // The frame has stolen all the arguments from the stack, - // so there is no need to clean them up. if (new_frame == NULL) { JUMP_TO_LABEL(error); } frame->return_offset = 4 ; DISPATCH_INLINED(new_frame); } - /* Callable is not a normal Python function */ STACKREFS_TO_PYOBJECTS(arguments, total_args, args_o); if (CONVERSION_FAILED(args_o)) { _PyFrame_SetStackPointer(frame, stack_pointer); @@ -1620,7 +1593,6 @@ stack_pointer = _PyFrame_GetStackPointer(frame); assert(_PyFrame_GetBytecode(shim)[0].op.code == EXIT_INIT_CHECK); assert(_PyFrame_GetBytecode(shim)[1].op.code == RETURN_VALUE); - /* Push self onto stack of shim */ shim->localsplus[0] = PyStackRef_DUP(self[0]); _PyFrame_SetStackPointer(frame, stack_pointer); _PyInterpreterFrame *temp = _PyEvalFramePushAndInit( @@ -1636,16 +1608,11 @@ } init_frame = temp; frame->return_offset = 1 + INLINE_CACHE_ENTRIES_CALL; - /* Account for pushing the extra frame. - * We don't check recursion depth here, - * as it will be checked after start_frame */ tstate->py_recursion_remaining--; } // _PUSH_FRAME { new_frame = init_frame; - // Write it out explicitly because it's subtly different. - // Eventually this should be the only occurrence of this code. assert(tstate->interp->eval_frame == NULL); _PyInterpreterFrame *temp = new_frame; _PyFrame_SetStackPointer(frame, stack_pointer); @@ -1781,8 +1748,6 @@ } // _PUSH_FRAME { - // Write it out explicitly because it's subtly different. - // Eventually this should be the only occurrence of this code. assert(tstate->interp->eval_frame == NULL); _PyInterpreterFrame *temp = new_frame; stack_pointer += -2 - oparg; @@ -1871,7 +1836,6 @@ { args = &stack_pointer[-oparg]; PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); - // oparg counts all of the args, but *not* self: int total_args = oparg; if (!PyStackRef_IsNull(self_or_null[0])) { args--; @@ -1886,7 +1850,6 @@ args, total_args, NULL, frame ); stack_pointer = _PyFrame_GetStackPointer(frame); - // The frame has stolen all the arguments from the stack. stack_pointer += -2 - oparg; assert(WITHIN_STACK_BOUNDS()); if (temp == NULL) { @@ -1905,8 +1868,6 @@ } // _PUSH_FRAME { - // Write it out explicitly because it's subtly different. - // Eventually this should be the only occurrence of this code. assert(tstate->interp->eval_frame == NULL); _PyInterpreterFrame *temp = new_frame; _PyFrame_SetStackPointer(frame, stack_pointer); @@ -2053,7 +2014,6 @@ args = &stack_pointer[-oparg]; self_or_null = &stack_pointer[-1 - oparg]; callable = &stack_pointer[-2 - oparg]; - /* Builtin METH_FASTCALL functions, without keywords */ PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); int total_args = oparg; _PyStackRef *arguments = args; @@ -2073,7 +2033,6 @@ } STAT_INC(CALL, hit); PyCFunction cfunc = PyCFunction_GET_FUNCTION(callable_o); - /* res = func(self, args, nargs) */ STACKREFS_TO_PYOBJECTS(arguments, total_args, args_o); if (CONVERSION_FAILED(args_o)) { _PyFrame_SetStackPointer(frame, stack_pointer); @@ -2169,7 +2128,6 @@ args = &stack_pointer[-oparg]; self_or_null = &stack_pointer[-1 - oparg]; callable = &stack_pointer[-2 - oparg]; - /* Builtin METH_FASTCALL | METH_KEYWORDS functions */ PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); int total_args = oparg; _PyStackRef *arguments = args; @@ -2188,7 +2146,6 @@ JUMP_TO_PREDICTED(CALL); } STAT_INC(CALL, hit); - /* res = func(self, arguments, nargs, kwnames) */ _PyFrame_SetStackPointer(frame, stack_pointer); PyCFunctionFastWithKeywords cfunc = (PyCFunctionFastWithKeywords)(void(*)(void)) @@ -2286,7 +2243,6 @@ args = &stack_pointer[-oparg]; self_or_null = &stack_pointer[-1 - oparg]; callable = &stack_pointer[-2 - oparg]; - /* Builtin METH_O functions */ PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); int total_args = oparg; if (!PyStackRef_IsNull(self_or_null[0])) { @@ -2308,7 +2264,6 @@ assert(_PyOpcode_Deopt[opcode] == (CALL)); JUMP_TO_PREDICTED(CALL); } - // CPython promises to check all non-vectorcall function calls. if (_Py_ReachedRecursionLimit(tstate)) { UPDATE_MISS_STATS(CALL); assert(_PyOpcode_Deopt[opcode] == (CALL)); @@ -2422,8 +2377,6 @@ func_st = func; (void)null; PyObject *func = PyStackRef_AsPyObjectBorrow(func_st); - // DICT_MERGE is called before this opcode if there are kwargs. - // It converts all dict subtypes in kwargs into regular dicts. EVAL_CALL_STAT_INC_IF_FUNCTION(EVAL_CALL_FUNCTION_EX, func); PyObject *result_o; assert(!_PyErr_Occurred(tstate)); @@ -2487,7 +2440,6 @@ tstate, func_st, locals, nargs, callargs, kwargs, frame); stack_pointer = _PyFrame_GetStackPointer(frame); - // Need to sync the stack since we exit with DISPATCH_INLINED. stack_pointer += -2; assert(WITHIN_STACK_BOUNDS()); if (new_frame == NULL) { @@ -2640,7 +2592,6 @@ args = &stack_pointer[-oparg]; self_or_null = &stack_pointer[-1 - oparg]; callable = stack_pointer[-2 - oparg]; - /* isinstance(o, o2) */ PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); int total_args = oparg; _PyStackRef *arguments = args; @@ -2751,7 +2702,6 @@ args = &stack_pointer[-1 - oparg]; PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); PyObject *kwnames_o = PyStackRef_AsPyObjectBorrow(kwnames); - // oparg counts all of the args, but *not* self: int total_args = oparg; _PyStackRef *arguments = args; if (!PyStackRef_IsNull(self_or_null[0])) { @@ -2759,7 +2709,6 @@ total_args++; } int positional_args = total_args - (int)PyTuple_GET_SIZE(kwnames_o); - // Check if the call can be inlined or not if (Py_TYPE(callable_o) == &PyFunction_Type && tstate->interp->eval_frame == NULL && ((PyFunctionObject *)callable_o)->vectorcall == _PyFunction_Vectorcall) @@ -2778,9 +2727,6 @@ _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(kwnames); stack_pointer = _PyFrame_GetStackPointer(frame); - // Sync stack explicitly since we leave using DISPATCH_INLINED(). - // The frame has stolen all the arguments from the stack, - // so there is no need to clean them up. if (new_frame == NULL) { JUMP_TO_LABEL(error); } @@ -2788,7 +2734,6 @@ frame->return_offset = 4 ; DISPATCH_INLINED(new_frame); } - /* Callable is not a normal Python function */ STACKREFS_TO_PYOBJECTS(arguments, total_args, args_o); if (CONVERSION_FAILED(args_o)) { stack_pointer[-1] = kwnames; @@ -2948,7 +2893,6 @@ kwnames = stack_pointer[-1]; args = &stack_pointer[-1 - oparg]; PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); - // oparg counts all of the args, but *not* self: int total_args = oparg; _PyStackRef *arguments = args; if (!PyStackRef_IsNull(self_or_null[0])) { @@ -2971,8 +2915,6 @@ _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(kwnames); stack_pointer = _PyFrame_GetStackPointer(frame); - // The frame has stolen all the arguments from the stack, - // so there is no need to clean them up. stack_pointer += -2 - oparg; assert(WITHIN_STACK_BOUNDS()); if (temp == NULL) { @@ -2991,8 +2933,6 @@ } // _PUSH_FRAME { - // Write it out explicitly because it's subtly different. - // Eventually this should be the only occurrence of this code. assert(tstate->interp->eval_frame == NULL); _PyInterpreterFrame *temp = new_frame; _PyFrame_SetStackPointer(frame, stack_pointer); @@ -3056,7 +2996,6 @@ arguments--; total_args++; } - /* Callable is not a normal Python function */ STACKREFS_TO_PYOBJECTS(arguments, total_args, args_o); if (CONVERSION_FAILED(args_o)) { _PyFrame_SetStackPointer(frame, stack_pointer); @@ -3188,7 +3127,6 @@ args = &stack_pointer[-1 - oparg]; self_or_null = &stack_pointer[-2 - oparg]; PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); - // oparg counts all of the args, but *not* self: int total_args = oparg; _PyStackRef *arguments = args; if (!PyStackRef_IsNull(self_or_null[0])) { @@ -3211,8 +3149,6 @@ _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(kwnames); stack_pointer = _PyFrame_GetStackPointer(frame); - // The frame has stolen all the arguments from the stack, - // so there is no need to clean them up. stack_pointer += -2 - oparg; assert(WITHIN_STACK_BOUNDS()); if (temp == NULL) { @@ -3231,8 +3167,6 @@ } // _PUSH_FRAME { - // Write it out explicitly because it's subtly different. - // Eventually this should be the only occurrence of this code. assert(tstate->interp->eval_frame == NULL); _PyInterpreterFrame *temp = new_frame; _PyFrame_SetStackPointer(frame, stack_pointer); @@ -3267,7 +3201,6 @@ args = &stack_pointer[-oparg]; self_or_null = &stack_pointer[-1 - oparg]; callable = &stack_pointer[-2 - oparg]; - /* len(o) */ PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); int total_args = oparg; if (!PyStackRef_IsNull(self_or_null[0])) { @@ -3370,8 +3303,7 @@ JUMP_TO_LABEL(error); } #if TIER_ONE - // Skip the following POP_TOP. This is done here in tier one, and - // during trace projection in tier two: + assert(next_instr->op.code == POP_TOP); SKIP_OVER(1); #endif @@ -3408,7 +3340,6 @@ total_args++; } PyMethodDescrObject *method = (PyMethodDescrObject *)callable_o; - /* Builtin METH_FASTCALL methods, without keywords */ if (!Py_IS_TYPE(method, &PyMethodDescr_Type)) { UPDATE_MISS_STATS(CALL); assert(_PyOpcode_Deopt[opcode] == (CALL)); @@ -3675,7 +3606,6 @@ assert(_PyOpcode_Deopt[opcode] == (CALL)); JUMP_TO_PREDICTED(CALL); } - // CPython promises to check all non-vectorcall function calls. if (_Py_ReachedRecursionLimit(tstate)) { UPDATE_MISS_STATS(CALL); assert(_PyOpcode_Deopt[opcode] == (CALL)); @@ -3771,7 +3701,6 @@ assert(_PyOpcode_Deopt[opcode] == (CALL)); JUMP_TO_PREDICTED(CALL); } - // CPython promises to check all non-vectorcall function calls. if (_Py_ReachedRecursionLimit(tstate)) { UPDATE_MISS_STATS(CALL); assert(_PyOpcode_Deopt[opcode] == (CALL)); @@ -3886,7 +3815,6 @@ arguments--; total_args++; } - /* Callable is not a normal Python function */ STACKREFS_TO_PYOBJECTS(arguments, total_args, args_o); if (CONVERSION_FAILED(args_o)) { _PyFrame_SetStackPointer(frame, stack_pointer); @@ -4054,8 +3982,6 @@ } // _PUSH_FRAME { - // Write it out explicitly because it's subtly different. - // Eventually this should be the only occurrence of this code. assert(tstate->interp->eval_frame == NULL); _PyInterpreterFrame *temp = new_frame; stack_pointer += -2 - oparg; @@ -4118,7 +4044,6 @@ args = &stack_pointer[-oparg]; self_or_null = &stack_pointer[-1 - oparg]; PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); - // oparg counts all of the args, but *not* self: int total_args = oparg; if (!PyStackRef_IsNull(self_or_null[0])) { args--; @@ -4133,7 +4058,6 @@ args, total_args, NULL, frame ); stack_pointer = _PyFrame_GetStackPointer(frame); - // The frame has stolen all the arguments from the stack. stack_pointer += -2 - oparg; assert(WITHIN_STACK_BOUNDS()); if (temp == NULL) { @@ -4152,8 +4076,6 @@ } // _PUSH_FRAME { - // Write it out explicitly because it's subtly different. - // Eventually this should be the only occurrence of this code. assert(tstate->interp->eval_frame == NULL); _PyInterpreterFrame *temp = new_frame; _PyFrame_SetStackPointer(frame, stack_pointer); @@ -4643,12 +4565,10 @@ STAT_INC(COMPARE_OP, hit); double dleft = PyFloat_AS_DOUBLE(left_o); double dright = PyFloat_AS_DOUBLE(right_o); - // 1 if NaN, 2 if <, 4 if >, 8 if ==; this matches low four bits of the oparg int sign_ish = COMPARISON_BIT(dleft, dright); PyStackRef_CLOSE_SPECIALIZED(left, _PyFloat_ExactDealloc); PyStackRef_CLOSE_SPECIALIZED(right, _PyFloat_ExactDealloc); res = (sign_ish & oparg) ? PyStackRef_True : PyStackRef_False; - // It's always a bool, so we don't care about oparg & 16. } stack_pointer[-2] = res; stack_pointer += -1; @@ -4713,12 +4633,10 @@ _PyLong_DigitCount((PyLongObject *)right_o) <= 1); Py_ssize_t ileft = _PyLong_CompactValue((PyLongObject *)left_o); Py_ssize_t iright = _PyLong_CompactValue((PyLongObject *)right_o); - // 2 if <, 4 if >, 8 if ==; this matches the low 4 bits of the oparg int sign_ish = COMPARISON_BIT(ileft, iright); PyStackRef_CLOSE_SPECIALIZED(left, _PyLong_ExactDealloc); PyStackRef_CLOSE_SPECIALIZED(right, _PyLong_ExactDealloc); res = (sign_ish & oparg) ? PyStackRef_True : PyStackRef_False; - // It's always a bool, so we don't care about oparg & 16. } stack_pointer[-2] = res; stack_pointer += -1; @@ -4781,7 +4699,6 @@ assert((oparg & 0xf) == COMPARISON_NOT_EQUALS || (oparg & 0xf) == COMPARISON_EQUALS); assert(COMPARISON_NOT_EQUALS + 1 == COMPARISON_EQUALS); res = ((COMPARISON_NOT_EQUALS + eq) & oparg) ? PyStackRef_True : PyStackRef_False; - // It's always a bool, so we don't care about oparg & 16. } stack_pointer[-2] = res; stack_pointer += -1; @@ -4922,7 +4839,6 @@ JUMP_TO_PREDICTED(CONTAINS_OP); } STAT_INC(CONTAINS_OP, hit); - // Note: both set and frozenset use the same seq_contains method! _PyFrame_SetStackPointer(frame, stack_pointer); int res = _PySet_Contains((PySetObject *)right_o, left_o); _PyStackRef tmp = right; @@ -5005,7 +4921,6 @@ frame->instr_ptr = next_instr; next_instr += 1; INSTRUCTION_STATS(COPY_FREE_VARS); - /* Copy closure variables to free variables */ PyCodeObject *co = _PyFrame_GetCode(frame); assert(PyStackRef_FunctionCheck(frame->f_funcobj)); PyFunctionObject *func = (PyFunctionObject *)PyStackRef_AsPyObjectBorrow(frame->f_funcobj); @@ -5053,8 +4968,6 @@ next_instr += 1; INSTRUCTION_STATS(DELETE_DEREF); PyObject *cell = PyStackRef_AsPyObjectBorrow(GETLOCAL(oparg)); - // Can't use ERROR_IF here. - // Fortunately we don't need its superpower. PyObject *oldobj = PyCell_SwapTakeRef((PyCellObject *)cell, NULL); if (oldobj == NULL) { _PyFrame_SetStackPointer(frame, stack_pointer); @@ -5106,7 +5019,6 @@ _PyFrame_SetStackPointer(frame, stack_pointer); int err = PyDict_Pop(GLOBALS(), name, NULL); stack_pointer = _PyFrame_GetStackPointer(frame); - // Can't use ERROR_IF here. if (err < 0) { JUMP_TO_LABEL(error); } @@ -5141,7 +5053,6 @@ _PyFrame_SetStackPointer(frame, stack_pointer); err = PyObject_DelItem(ns, name); stack_pointer = _PyFrame_GetStackPointer(frame); - // Can't use ERROR_IF here. if (err != 0) { _PyFrame_SetStackPointer(frame, stack_pointer); _PyEval_FormatExcCheckArg(tstate, PyExc_NameError, @@ -5165,7 +5076,6 @@ _PyStackRef sub; sub = stack_pointer[-1]; container = stack_pointer[-2]; - /* del container[sub] */ _PyFrame_SetStackPointer(frame, stack_pointer); int err = PyObject_DelItem(PyStackRef_AsPyObjectBorrow(container), PyStackRef_AsPyObjectBorrow(sub)); @@ -5282,7 +5192,7 @@ _PyStackRef exc_st; exc_st = stack_pointer[-1]; awaitable_st = stack_pointer[-2]; - JUMPBY(0); // Pretend jump as we need source offset for monitoring + JUMPBY(0); (void)oparg; PyObject *exc = PyStackRef_AsPyObjectBorrow(exc_st); assert(exc && PyExceptionInstance_Check(exc)); @@ -5322,11 +5232,6 @@ INSTRUCTION_STATS(END_FOR); _PyStackRef value; value = stack_pointer[-1]; - /* Don't update instr_ptr, so that POP_ITER sees - * the FOR_ITER as the previous instruction. - * This has the benign side effect that if value is - * finalized it will see the location as the FOR_ITER's. - */ stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); _PyFrame_SetStackPointer(frame, stack_pointer); @@ -5377,9 +5282,6 @@ assert(executor->vm_data.code == code); assert(executor->vm_data.valid); assert(tstate->previous_executor == NULL); - /* If the eval breaker is set then stay in tier 1. - * This avoids any potentially infinite loops - * involving _RESUME_CHECK */ if (_Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) & _PY_EVAL_EVENTS_MASK) { opcode = executor->vm_data.opcode; oparg = (oparg & ~255) | executor->vm_data.oparg; @@ -5450,8 +5352,6 @@ _PyStackRef res; value = stack_pointer[-1]; PyObject *value_o = PyStackRef_AsPyObjectBorrow(value); - /* If value is a unicode object, then we know the result - * of format(value) is value itself. */ if (!PyUnicode_CheckExact(value_o)) { _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *res_o = PyObject_Format(value_o, NULL); @@ -5545,7 +5445,6 @@ } // _FOR_ITER { - /* before: [iter]; after: [iter, iter()] *or* [] (and jump over END_FOR.) */ PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter); _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *next_o = (*Py_TYPE(iter_o)->tp_iternext)(iter_o); @@ -5563,15 +5462,12 @@ _PyErr_Clear(tstate); stack_pointer = _PyFrame_GetStackPointer(frame); } - /* iterator ended normally */ assert(next_instr[oparg].op.code == END_FOR || next_instr[oparg].op.code == INSTRUMENTED_END_FOR); - /* Jump forward oparg, then skip following END_FOR */ JUMPBY(oparg + 1); DISPATCH(); } next = PyStackRef_FromPyObjectSteal(next_o); - // Common case: no jump, leave it to the code generator } stack_pointer[0] = next; stack_pointer += 1; @@ -5612,10 +5508,6 @@ JUMP_TO_PREDICTED(FOR_ITER); } #ifdef Py_GIL_DISABLED - // Since generators can't be used by multiple threads anyway we - // don't need to deopt here, but this lets us work on making - // generators thread-safe without necessarily having to - // specialize them thread-safely as well. if (!_PyObject_IsUniquelyReferenced((PyObject *)gen)) { UPDATE_MISS_STATS(FOR_ITER); assert(_PyOpcode_Deopt[opcode] == (FOR_ITER)); @@ -5634,14 +5526,11 @@ gen->gi_exc_state.previous_item = tstate->exc_info; tstate->exc_info = &gen->gi_exc_state; gen_frame->previous = frame; - // oparg is the return offset from the next instruction. frame->return_offset = (uint16_t)( 2 + oparg); } // _PUSH_FRAME { new_frame = gen_frame; - // Write it out explicitly because it's subtly different. - // Eventually this should be the only occurrence of this code. assert(tstate->interp->eval_frame == NULL); _PyInterpreterFrame *temp = new_frame; _PyFrame_SetStackPointer(frame, stack_pointer); @@ -5698,10 +5587,6 @@ { PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter); assert(Py_TYPE(iter_o) == &PyListIter_Type); - // For free-threaded Python, the loop exit can happen at any point during - // item retrieval, so it doesn't make much sense to check and jump - // separately before item retrieval. Any length check we do here can be - // invalid by the time we actually try to fetch the item. #ifdef Py_GIL_DISABLED assert(_PyObject_IsUniquelyReferenced(iter_o)); (void)iter_o; @@ -5717,7 +5602,6 @@ Py_DECREF(seq); stack_pointer = _PyFrame_GetStackPointer(frame); } - /* Jump forward oparg, then skip following END_FOR instruction */ JUMPBY(oparg + 1); DISPATCH(); } @@ -5738,8 +5622,6 @@ _PyFrame_SetStackPointer(frame, stack_pointer); int result = _PyList_GetItemRefNoLock(seq, it->it_index, &next); stack_pointer = _PyFrame_GetStackPointer(frame); - // A negative result means we lost a race with another thread - // and we need to take the slow path. if (result < 0) { UPDATE_MISS_STATS(FOR_ITER); assert(_PyOpcode_Deopt[opcode] == (FOR_ITER)); @@ -5747,7 +5629,6 @@ } if (result == 0) { it->it_index = -1; - /* Jump forward oparg, then skip following END_FOR instruction */ JUMPBY(oparg + 1); DISPATCH(); } @@ -5803,7 +5684,6 @@ #endif STAT_INC(FOR_ITER, hit); if (r->len <= 0) { - // Jump over END_FOR instruction. JUMPBY(oparg + 1); DISPATCH(); } @@ -5882,7 +5762,7 @@ stack_pointer = _PyFrame_GetStackPointer(frame); } #endif - /* Jump forward oparg, then skip following END_FOR instruction */ + JUMPBY(oparg + 1); DISPATCH(); } @@ -6031,7 +5911,6 @@ _PyStackRef iterable; _PyStackRef iter; iterable = stack_pointer[-1]; - /* before: [obj]; after [getiter(obj)] */ _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *iter_o = PyObject_GetIter(PyStackRef_AsPyObjectBorrow(iterable)); stack_pointer = _PyFrame_GetStackPointer(frame); @@ -6061,7 +5940,6 @@ _PyStackRef obj; _PyStackRef len; obj = stack_pointer[-1]; - // PUSH(len(TOS)) _PyFrame_SetStackPointer(frame, stack_pointer); Py_ssize_t len_i = PyObject_Length(PyStackRef_AsPyObjectBorrow(obj)); stack_pointer = _PyFrame_GetStackPointer(frame); @@ -6090,13 +5968,9 @@ _PyStackRef iterable; _PyStackRef iter; iterable = stack_pointer[-1]; - /* before: [obj]; after [getiter(obj)] */ PyObject *iterable_o = PyStackRef_AsPyObjectBorrow(iterable); if (PyCoro_CheckExact(iterable_o)) { - /* `iterable` is a coroutine */ if (!(_PyFrame_GetCode(frame)->co_flags & (CO_COROUTINE | CO_ITERABLE_COROUTINE))) { - /* and it is used in a 'yield from' expression of a - regular generator. */ _PyFrame_SetStackPointer(frame, stack_pointer); _PyErr_SetString(tstate, PyExc_TypeError, "cannot 'yield from' a coroutine object " @@ -6106,26 +5980,23 @@ } iter = iterable; } + else if (PyGen_CheckExact(iterable_o)) { + iter = iterable; + } else { - if (PyGen_CheckExact(iterable_o)) { - iter = iterable; - } - else { - /* `iterable` is not a generator. */ - _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *iter_o = PyObject_GetIter(iterable_o); - stack_pointer = _PyFrame_GetStackPointer(frame); - if (iter_o == NULL) { - JUMP_TO_LABEL(error); - } - iter = PyStackRef_FromPyObjectSteal(iter_o); - _PyFrame_SetStackPointer(frame, stack_pointer); - _PyStackRef tmp = iterable; - iterable = iter; - stack_pointer[-1] = iterable; - PyStackRef_CLOSE(tmp); - stack_pointer = _PyFrame_GetStackPointer(frame); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyObject *iter_o = PyObject_GetIter(iterable_o); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (iter_o == NULL) { + JUMP_TO_LABEL(error); } + iter = PyStackRef_FromPyObjectSteal(iter_o); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef tmp = iterable; + iterable = iter; + stack_pointer[-1] = iterable; + PyStackRef_CLOSE(tmp); + stack_pointer = _PyFrame_GetStackPointer(frame); } stack_pointer[-1] = iter; DISPATCH(); @@ -6241,13 +6112,11 @@ if (is_meth) { arg0 = PyStackRef_AsPyObjectBorrow(maybe_self[0]); } + else if (oparg) { + arg0 = PyStackRef_AsPyObjectBorrow(args[0]); + } else { - if (oparg) { - arg0 = PyStackRef_AsPyObjectBorrow(args[0]); - } - else { - arg0 = &_PyInstrumentation_MISSING; - } + arg0 = &_PyInstrumentation_MISSING; } _PyFrame_SetStackPointer(frame, stack_pointer); int err = _Py_call_instrumentation_2args( @@ -6264,14 +6133,12 @@ self_or_null = maybe_self; callable = func; PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); - // oparg counts all of the args, but *not* self: int total_args = oparg; _PyStackRef *arguments = args; if (!PyStackRef_IsNull(self_or_null[0])) { arguments--; total_args++; } - // Check if the call can be inlined or not if (Py_TYPE(callable_o) == &PyFunction_Type && tstate->interp->eval_frame == NULL && ((PyFunctionObject *)callable_o)->vectorcall == _PyFunction_Vectorcall) @@ -6284,18 +6151,14 @@ arguments, total_args, NULL, frame ); stack_pointer = _PyFrame_GetStackPointer(frame); - // Manipulate stack directly since we leave using DISPATCH_INLINED(). stack_pointer += -2 - oparg; assert(WITHIN_STACK_BOUNDS()); - // The frame has stolen all the arguments from the stack, - // so there is no need to clean them up. if (new_frame == NULL) { JUMP_TO_LABEL(error); } frame->return_offset = 4 ; DISPATCH_INLINED(new_frame); } - /* Callable is not a normal Python function */ STACKREFS_TO_PYOBJECTS(arguments, total_args, args_o); if (CONVERSION_FAILED(args_o)) { _PyFrame_SetStackPointer(frame, stack_pointer); @@ -6455,8 +6318,6 @@ func_st = func; (void)null; PyObject *func = PyStackRef_AsPyObjectBorrow(func_st); - // DICT_MERGE is called before this opcode if there are kwargs. - // It converts all dict subtypes in kwargs into regular dicts. EVAL_CALL_STAT_INC_IF_FUNCTION(EVAL_CALL_FUNCTION_EX, func); PyObject *result_o; assert(!_PyErr_Occurred(tstate)); @@ -6520,7 +6381,6 @@ tstate, func_st, locals, nargs, callargs, kwargs, frame); stack_pointer = _PyFrame_GetStackPointer(frame); - // Need to sync the stack since we exit with DISPATCH_INLINED. stack_pointer += -2; assert(WITHIN_STACK_BOUNDS()); if (new_frame == NULL) { @@ -6631,13 +6491,11 @@ if (is_meth) { arg = PyStackRef_AsPyObjectBorrow(self_or_null[0]); } + else if (args) { + arg = PyStackRef_AsPyObjectBorrow(args[0]); + } else { - if (args) { - arg = PyStackRef_AsPyObjectBorrow(args[0]); - } - else { - arg = &_PyInstrumentation_MISSING; - } + arg = &_PyInstrumentation_MISSING; } PyObject *function = PyStackRef_AsPyObjectBorrow(callable[0]); stack_pointer[-1] = kwnames_out; @@ -6655,7 +6513,6 @@ kwnames = kwnames_out; PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); PyObject *kwnames_o = PyStackRef_AsPyObjectBorrow(kwnames); - // oparg counts all of the args, but *not* self: int total_args = oparg; _PyStackRef *arguments = args; if (!PyStackRef_IsNull(self_or_null[0])) { @@ -6663,7 +6520,6 @@ total_args++; } int positional_args = total_args - (int)PyTuple_GET_SIZE(kwnames_o); - // Check if the call can be inlined or not if (Py_TYPE(callable_o) == &PyFunction_Type && tstate->interp->eval_frame == NULL && ((PyFunctionObject *)callable_o)->vectorcall == _PyFunction_Vectorcall) @@ -6681,9 +6537,6 @@ _PyFrame_SetStackPointer(frame, stack_pointer); PyStackRef_CLOSE(kwnames); stack_pointer = _PyFrame_GetStackPointer(frame); - // Sync stack explicitly since we leave using DISPATCH_INLINED(). - // The frame has stolen all the arguments from the stack, - // so there is no need to clean them up. if (new_frame == NULL) { JUMP_TO_LABEL(error); } @@ -6691,7 +6544,6 @@ frame->return_offset = 4 ; DISPATCH_INLINED(new_frame); } - /* Callable is not a normal Python function */ STACKREFS_TO_PYOBJECTS(arguments, total_args, args_o); if (CONVERSION_FAILED(args_o)) { _PyFrame_SetStackPointer(frame, stack_pointer); @@ -6796,7 +6648,7 @@ { exc_st = stack_pointer[-1]; awaitable_st = stack_pointer[-2]; - JUMPBY(0); // Pretend jump as we need source offset for monitoring + JUMPBY(0); (void)oparg; PyObject *exc = PyStackRef_AsPyObjectBorrow(exc_st); assert(exc && PyExceptionInstance_Check(exc)); @@ -6841,8 +6693,6 @@ _PyStackRef value; value = stack_pointer[-1]; receiver = stack_pointer[-2]; - /* Need to create a fake StopIteration error here, - * to conform to PEP 380 */ if (PyStackRef_GenCheck(receiver)) { _PyFrame_SetStackPointer(frame, stack_pointer); int err = monitor_stop_iteration(tstate, frame, this_instr, PyStackRef_AsPyObjectBorrow(value)); @@ -6926,10 +6776,8 @@ _PyErr_Clear(tstate); stack_pointer = _PyFrame_GetStackPointer(frame); } - /* iterator ended normally */ assert(next_instr[oparg].op.code == END_FOR || next_instr[oparg].op.code == INSTRUMENTED_END_FOR); - /* Skip END_FOR */ JUMPBY(oparg + 1); } DISPATCH(); @@ -7041,8 +6889,6 @@ } if (_PyOpcode_Caches[original_opcode]) { _PyBinaryOpCache *cache = (_PyBinaryOpCache *)(next_instr+1); - /* Prevent the underlying instruction from specializing - * and overwriting the instrumentation. */ PAUSE_ADAPTIVE_COUNTER(cache->counter); } opcode = original_opcode; @@ -7101,8 +6947,6 @@ JUMP_TO_LABEL(error); } } - // we make no attempt to optimize here; specializations should - // handle any case whose performance we care about PyObject *stack[] = {class, self}; _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *super = PyObject_Vectorcall(global_super, stack, oparg & 2, NULL); @@ -7182,7 +7026,7 @@ frame->instr_ptr = next_instr; next_instr += 1; INSTRUCTION_STATS(INSTRUMENTED_NOT_TAKEN); - (void)this_instr; // INSTRUMENTED_JUMP requires this_instr + (void)this_instr; INSTRUMENTED_JUMP(prev_instr, next_instr, PY_MONITORING_EVENT_BRANCH_LEFT); DISPATCH(); } @@ -7324,8 +7168,6 @@ ptrdiff_t off = this_instr - _PyFrame_GetBytecode(frame); frame->tlbc_index = ((_PyThreadStateImpl *)tstate)->tlbc_index; frame->instr_ptr = bytecode + off; - // Make sure this_instr gets reset correctley for any uops that - // follow next_instr = frame->instr_ptr; DISPATCH(); } @@ -7352,7 +7194,7 @@ { if ((oparg & RESUME_OPARG_LOCATION_MASK) < RESUME_AFTER_YIELD_FROM) { _Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY(); - QSBR_QUIESCENT_STATE(tstate); \ + QSBR_QUIESCENT_STATE(tstate); if (_Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) & _PY_EVAL_EVENTS_MASK) { _PyFrame_SetStackPointer(frame, stack_pointer); int err = _Py_HandlePending(tstate); @@ -7373,7 +7215,6 @@ JUMP_TO_LABEL(error); } if (frame->instr_ptr != this_instr) { - /* Instrumentation has jumped */ next_instr = frame->instr_ptr; } } @@ -7415,7 +7256,6 @@ _PyFrame_SetStackPointer(frame, stack_pointer); assert(EMPTY()); _Py_LeaveRecursiveCallPy(tstate); - // GH-99729: We need to unlink the frame *before* clearing it: _PyInterpreterFrame *dying = frame; frame = tstate->current_frame = dying->previous; _PyEval_FrameClearAndPop(tstate, dying); @@ -7462,9 +7302,6 @@ // _YIELD_VALUE { retval = val; - // NOTE: It's important that YIELD_VALUE never raises an exception! - // The compiler treats any exception raised here as a failed close() - // or throw() call. assert(frame->owner != FRAME_OWNED_BY_INTERPRETER); frame->instr_ptr++; PyGenObject *gen = _PyGen_GetGeneratorFromFrame(frame); @@ -7481,7 +7318,6 @@ _PyInterpreterFrame *gen_frame = frame; frame = tstate->current_frame = frame->previous; gen_frame->previous = NULL; - /* We don't know which of these is relevant here, so keep them equal */ assert(INLINE_CACHE_ENTRIES_SEND == INLINE_CACHE_ENTRIES_FOR_ITER); #if TIER_ONE assert(frame->instr_ptr->op.code == INSTRUMENTED_LINE || @@ -7514,13 +7350,11 @@ retval = stack_pointer[-1]; assert(frame->owner == FRAME_OWNED_BY_INTERPRETER); assert(_PyFrame_IsIncomplete(frame)); - /* Restore previous frame and return. */ tstate->current_frame = frame->previous; assert(!_PyErr_Occurred(tstate)); PyObject *result = PyStackRef_AsPyObjectSteal(retval); stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); - /* Not strictly necessary, but prevents warnings */ return result; } @@ -7574,7 +7408,6 @@ #if ENABLE_SPECIALIZATION if (this_instr->op.code == JUMP_BACKWARD) { this_instr->op.code = tstate->interp->jit ? JUMP_BACKWARD_JIT : JUMP_BACKWARD_NO_JIT; - // Need to re-dispatch so the warmup counter isn't off by one: next_instr = this_instr; DISPATCH_SAME_OPARG(); } @@ -7595,11 +7428,6 @@ } // _JUMP_BACKWARD_NO_INTERRUPT { - /* This bytecode is used in the `yield from` or `await` loop. - * If there is an interrupt, we want it handled in the innermost - * generator or coroutine, so we deliberately do not check it here. - * (see bpo-30039). - */ assert(oparg <= INSTR_OFFSET()); JUMPBY(-oparg); } @@ -7633,11 +7461,6 @@ } // _JUMP_BACKWARD_NO_INTERRUPT { - /* This bytecode is used in the `yield from` or `await` loop. - * If there is an interrupt, we want it handled in the innermost - * generator or coroutine, so we deliberately do not check it here. - * (see bpo-30039). - */ assert(oparg <= INSTR_OFFSET()); JUMPBY(-oparg); } @@ -7647,7 +7470,6 @@ _Py_BackoffCounter counter = this_instr[1].counter; if (backoff_counter_triggers(counter) && this_instr->op.code == JUMP_BACKWARD_JIT) { _Py_CODEUNIT *start = this_instr; - /* Back up over EXTENDED_ARGs so optimizer sees the whole instruction */ while (oparg > 255) { oparg >>= 8; start--; @@ -7687,11 +7509,6 @@ frame->instr_ptr = next_instr; next_instr += 1; INSTRUCTION_STATS(JUMP_BACKWARD_NO_INTERRUPT); - /* This bytecode is used in the `yield from` or `await` loop. - * If there is an interrupt, we want it handled in the innermost - * generator or coroutine, so we deliberately do not check it here. - * (see bpo-30039). - */ assert(oparg <= INSTR_OFFSET()); JUMPBY(-oparg); DISPATCH(); @@ -7722,11 +7539,6 @@ } // _JUMP_BACKWARD_NO_INTERRUPT { - /* This bytecode is used in the `yield from` or `await` loop. - * If there is an interrupt, we want it handled in the innermost - * generator or coroutine, so we deliberately do not check it here. - * (see bpo-30039). - */ assert(oparg <= INSTR_OFFSET()); JUMPBY(-oparg); } @@ -7853,26 +7665,15 @@ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 1); PyObject *attr_o; if (oparg & 1) { - /* Designed to work in tandem with CALL, pushes two values. */ attr_o = NULL; _PyFrame_SetStackPointer(frame, stack_pointer); int is_meth = _PyObject_GetMethod(PyStackRef_AsPyObjectBorrow(owner), name, &attr_o); stack_pointer = _PyFrame_GetStackPointer(frame); if (is_meth) { - /* We can bypass temporary bound method object. - meth is unbound method and obj is self. - meth | self | arg1 | ... | argN - */ - assert(attr_o != NULL); // No errors on this branch - self_or_null[0] = owner; // Transfer ownership + assert(attr_o != NULL); + self_or_null[0] = owner; } else { - /* meth is not an unbound method (but a regular attr, or - something was returned by a descriptor protocol). Set - the second element of the stack to NULL, to signal - CALL that it's not a method call. - meth | NULL | arg1 | ... | argN - */ stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); _PyFrame_SetStackPointer(frame, stack_pointer); @@ -7887,7 +7688,6 @@ } } else { - /* Classic, pushes one value. */ _PyFrame_SetStackPointer(frame, stack_pointer); attr_o = PyObject_GetAttr(PyStackRef_AsPyObjectBorrow(owner), name); stack_pointer = _PyFrame_GetStackPointer(frame); @@ -8086,7 +7886,6 @@ PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 1); _PyInterpreterFrame *new_frame = _PyFrame_PushUnchecked( tstate, PyStackRef_FromPyObjectNew(f), 2, frame); - // Manipulate stack directly because we exit with DISPATCH_INLINED(). STACK_SHRINK(1); new_frame->localsplus[0] = owner; new_frame->localsplus[1] = PyStackRef_FromPyObjectNew(name); @@ -8144,7 +7943,8 @@ JUMP_TO_PREDICTED(LOAD_ATTR); } #ifdef Py_GIL_DISABLED - if (!_Py_TryIncrefCompareStackRef(value_ptr, attr_o, &attr)) { + int increfed = _Py_TryIncrefCompareStackRef(value_ptr, attr_o, &attr); + if (!increfed) { if (true) { UPDATE_MISS_STATS(LOAD_ATTR); assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR)); @@ -8205,7 +8005,6 @@ uint16_t dictoffset = read_u16(&this_instr[4].cache); char *ptr = ((char *)PyStackRef_AsPyObjectBorrow(owner)) + MANAGED_DICT_OFFSET + dictoffset; PyObject *dict = FT_ATOMIC_LOAD_PTR_ACQUIRE(*(PyObject **)ptr); - /* This object has a __dict__, just not yet created */ if (dict != NULL) { UPDATE_MISS_STATS(LOAD_ATTR); assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR)); @@ -8330,7 +8129,6 @@ { PyObject *descr = read_obj(&this_instr[6].cache); assert(oparg & 1); - /* Cached method object */ STAT_INC(LOAD_ATTR, hit); assert(descr != NULL); assert(_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR)); @@ -8610,8 +8408,6 @@ } // _PUSH_FRAME { - // Write it out explicitly because it's subtly different. - // Eventually this should be the only occurrence of this code. assert(tstate->interp->eval_frame == NULL); _PyInterpreterFrame *temp = new_frame; stack_pointer += -1; @@ -8778,7 +8574,8 @@ } STAT_INC(LOAD_ATTR, hit); #ifdef Py_GIL_DISABLED - if (!_Py_TryIncrefCompareStackRef(&ep->me_value, attr_o, &attr)) { + int increfed = _Py_TryIncrefCompareStackRef(&ep->me_value, attr_o, &attr); + if (!increfed) { if (true) { UPDATE_MISS_STATS(LOAD_ATTR); assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR)); @@ -8845,7 +8642,6 @@ next_instr += 1; INSTRUCTION_STATS(LOAD_COMMON_CONSTANT); _PyStackRef value; - // Keep in sync with _common_constants in opcode.py assert(oparg < NUM_COMMON_CONSTANTS); value = PyStackRef_FromPyObjectNew(tstate->interp->common_consts[oparg]); stack_pointer[0] = value; @@ -8866,8 +8662,6 @@ _Py_CODEUNIT* const this_instr = next_instr - 1; (void)this_instr; _PyStackRef value; - /* We can't do this in the bytecode compiler as - * marshalling can intern strings and make them immortal. */ PyObject *obj = GETITEM(FRAME_CO_CONSTS, oparg); value = PyStackRef_FromPyObjectNew(obj); #if ENABLE_SPECIALIZATION_FT @@ -8876,7 +8670,6 @@ if (!_Py_atomic_compare_exchange_uint8( &this_instr->op.code, &expected, _Py_IsImmortal(obj) ? LOAD_CONST_IMMORTAL : LOAD_CONST_MORTAL)) { - // We might lose a race with instrumentation, which we don't care about. assert(expected >= MIN_INSTRUMENTED_OPCODE); } #else @@ -9155,8 +8948,6 @@ stack_pointer = _PyFrame_GetStackPointer(frame); if (v_o == NULL) { if (!_PyErr_Occurred(tstate)) { - /* _PyDict_LoadGlobal() returns NULL without raising - * an exception if the key doesn't exist */ _PyFrame_SetStackPointer(frame, stack_pointer); _PyEval_FormatExcCheckArg(tstate, PyExc_NameError, NAME_ERROR_MSG, name); @@ -9166,8 +8957,6 @@ } } else { - /* Slow-path if globals or builtins is not a dict */ - /* namespace 1: globals */ _PyFrame_SetStackPointer(frame, stack_pointer); int err = PyMapping_GetOptionalItem(GLOBALS(), name, &v_o); stack_pointer = _PyFrame_GetStackPointer(frame); @@ -9175,7 +8964,6 @@ JUMP_TO_LABEL(error); } if (v_o == NULL) { - /* namespace 2: builtins */ _PyFrame_SetStackPointer(frame, stack_pointer); int err = PyMapping_GetOptionalItem(BUILTINS(), name, &v_o); stack_pointer = _PyFrame_GetStackPointer(frame); @@ -9578,8 +9366,6 @@ JUMP_TO_LABEL(error); } } - // we make no attempt to optimize here; specializations should - // handle any case whose performance we care about PyObject *stack[] = {class, self}; _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *super = PyObject_Vectorcall(global_super, stack, oparg & 2, NULL); @@ -9756,7 +9542,7 @@ JUMP_TO_LABEL(error); } if (method_found) { - self_or_null = self_st; // transfer ownership + self_or_null = self_st; } else { stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); @@ -9797,8 +9583,6 @@ frame->instr_ptr = next_instr; next_instr += 1; INSTRUCTION_STATS(MAKE_CELL); - // "initial" is probably NULL but not if it's an arg (or set - // via the f_locals proxy before MAKE_CELL has run). PyObject *initial = PyStackRef_AsPyObjectBorrow(GETLOCAL(oparg)); PyObject *cell = PyCell_New(initial); if (cell == NULL) { @@ -9861,8 +9645,6 @@ dict_st = stack_pointer[-3 - (oparg - 1)]; PyObject *dict = PyStackRef_AsPyObjectBorrow(dict_st); assert(PyDict_CheckExact(dict)); - /* dict[key] = value */ - // Do not DECREF INPUTS because the function steals the references _PyFrame_SetStackPointer(frame, stack_pointer); int err = _PyDict_SetItem_Take2( (PyDictObject *)dict, @@ -9893,8 +9675,6 @@ names = stack_pointer[-1]; type = stack_pointer[-2]; subject = stack_pointer[-3]; - // Pop TOS and TOS1. Set TOS to a tuple of attributes on success, or - // None on failure. assert(PyTuple_CheckExact(PyStackRef_AsPyObjectBorrow(names))); _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *attrs_o = _PyEval_MatchClass(tstate, @@ -9917,15 +9697,14 @@ stack_pointer += -3; assert(WITHIN_STACK_BOUNDS()); if (attrs_o) { - assert(PyTuple_CheckExact(attrs_o)); // Success! + assert(PyTuple_CheckExact(attrs_o)); attrs = PyStackRef_FromPyObjectSteal(attrs_o); } else { if (_PyErr_Occurred(tstate)) { JUMP_TO_LABEL(error); } - // Error! - attrs = PyStackRef_None; // Failure! + attrs = PyStackRef_None; } stack_pointer[0] = attrs; stack_pointer += 1; @@ -9946,7 +9725,6 @@ _PyStackRef values_or_none; keys = stack_pointer[-1]; subject = stack_pointer[-2]; - // On successful match, PUSH(values). Otherwise, PUSH(None). _PyFrame_SetStackPointer(frame, stack_pointer); PyObject *values_or_none_o = _PyEval_MatchKeys(tstate, PyStackRef_AsPyObjectBorrow(subject), PyStackRef_AsPyObjectBorrow(keys)); @@ -10362,8 +10140,6 @@ ptrdiff_t off = this_instr - _PyFrame_GetBytecode(frame); frame->tlbc_index = ((_PyThreadStateImpl *)tstate)->tlbc_index; frame->instr_ptr = bytecode + off; - // Make sure this_instr gets reset correctley for any uops that - // follow next_instr = frame->instr_ptr; DISPATCH(); } @@ -10398,7 +10174,7 @@ { if ((oparg & RESUME_OPARG_LOCATION_MASK) < RESUME_AFTER_YIELD_FROM) { _Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY(); - QSBR_QUIESCENT_STATE(tstate); \ + QSBR_QUIESCENT_STATE(tstate); if (_Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) & _PY_EVAL_EVENTS_MASK) { _PyFrame_SetStackPointer(frame, stack_pointer); int err = _Py_HandlePending(tstate); @@ -10507,7 +10283,6 @@ _PyFrame_SetStackPointer(frame, stack_pointer); assert(EMPTY()); _Py_LeaveRecursiveCallPy(tstate); - // GH-99729: We need to unlink the frame *before* clearing it: _PyInterpreterFrame *dying = frame; frame = tstate->current_frame = dying->previous; _PyEval_FrameClearAndPop(tstate, dying); @@ -10677,8 +10452,6 @@ // _PUSH_FRAME { new_frame = gen_frame; - // Write it out explicitly because it's subtly different. - // Eventually this should be the only occurrence of this code. assert(tstate->interp->eval_frame == NULL); _PyInterpreterFrame *temp = new_frame; stack_pointer += -1; @@ -10711,7 +10484,6 @@ stack_pointer = _PyFrame_GetStackPointer(frame); JUMP_TO_LABEL(error); } - /* check if __annotations__ in locals()... */ _PyFrame_SetStackPointer(frame, stack_pointer); int err = PyMapping_GetOptionalItem(LOCALS(), &_Py_ID(__annotations__), &ann_dict); stack_pointer = _PyFrame_GetStackPointer(frame); @@ -11092,8 +10864,6 @@ stack_pointer = _PyFrame_GetStackPointer(frame); FT_ATOMIC_STORE_PTR_RELEASE(ep->me_value, PyStackRef_AsPyObjectSteal(value)); UNLOCK_OBJECT(dict); - // old_value should be DECREFed after GC track checking is done, if not, it could raise a segmentation fault, - // when dict only holds the strong reference to value in ep->me_value. STAT_INC(STORE_ATTR, hit); stack_pointer += -2; assert(WITHIN_STACK_BOUNDS()); @@ -11299,7 +11069,6 @@ _PyStackRef stop; // _SPECIALIZE_STORE_SLICE { - // Placeholder until we implement STORE_SLICE specialization #if ENABLE_SPECIALIZATION OPCODE_DEFERRED_INC(STORE_SLICE); #endif /* ENABLE_SPECIALIZATION */ @@ -11384,7 +11153,6 @@ // _STORE_SUBSCR { v = stack_pointer[-3]; - /* container[sub] = v */ _PyFrame_SetStackPointer(frame, stack_pointer); int err = PyObject_SetItem(PyStackRef_AsPyObjectBorrow(container), PyStackRef_AsPyObjectBorrow(sub), PyStackRef_AsPyObjectBorrow(v)); _PyStackRef tmp = sub; @@ -11488,7 +11256,6 @@ assert(_PyOpcode_Deopt[opcode] == (STORE_SUBSCR)); JUMP_TO_PREDICTED(STORE_SUBSCR); } - // Ensure nonnegative, zero-or-one-digit ints. if (!_PyLong_IsNonNegativeCompact((PyLongObject *)sub)) { UPDATE_MISS_STATS(STORE_SUBSCR); assert(_PyOpcode_Deopt[opcode] == (STORE_SUBSCR)); @@ -11500,7 +11267,6 @@ assert(_PyOpcode_Deopt[opcode] == (STORE_SUBSCR)); JUMP_TO_PREDICTED(STORE_SUBSCR); } - // Ensure index < len(list) if (index >= PyList_GET_SIZE(list)) { UNLOCK_OBJECT(list); if (true) { @@ -11514,7 +11280,7 @@ FT_ATOMIC_STORE_PTR_RELEASE(_PyList_ITEMS(list)[index], PyStackRef_AsPyObjectSteal(value)); assert(old_value != NULL); - UNLOCK_OBJECT(list); // unlock before decrefs! + UNLOCK_OBJECT(list); PyStackRef_CLOSE_SPECIALIZED(sub_st, _PyLong_ExactDealloc); stack_pointer += -3; assert(WITHIN_STACK_BOUNDS()); @@ -11754,7 +11520,6 @@ /* Skip 1 cache entry */ /* Skip 2 cache entries */ value = stack_pointer[-1]; - // This one is a bit weird, because we expect *some* failures: if (!PyStackRef_IsNone(value)) { UPDATE_MISS_STATS(TO_BOOL); assert(_PyOpcode_Deopt[opcode] == (TO_BOOL)); @@ -12117,15 +11882,6 @@ lasti = stack_pointer[-3]; 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_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. - */ PyObject *exc, *tb; PyObject *val_o = PyStackRef_AsPyObjectBorrow(val); PyObject *exit_func_o = PyStackRef_AsPyObjectBorrow(exit_func); @@ -12136,7 +11892,7 @@ tb = Py_None; } assert(PyStackRef_LongCheck(lasti)); - (void)lasti; // Shut up compiler warning if asserts are off + (void)lasti; PyObject *stack[5] = {NULL, PyStackRef_AsPyObjectBorrow(exit_self), exc, val_o, tb}; int has_self = !PyStackRef_IsNull(exit_self); _PyFrame_SetStackPointer(frame, stack_pointer); @@ -12165,9 +11921,6 @@ _PyStackRef retval; _PyStackRef value; retval = stack_pointer[-1]; - // NOTE: It's important that YIELD_VALUE never raises an exception! - // The compiler treats any exception raised here as a failed close() - // or throw() call. assert(frame->owner != FRAME_OWNED_BY_INTERPRETER); frame->instr_ptr++; PyGenObject *gen = _PyGen_GetGeneratorFromFrame(frame); @@ -12184,7 +11937,6 @@ _PyInterpreterFrame *gen_frame = frame; frame = tstate->current_frame = frame->previous; gen_frame->previous = NULL; - /* We don't know which of these is relevant here, so keep them equal */ assert(INLINE_CACHE_ENTRIES_SEND == INLINE_CACHE_ENTRIES_FOR_ITER); #if TIER_ONE assert(frame->instr_ptr->op.code == INSTRUMENTED_LINE || @@ -12256,7 +12008,6 @@ JUMP_TO_LABEL(error); LABEL(error) { - /* Double-check exception status. */ #ifdef NDEBUG if (!_PyErr_Occurred(tstate)) { _PyFrame_SetStackPointer(frame, stack_pointer); @@ -12268,7 +12019,6 @@ JUMP_TO_LABEL(error); assert(_PyErr_Occurred(tstate)); #endif - /* Log traceback info. */ assert(frame->owner != FRAME_OWNED_BY_INTERPRETER); if (!_PyFrame_IsIncomplete(frame)) { _PyFrame_SetStackPointer(frame, stack_pointer); @@ -12287,15 +12037,11 @@ JUMP_TO_LABEL(error); LABEL(exception_unwind) { - /* STACK SPILLED */ - /* We can't use frame->instr_ptr here, as RERAISE may have set it */ int offset = INSTR_OFFSET()-1; int level, handler, lasti; int handled = get_exception_handler(_PyFrame_GetCode(frame), offset, &level, &handler, &lasti); if (handled == 0) { - // No handlers, so exit. assert(_PyErr_Occurred(tstate)); - /* Pop remaining stack entries. */ _PyStackRef *stackbase = _PyFrame_Stackbase(frame); while (frame->stackpointer > stackbase) { _PyStackRef ref = _PyFrame_StackPop(frame); @@ -12319,10 +12065,6 @@ JUMP_TO_LABEL(error); } _PyFrame_StackPush(frame, PyStackRef_FromPyObjectSteal(lasti)); } - /* Make the raw exception data - available to the handler, - so a program can emulate the - Python main loop. */ PyObject *exc = _PyErr_GetRaisedException(tstate); _PyFrame_StackPush(frame, PyStackRef_FromPyObjectSteal(exc)); next_instr = _PyFrame_GetBytecode(frame) + handler; @@ -12330,7 +12072,6 @@ JUMP_TO_LABEL(error); if (err < 0) { JUMP_TO_LABEL(exception_unwind); } - /* Resume normal execution */ #ifdef Py_DEBUG if (frame->lltrace >= 5) { lltrace_resume_frame(frame); @@ -12345,17 +12086,14 @@ JUMP_TO_LABEL(error); LABEL(exit_unwind) { - /* STACK SPILLED */ assert(_PyErr_Occurred(tstate)); _Py_LeaveRecursiveCallPy(tstate); assert(frame->owner != FRAME_OWNED_BY_INTERPRETER); - // GH-99729: We need to unlink the frame *before* clearing it: _PyInterpreterFrame *dying = frame; frame = tstate->current_frame = dying->previous; _PyEval_FrameClearAndPop(tstate, dying); frame->return_offset = 0; if (frame->owner == FRAME_OWNED_BY_INTERPRETER) { - /* Restore previous frame and exit */ tstate->current_frame = frame->previous; return NULL; } @@ -12366,7 +12104,6 @@ JUMP_TO_LABEL(error); LABEL(start_frame) { - /* STACK SPILLED */ int too_deep = _Py_EnterRecursivePy(tstate); if (too_deep) { JUMP_TO_LABEL(exit_unwind); @@ -12378,9 +12115,6 @@ JUMP_TO_LABEL(error); JUMP_TO_LABEL(exit_unwind); } frame->lltrace = lltrace; - /* _PyEval_EvalFrameDefault() must not be called with an exception set, - because it can clear it (directly or indirectly) and so the - caller loses its exception */ assert(!_PyErr_Occurred(tstate)); #endif stack_pointer = _PyFrame_GetStackPointer(frame); diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c index a948cccbf85..da36704d91e 100644 --- a/Python/optimizer_bytecodes.c +++ b/Python/optimizer_bytecodes.c @@ -367,34 +367,39 @@ dummy_func(void) { } op(_TO_BOOL, (value -- res)) { - if (!optimize_to_bool(this_instr, ctx, value, &res)) { + int already_bool = optimize_to_bool(this_instr, ctx, value, &res); + if (!already_bool) { res = sym_new_truthiness(ctx, value, true); } } op(_TO_BOOL_BOOL, (value -- res)) { - if (!optimize_to_bool(this_instr, ctx, value, &res)) { + int already_bool = optimize_to_bool(this_instr, ctx, value, &res); + if (!already_bool) { sym_set_type(value, &PyBool_Type); res = sym_new_truthiness(ctx, value, true); } } op(_TO_BOOL_INT, (value -- res)) { - if (!optimize_to_bool(this_instr, ctx, value, &res)) { + int already_bool = optimize_to_bool(this_instr, ctx, value, &res); + if (!already_bool) { sym_set_type(value, &PyLong_Type); res = sym_new_truthiness(ctx, value, true); } } op(_TO_BOOL_LIST, (value -- res)) { - if (!optimize_to_bool(this_instr, ctx, value, &res)) { + int already_bool = optimize_to_bool(this_instr, ctx, value, &res); + if (!already_bool) { sym_set_type(value, &PyList_Type); res = sym_new_type(ctx, &PyBool_Type); } } op(_TO_BOOL_NONE, (value -- res)) { - if (!optimize_to_bool(this_instr, ctx, value, &res)) { + int already_bool = optimize_to_bool(this_instr, ctx, value, &res); + if (!already_bool) { sym_set_const(value, Py_None); res = sym_new_const(ctx, Py_False); } @@ -415,7 +420,8 @@ dummy_func(void) { } op(_TO_BOOL_STR, (value -- res)) { - if (!optimize_to_bool(this_instr, ctx, value, &res)) { + int already_bool = optimize_to_bool(this_instr, ctx, value, &res); + if (!already_bool) { res = sym_new_truthiness(ctx, value, true); } } diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h index e306567c812..ea25b8224a4 100644 --- a/Python/optimizer_cases.c.h +++ b/Python/optimizer_cases.c.h @@ -28,7 +28,6 @@ case _LOAD_FAST_CHECK: { JitOptSymbol *value; value = GETLOCAL(oparg); - // We guarantee this will error - just bail and don't optimize it. if (sym_is_null(value)) { ctx->done = true; } @@ -162,7 +161,8 @@ JitOptSymbol *value; JitOptSymbol *res; value = stack_pointer[-1]; - if (!optimize_to_bool(this_instr, ctx, value, &res)) { + int already_bool = optimize_to_bool(this_instr, ctx, value, &res); + if (!already_bool) { res = sym_new_truthiness(ctx, value, true); } stack_pointer[-1] = res; @@ -173,7 +173,8 @@ JitOptSymbol *value; JitOptSymbol *res; value = stack_pointer[-1]; - if (!optimize_to_bool(this_instr, ctx, value, &res)) { + int already_bool = optimize_to_bool(this_instr, ctx, value, &res); + if (!already_bool) { sym_set_type(value, &PyBool_Type); res = sym_new_truthiness(ctx, value, true); } @@ -185,7 +186,8 @@ JitOptSymbol *value; JitOptSymbol *res; value = stack_pointer[-1]; - if (!optimize_to_bool(this_instr, ctx, value, &res)) { + int already_bool = optimize_to_bool(this_instr, ctx, value, &res); + if (!already_bool) { sym_set_type(value, &PyLong_Type); res = sym_new_truthiness(ctx, value, true); } @@ -197,7 +199,8 @@ JitOptSymbol *value; JitOptSymbol *res; value = stack_pointer[-1]; - if (!optimize_to_bool(this_instr, ctx, value, &res)) { + int already_bool = optimize_to_bool(this_instr, ctx, value, &res); + if (!already_bool) { sym_set_type(value, &PyList_Type); res = sym_new_type(ctx, &PyBool_Type); } @@ -209,7 +212,8 @@ JitOptSymbol *value; JitOptSymbol *res; value = stack_pointer[-1]; - if (!optimize_to_bool(this_instr, ctx, value, &res)) { + int already_bool = optimize_to_bool(this_instr, ctx, value, &res); + if (!already_bool) { sym_set_const(value, Py_None); res = sym_new_const(ctx, Py_False); } @@ -241,7 +245,8 @@ JitOptSymbol *value; JitOptSymbol *res; value = stack_pointer[-1]; - if (!optimize_to_bool(this_instr, ctx, value, &res)) { + int already_bool = optimize_to_bool(this_instr, ctx, value, &res); + if (!already_bool) { res = sym_new_truthiness(ctx, value, true); } stack_pointer[-1] = res; @@ -301,8 +306,6 @@ stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); Py_DECREF(temp); - // TODO gh-115506: - // replace opcode with constant propagated one and add tests! } else { res = sym_new_type(ctx, &PyLong_Type); @@ -332,8 +335,6 @@ stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); Py_DECREF(temp); - // TODO gh-115506: - // replace opcode with constant propagated one and add tests! } else { res = sym_new_type(ctx, &PyLong_Type); @@ -363,8 +364,6 @@ stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); Py_DECREF(temp); - // TODO gh-115506: - // replace opcode with constant propagated one and add tests! } else { res = sym_new_type(ctx, &PyLong_Type); @@ -415,8 +414,6 @@ stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); Py_DECREF(temp); - // TODO gh-115506: - // replace opcode with constant propagated one and update tests! } else { res = sym_new_type(ctx, &PyFloat_Type); @@ -447,8 +444,6 @@ stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); Py_DECREF(temp); - // TODO gh-115506: - // replace opcode with constant propagated one and update tests! } else { res = sym_new_type(ctx, &PyFloat_Type); @@ -479,8 +474,6 @@ stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); Py_DECREF(temp); - // TODO gh-115506: - // replace opcode with constant propagated one and update tests! } else { res = sym_new_type(ctx, &PyFloat_Type); @@ -538,7 +531,6 @@ else { res = sym_new_type(ctx, &PyUnicode_Type); } - // _STORE_FAST: GETLOCAL(this_instr->operand0) = res; stack_pointer += -2; assert(WITHIN_STACK_BOUNDS()); @@ -690,7 +682,6 @@ ctx->frame->stack_pointer = stack_pointer; frame_pop(ctx); stack_pointer = ctx->frame->stack_pointer; - /* Stack space handling */ assert(corresponding_check_stack == NULL); assert(co != NULL); int framesize = co->co_framesize; @@ -699,7 +690,6 @@ curr_space -= framesize; co = get_code(this_instr); if (co == NULL) { - // might be impossible, but bailing is still safe ctx->done = true; } res = temp; @@ -735,7 +725,6 @@ /* _SEND is not a viable micro-op for tier 2 */ case _SEND_GEN_FRAME: { - // We are about to hit the end of the trace: ctx->done = true; break; } @@ -784,7 +773,6 @@ case _UNPACK_SEQUENCE: { JitOptSymbol **values; values = &stack_pointer[-1]; - /* This has to be done manually */ for (int i = 0; i < oparg; i++) { values[i] = sym_new_unknown(ctx); } @@ -834,7 +822,6 @@ case _UNPACK_EX: { JitOptSymbol **values; values = &stack_pointer[-1]; - /* This has to be done manually */ int totalargs = (oparg & 0xFF) + (oparg >> 8) + 1; for (int i = 0; i < totalargs; i++) { values[i] = sym_new_unknown(ctx); @@ -1097,15 +1084,8 @@ if (sym_matches_type_version(owner, type_version)) { REPLACE_OP(this_instr, _NOP, 0, 0); } else { - // add watcher so that whenever the type changes we invalidate this PyTypeObject *type = _PyType_LookupByVersion(type_version); - // if the type is null, it was not found in the cache (there was a conflict) - // with the key, in which case we can't trust the version if (type) { - // if the type version was set properly, then add a watcher - // if it wasn't this means that the type version was previously set to something else - // and we set the owner to bottom, so we don't need to add a watcher because we must have - // already added one earlier. if (sym_set_type_version(owner, type_version)) { PyType_Watch(TYPE_WATCHER_ID, (PyObject *)type); _Py_BloomFilter_Add(dependencies, type); @@ -1156,7 +1136,6 @@ } } if (attr == NULL) { - /* No conversion made. We don't know what `attr` is. */ attr = sym_new_not_null(ctx); } stack_pointer[-1] = attr; @@ -1507,7 +1486,6 @@ } case _FOR_ITER_GEN_FRAME: { - /* We are about to hit the end of the trace */ ctx->done = true; break; } @@ -1712,8 +1690,6 @@ } case _CHECK_PEP_523: { - /* Setting the eval frame function invalidates - * all executors, so no need to check dynamically */ if (_PyInterpreterState_GET()->eval_frame == NULL) { REPLACE_OP(this_instr, _NOP, 0 ,0); } @@ -1761,7 +1737,6 @@ assert(self_or_null != NULL); assert(args != NULL); if (sym_is_not_null(self_or_null)) { - // Bound method fiddling, same as _INIT_CALL_PY_EXACT_ARGS in VM args--; argcount++; } @@ -1787,16 +1762,13 @@ stack_pointer = new_frame->stack_pointer; co = get_code(this_instr); if (co == NULL) { - // should be about to _EXIT_TRACE anyway ctx->done = true; break; } - /* Stack space handling */ int framesize = co->co_framesize; assert(framesize > 0); curr_space += framesize; if (curr_space < 0 || curr_space > INT32_MAX) { - // won't fit in signed 32-bit int ctx->done = true; break; } @@ -1804,11 +1776,8 @@ if (first_valid_check_stack == NULL) { first_valid_check_stack = corresponding_check_stack; } - else { - if (corresponding_check_stack) { - // delete all but the first valid _CHECK_STACK_SPACE - corresponding_check_stack->opcode = _NOP; - } + else if (corresponding_check_stack) { + corresponding_check_stack->opcode = _NOP; } corresponding_check_stack = NULL; break; @@ -2049,7 +2018,6 @@ frame_pop(ctx); stack_pointer = ctx->frame->stack_pointer; res = sym_new_unknown(ctx); - /* Stack space handling */ assert(corresponding_check_stack == NULL); assert(co != NULL); int framesize = co->co_framesize; @@ -2061,7 +2029,6 @@ assert(WITHIN_STACK_BOUNDS()); co = get_code(this_instr); if (co == NULL) { - // might be impossible, but bailing is still safe ctx->done = true; } stack_pointer[-1] = res; @@ -2123,64 +2090,34 @@ bool lhs_float = sym_matches_type(left, &PyFloat_Type); bool rhs_float = sym_matches_type(right, &PyFloat_Type); if (!((lhs_int || lhs_float) && (rhs_int || rhs_float))) { - // There's something other than an int or float involved: res = sym_new_unknown(ctx); } - else { - if (oparg == NB_POWER || oparg == NB_INPLACE_POWER) { - // This one's fun... the *type* of the result depends on the - // *values* being exponentiated. However, exponents with one - // constant part are reasonably common, so it's probably worth - // trying to infer some simple cases: - // - A: 1 ** 1 -> 1 (int ** int -> int) - // - B: 1 ** -1 -> 1.0 (int ** int -> float) - // - C: 1.0 ** 1 -> 1.0 (float ** int -> float) - // - D: 1 ** 1.0 -> 1.0 (int ** float -> float) - // - E: -1 ** 0.5 ~> 1j (int ** float -> complex) - // - F: 1.0 ** 1.0 -> 1.0 (float ** float -> float) - // - G: -1.0 ** 0.5 ~> 1j (float ** float -> complex) - if (rhs_float) { - // Case D, E, F, or G... can't know without the sign of the LHS - // or whether the RHS is whole, which isn't worth the effort: - res = sym_new_unknown(ctx); - } - else { - if (lhs_float) { - // Case C: - res = sym_new_type(ctx, &PyFloat_Type); - } - else { - if (!sym_is_const(ctx, right)) { - // Case A or B... can't know without the sign of the RHS: - res = sym_new_unknown(ctx); - } - else { - if (_PyLong_IsNegative((PyLongObject *)sym_get_const(ctx, right))) { - // Case B: - res = sym_new_type(ctx, &PyFloat_Type); - } - else { - // Case A: - res = sym_new_type(ctx, &PyLong_Type); - } - } - } - } + else if (oparg == NB_POWER || oparg == NB_INPLACE_POWER) { + if (rhs_float) { + res = sym_new_unknown(ctx); + } + else if (lhs_float) { + res = sym_new_type(ctx, &PyFloat_Type); + } + else if (!sym_is_const(ctx, right)) { + res = sym_new_unknown(ctx); + } + else if (_PyLong_IsNegative((PyLongObject *)sym_get_const(ctx, right))) { + res = sym_new_type(ctx, &PyFloat_Type); } else { - if (oparg == NB_TRUE_DIVIDE || oparg == NB_INPLACE_TRUE_DIVIDE) { - res = sym_new_type(ctx, &PyFloat_Type); - } - else { - if (lhs_int && rhs_int) { - res = sym_new_type(ctx, &PyLong_Type); - } - else { - res = sym_new_type(ctx, &PyFloat_Type); - } - } + res = sym_new_type(ctx, &PyLong_Type); } } + else if (oparg == NB_TRUE_DIVIDE || oparg == NB_INPLACE_TRUE_DIVIDE) { + res = sym_new_type(ctx, &PyFloat_Type); + } + else if (lhs_int && rhs_int) { + res = sym_new_type(ctx, &PyLong_Type); + } + else { + res = sym_new_type(ctx, &PyFloat_Type); + } stack_pointer[-2] = res; stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); @@ -2253,11 +2190,9 @@ assert(value != NULL); eliminate_pop_guard(this_instr, !Py_IsNone(value)); } - else { - if (sym_has_type(flag)) { - assert(!sym_matches_type(flag, &_PyNone_Type)); - eliminate_pop_guard(this_instr, true); - } + else if (sym_has_type(flag)) { + assert(!sym_matches_type(flag, &_PyNone_Type)); + eliminate_pop_guard(this_instr, true); } sym_set_const(flag, Py_None); stack_pointer += -1; @@ -2273,11 +2208,9 @@ assert(value != NULL); eliminate_pop_guard(this_instr, Py_IsNone(value)); } - else { - if (sym_has_type(flag)) { - assert(!sym_matches_type(flag, &_PyNone_Type)); - eliminate_pop_guard(this_instr, false); - } + else if (sym_has_type(flag)) { + assert(!sym_matches_type(flag, &_PyNone_Type)); + eliminate_pop_guard(this_instr, false); } stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); @@ -2296,8 +2229,6 @@ case _CHECK_STACK_SPACE_OPERAND: { uint32_t framesize = (uint32_t)this_instr->operand0; (void)framesize; - /* We should never see _CHECK_STACK_SPACE_OPERANDs. - * They are only created at the end of this pass. */ Py_UNREACHABLE(); break; } |