|
44 | 44 | # error "ceval.c must be build with Py_BUILD_CORE define for best performance" |
45 | 45 | #endif |
46 | 46 |
|
| 47 | +#ifndef Py_DEBUG |
| 48 | +// GH-89279: The MSVC compiler does not inline these static inline functions |
| 49 | +// in PGO build in _PyEval_EvalFrameDefault(), because this function is over |
| 50 | +// the limit of PGO, and that limit cannot be configured. |
| 51 | +// Define them as macros to make sure that they are always inlined by the |
| 52 | +// preprocessor. |
| 53 | + |
| 54 | +#undef Py_DECREF |
| 55 | +#define Py_DECREF(arg) \ |
| 56 | + do { \ |
| 57 | + PyObject *op = _PyObject_CAST(arg); \ |
| 58 | + if (--op->ob_refcnt == 0) { \ |
| 59 | + destructor dealloc = Py_TYPE(op)->tp_dealloc; \ |
| 60 | + (*dealloc)(op); \ |
| 61 | + } \ |
| 62 | + } while (0) |
| 63 | + |
| 64 | +#undef Py_XDECREF |
| 65 | +#define Py_XDECREF(arg) \ |
| 66 | + do { \ |
| 67 | + PyObject *xop = _PyObject_CAST(arg); \ |
| 68 | + if (xop != NULL) { \ |
| 69 | + Py_DECREF(xop); \ |
| 70 | + } \ |
| 71 | + } while (0) |
| 72 | + |
| 73 | +#undef Py_IS_TYPE |
| 74 | +#define Py_IS_TYPE(ob, type) \ |
| 75 | + (_PyObject_CAST(ob)->ob_type == (type)) |
| 76 | + |
| 77 | +#undef _Py_DECREF_SPECIALIZED |
| 78 | +#define _Py_DECREF_SPECIALIZED(arg, dealloc) \ |
| 79 | + do { \ |
| 80 | + PyObject *op = _PyObject_CAST(arg); \ |
| 81 | + if (--op->ob_refcnt == 0) { \ |
| 82 | + destructor d = (destructor)(dealloc); \ |
| 83 | + d(op); \ |
| 84 | + } \ |
| 85 | + } while (0) |
| 86 | +#endif |
| 87 | + |
| 88 | +// GH-89279: Similar to above, force inlining by using a macro. |
| 89 | +#if defined(_MSC_VER) && SIZEOF_INT == 4 |
| 90 | +#define _Py_atomic_load_relaxed_int32(ATOMIC_VAL) (assert(sizeof((ATOMIC_VAL)->_value) == 4), *((volatile int*)&((ATOMIC_VAL)->_value))) |
| 91 | +#else |
| 92 | +#define _Py_atomic_load_relaxed_int32(ATOMIC_VAL) _Py_atomic_load_relaxed(ATOMIC_VAL) |
| 93 | +#endif |
| 94 | + |
| 95 | + |
47 | 96 | /* Forward declarations */ |
48 | 97 | static PyObject *trace_call_function( |
49 | 98 | PyThreadState *tstate, PyObject *callable, PyObject **stack, |
@@ -192,10 +241,10 @@ COMPUTE_EVAL_BREAKER(PyInterpreterState *interp, |
192 | 241 | struct _ceval_state *ceval2) |
193 | 242 | { |
194 | 243 | _Py_atomic_store_relaxed(&ceval2->eval_breaker, |
195 | | - _Py_atomic_load_relaxed(&ceval2->gil_drop_request) |
196 | | - | (_Py_atomic_load_relaxed(&ceval->signals_pending) |
| 244 | + _Py_atomic_load_relaxed_int32(&ceval2->gil_drop_request) |
| 245 | + | (_Py_atomic_load_relaxed_int32(&ceval->signals_pending) |
197 | 246 | && _Py_ThreadCanHandleSignals(interp)) |
198 | | - | (_Py_atomic_load_relaxed(&ceval2->pending.calls_to_do) |
| 247 | + | (_Py_atomic_load_relaxed_int32(&ceval2->pending.calls_to_do) |
199 | 248 | && _Py_ThreadCanHandlePendingCalls()) |
200 | 249 | | ceval2->pending.async_exc); |
201 | 250 | } |
@@ -740,7 +789,7 @@ _Py_FinishPendingCalls(PyThreadState *tstate) |
740 | 789 |
|
741 | 790 | struct _pending_calls *pending = &tstate->interp->ceval.pending; |
742 | 791 |
|
743 | | - if (!_Py_atomic_load_relaxed(&(pending->calls_to_do))) { |
| 792 | + if (!_Py_atomic_load_relaxed_int32(&(pending->calls_to_do))) { |
744 | 793 | return; |
745 | 794 | } |
746 | 795 |
|
@@ -1187,22 +1236,22 @@ eval_frame_handle_pending(PyThreadState *tstate) |
1187 | 1236 | struct _ceval_runtime_state *ceval = &runtime->ceval; |
1188 | 1237 |
|
1189 | 1238 | /* Pending signals */ |
1190 | | - if (_Py_atomic_load_relaxed(&ceval->signals_pending)) { |
| 1239 | + if (_Py_atomic_load_relaxed_int32(&ceval->signals_pending)) { |
1191 | 1240 | if (handle_signals(tstate) != 0) { |
1192 | 1241 | return -1; |
1193 | 1242 | } |
1194 | 1243 | } |
1195 | 1244 |
|
1196 | 1245 | /* Pending calls */ |
1197 | 1246 | struct _ceval_state *ceval2 = &tstate->interp->ceval; |
1198 | | - if (_Py_atomic_load_relaxed(&ceval2->pending.calls_to_do)) { |
| 1247 | + if (_Py_atomic_load_relaxed_int32(&ceval2->pending.calls_to_do)) { |
1199 | 1248 | if (make_pending_calls(tstate->interp) != 0) { |
1200 | 1249 | return -1; |
1201 | 1250 | } |
1202 | 1251 | } |
1203 | 1252 |
|
1204 | 1253 | /* GIL drop request */ |
1205 | | - if (_Py_atomic_load_relaxed(&ceval2->gil_drop_request)) { |
| 1254 | + if (_Py_atomic_load_relaxed_int32(&ceval2->gil_drop_request)) { |
1206 | 1255 | /* Give another thread a chance */ |
1207 | 1256 | if (_PyThreadState_Swap(&runtime->gilstate, NULL) != tstate) { |
1208 | 1257 | Py_FatalError("tstate mix-up"); |
@@ -1360,7 +1409,7 @@ eval_frame_handle_pending(PyThreadState *tstate) |
1360 | 1409 |
|
1361 | 1410 | #define CHECK_EVAL_BREAKER() \ |
1362 | 1411 | _Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY(); \ |
1363 | | - if (_Py_atomic_load_relaxed(eval_breaker)) { \ |
| 1412 | + if (_Py_atomic_load_relaxed_int32(eval_breaker)) { \ |
1364 | 1413 | goto handle_eval_breaker; \ |
1365 | 1414 | } |
1366 | 1415 |
|
@@ -1640,10 +1689,8 @@ typedef struct { |
1640 | 1689 | PyObject *kwnames; |
1641 | 1690 | } CallShape; |
1642 | 1691 |
|
1643 | | -static inline bool |
1644 | | -is_method(PyObject **stack_pointer, int args) { |
1645 | | - return PEEK(args+2) != NULL; |
1646 | | -} |
| 1692 | +// GH-89279: Must be a macro to be sure it's inlined by MSVC. |
| 1693 | +#define is_method(stack_pointer, args) (PEEK((args)+2) != NULL) |
1647 | 1694 |
|
1648 | 1695 | #define KWNAMES_LEN() \ |
1649 | 1696 | (call_shape.kwnames == NULL ? 0 : ((int)PyTuple_GET_SIZE(call_shape.kwnames))) |
@@ -1796,7 +1843,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int |
1796 | 1843 | PREDICTED(RESUME_QUICK); |
1797 | 1844 | assert(tstate->cframe == &cframe); |
1798 | 1845 | assert(frame == cframe.current_frame); |
1799 | | - if (_Py_atomic_load_relaxed(eval_breaker) && oparg < 2) { |
| 1846 | + if (_Py_atomic_load_relaxed_int32(eval_breaker) && oparg < 2) { |
1800 | 1847 | goto handle_eval_breaker; |
1801 | 1848 | } |
1802 | 1849 | DISPATCH(); |
|
0 commit comments