mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2025-12-20 22:10:13 +01:00
[script] Slab allocator
Allocate small objects from a pool and maintain a per-size free-list.
This commit is contained in:
parent
83f0e6cf62
commit
c5c04528b5
2 changed files with 85 additions and 2 deletions
|
|
@ -41,6 +41,10 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
|
#ifndef MAX
|
||||||
|
#define MAX(a,b) (((a)>=(b))?(a):(b))
|
||||||
|
#endif
|
||||||
|
|
||||||
csi_status_t
|
csi_status_t
|
||||||
_csi_error (csi_status_t status)
|
_csi_error (csi_status_t status)
|
||||||
{
|
{
|
||||||
|
|
@ -90,19 +94,74 @@ _csi_free (csi_t *ctx, void *ptr)
|
||||||
void *
|
void *
|
||||||
_csi_slab_alloc (csi_t *ctx, int size)
|
_csi_slab_alloc (csi_t *ctx, int size)
|
||||||
{
|
{
|
||||||
|
int chunk_size;
|
||||||
|
csi_chunk_t *chunk;
|
||||||
|
void *ptr;
|
||||||
|
|
||||||
if (_csi_unlikely (ctx->status))
|
if (_csi_unlikely (ctx->status))
|
||||||
return NULL;
|
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
|
void
|
||||||
_csi_slab_free (csi_t *ctx, void *ptr, int size)
|
_csi_slab_free (csi_t *ctx, void *ptr, int size)
|
||||||
{
|
{
|
||||||
|
int chunk_size;
|
||||||
|
void **free_list;
|
||||||
|
|
||||||
if (_csi_unlikely (ptr == NULL))
|
if (_csi_unlikely (ptr == NULL))
|
||||||
return;
|
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
|
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_foreach (&ctx->strings, _intern_string_pluck, ctx);
|
||||||
_csi_hash_table_fini (&ctx->strings);
|
_csi_hash_table_fini (&ctx->strings);
|
||||||
|
|
||||||
|
_csi_slab_fini (ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
csi_status_t
|
csi_status_t
|
||||||
|
|
|
||||||
|
|
@ -409,6 +409,17 @@ struct _csi_file {
|
||||||
const csi_filter_funcs_t *filter;
|
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 {
|
struct _csi_scanner {
|
||||||
csi_status_t status;
|
csi_status_t status;
|
||||||
|
|
||||||
|
|
@ -432,6 +443,12 @@ struct _csi_scanner {
|
||||||
|
|
||||||
typedef cairo_script_interpreter_hooks_t csi_hooks_t;
|
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 {
|
struct _cairo_script_interpreter {
|
||||||
int ref_count;
|
int ref_count;
|
||||||
csi_status_t status;
|
csi_status_t status;
|
||||||
|
|
@ -445,6 +462,11 @@ struct _cairo_script_interpreter {
|
||||||
|
|
||||||
csi_scanner_t scanner;
|
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 */
|
/* caches of live data */
|
||||||
csi_list_t *_images;
|
csi_list_t *_images;
|
||||||
csi_list_t *_faces;
|
csi_list_t *_faces;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue