summaryrefslogtreecommitdiffstats
path: root/Include/objimpl.h
diff options
context:
space:
mode:
Diffstat (limited to 'Include/objimpl.h')
-rw-r--r--Include/objimpl.h46
1 files changed, 35 insertions, 11 deletions
diff --git a/Include/objimpl.h b/Include/objimpl.h
index e24d42e..2ea3ad5 100644
--- a/Include/objimpl.h
+++ b/Include/objimpl.h
@@ -56,14 +56,14 @@ form of memory management you're using).
Unless you have specific memory management requirements, it is
recommended to use PyObject_{New, NewVar, Del}. */
-/*
+/*
* Core object memory allocator
* ============================
*/
/* The purpose of the object allocator is to make the distinction
between "object memory" and the rest within the Python heap.
-
+
Object memory is the one allocated by PyObject_{New, NewVar}, i.e.
the one that holds the object's representation defined by its C
type structure, *excluding* any object-specific memory buffers that
@@ -172,16 +172,41 @@ extern DL_IMPORT(void) _PyObject_Del(PyObject *);
( (op)->ob_size = (size), PyObject_INIT((op), (typeobj)) )
#define _PyObject_SIZE(typeobj) ( (typeobj)->tp_basicsize )
-#define _PyObject_VAR_SIZE(typeobj, n) \
- ( (typeobj)->tp_basicsize + (n) * (typeobj)->tp_itemsize )
+
+/* _PyObject_VAR_SIZE computes the amount of memory allocated for a vrbl-
+ size object with nitems items, exclusive of gc overhead (if any). The
+ value is rounded up to the closest multiple of sizeof(void *), in order
+ to ensure that pointer fields at the end of the object are correctly
+ aligned for the platform (this is of special importance for subclasses
+ of, e.g., str or long, so that pointers can be stored after the embedded
+ data).
+
+ Note that there's no memory wastage in doing this, as malloc has to
+ return (at worst) pointer-aligned memory anyway
+
+ However, writing the macro to *return* the result is clumsy due to the
+ calculations needed. Instead you must pass the result lvalue as the first
+ argument, and it should be of type size_t (both because that's the
+ correct conceptual type, and because using an unsigned type allows the
+ compiler to generate faster code for the mod computation inside the
+ macro).
+*/
+#define _PyObject_VAR_SIZE(result, typeobj, nitems) \
+ do { \
+ size_t mod; \
+ (result) = (size_t) (typeobj)->tp_basicsize; \
+ (result) += (size_t) ((nitems)*(typeobj)->tp_itemsize); \
+ mod = (result) % SIZEOF_VOID_P; \
+ if (mod) \
+ (result) += SIZEOF_VOID_P - mod; \
+ } while(0)
#define PyObject_NEW(type, typeobj) \
( (type *) PyObject_Init( \
(PyObject *) PyObject_MALLOC( _PyObject_SIZE(typeobj) ), (typeobj)) )
-#define PyObject_NEW_VAR(type, typeobj, n) \
-( (type *) PyObject_InitVar( \
- (PyVarObject *) PyObject_MALLOC( _PyObject_VAR_SIZE((typeobj),(n)) ),\
- (typeobj), (n)) )
+
+#define PyObject_NEW_VAR(type, typeobj, nitems) \
+ ((type *) _PyObject_NewVar(typeobj, nitems))
#define PyObject_DEL(op) PyObject_FREE(op)
@@ -230,8 +255,7 @@ extern DL_IMPORT(void) _PyObject_Del(PyObject *);
#define PyObject_IS_GC(o) (PyType_IS_GC((o)->ob_type) && \
((o)->ob_type->tp_is_gc == NULL || (o)->ob_type->tp_is_gc(o)))
-extern DL_IMPORT(PyObject *) _PyObject_GC_Malloc(PyTypeObject *,
- int nitems, size_t padding);
+extern DL_IMPORT(PyObject *) _PyObject_GC_Malloc(PyTypeObject *, int);
extern DL_IMPORT(PyVarObject *) _PyObject_GC_Resize(PyVarObject *, int);
#define PyObject_GC_Resize(type, op, n) \
@@ -276,7 +300,7 @@ extern PyGC_Head _PyGC_generation0;
#define PyObject_GC_Track(op) _PyObject_GC_Track((PyObject *)op)
#define PyObject_GC_UnTrack(op) _PyObject_GC_UnTrack((PyObject *)op)
-
+
#define PyObject_GC_New(type, typeobj) \
( (type *) _PyObject_GC_New(typeobj) )