[Python-checkins] r51573 - python/branches/int_unification/Objects/longobject.c
martin.v.loewis
python-checkins at python.org
Fri Aug 25 00:47:44 CEST 2006
Author: martin.v.loewis
Date: Fri Aug 25 00:47:43 2006
New Revision: 51573
Modified:
python/branches/int_unification/Objects/longobject.c
Log:
Don't allocate padding in PyLongObject.
Slightly speed up PyLong_FromLong.
Modified: python/branches/int_unification/Objects/longobject.c
==============================================================================
--- python/branches/int_unification/Objects/longobject.c (original)
+++ python/branches/int_unification/Objects/longobject.c Fri Aug 25 00:47:43 2006
@@ -114,12 +114,15 @@
_PyLong_New(Py_ssize_t size)
{
PyLongObject *result;
- if (size > PY_SSIZE_T_MAX) {
- PyErr_NoMemory();
- return NULL;
- }
- result = PyObject_MALLOC(sizeof(PyLongObject) +
- (size-1)*sizeof(digit));
+ /* Can't use sizeof(PyLongObject) here, since the
+ compiler takes padding at the end into account.
+ As the consequence, this would waste 2 bytes on
+ a 32-bit system, and 6 bytes on a 64-bit system.
+ This computation would be incorrect on systems
+ which have padding before the digits; with 16-bit
+ digits this should not happen. */
+ result = PyObject_MALLOC(sizeof(PyVarObject) +
+ size*sizeof(digit));
if (!result) {
PyErr_NoMemory();
return NULL;
@@ -160,28 +163,37 @@
PyLongObject *v;
unsigned long t; /* unsigned so >> doesn't propagate sign bit */
int ndigits = 0;
- int negative = 0;
+ int sign = 1;
CHECK_SMALL_INT(ival);
+
if (ival < 0) {
ival = -ival;
- negative = 1;
+ sign = -1;
}
- if (ival < BASE) {
- /* Fast path for single-digits ints */
+ /* Fast path for single-digits ints */
+ if (!(ival>>SHIFT)) {
v = _PyLong_New(1);
if (v) {
- v->ob_size = negative ? -1 : 1;
+ v->ob_size = sign;
v->ob_digit[0] = ival;
}
return (PyObject*)v;
}
- /* Count the number of Python digits.
- We used to pick 5 ("big enough for anything"), but that's a
- waste of time and space given that 5*15 = 75 bits are rarely
- needed. */
+ /* 2 digits */
+ if (!(ival >> 2*SHIFT)) {
+ v = _PyLong_New(2);
+ if (v) {
+ v->ob_size = 2*sign;
+ v->ob_digit[0] = (digit)ival & MASK;
+ v->ob_digit[1] = ival >> SHIFT;
+ }
+ return (PyObject*)v;
+ }
+
+ /* Larger numbers: loop to determine number of digits */
t = (unsigned long)ival;
while (t) {
++ndigits;
@@ -190,7 +202,7 @@
v = _PyLong_New(ndigits);
if (v != NULL) {
digit *p = v->ob_digit;
- v->ob_size = negative ? -ndigits : ndigits;
+ v->ob_size = ndigits*sign;
t = (unsigned long)ival;
while (t) {
*p++ = (digit)(t & MASK);
@@ -3496,7 +3508,9 @@
PyObject_HEAD_INIT(&PyType_Type)
0, /* ob_size */
"long", /* tp_name */
- sizeof(PyLongObject) - sizeof(digit), /* tp_basicsize */
+ /* See _PyLong_New for why this isn't
+ sizeof(PyLongObject) - sizeof(digit) */
+ sizeof(PyVarObject), /* tp_basicsize */
sizeof(digit), /* tp_itemsize */
long_dealloc, /* tp_dealloc */
0, /* tp_print */
More information about the Python-checkins
mailing list