diff options
author | Guido van Rossum <guido@python.org> | 2023-11-01 20:13:02 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-11-01 20:13:02 (GMT) |
commit | 7e135a48d619407cd4b2a6d80a4ce204b2f5f938 (patch) | |
tree | e0f063e3993696fc700092f50a1cee81f97974ff /Python/bytecodes.c | |
parent | 5d6db168b9cda58b4897763041a6109b93e421cb (diff) | |
download | cpython-7e135a48d619407cd4b2a6d80a4ce204b2f5f938.zip cpython-7e135a48d619407cd4b2a6d80a4ce204b2f5f938.tar.gz cpython-7e135a48d619407cd4b2a6d80a4ce204b2f5f938.tar.bz2 |
gh-111520: Integrate the Tier 2 interpreter in the Tier 1 interpreter (#111428)
- There is no longer a separate Python/executor.c file.
- Conventions in Python/bytecodes.c are slightly different -- don't use `goto error`,
you must use `GOTO_ERROR(error)` (same for others like `unused_local_error`).
- The `TIER_ONE` and `TIER_TWO` symbols are only valid in the generated (.c.h) files.
- In Lib/test/support/__init__.py, `Py_C_RECURSION_LIMIT` is imported from `_testcapi`.
- On Windows, in debug mode, stack allocation grows from 8MiB to 12MiB.
- **Beware!** This changes the env vars to enable uops and their debugging
to `PYTHON_UOPS` and `PYTHON_LLTRACE`.
Diffstat (limited to 'Python/bytecodes.c')
-rw-r--r-- | Python/bytecodes.c | 126 |
1 files changed, 64 insertions, 62 deletions
diff --git a/Python/bytecodes.c b/Python/bytecodes.c index 4c9ce7d..98af114 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -63,6 +63,7 @@ static size_t jump; static uint16_t invert, counter, index, hint; #define unused 0 // Used in a macro def, can't be static static uint32_t type_version; +static _PyUOpExecutorObject *current_executor; static PyObject * dummy_func( @@ -171,7 +172,7 @@ dummy_func( uintptr_t code_version = _PyFrame_GetCode(frame)->_co_instrumentation_version; if (code_version != global_version) { if (_Py_Instrument(_PyFrame_GetCode(frame), tstate->interp)) { - goto error; + GOTO_ERROR(error); } next_instr = this_instr; } @@ -268,7 +269,7 @@ dummy_func( if (PyGen_Check(receiver)) { PyErr_SetObject(PyExc_StopIteration, value); if (monitor_stop_iteration(tstate, frame, this_instr)) { - goto error; + GOTO_ERROR(error); } PyErr_SetRaisedException(NULL); } @@ -284,7 +285,7 @@ dummy_func( if (PyGen_Check(receiver) || PyCoro_CheckExact(receiver)) { PyErr_SetObject(PyExc_StopIteration, value); if (monitor_stop_iteration(tstate, frame, this_instr)) { - goto error; + GOTO_ERROR(error); } PyErr_SetRaisedException(NULL); } @@ -826,7 +827,7 @@ dummy_func( int err = _Py_call_instrumentation_arg( tstate, PY_MONITORING_EVENT_PY_RETURN, frame, this_instr, retval); - if (err) goto error; + if (err) GOTO_ERROR(error); STACK_SHRINK(1); assert(EMPTY()); _PyFrame_SetStackPointer(frame, stack_pointer); @@ -850,7 +851,7 @@ dummy_func( int err = _Py_call_instrumentation_arg( tstate, PY_MONITORING_EVENT_PY_RETURN, frame, this_instr, retval); - if (err) goto error; + if (err) GOTO_ERROR(error); Py_INCREF(retval); assert(EMPTY()); _PyFrame_SetStackPointer(frame, stack_pointer); @@ -906,7 +907,7 @@ dummy_func( if (PyAsyncGen_CheckExact(aiter)) { awaitable = type->tp_as_async->am_anext(aiter); if (awaitable == NULL) { - goto error; + GOTO_ERROR(error); } } else { if (type->tp_as_async != NULL){ @@ -916,7 +917,7 @@ dummy_func( if (getter != NULL) { next_iter = (*getter)(aiter); if (next_iter == NULL) { - goto error; + GOTO_ERROR(error); } } else { @@ -924,7 +925,7 @@ dummy_func( "'async for' requires an iterator with " "__anext__ method, got %.100s", type->tp_name); - goto error; + GOTO_ERROR(error); } awaitable = _PyCoro_GetAwaitableIter(next_iter); @@ -936,7 +937,7 @@ dummy_func( Py_TYPE(next_iter)->tp_name); Py_DECREF(next_iter); - goto error; + GOTO_ERROR(error); } else { Py_DECREF(next_iter); } @@ -1019,7 +1020,7 @@ dummy_func( JUMPBY(oparg); } else { - goto error; + GOTO_ERROR(error); } } Py_DECREF(v); @@ -1054,7 +1055,7 @@ dummy_func( int err = _Py_call_instrumentation_arg( tstate, PY_MONITORING_EVENT_PY_YIELD, frame, this_instr, retval); - if (err) goto error; + if (err) GOTO_ERROR(error); tstate->exc_info = gen->gi_exc_state.previous_item; gen->gi_exc_state.previous_item = NULL; _Py_LeaveRecursiveCallPy(tstate); @@ -1108,7 +1109,7 @@ dummy_func( else { assert(PyLong_Check(lasti)); _PyErr_SetString(tstate, PyExc_SystemError, "lasti is not an int"); - goto error; + GOTO_ERROR(error); } } assert(exc && PyExceptionInstance_Check(exc)); @@ -1187,7 +1188,7 @@ dummy_func( if (ns == NULL) { _PyErr_Format(tstate, PyExc_SystemError, "no locals when deleting %R", name); - goto error; + GOTO_ERROR(error); } err = PyObject_DelItem(ns, name); // Can't use ERROR_IF here. @@ -1195,7 +1196,7 @@ dummy_func( _PyEval_FormatExcCheckArg(tstate, PyExc_NameError, NAME_ERROR_MSG, name); - goto error; + GOTO_ERROR(error); } } @@ -1319,7 +1320,7 @@ dummy_func( _PyEval_FormatExcCheckArg(tstate, PyExc_NameError, NAME_ERROR_MSG, name); } - goto error; + GOTO_ERROR(error); } } @@ -1336,7 +1337,7 @@ dummy_func( inst(LOAD_FROM_DICT_OR_GLOBALS, (mod_or_class_dict -- v)) { PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); if (PyMapping_GetOptionalItem(mod_or_class_dict, name, &v) < 0) { - goto error; + GOTO_ERROR(error); } if (v == NULL) { v = PyDict_GetItemWithError(GLOBALS(), name); @@ -1344,17 +1345,17 @@ dummy_func( Py_INCREF(v); } else if (_PyErr_Occurred(tstate)) { - goto error; + GOTO_ERROR(error); } else { if (PyMapping_GetOptionalItem(BUILTINS(), name, &v) < 0) { - goto error; + GOTO_ERROR(error); } if (v == NULL) { _PyEval_FormatExcCheckArg( tstate, PyExc_NameError, NAME_ERROR_MSG, name); - goto error; + GOTO_ERROR(error); } } } @@ -1370,7 +1371,7 @@ dummy_func( } PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); if (PyMapping_GetOptionalItem(mod_or_class_dict, name, &v) < 0) { - goto error; + GOTO_ERROR(error); } if (v == NULL) { v = PyDict_GetItemWithError(GLOBALS(), name); @@ -1378,17 +1379,17 @@ dummy_func( Py_INCREF(v); } else if (_PyErr_Occurred(tstate)) { - goto error; + GOTO_ERROR(error); } else { if (PyMapping_GetOptionalItem(BUILTINS(), name, &v) < 0) { - goto error; + GOTO_ERROR(error); } if (v == NULL) { _PyEval_FormatExcCheckArg( tstate, PyExc_NameError, NAME_ERROR_MSG, name); - goto error; + GOTO_ERROR(error); } } } @@ -1510,7 +1511,7 @@ dummy_func( PyObject *initial = GETLOCAL(oparg); PyObject *cell = PyCell_New(initial); if (cell == NULL) { - goto error; + GOTO_ERROR(error); } SETLOCAL(oparg, cell); } @@ -1522,7 +1523,7 @@ dummy_func( // Fortunately we don't need its superpower. if (oldobj == NULL) { _PyEval_FormatExcUnbound(tstate, _PyFrame_GetCode(frame), oparg); - goto error; + GOTO_ERROR(error); } PyCell_SET(cell, NULL); Py_DECREF(oldobj); @@ -1535,7 +1536,7 @@ dummy_func( name = PyTuple_GET_ITEM(_PyFrame_GetCode(frame)->co_localsplusnames, oparg); if (PyMapping_GetOptionalItem(class_dict, name, &value) < 0) { Py_DECREF(class_dict); - goto error; + GOTO_ERROR(error); } Py_DECREF(class_dict); if (!value) { @@ -1543,7 +1544,7 @@ dummy_func( value = PyCell_GET(cell); if (value == NULL) { _PyEval_FormatExcUnbound(tstate, _PyFrame_GetCode(frame), oparg); - goto error; + GOTO_ERROR(error); } Py_INCREF(value); } @@ -1622,7 +1623,7 @@ dummy_func( inst(BUILD_SET, (values[oparg] -- set)) { set = PySet_New(NULL); if (set == NULL) - goto error; + GOTO_ERROR(error); int err = 0; for (int i = 0; i < oparg; i++) { PyObject *item = values[i]; @@ -1690,7 +1691,7 @@ dummy_func( PyTuple_GET_SIZE(keys) != (Py_ssize_t)oparg) { _PyErr_SetString(tstate, PyExc_SystemError, "bad BUILD_CONST_KEY_MAP keys argument"); - goto error; // Pop the keys and values. + GOTO_ERROR(error); // Pop the keys and values. } map = _PyDict_FromItems( &PyTuple_GET_ITEM(keys, 0), 1, @@ -2363,13 +2364,16 @@ dummy_func( JUMPBY(1-original_oparg); frame->instr_ptr = next_instr; Py_INCREF(executor); + if (executor->execute == _PyUopExecute) { + current_executor = (_PyUOpExecutorObject *)executor; + GOTO_TIER_TWO(); + } frame = executor->execute(executor, frame, stack_pointer); if (frame == NULL) { frame = tstate->current_frame; goto resume_with_error; } - next_instr = frame->instr_ptr; - goto resume_frame; + goto enter_tier_one; } inst(POP_JUMP_IF_FALSE, (unused/1, cond -- )) { @@ -2469,7 +2473,7 @@ dummy_func( _PyErr_SetString(tstate, PyExc_TypeError, "cannot 'yield from' a coroutine object " "in a non-coroutine generator"); - goto error; + GOTO_ERROR(error); } iter = iterable; } @@ -2480,7 +2484,7 @@ dummy_func( /* `iterable` is not a generator. */ iter = PyObject_GetIter(iterable); if (iter == NULL) { - goto error; + GOTO_ERROR(error); } DECREF_INPUTS(); } @@ -2518,7 +2522,7 @@ dummy_func( if (next == NULL) { if (_PyErr_Occurred(tstate)) { if (!_PyErr_ExceptionMatches(tstate, PyExc_StopIteration)) { - goto error; + GOTO_ERROR(error); } monitor_raise(tstate, frame, this_instr); _PyErr_Clear(tstate); @@ -2548,7 +2552,7 @@ dummy_func( else { if (_PyErr_Occurred(tstate)) { if (!_PyErr_ExceptionMatches(tstate, PyExc_StopIteration)) { - goto error; + GOTO_ERROR(error); } monitor_raise(tstate, frame, this_instr); _PyErr_Clear(tstate); @@ -2743,7 +2747,7 @@ dummy_func( "asynchronous context manager protocol", Py_TYPE(mgr)->tp_name); } - goto error; + GOTO_ERROR(error); } exit = _PyObject_LookupSpecial(mgr, &_Py_ID(__aexit__)); if (exit == NULL) { @@ -2755,7 +2759,7 @@ dummy_func( Py_TYPE(mgr)->tp_name); } Py_DECREF(enter); - goto error; + GOTO_ERROR(error); } DECREF_INPUTS(); res = _PyObject_CallNoArgs(enter); @@ -2779,7 +2783,7 @@ dummy_func( "context manager protocol", Py_TYPE(mgr)->tp_name); } - goto error; + GOTO_ERROR(error); } exit = _PyObject_LookupSpecial(mgr, &_Py_ID(__exit__)); if (exit == NULL) { @@ -2791,7 +2795,7 @@ dummy_func( Py_TYPE(mgr)->tp_name); } Py_DECREF(enter); - goto error; + GOTO_ERROR(error); } DECREF_INPUTS(); res = _PyObject_CallNoArgs(enter); @@ -3041,7 +3045,7 @@ dummy_func( // The frame has stolen all the arguments from the stack, // so there is no need to clean them up. if (new_frame == NULL) { - goto error; + GOTO_ERROR(error); } frame->return_offset = (uint16_t)(next_instr - this_instr); DISPATCH_INLINED(new_frame); @@ -3258,7 +3262,7 @@ dummy_func( STAT_INC(CALL, hit); PyObject *self = _PyType_NewManagedObject(tp); if (self == NULL) { - goto error; + GOTO_ERROR(error); } Py_DECREF(tp); _PyInterpreterFrame *shim = _PyFrame_PushTrampolineUnchecked( @@ -3295,7 +3299,7 @@ dummy_func( PyErr_Format(PyExc_TypeError, "__init__() should return None, not '%.200s'", Py_TYPE(should_be_none)->tp_name); - goto error; + GOTO_ERROR(error); } } @@ -3334,7 +3338,7 @@ dummy_func( // This is slower but CPython promises to check all non-vectorcall // function calls. if (_Py_EnterRecursiveCallTstate(tstate, " while calling a Python object")) { - goto error; + GOTO_ERROR(error); } PyObject *arg = args[0]; res = _PyCFunction_TrampolineCall(cfunc, PyCFunction_GET_SELF(callable), arg); @@ -3419,7 +3423,7 @@ dummy_func( PyObject *arg = args[0]; Py_ssize_t len_i = PyObject_Length(arg); if (len_i < 0) { - goto error; + GOTO_ERROR(error); } res = PyLong_FromSsize_t(len_i); assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); @@ -3444,7 +3448,7 @@ dummy_func( PyObject *inst = args[0]; int retval = PyObject_IsInstance(inst, cls); if (retval < 0) { - goto error; + GOTO_ERROR(error); } res = PyBool_FromLong(retval); assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); @@ -3494,7 +3498,7 @@ dummy_func( // This is slower but CPython promises to check all non-vectorcall // function calls. if (_Py_EnterRecursiveCallTstate(tstate, " while calling a Python object")) { - goto error; + GOTO_ERROR(error); } res = _PyCFunction_TrampolineCall(cfunc, self, arg); _Py_LeaveRecursiveCallTstate(tstate); @@ -3554,7 +3558,7 @@ dummy_func( // This is slower but CPython promises to check all non-vectorcall // function calls. if (_Py_EnterRecursiveCallTstate(tstate, " while calling a Python object")) { - goto error; + GOTO_ERROR(error); } res = _PyCFunction_TrampolineCall(cfunc, self, NULL); _Py_LeaveRecursiveCallTstate(tstate); @@ -3641,7 +3645,7 @@ dummy_func( // The frame has stolen all the arguments from the stack, // so there is no need to clean them up. if (new_frame == NULL) { - goto error; + GOTO_ERROR(error); } assert(next_instr - this_instr == 1); frame->return_offset = 1; @@ -3689,11 +3693,11 @@ dummy_func( assert(kwargs == NULL || PyDict_CheckExact(kwargs)); if (!PyTuple_CheckExact(callargs)) { if (check_args_iterable(tstate, func, callargs) < 0) { - goto error; + GOTO_ERROR(error); } PyObject *tuple = PySequence_Tuple(callargs); if (tuple == NULL) { - goto error; + GOTO_ERROR(error); } Py_SETREF(callargs, tuple); } @@ -3707,7 +3711,7 @@ dummy_func( int err = _Py_call_instrumentation_2args( tstate, PY_MONITORING_EVENT_CALL, frame, this_instr, func, arg); - if (err) goto error; + if (err) GOTO_ERROR(error); result = PyObject_Call(func, callargs, kwargs); if (result == NULL) { _Py_call_instrumentation_exc2( @@ -3738,7 +3742,7 @@ dummy_func( // Need to manually shrink the stack since we exit with DISPATCH_INLINED. STACK_SHRINK(oparg + 3); if (new_frame == NULL) { - goto error; + GOTO_ERROR(error); } assert(next_instr - this_instr == 1); frame->return_offset = 1; @@ -3759,7 +3763,7 @@ dummy_func( Py_DECREF(codeobj); if (func_obj == NULL) { - goto error; + GOTO_ERROR(error); } _PyFunction_SetVersion( @@ -3799,7 +3803,7 @@ dummy_func( PyFunctionObject *func = (PyFunctionObject *)frame->f_funcobj; PyGenObject *gen = (PyGenObject *)_Py_MakeCoro(func); if (gen == NULL) { - goto error; + GOTO_ERROR(error); } assert(EMPTY()); _PyFrame_SetStackPointer(frame, stack_pointer); @@ -3988,24 +3992,25 @@ dummy_func( op(_POP_JUMP_IF_FALSE, (flag -- )) { if (Py_IsFalse(flag)) { - pc = oparg; + next_uop = current_executor->trace + oparg; } } op(_POP_JUMP_IF_TRUE, (flag -- )) { if (Py_IsTrue(flag)) { - pc = oparg; + next_uop = current_executor->trace + oparg; } } op(_JUMP_TO_TOP, (--)) { - pc = 0; + next_uop = current_executor->trace; CHECK_EVAL_BREAKER(); } op(_SET_IP, (--)) { TIER_TWO_ONLY - frame->instr_ptr = ip_offset + oparg; + // TODO: Put the code pointer in `operand` to avoid indirection via `frame` + frame->instr_ptr = _PyCode_CODE(_PyFrame_GetCode(frame)) + oparg; } op(_SAVE_RETURN_OFFSET, (--)) { @@ -4019,10 +4024,7 @@ dummy_func( op(_EXIT_TRACE, (--)) { TIER_TWO_ONLY - _PyFrame_SetStackPointer(frame, stack_pointer); - Py_DECREF(self); - OPT_HIST(trace_uop_execution_counter, trace_run_length_hist); - return frame; + GOTO_TIER_ONE(); } op(_INSERT, (unused[oparg], top -- top, unused[oparg])) { |