blob: 3a2e65ca592db3956d89909e3b1d697be411e280 [file] [log] [blame]
Neal Norwitzadb69fc2005-12-17 20:54:49 +00001#include "Python.h"
2#include "pyarena.h"
3
Jeremy Hylton56820c22006-02-28 19:57:06 +00004/* A simple arena block structure
5
6 Measurements with standard library modules suggest the average
7 allocation is about 20 bytes and that most compiles use a single
8 block.
9*/
Neal Norwitzadb69fc2005-12-17 20:54:49 +000010
Jeremy Hylton77f1bb22006-02-28 17:53:04 +000011#define DEFAULT_BLOCK_SIZE 8192
12typedef struct _block {
Jeremy Hylton08533fd2006-02-28 18:29:00 +000013 size_t ab_size;
14 size_t ab_offset;
15 struct _block *ab_next;
16 void *ab_mem;
Jeremy Hylton77f1bb22006-02-28 17:53:04 +000017} block;
Neal Norwitzadb69fc2005-12-17 20:54:49 +000018
Jeremy Hylton99b4ee62006-02-28 18:52:28 +000019/* The arena manages two kinds of memory, blocks of raw memory
20 and a list of PyObject* pointers. PyObjects are decrefed
21 when the arena is freed.
22*/
23
Neal Norwitzadb69fc2005-12-17 20:54:49 +000024struct _arena {
Jeremy Hylton08533fd2006-02-28 18:29:00 +000025 block *a_head;
26 block *a_cur;
Jeremy Hylton99b4ee62006-02-28 18:52:28 +000027 PyObject *a_objects;
Jeremy Hylton56820c22006-02-28 19:57:06 +000028#if defined(Py_DEBUG)
29 /* Debug output */
30 size_t total_allocs;
31 size_t total_size;
32 size_t total_blocks;
33 size_t total_block_size;
34 size_t total_big_blocks;
35#endif
Neal Norwitzadb69fc2005-12-17 20:54:49 +000036};
37
Jeremy Hylton77f1bb22006-02-28 17:53:04 +000038static block *
39block_new(size_t size)
40{
Jeremy Hylton08533fd2006-02-28 18:29:00 +000041 /* Allocate header and block as one unit.
42 ab_mem points just past header. */
43 block *b = (block *)malloc(sizeof(block) + size);
44 if (!b)
45 return NULL;
46 b->ab_size = size;
47 b->ab_mem = (void *)(b + 1);
48 b->ab_next = NULL;
49 b->ab_offset = 0;
50 return b;
Neal Norwitzadb69fc2005-12-17 20:54:49 +000051}
52
53static void
Jeremy Hylton77f1bb22006-02-28 17:53:04 +000054block_free(block *b) {
Jeremy Hylton08533fd2006-02-28 18:29:00 +000055 while (b) {
56 block *next = b->ab_next;
57 free(b);
58 b = next;
59 }
Neal Norwitzadb69fc2005-12-17 20:54:49 +000060}
61
Jeremy Hylton77f1bb22006-02-28 17:53:04 +000062static void *
63block_alloc(block *b, size_t size)
64{
Jeremy Hylton08533fd2006-02-28 18:29:00 +000065 void *p;
66 assert(b);
67 if (b->ab_offset + size > b->ab_size) {
68 /* If we need to allocate more memory than will fit in
69 the default block, allocate a one-off block that is
70 exactly the right size. */
71 /* TODO(jhylton): Think about space waste at end of block */
72 block *new = block_new(
73 size < DEFAULT_BLOCK_SIZE ?
74 DEFAULT_BLOCK_SIZE : size);
75 if (!new)
76 return NULL;
77 assert(!b->ab_next);
78 b->ab_next = new;
79 b = new;
80 }
Jeremy Hylton77f1bb22006-02-28 17:53:04 +000081
Jeremy Hylton08533fd2006-02-28 18:29:00 +000082 assert(b->ab_offset + size <= b->ab_size);
83 p = (void *)(((char *)b->ab_mem) + b->ab_offset);
84 b->ab_offset += size;
85 return p;
Jeremy Hylton77f1bb22006-02-28 17:53:04 +000086}
Neal Norwitzadb69fc2005-12-17 20:54:49 +000087
88PyArena *
89PyArena_New()
90{
Jeremy Hylton08533fd2006-02-28 18:29:00 +000091 PyArena* arena = (PyArena *)malloc(sizeof(PyArena));
92 if (!arena)
93 return NULL;
Neal Norwitzadb69fc2005-12-17 20:54:49 +000094
Jeremy Hylton08533fd2006-02-28 18:29:00 +000095 arena->a_head = block_new(DEFAULT_BLOCK_SIZE);
96 arena->a_cur = arena->a_head;
Jeremy Hylton99b4ee62006-02-28 18:52:28 +000097 if (!arena->a_head) {
98 free((void *)arena);
99 return NULL;
100 }
Jeremy Hylton56820c22006-02-28 19:57:06 +0000101 arena->a_objects = PyList_New(0);
Jeremy Hylton99b4ee62006-02-28 18:52:28 +0000102 if (!arena->a_objects) {
103 block_free(arena->a_head);
104 free((void *)arena);
105 return NULL;
106 }
Jeremy Hylton56820c22006-02-28 19:57:06 +0000107#if defined(Py_DEBUG)
108 arena->total_allocs = 0;
109 arena->total_size = 0;
110 arena->total_blocks = 1;
111 arena->total_block_size = DEFAULT_BLOCK_SIZE;
112 arena->total_big_blocks = 0;
113#endif
Jeremy Hylton08533fd2006-02-28 18:29:00 +0000114 return arena;
Neal Norwitzadb69fc2005-12-17 20:54:49 +0000115}
116
117void
118PyArena_Free(PyArena *arena)
119{
Jeremy Hylton08533fd2006-02-28 18:29:00 +0000120 assert(arena);
Jeremy Hylton56820c22006-02-28 19:57:06 +0000121#if defined(Py_DEBUG)
122 /*
123 fprintf(stderr,
124 "alloc=%d size=%d blocks=%d block_size=%d big=%d objects=%d\n",
125 arena->total_allocs, arena->total_size, arena->total_blocks,
126 arena->total_block_size, arena->total_big_blocks,
127 PyList_Size(arena->a_objects));
128 */
129#endif
Jeremy Hylton08533fd2006-02-28 18:29:00 +0000130 block_free(arena->a_head);
Jeremy Hylton99b4ee62006-02-28 18:52:28 +0000131 assert(arena->a_objects->ob_refcnt == 1);
132 Py_DECREF(arena->a_objects);
Jeremy Hylton08533fd2006-02-28 18:29:00 +0000133 free(arena);
Neal Norwitzadb69fc2005-12-17 20:54:49 +0000134}
135
136void *
137PyArena_Malloc(PyArena *arena, size_t size)
138{
Jeremy Hylton08533fd2006-02-28 18:29:00 +0000139 void *p = block_alloc(arena->a_cur, size);
140 if (!p)
141 return NULL;
Jeremy Hylton56820c22006-02-28 19:57:06 +0000142#if defined(Py_DEBUG)
143 arena->total_allocs++;
144 arena->total_size += size;
145#endif
Jeremy Hylton08533fd2006-02-28 18:29:00 +0000146 /* Reset cur if we allocated a new block. */
147 if (arena->a_cur->ab_next) {
148 arena->a_cur = arena->a_cur->ab_next;
Jeremy Hylton56820c22006-02-28 19:57:06 +0000149#if defined(Py_DEBUG)
150 arena->total_blocks++;
151 arena->total_block_size += arena->a_cur->ab_size;
152 if (arena->a_cur->ab_size > DEFAULT_BLOCK_SIZE)
153 arena->total_big_blocks++;
154#endif
Jeremy Hylton08533fd2006-02-28 18:29:00 +0000155 }
156 return p;
Neal Norwitzadb69fc2005-12-17 20:54:49 +0000157}
158
159int
Jeremy Hylton99b4ee62006-02-28 18:52:28 +0000160PyArena_AddPyObject(PyArena *arena, PyObject *obj)
Neal Norwitzadb69fc2005-12-17 20:54:49 +0000161{
Jeremy Hylton99b4ee62006-02-28 18:52:28 +0000162 return PyList_Append(arena->a_objects, obj) >= 0;
Neal Norwitzadb69fc2005-12-17 20:54:49 +0000163}