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:
Justine Tunney 2021-09-27 22:58:51 -07:00
parent fa7b4f5bd1
commit 39bf41f4eb
806 changed files with 77494 additions and 63859 deletions

View file

@ -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[])

View file

@ -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);

View file

@ -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*

View file

@ -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,

View file

@ -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;
}

View file

@ -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;

View file

@ -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;

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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) {

View file

@ -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

View file

@ -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

View file

@ -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;
}

View file

@ -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

View file

@ -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;

View file

@ -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);
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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) {

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff