summaryrefslogtreecommitdiffstats
path: root/Objects/floatobject.c
diff options
context:
space:
mode:
Diffstat (limited to 'Objects/floatobject.c')
-rw-r--r--Objects/floatobject.c221
1 files changed, 61 insertions, 160 deletions
diff --git a/Objects/floatobject.c b/Objects/floatobject.c
index e146a4f..a42be71 100644
--- a/Objects/floatobject.c
+++ b/Objects/floatobject.c
@@ -15,59 +15,17 @@
#define MIN(x, y) ((x) < (y) ? (x) : (y))
-#ifdef _OSF_SOURCE
-/* OSF1 5.1 doesn't make this available with XOPEN_SOURCE_EXTENDED defined */
-extern int finite(double);
-#endif
-
/* Special free list
-
- Since some Python programs can spend much of their time allocating
- and deallocating floats, these operations should be very fast.
- Therefore we use a dedicated allocation scheme with a much lower
- overhead (in space and time) than straight malloc(): a simple
- dedicated free list, filled when necessary with memory from malloc().
-
- block_list is a singly-linked list of all PyFloatBlocks ever allocated,
- linked via their next members. PyFloatBlocks are never returned to the
- system before shutdown (PyFloat_Fini).
-
free_list is a singly-linked list of available PyFloatObjects, linked
via abuse of their ob_type members.
*/
-#define BLOCK_SIZE 1000 /* 1K less typical malloc overhead */
-#define BHEAD_SIZE 8 /* Enough for a 64-bit pointer */
-#define N_FLOATOBJECTS ((BLOCK_SIZE - BHEAD_SIZE) / sizeof(PyFloatObject))
-
-struct _floatblock {
- struct _floatblock *next;
- PyFloatObject objects[N_FLOATOBJECTS];
-};
-
-typedef struct _floatblock PyFloatBlock;
-
-static PyFloatBlock *block_list = NULL;
+#ifndef PyFloat_MAXFREELIST
+#define PyFloat_MAXFREELIST 100
+#endif
+static int numfree = 0;
static PyFloatObject *free_list = NULL;
-static PyFloatObject *
-fill_free_list(void)
-{
- PyFloatObject *p, *q;
- /* XXX Float blocks escape the object heap. Use PyObject_MALLOC ??? */
- p = (PyFloatObject *) PyMem_MALLOC(sizeof(PyFloatBlock));
- if (p == NULL)
- return (PyFloatObject *) PyErr_NoMemory();
- ((PyFloatBlock *)p)->next = block_list;
- block_list = (PyFloatBlock *)p;
- p = &((PyFloatBlock *)p)->objects[0];
- q = p + N_FLOATOBJECTS;
- while (--q > p)
- Py_TYPE(q) = (struct _typeobject *)(q-1);
- Py_TYPE(q) = NULL;
- return p + N_FLOATOBJECTS - 1;
-}
-
double
PyFloat_GetMax(void)
{
@@ -156,14 +114,16 @@ PyFloat_GetInfo(void)
PyObject *
PyFloat_FromDouble(double fval)
{
- register PyFloatObject *op;
- if (free_list == NULL) {
- if ((free_list = fill_free_list()) == NULL)
- return NULL;
+ register PyFloatObject *op = free_list;
+ if (op != NULL) {
+ free_list = (PyFloatObject *) Py_TYPE(op);
+ numfree--;
+ } else {
+ op = (PyFloatObject*) PyObject_MALLOC(sizeof(PyFloatObject));
+ if (!op)
+ return PyErr_NoMemory();
}
/* Inline PyObject_New */
- op = free_list;
- free_list = (PyFloatObject *)Py_TYPE(op);
PyObject_INIT(op, &PyFloat_Type);
op->ob_fval = fval;
return (PyObject *) op;
@@ -179,25 +139,14 @@ PyFloat_FromString(PyObject *v)
PyObject *result = NULL;
if (PyUnicode_Check(v)) {
- Py_ssize_t i, buflen = PyUnicode_GET_SIZE(v);
- Py_UNICODE *bufptr;
- s_buffer = PyUnicode_TransformDecimalToASCII(
- PyUnicode_AS_UNICODE(v), buflen);
+ s_buffer = _PyUnicode_TransformDecimalAndSpaceToASCII(v);
if (s_buffer == NULL)
return NULL;
- /* Replace non-ASCII whitespace with ' ' */
- bufptr = PyUnicode_AS_UNICODE(s_buffer);
- for (i = 0; i < buflen; i++) {
- Py_UNICODE ch = bufptr[i];
- if (ch > 127 && Py_UNICODE_ISSPACE(ch))
- bufptr[i] = ' ';
- }
- s = _PyUnicode_AsStringAndSize(s_buffer, &len);
+ s = PyUnicode_AsUTF8AndSize(s_buffer, &len);
if (s == NULL) {
Py_DECREF(s_buffer);
return NULL;
}
- last = s + len;
}
else if (PyObject_AsCharBuffer(v, &s, &len)) {
PyErr_SetString(PyExc_TypeError,
@@ -233,6 +182,11 @@ static void
float_dealloc(PyFloatObject *op)
{
if (PyFloat_CheckExact(op)) {
+ if (numfree >= PyFloat_MAXFREELIST) {
+ PyObject_FREE(op);
+ return;
+ }
+ numfree++;
Py_TYPE(op) = (struct _typeobject *)free_list;
free_list = op;
}
@@ -313,13 +267,15 @@ static PyObject *
float_repr(PyFloatObject *v)
{
PyObject *result;
- char *buf = PyOS_double_to_string(PyFloat_AS_DOUBLE(v),
- 'r', 0,
- Py_DTSF_ADD_DOT_0,
- NULL);
+ char *buf;
+
+ buf = PyOS_double_to_string(PyFloat_AS_DOUBLE(v),
+ 'r', 0,
+ Py_DTSF_ADD_DOT_0,
+ NULL);
if (!buf)
return PyErr_NoMemory();
- result = PyUnicode_FromString(buf);
+ result = _PyUnicode_FromASCII(buf, strlen(buf));
PyMem_Free(buf);
return result;
}
@@ -523,8 +479,7 @@ float_richcompare(PyObject *v, PyObject *w, int op)
return PyBool_FromLong(r);
Unimplemented:
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
+ Py_RETURN_NOTIMPLEMENTED;
}
static Py_hash_t
@@ -1080,7 +1035,7 @@ static char
char_from_hex(int x)
{
assert(0 <= x && x < 16);
- return "0123456789abcdef"[x];
+ return Py_hexdigits[x];
}
static int
@@ -1750,12 +1705,22 @@ static PyObject *
float__format__(PyObject *self, PyObject *args)
{
PyObject *format_spec;
+ _PyUnicodeWriter writer;
+ int ret;
if (!PyArg_ParseTuple(args, "U:__format__", &format_spec))
return NULL;
- return _PyFloat_FormatAdvanced(self,
- PyUnicode_AS_UNICODE(format_spec),
- PyUnicode_GET_SIZE(format_spec));
+
+ _PyUnicodeWriter_Init(&writer, 0);
+ ret = _PyFloat_FormatAdvancedWriter(
+ &writer,
+ self,
+ format_spec, 0, PyUnicode_GET_LENGTH(format_spec));
+ if (ret == -1) {
+ _PyUnicodeWriter_Dealloc(&writer);
+ return NULL;
+ }
+ return _PyUnicodeWriter_Finish(&writer);
}
PyDoc_STRVAR(float__format__doc,
@@ -1950,98 +1915,34 @@ _PyFloat_Init(void)
int
PyFloat_ClearFreeList(void)
{
- PyFloatObject *p;
- PyFloatBlock *list, *next;
- int i;
- int u; /* remaining unfreed floats per block */
- int freelist_size = 0;
-
- list = block_list;
- block_list = NULL;
- free_list = NULL;
- while (list != NULL) {
- u = 0;
- for (i = 0, p = &list->objects[0];
- i < N_FLOATOBJECTS;
- i++, p++) {
- if (PyFloat_CheckExact(p) && Py_REFCNT(p) != 0)
- u++;
- }
- next = list->next;
- if (u) {
- list->next = block_list;
- block_list = list;
- for (i = 0, p = &list->objects[0];
- i < N_FLOATOBJECTS;
- i++, p++) {
- if (!PyFloat_CheckExact(p) ||
- Py_REFCNT(p) == 0) {
- Py_TYPE(p) = (struct _typeobject *)
- free_list;
- free_list = p;
- }
- }
- }
- else {
- PyMem_FREE(list);
- }
- freelist_size += u;
- list = next;
+ PyFloatObject *f = free_list, *next;
+ int i = numfree;
+ while (f) {
+ next = (PyFloatObject*) Py_TYPE(f);
+ PyObject_FREE(f);
+ f = next;
}
- return freelist_size;
+ free_list = NULL;
+ numfree = 0;
+ return i;
}
void
PyFloat_Fini(void)
{
- PyFloatObject *p;
- PyFloatBlock *list;
- int i;
- int u; /* total unfreed floats per block */
-
- u = PyFloat_ClearFreeList();
+ (void)PyFloat_ClearFreeList();
+}
- if (!Py_VerboseFlag)
- return;
- fprintf(stderr, "# cleanup floats");
- if (!u) {
- fprintf(stderr, "\n");
- }
- else {
- fprintf(stderr,
- ": %d unfreed float%s\n",
- u, u == 1 ? "" : "s");
- }
- if (Py_VerboseFlag > 1) {
- list = block_list;
- while (list != NULL) {
- for (i = 0, p = &list->objects[0];
- i < N_FLOATOBJECTS;
- i++, p++) {
- if (PyFloat_CheckExact(p) &&
- Py_REFCNT(p) != 0) {
- char *buf = PyOS_double_to_string(
- PyFloat_AS_DOUBLE(p), 'r',
- 0, 0, NULL);
- if (buf) {
- /* XXX(twouters) cast
- refcount to long
- until %zd is
- universally
- available
- */
- fprintf(stderr,
- "# <float at %p, refcnt=%ld, val=%s>\n",
- p, (long)Py_REFCNT(p), buf);
- PyMem_Free(buf);
- }
- }
- }
- list = list->next;
- }
- }
+/* Print summary info about the state of the optimized allocator */
+void
+_PyFloat_DebugMallocStats(FILE *out)
+{
+ _PyDebugAllocatorStats(out,
+ "free PyFloatObject",
+ numfree, sizeof(PyFloatObject));
}
+
/*----------------------------------------------------------------------------
* _PyFloat_{Pack,Unpack}{4,8}. See floatobject.h.
*/
@@ -2251,7 +2152,7 @@ _PyFloat_Pack8(double x, unsigned char *p, int le)
/* Eighth byte */
*p = flo & 0xFF;
- p += incr;
+ /* p += incr; */
/* Done */
return 0;