Merge remote-tracking branch 'origin/main' into HEAD

This commit is contained in:
Dino Viehland 2025-11-03 10:10:28 -08:00
commit 8d57aca95a
1284 changed files with 27792 additions and 11927 deletions

View file

@ -1469,14 +1469,14 @@ bytearray_removesuffix_impl(PyByteArrayObject *self, Py_buffer *suffix)
/*[clinic input]
bytearray.resize
size: Py_ssize_t
New size to resize to..
New size to resize to.
/
Resize the internal buffer of bytearray to len.
[clinic start generated code]*/
static PyObject *
bytearray_resize_impl(PyByteArrayObject *self, Py_ssize_t size)
/*[clinic end generated code: output=f73524922990b2d9 input=75fd4d17c4aa47d3]*/
/*[clinic end generated code: output=f73524922990b2d9 input=6c9a260ca7f72071]*/
{
Py_ssize_t start_size = PyByteArray_GET_SIZE(self);
int result = PyByteArray_Resize((PyObject *)self, size);

View file

@ -3171,7 +3171,7 @@ PyBytes_Concat(PyObject **pv, PyObject *w)
return;
}
if (Py_REFCNT(*pv) == 1 && PyBytes_CheckExact(*pv)) {
if (_PyObject_IsUniquelyReferenced(*pv) && PyBytes_CheckExact(*pv)) {
/* Only one reference, so we can resize in place */
Py_ssize_t oldsize;
Py_buffer wb;
@ -3256,7 +3256,7 @@ _PyBytes_Resize(PyObject **pv, Py_ssize_t newsize)
Py_DECREF(v);
return 0;
}
if (Py_REFCNT(v) != 1) {
if (!_PyObject_IsUniquelyReferenced(v)) {
if (oldsize < newsize) {
*pv = _PyBytes_FromSize(newsize, 0);
if (*pv) {

View file

@ -213,7 +213,7 @@ _PyObject_MakeTpCall(PyThreadState *tstate, PyObject *callable,
return NULL;
}
PyObject *argstuple = _PyTuple_FromArray(args, nargs);
PyObject *argstuple = PyTuple_FromArray(args, nargs);
if (argstuple == NULL) {
return NULL;
}

View file

@ -599,7 +599,7 @@ PyDoc_STRVAR(bytearray_resize__doc__,
"Resize the internal buffer of bytearray to len.\n"
"\n"
" size\n"
" New size to resize to..");
" New size to resize to.");
#define BYTEARRAY_RESIZE_METHODDEF \
{"resize", (PyCFunction)bytearray_resize, METH_O, bytearray_resize__doc__},
@ -1796,4 +1796,4 @@ bytearray_sizeof(PyObject *self, PyObject *Py_UNUSED(ignored))
{
return bytearray_sizeof_impl((PyByteArrayObject *)self);
}
/*[clinic end generated code: output=be6d28193bc96a2c input=a9049054013a1b77]*/
/*[clinic end generated code: output=fdfe41139c91e409 input=a9049054013a1b77]*/

View file

@ -6,6 +6,7 @@ preserve
# include "pycore_gc.h" // PyGC_Head
# include "pycore_runtime.h" // _Py_ID()
#endif
#include "pycore_critical_section.h"// Py_BEGIN_CRITICAL_SECTION()
#include "pycore_modsupport.h" // _PyArg_UnpackKeywords()
PyDoc_STRVAR(OrderedDict_fromkeys__doc__,
@ -73,6 +74,53 @@ exit:
return return_value;
}
PyDoc_STRVAR(OrderedDict___sizeof____doc__,
"__sizeof__($self, /)\n"
"--\n"
"\n");
#define ORDEREDDICT___SIZEOF___METHODDEF \
{"__sizeof__", (PyCFunction)OrderedDict___sizeof__, METH_NOARGS, OrderedDict___sizeof____doc__},
static Py_ssize_t
OrderedDict___sizeof___impl(PyODictObject *self);
static PyObject *
OrderedDict___sizeof__(PyObject *self, PyObject *Py_UNUSED(ignored))
{
PyObject *return_value = NULL;
Py_ssize_t _return_value;
Py_BEGIN_CRITICAL_SECTION(self);
_return_value = OrderedDict___sizeof___impl((PyODictObject *)self);
Py_END_CRITICAL_SECTION();
if ((_return_value == -1) && PyErr_Occurred()) {
goto exit;
}
return_value = PyLong_FromSsize_t(_return_value);
exit:
return return_value;
}
PyDoc_STRVAR(OrderedDict___reduce____doc__,
"__reduce__($self, /)\n"
"--\n"
"\n"
"Return state information for pickling");
#define ORDEREDDICT___REDUCE___METHODDEF \
{"__reduce__", (PyCFunction)OrderedDict___reduce__, METH_NOARGS, OrderedDict___reduce____doc__},
static PyObject *
OrderedDict___reduce___impl(PyODictObject *od);
static PyObject *
OrderedDict___reduce__(PyObject *od, PyObject *Py_UNUSED(ignored))
{
return OrderedDict___reduce___impl((PyODictObject *)od);
}
PyDoc_STRVAR(OrderedDict_setdefault__doc__,
"setdefault($self, /, key, default=None)\n"
"--\n"
@ -135,7 +183,9 @@ OrderedDict_setdefault(PyObject *self, PyObject *const *args, Py_ssize_t nargs,
}
default_value = args[1];
skip_optional_pos:
Py_BEGIN_CRITICAL_SECTION(self);
return_value = OrderedDict_setdefault_impl((PyODictObject *)self, key, default_value);
Py_END_CRITICAL_SECTION();
exit:
return return_value;
@ -204,7 +254,9 @@ OrderedDict_pop(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObjec
}
default_value = args[1];
skip_optional_pos:
Py_BEGIN_CRITICAL_SECTION(self);
return_value = OrderedDict_pop_impl((PyODictObject *)self, key, default_value);
Py_END_CRITICAL_SECTION();
exit:
return return_value;
@ -272,12 +324,62 @@ OrderedDict_popitem(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyO
goto exit;
}
skip_optional_pos:
Py_BEGIN_CRITICAL_SECTION(self);
return_value = OrderedDict_popitem_impl((PyODictObject *)self, last);
Py_END_CRITICAL_SECTION();
exit:
return return_value;
}
PyDoc_STRVAR(OrderedDict_clear__doc__,
"clear($self, /)\n"
"--\n"
"\n"
"Remove all items from ordered dict.");
#define ORDEREDDICT_CLEAR_METHODDEF \
{"clear", (PyCFunction)OrderedDict_clear, METH_NOARGS, OrderedDict_clear__doc__},
static PyObject *
OrderedDict_clear_impl(PyODictObject *self);
static PyObject *
OrderedDict_clear(PyObject *self, PyObject *Py_UNUSED(ignored))
{
PyObject *return_value = NULL;
Py_BEGIN_CRITICAL_SECTION(self);
return_value = OrderedDict_clear_impl((PyODictObject *)self);
Py_END_CRITICAL_SECTION();
return return_value;
}
PyDoc_STRVAR(OrderedDict_copy__doc__,
"copy($self, /)\n"
"--\n"
"\n"
"A shallow copy of ordered dict.");
#define ORDEREDDICT_COPY_METHODDEF \
{"copy", (PyCFunction)OrderedDict_copy, METH_NOARGS, OrderedDict_copy__doc__},
static PyObject *
OrderedDict_copy_impl(PyObject *od);
static PyObject *
OrderedDict_copy(PyObject *od, PyObject *Py_UNUSED(ignored))
{
PyObject *return_value = NULL;
Py_BEGIN_CRITICAL_SECTION(od);
return_value = OrderedDict_copy_impl(od);
Py_END_CRITICAL_SECTION();
return return_value;
}
PyDoc_STRVAR(OrderedDict_move_to_end__doc__,
"move_to_end($self, /, key, last=True)\n"
"--\n"
@ -342,9 +444,11 @@ OrderedDict_move_to_end(PyObject *self, PyObject *const *args, Py_ssize_t nargs,
goto exit;
}
skip_optional_pos:
Py_BEGIN_CRITICAL_SECTION(self);
return_value = OrderedDict_move_to_end_impl((PyODictObject *)self, key, last);
Py_END_CRITICAL_SECTION();
exit:
return return_value;
}
/*[clinic end generated code: output=7d8206823bb1f419 input=a9049054013a1b77]*/
/*[clinic end generated code: output=7bc997ca7900f06f input=a9049054013a1b77]*/

View file

@ -688,14 +688,14 @@ typealias_reduce(PyObject *self, PyObject *Py_UNUSED(ignored))
}
PyDoc_STRVAR(typealias_new__doc__,
"typealias(name, value, *, type_params=<unrepresentable>)\n"
"typealias(name, value, *, type_params=<unrepresentable>, qualname=None)\n"
"--\n"
"\n"
"Create a TypeAliasType.");
static PyObject *
typealias_new_impl(PyTypeObject *type, PyObject *name, PyObject *value,
PyObject *type_params);
PyObject *type_params, PyObject *qualname);
static PyObject *
typealias_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
@ -703,7 +703,7 @@ typealias_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
PyObject *return_value = NULL;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
#define NUM_KEYWORDS 3
#define NUM_KEYWORDS 4
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
@ -712,7 +712,7 @@ typealias_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
.ob_hash = -1,
.ob_item = { &_Py_ID(name), &_Py_ID(value), &_Py_ID(type_params), },
.ob_item = { &_Py_ID(name), &_Py_ID(value), &_Py_ID(type_params), &_Py_ID(qualname), },
};
#undef NUM_KEYWORDS
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
@ -721,20 +721,21 @@ typealias_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
# define KWTUPLE NULL
#endif // !Py_BUILD_CORE
static const char * const _keywords[] = {"name", "value", "type_params", NULL};
static const char * const _keywords[] = {"name", "value", "type_params", "qualname", NULL};
static _PyArg_Parser _parser = {
.keywords = _keywords,
.fname = "typealias",
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
PyObject *argsbuf[3];
PyObject *argsbuf[4];
PyObject * const *fastargs;
Py_ssize_t nargs = PyTuple_GET_SIZE(args);
Py_ssize_t noptargs = nargs + (kwargs ? PyDict_GET_SIZE(kwargs) : 0) - 2;
PyObject *name;
PyObject *value;
PyObject *type_params = NULL;
PyObject *qualname = NULL;
fastargs = _PyArg_UnpackKeywords(_PyTuple_CAST(args)->ob_item, nargs, kwargs, NULL, &_parser,
/*minpos*/ 2, /*maxpos*/ 2, /*minkw*/ 0, /*varpos*/ 0, argsbuf);
@ -750,11 +751,17 @@ typealias_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
if (!noptargs) {
goto skip_optional_kwonly;
}
type_params = fastargs[2];
if (fastargs[2]) {
type_params = fastargs[2];
if (!--noptargs) {
goto skip_optional_kwonly;
}
}
qualname = fastargs[3];
skip_optional_kwonly:
return_value = typealias_new_impl(type, name, value, type_params);
return_value = typealias_new_impl(type, name, value, type_params, qualname);
exit:
return return_value;
}
/*[clinic end generated code: output=9dad71445e079303 input=a9049054013a1b77]*/
/*[clinic end generated code: output=67ab9a5d1869f2c9 input=a9049054013a1b77]*/

View file

@ -313,7 +313,7 @@ method_vectorcall_VARARGS(
if (method_check_args(func, args, nargs, kwnames)) {
return NULL;
}
PyObject *argstuple = _PyTuple_FromArray(args+1, nargs-1);
PyObject *argstuple = PyTuple_FromArray(args+1, nargs-1);
if (argstuple == NULL) {
return NULL;
}
@ -338,7 +338,7 @@ method_vectorcall_VARARGS_KEYWORDS(
if (method_check_args(func, args, nargs, NULL)) {
return NULL;
}
PyObject *argstuple = _PyTuple_FromArray(args+1, nargs-1);
PyObject *argstuple = PyTuple_FromArray(args+1, nargs-1);
if (argstuple == NULL) {
return NULL;
}

View file

@ -1775,6 +1775,14 @@ static inline int
insert_combined_dict(PyInterpreterState *interp, PyDictObject *mp,
Py_hash_t hash, PyObject *key, PyObject *value)
{
// gh-140551: If dict was cleared in _Py_dict_lookup,
// we have to resize one more time to force general key kind.
if (DK_IS_UNICODE(mp->ma_keys) && !PyUnicode_CheckExact(key)) {
if (insertion_resize(mp, 0) < 0)
return -1;
assert(mp->ma_keys->dk_kind == DICT_KEYS_GENERAL);
}
if (mp->ma_keys->dk_usable <= 0) {
/* Need to resize. */
if (insertion_resize(mp, 1) < 0) {
@ -1871,38 +1879,31 @@ insertdict(PyInterpreterState *interp, PyDictObject *mp,
PyObject *key, Py_hash_t hash, PyObject *value)
{
PyObject *old_value;
Py_ssize_t ix;
ASSERT_DICT_LOCKED(mp);
if (DK_IS_UNICODE(mp->ma_keys) && !PyUnicode_CheckExact(key)) {
if (insertion_resize(mp, 0) < 0)
goto Fail;
assert(mp->ma_keys->dk_kind == DICT_KEYS_GENERAL);
}
if (_PyDict_HasSplitTable(mp)) {
Py_ssize_t ix = insert_split_key(mp->ma_keys, key, hash);
if (_PyDict_HasSplitTable(mp) && PyUnicode_CheckExact(key)) {
ix = insert_split_key(mp->ma_keys, key, hash);
if (ix != DKIX_EMPTY) {
insert_split_value(interp, mp, key, value, ix);
Py_DECREF(key);
Py_DECREF(value);
return 0;
}
/* No space in shared keys. Resize and continue below. */
if (insertion_resize(mp, 1) < 0) {
// No space in shared keys. Go to insert_combined_dict() below.
}
else {
ix = _Py_dict_lookup(mp, key, hash, &old_value);
if (ix == DKIX_ERROR)
goto Fail;
}
}
Py_ssize_t ix = _Py_dict_lookup(mp, key, hash, &old_value);
if (ix == DKIX_ERROR)
goto Fail;
if (ix == DKIX_EMPTY) {
assert(!_PyDict_HasSplitTable(mp));
/* Insert into new slot. */
assert(old_value == NULL);
// insert_combined_dict() will convert from non DICT_KEYS_GENERAL table
// into DICT_KEYS_GENERAL table if key is not Unicode.
// We don't convert it before _Py_dict_lookup because non-Unicode key
// may change generic table into Unicode table.
if (insert_combined_dict(interp, mp, hash, key, value) < 0) {
goto Fail;
}
@ -2819,8 +2820,8 @@ PyDict_DelItem(PyObject *op, PyObject *key)
return _PyDict_DelItem_KnownHash(op, key, hash);
}
static int
delitem_knownhash_lock_held(PyObject *op, PyObject *key, Py_hash_t hash)
int
_PyDict_DelItem_KnownHash_LockHeld(PyObject *op, PyObject *key, Py_hash_t hash)
{
Py_ssize_t ix;
PyDictObject *mp;
@ -2855,7 +2856,7 @@ _PyDict_DelItem_KnownHash(PyObject *op, PyObject *key, Py_hash_t hash)
{
int res;
Py_BEGIN_CRITICAL_SECTION(op);
res = delitem_knownhash_lock_held(op, key, hash);
res = _PyDict_DelItem_KnownHash_LockHeld(op, key, hash);
Py_END_CRITICAL_SECTION();
return res;
}
@ -4374,6 +4375,7 @@ dict_setdefault_ref_lock_held(PyObject *d, PyObject *key, PyObject *default_valu
PyDictObject *mp = (PyDictObject *)d;
PyObject *value;
Py_hash_t hash;
Py_ssize_t ix;
PyInterpreterState *interp = _PyInterpreterState_GET();
ASSERT_DICT_LOCKED(d);
@ -4409,17 +4411,8 @@ dict_setdefault_ref_lock_held(PyObject *d, PyObject *key, PyObject *default_valu
return 0;
}
if (!PyUnicode_CheckExact(key) && DK_IS_UNICODE(mp->ma_keys)) {
if (insertion_resize(mp, 0) < 0) {
if (result) {
*result = NULL;
}
return -1;
}
}
if (_PyDict_HasSplitTable(mp)) {
Py_ssize_t ix = insert_split_key(mp->ma_keys, key, hash);
if (_PyDict_HasSplitTable(mp) && PyUnicode_CheckExact(key)) {
ix = insert_split_key(mp->ma_keys, key, hash);
if (ix != DKIX_EMPTY) {
PyObject *value = mp->ma_values->values[ix];
int already_present = value != NULL;
@ -4432,27 +4425,22 @@ dict_setdefault_ref_lock_held(PyObject *d, PyObject *key, PyObject *default_valu
}
return already_present;
}
/* No space in shared keys. Resize and continue below. */
if (insertion_resize(mp, 1) < 0) {
goto error;
}
// No space in shared keys. Go to insert_combined_dict() below.
}
assert(!_PyDict_HasSplitTable(mp));
Py_ssize_t ix = _Py_dict_lookup(mp, key, hash, &value);
if (ix == DKIX_ERROR) {
if (result) {
*result = NULL;
else {
ix = _Py_dict_lookup(mp, key, hash, &value);
if (ix == DKIX_ERROR) {
if (result) {
*result = NULL;
}
return -1;
}
return -1;
}
if (ix == DKIX_EMPTY) {
assert(!_PyDict_HasSplitTable(mp));
value = default_value;
// See comment to this function in insertdict.
if (insert_combined_dict(interp, mp, hash, Py_NewRef(key), Py_NewRef(value)) < 0) {
Py_DECREF(key);
Py_DECREF(value);
@ -4477,12 +4465,6 @@ dict_setdefault_ref_lock_held(PyObject *d, PyObject *key, PyObject *default_valu
*result = incref_result ? Py_NewRef(value) : value;
}
return 1;
error:
if (result) {
*result = NULL;
}
return -1;
}
int
@ -4703,9 +4685,11 @@ dict_tp_clear(PyObject *op)
static PyObject *dictiter_new(PyDictObject *, PyTypeObject *);
static Py_ssize_t
sizeof_lock_held(PyDictObject *mp)
Py_ssize_t
_PyDict_SizeOf_LockHeld(PyDictObject *mp)
{
_Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(mp);
size_t res = _PyObject_SIZE(Py_TYPE(mp));
if (_PyDict_HasSplitTable(mp)) {
res += shared_keys_usable_size(mp->ma_keys) * sizeof(PyObject*);
@ -4732,7 +4716,7 @@ _PyDict_SizeOf(PyDictObject *mp)
{
Py_ssize_t res;
Py_BEGIN_CRITICAL_SECTION(mp);
res = sizeof_lock_held(mp);
res = _PyDict_SizeOf_LockHeld(mp);
Py_END_CRITICAL_SECTION();
return res;
@ -5673,22 +5657,10 @@ dictiter_iternext_threadsafe(PyDictObject *d, PyObject *self,
#endif
static bool
has_unique_reference(PyObject *op)
{
#ifdef Py_GIL_DISABLED
return (_Py_IsOwnedByCurrentThread(op) &&
op->ob_ref_local == 1 &&
_Py_atomic_load_ssize_relaxed(&op->ob_ref_shared) == 0);
#else
return Py_REFCNT(op) == 1;
#endif
}
static bool
acquire_iter_result(PyObject *result)
{
if (has_unique_reference(result)) {
if (_PyObject_IsUniquelyReferenced(result)) {
Py_INCREF(result);
return true;
}
@ -5725,8 +5697,11 @@ dictiter_iternextitem(PyObject *self)
}
else {
result = PyTuple_New(2);
if (result == NULL)
if (result == NULL) {
Py_DECREF(key);
Py_DECREF(value);
return NULL;
}
PyTuple_SET_ITEM(result, 0, key);
PyTuple_SET_ITEM(result, 1, value);
}
@ -5834,7 +5809,7 @@ dictreviter_iter_lock_held(PyDictObject *d, PyObject *self)
}
else if (Py_IS_TYPE(di, &PyDictRevIterItem_Type)) {
result = di->di_result;
if (Py_REFCNT(result) == 1) {
if (_PyObject_IsUniquelyReferenced(result)) {
PyObject *oldkey = PyTuple_GET_ITEM(result, 0);
PyObject *oldvalue = PyTuple_GET_ITEM(result, 1);
PyTuple_SET_ITEM(result, 0, Py_NewRef(key));
@ -6917,7 +6892,7 @@ _PyDict_SetItem_LockHeld(PyDictObject *dict, PyObject *name, PyObject *value)
dict_unhashable_type(name);
return -1;
}
return delitem_knownhash_lock_held((PyObject *)dict, name, hash);
return _PyDict_DelItem_KnownHash_LockHeld((PyObject *)dict, name, hash);
} else {
return setitem_lock_held(dict, name, value);
}

View file

@ -13,7 +13,6 @@
#include "pycore_modsupport.h" // _PyArg_NoKeywords()
#include "pycore_object.h"
#include "pycore_pyerrors.h" // struct _PyErr_SetRaisedException
#include "pycore_tuple.h" // _PyTuple_FromArray()
#include "osdefs.h" // SEP
#include "clinic/exceptions.c.h"
@ -119,7 +118,7 @@ BaseException_vectorcall(PyObject *type_obj, PyObject * const*args,
self->context = NULL;
self->suppress_context = 0;
self->args = _PyTuple_FromArray(args, PyVectorcall_NARGS(nargsf));
self->args = PyTuple_FromArray(args, PyVectorcall_NARGS(nargsf));
if (!self->args) {
Py_DECREF(self);
return NULL;

View file

@ -62,6 +62,7 @@ handle_func_event(PyFunction_WatchEvent event, PyFunctionObject *func,
case PyFunction_EVENT_MODIFY_CODE:
case PyFunction_EVENT_MODIFY_DEFAULTS:
case PyFunction_EVENT_MODIFY_KWDEFAULTS:
case PyFunction_EVENT_MODIFY_QUALNAME:
RARE_EVENT_INTERP_INC(interp, func_modification);
break;
default:
@ -747,6 +748,7 @@ func_set_qualname(PyObject *self, PyObject *value, void *Py_UNUSED(ignored))
"__qualname__ must be set to a string object");
return -1;
}
handle_func_event(PyFunction_EVENT_MODIFY_QUALNAME, (PyFunctionObject *) op, value);
Py_XSETREF(op->func_qualname, Py_NewRef(value));
return 0;
}

View file

@ -407,11 +407,12 @@ gen_close(PyObject *self, PyObject *args)
}
_PyInterpreterFrame *frame = &gen->gi_iframe;
if (is_resume(frame->instr_ptr)) {
bool no_unwind_tools = _PyEval_NoToolsForUnwind(_PyThreadState_GET());
/* We can safely ignore the outermost try block
* as it is automatically generated to handle
* StopIteration. */
int oparg = frame->instr_ptr->op.arg;
if (oparg & RESUME_OPARG_DEPTH1_MASK) {
if (oparg & RESUME_OPARG_DEPTH1_MASK && no_unwind_tools) {
// RESUME after YIELD_VALUE and exception depth is 1
assert((oparg & RESUME_OPARG_LOCATION_MASK) != RESUME_AT_FUNC_START);
gen->gi_frame_state = FRAME_COMPLETED;
@ -932,6 +933,7 @@ make_gen(PyTypeObject *type, PyFunctionObject *func)
gen->gi_weakreflist = NULL;
gen->gi_exc_state.exc_value = NULL;
gen->gi_exc_state.previous_item = NULL;
gen->gi_iframe.f_executable = PyStackRef_None;
assert(func->func_name != NULL);
gen->gi_name = Py_NewRef(func->func_name);
assert(func->func_qualname != NULL);

View file

@ -6,16 +6,16 @@
#include "pycore_critical_section.h" // _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED()
#include "pycore_dict.h" // _PyDictViewObject
#include "pycore_freelist.h" // _Py_FREELIST_FREE(), _Py_FREELIST_POP()
#include "pycore_pyatomic_ft_wrappers.h"
#include "pycore_interp.h" // PyInterpreterState.list
#include "pycore_list.h" // struct _Py_list_freelist, _PyListIterObject
#include "pycore_long.h" // _PyLong_DigitCount
#include "pycore_modsupport.h" // _PyArg_NoKwnames()
#include "pycore_object.h" // _PyObject_GC_TRACK(), _PyDebugAllocatorStats()
#include "pycore_stackref.h" // _Py_TryIncrefCompareStackRef()
#include "pycore_tuple.h" // _PyTuple_FromArray()
#include "pycore_typeobject.h" // _Py_TYPE_VERSION_LIST
#include "pycore_pyatomic_ft_wrappers.h"
#include "pycore_setobject.h" // _PySet_NextEntry()
#include "pycore_stackref.h" // _Py_TryIncrefCompareStackRef()
#include "pycore_tuple.h" // _PyTuple_FromArraySteal()
#include "pycore_typeobject.h" // _Py_TYPE_VERSION_LIST
#include <stddef.h>
/*[clinic input]
@ -1382,9 +1382,9 @@ list_extend_dictitems(PyListObject *self, PyDictObject *dict)
PyObject **dest = self->ob_item + m;
Py_ssize_t pos = 0;
Py_ssize_t i = 0;
PyObject *key, *value;
while (_PyDict_Next((PyObject *)dict, &pos, &key, &value, NULL)) {
PyObject *item = PyTuple_Pack(2, key, value);
PyObject *key_value[2];
while (_PyDict_Next((PyObject *)dict, &pos, &key_value[0], &key_value[1], NULL)) {
PyObject *item = PyTuple_FromArray(key_value, 2);
if (item == NULL) {
Py_SET_SIZE(self, m + i);
return -1;
@ -3221,7 +3221,7 @@ PyList_AsTuple(PyObject *v)
PyObject *ret;
PyListObject *self = (PyListObject *)v;
Py_BEGIN_CRITICAL_SECTION(self);
ret = _PyTuple_FromArray(self->ob_item, Py_SIZE(v));
ret = PyTuple_FromArray(self->ob_item, Py_SIZE(v));
Py_END_CRITICAL_SECTION();
return ret;
}

View file

@ -352,7 +352,7 @@ _PyLong_Negate(PyLongObject **x_p)
PyLongObject *x;
x = (PyLongObject *)*x_p;
if (Py_REFCNT(x) == 1) {
if (_PyObject_IsUniquelyReferenced((PyObject *)x)) {
_PyLong_FlipSign(x);
return;
}
@ -5849,7 +5849,7 @@ _PyLong_GCD(PyObject *aarg, PyObject *barg)
assert(size_a >= 0);
_PyLong_SetSignAndDigitCount(c, 1, size_a);
}
else if (Py_REFCNT(a) == 1) {
else if (_PyObject_IsUniquelyReferenced((PyObject *)a)) {
c = (PyLongObject*)Py_NewRef(a);
}
else {
@ -5863,7 +5863,8 @@ _PyLong_GCD(PyObject *aarg, PyObject *barg)
assert(size_a >= 0);
_PyLong_SetSignAndDigitCount(d, 1, size_a);
}
else if (Py_REFCNT(b) == 1 && size_a <= alloc_b) {
else if (_PyObject_IsUniquelyReferenced((PyObject *)b)
&& size_a <= alloc_b) {
d = (PyLongObject*)Py_NewRef(b);
assert(size_a >= 0);
_PyLong_SetSignAndDigitCount(d, 1, size_a);

View file

@ -536,6 +536,7 @@ struct _odictnode {
static Py_ssize_t
_odict_get_index_raw(PyODictObject *od, PyObject *key, Py_hash_t hash)
{
_Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
PyObject *value = NULL;
PyDictKeysObject *keys = ((PyDictObject *)od)->ma_keys;
Py_ssize_t ix;
@ -560,6 +561,7 @@ _odict_get_index_raw(PyODictObject *od, PyObject *key, Py_hash_t hash)
static int
_odict_resize(PyODictObject *od)
{
_Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
Py_ssize_t size, i;
_ODictNode **fast_nodes, *node;
@ -596,6 +598,7 @@ _odict_resize(PyODictObject *od)
static Py_ssize_t
_odict_get_index(PyODictObject *od, PyObject *key, Py_hash_t hash)
{
_Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
PyDictKeysObject *keys;
assert(key != NULL);
@ -616,6 +619,7 @@ _odict_get_index(PyODictObject *od, PyObject *key, Py_hash_t hash)
static _ODictNode *
_odict_find_node_hash(PyODictObject *od, PyObject *key, Py_hash_t hash)
{
_Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
Py_ssize_t index;
if (_odict_EMPTY(od))
@ -630,6 +634,7 @@ _odict_find_node_hash(PyODictObject *od, PyObject *key, Py_hash_t hash)
static _ODictNode *
_odict_find_node(PyODictObject *od, PyObject *key)
{
_Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
Py_ssize_t index;
Py_hash_t hash;
@ -648,6 +653,7 @@ _odict_find_node(PyODictObject *od, PyObject *key)
static void
_odict_add_head(PyODictObject *od, _ODictNode *node)
{
_Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
_odictnode_PREV(node) = NULL;
_odictnode_NEXT(node) = _odict_FIRST(od);
if (_odict_FIRST(od) == NULL)
@ -661,6 +667,7 @@ _odict_add_head(PyODictObject *od, _ODictNode *node)
static void
_odict_add_tail(PyODictObject *od, _ODictNode *node)
{
_Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
_odictnode_PREV(node) = _odict_LAST(od);
_odictnode_NEXT(node) = NULL;
if (_odict_LAST(od) == NULL)
@ -675,6 +682,7 @@ _odict_add_tail(PyODictObject *od, _ODictNode *node)
static int
_odict_add_new_node(PyODictObject *od, PyObject *key, Py_hash_t hash)
{
_Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
Py_ssize_t i;
_ODictNode *node;
@ -719,6 +727,7 @@ _odict_add_new_node(PyODictObject *od, PyObject *key, Py_hash_t hash)
static void
_odict_remove_node(PyODictObject *od, _ODictNode *node)
{
_Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
if (_odict_FIRST(od) == node)
_odict_FIRST(od) = _odictnode_NEXT(node);
else if (_odictnode_PREV(node) != NULL)
@ -754,6 +763,7 @@ static int
_odict_clear_node(PyODictObject *od, _ODictNode *node, PyObject *key,
Py_hash_t hash)
{
_Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
Py_ssize_t i;
assert(key != NULL);
@ -952,31 +962,34 @@ OrderedDict_fromkeys_impl(PyTypeObject *type, PyObject *seq, PyObject *value)
return _PyDict_FromKeys((PyObject *)type, seq, value);
}
/* __sizeof__() */
/*[clinic input]
@critical_section
OrderedDict.__sizeof__ -> Py_ssize_t
[clinic start generated code]*/
/* OrderedDict.__sizeof__() does not have a docstring. */
PyDoc_STRVAR(odict_sizeof__doc__, "");
static PyObject *
odict_sizeof(PyObject *op, PyObject *Py_UNUSED(ignored))
static Py_ssize_t
OrderedDict___sizeof___impl(PyODictObject *self)
/*[clinic end generated code: output=1a8560db8cf83ac5 input=655e989ae24daa6a]*/
{
PyODictObject *od = _PyODictObject_CAST(op);
Py_ssize_t res = _PyDict_SizeOf((PyDictObject *)od);
res += sizeof(_ODictNode *) * od->od_fast_nodes_size; /* od_fast_nodes */
if (!_odict_EMPTY(od)) {
res += sizeof(_ODictNode) * PyODict_SIZE(od); /* linked-list */
Py_ssize_t res = _PyDict_SizeOf_LockHeld((PyDictObject *)self);
res += sizeof(_ODictNode *) * self->od_fast_nodes_size; /* od_fast_nodes */
if (!_odict_EMPTY(self)) {
res += sizeof(_ODictNode) * PyODict_SIZE(self); /* linked-list */
}
return PyLong_FromSsize_t(res);
return res;
}
/* __reduce__() */
/*[clinic input]
OrderedDict.__reduce__
self as od: self(type="PyODictObject *")
PyDoc_STRVAR(odict_reduce__doc__, "Return state information for pickling");
Return state information for pickling
[clinic start generated code]*/
static PyObject *
odict_reduce(PyObject *op, PyObject *Py_UNUSED(ignored))
OrderedDict___reduce___impl(PyODictObject *od)
/*[clinic end generated code: output=71eeb81f760a6a8e input=b0467c7ec400fe5e]*/
{
register PyODictObject *od = _PyODictObject_CAST(op);
PyObject *state, *result = NULL;
PyObject *items_iter, *items, *args = NULL;
@ -1011,8 +1024,10 @@ odict_reduce(PyObject *op, PyObject *Py_UNUSED(ignored))
/* setdefault(): Skips __missing__() calls. */
static int PyODict_SetItem_LockHeld(PyObject *self, PyObject *key, PyObject *value);
/*[clinic input]
@critical_section
OrderedDict.setdefault
key: object
@ -1026,7 +1041,7 @@ Return the value for key if key is in the dictionary, else default.
static PyObject *
OrderedDict_setdefault_impl(PyODictObject *self, PyObject *key,
PyObject *default_value)
/*[clinic end generated code: output=97537cb7c28464b6 input=38e098381c1efbc6]*/
/*[clinic end generated code: output=97537cb7c28464b6 input=d7b93e92734f99b5]*/
{
PyObject *result = NULL;
@ -1036,7 +1051,7 @@ OrderedDict_setdefault_impl(PyODictObject *self, PyObject *key,
if (PyErr_Occurred())
return NULL;
assert(_odict_find_node(self, key) == NULL);
if (PyODict_SetItem((PyObject *)self, key, default_value) >= 0) {
if (PyODict_SetItem_LockHeld((PyObject *)self, key, default_value) >= 0) {
result = Py_NewRef(default_value);
}
}
@ -1066,10 +1081,9 @@ static PyObject *
_odict_popkey_hash(PyObject *od, PyObject *key, PyObject *failobj,
Py_hash_t hash)
{
_Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
PyObject *value = NULL;
Py_BEGIN_CRITICAL_SECTION(od);
_ODictNode *node = _odict_find_node_hash(_PyODictObject_CAST(od), key, hash);
if (node != NULL) {
/* Pop the node first to avoid a possible dict resize (due to
@ -1094,7 +1108,6 @@ _odict_popkey_hash(PyObject *od, PyObject *key, PyObject *failobj,
PyErr_SetObject(PyExc_KeyError, key);
}
}
Py_END_CRITICAL_SECTION();
done:
return value;
@ -1102,6 +1115,7 @@ _odict_popkey_hash(PyObject *od, PyObject *key, PyObject *failobj,
/* Skips __missing__() calls. */
/*[clinic input]
@critical_section
@permit_long_summary
OrderedDict.pop
@ -1117,7 +1131,7 @@ raise a KeyError.
static PyObject *
OrderedDict_pop_impl(PyODictObject *self, PyObject *key,
PyObject *default_value)
/*[clinic end generated code: output=7a6447d104e7494b input=eebd40ac51666d33]*/
/*[clinic end generated code: output=7a6447d104e7494b input=0742e3c9bf076a72]*/
{
Py_hash_t hash = PyObject_Hash(key);
if (hash == -1)
@ -1129,6 +1143,7 @@ OrderedDict_pop_impl(PyODictObject *self, PyObject *key,
/* popitem() */
/*[clinic input]
@critical_section
OrderedDict.popitem
last: bool = True
@ -1140,7 +1155,7 @@ Pairs are returned in LIFO order if last is true or FIFO order if false.
static PyObject *
OrderedDict_popitem_impl(PyODictObject *self, int last)
/*[clinic end generated code: output=98e7d986690d49eb input=d992ac5ee8305e1a]*/
/*[clinic end generated code: output=98e7d986690d49eb input=8aafc7433e0a40e7]*/
{
PyObject *key, *value, *item = NULL;
_ODictNode *node;
@ -1169,6 +1184,9 @@ OrderedDict_popitem_impl(PyODictObject *self, int last)
PyDoc_STRVAR(odict_keys__doc__, "");
static PyObject * odictkeys_new(PyObject *od, PyObject *Py_UNUSED(ignored)); /* forward */
static int
_PyODict_SetItem_KnownHash_LockHeld(PyObject *od, PyObject *key, PyObject *value,
Py_hash_t hash); /* forward */
/* values() */
@ -1194,32 +1212,36 @@ static PyObject * mutablemapping_update(PyObject *, PyObject *, PyObject *);
#define odict_update mutablemapping_update
/* clear() */
/*[clinic input]
@critical_section
OrderedDict.clear
PyDoc_STRVAR(odict_clear__doc__,
"od.clear() -> None. Remove all items from od.");
Remove all items from ordered dict.
[clinic start generated code]*/
static PyObject *
odict_clear(PyObject *op, PyObject *Py_UNUSED(ignored))
OrderedDict_clear_impl(PyODictObject *self)
/*[clinic end generated code: output=a1a76d1322f556c5 input=08b12322e74c535c]*/
{
register PyODictObject *od = _PyODictObject_CAST(op);
PyDict_Clear(op);
_odict_clear_nodes(od);
_PyDict_Clear_LockHeld((PyObject *)self);
_odict_clear_nodes(self);
Py_RETURN_NONE;
}
/* copy() */
/* forward */
static int _PyODict_SetItem_KnownHash(PyObject *, PyObject *, PyObject *,
Py_hash_t);
/*[clinic input]
@critical_section
OrderedDict.copy
self as od: self
PyDoc_STRVAR(odict_copy__doc__, "od.copy() -> a shallow copy of od");
A shallow copy of ordered dict.
[clinic start generated code]*/
static PyObject *
odict_copy(PyObject *op, PyObject *Py_UNUSED(ignored))
OrderedDict_copy_impl(PyObject *od)
/*[clinic end generated code: output=9cdbe7394aecc576 input=e329951ae617ed48]*/
{
register PyODictObject *od = _PyODictObject_CAST(op);
_ODictNode *node;
PyObject *od_copy;
@ -1239,8 +1261,8 @@ odict_copy(PyObject *op, PyObject *Py_UNUSED(ignored))
PyErr_SetObject(PyExc_KeyError, key);
goto fail;
}
if (_PyODict_SetItem_KnownHash((PyObject *)od_copy, key, value,
_odictnode_HASH(node)) != 0)
if (_PyODict_SetItem_KnownHash_LockHeld((PyObject *)od_copy, key, value,
_odictnode_HASH(node)) != 0)
goto fail;
}
}
@ -1288,6 +1310,7 @@ odict_reversed(PyObject *op, PyObject *Py_UNUSED(ignored))
/* move_to_end() */
/*[clinic input]
@critical_section
OrderedDict.move_to_end
key: object
@ -1300,7 +1323,7 @@ Raise KeyError if the element does not exist.
static PyObject *
OrderedDict_move_to_end_impl(PyODictObject *self, PyObject *key, int last)
/*[clinic end generated code: output=fafa4c5cc9b92f20 input=d6ceff7132a2fcd7]*/
/*[clinic end generated code: output=fafa4c5cc9b92f20 input=09f8bc7053c0f6d4]*/
{
_ODictNode *node;
@ -1341,10 +1364,8 @@ static PyMethodDef odict_methods[] = {
/* overridden dict methods */
ORDEREDDICT_FROMKEYS_METHODDEF
{"__sizeof__", odict_sizeof, METH_NOARGS,
odict_sizeof__doc__},
{"__reduce__", odict_reduce, METH_NOARGS,
odict_reduce__doc__},
ORDEREDDICT___SIZEOF___METHODDEF
ORDEREDDICT___REDUCE___METHODDEF
ORDEREDDICT_SETDEFAULT_METHODDEF
ORDEREDDICT_POP_METHODDEF
ORDEREDDICT_POPITEM_METHODDEF
@ -1356,11 +1377,8 @@ static PyMethodDef odict_methods[] = {
odict_items__doc__},
{"update", _PyCFunction_CAST(odict_update), METH_VARARGS | METH_KEYWORDS,
odict_update__doc__},
{"clear", odict_clear, METH_NOARGS,
odict_clear__doc__},
{"copy", odict_copy, METH_NOARGS,
odict_copy__doc__},
ORDEREDDICT_CLEAR_METHODDEF
ORDEREDDICT_COPY_METHODDEF
/* new methods */
{"__reversed__", odict_reversed, METH_NOARGS,
odict_reversed__doc__},
@ -1459,7 +1477,8 @@ odict_tp_clear(PyObject *op)
{
PyODictObject *od = _PyODictObject_CAST(op);
Py_CLEAR(od->od_inst_dict);
PyDict_Clear((PyObject *)od);
// cannot use lock held variant as critical section is not held here
PyDict_Clear(op);
_odict_clear_nodes(od);
return 0;
}
@ -1467,7 +1486,7 @@ odict_tp_clear(PyObject *op)
/* tp_richcompare */
static PyObject *
odict_richcompare(PyObject *v, PyObject *w, int op)
odict_richcompare_lock_held(PyObject *v, PyObject *w, int op)
{
if (!PyODict_Check(v) || !PyDict_Check(w)) {
Py_RETURN_NOTIMPLEMENTED;
@ -1500,6 +1519,16 @@ odict_richcompare(PyObject *v, PyObject *w, int op)
}
}
static PyObject *
odict_richcompare(PyObject *v, PyObject *w, int op)
{
PyObject *res;
Py_BEGIN_CRITICAL_SECTION2(v, w);
res = odict_richcompare_lock_held(v, w, op);
Py_END_CRITICAL_SECTION2();
return res;
}
/* tp_iter */
static PyObject *
@ -1590,10 +1619,11 @@ PyODict_New(void)
}
static int
_PyODict_SetItem_KnownHash(PyObject *od, PyObject *key, PyObject *value,
Py_hash_t hash)
_PyODict_SetItem_KnownHash_LockHeld(PyObject *od, PyObject *key, PyObject *value,
Py_hash_t hash)
{
int res = _PyDict_SetItem_KnownHash(od, key, value, hash);
_Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
int res = _PyDict_SetItem_KnownHash_LockHeld((PyDictObject *)od, key, value, hash);
if (res == 0) {
res = _odict_add_new_node(_PyODictObject_CAST(od), key, hash);
if (res < 0) {
@ -1606,18 +1636,32 @@ _PyODict_SetItem_KnownHash(PyObject *od, PyObject *key, PyObject *value,
return res;
}
int
PyODict_SetItem(PyObject *od, PyObject *key, PyObject *value)
static int
PyODict_SetItem_LockHeld(PyObject *od, PyObject *key, PyObject *value)
{
_Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
Py_hash_t hash = PyObject_Hash(key);
if (hash == -1)
if (hash == -1) {
return -1;
return _PyODict_SetItem_KnownHash(od, key, value, hash);
}
return _PyODict_SetItem_KnownHash_LockHeld(od, key, value, hash);
}
int
PyODict_DelItem(PyObject *od, PyObject *key)
PyODict_SetItem(PyObject *od, PyObject *key, PyObject *value)
{
int res;
Py_BEGIN_CRITICAL_SECTION(od);
res = PyODict_SetItem_LockHeld(od, key, value);
Py_END_CRITICAL_SECTION();
return res;
}
int
PyODict_DelItem_LockHeld(PyObject *od, PyObject *key)
{
_Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
int res;
Py_hash_t hash = PyObject_Hash(key);
if (hash == -1)
@ -1625,9 +1669,18 @@ PyODict_DelItem(PyObject *od, PyObject *key)
res = _odict_clear_node(_PyODictObject_CAST(od), NULL, key, hash);
if (res < 0)
return -1;
return _PyDict_DelItem_KnownHash(od, key, hash);
return _PyDict_DelItem_KnownHash_LockHeld(od, key, hash);
}
int
PyODict_DelItem(PyObject *od, PyObject *key)
{
int res;
Py_BEGIN_CRITICAL_SECTION(od);
res = PyODict_DelItem_LockHeld(od, key);
Py_END_CRITICAL_SECTION();
return res;
}
/* -------------------------------------------
* The OrderedDict views (keys/values/items)
@ -1669,14 +1722,14 @@ odictiter_traverse(PyObject *op, visitproc visit, void *arg)
/* In order to protect against modifications during iteration, we track
* the current key instead of the current node. */
static PyObject *
odictiter_nextkey(odictiterobject *di)
odictiter_nextkey_lock_held(odictiterobject *di)
{
assert(di->di_odict != NULL);
_Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(di->di_odict);
PyObject *key = NULL;
_ODictNode *node;
int reversed = di->kind & _odict_ITER_REVERSED;
if (di->di_odict == NULL)
return NULL;
if (di->di_current == NULL)
goto done; /* We're already done. */
@ -1721,8 +1774,23 @@ odictiter_nextkey(odictiterobject *di)
return key;
}
static PyObject *
odictiter_iternext(PyObject *op)
odictiter_nextkey(odictiterobject *di)
{
_Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(di);
if (di->di_odict == NULL) {
return NULL;
}
PyObject *res;
Py_BEGIN_CRITICAL_SECTION(di->di_odict);
res = odictiter_nextkey_lock_held(di);
Py_END_CRITICAL_SECTION();
return res;
}
static PyObject *
odictiter_iternext_lock_held(PyObject *op)
{
odictiterobject *di = (odictiterobject*)op;
PyObject *result, *value;
@ -1736,14 +1804,12 @@ odictiter_iternext(PyObject *op)
return key;
}
value = PyODict_GetItem((PyObject *)di->di_odict, key); /* borrowed */
if (value == NULL) {
if (PyDict_GetItemRef((PyObject *)di->di_odict, key, &value) != 1) {
if (!PyErr_Occurred())
PyErr_SetObject(PyExc_KeyError, key);
Py_DECREF(key);
goto done;
}
Py_INCREF(value);
/* Handle the values case. */
if (!(di->kind & _odict_ITER_KEYS)) {
@ -1754,7 +1820,7 @@ odictiter_iternext(PyObject *op)
/* Handle the items case. */
result = di->di_result;
if (Py_REFCNT(result) == 1) {
if (_PyObject_IsUniquelyReferenced(result)) {
/* not in use so we can reuse it
* (the common case during iteration) */
Py_INCREF(result);
@ -1783,6 +1849,17 @@ odictiter_iternext(PyObject *op)
return NULL;
}
static PyObject *
odictiter_iternext(PyObject *op)
{
PyObject *res;
Py_BEGIN_CRITICAL_SECTION(op);
res = odictiter_iternext_lock_held(op);
Py_END_CRITICAL_SECTION();
return res;
}
/* No need for tp_clear because odictiterobject is not mutable. */
PyDoc_STRVAR(reduce_doc, "Return state information for pickling");

View file

@ -2444,7 +2444,7 @@ set_init(PyObject *so, PyObject *args, PyObject *kwds)
if (!PyArg_UnpackTuple(args, Py_TYPE(self)->tp_name, 0, 1, &iterable))
return -1;
if (Py_REFCNT(self) == 1 && self->fill == 0) {
if (_PyObject_IsUniquelyReferenced((PyObject *)self) && self->fill == 0) {
self->hash = -1;
if (iterable == NULL) {
return 0;
@ -2774,7 +2774,7 @@ int
PySet_Add(PyObject *anyset, PyObject *key)
{
if (!PySet_Check(anyset) &&
(!PyFrozenSet_Check(anyset) || Py_REFCNT(anyset) != 1)) {
(!PyFrozenSet_Check(anyset) || !_PyObject_IsUniquelyReferenced(anyset))) {
PyErr_BadInternalCall();
return -1;
}

View file

@ -1,97 +0,0 @@
/* _PyUnicode_InsertThousandsGrouping() helper functions */
typedef struct {
const char *grouping;
char previous;
Py_ssize_t i; /* Where we're currently pointing in grouping. */
} GroupGenerator;
static void
GroupGenerator_init(GroupGenerator *self, const char *grouping)
{
self->grouping = grouping;
self->i = 0;
self->previous = 0;
}
/* Returns the next grouping, or 0 to signify end. */
static Py_ssize_t
GroupGenerator_next(GroupGenerator *self)
{
/* Note that we don't really do much error checking here. If a
grouping string contains just CHAR_MAX, for example, then just
terminate the generator. That shouldn't happen, but at least we
fail gracefully. */
switch (self->grouping[self->i]) {
case 0:
return self->previous;
case CHAR_MAX:
/* Stop the generator. */
return 0;
default: {
char ch = self->grouping[self->i];
self->previous = ch;
self->i++;
return (Py_ssize_t)ch;
}
}
}
/* Fill in some digits, leading zeros, and thousands separator. All
are optional, depending on when we're called. */
static void
InsertThousandsGrouping_fill(_PyUnicodeWriter *writer, Py_ssize_t *buffer_pos,
PyObject *digits, Py_ssize_t *digits_pos,
Py_ssize_t n_chars, Py_ssize_t n_zeros,
PyObject *thousands_sep, Py_ssize_t thousands_sep_len,
Py_UCS4 *maxchar, int forward)
{
if (!writer) {
/* if maxchar > 127, maxchar is already set */
if (*maxchar == 127 && thousands_sep) {
Py_UCS4 maxchar2 = PyUnicode_MAX_CHAR_VALUE(thousands_sep);
*maxchar = Py_MAX(*maxchar, maxchar2);
}
return;
}
if (thousands_sep) {
if (!forward) {
*buffer_pos -= thousands_sep_len;
}
/* Copy the thousands_sep chars into the buffer. */
_PyUnicode_FastCopyCharacters(writer->buffer, *buffer_pos,
thousands_sep, 0,
thousands_sep_len);
if (forward) {
*buffer_pos += thousands_sep_len;
}
}
if (!forward) {
*buffer_pos -= n_chars;
*digits_pos -= n_chars;
}
_PyUnicode_FastCopyCharacters(writer->buffer, *buffer_pos,
digits, *digits_pos,
n_chars);
if (forward) {
*buffer_pos += n_chars;
*digits_pos += n_chars;
}
if (n_zeros) {
if (!forward) {
*buffer_pos -= n_zeros;
}
int kind = PyUnicode_KIND(writer->buffer);
void *data = PyUnicode_DATA(writer->buffer);
unicode_fill(kind, data, '0', *buffer_pos, n_zeros);
if (forward) {
*buffer_pos += n_zeros;
}
}
}

View file

@ -12,7 +12,7 @@
#include "pycore_modsupport.h" // _PyArg_NoPositional()
#include "pycore_object.h" // _PyObject_GC_TRACK()
#include "pycore_structseq.h" // PyStructSequence_InitType()
#include "pycore_tuple.h" // _PyTuple_FromArray()
#include "pycore_tuple.h" // _PyTuple_RESET_HASH_CACHE()
#include "pycore_typeobject.h" // _PyStaticType_FiniBuiltin()
static const char visible_length_key[] = "n_sequence_fields";
@ -353,7 +353,7 @@ structseq_reduce(PyObject *op, PyObject *Py_UNUSED(ignored))
if (n_unnamed_fields < 0) {
return NULL;
}
tup = _PyTuple_FromArray(self->ob_item, n_visible_fields);
tup = PyTuple_FromArray(self->ob_item, n_visible_fields);
if (!tup)
goto error;

View file

@ -118,7 +118,7 @@ int
PyTuple_SetItem(PyObject *op, Py_ssize_t i, PyObject *newitem)
{
PyObject **p;
if (!PyTuple_Check(op) || Py_REFCNT(op) != 1) {
if (!PyTuple_Check(op) || !_PyObject_IsUniquelyReferenced(op)) {
Py_XDECREF(newitem);
PyErr_BadInternalCall();
return -1;
@ -156,6 +156,18 @@ _PyTuple_MaybeUntrack(PyObject *op)
_PyObject_GC_UNTRACK(op);
}
/* Fast, but conservative check if an object maybe tracked
May return true for an object that is not tracked,
Will always return true for an object that is tracked.
This is a temporary workaround until _PyObject_GC_IS_TRACKED
becomes fast and safe to call on non-GC objects.
*/
static bool
maybe_tracked(PyObject *ob)
{
return _PyType_IS_GC(Py_TYPE(ob));
}
PyObject *
PyTuple_Pack(Py_ssize_t n, ...)
{
@ -163,6 +175,7 @@ PyTuple_Pack(Py_ssize_t n, ...)
PyObject *o;
PyObject **items;
va_list vargs;
bool track = false;
if (n == 0) {
return tuple_get_empty();
@ -177,10 +190,15 @@ PyTuple_Pack(Py_ssize_t n, ...)
items = result->ob_item;
for (i = 0; i < n; i++) {
o = va_arg(vargs, PyObject *);
if (!track && maybe_tracked(o)) {
track = true;
}
items[i] = Py_NewRef(o);
}
va_end(vargs);
_PyObject_GC_TRACK(result);
if (track) {
_PyObject_GC_TRACK(result);
}
return (PyObject *)result;
}
@ -366,7 +384,7 @@ tuple_item(PyObject *op, Py_ssize_t i)
}
PyObject *
_PyTuple_FromArray(PyObject *const *src, Py_ssize_t n)
PyTuple_FromArray(PyObject *const *src, Py_ssize_t n)
{
if (n == 0) {
return tuple_get_empty();
@ -377,11 +395,17 @@ _PyTuple_FromArray(PyObject *const *src, Py_ssize_t n)
return NULL;
}
PyObject **dst = tuple->ob_item;
bool track = false;
for (Py_ssize_t i = 0; i < n; i++) {
PyObject *item = src[i];
if (!track && maybe_tracked(item)) {
track = true;
}
dst[i] = Py_NewRef(item);
}
_PyObject_GC_TRACK(tuple);
if (track) {
_PyObject_GC_TRACK(tuple);
}
return (PyObject *)tuple;
}
@ -396,10 +420,17 @@ _PyTuple_FromStackRefStealOnSuccess(const _PyStackRef *src, Py_ssize_t n)
return NULL;
}
PyObject **dst = tuple->ob_item;
bool track = false;
for (Py_ssize_t i = 0; i < n; i++) {
dst[i] = PyStackRef_AsPyObjectSteal(src[i]);
PyObject *item = PyStackRef_AsPyObjectSteal(src[i]);
if (!track && maybe_tracked(item)) {
track = true;
}
dst[i] = item;
}
if (track) {
_PyObject_GC_TRACK(tuple);
}
_PyObject_GC_TRACK(tuple);
return (PyObject *)tuple;
}
@ -438,7 +469,7 @@ tuple_slice(PyTupleObject *a, Py_ssize_t ilow,
if (ilow == 0 && ihigh == Py_SIZE(a) && PyTuple_CheckExact(a)) {
return Py_NewRef(a);
}
return _PyTuple_FromArray(a->ob_item + ilow, ihigh - ilow);
return PyTuple_FromArray(a->ob_item + ilow, ihigh - ilow);
}
PyObject *
@ -923,7 +954,7 @@ _PyTuple_Resize(PyObject **pv, Py_ssize_t newsize)
v = (PyTupleObject *) *pv;
if (v == NULL || !Py_IS_TYPE(v, &PyTuple_Type) ||
(Py_SIZE(v) != 0 && Py_REFCNT(v) != 1)) {
(Py_SIZE(v) != 0 && !_PyObject_IsUniquelyReferenced(*pv))) {
*pv = 0;
Py_XDECREF(v);
PyErr_BadInternalCall();

View file

@ -72,7 +72,7 @@ class object "PyObject *" "&PyBaseObject_Type"
// the type has been revealed to other threads or we only do those updates
// while the stop-the-world mechanism is active. The slots and flags are read
// in many places without holding a lock and without atomics.
#define TYPE_LOCK &PyInterpreterState_Get()->types.mutex
#define TYPE_LOCK &_PyInterpreterState_GET()->types.mutex
#define BEGIN_TYPE_LOCK() Py_BEGIN_CRITICAL_SECTION_MUTEX(TYPE_LOCK)
#define END_TYPE_LOCK() Py_END_CRITICAL_SECTION()
@ -81,7 +81,7 @@ class object "PyObject *" "&PyBaseObject_Type"
#define END_TYPE_DICT_LOCK() Py_END_CRITICAL_SECTION2()
#ifdef Py_DEBUG
#ifndef NDEBUG
// Return true if the world is currently stopped.
static bool
types_world_is_stopped(void)
@ -1780,7 +1780,7 @@ static int recurse_down_subclasses(PyTypeObject *type, PyObject *name,
// Compute tp_mro for this type and all of its subclasses. This
// is called after __bases__ is assigned to an existing type.
static int
mro_hierarchy(PyTypeObject *type, PyObject *temp)
mro_hierarchy_for_complete_type(PyTypeObject *type, PyObject *temp)
{
ASSERT_TYPE_LOCK_HELD();
@ -1791,6 +1791,7 @@ mro_hierarchy(PyTypeObject *type, PyObject *temp)
return res;
}
PyObject *new_mro = lookup_tp_mro(type);
assert(new_mro != NULL);
PyObject *tuple;
if (old_mro != NULL) {
@ -1835,7 +1836,7 @@ mro_hierarchy(PyTypeObject *type, PyObject *temp)
Py_ssize_t n = PyList_GET_SIZE(subclasses);
for (Py_ssize_t i = 0; i < n; i++) {
PyTypeObject *subclass = _PyType_CAST(PyList_GET_ITEM(subclasses, i));
res = mro_hierarchy(subclass, temp);
res = mro_hierarchy_for_complete_type(subclass, temp);
if (res < 0) {
break;
}
@ -1926,7 +1927,7 @@ type_set_bases_unlocked(PyTypeObject *type, PyObject *new_bases, PyTypeObject *b
if (temp == NULL) {
goto bail;
}
if (mro_hierarchy(type, temp) < 0) {
if (mro_hierarchy_for_complete_type(type, temp) < 0) {
goto undo;
}
Py_DECREF(temp);
@ -3432,6 +3433,7 @@ mro_implementation_unlocked(PyTypeObject *type)
*/
PyTypeObject *base = _PyType_CAST(PyTuple_GET_ITEM(bases, 0));
PyObject *base_mro = lookup_tp_mro(base);
assert(base_mro != NULL);
Py_ssize_t k = PyTuple_GET_SIZE(base_mro);
PyObject *result = PyTuple_New(k + 1);
if (result == NULL) {
@ -3466,9 +3468,12 @@ mro_implementation_unlocked(PyTypeObject *type)
return NULL;
}
PyObject *mro_to_merge;
for (Py_ssize_t i = 0; i < n; i++) {
PyTypeObject *base = _PyType_CAST(PyTuple_GET_ITEM(bases, i));
to_merge[i] = lookup_tp_mro(base);
mro_to_merge = lookup_tp_mro(base);
assert(mro_to_merge != NULL);
to_merge[i] = mro_to_merge;
}
to_merge[n] = bases;
@ -8893,6 +8898,13 @@ type_ready_preheader(PyTypeObject *type)
type->tp_name);
return -1;
}
if (!(type->tp_flags & Py_TPFLAGS_HAVE_GC)) {
PyErr_Format(PyExc_SystemError,
"type %s has the Py_TPFLAGS_MANAGED_DICT flag "
"but not Py_TPFLAGS_HAVE_GC flag",
type->tp_name);
return -1;
}
type->tp_dictoffset = -1;
}
if (type->tp_flags & Py_TPFLAGS_MANAGED_WEAKREF) {
@ -8905,6 +8917,13 @@ type_ready_preheader(PyTypeObject *type)
type->tp_name);
return -1;
}
if (!(type->tp_flags & Py_TPFLAGS_HAVE_GC)) {
PyErr_Format(PyExc_SystemError,
"type %s has the Py_TPFLAGS_MANAGED_WEAKREF flag "
"but not Py_TPFLAGS_HAVE_GC flag",
type->tp_name);
return -1;
}
type->tp_weaklistoffset = MANAGED_WEAKREF_OFFSET;
}
return 0;
@ -8998,6 +9017,7 @@ type_ready_inherit(PyTypeObject *type)
// Inherit slots
PyObject *mro = lookup_tp_mro(type);
assert(mro != NULL);
Py_ssize_t n = PyTuple_GET_SIZE(mro);
for (Py_ssize_t i = 1; i < n; i++) {
PyObject *b = PyTuple_GET_ITEM(mro, i);
@ -10569,6 +10589,7 @@ slot_tp_hash(PyObject *self)
return PyObject_HashNotImplemented(self);
}
if (!PyLong_Check(res)) {
Py_DECREF(res);
PyErr_SetString(PyExc_TypeError,
"__hash__ method should return an integer");
return -1;
@ -11422,6 +11443,11 @@ static pytype_slotdef slotdefs[] = {
{NULL}
};
/* Stores the number of times where slotdefs has elements with same name.
This counter precalculated by _PyType_InitSlotDefs() when the main
interpreter starts. */
static uint8_t slotdefs_name_counts[Py_ARRAY_LENGTH(slotdefs)];
/* Given a type pointer and an offset gotten from a slotdef entry, return a
pointer to the actual slot. This is not quite the same as simply adding
the offset to the type pointer, since it takes care to indirect through the
@ -11464,61 +11490,6 @@ slotptr(PyTypeObject *type, int ioffset)
return (void **)ptr;
}
/* Return a slot pointer for a given name, but ONLY if the attribute has
exactly one slot function. The name must be an interned string. */
static void **
resolve_slotdups(PyTypeObject *type, PyObject *name)
{
/* XXX Maybe this could be optimized more -- but is it worth it? */
#ifdef Py_GIL_DISABLED
pytype_slotdef *ptrs[MAX_EQUIV];
pytype_slotdef **pp = ptrs;
/* Collect all slotdefs that match name into ptrs. */
for (pytype_slotdef *p = slotdefs; p->name_strobj; p++) {
if (p->name_strobj == name)
*pp++ = p;
}
*pp = NULL;
#else
/* pname and ptrs act as a little cache */
PyInterpreterState *interp = _PyInterpreterState_GET();
#define pname _Py_INTERP_CACHED_OBJECT(interp, type_slots_pname)
#define ptrs _Py_INTERP_CACHED_OBJECT(interp, type_slots_ptrs)
pytype_slotdef *p, **pp;
if (pname != name) {
/* Collect all slotdefs that match name into ptrs. */
pname = name;
pp = ptrs;
for (p = slotdefs; p->name_strobj; p++) {
if (p->name_strobj == name)
*pp++ = p;
}
*pp = NULL;
}
#endif
/* Look in all slots of the type matching the name. If exactly one of these
has a filled-in slot, return a pointer to that slot.
Otherwise, return NULL. */
void **res, **ptr;
res = NULL;
for (pp = ptrs; *pp; pp++) {
ptr = slotptr(type, (*pp)->offset);
if (ptr == NULL || *ptr == NULL)
continue;
if (res != NULL)
return NULL;
res = ptr;
}
#ifndef Py_GIL_DISABLED
#undef pname
#undef ptrs
#endif
return res;
}
// Return true if "name" corresponds to at least one slot definition. This is
// a more accurate but more expensive test compared to is_dunder_name().
static bool
@ -11645,7 +11616,15 @@ update_one_slot(PyTypeObject *type, pytype_slotdef *p, pytype_slotdef **next_p,
}
if (Py_IS_TYPE(descr, &PyWrapperDescr_Type) &&
((PyWrapperDescrObject *)descr)->d_base->name_strobj == p->name_strobj) {
void **tptr = resolve_slotdups(type, p->name_strobj);
void **tptr;
size_t index = (p - slotdefs) / sizeof(slotdefs[0]);
if (slotdefs_name_counts[index] == 1) {
tptr = slotptr(type, p->offset);
}
else {
tptr = NULL;
}
if (tptr == NULL || tptr == ptr)
generic = p->function;
d = (PyWrapperDescrObject *)descr;
@ -11858,6 +11837,76 @@ update_all_slots(PyTypeObject* type)
#endif
int
_PyType_InitSlotDefs(PyInterpreterState *interp)
{
if (!_Py_IsMainInterpreter(interp)) {
return 0;
}
PyObject *bytearray = NULL;
PyObject *cache = PyDict_New();
if (!cache) {
return -1;
}
pytype_slotdef *p;
Py_ssize_t idx = 0;
for (p = slotdefs; p->name_strobj; p++, idx++) {
assert(idx < 255);
if (PyDict_GetItemRef(cache, p->name_strobj, &bytearray) < 0) {
goto error;
}
if (!bytearray) {
Py_ssize_t size = sizeof(uint8_t) * (1 + MAX_EQUIV);
bytearray = PyByteArray_FromStringAndSize(NULL, size);
if (!bytearray) {
goto error;
}
uint8_t *data = (uint8_t *)PyByteArray_AS_STRING(bytearray);
data[0] = 0;
if (PyDict_SetItem(cache, p->name_strobj, bytearray) < 0) {
goto error;
}
}
assert(PyByteArray_CheckExact(bytearray));
uint8_t *data = (uint8_t *)PyByteArray_AS_STRING(bytearray);
data[0] += 1;
assert(data[0] < MAX_EQUIV);
data[data[0]] = (uint8_t)idx;
Py_CLEAR(bytearray);
}
memset(slotdefs_name_counts, 0, sizeof(slotdefs_name_counts));
Py_ssize_t pos = 0;
PyObject *key = NULL;
PyObject *value = NULL;
while (PyDict_Next(cache, &pos, &key, &value)) {
uint8_t *data = (uint8_t *)PyByteArray_AS_STRING(value);
uint8_t n = data[0];
for (uint8_t i = 0; i < n; i++) {
uint8_t idx = data[i + 1];
slotdefs_name_counts[idx] = n;
}
}
Py_DECREF(cache);
return 0;
error:
Py_XDECREF(bytearray);
Py_DECREF(cache);
return -1;
}
PyObject *
_PyType_GetSlotWrapperNames(void)

View file

@ -53,6 +53,7 @@ typedef struct {
typedef struct {
PyObject_HEAD
PyObject *name;
PyObject *qualname;
PyObject *type_params;
PyObject *compute_value;
PyObject *value;
@ -472,7 +473,7 @@ typevar_dealloc(PyObject *self)
_PyObject_GC_UNTRACK(self);
Py_DECREF(tv->name);
Py_XDECREF(tv->name);
Py_XDECREF(tv->bound);
Py_XDECREF(tv->evaluate_bound);
Py_XDECREF(tv->constraints);
@ -491,6 +492,7 @@ typevar_traverse(PyObject *self, visitproc visit, void *arg)
{
Py_VISIT(Py_TYPE(self));
typevarobject *tv = typevarobject_CAST(self);
Py_VISIT(tv->name);
Py_VISIT(tv->bound);
Py_VISIT(tv->evaluate_bound);
Py_VISIT(tv->constraints);
@ -505,6 +507,7 @@ static int
typevar_clear(PyObject *op)
{
typevarobject *self = typevarobject_CAST(op);
Py_CLEAR(self->name);
Py_CLEAR(self->bound);
Py_CLEAR(self->evaluate_bound);
Py_CLEAR(self->constraints);
@ -1171,7 +1174,7 @@ paramspec_dealloc(PyObject *self)
_PyObject_GC_UNTRACK(self);
Py_DECREF(ps->name);
Py_XDECREF(ps->name);
Py_XDECREF(ps->bound);
Py_XDECREF(ps->default_value);
Py_XDECREF(ps->evaluate_default);
@ -1187,6 +1190,7 @@ paramspec_traverse(PyObject *self, visitproc visit, void *arg)
{
Py_VISIT(Py_TYPE(self));
paramspecobject *ps = paramspecobject_CAST(self);
Py_VISIT(ps->name);
Py_VISIT(ps->bound);
Py_VISIT(ps->default_value);
Py_VISIT(ps->evaluate_default);
@ -1198,6 +1202,7 @@ static int
paramspec_clear(PyObject *op)
{
paramspecobject *self = paramspecobject_CAST(op);
Py_CLEAR(self->name);
Py_CLEAR(self->bound);
Py_CLEAR(self->default_value);
Py_CLEAR(self->evaluate_default);
@ -1519,7 +1524,7 @@ typevartuple_dealloc(PyObject *self)
_PyObject_GC_UNTRACK(self);
typevartupleobject *tvt = typevartupleobject_CAST(self);
Py_DECREF(tvt->name);
Py_XDECREF(tvt->name);
Py_XDECREF(tvt->default_value);
Py_XDECREF(tvt->evaluate_default);
PyObject_ClearManagedDict(self);
@ -1683,6 +1688,7 @@ typevartuple_traverse(PyObject *self, visitproc visit, void *arg)
{
Py_VISIT(Py_TYPE(self));
typevartupleobject *tvt = typevartupleobject_CAST(self);
Py_VISIT(tvt->name);
Py_VISIT(tvt->default_value);
Py_VISIT(tvt->evaluate_default);
PyObject_VisitManagedDict(self, visit, arg);
@ -1693,6 +1699,7 @@ static int
typevartuple_clear(PyObject *self)
{
typevartupleobject *tvt = typevartupleobject_CAST(self);
Py_CLEAR(tvt->name);
Py_CLEAR(tvt->default_value);
Py_CLEAR(tvt->evaluate_default);
PyObject_ClearManagedDict(self);
@ -1851,7 +1858,8 @@ typealias_dealloc(PyObject *self)
PyTypeObject *tp = Py_TYPE(self);
_PyObject_GC_UNTRACK(self);
typealiasobject *ta = typealiasobject_CAST(self);
Py_DECREF(ta->name);
Py_XDECREF(ta->name);
Py_XDECREF(ta->qualname);
Py_XDECREF(ta->type_params);
Py_XDECREF(ta->compute_value);
Py_XDECREF(ta->value);
@ -1878,11 +1886,12 @@ static PyObject *
typealias_repr(PyObject *self)
{
typealiasobject *ta = (typealiasobject *)self;
return Py_NewRef(ta->name);
return Py_NewRef(ta->qualname);
}
static PyMemberDef typealias_members[] = {
{"__name__", _Py_T_OBJECT, offsetof(typealiasobject, name), Py_READONLY},
{"__qualname__", _Py_T_OBJECT, offsetof(typealiasobject, qualname), Py_READONLY},
{0}
};
@ -1997,7 +2006,7 @@ typealias_check_type_params(PyObject *type_params, int *err) {
}
static PyObject *
typelias_convert_type_params(PyObject *type_params)
typealias_convert_type_params(PyObject *type_params)
{
if (
type_params == NULL
@ -2012,14 +2021,15 @@ typelias_convert_type_params(PyObject *type_params)
}
static typealiasobject *
typealias_alloc(PyObject *name, PyObject *type_params, PyObject *compute_value,
PyObject *value, PyObject *module)
typealias_alloc(PyObject *name, PyObject *qualname, PyObject *type_params,
PyObject *compute_value, PyObject *value, PyObject *module)
{
typealiasobject *ta = PyObject_GC_New(typealiasobject, &_PyTypeAlias_Type);
if (ta == NULL) {
return NULL;
}
ta->name = Py_NewRef(name);
ta->qualname = Py_NewRef(qualname);
ta->type_params = Py_XNewRef(type_params);
ta->compute_value = Py_XNewRef(compute_value);
ta->value = Py_XNewRef(value);
@ -2032,6 +2042,8 @@ static int
typealias_traverse(PyObject *op, visitproc visit, void *arg)
{
typealiasobject *self = typealiasobject_CAST(op);
Py_VISIT(self->name);
Py_VISIT(self->qualname);
Py_VISIT(self->type_params);
Py_VISIT(self->compute_value);
Py_VISIT(self->value);
@ -2043,6 +2055,8 @@ static int
typealias_clear(PyObject *op)
{
typealiasobject *self = typealiasobject_CAST(op);
Py_CLEAR(self->name);
Py_CLEAR(self->qualname);
Py_CLEAR(self->type_params);
Py_CLEAR(self->compute_value);
Py_CLEAR(self->value);
@ -2088,14 +2102,15 @@ typealias.__new__ as typealias_new
value: object
*
type_params: object = NULL
qualname: object(c_default="NULL") = None
Create a TypeAliasType.
[clinic start generated code]*/
static PyObject *
typealias_new_impl(PyTypeObject *type, PyObject *name, PyObject *value,
PyObject *type_params)
/*[clinic end generated code: output=8920ce6bdff86f00 input=df163c34e17e1a35]*/
PyObject *type_params, PyObject *qualname)
/*[clinic end generated code: output=b7f6d9f1c577cd9c input=cbec290f8c4886ef]*/
{
if (type_params != NULL && !PyTuple_Check(type_params)) {
PyErr_SetString(PyExc_TypeError, "type_params must be a tuple");
@ -2108,12 +2123,23 @@ typealias_new_impl(PyTypeObject *type, PyObject *name, PyObject *value,
return NULL;
}
if (qualname == NULL || qualname == Py_None) {
// If qualname was not set directly, we use name instead.
qualname = name;
} else {
if (!PyUnicode_Check(qualname)) {
PyErr_SetString(PyExc_TypeError, "qualname must be a string");
return NULL;
}
}
PyObject *module = caller();
if (module == NULL) {
return NULL;
}
PyObject *ta = (PyObject *)typealias_alloc(name, checked_params, NULL, value,
module);
PyObject *ta = (PyObject *)typealias_alloc(
name, qualname, checked_params, NULL, value, module);
Py_DECREF(module);
return ta;
}
@ -2179,10 +2205,17 @@ _Py_make_typealias(PyThreadState* unused, PyObject *args)
assert(PyTuple_GET_SIZE(args) == 3);
PyObject *name = PyTuple_GET_ITEM(args, 0);
assert(PyUnicode_Check(name));
PyObject *type_params = typelias_convert_type_params(PyTuple_GET_ITEM(args, 1));
PyObject *type_params = typealias_convert_type_params(PyTuple_GET_ITEM(args, 1));
PyObject *compute_value = PyTuple_GET_ITEM(args, 2);
assert(PyFunction_Check(compute_value));
return (PyObject *)typealias_alloc(name, type_params, compute_value, NULL, NULL);
PyFunctionObject *compute_func = (PyFunctionObject *)compute_value;
PyCodeObject *code_obj = (PyCodeObject *)compute_func->func_code;
PyObject *qualname = code_obj->co_qualname;
assert(qualname != NULL);
return (PyObject *)typealias_alloc(
name, qualname, type_params, compute_value, NULL, NULL);
}
PyDoc_STRVAR(generic_doc,

1002
Objects/unicode_format.c Normal file

File diff suppressed because it is too large Load diff

1961
Objects/unicode_formatter.c Normal file

File diff suppressed because it is too large Load diff

639
Objects/unicode_writer.c Normal file
View file

@ -0,0 +1,639 @@
/*
Unicode implementation based on original code by Fredrik Lundh,
modified by Marc-Andre Lemburg <mal@lemburg.com>.
Major speed upgrades to the method implementations at the Reykjavik
NeedForSpeed sprint, by Fredrik Lundh and Andrew Dalke.
Copyright (c) Corporation for National Research Initiatives.
--------------------------------------------------------------------
The original string type implementation is:
Copyright (c) 1999 by Secret Labs AB
Copyright (c) 1999 by Fredrik Lundh
By obtaining, using, and/or copying this software and/or its
associated documentation, you agree that you have read, understood,
and will comply with the following terms and conditions:
Permission to use, copy, modify, and distribute this software and its
associated documentation for any purpose and without fee is hereby
granted, provided that the above copyright notice appears in all
copies, and that both that copyright notice and this permission notice
appear in supporting documentation, and that the name of Secret Labs
AB or the author not be used in advertising or publicity pertaining to
distribution of the software without specific, written prior
permission.
SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO
THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS. IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR BE LIABLE FOR
ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
--------------------------------------------------------------------
*/
#include "Python.h"
#include "pycore_freelist.h" // _Py_FREELIST_FREE()
#include "pycore_long.h" // _PyLong_FormatWriter()
#include "pycore_unicodeobject.h" // _PyUnicode_Result()
#ifdef MS_WINDOWS
/* On Windows, overallocate by 50% is the best factor */
# define OVERALLOCATE_FACTOR 2
#else
/* On Linux, overallocate by 25% is the best factor */
# define OVERALLOCATE_FACTOR 4
#endif
/* Compilation of templated routines */
#define STRINGLIB_GET_EMPTY() _PyUnicode_GetEmpty()
#include "stringlib/ucs1lib.h"
#include "stringlib/find_max_char.h"
#include "stringlib/undef.h"
/* Copy an ASCII or latin1 char* string into a Python Unicode string.
WARNING: The function doesn't copy the terminating null character and
doesn't check the maximum character (may write a latin1 character in an
ASCII string). */
static void
unicode_write_cstr(PyObject *unicode, Py_ssize_t index,
const char *str, Py_ssize_t len)
{
int kind = PyUnicode_KIND(unicode);
const void *data = PyUnicode_DATA(unicode);
const char *end = str + len;
assert(index + len <= PyUnicode_GET_LENGTH(unicode));
switch (kind) {
case PyUnicode_1BYTE_KIND: {
#ifdef Py_DEBUG
if (PyUnicode_IS_ASCII(unicode)) {
Py_UCS4 maxchar = ucs1lib_find_max_char(
(const Py_UCS1*)str,
(const Py_UCS1*)str + len);
assert(maxchar < 128);
}
#endif
memcpy((char *) data + index, str, len);
break;
}
case PyUnicode_2BYTE_KIND: {
Py_UCS2 *start = (Py_UCS2 *)data + index;
Py_UCS2 *ucs2 = start;
for (; str < end; ++ucs2, ++str)
*ucs2 = (Py_UCS2)*str;
assert((ucs2 - start) <= PyUnicode_GET_LENGTH(unicode));
break;
}
case PyUnicode_4BYTE_KIND: {
Py_UCS4 *start = (Py_UCS4 *)data + index;
Py_UCS4 *ucs4 = start;
for (; str < end; ++ucs4, ++str)
*ucs4 = (Py_UCS4)*str;
assert((ucs4 - start) <= PyUnicode_GET_LENGTH(unicode));
break;
}
default:
Py_UNREACHABLE();
}
}
static inline void
_PyUnicodeWriter_Update(_PyUnicodeWriter *writer)
{
writer->maxchar = PyUnicode_MAX_CHAR_VALUE(writer->buffer);
writer->data = PyUnicode_DATA(writer->buffer);
if (!writer->readonly) {
writer->kind = PyUnicode_KIND(writer->buffer);
writer->size = PyUnicode_GET_LENGTH(writer->buffer);
}
else {
/* use a value smaller than PyUnicode_1BYTE_KIND() so
_PyUnicodeWriter_PrepareKind() will copy the buffer. */
writer->kind = 0;
assert(writer->kind <= PyUnicode_1BYTE_KIND);
/* Copy-on-write mode: set buffer size to 0 so
* _PyUnicodeWriter_Prepare() will copy (and enlarge) the buffer on
* next write. */
writer->size = 0;
}
}
void
_PyUnicodeWriter_Init(_PyUnicodeWriter *writer)
{
memset(writer, 0, sizeof(*writer));
/* ASCII is the bare minimum */
writer->min_char = 127;
/* use a kind value smaller than PyUnicode_1BYTE_KIND so
_PyUnicodeWriter_PrepareKind() will copy the buffer. */
assert(writer->kind == 0);
assert(writer->kind < PyUnicode_1BYTE_KIND);
}
PyUnicodeWriter*
PyUnicodeWriter_Create(Py_ssize_t length)
{
if (length < 0) {
PyErr_SetString(PyExc_ValueError,
"length must be positive");
return NULL;
}
const size_t size = sizeof(_PyUnicodeWriter);
PyUnicodeWriter *pub_writer;
pub_writer = _Py_FREELIST_POP_MEM(unicode_writers);
if (pub_writer == NULL) {
pub_writer = (PyUnicodeWriter *)PyMem_Malloc(size);
if (pub_writer == NULL) {
return (PyUnicodeWriter *)PyErr_NoMemory();
}
}
_PyUnicodeWriter *writer = (_PyUnicodeWriter *)pub_writer;
_PyUnicodeWriter_Init(writer);
if (_PyUnicodeWriter_Prepare(writer, length, 127) < 0) {
PyUnicodeWriter_Discard(pub_writer);
return NULL;
}
writer->overallocate = 1;
return pub_writer;
}
void PyUnicodeWriter_Discard(PyUnicodeWriter *writer)
{
if (writer == NULL) {
return;
}
_PyUnicodeWriter_Dealloc((_PyUnicodeWriter*)writer);
_Py_FREELIST_FREE(unicode_writers, writer, PyMem_Free);
}
// Initialize _PyUnicodeWriter with initial buffer
void
_PyUnicodeWriter_InitWithBuffer(_PyUnicodeWriter *writer, PyObject *buffer)
{
memset(writer, 0, sizeof(*writer));
writer->buffer = buffer;
_PyUnicodeWriter_Update(writer);
writer->min_length = writer->size;
}
int
_PyUnicodeWriter_PrepareInternal(_PyUnicodeWriter *writer,
Py_ssize_t length, Py_UCS4 maxchar)
{
Py_ssize_t newlen;
PyObject *newbuffer;
assert(length >= 0);
assert(maxchar <= _Py_MAX_UNICODE);
/* ensure that the _PyUnicodeWriter_Prepare macro was used */
assert((maxchar > writer->maxchar && length >= 0)
|| length > 0);
if (length > PY_SSIZE_T_MAX - writer->pos) {
PyErr_NoMemory();
return -1;
}
newlen = writer->pos + length;
maxchar = Py_MAX(maxchar, writer->min_char);
if (writer->buffer == NULL) {
assert(!writer->readonly);
if (writer->overallocate
&& newlen <= (PY_SSIZE_T_MAX - newlen / OVERALLOCATE_FACTOR)) {
/* overallocate to limit the number of realloc() */
newlen += newlen / OVERALLOCATE_FACTOR;
}
if (newlen < writer->min_length)
newlen = writer->min_length;
writer->buffer = PyUnicode_New(newlen, maxchar);
if (writer->buffer == NULL)
return -1;
}
else if (newlen > writer->size) {
if (writer->overallocate
&& newlen <= (PY_SSIZE_T_MAX - newlen / OVERALLOCATE_FACTOR)) {
/* overallocate to limit the number of realloc() */
newlen += newlen / OVERALLOCATE_FACTOR;
}
if (newlen < writer->min_length)
newlen = writer->min_length;
if (maxchar > writer->maxchar || writer->readonly) {
/* resize + widen */
maxchar = Py_MAX(maxchar, writer->maxchar);
newbuffer = PyUnicode_New(newlen, maxchar);
if (newbuffer == NULL)
return -1;
_PyUnicode_FastCopyCharacters(newbuffer, 0,
writer->buffer, 0, writer->pos);
Py_DECREF(writer->buffer);
writer->readonly = 0;
}
else {
newbuffer = _PyUnicode_ResizeCompact(writer->buffer, newlen);
if (newbuffer == NULL)
return -1;
}
writer->buffer = newbuffer;
}
else if (maxchar > writer->maxchar) {
assert(!writer->readonly);
newbuffer = PyUnicode_New(writer->size, maxchar);
if (newbuffer == NULL)
return -1;
_PyUnicode_FastCopyCharacters(newbuffer, 0,
writer->buffer, 0, writer->pos);
Py_SETREF(writer->buffer, newbuffer);
}
_PyUnicodeWriter_Update(writer);
return 0;
#undef OVERALLOCATE_FACTOR
}
int
_PyUnicodeWriter_PrepareKindInternal(_PyUnicodeWriter *writer,
int kind)
{
Py_UCS4 maxchar;
/* ensure that the _PyUnicodeWriter_PrepareKind macro was used */
assert(writer->kind < kind);
switch (kind)
{
case PyUnicode_1BYTE_KIND: maxchar = 0xff; break;
case PyUnicode_2BYTE_KIND: maxchar = 0xffff; break;
case PyUnicode_4BYTE_KIND: maxchar = _Py_MAX_UNICODE; break;
default:
Py_UNREACHABLE();
}
return _PyUnicodeWriter_PrepareInternal(writer, 0, maxchar);
}
int
_PyUnicodeWriter_WriteChar(_PyUnicodeWriter *writer, Py_UCS4 ch)
{
return _PyUnicodeWriter_WriteCharInline(writer, ch);
}
int
PyUnicodeWriter_WriteChar(PyUnicodeWriter *writer, Py_UCS4 ch)
{
if (ch > _Py_MAX_UNICODE) {
PyErr_SetString(PyExc_ValueError,
"character must be in range(0x110000)");
return -1;
}
return _PyUnicodeWriter_WriteChar((_PyUnicodeWriter*)writer, ch);
}
int
_PyUnicodeWriter_WriteStr(_PyUnicodeWriter *writer, PyObject *str)
{
assert(PyUnicode_Check(str));
Py_UCS4 maxchar;
Py_ssize_t len;
len = PyUnicode_GET_LENGTH(str);
if (len == 0)
return 0;
maxchar = PyUnicode_MAX_CHAR_VALUE(str);
if (maxchar > writer->maxchar || len > writer->size - writer->pos) {
if (writer->buffer == NULL && !writer->overallocate) {
assert(_PyUnicode_CheckConsistency(str, 1));
writer->readonly = 1;
writer->buffer = Py_NewRef(str);
_PyUnicodeWriter_Update(writer);
writer->pos += len;
return 0;
}
if (_PyUnicodeWriter_PrepareInternal(writer, len, maxchar) == -1)
return -1;
}
_PyUnicode_FastCopyCharacters(writer->buffer, writer->pos,
str, 0, len);
writer->pos += len;
return 0;
}
int
PyUnicodeWriter_WriteStr(PyUnicodeWriter *writer, PyObject *obj)
{
PyTypeObject *type = Py_TYPE(obj);
if (type == &PyUnicode_Type) {
return _PyUnicodeWriter_WriteStr((_PyUnicodeWriter*)writer, obj);
}
if (type == &PyLong_Type) {
return _PyLong_FormatWriter((_PyUnicodeWriter*)writer, obj, 10, 0);
}
PyObject *str = PyObject_Str(obj);
if (str == NULL) {
return -1;
}
int res = _PyUnicodeWriter_WriteStr((_PyUnicodeWriter*)writer, str);
Py_DECREF(str);
return res;
}
int
PyUnicodeWriter_WriteRepr(PyUnicodeWriter *writer, PyObject *obj)
{
if (Py_TYPE(obj) == &PyLong_Type) {
return _PyLong_FormatWriter((_PyUnicodeWriter*)writer, obj, 10, 0);
}
PyObject *repr = PyObject_Repr(obj);
if (repr == NULL) {
return -1;
}
int res = _PyUnicodeWriter_WriteStr((_PyUnicodeWriter*)writer, repr);
Py_DECREF(repr);
return res;
}
int
_PyUnicodeWriter_WriteSubstring(_PyUnicodeWriter *writer, PyObject *str,
Py_ssize_t start, Py_ssize_t end)
{
assert(0 <= start);
assert(end <= PyUnicode_GET_LENGTH(str));
assert(start <= end);
if (start == 0 && end == PyUnicode_GET_LENGTH(str))
return _PyUnicodeWriter_WriteStr(writer, str);
Py_ssize_t len = end - start;
if (len == 0) {
return 0;
}
Py_UCS4 maxchar;
if (PyUnicode_MAX_CHAR_VALUE(str) > writer->maxchar) {
maxchar = _PyUnicode_FindMaxChar(str, start, end);
}
else {
maxchar = writer->maxchar;
}
if (_PyUnicodeWriter_Prepare(writer, len, maxchar) < 0) {
return -1;
}
_PyUnicode_FastCopyCharacters(writer->buffer, writer->pos,
str, start, len);
writer->pos += len;
return 0;
}
int
PyUnicodeWriter_WriteSubstring(PyUnicodeWriter *writer, PyObject *str,
Py_ssize_t start, Py_ssize_t end)
{
if (!PyUnicode_Check(str)) {
PyErr_Format(PyExc_TypeError, "expect str, not %T", str);
return -1;
}
if (start < 0 || start > end) {
PyErr_Format(PyExc_ValueError, "invalid start argument");
return -1;
}
if (end > PyUnicode_GET_LENGTH(str)) {
PyErr_Format(PyExc_ValueError, "invalid end argument");
return -1;
}
return _PyUnicodeWriter_WriteSubstring((_PyUnicodeWriter*)writer, str,
start, end);
}
int
_PyUnicodeWriter_WriteASCIIString(_PyUnicodeWriter *writer,
const char *ascii, Py_ssize_t len)
{
if (len == -1)
len = strlen(ascii);
assert(ucs1lib_find_max_char((const Py_UCS1*)ascii, (const Py_UCS1*)ascii + len) < 128);
if (writer->buffer == NULL && !writer->overallocate) {
PyObject *str;
str = _PyUnicode_FromASCII(ascii, len);
if (str == NULL)
return -1;
writer->readonly = 1;
writer->buffer = str;
_PyUnicodeWriter_Update(writer);
writer->pos += len;
return 0;
}
if (_PyUnicodeWriter_Prepare(writer, len, 127) == -1)
return -1;
switch (writer->kind)
{
case PyUnicode_1BYTE_KIND:
{
const Py_UCS1 *str = (const Py_UCS1 *)ascii;
Py_UCS1 *data = writer->data;
memcpy(data + writer->pos, str, len);
break;
}
case PyUnicode_2BYTE_KIND:
{
_PyUnicode_CONVERT_BYTES(
Py_UCS1, Py_UCS2,
ascii, ascii + len,
(Py_UCS2 *)writer->data + writer->pos);
break;
}
case PyUnicode_4BYTE_KIND:
{
_PyUnicode_CONVERT_BYTES(
Py_UCS1, Py_UCS4,
ascii, ascii + len,
(Py_UCS4 *)writer->data + writer->pos);
break;
}
default:
Py_UNREACHABLE();
}
writer->pos += len;
return 0;
}
int
PyUnicodeWriter_WriteASCII(PyUnicodeWriter *writer,
const char *str,
Py_ssize_t size)
{
assert(writer != NULL);
_Py_AssertHoldsTstate();
_PyUnicodeWriter *priv_writer = (_PyUnicodeWriter*)writer;
return _PyUnicodeWriter_WriteASCIIString(priv_writer, str, size);
}
int
PyUnicodeWriter_WriteUTF8(PyUnicodeWriter *writer,
const char *str,
Py_ssize_t size)
{
if (size < 0) {
size = strlen(str);
}
_PyUnicodeWriter *_writer = (_PyUnicodeWriter*)writer;
Py_ssize_t old_pos = _writer->pos;
int res = _PyUnicode_DecodeUTF8Writer(_writer, str, size,
_Py_ERROR_STRICT, NULL, NULL);
if (res < 0) {
_writer->pos = old_pos;
}
return res;
}
int
PyUnicodeWriter_DecodeUTF8Stateful(PyUnicodeWriter *writer,
const char *string,
Py_ssize_t length,
const char *errors,
Py_ssize_t *consumed)
{
if (length < 0) {
length = strlen(string);
}
_PyUnicodeWriter *_writer = (_PyUnicodeWriter*)writer;
Py_ssize_t old_pos = _writer->pos;
int res = _PyUnicode_DecodeUTF8Writer(_writer, string, length,
_Py_ERROR_UNKNOWN, errors,
consumed);
if (res < 0) {
_writer->pos = old_pos;
if (consumed) {
*consumed = 0;
}
}
return res;
}
int
_PyUnicodeWriter_WriteLatin1String(_PyUnicodeWriter *writer,
const char *str, Py_ssize_t len)
{
Py_UCS4 maxchar;
maxchar = ucs1lib_find_max_char((const Py_UCS1*)str, (const Py_UCS1*)str + len);
if (_PyUnicodeWriter_Prepare(writer, len, maxchar) == -1)
return -1;
unicode_write_cstr(writer->buffer, writer->pos, str, len);
writer->pos += len;
return 0;
}
PyObject *
_PyUnicodeWriter_Finish(_PyUnicodeWriter *writer)
{
PyObject *str;
if (writer->pos == 0) {
Py_CLEAR(writer->buffer);
return _PyUnicode_GetEmpty();
}
str = writer->buffer;
writer->buffer = NULL;
if (writer->readonly) {
assert(PyUnicode_GET_LENGTH(str) == writer->pos);
return str;
}
if (PyUnicode_GET_LENGTH(str) != writer->pos) {
PyObject *str2;
str2 = _PyUnicode_ResizeCompact(str, writer->pos);
if (str2 == NULL) {
Py_DECREF(str);
return NULL;
}
str = str2;
}
assert(_PyUnicode_CheckConsistency(str, 1));
return _PyUnicode_Result(str);
}
PyObject*
PyUnicodeWriter_Finish(PyUnicodeWriter *writer)
{
PyObject *str = _PyUnicodeWriter_Finish((_PyUnicodeWriter*)writer);
assert(((_PyUnicodeWriter*)writer)->buffer == NULL);
_Py_FREELIST_FREE(unicode_writers, writer, PyMem_Free);
return str;
}
void
_PyUnicodeWriter_Dealloc(_PyUnicodeWriter *writer)
{
Py_CLEAR(writer->buffer);
}

View file

@ -9,6 +9,7 @@
*/
#include "Python.h"
#include "pycore_unicodectype.h" // export _PyUnicode_IsXidStart(), _PyUnicode_IsXidContinue()
#define ALPHA_MASK 0x01
#define DECIMAL_MASK 0x02

File diff suppressed because it is too large Load diff

View file

@ -393,8 +393,23 @@ static PyGetSetDef union_properties[] = {
{0}
};
static PyObject *
union_nb_or(PyObject *a, PyObject *b)
{
unionbuilder ub;
if (!unionbuilder_init(&ub, true)) {
return NULL;
}
if (!unionbuilder_add_single(&ub, a) ||
!unionbuilder_add_single(&ub, b)) {
unionbuilder_finalize(&ub);
return NULL;
}
return make_union(&ub);
}
static PyNumberMethods union_as_number = {
.nb_or = _Py_union_type_or, // Add __or__ function
.nb_or = union_nb_or, // Add __or__ function
};
static const char* const cls_attrs[] = {
@ -474,11 +489,13 @@ _Py_union_from_tuple(PyObject *args)
}
if (PyTuple_CheckExact(args)) {
if (!unionbuilder_add_tuple(&ub, args)) {
unionbuilder_finalize(&ub);
return NULL;
}
}
else {
if (!unionbuilder_add_single(&ub, args)) {
unionbuilder_finalize(&ub);
return NULL;
}
}