Skip to content

Commit 5a41aaa

Browse files
committed
Use calloc rather than malloc + memset
1 parent 5765855 commit 5a41aaa

File tree

3 files changed

+78
-7
lines changed

3 files changed

+78
-7
lines changed

qjs.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,29 @@ static void js_trace_malloc_init(struct trace_malloc_data *s)
226226
free(s->base = malloc(8));
227227
}
228228

229+
static void *js_trace_calloc(JSMallocState *s, size_t count, size_t size)
230+
{
231+
void *ptr;
232+
233+
/* Do not allocate zero bytes: behavior is platform dependent */
234+
assert(count != 0 && size != 0);
235+
236+
if (size > 0)
237+
if (unlikely(count != (count * size) / size))
238+
return NULL;
239+
240+
/* When malloc_limit is 0 (unlimited), malloc_limit - 1 will be SIZE_MAX. */
241+
if (unlikely(s->malloc_size + (count * size) > s->malloc_limit - 1))
242+
return NULL;
243+
ptr = calloc(count, size);
244+
js_trace_malloc_printf(s, "C %zd %zd -> %p\n", count, size, ptr);
245+
if (ptr) {
246+
s->malloc_count++;
247+
s->malloc_size += js__malloc_usable_size(ptr) + MALLOC_OVERHEAD;
248+
}
249+
return ptr;
250+
}
251+
229252
static void *js_trace_malloc(JSMallocState *s, size_t size)
230253
{
231254
void *ptr;
@@ -288,6 +311,7 @@ static void *js_trace_realloc(JSMallocState *s, void *ptr, size_t size)
288311
}
289312

290313
static const JSMallocFunctions trace_mf = {
314+
js_trace_calloc,
291315
js_trace_malloc,
292316
js_trace_free,
293317
js_trace_realloc,

quickjs.c

Lines changed: 51 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1378,6 +1378,11 @@ static size_t js_malloc_usable_size_unknown(const void *ptr)
13781378
return 0;
13791379
}
13801380

1381+
void *js_calloc_rt(JSRuntime *rt, size_t count, size_t size)
1382+
{
1383+
return rt->mf.js_calloc(&rt->malloc_state, count, size);
1384+
}
1385+
13811386
void *js_malloc_rt(JSRuntime *rt, size_t size)
13821387
{
13831388
return rt->mf.js_malloc(&rt->malloc_state, size);
@@ -1404,13 +1409,16 @@ size_t js_malloc_usable_size_rt(JSRuntime *rt, const void *ptr)
14041409
return rt->mf.js_malloc_usable_size(ptr);
14051410
}
14061411

1412+
/**
1413+
* This used to be implemented as malloc + memset, but using calloc
1414+
* yields better performance in initial, bursty allocations, something useful
1415+
* for QuickJS.
1416+
*
1417+
* More information: https://github.com/quickjs-ng/quickjs/pull/519
1418+
*/
14071419
void *js_mallocz_rt(JSRuntime *rt, size_t size)
14081420
{
1409-
void *ptr;
1410-
ptr = js_malloc_rt(rt, size);
1411-
if (!ptr)
1412-
return NULL;
1413-
return memset(ptr, 0, size);
1421+
return js_calloc_rt(rt, 1, size);
14141422
}
14151423

14161424
/* called by libbf */
@@ -1420,6 +1428,18 @@ static void *js_bf_realloc(void *opaque, void *ptr, size_t size)
14201428
return js_realloc_rt(rt, ptr, size);
14211429
}
14221430

1431+
/* Throw out of memory in case of error */
1432+
void *js_calloc(JSContext *ctx, size_t count, size_t size)
1433+
{
1434+
void *ptr;
1435+
ptr = js_calloc_rt(ctx->rt, count, size);
1436+
if (unlikely(!ptr)) {
1437+
JS_ThrowOutOfMemory(ctx);
1438+
return NULL;
1439+
}
1440+
return ptr;
1441+
}
1442+
14231443
/* Throw out of memory in case of error */
14241444
void *js_malloc(JSContext *ctx, size_t size)
14251445
{
@@ -1631,10 +1651,9 @@ JSRuntime *JS_NewRuntime2(const JSMallocFunctions *mf, void *opaque)
16311651
ms.opaque = opaque;
16321652
ms.malloc_limit = 0;
16331653

1634-
rt = mf->js_malloc(&ms, sizeof(JSRuntime));
1654+
rt = mf->js_calloc(&ms, 1, sizeof(JSRuntime));
16351655
if (!rt)
16361656
return NULL;
1637-
memset(rt, 0, sizeof(*rt));
16381657
rt->mf = *mf;
16391658
if (!rt->mf.js_malloc_usable_size) {
16401659
/* use dummy function if none provided */
@@ -1699,6 +1718,30 @@ void JS_SetRuntimeOpaque(JSRuntime *rt, void *opaque)
16991718
rt->user_opaque = opaque;
17001719
}
17011720

1721+
static void *js_def_calloc(JSMallocState *s, size_t count, size_t size)
1722+
{
1723+
void *ptr;
1724+
1725+
/* Do not allocate zero bytes: behavior is platform dependent */
1726+
assert(count != 0 && size != 0);
1727+
1728+
if (size > 0)
1729+
if (unlikely(count != (count * size) / size))
1730+
return NULL;
1731+
1732+
/* When malloc_limit is 0 (unlimited), malloc_limit - 1 will be SIZE_MAX. */
1733+
if (unlikely(s->malloc_size + (count * size) > s->malloc_limit - 1))
1734+
return NULL;
1735+
1736+
ptr = calloc(count, size);
1737+
if (!ptr)
1738+
return NULL;
1739+
1740+
s->malloc_count++;
1741+
s->malloc_size += js__malloc_usable_size(ptr) + MALLOC_OVERHEAD;
1742+
return ptr;
1743+
}
1744+
17021745
static void *js_def_malloc(JSMallocState *s, size_t size)
17031746
{
17041747
void *ptr;
@@ -1758,6 +1801,7 @@ static void *js_def_realloc(JSMallocState *s, void *ptr, size_t size)
17581801
}
17591802

17601803
static const JSMallocFunctions def_malloc_funcs = {
1804+
js_def_calloc,
17611805
js_def_malloc,
17621806
js_def_free,
17631807
js_def_realloc,

quickjs.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,7 @@ typedef struct JSMallocState {
291291
} JSMallocState;
292292

293293
typedef struct JSMallocFunctions {
294+
void *(*js_calloc)(JSMallocState *s, size_t count, size_t size);
294295
void *(*js_malloc)(JSMallocState *s, size_t size);
295296
void (*js_free)(JSMallocState *s, void *ptr);
296297
void *(*js_realloc)(JSMallocState *s, void *ptr, size_t size);
@@ -358,12 +359,14 @@ JS_EXTERN JS_BOOL JS_IsSameValueZero(JSContext *ctx, JSValue op1, JSValue op2);
358359
JS_EXTERN JSValue js_string_codePointRange(JSContext *ctx, JSValue this_val,
359360
int argc, JSValue *argv);
360361

362+
JS_EXTERN void *js_calloc_rt(JSRuntime *rt, size_t count, size_t size);
361363
JS_EXTERN void *js_malloc_rt(JSRuntime *rt, size_t size);
362364
JS_EXTERN void js_free_rt(JSRuntime *rt, void *ptr);
363365
JS_EXTERN void *js_realloc_rt(JSRuntime *rt, void *ptr, size_t size);
364366
JS_EXTERN size_t js_malloc_usable_size_rt(JSRuntime *rt, const void *ptr);
365367
JS_EXTERN void *js_mallocz_rt(JSRuntime *rt, size_t size);
366368

369+
JS_EXTERN void *js_calloc(JSContext *ctx, size_t count, size_t size);
367370
JS_EXTERN void *js_malloc(JSContext *ctx, size_t size);
368371
JS_EXTERN void js_free(JSContext *ctx, void *ptr);
369372
JS_EXTERN void *js_realloc(JSContext *ctx, void *ptr, size_t size);

0 commit comments

Comments
 (0)