4 /* A simple arena block structure.
6 Measurements with standard library modules suggest the average
7 allocation is about 20 bytes and that most compiles use a single
10 TODO(jhylton): Think about a realloc API, maybe just for the last
14 #define DEFAULT_BLOCK_SIZE 8192
16 #define ALIGNMENT_MASK (ALIGNMENT - 1)
17 #define ROUNDUP(x) (((x) + ALIGNMENT_MASK) & ~ALIGNMENT_MASK)
19 typedef struct _block
{
20 /* Total number of bytes owned by this block available to pass out.
21 * Read-only after initialization. The first such byte starts at
26 /* Total number of bytes already passed out. The next byte available
27 * to pass out starts at ab_mem + ab_offset.
31 /* An arena maintains a singly-linked, NULL-terminated list of
32 * all blocks owned by the arena. These are linked via the
35 struct _block
*ab_next
;
37 /* Pointer to the first allocatable byte owned by this block. Read-
38 * only after initialization.
43 /* The arena manages two kinds of memory, blocks of raw memory
44 and a list of PyObject* pointers. PyObjects are decrefed
45 when the arena is freed.
49 /* Pointer to the first block allocated for the arena, never NULL.
50 It is used only to find the first block when the arena is
55 /* Pointer to the block currently used for allocation. It's
56 ab_next field should be NULL. If it is not-null after a
57 call to block_alloc(), it means a new block has been allocated
58 and a_cur should be reset to point it.
62 /* A Python list object containing references to all the PyObject
63 pointers associated with this area. They will be DECREFed
64 when the arena is freed.
73 size_t total_block_size
;
74 size_t total_big_blocks
;
79 block_new(size_t size
)
81 /* Allocate header and block as one unit.
82 ab_mem points just past header. */
83 block
*b
= (block
*)malloc(sizeof(block
) + size
);
87 b
->ab_mem
= (void *)(b
+ 1);
89 b
->ab_offset
= ROUNDUP((Py_uintptr_t
)(b
->ab_mem
)) -
90 (Py_uintptr_t
)(b
->ab_mem
);
95 block_free(block
*b
) {
97 block
*next
= b
->ab_next
;
104 block_alloc(block
*b
, size_t size
)
108 size
= ROUNDUP(size
);
109 if (b
->ab_offset
+ size
> b
->ab_size
) {
110 /* If we need to allocate more memory than will fit in
111 the default block, allocate a one-off block that is
112 exactly the right size. */
113 /* TODO(jhylton): Think about space waste at end of block */
114 block
*newbl
= block_new(
115 size
< DEFAULT_BLOCK_SIZE
?
116 DEFAULT_BLOCK_SIZE
: size
);
124 assert(b
->ab_offset
+ size
<= b
->ab_size
);
125 p
= (void *)(((char *)b
->ab_mem
) + b
->ab_offset
);
126 b
->ab_offset
+= size
;
133 PyArena
* arena
= (PyArena
*)malloc(sizeof(PyArena
));
137 arena
->a_head
= block_new(DEFAULT_BLOCK_SIZE
);
138 arena
->a_cur
= arena
->a_head
;
139 if (!arena
->a_head
) {
143 arena
->a_objects
= PyList_New(0);
144 if (!arena
->a_objects
) {
145 block_free(arena
->a_head
);
149 #if defined(Py_DEBUG)
150 arena
->total_allocs
= 0;
151 arena
->total_size
= 0;
152 arena
->total_blocks
= 1;
153 arena
->total_block_size
= DEFAULT_BLOCK_SIZE
;
154 arena
->total_big_blocks
= 0;
160 PyArena_Free(PyArena
*arena
)
164 #if defined(Py_DEBUG)
167 "alloc=%d size=%d blocks=%d block_size=%d big=%d objects=%d\n",
168 arena->total_allocs, arena->total_size, arena->total_blocks,
169 arena->total_block_size, arena->total_big_blocks,
170 PyList_Size(arena->a_objects));
173 block_free(arena
->a_head
);
174 /* This property normally holds, except when the code being compiled
175 is sys.getobjects(0), in which case there will be two references.
176 assert(arena->a_objects->ob_refcnt == 1);
179 /* Clear all the elements from the list. This is necessary
180 to guarantee that they will be DECREFed. */
181 r
= PyList_SetSlice(arena
->a_objects
,
182 0, PyList_GET_SIZE(arena
->a_objects
), NULL
);
184 assert(PyList_GET_SIZE(arena
->a_objects
) == 0);
185 Py_DECREF(arena
->a_objects
);
190 PyArena_Malloc(PyArena
*arena
, size_t size
)
192 void *p
= block_alloc(arena
->a_cur
, size
);
195 #if defined(Py_DEBUG)
196 arena
->total_allocs
++;
197 arena
->total_size
+= size
;
199 /* Reset cur if we allocated a new block. */
200 if (arena
->a_cur
->ab_next
) {
201 arena
->a_cur
= arena
->a_cur
->ab_next
;
202 #if defined(Py_DEBUG)
203 arena
->total_blocks
++;
204 arena
->total_block_size
+= arena
->a_cur
->ab_size
;
205 if (arena
->a_cur
->ab_size
> DEFAULT_BLOCK_SIZE
)
206 ++arena
->total_big_blocks
;
213 PyArena_AddPyObject(PyArena
*arena
, PyObject
*obj
)
215 int r
= PyList_Append(arena
->a_objects
, obj
);