Back to index

python3.2  3.2.2
Classes | Defines | Typedefs | Functions
pyarena.c File Reference
#include "Python.h"

Go to the source code of this file.

Classes

struct  _block
struct  _arena

Defines

#define DEFAULT_BLOCK_SIZE   8192
#define ALIGNMENT   8
#define ALIGNMENT_MASK   (ALIGNMENT - 1)
#define ROUNDUP(x)   (((x) + ALIGNMENT_MASK) & ~ALIGNMENT_MASK)

Typedefs

typedef struct _block block

Functions

static blockblock_new (size_t size)
static void block_free (block *b)
static voidblock_alloc (block *b, size_t size)
PyArena * PyArena_New ()
void PyArena_Free (PyArena *arena)
voidPyArena_Malloc (PyArena *arena, size_t size)
int PyArena_AddPyObject (PyArena *arena, PyObject *obj)

Class Documentation

struct _block

Definition at line 18 of file pyarena.c.

Collaboration diagram for _block:
Class Members
void * ab_mem
struct _block * ab_next
size_t ab_offset
size_t ab_size
struct _arena

Definition at line 47 of file pyarena.c.

Collaboration diagram for _arena:
Class Members
block * a_cur
block * a_head
PyObject * a_objects

Define Documentation

#define ALIGNMENT   8

Definition at line 14 of file pyarena.c.

#define ALIGNMENT_MASK   (ALIGNMENT - 1)

Definition at line 15 of file pyarena.c.

#define DEFAULT_BLOCK_SIZE   8192

Definition at line 13 of file pyarena.c.

#define ROUNDUP (   x)    (((x) + ALIGNMENT_MASK) & ~ALIGNMENT_MASK)

Definition at line 16 of file pyarena.c.


Typedef Documentation

typedef struct _block block

Function Documentation

static void* block_alloc ( block b,
size_t  size 
) [static]

Definition at line 103 of file pyarena.c.

{
    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 *newbl = block_new(
                        size < DEFAULT_BLOCK_SIZE ?
                        DEFAULT_BLOCK_SIZE : size);
        if (!newbl)
            return NULL;
        assert(!b->ab_next);
        b->ab_next = newbl;
        b = newbl;
    }

    assert(b->ab_offset + size <= b->ab_size);
    p = (void *)(((char *)b->ab_mem) + b->ab_offset);
    b->ab_offset += size;
    return p;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void block_free ( block b) [static]

Definition at line 94 of file pyarena.c.

                     {
    while (b) {
        block *next = b->ab_next;
        free(b);
        b = next;
    }
}

Here is the caller graph for this function:

static block* block_new ( size_t  size) [static]

Definition at line 78 of file pyarena.c.

{
    /* Allocate header and block as one unit.
       ab_mem points just past header. */
    block *b = (block *)malloc(sizeof(block) + size);
    if (!b)
        return NULL;
    b->ab_size = size;
    b->ab_mem = (void *)(b + 1);
    b->ab_next = NULL;
    b->ab_offset = ROUNDUP((Py_uintptr_t)(b->ab_mem)) -
      (Py_uintptr_t)(b->ab_mem);
    return b;
}

Here is the caller graph for this function:

int PyArena_AddPyObject ( PyArena *  arena,
PyObject obj 
)

Definition at line 212 of file pyarena.c.

{
    int r = PyList_Append(arena->a_objects, obj);
    if (r >= 0) {
        Py_DECREF(obj);
    }
    return r;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void PyArena_Free ( PyArena *  arena)

Definition at line 159 of file pyarena.c.

{
    int r;
    assert(arena);
#if defined(Py_DEBUG)
    /*
    fprintf(stderr,
        "alloc=%d size=%d blocks=%d block_size=%d big=%d objects=%d\n",
        arena->total_allocs, arena->total_size, arena->total_blocks,
        arena->total_block_size, arena->total_big_blocks,
        PyList_Size(arena->a_objects));
    */
#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);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void* PyArena_Malloc ( PyArena *  arena,
size_t  size 
)

Definition at line 189 of file pyarena.c.

{
    void *p = block_alloc(arena->a_cur, size);
    if (!p)
        return PyErr_NoMemory();
#if defined(Py_DEBUG)
    arena->total_allocs++;
    arena->total_size += size;
#endif
    /* Reset cur if we allocated a new block. */
    if (arena->a_cur->ab_next) {
        arena->a_cur = arena->a_cur->ab_next;
#if defined(Py_DEBUG)
        arena->total_blocks++;
        arena->total_block_size += arena->a_cur->ab_size;
        if (arena->a_cur->ab_size > DEFAULT_BLOCK_SIZE)
            ++arena->total_big_blocks;
#endif
    }
    return p;
}

Here is the call graph for this function:

PyArena* PyArena_New ( )

Definition at line 130 of file pyarena.c.

{
    PyArena* arena = (PyArena *)malloc(sizeof(PyArena));
    if (!arena)
        return (PyArena*)PyErr_NoMemory();

    arena->a_head = block_new(DEFAULT_BLOCK_SIZE);
    arena->a_cur = arena->a_head;
    if (!arena->a_head) {
        free((void *)arena);
        return (PyArena*)PyErr_NoMemory();
    }
    arena->a_objects = PyList_New(0);
    if (!arena->a_objects) {
        block_free(arena->a_head);
        free((void *)arena);
        return (PyArena*)PyErr_NoMemory();
    }
#if defined(Py_DEBUG)
    arena->total_allocs = 0;
    arena->total_size = 0;
    arena->total_blocks = 1;
    arena->total_block_size = DEFAULT_BLOCK_SIZE;
    arena->total_big_blocks = 0;
#endif
    return arena;
}

Here is the call graph for this function:

Here is the caller graph for this function: