-
Notifications
You must be signed in to change notification settings - Fork 203
Closed
Description
I'm experimenting with using mimalloc on txiki.js and when it came to overriding the allocator in QuickJS it seems like a lot of bolierplate is needed:
static void *js_def_malloc(JSMallocState *s, size_t size)
{
void *ptr;
/* Do not allocate zero bytes: behavior is platform dependent */
assert(size != 0);
if (unlikely(s->malloc_size + size > s->malloc_limit))
return NULL;
ptr = malloc(size);
if (!ptr)
return NULL;
s->malloc_count++;
s->malloc_size += js__malloc_usable_size(ptr) + MALLOC_OVERHEAD;
return ptr;
}
static void js_def_free(JSMallocState *s, void *ptr)
{
if (!ptr)
return;
s->malloc_count--;
s->malloc_size -= js__malloc_usable_size(ptr) + MALLOC_OVERHEAD;
free(ptr);
}
static void *js_def_realloc(JSMallocState *s, void *ptr, size_t size)
{
size_t old_size;
if (!ptr) {
if (size == 0)
return NULL;
return js_def_malloc(s, size);
}
old_size = js__malloc_usable_size(ptr);
if (size == 0) {
s->malloc_count--;
s->malloc_size -= old_size + MALLOC_OVERHEAD;
free(ptr);
return NULL;
}
if (s->malloc_size + size - old_size > s->malloc_limit)
return NULL;
ptr = realloc(ptr, size);
if (!ptr)
return NULL;
s->malloc_size += js__malloc_usable_size(ptr) - old_size;
return ptr;
}
This is because the allocator customization works as follows:
typedef struct JSMallocFunctions {
void *(*js_malloc)(JSMallocState *s, size_t size);
void (*js_free)(JSMallocState *s, void *ptr);
void *(*js_realloc)(JSMallocState *s, void *ptr, size_t size);
size_t (*js_malloc_usable_size)(const void *ptr);
} JSMallocFunctions;
So if someone just wants to use mi_malloc
and friends they need to copy the whole code to change a couple of lines.
Here is a proposal: alter JSMallocFunctions
to take the system allocator into account:
typedef struct JSMallocFunctions {
void *(*js_malloc)(JSMallocState *s, size_t size);
void (*js_free)(JSMallocState *s, void *ptr);
void *(*js_realloc)(JSMallocState *s, void *ptr, size_t size);
size_t (*js_malloc_usable_size)(const void *ptr);
void *(*sys_malloc)(size_t size);
void (*sys_free)(void *ptr);
void *(*sys_realloc)(void *ptr, size_t size);
} JSMallocFunctions;
This way, if all you want is to modify the system allocator to use mimalloc (for example), you'd do:
static const JSMallocFunctions mi_mf = {
NULL,
NULL,
NULL,
mi_malloc_usable_size,
mi_malloc,
mi_free,
mi_realloc
};
Internally QuickJS would use the default functions and delegate to the overriden system allocator.
Thoughts?
PS: Why is QuickJS doing that extra MALLOC_OVERHEAD thing?
Metadata
Metadata
Assignees
Labels
No labels