|
22 | 22 | #include "pycore_sysmodule.h" // _PySys_Audit()
|
23 | 23 | #include "pycore_tuple.h" // _PyTuple_ITEMS()
|
24 | 24 | #include "pycore_typeobject.h" // _PySuper_Lookup()
|
| 25 | +#include "pycore_uops.h" // _PyUOpExecutorObject |
25 | 26 | #include "pycore_emscripten_signal.h" // _Py_CHECK_EMSCRIPTEN_SIGNALS
|
26 | 27 |
|
27 | 28 | #include "pycore_dict.h"
|
@@ -223,14 +224,6 @@ _PyEvalFramePushAndInit_Ex(PyThreadState *tstate, PyFunctionObject *func,
|
223 | 224 | static void
|
224 | 225 | _PyEvalFrameClearAndPop(PyThreadState *tstate, _PyInterpreterFrame *frame);
|
225 | 226 |
|
226 |
| -typedef PyObject *(*convertion_func_ptr)(PyObject *); |
227 |
| - |
228 |
| -static const convertion_func_ptr CONVERSION_FUNCTIONS[4] = { |
229 |
| - [FVC_STR] = PyObject_Str, |
230 |
| - [FVC_REPR] = PyObject_Repr, |
231 |
| - [FVC_ASCII] = PyObject_ASCII |
232 |
| -}; |
233 |
| - |
234 | 227 | #define UNBOUNDLOCAL_ERROR_MSG \
|
235 | 228 | "cannot access local variable '%s' where it is not associated with a value"
|
236 | 229 | #define UNBOUNDFREE_ERROR_MSG \
|
@@ -2771,3 +2764,131 @@ void Py_LeaveRecursiveCall(void)
|
2771 | 2764 | {
|
2772 | 2765 | _Py_LeaveRecursiveCall();
|
2773 | 2766 | }
|
| 2767 | + |
| 2768 | +///////////////////// Experimental UOp Interpreter ///////////////////// |
| 2769 | + |
| 2770 | +// UPDATE_MISS_STATS (called by DEOPT_IF) uses next_instr |
| 2771 | +// TODO: Make it do something useful |
| 2772 | +#undef UPDATE_MISS_STATS |
| 2773 | +#define UPDATE_MISS_STATS(INSTNAME) ((void)0) |
| 2774 | + |
| 2775 | +_PyInterpreterFrame * |
| 2776 | +_PyUopExecute(_PyExecutorObject *executor, _PyInterpreterFrame *frame, PyObject **stack_pointer) |
| 2777 | +{ |
| 2778 | +#ifdef LLTRACE |
| 2779 | + char *uop_debug = Py_GETENV("PYTHONUOPSDEBUG"); |
| 2780 | + int lltrace = 0; |
| 2781 | + if (uop_debug != NULL && *uop_debug >= '0') { |
| 2782 | + lltrace = *uop_debug - '0'; // TODO: Parse an int and all that |
| 2783 | + } |
| 2784 | + if (lltrace >= 2) { |
| 2785 | + PyCodeObject *code = _PyFrame_GetCode(frame); |
| 2786 | + _Py_CODEUNIT *instr = frame->prev_instr + 1; |
| 2787 | + fprintf(stderr, |
| 2788 | + "Entering _PyUopExecute for %s (%s:%d) at offset %ld\n", |
| 2789 | + PyUnicode_AsUTF8(code->co_qualname), |
| 2790 | + PyUnicode_AsUTF8(code->co_filename), |
| 2791 | + code->co_firstlineno, |
| 2792 | + (long)(instr - (_Py_CODEUNIT *)code->co_code_adaptive)); |
| 2793 | + } |
| 2794 | +#endif |
| 2795 | + |
| 2796 | + PyThreadState *tstate = _PyThreadState_GET(); |
| 2797 | + _PyUOpExecutorObject *self = (_PyUOpExecutorObject *)executor; |
| 2798 | + |
| 2799 | + // Equivalent to CHECK_EVAL_BREAKER() |
| 2800 | + _Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY(); |
| 2801 | + if (_Py_atomic_load_relaxed_int32(&tstate->interp->ceval.eval_breaker)) { |
| 2802 | + if (_Py_HandlePending(tstate) != 0) { |
| 2803 | + goto error; |
| 2804 | + } |
| 2805 | + } |
| 2806 | + |
| 2807 | + OBJECT_STAT_INC(optimization_traces_executed); |
| 2808 | + _Py_CODEUNIT *ip_offset = (_Py_CODEUNIT *)_PyFrame_GetCode(frame)->co_code_adaptive - 1; |
| 2809 | + int pc = 0; |
| 2810 | + int opcode; |
| 2811 | + uint64_t operand; |
| 2812 | + int oparg; |
| 2813 | + for (;;) { |
| 2814 | + opcode = self->trace[pc].opcode; |
| 2815 | + operand = self->trace[pc].operand; |
| 2816 | + oparg = (int)operand; |
| 2817 | +#ifdef LLTRACE |
| 2818 | + if (lltrace >= 3) { |
| 2819 | + const char *opname = opcode < 256 ? _PyOpcode_OpName[opcode] : ""; |
| 2820 | + int stack_level = (int)(stack_pointer - _PyFrame_Stackbase(frame)); |
| 2821 | + fprintf(stderr, " uop %s %d, operand %" PRIu64 ", stack_level %d\n", |
| 2822 | + opname, opcode, operand, stack_level); |
| 2823 | + } |
| 2824 | +#endif |
| 2825 | + pc++; |
| 2826 | + OBJECT_STAT_INC(optimization_uops_executed); |
| 2827 | + switch (opcode) { |
| 2828 | + |
| 2829 | +#undef ENABLE_SPECIALIZATION |
| 2830 | +#define ENABLE_SPECIALIZATION 0 |
| 2831 | +#include "executor_cases.c.h" |
| 2832 | + |
| 2833 | + case SET_IP: |
| 2834 | + { |
| 2835 | + frame->prev_instr = ip_offset + oparg; |
| 2836 | + break; |
| 2837 | + } |
| 2838 | + |
| 2839 | + case EXIT_TRACE: |
| 2840 | + { |
| 2841 | + _PyFrame_SetStackPointer(frame, stack_pointer); |
| 2842 | + Py_DECREF(self); |
| 2843 | + return frame; |
| 2844 | + } |
| 2845 | + |
| 2846 | + default: |
| 2847 | + { |
| 2848 | + fprintf(stderr, "Unknown uop %d, operand %" PRIu64 "\n", opcode, operand); |
| 2849 | + Py_FatalError("Unknown uop"); |
| 2850 | + abort(); // Unreachable |
| 2851 | + for (;;) {} |
| 2852 | + // Really unreachable |
| 2853 | + } |
| 2854 | + |
| 2855 | + } |
| 2856 | + } |
| 2857 | + |
| 2858 | +pop_4_error: |
| 2859 | + STACK_SHRINK(1); |
| 2860 | +pop_3_error: |
| 2861 | + STACK_SHRINK(1); |
| 2862 | +pop_2_error: |
| 2863 | + STACK_SHRINK(1); |
| 2864 | +pop_1_error: |
| 2865 | + STACK_SHRINK(1); |
| 2866 | +error: |
| 2867 | + // On ERROR_IF we return NULL as the frame. |
| 2868 | + // The caller recovers the frame from cframe.current_frame. |
| 2869 | +#ifdef LLTRACE |
| 2870 | + if (lltrace >= 2) { |
| 2871 | + fprintf(stderr, "Error: [Opcode %d, operand %" PRIu64 "]\n", opcode, operand); |
| 2872 | + } |
| 2873 | +#endif |
| 2874 | + _PyFrame_SetStackPointer(frame, stack_pointer); |
| 2875 | + Py_DECREF(self); |
| 2876 | + return NULL; |
| 2877 | + |
| 2878 | +PREDICTED(UNPACK_SEQUENCE) |
| 2879 | +PREDICTED(COMPARE_OP) |
| 2880 | +PREDICTED(LOAD_SUPER_ATTR) |
| 2881 | +PREDICTED(STORE_SUBSCR) |
| 2882 | +PREDICTED(BINARY_SUBSCR) |
| 2883 | +PREDICTED(BINARY_OP) |
| 2884 | + // On DEOPT_IF we just repeat the last instruction. |
| 2885 | + // This presumes nothing was popped from the stack (nor pushed). |
| 2886 | +#ifdef LLTRACE |
| 2887 | + if (lltrace >= 2) { |
| 2888 | + fprintf(stderr, "DEOPT: [Opcode %d, operand %" PRIu64 "]\n", opcode, operand); |
| 2889 | + } |
| 2890 | +#endif |
| 2891 | + _PyFrame_SetStackPointer(frame, stack_pointer); |
| 2892 | + Py_DECREF(self); |
| 2893 | + return frame; |
| 2894 | +} |
0 commit comments