Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 4 additions & 5 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -156,16 +156,15 @@ Misc/libabigail.abignore @encukou
# ----------------------------------------------------------------------------

# Android
Android/ @mhsmith @freakboy3742
Platforms/Android/ @mhsmith @freakboy3742
Doc/using/android.rst @mhsmith @freakboy3742
Lib/_android_support.py @mhsmith @freakboy3742
Lib/test/test_android.py @mhsmith @freakboy3742

# iOS
Doc/using/ios.rst @freakboy3742
Lib/_ios_support.py @freakboy3742
Apple/ @freakboy3742
iOS/ @freakboy3742
Platforms/Apple/ @freakboy3742

# macOS
Mac/ @python/macos-team
Expand All @@ -176,8 +175,8 @@ Lib/test/test__osx_support.py @python/macos-team
Tools/wasm/README.md @brettcannon @freakboy3742 @emmatyping

# WebAssembly (Emscripten)
Tools/wasm/config.site-wasm32-emscripten @freakboy3742 @emmatyping
Tools/wasm/emscripten @freakboy3742 @emmatyping
Platforms/emscripten @freakboy3742 @emmatyping
Tools/wasm/emscripten @freakboy3742 @emmatyping

# WebAssembly (WASI)
Platforms/WASI @brettcannon @emmatyping @savannahostrowski
Expand Down
2 changes: 1 addition & 1 deletion Doc/c-api/dict.rst
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ Dictionary objects
* If the key is present, set *\*result* to a new :term:`strong reference`
to the value and return ``1``.
* If the key is missing, set *\*result* to ``NULL`` and return ``0``.
* On error, raise an exception and return ``-1``.
* On error, raise an exception, set *\*result* to ``NULL`` and return ``-1``.

The first argument can be a :class:`dict` or a :class:`frozendict`.

Expand Down
4 changes: 2 additions & 2 deletions Doc/whatsnew/3.15.rst
Original file line number Diff line number Diff line change
Expand Up @@ -411,8 +411,8 @@ embedding applications, and native libraries.
unwinding for the whole Python process.

(Contributed by Pablo Galindo Salgado and Savannah Ostrowski in
:gh:`149201`; PEP 831 written by Pablo Galindo Salgado, Ken Jin, and
Savannah Ostrowski.)
:gh:`149201`; PEP 831 written by Pablo Galindo Salgado, Ken Jin,
Savannah Ostrowski, and Diego Russo.)

.. seealso:: :pep:`831` for further details.

Expand Down
4 changes: 3 additions & 1 deletion Include/internal/pycore_bytesobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,11 @@ _PyBytes_ReverseFind(const char *haystack, Py_ssize_t len_haystack,
//
// Export for 'array' shared extension.
PyAPI_FUNC(void)
_PyBytes_Repeat(char* dest, Py_ssize_t len_dest,
_PyBytes_RepeatBuffer(char* dest, Py_ssize_t len_dest,
const char* src, Py_ssize_t len_src);

PyAPI_FUNC(PyObject *) _PyBytes_Repeat(PyObject *self, Py_ssize_t n);

/* _PyBytesObject_SIZE gives the basic size of a bytes object; any memory allocation
for a bytes object of length n should request PyBytesObject_SIZE + n bytes.

Expand Down
1 change: 1 addition & 0 deletions Include/internal/pycore_tuple.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ PyAPI_FUNC(PyObject *)_PyTuple_FromStackRefStealOnSuccess(const union _PyStackRe
PyAPI_FUNC(PyObject *)_PyTuple_FromArraySteal(PyObject *const *, Py_ssize_t);
PyAPI_FUNC(PyObject *) _PyTuple_BinarySlice(PyObject *, PyObject *, PyObject *);
PyAPI_FUNC(PyObject *) _PyTuple_Concat(PyObject *, PyObject *);
PyAPI_FUNC(PyObject *) _PyTuple_Repeat(PyObject *self, Py_ssize_t n);

PyAPI_FUNC(PyObject *) _PyTuple_FromPair(PyObject *, PyObject *);
PyAPI_FUNC(PyObject *) _PyTuple_FromPairSteal(PyObject *, PyObject *);
Expand Down
1 change: 1 addition & 0 deletions Include/internal/pycore_unicodeobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ extern PyObject* _PyUnicode_ResizeCompact(
Py_ssize_t length);
extern PyObject* _PyUnicode_GetEmpty(void);
PyAPI_FUNC(PyObject*) _PyUnicode_BinarySlice(PyObject *, PyObject *, PyObject *);
PyAPI_FUNC(PyObject *) _PyUnicode_Repeat(PyObject *str, Py_ssize_t len);


/* Generic helper macro to convert characters of different types.
Expand Down
14 changes: 14 additions & 0 deletions Lib/test/test_capi/test_opt.py
Original file line number Diff line number Diff line change
Expand Up @@ -6138,6 +6138,20 @@ def __init__(self, x):
C(0) if i else str(0)
"""))

def test_load_special_type_guard_deopt(self):
script_helper.assert_python_ok("-s", "-c", textwrap.dedent(f"""
def f1():
class Context:
def __enter__(self): ...
def __exit__(self, e, v, t): ...

with Context():
pass

for _ in range({TIER2_THRESHOLD + 5}):
f1()
"""), PYTHON_JIT="1")

def global_identity(x):
return x

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fix a crash in the JIT optimizer when a specialized ``LOAD_SPECIAL`` guard deoptimized after inserting the synthetic ``NULL`` stack entry.
14 changes: 8 additions & 6 deletions Modules/_remote_debugging/threads.c
Original file line number Diff line number Diff line change
Expand Up @@ -450,12 +450,14 @@ unwind_stack_for_thread(
set_exception_cause(unwinder, PyExc_RuntimeError, "Failed to collect frames");
goto error;
}
// Update last_profiled_frame for next sample
uintptr_t lpf_addr =
*current_tstate + (uintptr_t)unwinder->debug_offsets.thread_state.last_profiled_frame;
if (_Py_RemoteDebug_WriteRemoteMemory(&unwinder->handle, lpf_addr,
sizeof(uintptr_t), &frame_addr) < 0) {
PyErr_Clear(); // Non-fatal
// Update last_profiled_frame for next sample if it changed
if (frame_addr != ctx.last_profiled_frame) {
uintptr_t lpf_addr =
*current_tstate + (uintptr_t)unwinder->debug_offsets.thread_state.last_profiled_frame;
if (_Py_RemoteDebug_WriteRemoteMemory(&unwinder->handle, lpf_addr,
sizeof(uintptr_t), &frame_addr) < 0) {
PyErr_Clear(); // Non-fatal
}
}
} else {
// No caching - process entire frame chain with base_frame validation
Expand Down
6 changes: 3 additions & 3 deletions Modules/arraymodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
#endif

#include "Python.h"
#include "pycore_bytesobject.h" // _PyBytes_Repeat
#include "pycore_bytesobject.h" // _PyBytes_RepeatBuffer
#include "pycore_call.h" // _PyObject_CallMethod()
#include "pycore_ceval.h" // _PyEval_GetBuiltin()
#include "pycore_floatobject.h" // _PY_FLOAT_BIG_ENDIAN
Expand Down Expand Up @@ -1147,7 +1147,7 @@ array_repeat(PyObject *op, Py_ssize_t n)

const Py_ssize_t oldbytes = array_length * a->ob_descr->itemsize;
const Py_ssize_t newbytes = oldbytes * n;
_PyBytes_Repeat(np->ob_item, newbytes, a->ob_item, oldbytes);
_PyBytes_RepeatBuffer(np->ob_item, newbytes, a->ob_item, oldbytes);

return (PyObject *)np;
}
Expand Down Expand Up @@ -1304,7 +1304,7 @@ array_inplace_repeat(PyObject *op, Py_ssize_t n)
if (array_resize(self, n * array_size) == -1)
return NULL;

_PyBytes_Repeat(self->ob_item, n*size, self->ob_item, size);
_PyBytes_RepeatBuffer(self->ob_item, n*size, self->ob_item, size);
}
return Py_NewRef(self);
}
Expand Down
4 changes: 2 additions & 2 deletions Objects/bytearrayobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -402,7 +402,7 @@ bytearray_repeat_lock_held(PyObject *op, Py_ssize_t count)
PyByteArrayObject* result = (PyByteArrayObject *)PyByteArray_FromStringAndSize(NULL, size);
const char* buf = PyByteArray_AS_STRING(self);
if (result != NULL && size != 0) {
_PyBytes_Repeat(result->ob_bytes, size, buf, mysize);
_PyBytes_RepeatBuffer(result->ob_bytes, size, buf, mysize);
}
return (PyObject *)result;
}
Expand Down Expand Up @@ -439,7 +439,7 @@ bytearray_irepeat_lock_held(PyObject *op, Py_ssize_t count)
}

char* buf = PyByteArray_AS_STRING(self);
_PyBytes_Repeat(buf, size, buf, mysize);
_PyBytes_RepeatBuffer(buf, size, buf, mysize);

return Py_NewRef(self);
}
Expand Down
12 changes: 6 additions & 6 deletions Objects/bytesobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#include "Python.h"
#include "pycore_abstract.h" // _PyIndex_Check()
#include "pycore_bytes_methods.h" // _Py_bytes_startswith()
#include "pycore_bytesobject.h" // _PyBytes_Find(), _PyBytes_Repeat()
#include "pycore_bytesobject.h" // _PyBytes_Find(), _PyBytes_RepeatBuffer()
#include "pycore_call.h" // _PyObject_CallNoArgs()
#include "pycore_ceval.h" // _PyEval_GetBuiltin()
#include "pycore_format.h" // F_LJUST
Expand Down Expand Up @@ -1581,8 +1581,8 @@ _PyBytes_Concat(PyObject *a, PyObject *b)
return result;
}

static PyObject *
bytes_repeat(PyObject *self, Py_ssize_t n)
PyObject *
_PyBytes_Repeat(PyObject *self, Py_ssize_t n)
{
PyBytesObject *a = _PyBytes_CAST(self);
if (n < 0)
Expand Down Expand Up @@ -1613,7 +1613,7 @@ bytes_repeat(PyObject *self, Py_ssize_t n)
set_ob_shash(op, -1);
op->ob_sval[size] = '\0';

_PyBytes_Repeat(op->ob_sval, size, a->ob_sval, Py_SIZE(a));
_PyBytes_RepeatBuffer(op->ob_sval, size, a->ob_sval, Py_SIZE(a));

return (PyObject *) op;
}
Expand Down Expand Up @@ -1805,7 +1805,7 @@ bytes_buffer_getbuffer(PyObject *op, Py_buffer *view, int flags)
static PySequenceMethods bytes_as_sequence = {
bytes_length, /*sq_length*/
_PyBytes_Concat, /*sq_concat*/
bytes_repeat, /*sq_repeat*/
_PyBytes_Repeat, /*sq_repeat*/
bytes_item, /*sq_item*/
0, /*sq_slice*/
0, /*sq_ass_item*/
Expand Down Expand Up @@ -3555,7 +3555,7 @@ bytes_iter(PyObject *seq)


void
_PyBytes_Repeat(char* dest, Py_ssize_t len_dest,
_PyBytes_RepeatBuffer(char* dest, Py_ssize_t len_dest,
const char* src, Py_ssize_t len_src)
{
if (len_dest == 0) {
Expand Down
6 changes: 3 additions & 3 deletions Objects/tupleobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -594,8 +594,8 @@ _PyTuple_Concat(PyObject *aa, PyObject *bb)
return (PyObject *)np;
}

static PyObject *
tuple_repeat(PyObject *self, Py_ssize_t n)
PyObject *
_PyTuple_Repeat(PyObject *self, Py_ssize_t n)
{
PyTupleObject *a = _PyTuple_CAST(self);
const Py_ssize_t input_size = Py_SIZE(a);
Expand Down Expand Up @@ -865,7 +865,7 @@ tuple_subtype_new(PyTypeObject *type, PyObject *iterable)
static PySequenceMethods tuple_as_sequence = {
tuple_length, /* sq_length */
_PyTuple_Concat, /* sq_concat */
tuple_repeat, /* sq_repeat */
_PyTuple_Repeat, /* sq_repeat */
tuple_item, /* sq_item */
0, /* sq_slice */
0, /* sq_ass_item */
Expand Down
10 changes: 5 additions & 5 deletions Objects/unicodeobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include "Python.h"
#include "pycore_abstract.h" // _PyIndex_Check()
#include "pycore_bytes_methods.h" // _Py_bytes_lower()
#include "pycore_bytesobject.h" // _PyBytes_Repeat()
#include "pycore_bytesobject.h" // _PyBytes_RepeatBuffer()
#include "pycore_ceval.h" // _PyEval_GetBuiltin()
#include "pycore_codecs.h" // _PyCodec_Lookup()
#include "pycore_critical_section.h" // Py_*_CRITICAL_SECTION_SEQUENCE_FAST
Expand Down Expand Up @@ -12502,8 +12502,8 @@ unicode_rstrip_impl(PyObject *self, PyObject *chars)
}


static PyObject*
unicode_repeat(PyObject *str, Py_ssize_t len)
PyObject *
_PyUnicode_Repeat(PyObject *str, Py_ssize_t len)
{
PyObject *u;
Py_ssize_t nchars, n;
Expand Down Expand Up @@ -12548,7 +12548,7 @@ unicode_repeat(PyObject *str, Py_ssize_t len)
else {
Py_ssize_t char_size = PyUnicode_KIND(str);
char *to = (char *) PyUnicode_DATA(u);
_PyBytes_Repeat(to, nchars * char_size, PyUnicode_DATA(str),
_PyBytes_RepeatBuffer(to, nchars * char_size, PyUnicode_DATA(str),
PyUnicode_GET_LENGTH(str) * char_size);
}

Expand Down Expand Up @@ -13734,7 +13734,7 @@ static PyNumberMethods unicode_as_number = {
static PySequenceMethods unicode_as_sequence = {
unicode_length, /* sq_length */
PyUnicode_Concat, /* sq_concat */
unicode_repeat, /* sq_repeat */
_PyUnicode_Repeat, /* sq_repeat */
unicode_getitem, /* sq_item */
0, /* sq_slice */
0, /* sq_ass_item */
Expand Down
11 changes: 10 additions & 1 deletion Python/optimizer_bytecodes.c
Original file line number Diff line number Diff line change
Expand Up @@ -2043,7 +2043,16 @@ dummy_func(void) {
PyObject *name = _Py_SpecialMethods[oparg].name;
PyObject *descr = _PyType_Lookup(type, name);
if (descr != NULL && (Py_TYPE(descr)->tp_flags & Py_TPFLAGS_METHOD_DESCRIPTOR)) {
ADD_OP(_GUARD_TYPE_VERSION, 0, type->tp_version_tag);
/* LOAD_SPECIAL expands to _RECORD_TOS_TYPE + _INSERT_NULL +
* _LOAD_SPECIAL. Insert _GUARD_TYPE_VERSION before the
* already-emitted _INSERT_NULL so deopt sees the original
* stack shape.*/
_PyUOpInstruction *insert_null = uop_buffer_last(&ctx->out_buffer);
assert(insert_null->opcode == _INSERT_NULL);
assert(insert_null->target == this_instr->target);
REPLACE_OP(insert_null, _GUARD_TYPE_VERSION, 0, type->tp_version_tag);
ADD_OP(_INSERT_NULL, 0, 0);

bool immortal = _Py_IsImmortal(descr) || (type->tp_flags & Py_TPFLAGS_IMMUTABLETYPE);
ADD_OP(immortal ? _LOAD_CONST_INLINE_BORROW : _LOAD_CONST_INLINE,
0, (uintptr_t)descr);
Expand Down
6 changes: 5 additions & 1 deletion Python/optimizer_cases.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading