Skip to content

Commit a1b480e

Browse files
committed
core: use mimalloc
Currently disabled by default until #461 is solved.
1 parent 179be68 commit a1b480e

File tree

2 files changed

+130
-3
lines changed

2 files changed

+130
-3
lines changed

CMakeLists.txt

+15
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ macro(cpr_option OPTION_NAME OPTION_TEXT OPTION_DEFAULT)
4545
endmacro()
4646

4747
cpr_option(BUILD_WITH_ASAN "If ON, build with the address sanitizer enabled" OFF)
48+
cpr_option(BUILD_WITH_MIMALLOC "If ON, build with mimalloc" OFF)
4849
cpr_option(USE_EXTERNAL_FFI "Specify to use external ffi dependency" OFF)
4950

5051
add_subdirectory(deps/quickjs EXCLUDE_FROM_ALL)
@@ -57,6 +58,15 @@ add_subdirectory(deps/sqlite3 EXCLUDE_FROM_ALL)
5758
set(BUILD_WASI "simple" CACHE STRING "WASI implementation")
5859
add_subdirectory(deps/wasm3 EXCLUDE_FROM_ALL)
5960

61+
if(BUILD_WITH_MIMALLOC)
62+
option(MI_OVERRIDE "" OFF)
63+
option(MI_BUILD_SHARED "" OFF)
64+
option(MI_BUILD_STATIC "" ON)
65+
option(MI_BUILD_OBJECT "" OFF)
66+
option(MI_BUILD_TESTS "" OFF)
67+
add_subdirectory(deps/mimalloc EXCLUDE_FROM_ALL)
68+
endif()
69+
6070
find_package(CURL REQUIRED)
6171

6272
add_executable(tjs
@@ -143,6 +153,11 @@ target_compile_definitions(tjs PRIVATE TJS__PLATFORM="${TJS_PLATFORM}")
143153
target_include_directories(tjs PRIVATE ${CURL_INCLUDE_DIRS})
144154
target_link_libraries(tjs qjs uv_a m3 sqlite3 m pthread ${CURL_LIBRARIES})
145155

156+
if (BUILD_WITH_MIMALLOC)
157+
target_compile_definitions(tjs PRIVATE TJS__HAS_MIMALLOC)
158+
target_link_libraries(tjs mimalloc-static)
159+
endif()
160+
146161
if (BUILD_WITH_ASAN)
147162
target_compile_options(tjs PRIVATE -fsanitize=address)
148163
target_link_options(tjs PRIVATE -fsanitize=address)

src/vm.c

+115-3
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,119 @@
2727

2828
#include <string.h>
2929

30+
#ifdef TJS__HAS_MIMALLOC
31+
#include <mimalloc.h>
32+
#endif
3033

3134
#define TJS__DEFAULT_STACK_SIZE 1048576
3235

36+
static inline size_t tjs__malloc_usable_size(const void *ptr) {
37+
#if defined(TJS__HAS_MIMALLOC)
38+
return mi_malloc_usable_size(ptr);
39+
#elif defined(__APPLE__)
40+
return malloc_size(ptr);
41+
#elif defined(_WIN32)
42+
return _msize(ptr);
43+
#elif defined(__linux__) || defined (__CYGWIN__)
44+
return malloc_usable_size(ptr);
45+
#else
46+
// Unknown.
47+
return 0;
48+
#endif
49+
}
50+
51+
static inline void *tjs__malloc(size_t size) {
52+
#ifdef TJS__HAS_MIMALLOC
53+
return mi_malloc(size);
54+
#else
55+
return malloc(size);
56+
#endif
57+
}
58+
59+
static inline void *tjs__calloc(size_t count, size_t size) {
60+
#ifdef TJS__HAS_MIMALLOC
61+
return mi_calloc(count, size);
62+
#else
63+
return calloc(count, size);
64+
#endif
65+
}
66+
67+
static inline void tjs__free(void *ptr) {
68+
#ifdef TJS__HAS_MIMALLOC
69+
mi_free(ptr);
70+
#else
71+
free(ptr);
72+
#endif
73+
}
74+
75+
static inline void *tjs__realloc(void *ptr, size_t size) {
76+
#ifdef TJS__HAS_MIMALLOC
77+
return mi_realloc(ptr, size);
78+
#else
79+
return realloc(ptr, size);
80+
#endif
81+
}
82+
83+
static void *tjs__mf_malloc(JSMallocState *s, size_t size) {
84+
void *ptr;
85+
86+
/* Do not allocate zero bytes: behavior is platform dependent */
87+
assert(size != 0);
88+
89+
if (unlikely(s->malloc_size + size > s->malloc_limit))
90+
return NULL;
91+
92+
ptr = tjs__malloc(size);
93+
if (!ptr)
94+
return NULL;
95+
96+
s->malloc_count++;
97+
s->malloc_size += tjs__malloc_usable_size(ptr);
98+
return ptr;
99+
}
100+
101+
static void tjs__mf_free(JSMallocState *s, void *ptr) {
102+
if (!ptr)
103+
return;
104+
105+
s->malloc_count--;
106+
s->malloc_size -= tjs__malloc_usable_size(ptr);
107+
tjs__free(ptr);
108+
}
109+
110+
static void *tjs__mf_realloc(JSMallocState *s, void *ptr, size_t size) {
111+
size_t old_size;
112+
113+
if (!ptr) {
114+
if (size == 0)
115+
return NULL;
116+
return tjs__mf_malloc(s, size);
117+
}
118+
old_size = tjs__malloc_usable_size(ptr);
119+
if (size == 0) {
120+
s->malloc_count--;
121+
s->malloc_size -= old_size;
122+
tjs__free(ptr);
123+
return NULL;
124+
}
125+
if (s->malloc_size + size - old_size > s->malloc_limit)
126+
return NULL;
127+
128+
ptr = tjs__realloc(ptr, size);
129+
if (!ptr)
130+
return NULL;
131+
132+
s->malloc_size += tjs__malloc_usable_size(ptr) - old_size;
133+
return ptr;
134+
}
135+
136+
static const JSMallocFunctions tjs_mf = {
137+
tjs__mf_malloc,
138+
tjs__mf_free,
139+
tjs__mf_realloc,
140+
tjs__malloc_usable_size
141+
};
142+
33143
/* core */
34144
extern const uint8_t tjs__core[];
35145
extern const uint32_t tjs__core_size;
@@ -157,11 +267,11 @@ TJSRuntime *TJS_NewRuntimeWorker(void) {
157267
}
158268

159269
TJSRuntime *TJS_NewRuntimeInternal(bool is_worker, TJSRunOptions *options) {
160-
TJSRuntime *qrt = calloc(1, sizeof(*qrt));
270+
TJSRuntime *qrt = tjs__calloc(1, sizeof(*qrt));
161271

162272
memcpy(&qrt->options, options, sizeof(*options));
163273

164-
qrt->rt = JS_NewRuntime();
274+
qrt->rt = JS_NewRuntime2(&tjs_mf, NULL);
165275
CHECK_NOT_NULL(qrt->rt);
166276

167277
qrt->ctx = JS_NewContext(qrt->rt);
@@ -279,12 +389,14 @@ void TJS_FreeRuntime(TJSRuntime *qrt) {
279389
JS_FreeRuntime(qrt->rt);
280390
qrt->rt = NULL;
281391

282-
free(qrt);
392+
tjs__free(qrt);
283393
}
284394

285395
void TJS_Initialize(int argc, char **argv) {
286396
curl_global_init(CURL_GLOBAL_ALL);
287397

398+
CHECK_EQ(0, uv_replace_allocator(tjs__malloc, tjs__realloc, tjs__calloc, tjs__free));
399+
288400
tjs__argc = argc;
289401
tjs__argv = uv_setup_args(argc, argv);
290402
}

0 commit comments

Comments
 (0)