blob: c6d0139af1e7bfad3dbb3bf449a0a4fd9b87bf2c [file] [log] [blame]
Neal Norwitzadb69fc2005-12-17 20:54:49 +00001#include "Python.h"
2#include "pyarena.h"
3
Jeremy Hylton77f1bb22006-02-28 17:53:04 +00004/* A simple arena block structure */
5/* TODO(jhylton): Measurement to justify block size. */
Neal Norwitzadb69fc2005-12-17 20:54:49 +00006
Jeremy Hylton77f1bb22006-02-28 17:53:04 +00007#define DEFAULT_BLOCK_SIZE 8192
8typedef struct _block {
Jeremy Hylton08533fd2006-02-28 18:29:00 +00009 size_t ab_size;
10 size_t ab_offset;
11 struct _block *ab_next;
12 void *ab_mem;
Jeremy Hylton77f1bb22006-02-28 17:53:04 +000013} block;
Neal Norwitzadb69fc2005-12-17 20:54:49 +000014
Jeremy Hylton99b4ee62006-02-28 18:52:28 +000015/* The arena manages two kinds of memory, blocks of raw memory
16 and a list of PyObject* pointers. PyObjects are decrefed
17 when the arena is freed.
18*/
19
Neal Norwitzadb69fc2005-12-17 20:54:49 +000020struct _arena {
Jeremy Hylton08533fd2006-02-28 18:29:00 +000021 block *a_head;
22 block *a_cur;
Jeremy Hylton99b4ee62006-02-28 18:52:28 +000023 PyObject *a_objects;
Neal Norwitzadb69fc2005-12-17 20:54:49 +000024};
25
Jeremy Hylton77f1bb22006-02-28 17:53:04 +000026static block *
27block_new(size_t size)
28{
Jeremy Hylton08533fd2006-02-28 18:29:00 +000029 /* Allocate header and block as one unit.
30 ab_mem points just past header. */
31 block *b = (block *)malloc(sizeof(block) + size);
32 if (!b)
33 return NULL;
34 b->ab_size = size;
35 b->ab_mem = (void *)(b + 1);
36 b->ab_next = NULL;
37 b->ab_offset = 0;
38 return b;
Neal Norwitzadb69fc2005-12-17 20:54:49 +000039}
40
41static void
Jeremy Hylton77f1bb22006-02-28 17:53:04 +000042block_free(block *b) {
Jeremy Hylton08533fd2006-02-28 18:29:00 +000043 while (b) {
44 block *next = b->ab_next;
45 free(b);
46 b = next;
47 }
Neal Norwitzadb69fc2005-12-17 20:54:49 +000048}
49
Jeremy Hylton77f1bb22006-02-28 17:53:04 +000050static void *
51block_alloc(block *b, size_t size)
52{
Jeremy Hylton08533fd2006-02-28 18:29:00 +000053 void *p;
54 assert(b);
55 if (b->ab_offset + size > b->ab_size) {
56 /* If we need to allocate more memory than will fit in
57 the default block, allocate a one-off block that is
58 exactly the right size. */
59 /* TODO(jhylton): Think about space waste at end of block */
60 block *new = block_new(
61 size < DEFAULT_BLOCK_SIZE ?
62 DEFAULT_BLOCK_SIZE : size);
63 if (!new)
64 return NULL;
65 assert(!b->ab_next);
66 b->ab_next = new;
67 b = new;
68 }
Jeremy Hylton77f1bb22006-02-28 17:53:04 +000069
Jeremy Hylton08533fd2006-02-28 18:29:00 +000070 assert(b->ab_offset + size <= b->ab_size);
71 p = (void *)(((char *)b->ab_mem) + b->ab_offset);
72 b->ab_offset += size;
73 return p;
Jeremy Hylton77f1bb22006-02-28 17:53:04 +000074}
Neal Norwitzadb69fc2005-12-17 20:54:49 +000075
76PyArena *
77PyArena_New()
78{
Jeremy Hylton08533fd2006-02-28 18:29:00 +000079 PyArena* arena = (PyArena *)malloc(sizeof(PyArena));
80 if (!arena)
81 return NULL;
Neal Norwitzadb69fc2005-12-17 20:54:49 +000082
Jeremy Hylton08533fd2006-02-28 18:29:00 +000083 arena->a_head = block_new(DEFAULT_BLOCK_SIZE);
84 arena->a_cur = arena->a_head;
Jeremy Hylton99b4ee62006-02-28 18:52:28 +000085 if (!arena->a_head) {
86 free((void *)arena);
87 return NULL;
88 }
89 arena->a_objects = PyList_New(16);
90 if (!arena->a_objects) {
91 block_free(arena->a_head);
92 free((void *)arena);
93 return NULL;
94 }
Jeremy Hylton08533fd2006-02-28 18:29:00 +000095 return arena;
Neal Norwitzadb69fc2005-12-17 20:54:49 +000096}
97
98void
99PyArena_Free(PyArena *arena)
100{
Jeremy Hylton08533fd2006-02-28 18:29:00 +0000101 assert(arena);
102 block_free(arena->a_head);
Jeremy Hylton99b4ee62006-02-28 18:52:28 +0000103 assert(arena->a_objects->ob_refcnt == 1);
104 Py_DECREF(arena->a_objects);
Jeremy Hylton08533fd2006-02-28 18:29:00 +0000105 free(arena);
Neal Norwitzadb69fc2005-12-17 20:54:49 +0000106}
107
108void *
109PyArena_Malloc(PyArena *arena, size_t size)
110{
Jeremy Hylton08533fd2006-02-28 18:29:00 +0000111 void *p = block_alloc(arena->a_cur, size);
112 if (!p)
113 return NULL;
114 /* Reset cur if we allocated a new block. */
115 if (arena->a_cur->ab_next) {
116 arena->a_cur = arena->a_cur->ab_next;
117 }
118 return p;
Neal Norwitzadb69fc2005-12-17 20:54:49 +0000119}
120
121int
Jeremy Hylton99b4ee62006-02-28 18:52:28 +0000122PyArena_AddPyObject(PyArena *arena, PyObject *obj)
Neal Norwitzadb69fc2005-12-17 20:54:49 +0000123{
Jeremy Hylton99b4ee62006-02-28 18:52:28 +0000124 return PyList_Append(arena->a_objects, obj) >= 0;
Neal Norwitzadb69fc2005-12-17 20:54:49 +0000125}