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

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