mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-05-22 21:32:31 +00:00
Make numerous improvements
- Python static hello world now 1.8mb - Python static fully loaded now 10mb - Python HTTPS client now uses MbedTLS - Python REPL now completes import stmts - Increase stack size for Python for now - Begin synthesizing posixpath and ntpath - Restore Python \N{UNICODE NAME} support - Restore Python NFKD symbol normalization - Add optimized code path for Intel SHA-NI - Get more Python unit tests passing faster - Get Python help() pagination working on NT - Python hashlib now supports MbedTLS PBKDF2 - Make memcpy/memmove/memcmp/bcmp/etc. faster - Add Mersenne Twister and Vigna to LIBC_RAND - Provide privileged __printf() for error code - Fix zipos opendir() so that it reports ENOTDIR - Add basic chmod() implementation for Windows NT - Add Cosmo's best functions to Python cosmo module - Pin function trace indent depth to that of caller - Show memory diagram on invalid access in MODE=dbg - Differentiate stack overflow on crash in MODE=dbg - Add stb_truetype and tools for analyzing font files - Upgrade to UNICODE 13 and reduce its binary footprint - COMPILE.COM now logs resource usage of build commands - Start implementing basic poll() support on bare metal - Set getauxval(AT_EXECFN) to GetModuleFileName() on NT - Add descriptions to strerror() in non-TINY build modes - Add COUNTBRANCH() macro to help with micro-optimizations - Make error / backtrace / asan / memory code more unbreakable - Add fast perfect C implementation of μ-Law and a-Law audio codecs - Make strtol() functions consistent with other libc implementations - Improve Linenoise implementation (see also github.com/jart/bestline) - COMPILE.COM now suppresses stdout/stderr of successful build commands
This commit is contained in:
parent
fa7b4f5bd1
commit
39bf41f4eb
806 changed files with 77494 additions and 63859 deletions
303
third_party/python/Objects/abstract.c
vendored
303
third_party/python/Objects/abstract.c
vendored
|
@ -54,11 +54,9 @@ PyObject *
|
|||
PyObject_Type(PyObject *o)
|
||||
{
|
||||
PyObject *v;
|
||||
|
||||
if (o == NULL) {
|
||||
return null_error();
|
||||
}
|
||||
|
||||
v = (PyObject *)o->ob_type;
|
||||
Py_INCREF(v);
|
||||
return v;
|
||||
|
@ -68,16 +66,13 @@ Py_ssize_t
|
|||
PyObject_Size(PyObject *o)
|
||||
{
|
||||
PySequenceMethods *m;
|
||||
|
||||
if (o == NULL) {
|
||||
null_error();
|
||||
return -1;
|
||||
}
|
||||
|
||||
m = o->ob_type->tp_as_sequence;
|
||||
if (m && m->sq_length)
|
||||
return m->sq_length(o);
|
||||
|
||||
return PyMapping_Size(o);
|
||||
}
|
||||
|
||||
|
@ -767,6 +762,38 @@ PyNumber_Check(PyObject *o)
|
|||
#define NB_TERNOP(nb_methods, slot) \
|
||||
(*(ternaryfunc*)(& ((char*)nb_methods)[slot]))
|
||||
|
||||
static noinline PyObject *
|
||||
binop_type_error(PyObject *v, PyObject *w, const char *op_name)
|
||||
{
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"unsupported operand type(s) for %.100s: "
|
||||
"'%.100s' and '%.100s'",
|
||||
op_name,
|
||||
v->ob_type->tp_name,
|
||||
w->ob_type->tp_name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static noinline PyObject *
|
||||
binop_not_implemented(PyObject *v, PyObject *w,
|
||||
const int op_slot, const char *op_name)
|
||||
{
|
||||
if (op_slot == NB_SLOT(nb_rshift) &&
|
||||
PyCFunction_Check(v) &&
|
||||
strcmp(((PyCFunctionObject *)v)->m_ml->ml_name, "print") == 0)
|
||||
{
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"unsupported operand type(s) for %.100s: "
|
||||
"'%.100s' and '%.100s'. Did you mean \"print(<message>, "
|
||||
"file=<output_stream>)\"?",
|
||||
op_name,
|
||||
v->ob_type->tp_name,
|
||||
w->ob_type->tp_name);
|
||||
return NULL;
|
||||
}
|
||||
return binop_type_error(v, w, op_name);
|
||||
}
|
||||
|
||||
/*
|
||||
Calling scheme used for binary operations:
|
||||
|
||||
|
@ -783,7 +810,6 @@ binary_op1(PyObject *v, PyObject *w, const int op_slot)
|
|||
PyObject *x;
|
||||
binaryfunc slotv = NULL;
|
||||
binaryfunc slotw = NULL;
|
||||
|
||||
if (v->ob_type->tp_as_number != NULL)
|
||||
slotv = NB_BINOP(v->ob_type->tp_as_number, op_slot);
|
||||
if (w->ob_type != v->ob_type &&
|
||||
|
@ -814,44 +840,59 @@ binary_op1(PyObject *v, PyObject *w, const int op_slot)
|
|||
Py_RETURN_NOTIMPLEMENTED;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
binop_type_error(PyObject *v, PyObject *w, const char *op_name)
|
||||
{
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"unsupported operand type(s) for %.100s: "
|
||||
"'%.100s' and '%.100s'",
|
||||
op_name,
|
||||
v->ob_type->tp_name,
|
||||
w->ob_type->tp_name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
binary_op(PyObject *v, PyObject *w, const int op_slot, const char *op_name)
|
||||
{
|
||||
PyObject *result = binary_op1(v, w, op_slot);
|
||||
if (result == Py_NotImplemented) {
|
||||
PyObject *result;
|
||||
if ((result = binary_op1(v, w, op_slot)) != Py_NotImplemented) {
|
||||
return result;
|
||||
} else {
|
||||
Py_DECREF(result);
|
||||
|
||||
if (op_slot == NB_SLOT(nb_rshift) &&
|
||||
PyCFunction_Check(v) &&
|
||||
strcmp(((PyCFunctionObject *)v)->m_ml->ml_name, "print") == 0)
|
||||
{
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"unsupported operand type(s) for %.100s: "
|
||||
"'%.100s' and '%.100s'. Did you mean \"print(<message>, "
|
||||
"file=<output_stream>)\"?",
|
||||
op_name,
|
||||
v->ob_type->tp_name,
|
||||
w->ob_type->tp_name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return binop_type_error(v, w, op_name);
|
||||
return binop_not_implemented(v, w, op_slot, op_name);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
PyObject *
|
||||
PyNumber_Subtract(PyObject *v, PyObject *w)
|
||||
{
|
||||
return binary_op(v, w, offsetof(PyNumberMethods, nb_subtract), "-");
|
||||
}
|
||||
|
||||
PyObject *
|
||||
PyNumber_Or(PyObject *v, PyObject *w)
|
||||
{
|
||||
return binary_op(v, w, offsetof(PyNumberMethods, nb_or), "|");
|
||||
}
|
||||
|
||||
PyObject *
|
||||
PyNumber_Xor(PyObject *v, PyObject *w)
|
||||
{
|
||||
return binary_op(v, w, offsetof(PyNumberMethods, nb_xor), "^");
|
||||
}
|
||||
|
||||
PyObject *
|
||||
PyNumber_And(PyObject *v, PyObject *w)
|
||||
{
|
||||
return binary_op(v, w, offsetof(PyNumberMethods, nb_and), "&");
|
||||
}
|
||||
|
||||
PyObject *
|
||||
PyNumber_Lshift(PyObject *v, PyObject *w)
|
||||
{
|
||||
return binary_op(v, w, offsetof(PyNumberMethods, nb_lshift), "<<");
|
||||
}
|
||||
|
||||
PyObject *
|
||||
PyNumber_Rshift(PyObject *v, PyObject *w)
|
||||
{
|
||||
return binary_op(v, w, offsetof(PyNumberMethods, nb_rshift), ">>");
|
||||
}
|
||||
|
||||
PyObject *
|
||||
PyNumber_Divmod(PyObject *v, PyObject *w)
|
||||
{
|
||||
return binary_op(v, w, offsetof(PyNumberMethods, nb_divmod), "divmod()");
|
||||
}
|
||||
|
||||
/*
|
||||
Calling scheme used for ternary operations:
|
||||
|
@ -872,7 +913,6 @@ ternary_op(PyObject *v,
|
|||
ternaryfunc slotv = NULL;
|
||||
ternaryfunc slotw = NULL;
|
||||
ternaryfunc slotz = NULL;
|
||||
|
||||
mv = v->ob_type->tp_as_number;
|
||||
mw = w->ob_type->tp_as_number;
|
||||
if (mv != NULL)
|
||||
|
@ -914,7 +954,6 @@ ternary_op(PyObject *v,
|
|||
Py_DECREF(x); /* can't do it */
|
||||
}
|
||||
}
|
||||
|
||||
if (z == Py_None)
|
||||
PyErr_Format(
|
||||
PyExc_TypeError,
|
||||
|
@ -933,20 +972,6 @@ ternary_op(PyObject *v,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
#define BINARY_FUNC(func, op, op_name) \
|
||||
PyObject * \
|
||||
func(PyObject *v, PyObject *w) { \
|
||||
return binary_op(v, w, NB_SLOT(op), op_name); \
|
||||
}
|
||||
|
||||
BINARY_FUNC(PyNumber_Or, nb_or, "|")
|
||||
BINARY_FUNC(PyNumber_Xor, nb_xor, "^")
|
||||
BINARY_FUNC(PyNumber_And, nb_and, "&")
|
||||
BINARY_FUNC(PyNumber_Lshift, nb_lshift, "<<")
|
||||
BINARY_FUNC(PyNumber_Rshift, nb_rshift, ">>")
|
||||
BINARY_FUNC(PyNumber_Subtract, nb_subtract, "-")
|
||||
BINARY_FUNC(PyNumber_Divmod, nb_divmod, "divmod()")
|
||||
|
||||
PyObject *
|
||||
PyNumber_Add(PyObject *v, PyObject *w)
|
||||
{
|
||||
|
@ -1292,11 +1317,16 @@ PyNumber_Index(PyObject *item)
|
|||
Py_ssize_t
|
||||
PyNumber_AsSsize_t(PyObject *item, PyObject *err)
|
||||
{
|
||||
Py_ssize_t result;
|
||||
PyObject *value;
|
||||
PyObject *runerr;
|
||||
PyObject *value = PyNumber_Index(item);
|
||||
if (value == NULL)
|
||||
Py_ssize_t result;
|
||||
|
||||
if (item && PyLong_Check(item)) {
|
||||
Py_INCREF(item);
|
||||
value = item;
|
||||
} else if (!(value = PyNumber_Index(item))) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* We're done if PyLong_AsSsize_t() returns without error. */
|
||||
result = PyLong_AsSsize_t(value);
|
||||
|
@ -2089,11 +2119,9 @@ PyObject *
|
|||
PyMapping_GetItemString(PyObject *o, const char *key)
|
||||
{
|
||||
PyObject *okey, *r;
|
||||
|
||||
if (key == NULL) {
|
||||
return null_error();
|
||||
}
|
||||
|
||||
okey = PyUnicode_FromString(key);
|
||||
if (okey == NULL)
|
||||
return NULL;
|
||||
|
@ -2107,12 +2135,10 @@ PyMapping_SetItemString(PyObject *o, const char *key, PyObject *value)
|
|||
{
|
||||
PyObject *okey;
|
||||
int r;
|
||||
|
||||
if (key == NULL) {
|
||||
null_error();
|
||||
return -1;
|
||||
}
|
||||
|
||||
okey = PyUnicode_FromString(key);
|
||||
if (okey == NULL)
|
||||
return -1;
|
||||
|
@ -2125,7 +2151,6 @@ int
|
|||
PyMapping_HasKeyString(PyObject *o, const char *key)
|
||||
{
|
||||
PyObject *v;
|
||||
|
||||
v = PyMapping_GetItemString(o, key);
|
||||
if (v) {
|
||||
Py_DECREF(v);
|
||||
|
@ -2139,7 +2164,6 @@ int
|
|||
PyMapping_HasKey(PyObject *o, PyObject *key)
|
||||
{
|
||||
PyObject *v;
|
||||
|
||||
v = PyObject_GetItem(o, key);
|
||||
if (v) {
|
||||
Py_DECREF(v);
|
||||
|
@ -2155,7 +2179,6 @@ PyMapping_Keys(PyObject *o)
|
|||
PyObject *keys;
|
||||
PyObject *fast;
|
||||
_Py_IDENTIFIER(keys);
|
||||
|
||||
if (PyDict_CheckExact(o))
|
||||
return PyDict_Keys(o);
|
||||
keys = _PyObject_CallMethodId(o, &PyId_keys, NULL);
|
||||
|
@ -2172,7 +2195,6 @@ PyMapping_Items(PyObject *o)
|
|||
PyObject *items;
|
||||
PyObject *fast;
|
||||
_Py_IDENTIFIER(items);
|
||||
|
||||
if (PyDict_CheckExact(o))
|
||||
return PyDict_Items(o);
|
||||
items = _PyObject_CallMethodId(o, &PyId_items, NULL);
|
||||
|
@ -2189,7 +2211,6 @@ PyMapping_Values(PyObject *o)
|
|||
PyObject *values;
|
||||
PyObject *fast;
|
||||
_Py_IDENTIFIER(values);
|
||||
|
||||
if (PyDict_CheckExact(o))
|
||||
return PyDict_Values(o);
|
||||
values = _PyObject_CallMethodId(o, &PyId_values, NULL);
|
||||
|
@ -2200,10 +2221,6 @@ PyMapping_Values(PyObject *o)
|
|||
return fast;
|
||||
}
|
||||
|
||||
/* Operations on callable objects */
|
||||
|
||||
/* XXX PyCallable_Check() is in object.c */
|
||||
|
||||
PyObject *
|
||||
PyObject_CallObject(PyObject *o, PyObject *a)
|
||||
{
|
||||
|
@ -2214,9 +2231,7 @@ PyObject*
|
|||
(_Py_CheckFunctionResult)(PyObject *func, PyObject *result, const char *where)
|
||||
{
|
||||
int err_occurred = (PyErr_Occurred() != NULL);
|
||||
|
||||
assert((func != NULL) ^ (where != NULL));
|
||||
|
||||
if (result == NULL) {
|
||||
if (!err_occurred) {
|
||||
if (func)
|
||||
|
@ -2237,7 +2252,6 @@ PyObject*
|
|||
else {
|
||||
if (err_occurred) {
|
||||
Py_DECREF(result);
|
||||
|
||||
if (func) {
|
||||
_PyErr_FormatFromCause(PyExc_SystemError,
|
||||
"%R returned a result with an error set",
|
||||
|
@ -2263,49 +2277,40 @@ PyObject_Call(PyObject *func, PyObject *args, PyObject *kwargs)
|
|||
{
|
||||
ternaryfunc call;
|
||||
PyObject *result;
|
||||
|
||||
/* PyObject_Call() must not be called with an exception set,
|
||||
because it may clear it (directly or indirectly) and so the
|
||||
caller loses its exception */
|
||||
assert(!PyErr_Occurred());
|
||||
assert(PyTuple_Check(args));
|
||||
assert(kwargs == NULL || PyDict_Check(kwargs));
|
||||
|
||||
call = func->ob_type->tp_call;
|
||||
if (call == NULL) {
|
||||
PyErr_Format(PyExc_TypeError, "'%.200s' object is not callable",
|
||||
func->ob_type->tp_name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (Py_EnterRecursiveCall(" while calling a Python object"))
|
||||
return NULL;
|
||||
|
||||
result = (*call)(func, args, kwargs);
|
||||
|
||||
Py_LeaveRecursiveCall();
|
||||
|
||||
return _Py_CheckFunctionResult(func, result, NULL);
|
||||
}
|
||||
|
||||
PyObject*
|
||||
PyObject *
|
||||
_PyStack_AsTuple(PyObject **stack, Py_ssize_t nargs)
|
||||
{
|
||||
PyObject *args;
|
||||
Py_ssize_t i;
|
||||
|
||||
args = PyTuple_New(nargs);
|
||||
if (args == NULL) {
|
||||
return NULL;
|
||||
PyObject *item, *args;
|
||||
if ((args = PyTuple_New(nargs))) {
|
||||
for (i=0; i < nargs; i++) {
|
||||
item = stack[i];
|
||||
Py_INCREF(item);
|
||||
PyTuple_SET_ITEM(args, i, item);
|
||||
}
|
||||
return args;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i=0; i < nargs; i++) {
|
||||
PyObject *item = stack[i];
|
||||
Py_INCREF(item);
|
||||
PyTuple_SET_ITEM(args, i, item);
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
PyObject *
|
||||
|
@ -2314,21 +2319,17 @@ _PyObject_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs,
|
|||
{
|
||||
ternaryfunc call;
|
||||
PyObject *result = NULL;
|
||||
|
||||
/* _PyObject_FastCallDict() must not be called with an exception set,
|
||||
because it may clear it (directly or indirectly) and so the
|
||||
caller loses its exception */
|
||||
assert(!PyErr_Occurred());
|
||||
|
||||
assert(func != NULL);
|
||||
assert(nargs >= 0);
|
||||
assert(nargs == 0 || args != NULL);
|
||||
assert(kwargs == NULL || PyDict_Check(kwargs));
|
||||
|
||||
if (Py_EnterRecursiveCall(" while calling a Python object")) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (PyFunction_Check(func)) {
|
||||
result = _PyFunction_FastCallDict(func, args, nargs, kwargs);
|
||||
}
|
||||
|
@ -2336,8 +2337,8 @@ _PyObject_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs,
|
|||
result = _PyCFunction_FastCallDict(func, args, nargs, kwargs);
|
||||
}
|
||||
else {
|
||||
PyObject *tuple;
|
||||
|
||||
Py_ssize_t i;
|
||||
PyObject *item, *tuple;
|
||||
/* Slow-path: build a temporary tuple */
|
||||
call = func->ob_type->tp_call;
|
||||
if (call == NULL) {
|
||||
|
@ -2345,21 +2346,19 @@ _PyObject_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs,
|
|||
func->ob_type->tp_name);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
tuple = _PyStack_AsTuple(args, nargs);
|
||||
if (tuple == NULL) {
|
||||
goto exit;
|
||||
/* [jart] inlined _PyStack_AsTuple b/c profiling */
|
||||
if (!(tuple = PyTuple_New(nargs))) return 0;
|
||||
for (i = 0; i < nargs; i++) {
|
||||
item = args[i];
|
||||
Py_INCREF(item);
|
||||
PyTuple_SET_ITEM(tuple, i, item);
|
||||
}
|
||||
|
||||
result = (*call)(func, tuple, kwargs);
|
||||
Py_DECREF(tuple);
|
||||
|
||||
result = _Py_CheckFunctionResult(func, result, NULL);
|
||||
}
|
||||
|
||||
exit:
|
||||
Py_LeaveRecursiveCall();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -2372,9 +2371,7 @@ _PyObject_Call_Prepend(PyObject *func,
|
|||
PyObject **stack;
|
||||
Py_ssize_t argcount;
|
||||
PyObject *result;
|
||||
|
||||
assert(PyTuple_Check(args));
|
||||
|
||||
argcount = PyTuple_GET_SIZE(args);
|
||||
if (argcount + 1 <= (Py_ssize_t)Py_ARRAY_LENGTH(small_stack)) {
|
||||
stack = small_stack;
|
||||
|
@ -2386,13 +2383,11 @@ _PyObject_Call_Prepend(PyObject *func,
|
|||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* use borrowed references */
|
||||
stack[0] = obj;
|
||||
memcpy(&stack[1],
|
||||
&PyTuple_GET_ITEM(args, 0),
|
||||
argcount * sizeof(PyObject *));
|
||||
|
||||
result = _PyObject_FastCallDict(func,
|
||||
stack, argcount + 1,
|
||||
kwargs);
|
||||
|
@ -2408,12 +2403,10 @@ _PyStack_AsDict(PyObject **values, PyObject *kwnames)
|
|||
Py_ssize_t nkwargs = PyTuple_GET_SIZE(kwnames);
|
||||
PyObject *kwdict;
|
||||
Py_ssize_t i;
|
||||
|
||||
kwdict = PyDict_New();
|
||||
if (kwdict == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < nkwargs; i++) {
|
||||
PyObject *key = PyTuple_GET_ITEM(kwnames, i);
|
||||
PyObject *value = *values++;
|
||||
|
@ -2436,36 +2429,29 @@ _PyStack_UnpackDict(PyObject **args, Py_ssize_t nargs, PyObject *kwargs,
|
|||
Py_ssize_t pos, i;
|
||||
PyObject *key, *value;
|
||||
PyObject *kwnames;
|
||||
|
||||
assert(nargs >= 0);
|
||||
assert(kwargs == NULL || PyDict_CheckExact(kwargs));
|
||||
|
||||
if (kwargs == NULL || (nkwargs = PyDict_Size(kwargs)) == 0) {
|
||||
*p_stack = args;
|
||||
*p_kwnames = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((size_t)nargs > PY_SSIZE_T_MAX / sizeof(stack[0]) - (size_t)nkwargs) {
|
||||
PyErr_NoMemory();
|
||||
return -1;
|
||||
}
|
||||
|
||||
stack = PyMem_Malloc((nargs + nkwargs) * sizeof(stack[0]));
|
||||
if (stack == NULL) {
|
||||
PyErr_NoMemory();
|
||||
return -1;
|
||||
}
|
||||
|
||||
kwnames = PyTuple_New(nkwargs);
|
||||
if (kwnames == NULL) {
|
||||
PyMem_Free(stack);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Copy position arguments (borrowed references) */
|
||||
memcpy(stack, args, nargs * sizeof(stack[0]));
|
||||
|
||||
kwstack = stack + nargs;
|
||||
pos = i = 0;
|
||||
/* This loop doesn't support lookup function mutating the dictionary
|
||||
|
@ -2478,7 +2464,6 @@ _PyStack_UnpackDict(PyObject **args, Py_ssize_t nargs, PyObject *kwargs,
|
|||
kwstack[i] = value;
|
||||
i++;
|
||||
}
|
||||
|
||||
*p_stack = stack;
|
||||
*p_kwnames = kwnames;
|
||||
return 0;
|
||||
|
@ -2490,22 +2475,18 @@ _PyObject_FastCallKeywords(PyObject *func, PyObject **stack, Py_ssize_t nargs,
|
|||
{
|
||||
PyObject *kwdict, *result;
|
||||
Py_ssize_t nkwargs = (kwnames == NULL) ? 0 : PyTuple_GET_SIZE(kwnames);
|
||||
|
||||
assert(nargs >= 0);
|
||||
assert(kwnames == NULL || PyTuple_CheckExact(kwnames));
|
||||
assert((nargs == 0 && nkwargs == 0) || stack != NULL);
|
||||
/* kwnames must only contains str strings, no subclass, and all keys must
|
||||
be unique: these are implemented in Python/ceval.c and
|
||||
_PyArg_ParseStack(). */
|
||||
|
||||
if (PyFunction_Check(func)) {
|
||||
return _PyFunction_FastCallKeywords(func, stack, nargs, kwnames);
|
||||
}
|
||||
|
||||
if (PyCFunction_Check(func)) {
|
||||
return _PyCFunction_FastCallKeywords(func, stack, nargs, kwnames);
|
||||
}
|
||||
|
||||
if (nkwargs > 0) {
|
||||
kwdict = _PyStack_AsDict(stack + nargs, kwnames);
|
||||
if (kwdict == NULL) {
|
||||
|
@ -2515,7 +2496,6 @@ _PyObject_FastCallKeywords(PyObject *func, PyObject **stack, Py_ssize_t nargs,
|
|||
else {
|
||||
kwdict = NULL;
|
||||
}
|
||||
|
||||
result = _PyObject_FastCallDict(func, stack, nargs, kwdict);
|
||||
Py_XDECREF(kwdict);
|
||||
return result;
|
||||
|
@ -2525,16 +2505,13 @@ static PyObject*
|
|||
call_function_tail(PyObject *callable, PyObject *args)
|
||||
{
|
||||
PyObject *result;
|
||||
|
||||
assert(args != NULL);
|
||||
|
||||
if (!PyTuple_Check(args)) {
|
||||
result = _PyObject_CallArg1(callable, args);
|
||||
}
|
||||
else {
|
||||
result = PyObject_Call(callable, args, NULL);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -2543,22 +2520,18 @@ PyObject_CallFunction(PyObject *callable, const char *format, ...)
|
|||
{
|
||||
va_list va;
|
||||
PyObject *args, *result;
|
||||
|
||||
if (callable == NULL) {
|
||||
return null_error();
|
||||
}
|
||||
|
||||
if (!format || !*format) {
|
||||
return _PyObject_CallNoArg(callable);
|
||||
}
|
||||
|
||||
va_start(va, format);
|
||||
args = Py_VaBuildValue(format, va);
|
||||
va_end(va);
|
||||
if (args == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
result = call_function_tail(callable, args);
|
||||
Py_DECREF(args);
|
||||
return result;
|
||||
|
@ -2569,22 +2542,18 @@ _PyObject_CallFunction_SizeT(PyObject *callable, const char *format, ...)
|
|||
{
|
||||
va_list va;
|
||||
PyObject *args, *result;
|
||||
|
||||
if (callable == NULL) {
|
||||
return null_error();
|
||||
}
|
||||
|
||||
if (!format || !*format) {
|
||||
return _PyObject_CallNoArg(callable);
|
||||
}
|
||||
|
||||
va_start(va, format);
|
||||
args = _Py_VaBuildValue_SizeT(format, va);
|
||||
va_end(va);
|
||||
if (args == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
result = call_function_tail(callable, args);
|
||||
Py_DECREF(args);
|
||||
return result;
|
||||
|
@ -2594,18 +2563,14 @@ static PyObject*
|
|||
callmethod(PyObject* func, const char *format, va_list va, int is_size_t)
|
||||
{
|
||||
PyObject *args, *result;
|
||||
|
||||
assert(func != NULL);
|
||||
|
||||
if (!PyCallable_Check(func)) {
|
||||
type_error("attribute of type '%.200s' is not callable", func);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!format || !*format) {
|
||||
return _PyObject_CallNoArg(func);
|
||||
}
|
||||
|
||||
if (is_size_t) {
|
||||
args = _Py_VaBuildValue_SizeT(format, va);
|
||||
}
|
||||
|
@ -2615,7 +2580,6 @@ callmethod(PyObject* func, const char *format, va_list va, int is_size_t)
|
|||
if (args == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
result = call_function_tail(func, args);
|
||||
Py_DECREF(args);
|
||||
return result;
|
||||
|
@ -2627,15 +2591,12 @@ PyObject_CallMethod(PyObject *o, const char *name, const char *format, ...)
|
|||
va_list va;
|
||||
PyObject *func = NULL;
|
||||
PyObject *retval = NULL;
|
||||
|
||||
if (o == NULL || name == NULL) {
|
||||
return null_error();
|
||||
}
|
||||
|
||||
func = PyObject_GetAttrString(o, name);
|
||||
if (func == NULL)
|
||||
return NULL;
|
||||
|
||||
va_start(va, format);
|
||||
retval = callmethod(func, format, va, 0);
|
||||
va_end(va);
|
||||
|
@ -2650,15 +2611,12 @@ _PyObject_CallMethodId(PyObject *o, _Py_Identifier *name,
|
|||
va_list va;
|
||||
PyObject *func = NULL;
|
||||
PyObject *retval = NULL;
|
||||
|
||||
if (o == NULL || name == NULL) {
|
||||
return null_error();
|
||||
}
|
||||
|
||||
func = _PyObject_GetAttrId(o, name);
|
||||
if (func == NULL)
|
||||
return NULL;
|
||||
|
||||
va_start(va, format);
|
||||
retval = callmethod(func, format, va, 0);
|
||||
va_end(va);
|
||||
|
@ -2673,11 +2631,9 @@ _PyObject_CallMethod_SizeT(PyObject *o, const char *name,
|
|||
va_list va;
|
||||
PyObject *func = NULL;
|
||||
PyObject *retval;
|
||||
|
||||
if (o == NULL || name == NULL) {
|
||||
return null_error();
|
||||
}
|
||||
|
||||
func = PyObject_GetAttrString(o, name);
|
||||
if (func == NULL)
|
||||
return NULL;
|
||||
|
@ -2695,11 +2651,9 @@ _PyObject_CallMethodId_SizeT(PyObject *o, _Py_Identifier *name,
|
|||
va_list va;
|
||||
PyObject *func = NULL;
|
||||
PyObject *retval;
|
||||
|
||||
if (o == NULL || name == NULL) {
|
||||
return null_error();
|
||||
}
|
||||
|
||||
func = _PyObject_GetAttrId(o, name);
|
||||
if (func == NULL) {
|
||||
return NULL;
|
||||
|
@ -2718,10 +2672,8 @@ objargs_mkstack(PyObject **small_stack, Py_ssize_t small_stack_size,
|
|||
Py_ssize_t i, n;
|
||||
va_list countva;
|
||||
PyObject **stack;
|
||||
|
||||
/* Count the number of arguments */
|
||||
va_copy(countva, va);
|
||||
|
||||
n = 0;
|
||||
while (1) {
|
||||
PyObject *arg = va_arg(countva, PyObject *);
|
||||
|
@ -2731,7 +2683,6 @@ objargs_mkstack(PyObject **small_stack, Py_ssize_t small_stack_size,
|
|||
n++;
|
||||
}
|
||||
*p_nargs = n;
|
||||
|
||||
/* Copy arguments */
|
||||
if (n <= small_stack_size) {
|
||||
stack = small_stack;
|
||||
|
@ -2744,7 +2695,6 @@ objargs_mkstack(PyObject **small_stack, Py_ssize_t small_stack_size,
|
|||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < n; ++i) {
|
||||
stack[i] = va_arg(va, PyObject *);
|
||||
}
|
||||
|
@ -2760,15 +2710,12 @@ PyObject_CallMethodObjArgs(PyObject *callable, PyObject *name, ...)
|
|||
Py_ssize_t nargs;
|
||||
PyObject *result;
|
||||
va_list vargs;
|
||||
|
||||
if (callable == NULL || name == NULL) {
|
||||
return null_error();
|
||||
}
|
||||
|
||||
callable = PyObject_GetAttr(callable, name);
|
||||
if (callable == NULL)
|
||||
return NULL;
|
||||
|
||||
/* count the args */
|
||||
va_start(vargs, name);
|
||||
stack = objargs_mkstack(small_stack, Py_ARRAY_LENGTH(small_stack),
|
||||
|
@ -2778,34 +2725,29 @@ PyObject_CallMethodObjArgs(PyObject *callable, PyObject *name, ...)
|
|||
Py_DECREF(callable);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
result = _PyObject_FastCall(callable, stack, nargs);
|
||||
Py_DECREF(callable);
|
||||
if (stack != small_stack) {
|
||||
PyMem_Free(stack);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
PyObject *
|
||||
_PyObject_CallMethodIdObjArgs(PyObject *callable,
|
||||
struct _Py_Identifier *name, ...)
|
||||
struct _Py_Identifier *name, ...)
|
||||
{
|
||||
PyObject *small_stack[5];
|
||||
PyObject **stack;
|
||||
Py_ssize_t nargs;
|
||||
PyObject *result;
|
||||
va_list vargs;
|
||||
|
||||
if (callable == NULL || name == NULL) {
|
||||
return null_error();
|
||||
}
|
||||
|
||||
callable = _PyObject_GetAttrId(callable, name);
|
||||
if (callable == NULL)
|
||||
return NULL;
|
||||
|
||||
/* count the args */
|
||||
va_start(vargs, name);
|
||||
stack = objargs_mkstack(small_stack, Py_ARRAY_LENGTH(small_stack),
|
||||
|
@ -2815,13 +2757,11 @@ _PyObject_CallMethodIdObjArgs(PyObject *callable,
|
|||
Py_DECREF(callable);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
result = _PyObject_FastCall(callable, stack, nargs);
|
||||
Py_DECREF(callable);
|
||||
if (stack != small_stack) {
|
||||
PyMem_Free(stack);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -2833,11 +2773,9 @@ PyObject_CallFunctionObjArgs(PyObject *callable, ...)
|
|||
Py_ssize_t nargs;
|
||||
PyObject *result;
|
||||
va_list vargs;
|
||||
|
||||
if (callable == NULL) {
|
||||
return null_error();
|
||||
}
|
||||
|
||||
/* count the args */
|
||||
va_start(vargs, callable);
|
||||
stack = objargs_mkstack(small_stack, Py_ARRAY_LENGTH(small_stack),
|
||||
|
@ -2846,18 +2784,13 @@ PyObject_CallFunctionObjArgs(PyObject *callable, ...)
|
|||
if (stack == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
result = _PyObject_FastCall(callable, stack, nargs);
|
||||
if (stack != small_stack) {
|
||||
PyMem_Free(stack);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/* isinstance(), issubclass() */
|
||||
|
||||
/* abstract_get_bases() has logically 4 return states:
|
||||
*
|
||||
* 1. getattr(cls, '__bases__') could raise an AttributeError
|
||||
|
@ -2887,7 +2820,6 @@ abstract_get_bases(PyObject *cls)
|
|||
{
|
||||
_Py_IDENTIFIER(__bases__);
|
||||
PyObject *bases;
|
||||
|
||||
Py_ALLOW_RECURSION
|
||||
bases = _PyObject_GetAttrId(cls, &PyId___bases__);
|
||||
Py_END_ALLOW_RECURSION
|
||||
|
@ -2903,14 +2835,12 @@ abstract_get_bases(PyObject *cls)
|
|||
return bases;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
abstract_issubclass(PyObject *derived, PyObject *cls)
|
||||
{
|
||||
PyObject *bases = NULL;
|
||||
Py_ssize_t i, n;
|
||||
int r = 0;
|
||||
|
||||
while (1) {
|
||||
if (derived == cls)
|
||||
return 1;
|
||||
|
@ -2961,7 +2891,6 @@ recursive_isinstance(PyObject *inst, PyObject *cls)
|
|||
PyObject *icls;
|
||||
int retval = 0;
|
||||
_Py_IDENTIFIER(__class__);
|
||||
|
||||
if (PyType_Check(cls)) {
|
||||
retval = PyObject_TypeCheck(inst, (PyTypeObject *)cls);
|
||||
if (retval == 0) {
|
||||
|
@ -2998,7 +2927,6 @@ recursive_isinstance(PyObject *inst, PyObject *cls)
|
|||
Py_DECREF(icls);
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
@ -3007,21 +2935,17 @@ PyObject_IsInstance(PyObject *inst, PyObject *cls)
|
|||
{
|
||||
_Py_IDENTIFIER(__instancecheck__);
|
||||
PyObject *checker;
|
||||
|
||||
/* Quick test for an exact match */
|
||||
if (Py_TYPE(inst) == (PyTypeObject *)cls)
|
||||
return 1;
|
||||
|
||||
/* We know what type's __instancecheck__ does. */
|
||||
if (PyType_CheckExact(cls)) {
|
||||
return recursive_isinstance(inst, cls);
|
||||
}
|
||||
|
||||
if (PyTuple_Check(cls)) {
|
||||
Py_ssize_t i;
|
||||
Py_ssize_t n;
|
||||
int r = 0;
|
||||
|
||||
if (Py_EnterRecursiveCall(" in __instancecheck__"))
|
||||
return -1;
|
||||
n = PyTuple_GET_SIZE(cls);
|
||||
|
@ -3035,7 +2959,6 @@ PyObject_IsInstance(PyObject *inst, PyObject *cls)
|
|||
Py_LeaveRecursiveCall();
|
||||
return r;
|
||||
}
|
||||
|
||||
checker = _PyObject_LookupSpecial(cls, &PyId___instancecheck__);
|
||||
if (checker != NULL) {
|
||||
PyObject *res;
|
||||
|
@ -3073,7 +2996,6 @@ recursive_issubclass(PyObject *derived, PyObject *cls)
|
|||
"issubclass() arg 2 must be a class"
|
||||
" or tuple of classes"))
|
||||
return -1;
|
||||
|
||||
return abstract_issubclass(derived, cls);
|
||||
}
|
||||
|
||||
|
@ -3082,7 +3004,6 @@ PyObject_IsSubclass(PyObject *derived, PyObject *cls)
|
|||
{
|
||||
_Py_IDENTIFIER(__subclasscheck__);
|
||||
PyObject *checker;
|
||||
|
||||
/* We know what type's __subclasscheck__ does. */
|
||||
if (PyType_CheckExact(cls)) {
|
||||
/* Quick test for an exact match */
|
||||
|
@ -3090,12 +3011,10 @@ PyObject_IsSubclass(PyObject *derived, PyObject *cls)
|
|||
return 1;
|
||||
return recursive_issubclass(derived, cls);
|
||||
}
|
||||
|
||||
if (PyTuple_Check(cls)) {
|
||||
Py_ssize_t i;
|
||||
Py_ssize_t n;
|
||||
int r = 0;
|
||||
|
||||
if (Py_EnterRecursiveCall(" in __subclasscheck__"))
|
||||
return -1;
|
||||
n = PyTuple_GET_SIZE(cls);
|
||||
|
@ -3109,7 +3028,6 @@ PyObject_IsSubclass(PyObject *derived, PyObject *cls)
|
|||
Py_LeaveRecursiveCall();
|
||||
return r;
|
||||
}
|
||||
|
||||
checker = _PyObject_LookupSpecial(cls, &PyId___subclasscheck__);
|
||||
if (checker != NULL) {
|
||||
PyObject *res;
|
||||
|
@ -3145,7 +3063,6 @@ _PyObject_RealIsSubclass(PyObject *derived, PyObject *cls)
|
|||
return recursive_issubclass(derived, cls);
|
||||
}
|
||||
|
||||
|
||||
PyObject *
|
||||
PyObject_GetIter(PyObject *o)
|
||||
{
|
||||
|
@ -3190,7 +3107,6 @@ PyIter_Next(PyObject *iter)
|
|||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Flatten a sequence of bytes() objects into a C array of
|
||||
* NULL terminated string pointers with a NULL char* terminating the array.
|
||||
|
@ -3206,18 +3122,14 @@ _PySequence_BytesToCharpArray(PyObject* self)
|
|||
Py_ssize_t i, argc;
|
||||
PyObject *item = NULL;
|
||||
Py_ssize_t size;
|
||||
|
||||
argc = PySequence_Size(self);
|
||||
if (argc == -1)
|
||||
return NULL;
|
||||
|
||||
assert(argc >= 0);
|
||||
|
||||
if ((size_t)argc > (PY_SSIZE_T_MAX-sizeof(char *)) / sizeof(char *)) {
|
||||
PyErr_NoMemory();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
array = PyMem_Malloc((argc + 1) * sizeof(char *));
|
||||
if (array == NULL) {
|
||||
PyErr_NoMemory();
|
||||
|
@ -3247,16 +3159,13 @@ _PySequence_BytesToCharpArray(PyObject* self)
|
|||
Py_DECREF(item);
|
||||
}
|
||||
array[argc] = NULL;
|
||||
|
||||
return array;
|
||||
|
||||
fail:
|
||||
Py_XDECREF(item);
|
||||
_Py_FreeCharPArray(array);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* Free's a NULL terminated char** array of C strings. */
|
||||
void
|
||||
_Py_FreeCharPArray(char *const array[])
|
||||
|
|
2
third_party/python/Objects/bytes_methods.c
vendored
2
third_party/python/Objects/bytes_methods.c
vendored
|
@ -726,7 +726,7 @@ tailmatch(const char *str, Py_ssize_t len, PyObject *substr,
|
|||
}
|
||||
if (end - start < slen)
|
||||
goto notfound;
|
||||
if (memcmp(str + start, sub, slen) != 0)
|
||||
if (bcmp(str + start, sub, slen) != 0)
|
||||
goto notfound;
|
||||
|
||||
PyBuffer_Release(&sub_view);
|
||||
|
|
15
third_party/python/Objects/bytesobject.c
vendored
15
third_party/python/Objects/bytesobject.c
vendored
|
@ -135,13 +135,11 @@ PyBytes_FromStringAndSize(const char *str, Py_ssize_t size)
|
|||
Py_INCREF(op);
|
||||
return (PyObject *)op;
|
||||
}
|
||||
|
||||
op = (PyBytesObject *)_PyBytes_FromSize(size, 0);
|
||||
if (op == NULL)
|
||||
return NULL;
|
||||
if (str == NULL)
|
||||
return (PyObject *) op;
|
||||
|
||||
memcpy(op->ob_sval, str, size);
|
||||
/* share short strings */
|
||||
if (size == 1) {
|
||||
|
@ -156,7 +154,6 @@ PyBytes_FromString(const char *str)
|
|||
{
|
||||
size_t size;
|
||||
PyBytesObject *op;
|
||||
|
||||
assert(str != NULL);
|
||||
size = strlen(str);
|
||||
if (size > PY_SSIZE_T_MAX - PyBytesObject_SIZE) {
|
||||
|
@ -178,7 +175,6 @@ PyBytes_FromString(const char *str)
|
|||
Py_INCREF(op);
|
||||
return (PyObject *)op;
|
||||
}
|
||||
|
||||
/* Inline PyObject_NewVar */
|
||||
op = (PyBytesObject *)PyObject_MALLOC(PyBytesObject_SIZE + size);
|
||||
if (op == NULL)
|
||||
|
@ -1563,21 +1559,14 @@ bytes_item(PyBytesObject *a, Py_ssize_t i)
|
|||
return PyLong_FromLong((unsigned char)a->ob_sval[i]);
|
||||
}
|
||||
|
||||
static int
|
||||
static inline int
|
||||
bytes_compare_eq(PyBytesObject *a, PyBytesObject *b)
|
||||
{
|
||||
int cmp;
|
||||
Py_ssize_t len;
|
||||
|
||||
len = Py_SIZE(a);
|
||||
if (Py_SIZE(b) != len)
|
||||
return 0;
|
||||
|
||||
if (a->ob_sval[0] != b->ob_sval[0])
|
||||
return 0;
|
||||
|
||||
cmp = memcmp(a->ob_sval, b->ob_sval, len);
|
||||
return (cmp == 0);
|
||||
return !bcmp(a->ob_sval, b->ob_sval, len);
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
|
|
5
third_party/python/Objects/dict-common.h
vendored
5
third_party/python/Objects/dict-common.h
vendored
|
@ -11,8 +11,9 @@ typedef struct {
|
|||
PyObject *me_value; /* This field is only meaningful for combined tables */
|
||||
} PyDictKeyEntry;
|
||||
|
||||
/* dict_lookup_func() returns index of entry which can be used like DK_ENTRIES(dk)[index].
|
||||
* -1 when no entry found, -3 when compare raises error.
|
||||
/* dict_lookup_func() returns index of entry which can be used like
|
||||
* DK_ENTRIES(dk)[index]. -1 when no entry found, -3 when compare raises
|
||||
* error.
|
||||
*/
|
||||
typedef Py_ssize_t (*dict_lookup_func)
|
||||
(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject ***value_addr,
|
||||
|
|
60
third_party/python/Objects/dictobject.c
vendored
60
third_party/python/Objects/dictobject.c
vendored
|
@ -4,6 +4,10 @@
|
|||
│ Python 3 │
|
||||
│ https://docs.python.org/3/license.html │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/likely.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "third_party/python/Include/abstract.h"
|
||||
#include "third_party/python/Include/boolobject.h"
|
||||
#include "third_party/python/Include/longobject.h"
|
||||
|
@ -298,7 +302,6 @@ _PyDict_DebugMallocStats(FILE *out)
|
|||
"free PyDictObject", numfree, sizeof(PyDictObject));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PyDict_Fini(void)
|
||||
{
|
||||
|
@ -335,7 +338,6 @@ dk_get_index(PyDictKeysObject *keys, Py_ssize_t i)
|
|||
{
|
||||
Py_ssize_t s = DK_SIZE(keys);
|
||||
Py_ssize_t ix;
|
||||
|
||||
if (s <= 0xff) {
|
||||
int8_t *indices = (int8_t*)(keys->dk_indices);
|
||||
ix = indices[i];
|
||||
|
@ -672,8 +674,7 @@ lookdict_index(PyDictKeysObject *k, Py_hash_t hash, Py_ssize_t index)
|
|||
return DKIX_EMPTY;
|
||||
}
|
||||
}
|
||||
assert(0); /* NOT REACHED */
|
||||
return DKIX_ERROR;
|
||||
unreachable;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -811,8 +812,7 @@ top:
|
|||
}
|
||||
}
|
||||
}
|
||||
assert(0); /* NOT REACHED */
|
||||
return 0;
|
||||
unreachable;
|
||||
}
|
||||
|
||||
/* Specialized version for string-only keys */
|
||||
|
@ -885,14 +885,13 @@ lookdict_unicode(PyDictObject *mp, PyObject *key,
|
|||
return ix;
|
||||
}
|
||||
}
|
||||
assert(0); /* NOT REACHED */
|
||||
return 0;
|
||||
unreachable;
|
||||
}
|
||||
|
||||
/* Faster version of lookdict_unicode when it is known that no <dummy> keys
|
||||
* will be present. */
|
||||
static Py_ssize_t
|
||||
lookdict_unicode_nodummy(PyDictObject *mp, PyObject *key,
|
||||
lookdict_unicode_nodummy(PyDictObject *restrict mp, PyObject *restrict key,
|
||||
Py_hash_t hash, PyObject ***value_addr,
|
||||
Py_ssize_t *hashpos)
|
||||
{
|
||||
|
@ -900,29 +899,28 @@ lookdict_unicode_nodummy(PyDictObject *mp, PyObject *key,
|
|||
size_t mask = DK_MASK(mp->ma_keys);
|
||||
Py_ssize_t ix;
|
||||
PyDictKeyEntry *ep, *ep0 = DK_ENTRIES(mp->ma_keys);
|
||||
|
||||
assert(mp->ma_values == NULL);
|
||||
/* Make sure this function doesn't have to handle non-unicode keys,
|
||||
including subclasses of str; e.g., one reason to subclass
|
||||
unicodes is to override __eq__, and for speed we don't cater to
|
||||
that here. */
|
||||
if (!PyUnicode_CheckExact(key)) {
|
||||
if (UNLIKELY(!PyUnicode_CheckExact(key)) /* 0.00001% taken */) {
|
||||
mp->ma_keys->dk_lookup = lookdict;
|
||||
return lookdict(mp, key, hash, value_addr, hashpos);
|
||||
}
|
||||
i = (size_t)hash & mask;
|
||||
ix = dk_get_index(mp->ma_keys, i);
|
||||
assert (ix != DKIX_DUMMY);
|
||||
if (ix == DKIX_EMPTY) {
|
||||
assert(ix != DKIX_DUMMY);
|
||||
if (UNLIKELY(ix == DKIX_EMPTY)) { /* 4% taken */
|
||||
if (hashpos != NULL)
|
||||
*hashpos = i;
|
||||
*value_addr = NULL;
|
||||
return DKIX_EMPTY;
|
||||
}
|
||||
ep = &ep0[ix];
|
||||
assert(ep->me_key != NULL);
|
||||
assert(ep->me_key);
|
||||
assert(PyUnicode_CheckExact(ep->me_key));
|
||||
if (ep->me_key == key ||
|
||||
if (ep->me_key == key || /* 70.671% taken */
|
||||
(ep->me_hash == hash && unicode_eq(ep->me_key, key))) {
|
||||
if (hashpos != NULL)
|
||||
*hashpos = i;
|
||||
|
@ -933,16 +931,17 @@ lookdict_unicode_nodummy(PyDictObject *mp, PyObject *key,
|
|||
perturb >>= PERTURB_SHIFT;
|
||||
i = mask & ((i << 2) + i + perturb + 1);
|
||||
ix = dk_get_index(mp->ma_keys, i);
|
||||
assert (ix != DKIX_DUMMY);
|
||||
if (ix == DKIX_EMPTY) {
|
||||
assert(ix != DKIX_DUMMY);
|
||||
if (UNLIKELY(ix == DKIX_EMPTY)) {
|
||||
if (hashpos != NULL)
|
||||
*hashpos = i;
|
||||
*value_addr = NULL;
|
||||
return DKIX_EMPTY;
|
||||
}
|
||||
ep = &ep0[ix];
|
||||
assert(ep->me_key != NULL && PyUnicode_CheckExact(ep->me_key));
|
||||
if (ep->me_key == key ||
|
||||
assert(ep->me_key);
|
||||
assert(PyUnicode_CheckExact(ep->me_key));
|
||||
if (LIKELY(ep->me_key == key) || /* 99.8697% taken (interning?) */
|
||||
(ep->me_hash == hash && unicode_eq(ep->me_key, key))) {
|
||||
if (hashpos != NULL)
|
||||
*hashpos = i;
|
||||
|
@ -950,8 +949,7 @@ lookdict_unicode_nodummy(PyDictObject *mp, PyObject *key,
|
|||
return ix;
|
||||
}
|
||||
}
|
||||
assert(0); /* NOT REACHED */
|
||||
return 0;
|
||||
unreachable;
|
||||
}
|
||||
|
||||
/* Version of lookdict for split tables.
|
||||
|
@ -1017,8 +1015,7 @@ lookdict_split(PyDictObject *mp, PyObject *key,
|
|||
return ix;
|
||||
}
|
||||
}
|
||||
assert(0); /* NOT REACHED */
|
||||
return 0;
|
||||
unreachable;
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -1456,10 +1453,13 @@ PyDict_GetItem(PyObject *op, PyObject *key)
|
|||
else {
|
||||
ix = (mp->ma_keys->dk_lookup)(mp, key, hash, &value_addr, NULL);
|
||||
if (ix < 0) {
|
||||
PyErr_Clear();
|
||||
/* [jart] don't clear the error if there is no error */
|
||||
if (UNLIKELY(ix == DKIX_ERROR))
|
||||
PyErr_Clear();
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return *value_addr;
|
||||
}
|
||||
|
||||
|
@ -1540,25 +1540,23 @@ _PyDict_LoadGlobal(PyDictObject *globals, PyDictObject *builtins, PyObject *key)
|
|||
Py_ssize_t ix;
|
||||
Py_hash_t hash;
|
||||
PyObject **value_addr;
|
||||
|
||||
if (!PyUnicode_CheckExact(key) ||
|
||||
if (UNLIKELY(!PyUnicode_CheckExact(key)) ||
|
||||
(hash = ((PyASCIIObject *) key)->hash) == -1)
|
||||
{
|
||||
hash = PyObject_Hash(key);
|
||||
if (hash == -1)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* namespace 1: globals */
|
||||
ix = globals->ma_keys->dk_lookup(globals, key, hash, &value_addr, NULL);
|
||||
if (ix == DKIX_ERROR)
|
||||
if (UNLIKELY(ix == DKIX_ERROR)) /* 0% taken */
|
||||
return NULL;
|
||||
if (ix != DKIX_EMPTY && *value_addr != NULL)
|
||||
if (LIKELY(ix != DKIX_EMPTY) && /* 90.3814% taken */
|
||||
LIKELY(*value_addr != NULL)) /* 100% taken */
|
||||
return *value_addr;
|
||||
|
||||
/* namespace 2: builtins */
|
||||
ix = builtins->ma_keys->dk_lookup(builtins, key, hash, &value_addr, NULL);
|
||||
if (ix < 0)
|
||||
if (UNLIKELY(ix < 0)) /* 5.9974e-05% taken */
|
||||
return NULL;
|
||||
return *value_addr;
|
||||
}
|
||||
|
|
35
third_party/python/Objects/floatobject.c
vendored
35
third_party/python/Objects/floatobject.c
vendored
|
@ -67,22 +67,17 @@ information about the precision and internal representation. Please study\n\
|
|||
your system's :file:`float.h` for more information.");
|
||||
|
||||
static PyStructSequence_Field floatinfo_fields[] = {
|
||||
{"max", "DBL_MAX -- maximum representable finite float"},
|
||||
{"max_exp", "DBL_MAX_EXP -- maximum int e such that radix**(e-1) "
|
||||
"is representable"},
|
||||
{"max_10_exp", "DBL_MAX_10_EXP -- maximum int e such that 10**e "
|
||||
"is representable"},
|
||||
{"min", "DBL_MIN -- Minimum positive normalized float"},
|
||||
{"min_exp", "DBL_MIN_EXP -- minimum int e such that radix**(e-1) "
|
||||
"is a normalized float"},
|
||||
{"min_10_exp", "DBL_MIN_10_EXP -- minimum int e such that 10**e is "
|
||||
"a normalized"},
|
||||
{"dig", "DBL_DIG -- digits"},
|
||||
{"mant_dig", "DBL_MANT_DIG -- mantissa digits"},
|
||||
{"epsilon", "DBL_EPSILON -- Difference between 1 and the next "
|
||||
"representable float"},
|
||||
{"radix", "FLT_RADIX -- radix of exponent"},
|
||||
{"rounds", "FLT_ROUNDS -- rounding mode"},
|
||||
{"max", PyDoc_STR("DBL_MAX -- maximum representable finite float")},
|
||||
{"max_exp", PyDoc_STR("DBL_MAX_EXP -- maximum int e such that radix**(e-1) is representable")},
|
||||
{"max_10_exp", PyDoc_STR("DBL_MAX_10_EXP -- maximum int e such that 10**e is representable")},
|
||||
{"min", PyDoc_STR("DBL_MIN -- Minimum positive normalized float")},
|
||||
{"min_exp", PyDoc_STR("DBL_MIN_EXP -- minimum int e such that radix**(e-1) is a normalized float")},
|
||||
{"min_10_exp", PyDoc_STR("DBL_MIN_10_EXP -- minimum int e such that 10**e is a normalized")},
|
||||
{"dig", PyDoc_STR("DBL_DIG -- digits")},
|
||||
{"mant_dig", PyDoc_STR("DBL_MANT_DIG -- mantissa digits")},
|
||||
{"epsilon", PyDoc_STR("DBL_EPSILON -- Difference between 1 and the next representable float")},
|
||||
{"radix", PyDoc_STR("FLT_RADIX -- radix of exponent")},
|
||||
{"rounds", PyDoc_STR("FLT_ROUNDS -- rounding mode")},
|
||||
{0}
|
||||
};
|
||||
|
||||
|
@ -1944,9 +1939,9 @@ _PyFloat_Init(void)
|
|||
#if SIZEOF_DOUBLE == 8
|
||||
{
|
||||
double x = 9006104071832581.0;
|
||||
if (memcmp(&x, "\x43\x3f\xff\x01\x02\x03\x04\x05", 8) == 0)
|
||||
if (bcmp(&x, "\x43\x3f\xff\x01\x02\x03\x04\x05", 8) == 0)
|
||||
detected_double_format = ieee_big_endian_format;
|
||||
else if (memcmp(&x, "\x05\x04\x03\x02\x01\xff\x3f\x43", 8) == 0)
|
||||
else if (bcmp(&x, "\x05\x04\x03\x02\x01\xff\x3f\x43", 8) == 0)
|
||||
detected_double_format = ieee_little_endian_format;
|
||||
else
|
||||
detected_double_format = unknown_format;
|
||||
|
@ -1958,9 +1953,9 @@ _PyFloat_Init(void)
|
|||
#if SIZEOF_FLOAT == 4
|
||||
{
|
||||
float y = 16711938.0;
|
||||
if (memcmp(&y, "\x4b\x7f\x01\x02", 4) == 0)
|
||||
if (bcmp(&y, "\x4b\x7f\x01\x02", 4) == 0)
|
||||
detected_float_format = ieee_big_endian_format;
|
||||
else if (memcmp(&y, "\x02\x01\x7f\x4b", 4) == 0)
|
||||
else if (bcmp(&y, "\x02\x01\x7f\x4b", 4) == 0)
|
||||
detected_float_format = ieee_little_endian_format;
|
||||
else
|
||||
detected_float_format = unknown_format;
|
||||
|
|
18
third_party/python/Objects/frameobject.c
vendored
18
third_party/python/Objects/frameobject.c
vendored
|
@ -4,6 +4,7 @@
|
|||
│ Python 3 │
|
||||
│ https://docs.python.org/3/license.html │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/likely.h"
|
||||
#include "third_party/python/Include/abstract.h"
|
||||
#include "third_party/python/Include/cellobject.h"
|
||||
#include "third_party/python/Include/code.h"
|
||||
|
@ -231,8 +232,8 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno, void *Py_UNUSED(ignore
|
|||
* whether we're in a 'finally' block at each blockstack level. */
|
||||
f_lasti_setup_addr = -1;
|
||||
new_lasti_setup_addr = -1;
|
||||
memset(blockstack, '\0', sizeof(blockstack));
|
||||
memset(in_finally, '\0', sizeof(in_finally));
|
||||
bzero(blockstack, sizeof(blockstack));
|
||||
bzero(in_finally, sizeof(in_finally));
|
||||
blockstack_top = 0;
|
||||
for (addr = 0; addr < code_len; addr += sizeof(_Py_CODEUNIT)) {
|
||||
unsigned char op = code[addr];
|
||||
|
@ -456,13 +457,12 @@ static PyGetSetDef frame_getsetlist[] = {
|
|||
frames could provoke free_list into growing without bound.
|
||||
*/
|
||||
|
||||
static PyFrameObject *free_list = NULL;
|
||||
static int numfree = 0; /* number of frames currently in free_list */
|
||||
/* max value for numfree */
|
||||
static int numfree;
|
||||
static PyFrameObject *free_list;
|
||||
#define PyFrame_MAXFREELIST 200
|
||||
|
||||
static void
|
||||
frame_dealloc(PyFrameObject *f)
|
||||
frame_dealloc(PyFrameObject *restrict f)
|
||||
{
|
||||
PyObject **p, **valuestack;
|
||||
PyCodeObject *co;
|
||||
|
@ -475,7 +475,7 @@ frame_dealloc(PyFrameObject *f)
|
|||
Py_CLEAR(*p);
|
||||
|
||||
/* Free stack */
|
||||
if (f->f_stacktop != NULL) {
|
||||
if (UNLIKELY(f->f_stacktop != NULL)) { /* 0% taken */
|
||||
for (p = valuestack; p < f->f_stacktop; p++)
|
||||
Py_XDECREF(*p);
|
||||
}
|
||||
|
@ -715,8 +715,7 @@ PyFrame_New(PyThreadState *tstate, PyCodeObject *code, PyObject *globals,
|
|||
extras = code->co_stacksize + code->co_nlocals + ncells +
|
||||
nfrees;
|
||||
if (free_list == NULL) {
|
||||
f = PyObject_GC_NewVar(PyFrameObject, &PyFrame_Type,
|
||||
extras);
|
||||
f = PyObject_GC_NewVar(PyFrameObject, &PyFrame_Type, extras);
|
||||
if (f == NULL) {
|
||||
Py_DECREF(builtins);
|
||||
return NULL;
|
||||
|
@ -1024,7 +1023,6 @@ int
|
|||
PyFrame_ClearFreeList(void)
|
||||
{
|
||||
int freelist_size = numfree;
|
||||
|
||||
while (free_list != NULL) {
|
||||
PyFrameObject *f = free_list;
|
||||
free_list = free_list->f_back;
|
||||
|
|
4
third_party/python/Objects/listobject.c
vendored
4
third_party/python/Objects/listobject.c
vendored
|
@ -415,10 +415,8 @@ list_contains(PyListObject *a, PyObject *el)
|
|||
{
|
||||
Py_ssize_t i;
|
||||
int cmp;
|
||||
|
||||
for (i = 0, cmp = 0 ; cmp == 0 && i < Py_SIZE(a); ++i)
|
||||
cmp = PyObject_RichCompareBool(el, PyList_GET_ITEM(a, i),
|
||||
Py_EQ);
|
||||
cmp = PyObject_RichCompareBool(el, PyList_GET_ITEM(a, i), Py_EQ);
|
||||
return cmp;
|
||||
}
|
||||
|
||||
|
|
149
third_party/python/Objects/longobject.c
vendored
149
third_party/python/Objects/longobject.c
vendored
|
@ -5,6 +5,7 @@
|
|||
│ https://docs.python.org/3/license.html │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/bits/popcnt.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/log/check.h"
|
||||
|
@ -31,10 +32,10 @@
|
|||
/* XXX The functional organization of this file is terrible */
|
||||
|
||||
#ifndef NSMALLPOSINTS
|
||||
#define NSMALLPOSINTS 257
|
||||
#define NSMALLPOSINTS 257L
|
||||
#endif
|
||||
#ifndef NSMALLNEGINTS
|
||||
#define NSMALLNEGINTS 5
|
||||
#define NSMALLNEGINTS 5L
|
||||
#endif
|
||||
|
||||
/* convert a PyLong of size 1, 0 or -1 to an sdigit */
|
||||
|
@ -54,7 +55,7 @@ static PyLongObject small_ints[NSMALLNEGINTS + NSMALLPOSINTS];
|
|||
Py_ssize_t quick_int_allocs, quick_neg_int_allocs;
|
||||
#endif
|
||||
|
||||
static PyObject *
|
||||
static inline PyObject *
|
||||
get_small_int(sdigit ival)
|
||||
{
|
||||
PyObject *v;
|
||||
|
@ -621,14 +622,12 @@ PyLong_AsUnsignedLong(PyObject *vv)
|
|||
|
||||
/* Get a C size_t from an int object. Returns (size_t)-1 and sets
|
||||
an error condition if overflow occurs. */
|
||||
|
||||
size_t
|
||||
PyLong_AsSize_t(PyObject *vv)
|
||||
{
|
||||
PyLongObject *v;
|
||||
size_t x, prev;
|
||||
Py_ssize_t i;
|
||||
|
||||
if (vv == NULL) {
|
||||
PyErr_BadInternalCall();
|
||||
return (size_t) -1;
|
||||
|
@ -637,7 +636,6 @@ PyLong_AsSize_t(PyObject *vv)
|
|||
PyErr_SetString(PyExc_TypeError, "an integer is required");
|
||||
return (size_t)-1;
|
||||
}
|
||||
|
||||
v = (PyLongObject *)vv;
|
||||
i = Py_SIZE(v);
|
||||
x = 0;
|
||||
|
@ -664,7 +662,6 @@ PyLong_AsSize_t(PyObject *vv)
|
|||
|
||||
/* Get a C unsigned long int from an int object, ignoring the high bits.
|
||||
Returns -1 and sets an error condition if an error occurs. */
|
||||
|
||||
static unsigned long
|
||||
_PyLong_AsUnsignedLongMask(PyObject *vv)
|
||||
{
|
||||
|
@ -672,7 +669,6 @@ _PyLong_AsUnsignedLongMask(PyObject *vv)
|
|||
unsigned long x;
|
||||
Py_ssize_t i;
|
||||
int sign;
|
||||
|
||||
if (vv == NULL || !PyLong_Check(vv)) {
|
||||
PyErr_BadInternalCall();
|
||||
return (unsigned long) -1;
|
||||
|
@ -700,20 +696,16 @@ PyLong_AsUnsignedLongMask(PyObject *op)
|
|||
{
|
||||
PyLongObject *lo;
|
||||
unsigned long val;
|
||||
|
||||
if (op == NULL) {
|
||||
PyErr_BadInternalCall();
|
||||
return (unsigned long)-1;
|
||||
}
|
||||
|
||||
if (PyLong_Check(op)) {
|
||||
return _PyLong_AsUnsignedLongMask(op);
|
||||
}
|
||||
|
||||
lo = _PyLong_FromNbInt(op);
|
||||
if (lo == NULL)
|
||||
return (unsigned long)-1;
|
||||
|
||||
val = _PyLong_AsUnsignedLongMask((PyObject *)lo);
|
||||
Py_DECREF(lo);
|
||||
return val;
|
||||
|
@ -723,38 +715,57 @@ int
|
|||
_PyLong_Sign(PyObject *vv)
|
||||
{
|
||||
PyLongObject *v = (PyLongObject *)vv;
|
||||
|
||||
assert(v != NULL);
|
||||
assert(PyLong_Check(v));
|
||||
|
||||
return Py_SIZE(v) == 0 ? 0 : (Py_SIZE(v) < 0 ? -1 : 1);
|
||||
}
|
||||
|
||||
/* bits_in_digit(d) returns the unique integer k such that 2**(k-1) <= d <
|
||||
2**k if d is nonzero, else 0. */
|
||||
static inline int
|
||||
bits_in_digit(digit d)
|
||||
{
|
||||
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
|
||||
/* [jart] faster bit scanning */
|
||||
if (d) {
|
||||
_Static_assert(sizeof(digit) <= sizeof(unsigned), "");
|
||||
return (__builtin_clz(d) ^ (sizeof(unsigned) * CHAR_BIT - 1)) + 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static const unsigned char BitLengthTable[32] = {
|
||||
0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
|
||||
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
|
||||
};
|
||||
int d_bits = 0;
|
||||
while (d >= 32) {
|
||||
d_bits += 6;
|
||||
d >>= 6;
|
||||
}
|
||||
d_bits += (int)BitLengthTable[d];
|
||||
return d_bits;
|
||||
#endif
|
||||
}
|
||||
|
||||
size_t
|
||||
_PyLong_NumBits(PyObject *vv)
|
||||
{
|
||||
PyLongObject *v = (PyLongObject *)vv;
|
||||
size_t result = 0;
|
||||
Py_ssize_t ndigits;
|
||||
|
||||
assert(v != NULL);
|
||||
assert(PyLong_Check(v));
|
||||
ndigits = Py_ABS(Py_SIZE(v));
|
||||
assert(ndigits == 0 || v->ob_digit[ndigits - 1] != 0);
|
||||
if (ndigits > 0) {
|
||||
digit msd = v->ob_digit[ndigits - 1];
|
||||
if ((size_t)(ndigits - 1) > SIZE_MAX / (size_t)PyLong_SHIFT)
|
||||
goto Overflow;
|
||||
/* [jart] faster bit scanning */
|
||||
result = (size_t)(ndigits - 1) * (size_t)PyLong_SHIFT;
|
||||
do {
|
||||
++result;
|
||||
if (result == 0)
|
||||
goto Overflow;
|
||||
msd >>= 1;
|
||||
} while (msd);
|
||||
result += bits_in_digit(v->ob_digit[ndigits - 1]);
|
||||
}
|
||||
return result;
|
||||
|
||||
Overflow:
|
||||
PyErr_SetString(PyExc_OverflowError, "int has too many bits "
|
||||
"to express in a platform size_t");
|
||||
|
@ -1437,26 +1448,6 @@ PyLong_AsLongLongAndOverflow(PyObject *vv, int *overflow)
|
|||
Py_RETURN_NOTIMPLEMENTED; \
|
||||
} while(0)
|
||||
|
||||
/* bits_in_digit(d) returns the unique integer k such that 2**(k-1) <= d <
|
||||
2**k if d is nonzero, else 0. */
|
||||
|
||||
static const unsigned char BitLengthTable[32] = {
|
||||
0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
|
||||
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
|
||||
};
|
||||
|
||||
static int
|
||||
bits_in_digit(digit d)
|
||||
{
|
||||
int d_bits = 0;
|
||||
while (d >= 32) {
|
||||
d_bits += 6;
|
||||
d >>= 6;
|
||||
}
|
||||
d_bits += (int)BitLengthTable[d];
|
||||
return d_bits;
|
||||
}
|
||||
|
||||
/* x[0:m] and y[0:n] are digit vectors, LSD first, m >= n required. x[0:n]
|
||||
* is modified in place, by adding y to it. Carries are propagated as far as
|
||||
* x[m-1], and the remaining carry (0 or 1) is returned.
|
||||
|
@ -1611,6 +1602,7 @@ long_to_decimal_string_internal(PyObject *aa,
|
|||
PyErr_BadInternalCall();
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_a = Py_ABS(Py_SIZE(a));
|
||||
negative = Py_SIZE(a) < 0;
|
||||
|
||||
|
@ -1647,8 +1639,7 @@ long_to_decimal_string_internal(PyObject *aa,
|
|||
for (j = 0; j < size; j++) {
|
||||
twodigits z = (twodigits)pout[j] << PyLong_SHIFT | hi;
|
||||
hi = (digit)(z / _PyLong_DECIMAL_BASE);
|
||||
pout[j] = (digit)(z - (twodigits)hi *
|
||||
_PyLong_DECIMAL_BASE);
|
||||
pout[j] = (digit)(z - (twodigits)hi * _PyLong_DECIMAL_BASE);
|
||||
}
|
||||
while (hi) {
|
||||
pout[size++] = hi % _PyLong_DECIMAL_BASE;
|
||||
|
@ -2345,7 +2336,7 @@ digit beyond the first.
|
|||
* being stored into.
|
||||
*/
|
||||
fsize_z = digits * log_base_BASE[base] + 1;
|
||||
if (fsize_z > MAX_LONG_DIGITS) {
|
||||
if (fsize_z > (double)(MAX_LONG_DIGITS/2)) {
|
||||
/* The same exception as in _PyLong_New(). */
|
||||
PyErr_SetString(PyExc_OverflowError,
|
||||
"too many digits in integer");
|
||||
|
@ -2917,12 +2908,13 @@ long_dealloc(PyObject *v)
|
|||
static int
|
||||
long_compare(PyLongObject *a, PyLongObject *b)
|
||||
{
|
||||
Py_ssize_t sign;
|
||||
|
||||
if (Py_SIZE(a) != Py_SIZE(b)) {
|
||||
Py_ssize_t sign;
|
||||
sign = Py_SIZE(a) - Py_SIZE(b);
|
||||
return sign < 0 ? -1 : sign > 0 ? 1 : 0;
|
||||
}
|
||||
else {
|
||||
int sign;
|
||||
Py_ssize_t i = Py_ABS(Py_SIZE(a));
|
||||
while (--i >= 0 && a->ob_digit[i] == b->ob_digit[i])
|
||||
;
|
||||
|
@ -2933,8 +2925,8 @@ long_compare(PyLongObject *a, PyLongObject *b)
|
|||
if (Py_SIZE(a) < 0)
|
||||
sign = -sign;
|
||||
}
|
||||
return sign < 0 ? -1 : sign > 0 ? 1 : 0;
|
||||
}
|
||||
return sign < 0 ? -1 : sign > 0 ? 1 : 0;
|
||||
}
|
||||
|
||||
#define TEST_COND(cond) \
|
||||
|
@ -2946,10 +2938,11 @@ long_richcompare(PyObject *self, PyObject *other, int op)
|
|||
int result;
|
||||
PyObject *v;
|
||||
CHECK_BINOP(self, other);
|
||||
if (self == other)
|
||||
if (self == other) {
|
||||
result = 0;
|
||||
else
|
||||
} else {
|
||||
result = long_compare((PyLongObject*)self, (PyLongObject*)other);
|
||||
}
|
||||
/* Convert the return value to a Boolean */
|
||||
switch (op) {
|
||||
case Py_EQ:
|
||||
|
@ -3688,7 +3681,6 @@ l_divmod(PyLongObject *v, PyLongObject *w,
|
|||
PyLongObject **pdiv, PyLongObject **pmod)
|
||||
{
|
||||
PyLongObject *div, *mod;
|
||||
|
||||
if (Py_ABS(Py_SIZE(v)) == 1 && Py_ABS(Py_SIZE(w)) == 1) {
|
||||
/* Fast path for single-digit longs */
|
||||
div = NULL;
|
||||
|
@ -5115,26 +5107,16 @@ static PyObject *
|
|||
long_bit_length(PyLongObject *v)
|
||||
{
|
||||
PyLongObject *result, *x, *y;
|
||||
Py_ssize_t ndigits, msd_bits = 0;
|
||||
digit msd;
|
||||
|
||||
Py_ssize_t ndigits, msd_bits;
|
||||
assert(v != NULL);
|
||||
assert(PyLong_Check(v));
|
||||
|
||||
ndigits = Py_ABS(Py_SIZE(v));
|
||||
if (ndigits == 0)
|
||||
return PyLong_FromLong(0);
|
||||
|
||||
msd = v->ob_digit[ndigits-1];
|
||||
while (msd >= 32) {
|
||||
msd_bits += 6;
|
||||
msd >>= 6;
|
||||
}
|
||||
msd_bits += (long)(BitLengthTable[msd]);
|
||||
|
||||
/* [jart] faster bit scanning */
|
||||
msd_bits = bits_in_digit(v->ob_digit[ndigits-1]);
|
||||
if (ndigits <= PY_SSIZE_T_MAX/PyLong_SHIFT)
|
||||
return PyLong_FromSsize_t((ndigits-1)*PyLong_SHIFT + msd_bits);
|
||||
|
||||
/* expression above may overflow; use Python integers instead */
|
||||
result = (PyLongObject *)PyLong_FromSsize_t(ndigits - 1);
|
||||
if (result == NULL)
|
||||
|
@ -5148,7 +5130,6 @@ long_bit_length(PyLongObject *v)
|
|||
goto error;
|
||||
Py_DECREF(result);
|
||||
result = y;
|
||||
|
||||
x = (PyLongObject *)PyLong_FromLong((long)msd_bits);
|
||||
if (x == NULL)
|
||||
goto error;
|
||||
|
@ -5158,9 +5139,7 @@ long_bit_length(PyLongObject *v)
|
|||
goto error;
|
||||
Py_DECREF(result);
|
||||
result = y;
|
||||
|
||||
return (PyObject *)result;
|
||||
|
||||
error:
|
||||
Py_DECREF(result);
|
||||
return NULL;
|
||||
|
@ -5175,6 +5154,31 @@ Number of bits necessary to represent self in binary.\n\
|
|||
>>> (37).bit_length()\n\
|
||||
6");
|
||||
|
||||
/* [jart] the nsa instruction */
|
||||
static PyObject *
|
||||
long_bit_count(PyLongObject *v)
|
||||
{
|
||||
Py_ssize_t digs;
|
||||
assert(v != NULL);
|
||||
assert(PyLong_Check(v));
|
||||
digs = Py_ABS(Py_SIZE(v));
|
||||
if (digs > PY_SSIZE_T_MAX/PyLong_SHIFT)
|
||||
goto Overflow;
|
||||
return PyLong_FromSize_t(_countbits(v->ob_digit, digs * sizeof(digit)));
|
||||
Overflow:
|
||||
PyErr_SetString(PyExc_OverflowError, "size_t too small");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(long_bit_count_doc,
|
||||
"int.bit_count() -> int\n\
|
||||
\n\
|
||||
Population count of integer.\n\
|
||||
>>> bin(37)\n\
|
||||
'0b100101'\n\
|
||||
>>> (37).bit_count()\n\
|
||||
3");
|
||||
|
||||
#if 0
|
||||
static PyObject *
|
||||
long_is_finite(PyObject *v)
|
||||
|
@ -5349,6 +5353,8 @@ static PyMethodDef long_methods[] = {
|
|||
"Returns self, the complex conjugate of any int."},
|
||||
{"bit_length", (PyCFunction)long_bit_length, METH_NOARGS,
|
||||
long_bit_length_doc},
|
||||
{"bit_count", (PyCFunction)long_bit_count, METH_NOARGS,
|
||||
long_bit_count_doc},
|
||||
#if 0
|
||||
{"is_finite", (PyCFunction)long_is_finite, METH_NOARGS,
|
||||
"Returns always True."},
|
||||
|
@ -5498,8 +5504,8 @@ A struct sequence that holds information about Python's\n\
|
|||
internal representation of integers. The attributes are read only.");
|
||||
|
||||
static PyStructSequence_Field int_info_fields[] = {
|
||||
{"bits_per_digit", "size of a digit in bits"},
|
||||
{"sizeof_digit", "size in bytes of the C type used to represent a digit"},
|
||||
{"bits_per_digit", PyDoc_STR("size of a digit in bits")},
|
||||
{"sizeof_digit", PyDoc_STR("size in bytes of the C type used to represent a digit")},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
|
@ -5535,7 +5541,6 @@ _PyLong_Init(void)
|
|||
#if NSMALLNEGINTS + NSMALLPOSINTS > 0
|
||||
int ival, size;
|
||||
PyLongObject *v = small_ints;
|
||||
|
||||
for (ival = -NSMALLNEGINTS; ival < NSMALLPOSINTS; ival++, v++) {
|
||||
size = (ival < 0) ? -1 : ((ival == 0) ? 0 : 1);
|
||||
if (Py_TYPE(v) == &PyLong_Type) {
|
||||
|
@ -5544,7 +5549,6 @@ _PyLong_Init(void)
|
|||
*/
|
||||
Py_ssize_t refcnt;
|
||||
PyObject* op = (PyObject*)v;
|
||||
|
||||
refcnt = Py_REFCNT(op) < 0 ? 0 : Py_REFCNT(op);
|
||||
_Py_NewReference(op);
|
||||
/* _Py_NewReference sets the ref count to 1 but
|
||||
|
@ -5566,7 +5570,6 @@ _PyLong_Init(void)
|
|||
if (PyStructSequence_InitType2(&Int_InfoType, &int_info_desc) < 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
12
third_party/python/Objects/methodobject.c
vendored
12
third_party/python/Objects/methodobject.c
vendored
|
@ -226,7 +226,8 @@ _PyCFunction_FastCallDict(PyObject *func_obj, PyObject **args, Py_ssize_t nargs,
|
|||
case METH_VARARGS | METH_KEYWORDS:
|
||||
{
|
||||
/* Slow-path: create a temporary tuple */
|
||||
PyObject *tuple;
|
||||
Py_ssize_t i;
|
||||
PyObject *item, *tuple;
|
||||
|
||||
if (!(flags & METH_KEYWORDS) && kwargs != NULL && PyDict_Size(kwargs) != 0) {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
|
@ -235,9 +236,12 @@ _PyCFunction_FastCallDict(PyObject *func_obj, PyObject **args, Py_ssize_t nargs,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
tuple = _PyStack_AsTuple(args, nargs);
|
||||
if (tuple == NULL) {
|
||||
return NULL;
|
||||
/* [jart] inlined _PyStack_AsTuple b/c profiling */
|
||||
if (!(tuple = PyTuple_New(nargs))) return 0;
|
||||
for (i = 0; i < nargs; i++) {
|
||||
item = args[i];
|
||||
Py_INCREF(item);
|
||||
PyTuple_SET_ITEM(tuple, i, item);
|
||||
}
|
||||
|
||||
if (flags & METH_KEYWORDS) {
|
||||
|
|
6
third_party/python/Objects/object.c
vendored
6
third_party/python/Objects/object.c
vendored
|
@ -63,7 +63,6 @@ void
|
|||
_PyDebug_PrintTotalRefs(void) {
|
||||
PyObject *xoptions, *value;
|
||||
_Py_IDENTIFIER(showrefcount);
|
||||
|
||||
xoptions = PySys_GetXOptions();
|
||||
if (xoptions == NULL)
|
||||
return;
|
||||
|
@ -452,7 +451,6 @@ _Py_BreakPoint(void)
|
|||
{
|
||||
}
|
||||
|
||||
|
||||
/* Heuristic checking if the object memory has been deallocated.
|
||||
Rely on the debug hooks on Python memory allocators which fills the memory
|
||||
with DEADBYTE (0xDB) when memory is deallocated.
|
||||
|
@ -770,12 +768,10 @@ do_richcompare(PyObject *v, PyObject *w, int op)
|
|||
|
||||
/* Perform a rich comparison with object result. This wraps do_richcompare()
|
||||
with a check for NULL arguments and a recursion check. */
|
||||
|
||||
PyObject *
|
||||
PyObject_RichCompare(PyObject *v, PyObject *w, int op)
|
||||
{
|
||||
PyObject *res;
|
||||
|
||||
assert(Py_LT <= op && op <= Py_GE);
|
||||
if (v == NULL || w == NULL) {
|
||||
if (!PyErr_Occurred())
|
||||
|
@ -1814,7 +1810,7 @@ _Py_NewReference(PyObject *op)
|
|||
_Py_INC_TPALLOCS(op);
|
||||
}
|
||||
|
||||
void
|
||||
noasan void
|
||||
_Py_ForgetReference(PyObject *op)
|
||||
{
|
||||
#ifdef SLOW_UNREF_CHECK
|
||||
|
|
145
third_party/python/Objects/obmalloc.c
vendored
145
third_party/python/Objects/obmalloc.c
vendored
|
@ -5,12 +5,15 @@
|
|||
│ https://docs.python.org/3/license.html │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sysv/consts/map.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
#include "third_party/dlmalloc/dlmalloc.internal.h"
|
||||
#include "third_party/python/Include/objimpl.h"
|
||||
#include "third_party/python/Include/pydebug.h"
|
||||
#include "third_party/python/Include/pyerrors.h"
|
||||
|
@ -26,18 +29,16 @@
|
|||
#define uint unsigned int /* assuming >= 16 bits */
|
||||
|
||||
/* Forward declaration */
|
||||
static void* _PyMem_DebugRawMalloc(void *ctx, size_t size);
|
||||
static void* _PyMem_DebugRawCalloc(void *ctx, size_t nelem, size_t elsize);
|
||||
static void* _PyMem_DebugRawRealloc(void *ctx, void *ptr, size_t size);
|
||||
static void _PyMem_DebugRawFree(void *ctx, void *p);
|
||||
|
||||
static void* _PyMem_DebugMalloc(void *ctx, size_t size);
|
||||
static void* _PyMem_DebugCalloc(void *ctx, size_t nelem, size_t elsize);
|
||||
static void* _PyMem_DebugRealloc(void *ctx, void *ptr, size_t size);
|
||||
static void _PyMem_DebugFree(void *ctx, void *p);
|
||||
|
||||
static void _PyObject_DebugDumpAddress(const void *p);
|
||||
static void _PyMem_DebugCheckAddress(char api_id, const void *p);
|
||||
static void *_PyMem_DebugRawMalloc(void *, size_t);
|
||||
static void *_PyMem_DebugRawCalloc(void *, size_t, size_t);
|
||||
static void *_PyMem_DebugRawRealloc(void *, void *, size_t);
|
||||
static void _PyMem_DebugRawFree(void *, void *);
|
||||
static void *_PyMem_DebugMalloc(void *, size_t);
|
||||
static void *_PyMem_DebugCalloc(void *, size_t, size_t);
|
||||
static void *_PyMem_DebugRealloc(void *, void *, size_t);
|
||||
static void _PyMem_DebugFree(void *, void *);
|
||||
static void _PyObject_DebugDumpAddress(const void *);
|
||||
static void _PyMem_DebugCheckAddress(char, const void *);
|
||||
|
||||
#if defined(__has_feature) /* Clang */
|
||||
# if __has_feature(address_sanitizer) /* is ASAN enabled? */
|
||||
|
@ -83,10 +84,16 @@ static void _PyObject_Free(void *ctx, void *p);
|
|||
static void* _PyObject_Realloc(void *ctx, void *ptr, size_t size);
|
||||
#endif
|
||||
|
||||
|
||||
static void *
|
||||
static inline void *
|
||||
_PyMem_RawMalloc(void *ctx, size_t size)
|
||||
{
|
||||
#ifdef __COSMOPOLITAN__
|
||||
#ifdef __FSANITIZE_ADDRESS__
|
||||
return __asan_memalign(__BIGGEST_ALIGNMENT__, size);
|
||||
#else
|
||||
return dlmalloc(size);
|
||||
#endif
|
||||
#else
|
||||
/* PyMem_RawMalloc(0) means malloc(1). Some systems would return NULL
|
||||
for malloc(0), which would be treated as an error. Some platforms would
|
||||
return a pointer with no memory behind it, which would break pymalloc.
|
||||
|
@ -94,11 +101,19 @@ _PyMem_RawMalloc(void *ctx, size_t size)
|
|||
if (size == 0)
|
||||
size = 1;
|
||||
return malloc(size);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void *
|
||||
static inline void *
|
||||
_PyMem_RawCalloc(void *ctx, size_t nelem, size_t elsize)
|
||||
{
|
||||
#ifdef __COSMOPOLITAN__
|
||||
#ifdef __FSANITIZE_ADDRESS__
|
||||
return __asan_calloc(nelem, elsize);
|
||||
#else
|
||||
return dlcalloc(nelem, elsize);
|
||||
#endif
|
||||
#else
|
||||
/* PyMem_RawCalloc(0, 0) means calloc(1, 1). Some systems would return NULL
|
||||
for calloc(0, 0), which would be treated as an error. Some platforms
|
||||
would return a pointer with no memory behind it, which would break
|
||||
|
@ -108,23 +123,39 @@ _PyMem_RawCalloc(void *ctx, size_t nelem, size_t elsize)
|
|||
elsize = 1;
|
||||
}
|
||||
return calloc(nelem, elsize);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void *
|
||||
static inline void *
|
||||
_PyMem_RawRealloc(void *ctx, void *ptr, size_t size)
|
||||
{
|
||||
if (size == 0)
|
||||
size = 1;
|
||||
#ifdef __COSMOPOLITAN__
|
||||
#ifdef __FSANITIZE_ADDRESS__
|
||||
return __asan_realloc(ptr, size);
|
||||
#else
|
||||
return dlrealloc(ptr, size);
|
||||
#endif
|
||||
#else
|
||||
return realloc(ptr, size);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
static inline void
|
||||
_PyMem_RawFree(void *ctx, void *ptr)
|
||||
{
|
||||
#ifdef __COSMOPOLITAN__
|
||||
#ifdef __FSANITIZE_ADDRESS__
|
||||
__asan_free(ptr);
|
||||
#else
|
||||
dlfree(ptr);
|
||||
#endif
|
||||
#else
|
||||
free(ptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#ifdef MS_WINDOWS
|
||||
static void *
|
||||
_PyObject_ArenaVirtualAlloc(void *ctx, size_t size)
|
||||
|
@ -143,6 +174,9 @@ _PyObject_ArenaVirtualFree(void *ctx, void *ptr, size_t size)
|
|||
static void *
|
||||
_PyObject_ArenaMmap(void *ctx, size_t size)
|
||||
{
|
||||
#ifdef __COSMOPOLITAN__
|
||||
return mapanon(size);
|
||||
#else
|
||||
void *ptr;
|
||||
ptr = mmap(NULL, size, PROT_READ|PROT_WRITE,
|
||||
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
|
||||
|
@ -150,6 +184,7 @@ _PyObject_ArenaMmap(void *ctx, size_t size)
|
|||
return NULL;
|
||||
assert(ptr != NULL);
|
||||
return ptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -159,20 +194,19 @@ _PyObject_ArenaMunmap(void *ctx, void *ptr, size_t size)
|
|||
}
|
||||
|
||||
#else
|
||||
static void *
|
||||
static inline void *
|
||||
_PyObject_ArenaMalloc(void *ctx, size_t size)
|
||||
{
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
static void
|
||||
static inline void
|
||||
_PyObject_ArenaFree(void *ctx, void *ptr, size_t size)
|
||||
{
|
||||
free(ptr);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#define PYRAW_FUNCS _PyMem_RawMalloc, _PyMem_RawCalloc, _PyMem_RawRealloc, _PyMem_RawFree
|
||||
#ifdef WITH_PYMALLOC
|
||||
# define PYOBJ_FUNCS _PyObject_Malloc, _PyObject_Calloc, _PyObject_Realloc, _PyObject_Free
|
||||
|
@ -460,7 +494,7 @@ PyMem_Realloc(void *ptr, size_t new_size)
|
|||
}
|
||||
|
||||
void
|
||||
PyMem_Free(void *ptr)
|
||||
(PyMem_Free)(void *ptr)
|
||||
{
|
||||
_PyMem.free(_PyMem.ctx, ptr);
|
||||
}
|
||||
|
@ -470,7 +504,6 @@ _PyMem_RawStrdup(const char *str)
|
|||
{
|
||||
size_t size;
|
||||
char *copy;
|
||||
|
||||
size = strlen(str) + 1;
|
||||
copy = PyMem_RawMalloc(size);
|
||||
if (copy == NULL)
|
||||
|
@ -484,7 +517,6 @@ _PyMem_Strdup(const char *str)
|
|||
{
|
||||
size_t size;
|
||||
char *copy;
|
||||
|
||||
size = strlen(str) + 1;
|
||||
copy = PyMem_Malloc(size);
|
||||
if (copy == NULL)
|
||||
|
@ -494,7 +526,7 @@ _PyMem_Strdup(const char *str)
|
|||
}
|
||||
|
||||
void *
|
||||
PyObject_Malloc(size_t size)
|
||||
(PyObject_Malloc)(size_t size)
|
||||
{
|
||||
/* see PyMem_RawMalloc() */
|
||||
if (size > (size_t)PY_SSIZE_T_MAX)
|
||||
|
@ -1211,11 +1243,12 @@ obmalloc controls. Since this test is needed at every entry point, it's
|
|||
extremely desirable that it be this fast.
|
||||
*/
|
||||
|
||||
static bool _Py_NO_ADDRESS_SAFETY_ANALYSIS
|
||||
_Py_NO_SANITIZE_THREAD
|
||||
_Py_NO_SANITIZE_MEMORY
|
||||
static inline bool _Py_NO_ADDRESS_SAFETY_ANALYSIS
|
||||
_Py_NO_SANITIZE_THREAD
|
||||
_Py_NO_SANITIZE_MEMORY
|
||||
address_in_range(void *p, poolp pool)
|
||||
{
|
||||
#ifdef WITH_THREAD
|
||||
// Since address_in_range may be reading from memory which was not allocated
|
||||
// by Python, it is important that pool->arenaindex is read only once, as
|
||||
// another thread may be concurrently modifying the value without holding
|
||||
|
@ -1225,6 +1258,11 @@ address_in_range(void *p, poolp pool)
|
|||
return arenaindex < maxarenas &&
|
||||
(uintptr_t)p - arenas[arenaindex].address < ARENA_SIZE &&
|
||||
arenas[arenaindex].address != 0;
|
||||
#else
|
||||
return pool->arenaindex < maxarenas &&
|
||||
(uintptr_t)p - arenas[pool->arenaindex].address < ARENA_SIZE &&
|
||||
arenas[pool->arenaindex].address != 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*==========================================================================*/
|
||||
|
@ -1456,13 +1494,13 @@ redirect:
|
|||
}
|
||||
}
|
||||
|
||||
static void *
|
||||
static inline void *
|
||||
_PyObject_Malloc(void *ctx, size_t nbytes)
|
||||
{
|
||||
return _PyObject_Alloc(0, ctx, 1, nbytes);
|
||||
}
|
||||
|
||||
static void *
|
||||
static inline void *
|
||||
_PyObject_Calloc(void *ctx, size_t nelem, size_t elsize)
|
||||
{
|
||||
return _PyObject_Alloc(1, ctx, nelem, elsize);
|
||||
|
@ -1701,16 +1739,13 @@ _PyObject_Realloc(void *ctx, void *p, size_t nbytes)
|
|||
void *bp;
|
||||
poolp pool;
|
||||
size_t size;
|
||||
|
||||
if (p == NULL)
|
||||
return _PyObject_Alloc(0, ctx, 1, nbytes);
|
||||
|
||||
#ifdef WITH_VALGRIND
|
||||
/* Treat running_on_valgrind == -1 the same as 0 */
|
||||
if (UNLIKELY(running_on_valgrind > 0))
|
||||
goto redirect;
|
||||
#endif
|
||||
|
||||
pool = POOL_ADDR(p);
|
||||
if (address_in_range(p, pool)) {
|
||||
/* We're in charge of this block */
|
||||
|
@ -1777,7 +1812,6 @@ _Py_GetAllocatedBlocks(void)
|
|||
|
||||
#endif /* WITH_PYMALLOC */
|
||||
|
||||
|
||||
/*==========================================================================*/
|
||||
/* A x-platform debugging allocator. This doesn't manage memory directly,
|
||||
* it wraps a real allocator, adding extra debugging info to the memory blocks.
|
||||
|
@ -1799,7 +1833,7 @@ static size_t serialno = 0; /* incremented on each debug {m,re}alloc */
|
|||
/* serialno is always incremented via calling this routine. The point is
|
||||
* to supply a single place to set a breakpoint.
|
||||
*/
|
||||
static void
|
||||
static inline void
|
||||
bumpserialno(void)
|
||||
{
|
||||
++serialno;
|
||||
|
@ -1807,31 +1841,16 @@ bumpserialno(void)
|
|||
|
||||
#define SST SIZEOF_SIZE_T
|
||||
|
||||
/* Read sizeof(size_t) bytes at p as a big-endian size_t. */
|
||||
static noasan size_t
|
||||
static inline optimizespeed noasan size_t
|
||||
read_size_t(const void *p)
|
||||
{
|
||||
int i;
|
||||
const uint8_t *q = (const uint8_t *)p;
|
||||
size_t result = *q++;
|
||||
for (i = SST; --i > 0; ++q)
|
||||
result = (result << 8) | *q;
|
||||
return result;
|
||||
return READ64BE(p);
|
||||
}
|
||||
|
||||
/* Write n as a big-endian size_t, MSB at address p, LSB at
|
||||
* p + sizeof(size_t) - 1.
|
||||
*/
|
||||
static noasan void
|
||||
static inline optimizespeed noasan void
|
||||
write_size_t(void *p, size_t n)
|
||||
{
|
||||
uint8_t *q = (uint8_t *)p + SST - 1;
|
||||
int i;
|
||||
|
||||
for (i = SST; --i >= 0; --q) {
|
||||
*q = (uint8_t)(n & 0xff);
|
||||
n >>= 8;
|
||||
}
|
||||
WRITE64BE((char *)p, n);
|
||||
}
|
||||
|
||||
/* Let S = sizeof(size_t). The debug malloc asks for 4*S extra bytes and
|
||||
|
@ -1893,6 +1912,7 @@ _PyMem_DebugRawAlloc(int use_calloc, void *ctx, size_t nbytes)
|
|||
tail = p + 2*SST + nbytes;
|
||||
memset(tail, FORBIDDENBYTE, SST);
|
||||
write_size_t(tail + SST, serialno);
|
||||
_PyMem_DebugCheckAddress(api->api_id, p+2*SST);
|
||||
|
||||
if (IsAsan()) {
|
||||
__asan_poison((uintptr_t)(p + SST + 1), SST-1, kAsanHeapUnderrun);
|
||||
|
@ -1917,7 +1937,6 @@ _PyMem_DebugRawCalloc(void *ctx, size_t nelem, size_t elsize)
|
|||
return _PyMem_DebugRawAlloc(1, ctx, nbytes);
|
||||
}
|
||||
|
||||
|
||||
/* Heuristic checking if the memory has been freed. Rely on the debug hooks on
|
||||
Python memory allocators which fills the memory with DEADBYTE (0xDB) when
|
||||
memory is deallocated. */
|
||||
|
@ -1933,7 +1952,6 @@ _PyMem_IsFreed(void *ptr, size_t size)
|
|||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* The debug free first checks the 2*SST bytes on each end for sanity (in
|
||||
particular, that the FORBIDDENBYTEs with the api ID are still intact).
|
||||
Then fills the original bytes with DEADBYTE.
|
||||
|
@ -1945,7 +1963,6 @@ _PyMem_DebugRawFree(void *ctx, void *p)
|
|||
debug_alloc_api_t *api = (debug_alloc_api_t *)ctx;
|
||||
uint8_t *q = (uint8_t *)p - 2*SST; /* address returned from malloc */
|
||||
size_t nbytes;
|
||||
|
||||
if (p == NULL)
|
||||
return;
|
||||
_PyMem_DebugCheckAddress(api->api_id, p);
|
||||
|
@ -1963,16 +1980,16 @@ _PyMem_DebugRawFree(void *ctx, void *p)
|
|||
static noasan void *
|
||||
_PyMem_DebugRawRealloc(void *ctx, void *p, size_t nbytes)
|
||||
{
|
||||
_Static_assert(sizeof(size_t) == 8, "");
|
||||
debug_alloc_api_t *api = (debug_alloc_api_t *)ctx;
|
||||
uint8_t *q = (uint8_t *)p;
|
||||
uint8_t *tail;
|
||||
size_t total; /* nbytes + 4*SST */
|
||||
size_t original_nbytes;
|
||||
size_t w;
|
||||
int i;
|
||||
|
||||
if (p == NULL)
|
||||
return _PyMem_DebugRawAlloc(0, ctx, nbytes);
|
||||
|
||||
_PyMem_DebugCheckAddress(api->api_id, p);
|
||||
bumpserialno();
|
||||
original_nbytes = read_size_t(q - 2*SST);
|
||||
|
@ -1980,23 +1997,20 @@ _PyMem_DebugRawRealloc(void *ctx, void *p, size_t nbytes)
|
|||
if (nbytes > PY_SSIZE_T_MAX - 4*SST)
|
||||
/* overflow: can't represent total as a Py_ssize_t */
|
||||
return NULL;
|
||||
|
||||
/* Resize and add decorations. */
|
||||
q = (uint8_t *)api->alloc.realloc(api->alloc.ctx, q - 2*SST, total);
|
||||
if (q == NULL)
|
||||
return NULL;
|
||||
|
||||
write_size_t(q, nbytes);
|
||||
assert(q[SST] == (uint8_t)api->api_id);
|
||||
for (i = 1; i < SST; ++i)
|
||||
assert(q[SST + i] == FORBIDDENBYTE);
|
||||
q += 2*SST;
|
||||
|
||||
tail = q + nbytes;
|
||||
__builtin_memset(tail, FORBIDDENBYTE, SST);
|
||||
w = 0x0101010101010101ull * FORBIDDENBYTE;
|
||||
WRITE64LE(tail, w);
|
||||
if (IsAsan()) __asan_poison((uintptr_t)tail, SST, kAsanHeapOverrun);
|
||||
write_size_t(tail + SST, serialno);
|
||||
|
||||
if (nbytes > original_nbytes) {
|
||||
/* growing: mark new extra memory clean */
|
||||
if (IsAsan()) {
|
||||
|
@ -2006,11 +2020,10 @@ _PyMem_DebugRawRealloc(void *ctx, void *p, size_t nbytes)
|
|||
memset(q + original_nbytes, CLEANBYTE,
|
||||
nbytes - original_nbytes);
|
||||
}
|
||||
|
||||
return q;
|
||||
}
|
||||
|
||||
static void
|
||||
static inline void
|
||||
_PyMem_DebugCheckGIL(void)
|
||||
{
|
||||
#ifdef WITH_THREAD
|
||||
|
|
15
third_party/python/Objects/stringlib/eq.inc
vendored
15
third_party/python/Objects/stringlib/eq.inc
vendored
|
@ -16,18 +16,17 @@ unicode_eq(PyObject *aa, PyObject *bb)
|
|||
{
|
||||
PyUnicodeObject *a = (PyUnicodeObject *)aa;
|
||||
PyUnicodeObject *b = (PyUnicodeObject *)bb;
|
||||
|
||||
if (PyUnicode_READY(a) == -1 || PyUnicode_READY(b) == -1) {
|
||||
if (UNLIKELY(PyUnicode_READY(a) == -1) ||
|
||||
UNLIKELY(PyUnicode_READY(b) == -1)) {
|
||||
assert(0 && "unicode_eq ready fail");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (PyUnicode_GET_LENGTH(a) != PyUnicode_GET_LENGTH(b))
|
||||
if (UNLIKELY(PyUnicode_GET_LENGTH(a) != PyUnicode_GET_LENGTH(b)))
|
||||
return 0;
|
||||
if (PyUnicode_GET_LENGTH(a) == 0)
|
||||
if (UNLIKELY(PyUnicode_GET_LENGTH(a) == 0))
|
||||
return 1;
|
||||
if (PyUnicode_KIND(a) != PyUnicode_KIND(b))
|
||||
if (UNLIKELY(PyUnicode_KIND(a) != PyUnicode_KIND(b)))
|
||||
return 0;
|
||||
return memcmp(PyUnicode_1BYTE_DATA(a), PyUnicode_1BYTE_DATA(b),
|
||||
PyUnicode_GET_LENGTH(a) * PyUnicode_KIND(a)) == 0;
|
||||
return bcmp(PyUnicode_1BYTE_DATA(a), PyUnicode_1BYTE_DATA(b),
|
||||
PyUnicode_GET_LENGTH(a) * PyUnicode_KIND(a)) == 0;
|
||||
}
|
||||
|
|
20
third_party/python/Objects/stringlib/undef.inc
vendored
20
third_party/python/Objects/stringlib/undef.inc
vendored
|
@ -4,16 +4,14 @@
|
|||
│ Python 3 │
|
||||
│ https://docs.python.org/3/license.html │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
/* clang-format off */
|
||||
|
||||
#undef FASTSEARCH
|
||||
#undef STRINGLIB
|
||||
#undef STRINGLIB_SIZEOF_CHAR
|
||||
#undef STRINGLIB_MAX_CHAR
|
||||
#undef STRINGLIB_CHAR
|
||||
#undef STRINGLIB_STR
|
||||
#undef STRINGLIB_LEN
|
||||
#undef STRINGLIB_NEW
|
||||
#undef _Py_InsertThousandsGrouping
|
||||
#undef FASTSEARCH
|
||||
#undef STRINGLIB
|
||||
#undef STRINGLIB_SIZEOF_CHAR
|
||||
#undef STRINGLIB_MAX_CHAR
|
||||
#undef STRINGLIB_CHAR
|
||||
#undef STRINGLIB_STR
|
||||
#undef STRINGLIB_LEN
|
||||
#undef STRINGLIB_NEW
|
||||
#undef _Py_InsertThousandsGrouping
|
||||
#undef STRINGLIB_IS_UNICODE
|
||||
|
||||
|
|
6
third_party/python/Objects/typeobject.c
vendored
6
third_party/python/Objects/typeobject.c
vendored
|
@ -966,7 +966,7 @@ PyType_GenericAlloc(PyTypeObject *type, Py_ssize_t nitems)
|
|||
if (obj == NULL)
|
||||
return PyErr_NoMemory();
|
||||
|
||||
memset(obj, '\0', size);
|
||||
bzero(obj, size);
|
||||
|
||||
if (type->tp_flags & Py_TPFLAGS_HEAPTYPE)
|
||||
Py_INCREF(type);
|
||||
|
@ -1379,7 +1379,6 @@ int
|
|||
PyType_IsSubtype(PyTypeObject *a, PyTypeObject *b)
|
||||
{
|
||||
PyObject *mro;
|
||||
|
||||
mro = a->tp_mro;
|
||||
if (mro != NULL) {
|
||||
/* Deal with multiple inheritance without recursion
|
||||
|
@ -1415,11 +1414,10 @@ PyType_IsSubtype(PyTypeObject *a, PyTypeObject *b)
|
|||
- _PyObject_LookupSpecial() exported for the benefit of other places.
|
||||
*/
|
||||
|
||||
static PyObject *
|
||||
forceinline PyObject *
|
||||
lookup_maybe(PyObject *self, _Py_Identifier *attrid)
|
||||
{
|
||||
PyObject *res;
|
||||
|
||||
res = _PyType_LookupId(Py_TYPE(self), attrid);
|
||||
if (res != NULL) {
|
||||
descrgetfunc f;
|
||||
|
|
161
third_party/python/Objects/unicodectype.c
vendored
161
third_party/python/Objects/unicodectype.c
vendored
|
@ -5,73 +5,54 @@
|
|||
│ https://docs.python.org/3/license.html │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "third_party/python/Include/unicodeobject.h"
|
||||
#include "third_party/python/Modules/unicodedata.h"
|
||||
#include "third_party/python/Modules/unicodedata_unidata.h"
|
||||
/* clang-format off */
|
||||
|
||||
/*
|
||||
Unicode character type helpers.
|
||||
* Unicode character type helpers.
|
||||
*
|
||||
* Written by Marc-Andre Lemburg (mal@lemburg.com).
|
||||
* Modified for Python 2.0 by Fredrik Lundh (fredrik@pythonware.com)
|
||||
*
|
||||
* Copyright (c) Corporation for National Research Initiatives.
|
||||
*/
|
||||
|
||||
Written by Marc-Andre Lemburg (mal@lemburg.com).
|
||||
Modified for Python 2.0 by Fredrik Lundh (fredrik@pythonware.com)
|
||||
|
||||
Copyright (c) Corporation for National Research Initiatives.
|
||||
|
||||
*/
|
||||
|
||||
#define ALPHA_MASK 0x01
|
||||
#define DECIMAL_MASK 0x02
|
||||
#define DIGIT_MASK 0x04
|
||||
#define LOWER_MASK 0x08
|
||||
#define LINEBREAK_MASK 0x10
|
||||
#define SPACE_MASK 0x20
|
||||
#define TITLE_MASK 0x40
|
||||
#define UPPER_MASK 0x80
|
||||
#define XID_START_MASK 0x100
|
||||
#define XID_CONTINUE_MASK 0x200
|
||||
#define PRINTABLE_MASK 0x400
|
||||
#define NUMERIC_MASK 0x800
|
||||
#define ALPHA_MASK 0x01
|
||||
#define DECIMAL_MASK 0x02
|
||||
#define DIGIT_MASK 0x04
|
||||
#define LOWER_MASK 0x08
|
||||
#define LINEBREAK_MASK 0x10
|
||||
#define SPACE_MASK 0x20
|
||||
#define TITLE_MASK 0x40
|
||||
#define UPPER_MASK 0x80
|
||||
#define XID_START_MASK 0x100
|
||||
#define XID_CONTINUE_MASK 0x200
|
||||
#define PRINTABLE_MASK 0x400
|
||||
#define NUMERIC_MASK 0x800
|
||||
#define CASE_IGNORABLE_MASK 0x1000
|
||||
#define CASED_MASK 0x2000
|
||||
#define EXTENDED_CASE_MASK 0x4000
|
||||
|
||||
typedef struct {
|
||||
/*
|
||||
These are either deltas to the character or offsets in
|
||||
_PyUnicode_ExtendedCase.
|
||||
*/
|
||||
const int upper;
|
||||
const int lower;
|
||||
const int title;
|
||||
/* Note if more flag space is needed, decimal and digit could be unified. */
|
||||
const unsigned char decimal;
|
||||
const unsigned char digit;
|
||||
const unsigned short flags;
|
||||
} _PyUnicode_TypeRecord;
|
||||
|
||||
#include "third_party/python/Objects/unicodetype_db.inc"
|
||||
#define CASED_MASK 0x2000
|
||||
#define EXTENDED_CASE_MASK 0x4000
|
||||
|
||||
static const _PyUnicode_TypeRecord *
|
||||
gettyperecord(Py_UCS4 code)
|
||||
_PyUnicode_GetTypeRecord(Py_UCS4 c)
|
||||
{
|
||||
int index;
|
||||
|
||||
if (code >= 0x110000)
|
||||
index = 0;
|
||||
else
|
||||
{
|
||||
index = index1[(code>>SHIFT)];
|
||||
index = index2[(index<<SHIFT)+(code&((1<<SHIFT)-1))];
|
||||
int i, k;
|
||||
if (c >= 0x110000) {
|
||||
i = 0;
|
||||
} else {
|
||||
k = _PyUnicode_TypeRecordsShift;
|
||||
i = _PyUnicode_TypeRecordsIndex1[(c >> k)];
|
||||
i = _PyUnicode_TypeRecordsIndex2[(i << k) + (c & ((1 << k) - 1))];
|
||||
}
|
||||
|
||||
return &_PyUnicode_TypeRecords[index];
|
||||
return &_PyUnicode_TypeRecords[i];
|
||||
}
|
||||
|
||||
/* Returns the titlecase Unicode characters corresponding to ch or just
|
||||
ch if no titlecase mapping is known. */
|
||||
|
||||
Py_UCS4 _PyUnicode_ToTitlecase(Py_UCS4 ch)
|
||||
{
|
||||
const _PyUnicode_TypeRecord *ctype = gettyperecord(ch);
|
||||
|
||||
const _PyUnicode_TypeRecord *ctype = _PyUnicode_GetTypeRecord(ch);
|
||||
if (ctype->flags & EXTENDED_CASE_MASK)
|
||||
return _PyUnicode_ExtendedCase[ctype->title & 0xFFFF];
|
||||
return ch + ctype->title;
|
||||
|
@ -79,41 +60,30 @@ Py_UCS4 _PyUnicode_ToTitlecase(Py_UCS4 ch)
|
|||
|
||||
/* Returns 1 for Unicode characters having the category 'Lt', 0
|
||||
otherwise. */
|
||||
|
||||
int _PyUnicode_IsTitlecase(Py_UCS4 ch)
|
||||
{
|
||||
const _PyUnicode_TypeRecord *ctype = gettyperecord(ch);
|
||||
|
||||
return (ctype->flags & TITLE_MASK) != 0;
|
||||
return !!(_PyUnicode_GetTypeRecord(ch)->flags & TITLE_MASK);
|
||||
}
|
||||
|
||||
/* Returns 1 for Unicode characters having the XID_Start property, 0
|
||||
otherwise. */
|
||||
|
||||
int _PyUnicode_IsXidStart(Py_UCS4 ch)
|
||||
{
|
||||
const _PyUnicode_TypeRecord *ctype = gettyperecord(ch);
|
||||
|
||||
return (ctype->flags & XID_START_MASK) != 0;
|
||||
return !!(_PyUnicode_GetTypeRecord(ch)->flags & XID_START_MASK);
|
||||
}
|
||||
|
||||
/* Returns 1 for Unicode characters having the XID_Continue property,
|
||||
0 otherwise. */
|
||||
|
||||
int _PyUnicode_IsXidContinue(Py_UCS4 ch)
|
||||
{
|
||||
const _PyUnicode_TypeRecord *ctype = gettyperecord(ch);
|
||||
|
||||
return (ctype->flags & XID_CONTINUE_MASK) != 0;
|
||||
return !!(_PyUnicode_GetTypeRecord(ch)->flags & XID_CONTINUE_MASK);
|
||||
}
|
||||
|
||||
/* Returns the integer decimal (0-9) for Unicode characters having
|
||||
this property, -1 otherwise. */
|
||||
|
||||
int _PyUnicode_ToDecimalDigit(Py_UCS4 ch)
|
||||
{
|
||||
const _PyUnicode_TypeRecord *ctype = gettyperecord(ch);
|
||||
|
||||
const _PyUnicode_TypeRecord *ctype = _PyUnicode_GetTypeRecord(ch);
|
||||
return (ctype->flags & DECIMAL_MASK) ? ctype->decimal : -1;
|
||||
}
|
||||
|
||||
|
@ -126,11 +96,9 @@ int _PyUnicode_IsDecimalDigit(Py_UCS4 ch)
|
|||
|
||||
/* Returns the integer digit (0-9) for Unicode characters having
|
||||
this property, -1 otherwise. */
|
||||
|
||||
int _PyUnicode_ToDigit(Py_UCS4 ch)
|
||||
{
|
||||
const _PyUnicode_TypeRecord *ctype = gettyperecord(ch);
|
||||
|
||||
const _PyUnicode_TypeRecord *ctype = _PyUnicode_GetTypeRecord(ch);
|
||||
return (ctype->flags & DIGIT_MASK) ? ctype->digit : -1;
|
||||
}
|
||||
|
||||
|
@ -143,12 +111,9 @@ int _PyUnicode_IsDigit(Py_UCS4 ch)
|
|||
|
||||
/* Returns the numeric value as double for Unicode characters having
|
||||
this property, -1.0 otherwise. */
|
||||
|
||||
int _PyUnicode_IsNumeric(Py_UCS4 ch)
|
||||
{
|
||||
const _PyUnicode_TypeRecord *ctype = gettyperecord(ch);
|
||||
|
||||
return (ctype->flags & NUMERIC_MASK) != 0;
|
||||
return !!(_PyUnicode_GetTypeRecord(ch)->flags & NUMERIC_MASK);
|
||||
}
|
||||
|
||||
/* Returns 1 for Unicode characters to be hex-escaped when repr()ed,
|
||||
|
@ -166,38 +131,28 @@ int _PyUnicode_IsNumeric(Py_UCS4 ch)
|
|||
*/
|
||||
int _PyUnicode_IsPrintable(Py_UCS4 ch)
|
||||
{
|
||||
const _PyUnicode_TypeRecord *ctype = gettyperecord(ch);
|
||||
|
||||
return (ctype->flags & PRINTABLE_MASK) != 0;
|
||||
return !!(_PyUnicode_GetTypeRecord(ch)->flags & PRINTABLE_MASK);
|
||||
}
|
||||
|
||||
/* Returns 1 for Unicode characters having the category 'Ll', 0
|
||||
otherwise. */
|
||||
|
||||
int _PyUnicode_IsLowercase(Py_UCS4 ch)
|
||||
{
|
||||
const _PyUnicode_TypeRecord *ctype = gettyperecord(ch);
|
||||
|
||||
return (ctype->flags & LOWER_MASK) != 0;
|
||||
return !!(_PyUnicode_GetTypeRecord(ch)->flags & LOWER_MASK);
|
||||
}
|
||||
|
||||
/* Returns 1 for Unicode characters having the category 'Lu', 0
|
||||
otherwise. */
|
||||
|
||||
int _PyUnicode_IsUppercase(Py_UCS4 ch)
|
||||
{
|
||||
const _PyUnicode_TypeRecord *ctype = gettyperecord(ch);
|
||||
|
||||
return (ctype->flags & UPPER_MASK) != 0;
|
||||
return !!(_PyUnicode_GetTypeRecord(ch)->flags & UPPER_MASK);
|
||||
}
|
||||
|
||||
/* Returns the uppercase Unicode characters corresponding to ch or just
|
||||
ch if no uppercase mapping is known. */
|
||||
|
||||
Py_UCS4 _PyUnicode_ToUppercase(Py_UCS4 ch)
|
||||
{
|
||||
const _PyUnicode_TypeRecord *ctype = gettyperecord(ch);
|
||||
|
||||
const _PyUnicode_TypeRecord *ctype = _PyUnicode_GetTypeRecord(ch);
|
||||
if (ctype->flags & EXTENDED_CASE_MASK)
|
||||
return _PyUnicode_ExtendedCase[ctype->upper & 0xFFFF];
|
||||
return ch + ctype->upper;
|
||||
|
@ -205,11 +160,9 @@ Py_UCS4 _PyUnicode_ToUppercase(Py_UCS4 ch)
|
|||
|
||||
/* Returns the lowercase Unicode characters corresponding to ch or just
|
||||
ch if no lowercase mapping is known. */
|
||||
|
||||
Py_UCS4 _PyUnicode_ToLowercase(Py_UCS4 ch)
|
||||
{
|
||||
const _PyUnicode_TypeRecord *ctype = gettyperecord(ch);
|
||||
|
||||
const _PyUnicode_TypeRecord *ctype = _PyUnicode_GetTypeRecord(ch);
|
||||
if (ctype->flags & EXTENDED_CASE_MASK)
|
||||
return _PyUnicode_ExtendedCase[ctype->lower & 0xFFFF];
|
||||
return ch + ctype->lower;
|
||||
|
@ -217,8 +170,7 @@ Py_UCS4 _PyUnicode_ToLowercase(Py_UCS4 ch)
|
|||
|
||||
int _PyUnicode_ToLowerFull(Py_UCS4 ch, Py_UCS4 *res)
|
||||
{
|
||||
const _PyUnicode_TypeRecord *ctype = gettyperecord(ch);
|
||||
|
||||
const _PyUnicode_TypeRecord *ctype = _PyUnicode_GetTypeRecord(ch);
|
||||
if (ctype->flags & EXTENDED_CASE_MASK) {
|
||||
int index = ctype->lower & 0xFFFF;
|
||||
int n = ctype->lower >> 24;
|
||||
|
@ -233,8 +185,7 @@ int _PyUnicode_ToLowerFull(Py_UCS4 ch, Py_UCS4 *res)
|
|||
|
||||
int _PyUnicode_ToTitleFull(Py_UCS4 ch, Py_UCS4 *res)
|
||||
{
|
||||
const _PyUnicode_TypeRecord *ctype = gettyperecord(ch);
|
||||
|
||||
const _PyUnicode_TypeRecord *ctype = _PyUnicode_GetTypeRecord(ch);
|
||||
if (ctype->flags & EXTENDED_CASE_MASK) {
|
||||
int index = ctype->title & 0xFFFF;
|
||||
int n = ctype->title >> 24;
|
||||
|
@ -249,8 +200,7 @@ int _PyUnicode_ToTitleFull(Py_UCS4 ch, Py_UCS4 *res)
|
|||
|
||||
int _PyUnicode_ToUpperFull(Py_UCS4 ch, Py_UCS4 *res)
|
||||
{
|
||||
const _PyUnicode_TypeRecord *ctype = gettyperecord(ch);
|
||||
|
||||
const _PyUnicode_TypeRecord *ctype = _PyUnicode_GetTypeRecord(ch);
|
||||
if (ctype->flags & EXTENDED_CASE_MASK) {
|
||||
int index = ctype->upper & 0xFFFF;
|
||||
int n = ctype->upper >> 24;
|
||||
|
@ -265,8 +215,7 @@ int _PyUnicode_ToUpperFull(Py_UCS4 ch, Py_UCS4 *res)
|
|||
|
||||
int _PyUnicode_ToFoldedFull(Py_UCS4 ch, Py_UCS4 *res)
|
||||
{
|
||||
const _PyUnicode_TypeRecord *ctype = gettyperecord(ch);
|
||||
|
||||
const _PyUnicode_TypeRecord *ctype = _PyUnicode_GetTypeRecord(ch);
|
||||
if (ctype->flags & EXTENDED_CASE_MASK && (ctype->lower >> 20) & 7) {
|
||||
int index = (ctype->lower & 0xFFFF) + (ctype->lower >> 24);
|
||||
int n = (ctype->lower >> 20) & 7;
|
||||
|
@ -280,25 +229,17 @@ int _PyUnicode_ToFoldedFull(Py_UCS4 ch, Py_UCS4 *res)
|
|||
|
||||
int _PyUnicode_IsCased(Py_UCS4 ch)
|
||||
{
|
||||
const _PyUnicode_TypeRecord *ctype = gettyperecord(ch);
|
||||
|
||||
return (ctype->flags & CASED_MASK) != 0;
|
||||
return !!(_PyUnicode_GetTypeRecord(ch)->flags & CASED_MASK);
|
||||
}
|
||||
|
||||
int _PyUnicode_IsCaseIgnorable(Py_UCS4 ch)
|
||||
{
|
||||
const _PyUnicode_TypeRecord *ctype = gettyperecord(ch);
|
||||
|
||||
return (ctype->flags & CASE_IGNORABLE_MASK) != 0;
|
||||
return !!(_PyUnicode_GetTypeRecord(ch)->flags & CASE_IGNORABLE_MASK);
|
||||
}
|
||||
|
||||
/* Returns 1 for Unicode characters having the category 'Ll', 'Lu', 'Lt',
|
||||
'Lo' or 'Lm', 0 otherwise. */
|
||||
|
||||
int _PyUnicode_IsAlpha(Py_UCS4 ch)
|
||||
{
|
||||
const _PyUnicode_TypeRecord *ctype = gettyperecord(ch);
|
||||
|
||||
return (ctype->flags & ALPHA_MASK) != 0;
|
||||
return !!(_PyUnicode_GetTypeRecord(ch)->flags & ALPHA_MASK);
|
||||
}
|
||||
|
||||
|
|
33
third_party/python/Objects/unicodeislinebreak.c
vendored
33
third_party/python/Objects/unicodeislinebreak.c
vendored
|
@ -1,33 +0,0 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=4 sts=4 sw=4 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Python 3 │
|
||||
│ https://docs.python.org/3/license.html │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/dce.h"
|
||||
#include "third_party/python/Include/unicodeobject.h"
|
||||
/* clang-format off */
|
||||
|
||||
/**
|
||||
* Returns 1 for Unicode characters having the line break
|
||||
* property 'BK', 'CR', 'LF' or 'NL' or having bidirectional
|
||||
* type 'B', 0 otherwise.
|
||||
*/
|
||||
int _PyUnicode_IsLinebreak(const Py_UCS4 ch)
|
||||
{
|
||||
switch (ch) {
|
||||
case 0x000A:
|
||||
case 0x000B:
|
||||
case 0x000C:
|
||||
case 0x000D:
|
||||
case 0x001C:
|
||||
case 0x001D:
|
||||
case 0x001E:
|
||||
case 0x0085:
|
||||
case 0x2028:
|
||||
case 0x2029:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
51
third_party/python/Objects/unicodeiswhitespace.c
vendored
51
third_party/python/Objects/unicodeiswhitespace.c
vendored
|
@ -1,51 +0,0 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=4 sts=4 sw=4 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Python 3 │
|
||||
│ https://docs.python.org/3/license.html │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/dce.h"
|
||||
#include "third_party/python/Include/unicodeobject.h"
|
||||
/* clang-format off */
|
||||
|
||||
/**
|
||||
* Returns 1 for Unicode characters having the bidirectional
|
||||
* type 'WS', 'B' or 'S' or the category 'Zs', 0 otherwise.
|
||||
*/
|
||||
int _PyUnicode_IsWhitespace(const Py_UCS4 ch)
|
||||
{
|
||||
switch (ch) {
|
||||
case 0x0009:
|
||||
case 0x000A:
|
||||
case 0x000B:
|
||||
case 0x000C:
|
||||
case 0x000D:
|
||||
case 0x001C:
|
||||
case 0x001D:
|
||||
case 0x001E:
|
||||
case 0x001F:
|
||||
case 0x0020:
|
||||
case 0x0085:
|
||||
case 0x00A0:
|
||||
case 0x1680:
|
||||
case 0x2000:
|
||||
case 0x2001:
|
||||
case 0x2002:
|
||||
case 0x2003:
|
||||
case 0x2004:
|
||||
case 0x2005:
|
||||
case 0x2006:
|
||||
case 0x2007:
|
||||
case 0x2008:
|
||||
case 0x2009:
|
||||
case 0x200A:
|
||||
case 0x2028:
|
||||
case 0x2029:
|
||||
case 0x202F:
|
||||
case 0x205F:
|
||||
case 0x3000:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
106
third_party/python/Objects/unicodeobject.c
vendored
106
third_party/python/Objects/unicodeobject.c
vendored
|
@ -6,6 +6,8 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#define PY_SSIZE_T_CLEAN
|
||||
#include "libc/assert.h"
|
||||
#include "libc/bits/likely.h"
|
||||
#include "libc/bits/weaken.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/str/str.h"
|
||||
|
@ -39,7 +41,7 @@
|
|||
#include "third_party/python/Include/unicodeobject.h"
|
||||
#include "third_party/python/Include/warnings.h"
|
||||
#include "third_party/python/Include/yoink.h"
|
||||
#include "third_party/python/Objects/stringlib/eq.inc"
|
||||
#include "third_party/python/Modules/unicodedata.h"
|
||||
/* clang-format off */
|
||||
|
||||
PYTHON_PROVIDE("_string");
|
||||
|
@ -51,6 +53,8 @@ PYTHON_PROVIDE("_string.__spec__");
|
|||
PYTHON_PROVIDE("_string.formatter_field_name_split");
|
||||
PYTHON_PROVIDE("_string.formatter_parser");
|
||||
|
||||
#include "third_party/python/Objects/stringlib/eq.inc"
|
||||
|
||||
/*
|
||||
|
||||
Unicode implementation based on original code by Fredrik Lundh,
|
||||
|
@ -1411,12 +1415,10 @@ unicode_convert_wchar_to_ucs4(const wchar_t *begin, const wchar_t *end,
|
|||
{
|
||||
const wchar_t *iter;
|
||||
Py_UCS4 *ucs4_out;
|
||||
|
||||
assert(unicode != NULL);
|
||||
assert(_PyUnicode_CHECK(unicode));
|
||||
assert(_PyUnicode_KIND(unicode) == PyUnicode_4BYTE_KIND);
|
||||
ucs4_out = PyUnicode_4BYTE_DATA(unicode);
|
||||
|
||||
for (iter = begin; iter < end; ) {
|
||||
assert(ucs4_out < (PyUnicode_4BYTE_DATA(unicode) +
|
||||
_PyUnicode_GET_LENGTH(unicode)));
|
||||
|
@ -1434,7 +1436,6 @@ unicode_convert_wchar_to_ucs4(const wchar_t *begin, const wchar_t *end,
|
|||
}
|
||||
assert(ucs4_out == (PyUnicode_4BYTE_DATA(unicode) +
|
||||
_PyUnicode_GET_LENGTH(unicode)));
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -2993,7 +2994,6 @@ PyUnicode_FromFormat(const char *format, ...)
|
|||
{
|
||||
PyObject* ret;
|
||||
va_list vargs;
|
||||
|
||||
#ifdef HAVE_STDARG_PROTOTYPES
|
||||
va_start(vargs, format);
|
||||
#else
|
||||
|
@ -3203,9 +3203,7 @@ _Py_normalize_encoding(const char *encoding,
|
|||
char *l;
|
||||
char *l_end;
|
||||
int punct;
|
||||
|
||||
assert(encoding != NULL);
|
||||
|
||||
e = encoding;
|
||||
l = lower;
|
||||
l_end = &lower[lower_len - 1];
|
||||
|
@ -3215,7 +3213,6 @@ _Py_normalize_encoding(const char *encoding,
|
|||
if (c == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (Py_ISALNUM(c) || c == '.') {
|
||||
if (punct && l != lower) {
|
||||
if (l == l_end) {
|
||||
|
@ -3224,7 +3221,6 @@ _Py_normalize_encoding(const char *encoding,
|
|||
*l++ = '_';
|
||||
}
|
||||
punct = 0;
|
||||
|
||||
if (l == l_end) {
|
||||
return 0;
|
||||
}
|
||||
|
@ -3233,7 +3229,6 @@ _Py_normalize_encoding(const char *encoding,
|
|||
else {
|
||||
punct = 1;
|
||||
}
|
||||
|
||||
e++;
|
||||
}
|
||||
*l = '\0';
|
||||
|
@ -3385,7 +3380,6 @@ PyUnicode_Encode(const Py_UNICODE *s,
|
|||
const char *errors)
|
||||
{
|
||||
PyObject *v, *unicode;
|
||||
|
||||
unicode = PyUnicode_FromUnicode(s, size);
|
||||
if (unicode == NULL)
|
||||
return NULL;
|
||||
|
@ -3613,7 +3607,7 @@ PyUnicode_EncodeLocale(PyObject *unicode, const char *errors)
|
|||
PyObject *
|
||||
PyUnicode_EncodeFSDefault(PyObject *unicode)
|
||||
{
|
||||
#if defined(__APPLE__)
|
||||
#if defined(__APPLE__) || defined(__COSMOPOLITAN__)
|
||||
return _PyUnicode_AsUTF8String(unicode, Py_FileSystemDefaultEncodeErrors);
|
||||
#else
|
||||
PyInterpreterState *interp = PyThreadState_GET()->interp;
|
||||
|
@ -3930,7 +3924,7 @@ PyUnicode_DecodeFSDefault(const char *s) {
|
|||
PyObject*
|
||||
PyUnicode_DecodeFSDefaultAndSize(const char *s, Py_ssize_t size)
|
||||
{
|
||||
#if defined(__APPLE__)
|
||||
#if defined(__APPLE__) || defined(__COSMOPOLITAN__)
|
||||
return PyUnicode_DecodeUTF8Stateful(s, size, Py_FileSystemDefaultEncodeErrors, NULL);
|
||||
#else
|
||||
PyInterpreterState *interp = PyThreadState_GET()->interp;
|
||||
|
@ -3955,7 +3949,6 @@ PyUnicode_DecodeFSDefaultAndSize(const char *s, Py_ssize_t size)
|
|||
#endif
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
PyUnicode_FSConverter(PyObject* arg, void* addr)
|
||||
{
|
||||
|
@ -4071,18 +4064,16 @@ PyUnicode_FSDecoder(PyObject* arg, void* addr)
|
|||
}
|
||||
|
||||
|
||||
char*
|
||||
char *
|
||||
PyUnicode_AsUTF8AndSize(PyObject *unicode, Py_ssize_t *psize)
|
||||
{
|
||||
PyObject *bytes;
|
||||
|
||||
if (!PyUnicode_Check(unicode)) {
|
||||
PyErr_BadArgument();
|
||||
return NULL;
|
||||
}
|
||||
if (PyUnicode_READY(unicode) == -1)
|
||||
return NULL;
|
||||
|
||||
if (PyUnicode_UTF8(unicode) == NULL) {
|
||||
assert(!PyUnicode_IS_COMPACT_ASCII(unicode));
|
||||
bytes = _PyUnicode_AsUTF8String(unicode, NULL);
|
||||
|
@ -4100,13 +4091,12 @@ PyUnicode_AsUTF8AndSize(PyObject *unicode, Py_ssize_t *psize)
|
|||
_PyUnicode_UTF8_LENGTH(unicode) + 1);
|
||||
Py_DECREF(bytes);
|
||||
}
|
||||
|
||||
if (psize)
|
||||
*psize = PyUnicode_UTF8_LENGTH(unicode);
|
||||
return PyUnicode_UTF8(unicode);
|
||||
}
|
||||
|
||||
char*
|
||||
char *
|
||||
PyUnicode_AsUTF8(PyObject *unicode)
|
||||
{
|
||||
return PyUnicode_AsUTF8AndSize(unicode, NULL);
|
||||
|
@ -5989,8 +5979,6 @@ PyUnicode_AsUTF16String(PyObject *unicode)
|
|||
|
||||
/* --- Unicode Escape Codec ----------------------------------------------- */
|
||||
|
||||
static _PyUnicode_Name_CAPI *ucnhash_CAPI = NULL;
|
||||
|
||||
PyObject *
|
||||
_PyUnicode_DecodeUnicodeEscape(const char *s,
|
||||
Py_ssize_t size,
|
||||
|
@ -6142,19 +6130,13 @@ _PyUnicode_DecodeUnicodeEscape(const char *s,
|
|||
|
||||
/* \N{name} */
|
||||
case 'N':
|
||||
if (ucnhash_CAPI == NULL) {
|
||||
/* load the unicode data module */
|
||||
ucnhash_CAPI = (_PyUnicode_Name_CAPI *)PyCapsule_Import(
|
||||
PyUnicodeData_CAPSULE_NAME, 1);
|
||||
if (ucnhash_CAPI == NULL) {
|
||||
PyErr_SetString(
|
||||
PyExc_UnicodeError,
|
||||
"\\N escapes not supported (can't load unicodedata module)"
|
||||
);
|
||||
goto onError;
|
||||
}
|
||||
if (!weaken(_PyUnicode_GetCode)) {
|
||||
PyErr_SetString(
|
||||
PyExc_UnicodeError,
|
||||
"\\N escapes not supported "
|
||||
"(you must yoink pyc:unicodedata or _PyUnicode_GetCode)");
|
||||
goto onError;
|
||||
}
|
||||
|
||||
message = "malformed \\N character escape";
|
||||
if (s < end && *s == '{') {
|
||||
const char *start = ++s;
|
||||
|
@ -6168,8 +6150,7 @@ _PyUnicode_DecodeUnicodeEscape(const char *s,
|
|||
s++;
|
||||
ch = 0xffffffff; /* in case 'getcode' messes up */
|
||||
if (namelen <= INT_MAX &&
|
||||
ucnhash_CAPI->getcode(NULL, start, (int)namelen,
|
||||
&ch, 0)) {
|
||||
weaken(_PyUnicode_GetCode)(NULL, start, (int)namelen, &ch, 0)) {
|
||||
assert(ch <= MAX_UNICODE);
|
||||
WRITE_CHAR(ch);
|
||||
continue;
|
||||
|
@ -7613,7 +7594,6 @@ encoding_map_lookup(Py_UCS4 c, PyObject *mapping)
|
|||
int l2 = (c>>7) & 0xF;
|
||||
int l3 = c & 0x7F;
|
||||
int i;
|
||||
|
||||
if (c > 0xFFFF)
|
||||
return -1;
|
||||
if (c == 0)
|
||||
|
@ -7644,7 +7624,6 @@ charmapencode_lookup(Py_UCS4 c, PyObject *mapping)
|
|||
{
|
||||
PyObject *w = PyLong_FromLong((long)c);
|
||||
PyObject *x;
|
||||
|
||||
if (w == NULL)
|
||||
return NULL;
|
||||
x = PyObject_GetItem(mapping, w);
|
||||
|
@ -9006,11 +8985,11 @@ tailmatch(PyObject *self,
|
|||
PyUnicode_READ(kind_sub, data_sub, end_sub)) {
|
||||
/* If both are of the same kind, memcmp is sufficient */
|
||||
if (kind_self == kind_sub) {
|
||||
return ! memcmp((char *)data_self +
|
||||
(offset * PyUnicode_KIND(substring)),
|
||||
data_sub,
|
||||
PyUnicode_GET_LENGTH(substring) *
|
||||
PyUnicode_KIND(substring));
|
||||
return !bcmp((char *)data_self +
|
||||
(offset * PyUnicode_KIND(substring)),
|
||||
data_sub,
|
||||
PyUnicode_GET_LENGTH(substring) *
|
||||
PyUnicode_KIND(substring));
|
||||
}
|
||||
/* otherwise we have to compare each character by first accessing it */
|
||||
else {
|
||||
|
@ -10387,14 +10366,12 @@ unicode_compare(PyObject *str1, PyObject *str2)
|
|||
#undef COMPARE
|
||||
}
|
||||
|
||||
static int
|
||||
static inline int
|
||||
unicode_compare_eq(PyObject *str1, PyObject *str2)
|
||||
{
|
||||
int kind;
|
||||
void *data1, *data2;
|
||||
Py_ssize_t len;
|
||||
int cmp;
|
||||
|
||||
len = PyUnicode_GET_LENGTH(str1);
|
||||
if (PyUnicode_GET_LENGTH(str2) != len)
|
||||
return 0;
|
||||
|
@ -10403,9 +10380,7 @@ unicode_compare_eq(PyObject *str1, PyObject *str2)
|
|||
return 0;
|
||||
data1 = PyUnicode_DATA(str1);
|
||||
data2 = PyUnicode_DATA(str2);
|
||||
|
||||
cmp = memcmp(data1, data2, len * kind);
|
||||
return (cmp == 0);
|
||||
return !bcmp(data1, data2, len * kind);
|
||||
}
|
||||
|
||||
|
||||
|
@ -10509,17 +10484,25 @@ non_ready_unicode_equal_to_ascii_string(PyObject *unicode, const char *str)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
IsPureAscii(const char *p)
|
||||
{
|
||||
int c;
|
||||
while ((c = *p++)) {
|
||||
if (c & 128) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
_PyUnicode_EqualToASCIIString(PyObject *unicode, const char *str)
|
||||
{
|
||||
size_t len;
|
||||
assert(_PyUnicode_CHECK(unicode));
|
||||
assert(str);
|
||||
#ifndef NDEBUG
|
||||
for (const char *p = str; *p; p++) {
|
||||
assert((unsigned char)*p < 128);
|
||||
}
|
||||
#endif
|
||||
assert(IsPureAscii(str));
|
||||
assert(_PyUnicode_CHECK(unicode));
|
||||
if (PyUnicode_READY(unicode) == -1) {
|
||||
/* Memory error or bad data */
|
||||
PyErr_Clear();
|
||||
|
@ -10529,7 +10512,7 @@ _PyUnicode_EqualToASCIIString(PyObject *unicode, const char *str)
|
|||
return 0;
|
||||
len = (size_t)PyUnicode_GET_LENGTH(unicode);
|
||||
return strlen(str) == len &&
|
||||
memcmp(PyUnicode_1BYTE_DATA(unicode), str, len) == 0;
|
||||
!bcmp(PyUnicode_1BYTE_DATA(unicode), str, len);
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -10540,11 +10523,7 @@ _PyUnicode_EqualToASCIIId(PyObject *left, _Py_Identifier *right)
|
|||
|
||||
assert(_PyUnicode_CHECK(left));
|
||||
assert(right->string);
|
||||
#ifndef NDEBUG
|
||||
for (const char *p = right->string; *p; p++) {
|
||||
assert((unsigned char)*p < 128);
|
||||
}
|
||||
#endif
|
||||
assert(IsPureAscii(right->string));
|
||||
|
||||
if (PyUnicode_READY(left) == -1) {
|
||||
/* memory error or bad data */
|
||||
|
@ -10585,11 +10564,12 @@ PyUnicode_RichCompare(PyObject *left, PyObject *right, int op)
|
|||
int result;
|
||||
PyObject *v;
|
||||
|
||||
if (!PyUnicode_Check(left) || !PyUnicode_Check(right))
|
||||
if (UNLIKELY(!PyUnicode_Check(left) ||
|
||||
!PyUnicode_Check(right)))
|
||||
Py_RETURN_NOTIMPLEMENTED;
|
||||
|
||||
if (PyUnicode_READY(left) == -1 ||
|
||||
PyUnicode_READY(right) == -1)
|
||||
if (UNLIKELY(PyUnicode_READY(left) == -1 ||
|
||||
PyUnicode_READY(right) == -1))
|
||||
return NULL;
|
||||
|
||||
if (left == right) {
|
||||
|
|
1851
third_party/python/Objects/unicodetonumeric.c
vendored
1851
third_party/python/Objects/unicodetonumeric.c
vendored
File diff suppressed because it is too large
Load diff
4012
third_party/python/Objects/unicodetype_db.inc
vendored
4012
third_party/python/Objects/unicodetype_db.inc
vendored
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue