@@ -1378,6 +1378,11 @@ static size_t js_malloc_usable_size_unknown(const void *ptr)
1378
1378
return 0;
1379
1379
}
1380
1380
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
+
1381
1386
void *js_malloc_rt(JSRuntime *rt, size_t size)
1382
1387
{
1383
1388
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)
1404
1409
return rt->mf.js_malloc_usable_size(ptr);
1405
1410
}
1406
1411
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
+ */
1407
1419
void *js_mallocz_rt(JSRuntime *rt, size_t size)
1408
1420
{
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);
1414
1422
}
1415
1423
1416
1424
/* called by libbf */
@@ -1420,6 +1428,18 @@ static void *js_bf_realloc(void *opaque, void *ptr, size_t size)
1420
1428
return js_realloc_rt(rt, ptr, size);
1421
1429
}
1422
1430
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
+
1423
1443
/* Throw out of memory in case of error */
1424
1444
void *js_malloc(JSContext *ctx, size_t size)
1425
1445
{
@@ -1631,10 +1651,9 @@ JSRuntime *JS_NewRuntime2(const JSMallocFunctions *mf, void *opaque)
1631
1651
ms.opaque = opaque;
1632
1652
ms.malloc_limit = 0;
1633
1653
1634
- rt = mf->js_malloc (&ms, sizeof(JSRuntime));
1654
+ rt = mf->js_calloc (&ms, 1 , sizeof(JSRuntime));
1635
1655
if (!rt)
1636
1656
return NULL;
1637
- memset(rt, 0, sizeof(*rt));
1638
1657
rt->mf = *mf;
1639
1658
if (!rt->mf.js_malloc_usable_size) {
1640
1659
/* use dummy function if none provided */
@@ -1699,6 +1718,30 @@ void JS_SetRuntimeOpaque(JSRuntime *rt, void *opaque)
1699
1718
rt->user_opaque = opaque;
1700
1719
}
1701
1720
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
+
1702
1745
static void *js_def_malloc(JSMallocState *s, size_t size)
1703
1746
{
1704
1747
void *ptr;
@@ -1758,6 +1801,7 @@ static void *js_def_realloc(JSMallocState *s, void *ptr, size_t size)
1758
1801
}
1759
1802
1760
1803
static const JSMallocFunctions def_malloc_funcs = {
1804
+ js_def_calloc,
1761
1805
js_def_malloc,
1762
1806
js_def_free,
1763
1807
js_def_realloc,
0 commit comments