diff options
Diffstat (limited to 'alloc.c')
-rw-r--r-- | alloc.c | 115 |
1 files changed, 77 insertions, 38 deletions
@@ -18,25 +18,6 @@ #define BLOCKING 1024 -#define DEFINE_ALLOCATOR(name, type) \ -static unsigned int name##_allocs; \ -void *alloc_##name##_node(void) \ -{ \ - static int nr; \ - static type *block; \ - void *ret; \ - \ - if (!nr) { \ - nr = BLOCKING; \ - block = xmalloc(BLOCKING * sizeof(type)); \ - } \ - nr--; \ - name##_allocs++; \ - ret = block++; \ - memset(ret, 0, sizeof(type)); \ - return ret; \ -} - union any_object { struct object object; struct blob blob; @@ -45,32 +26,90 @@ union any_object { struct tag tag; }; -DEFINE_ALLOCATOR(blob, struct blob) -DEFINE_ALLOCATOR(tree, struct tree) -DEFINE_ALLOCATOR(commit, struct commit) -DEFINE_ALLOCATOR(tag, struct tag) -DEFINE_ALLOCATOR(object, union any_object) +struct alloc_state { + int count; /* total number of nodes allocated */ + int nr; /* number of nodes left in current allocation */ + void *p; /* first free node in current allocation */ +}; -#ifdef NO_C99_FORMAT -#define SZ_FMT "%u" -#else -#define SZ_FMT "%zu" -#endif +static inline void *alloc_node(struct alloc_state *s, size_t node_size) +{ + void *ret; -static void report(const char *name, unsigned int count, size_t size) + if (!s->nr) { + s->nr = BLOCKING; + s->p = xmalloc(BLOCKING * node_size); + } + s->nr--; + s->count++; + ret = s->p; + s->p = (char *)s->p + node_size; + memset(ret, 0, node_size); + return ret; +} + +static struct alloc_state blob_state; +void *alloc_blob_node(void) +{ + struct blob *b = alloc_node(&blob_state, sizeof(struct blob)); + b->object.type = OBJ_BLOB; + return b; +} + +static struct alloc_state tree_state; +void *alloc_tree_node(void) +{ + struct tree *t = alloc_node(&tree_state, sizeof(struct tree)); + t->object.type = OBJ_TREE; + return t; +} + +static struct alloc_state tag_state; +void *alloc_tag_node(void) { - fprintf(stderr, "%10s: %8u (" SZ_FMT " kB)\n", name, count, size); + struct tag *t = alloc_node(&tag_state, sizeof(struct tag)); + t->object.type = OBJ_TAG; + return t; } -#undef SZ_FMT +static struct alloc_state object_state; +void *alloc_object_node(void) +{ + struct object *obj = alloc_node(&object_state, sizeof(union any_object)); + obj->type = OBJ_NONE; + return obj; +} + +static struct alloc_state commit_state; + +unsigned int alloc_commit_index(void) +{ + static unsigned int count; + return count++; +} + +void *alloc_commit_node(void) +{ + struct commit *c = alloc_node(&commit_state, sizeof(struct commit)); + c->object.type = OBJ_COMMIT; + c->index = alloc_commit_index(); + return c; +} + +static void report(const char *name, unsigned int count, size_t size) +{ + fprintf(stderr, "%10s: %8u (%"PRIuMAX" kB)\n", + name, count, (uintmax_t) size); +} -#define REPORT(name) \ - report(#name, name##_allocs, name##_allocs*sizeof(struct name) >> 10) +#define REPORT(name, type) \ + report(#name, name##_state.count, name##_state.count * sizeof(type) >> 10) void alloc_report(void) { - REPORT(blob); - REPORT(tree); - REPORT(commit); - REPORT(tag); + REPORT(blob, struct blob); + REPORT(tree, struct tree); + REPORT(commit, struct commit); + REPORT(tag, struct tag); + REPORT(object, union any_object); } |