Skip to content

Commit 61edee2

Browse files
committed
Merge remote-tracking branch 'upstream/main' into expose_codegen
2 parents 50c0cc2 + 1e197e6 commit 61edee2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

77 files changed

+2915
-1569
lines changed

Doc/c-api/refcounting.rst

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
Reference Counting
88
******************
99

10-
The macros in this section are used for managing reference counts of Python
11-
objects.
10+
The functions and macros in this section are used for managing reference counts
11+
of Python objects.
1212

1313

1414
.. c:function:: Py_ssize_t Py_REFCNT(PyObject *o)
@@ -129,6 +129,11 @@ objects.
129129
It is a good idea to use this macro whenever decrementing the reference
130130
count of an object that might be traversed during garbage collection.
131131
132+
.. versionchanged:: 3.12
133+
The macro argument is now only evaluated once. If the argument has side
134+
effects, these are no longer duplicated.
135+
136+
132137
.. c:function:: void Py_IncRef(PyObject *o)
133138
134139
Increment the reference count for object *o*. A function version of :c:func:`Py_XINCREF`.
@@ -139,3 +144,40 @@ objects.
139144
140145
Decrement the reference count for object *o*. A function version of :c:func:`Py_XDECREF`.
141146
It can be used for runtime dynamic embedding of Python.
147+
148+
149+
.. c:macro:: Py_SETREF(dst, src)
150+
151+
Macro safely decrementing the `dst` reference count and setting `dst` to
152+
`src`.
153+
154+
As in case of :c:func:`Py_CLEAR`, "the obvious" code can be deadly::
155+
156+
Py_DECREF(dst);
157+
dst = src;
158+
159+
The safe way is::
160+
161+
Py_SETREF(dst, src);
162+
163+
That arranges to set `dst` to `src` _before_ decrementing reference count of
164+
*dst* old value, so that any code triggered as a side-effect of `dst`
165+
getting torn down no longer believes `dst` points to a valid object.
166+
167+
.. versionadded:: 3.6
168+
169+
.. versionchanged:: 3.12
170+
The macro arguments are now only evaluated once. If an argument has side
171+
effects, these are no longer duplicated.
172+
173+
174+
.. c:macro:: Py_XSETREF(dst, src)
175+
176+
Variant of :c:macro:`Py_SETREF` macro that uses :c:func:`Py_XDECREF` instead
177+
of :c:func:`Py_DECREF`.
178+
179+
.. versionadded:: 3.6
180+
181+
.. versionchanged:: 3.12
182+
The macro arguments are now only evaluated once. If an argument has side
183+
effects, these are no longer duplicated.

Doc/library/index.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ as a collection of packages, so it may be necessary to use the packaging
2727
tools provided with the operating system to obtain some or all of the
2828
optional components.
2929

30-
In addition to the standard library, there is a growing collection of
31-
several thousand components (from individual programs and modules to
30+
In addition to the standard library, there is an active collection of
31+
hundreds of thousands of components (from individual programs and modules to
3232
packages and entire application development frameworks), available from
3333
the `Python Package Index <https://pypi.org>`_.
3434

Doc/whatsnew/3.12.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -792,6 +792,11 @@ Porting to Python 3.12
792792
:class:`bytes` type is accepted for bytes strings.
793793
(Contributed by Victor Stinner in :gh:`98393`.)
794794

795+
* The :c:macro:`Py_CLEAR`, :c:macro:`Py_SETREF` and :c:macro:`Py_XSETREF`
796+
macros now only evaluate their argument once. If the argument has side
797+
effects, these side effects are no longer duplicated.
798+
(Contributed by Victor Stinner in :gh:`98724`.)
799+
795800
Deprecated
796801
----------
797802

Include/cpython/object.h

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -41,15 +41,15 @@ typedef struct _Py_Identifier {
4141
Py_ssize_t index;
4242
} _Py_Identifier;
4343

44-
#if defined(NEEDS_PY_IDENTIFIER) || !defined(Py_BUILD_CORE)
44+
#ifndef Py_BUILD_CORE
4545
// For now we are keeping _Py_IDENTIFIER for continued use
4646
// in non-builtin extensions (and naughty PyPI modules).
4747

4848
#define _Py_static_string_init(value) { .string = (value), .index = -1 }
4949
#define _Py_static_string(varname, value) static _Py_Identifier varname = _Py_static_string_init(value)
5050
#define _Py_IDENTIFIER(varname) _Py_static_string(PyId_##varname, #varname)
5151

52-
#endif /* NEEDS_PY_IDENTIFIER */
52+
#endif /* !Py_BUILD_CORE */
5353

5454
typedef struct {
5555
/* Number implementations must check *both*
@@ -305,37 +305,41 @@ _PyObject_GenericSetAttrWithDict(PyObject *, PyObject *,
305305

306306
PyAPI_FUNC(PyObject *) _PyObject_FunctionStr(PyObject *);
307307

308-
/* Safely decref `op` and set `op` to `op2`.
308+
/* Safely decref `dst` and set `dst` to `src`.
309309
*
310310
* As in case of Py_CLEAR "the obvious" code can be deadly:
311311
*
312-
* Py_DECREF(op);
313-
* op = op2;
312+
* Py_DECREF(dst);
313+
* dst = src;
314314
*
315315
* The safe way is:
316316
*
317-
* Py_SETREF(op, op2);
317+
* Py_SETREF(dst, src);
318318
*
319-
* That arranges to set `op` to `op2` _before_ decref'ing, so that any code
320-
* triggered as a side-effect of `op` getting torn down no longer believes
321-
* `op` points to a valid object.
319+
* That arranges to set `dst` to `src` _before_ decref'ing, so that any code
320+
* triggered as a side-effect of `dst` getting torn down no longer believes
321+
* `dst` points to a valid object.
322322
*
323-
* Py_XSETREF is a variant of Py_SETREF that uses Py_XDECREF instead of
324-
* Py_DECREF.
323+
* gh-98724: Use the _tmp_dst_ptr variable to evaluate the 'dst' macro argument
324+
* exactly once, to prevent the duplication of side effects in this macro.
325325
*/
326-
327-
#define Py_SETREF(op, op2) \
328-
do { \
329-
PyObject *_py_tmp = _PyObject_CAST(op); \
330-
(op) = (op2); \
331-
Py_DECREF(_py_tmp); \
326+
#define Py_SETREF(dst, src) \
327+
do { \
328+
PyObject **_tmp_dst_ptr = _Py_CAST(PyObject**, &(dst)); \
329+
PyObject *_tmp_dst = (*_tmp_dst_ptr); \
330+
*_tmp_dst_ptr = _PyObject_CAST(src); \
331+
Py_DECREF(_tmp_dst); \
332332
} while (0)
333333

334-
#define Py_XSETREF(op, op2) \
335-
do { \
336-
PyObject *_py_tmp = _PyObject_CAST(op); \
337-
(op) = (op2); \
338-
Py_XDECREF(_py_tmp); \
334+
/* Py_XSETREF() is a variant of Py_SETREF() that uses Py_XDECREF() instead of
335+
* Py_DECREF().
336+
*/
337+
#define Py_XSETREF(dst, src) \
338+
do { \
339+
PyObject **_tmp_dst_ptr = _Py_CAST(PyObject**, &(dst)); \
340+
PyObject *_tmp_dst = (*_tmp_dst_ptr); \
341+
*_tmp_dst_ptr = _PyObject_CAST(src); \
342+
Py_XDECREF(_tmp_dst); \
339343
} while (0)
340344

341345

Include/internal/pycore_code.h

Lines changed: 43 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,6 @@ typedef struct {
9191

9292
#define INLINE_CACHE_ENTRIES_FOR_ITER CACHE_ENTRIES(_PyForIterCache)
9393

94-
extern uint8_t _PyOpcode_Adaptive[256];
95-
9694
// Borrowed references to common callables:
9795
struct callable_cache {
9896
PyObject *isinstance;
@@ -219,11 +217,14 @@ extern int _Py_Specialize_LoadAttr(PyObject *owner, _Py_CODEUNIT *instr,
219217
PyObject *name);
220218
extern int _Py_Specialize_StoreAttr(PyObject *owner, _Py_CODEUNIT *instr,
221219
PyObject *name);
222-
extern int _Py_Specialize_LoadGlobal(PyObject *globals, PyObject *builtins, _Py_CODEUNIT *instr, PyObject *name);
223-
extern int _Py_Specialize_BinarySubscr(PyObject *sub, PyObject *container, _Py_CODEUNIT *instr);
224-
extern int _Py_Specialize_StoreSubscr(PyObject *container, PyObject *sub, _Py_CODEUNIT *instr);
225-
extern int _Py_Specialize_Call(PyObject *callable, _Py_CODEUNIT *instr,
226-
int nargs, PyObject *kwnames);
220+
extern void _Py_Specialize_LoadGlobal(PyObject *globals, PyObject *builtins,
221+
_Py_CODEUNIT *instr, PyObject *name);
222+
extern void _Py_Specialize_BinarySubscr(PyObject *sub, PyObject *container,
223+
_Py_CODEUNIT *instr);
224+
extern void _Py_Specialize_StoreSubscr(PyObject *container, PyObject *sub,
225+
_Py_CODEUNIT *instr);
226+
extern void _Py_Specialize_Call(PyObject *callable, _Py_CODEUNIT *instr,
227+
int nargs, PyObject *kwnames);
227228
extern void _Py_Specialize_BinaryOp(PyObject *lhs, PyObject *rhs, _Py_CODEUNIT *instr,
228229
int oparg, PyObject **locals);
229230
extern void _Py_Specialize_CompareOp(PyObject *lhs, PyObject *rhs,
@@ -377,8 +378,22 @@ write_location_entry_start(uint8_t *ptr, int code, int length)
377378

378379
/* With a 16-bit counter, we have 12 bits for the counter value, and 4 bits for the backoff */
379380
#define ADAPTIVE_BACKOFF_BITS 4
380-
/* The initial counter value is 1 == 2**ADAPTIVE_BACKOFF_START - 1 */
381-
#define ADAPTIVE_BACKOFF_START 1
381+
382+
// A value of 1 means that we attempt to specialize the *second* time each
383+
// instruction is executed. Executing twice is a much better indicator of
384+
// "hotness" than executing once, but additional warmup delays only prevent
385+
// specialization. Most types stabilize by the second execution, too:
386+
#define ADAPTIVE_WARMUP_VALUE 1
387+
#define ADAPTIVE_WARMUP_BACKOFF 1
388+
389+
// A value of 52 means that we attempt to re-specialize after 53 misses (a prime
390+
// number, useful for avoiding artifacts if every nth value is a different type
391+
// or something). Setting the backoff to 0 means that the counter is reset to
392+
// the same state as a warming-up instruction (value == 1, backoff == 1) after
393+
// deoptimization. This isn't strictly necessary, but it is bit easier to reason
394+
// about when thinking about the opcode transitions as a state machine:
395+
#define ADAPTIVE_COOLDOWN_VALUE 52
396+
#define ADAPTIVE_COOLDOWN_BACKOFF 0
382397

383398
#define MAX_BACKOFF_VALUE (16 - ADAPTIVE_BACKOFF_BITS)
384399

@@ -390,9 +405,15 @@ adaptive_counter_bits(int value, int backoff) {
390405
}
391406

392407
static inline uint16_t
393-
adaptive_counter_start(void) {
394-
unsigned int value = (1 << ADAPTIVE_BACKOFF_START) - 1;
395-
return adaptive_counter_bits(value, ADAPTIVE_BACKOFF_START);
408+
adaptive_counter_warmup(void) {
409+
return adaptive_counter_bits(ADAPTIVE_WARMUP_VALUE,
410+
ADAPTIVE_WARMUP_BACKOFF);
411+
}
412+
413+
static inline uint16_t
414+
adaptive_counter_cooldown(void) {
415+
return adaptive_counter_bits(ADAPTIVE_COOLDOWN_VALUE,
416+
ADAPTIVE_COOLDOWN_BACKOFF);
396417
}
397418

398419
static inline uint16_t
@@ -435,6 +456,16 @@ _PyCode_LineNumberFromArray(PyCodeObject *co, int index)
435456
}
436457
}
437458

459+
typedef struct _PyShimCodeDef {
460+
const uint8_t *code;
461+
int codelen;
462+
int stacksize;
463+
const char *cname;
464+
} _PyShimCodeDef;
465+
466+
extern PyCodeObject *
467+
_Py_MakeShimCode(const _PyShimCodeDef *code);
468+
438469

439470
#ifdef __cplusplus
440471
}

Include/internal/pycore_frame.h

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -42,27 +42,27 @@ typedef enum _framestate {
4242
enum _frameowner {
4343
FRAME_OWNED_BY_THREAD = 0,
4444
FRAME_OWNED_BY_GENERATOR = 1,
45-
FRAME_OWNED_BY_FRAME_OBJECT = 2
45+
FRAME_OWNED_BY_FRAME_OBJECT = 2,
46+
FRAME_OWNED_BY_CSTACK = 3,
4647
};
4748

4849
typedef struct _PyInterpreterFrame {
4950
/* "Specials" section */
50-
PyObject *f_funcobj; /* Strong reference */
51-
PyObject *f_globals; /* Borrowed reference */
52-
PyObject *f_builtins; /* Borrowed reference */
53-
PyObject *f_locals; /* Strong reference, may be NULL */
51+
PyObject *f_funcobj; /* Strong reference. Only valid if not on C stack */
52+
PyObject *f_globals; /* Borrowed reference. Only valid if not on C stack */
53+
PyObject *f_builtins; /* Borrowed reference. Only valid if not on C stack */
54+
PyObject *f_locals; /* Strong reference, may be NULL. Only valid if not on C stack */
5455
PyCodeObject *f_code; /* Strong reference */
55-
PyFrameObject *frame_obj; /* Strong reference, may be NULL */
56+
PyFrameObject *frame_obj; /* Strong reference, may be NULL. Only valid if not on C stack */
5657
/* Linkage section */
5758
struct _PyInterpreterFrame *previous;
5859
// NOTE: This is not necessarily the last instruction started in the given
5960
// frame. Rather, it is the code unit *prior to* the *next* instruction. For
6061
// example, it may be an inline CACHE entry, an instruction we just jumped
6162
// over, or (in the case of a newly-created frame) a totally invalid value:
6263
_Py_CODEUNIT *prev_instr;
63-
int stacktop; /* Offset of TOS from localsplus */
64+
int stacktop; /* Offset of TOS from localsplus */
6465
uint16_t yield_offset;
65-
bool is_entry; // Whether this is the "root" frame for the current _PyCFrame.
6666
char owner;
6767
/* Locals and stack */
6868
PyObject *localsplus[1];
@@ -110,7 +110,6 @@ _PyFrame_InitializeSpecials(
110110
frame->stacktop = code->co_nlocalsplus;
111111
frame->frame_obj = NULL;
112112
frame->prev_instr = _PyCode_CODE(code) - 1;
113-
frame->is_entry = false;
114113
frame->yield_offset = 0;
115114
frame->owner = FRAME_OWNED_BY_THREAD;
116115
}

0 commit comments

Comments
 (0)