diff options
author | Thomas Wouters <thomas@python.org> | 2006-04-21 10:40:58 (GMT) |
---|---|---|
committer | Thomas Wouters <thomas@python.org> | 2006-04-21 10:40:58 (GMT) |
commit | 49fd7fa4431da299196d74087df4a04f99f9c46f (patch) | |
tree | 35ace5fe78d3d52c7a9ab356ab9f6dbf8d4b71f4 /Python/pyarena.c | |
parent | 9ada3d6e29d5165dadacbe6be07bcd35cfbef59d (diff) | |
download | cpython-49fd7fa4431da299196d74087df4a04f99f9c46f.zip cpython-49fd7fa4431da299196d74087df4a04f99f9c46f.tar.gz cpython-49fd7fa4431da299196d74087df4a04f99f9c46f.tar.bz2 |
Merge p3yk branch with the trunk up to revision 45595. This breaks a fair
number of tests, all because of the codecs/_multibytecodecs issue described
here (it's not a Py3K issue, just something Py3K discovers):
http://mail.python.org/pipermail/python-dev/2006-April/064051.html
Hye-Shik Chang promised to look for a fix, so no need to fix it here. The
tests that are expected to break are:
test_codecencodings_cn
test_codecencodings_hk
test_codecencodings_jp
test_codecencodings_kr
test_codecencodings_tw
test_codecs
test_multibytecodec
This merge fixes an actual test failure (test_weakref) in this branch,
though, so I believe merging is the right thing to do anyway.
Diffstat (limited to 'Python/pyarena.c')
-rw-r--r-- | Python/pyarena.c | 46 |
1 files changed, 41 insertions, 5 deletions
diff --git a/Python/pyarena.c b/Python/pyarena.c index 242ca1d..f11a905 100644 --- a/Python/pyarena.c +++ b/Python/pyarena.c @@ -6,9 +6,16 @@ Measurements with standard library modules suggest the average allocation is about 20 bytes and that most compiles use a single block. + + TODO(jhylton): Think about a realloc API, maybe just for the last + allocation? */ #define DEFAULT_BLOCK_SIZE 8192 +#define ALIGNMENT 8 +#define ALIGNMENT_MASK (ALIGNMENT - 1) +#define ROUNDUP(x) (((x) + ALIGNMENT_MASK) & ~ALIGNMENT_MASK) + typedef struct _block { /* Total number of bytes owned by this block available to pass out. * Read-only after initialization. The first such byte starts at @@ -39,9 +46,25 @@ typedef struct _block { */ struct _arena { + /* Pointer to the first block allocated for the arena, never NULL. + It is used only to find the first block when the arena is + being freed. + */ block *a_head; + + /* Pointer to the block currently used for allocation. It's + ab_next field should be NULL. If it is not-null after a + call to block_alloc(), it means a new block has been allocated + and a_cur should be reset to point it. + */ block *a_cur; + + /* A Python list object containing references to all the PyObject + pointers associated with this area. They will be DECREFed + when the arena is freed. + */ PyObject *a_objects; + #if defined(Py_DEBUG) /* Debug output */ size_t total_allocs; @@ -63,7 +86,8 @@ block_new(size_t size) b->ab_size = size; b->ab_mem = (void *)(b + 1); b->ab_next = NULL; - b->ab_offset = 0; + b->ab_offset = ROUNDUP((Py_uintptr_t)(b->ab_mem)) - + (Py_uintptr_t)(b->ab_mem); return b; } @@ -81,19 +105,20 @@ block_alloc(block *b, size_t size) { void *p; assert(b); + size = ROUNDUP(size); if (b->ab_offset + size > b->ab_size) { /* If we need to allocate more memory than will fit in the default block, allocate a one-off block that is exactly the right size. */ /* TODO(jhylton): Think about space waste at end of block */ - block *new = block_new( + block *newbl = block_new( size < DEFAULT_BLOCK_SIZE ? DEFAULT_BLOCK_SIZE : size); - if (!new) + if (!newbl) return NULL; assert(!b->ab_next); - b->ab_next = new; - b = new; + b->ab_next = newbl; + b = newbl; } assert(b->ab_offset + size <= b->ab_size); @@ -134,6 +159,7 @@ PyArena_New() void PyArena_Free(PyArena *arena) { + int r; assert(arena); #if defined(Py_DEBUG) /* @@ -145,7 +171,17 @@ PyArena_Free(PyArena *arena) */ #endif block_free(arena->a_head); + /* This property normally holds, except when the code being compiled + is sys.getobjects(0), in which case there will be two references. assert(arena->a_objects->ob_refcnt == 1); + */ + + /* Clear all the elements from the list. This is necessary + to guarantee that they will be DECREFed. */ + r = PyList_SetSlice(arena->a_objects, + 0, PyList_GET_SIZE(arena->a_objects), NULL); + assert(r == 0); + assert(PyList_GET_SIZE(arena->a_objects) == 0); Py_DECREF(arena->a_objects); free(arena); } |