[script] Slab allocator

Allocate small objects from a pool and maintain a per-size free-list.
This commit is contained in:
Chris Wilson 2008-12-10 17:30:21 +00:00
parent 83f0e6cf62
commit c5c04528b5
2 changed files with 85 additions and 2 deletions

View file

@ -41,6 +41,10 @@
#include <string.h>
#include <math.h>
#ifndef MAX
#define MAX(a,b) (((a)>=(b))?(a):(b))
#endif
csi_status_t
_csi_error (csi_status_t status)
{
@ -90,19 +94,74 @@ _csi_free (csi_t *ctx, void *ptr)
void *
_csi_slab_alloc (csi_t *ctx, int size)
{
int chunk_size;
csi_chunk_t *chunk;
void *ptr;
if (_csi_unlikely (ctx->status))
return NULL;
return malloc (size);
chunk_size = 2 * sizeof (void *);
chunk_size = (size + chunk_size - 1) / chunk_size;
if (ctx->slabs[chunk_size].free_list) {
ptr = ctx->slabs[chunk_size].free_list;
ctx->slabs[chunk_size].free_list = *(void **) ptr;
return ptr;
}
chunk = ctx->slabs[chunk_size].chunk;
if (chunk == NULL || ! chunk->rem) {
int cnt = MAX (128, 8192 / (chunk_size * 2 * sizeof (void *)));
chunk = _csi_alloc (ctx,
sizeof (csi_chunk_t) +
cnt * chunk_size * 2 * sizeof (void *));
if (_csi_unlikely (chunk == NULL))
return NULL;
chunk->rem = cnt;
chunk->ptr = (char *) (chunk + 1);
chunk->next = ctx->slabs[chunk_size].chunk;
ctx->slabs[chunk_size].chunk = chunk;
}
ptr = chunk->ptr;
chunk->ptr += chunk_size * 2 * sizeof (void *);
chunk->rem--;
return ptr;
}
void
_csi_slab_free (csi_t *ctx, void *ptr, int size)
{
int chunk_size;
void **free_list;
if (_csi_unlikely (ptr == NULL))
return;
free (ptr);
chunk_size = 2 * sizeof (void *);
chunk_size = (size + chunk_size - 1) / chunk_size;
free_list = ptr;
*free_list = ctx->slabs[chunk_size].free_list;
ctx->slabs[chunk_size].free_list = ptr;
}
static void
_csi_slab_fini (csi_t *ctx)
{
unsigned int i;
for (i = 0; i < sizeof (ctx->slabs) / sizeof (ctx->slabs[0]); i++) {
while (ctx->slabs[i].chunk != NULL) {
csi_chunk_t *chunk = ctx->slabs[i].chunk;
ctx->slabs[i].chunk = chunk->next;
_csi_free (ctx, chunk);
}
}
}
static csi_status_t
@ -318,6 +377,8 @@ _csi_fini (csi_t *ctx)
_csi_hash_table_foreach (&ctx->strings, _intern_string_pluck, ctx);
_csi_hash_table_fini (&ctx->strings);
_csi_slab_fini (ctx);
}
csi_status_t

View file

@ -409,6 +409,17 @@ struct _csi_file {
const csi_filter_funcs_t *filter;
};
union _csi_union_object {
void *ptr[2];
csi_stack_t stack;
csi_array_t arry;
csi_dictionary_t dictionary;
csi_matrix_t matrix;
csi_string_t string;
csi_file_t file;
csi_object_t object;
};
struct _csi_scanner {
csi_status_t status;
@ -432,6 +443,12 @@ struct _csi_scanner {
typedef cairo_script_interpreter_hooks_t csi_hooks_t;
typedef struct _csi_chunk {
struct _csi_chunk *next;
int rem;
char *ptr;
} csi_chunk_t;
struct _cairo_script_interpreter {
int ref_count;
csi_status_t status;
@ -445,6 +462,11 @@ struct _cairo_script_interpreter {
csi_scanner_t scanner;
struct {
csi_chunk_t *chunk;
void *free_list;
} slabs[(sizeof (union _csi_union_object) + (2*sizeof (void *)-1))/ (2*sizeof (void*))];
/* caches of live data */
csi_list_t *_images;
csi_list_t *_faces;