Skip to content

Commit 9ba36e2

Browse files
authored
Implement shared heap for AOT (#3815)
1 parent c4aa1de commit 9ba36e2

29 files changed

+684
-81
lines changed

.github/workflows/compilation_on_android_ubuntu.yml

+1
Original file line numberDiff line numberDiff line change
@@ -585,6 +585,7 @@ jobs:
585585
cmake ..
586586
cmake --build . --config Debug --parallel 4
587587
./shared_heap_test
588+
./shared_heap_test --aot
588589
589590
test:
590591
needs:

.github/workflows/compilation_on_macos.yml

+1
Original file line numberDiff line numberDiff line change
@@ -394,3 +394,4 @@ jobs:
394394
cmake ..
395395
cmake --build . --config Debug --parallel 4
396396
./shared_heap_test
397+
./shared_heap_test --aot

.github/workflows/nightly_run.yml

+1
Original file line numberDiff line numberDiff line change
@@ -600,6 +600,7 @@ jobs:
600600
cmake ..
601601
cmake --build . --config Debug --parallel 4
602602
./shared_heap_test
603+
./shared_heap_test --aot
603604
604605
test:
605606
needs:

core/config.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -396,7 +396,9 @@
396396
#define APP_HEAP_SIZE_DEFAULT (8 * 1024)
397397
#endif
398398
#define APP_HEAP_SIZE_MIN (256)
399-
#define APP_HEAP_SIZE_MAX (512 * 1024 * 1024)
399+
/* The ems memory allocator supports maximal heap size 1GB,
400+
see ems_gc_internal.h */
401+
#define APP_HEAP_SIZE_MAX (1024 * 1024 * 1024)
400402

401403
/* Default min/max gc heap size of each app */
402404
#ifndef GC_HEAP_SIZE_DEFAULT

core/iwasm/aot/aot_runtime.c

+21
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ bh_static_assert(sizeof(AOTMemoryInstance) == 120);
5757
bh_static_assert(offsetof(AOTTableInstance, elems) == 24);
5858

5959
bh_static_assert(offsetof(AOTModuleInstanceExtra, stack_sizes) == 0);
60+
bh_static_assert(offsetof(AOTModuleInstanceExtra, shared_heap_base_addr_adj)
61+
== 8);
62+
bh_static_assert(offsetof(AOTModuleInstanceExtra, shared_heap_start_off) == 16);
6063

6164
bh_static_assert(sizeof(CApiFuncImport) == sizeof(uintptr_t) * 3);
6265

@@ -1885,6 +1888,24 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent,
18851888
extra->stack_sizes =
18861889
aot_get_data_section_addr(module, AOT_STACK_SIZES_SECTION_NAME, NULL);
18871890

1891+
/*
1892+
* The AOT code checks whether the n bytes to access are in shared heap
1893+
* by checking whether the beginning address meets:
1894+
* addr >= start_off && addr <= end_off - n-bytes + 1
1895+
* where n is 1/2/4/8/16 and `end_off - n-bytes + 1` is constant, e.g.,
1896+
* UINT32_MAX, UINT32_MAX-1, UINT32_MAX-3 for n = 1, 2 or 4 in 32-bit
1897+
* target. To simplify the check, when shared heap is disabled, we set
1898+
* the start off to UINT64_MAX in 64-bit target and UINT32_MAX in 32-bit
1899+
* target, so in the checking, the above formula will be false, we don't
1900+
* need to check whether the shared heap is enabled or not in the AOT
1901+
* code.
1902+
*/
1903+
#if UINTPTR_MAX == UINT64_MAX
1904+
extra->shared_heap_start_off.u64 = UINT64_MAX;
1905+
#else
1906+
extra->shared_heap_start_off.u32[0] = UINT32_MAX;
1907+
#endif
1908+
18881909
#if WASM_ENABLE_PERF_PROFILING != 0
18891910
total_size = sizeof(AOTFuncPerfProfInfo)
18901911
* ((uint64)module->import_func_count + module->func_count);

core/iwasm/aot/aot_runtime.h

+8
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,14 @@ typedef struct AOTFunctionInstance {
111111

112112
typedef struct AOTModuleInstanceExtra {
113113
DefPointer(const uint32 *, stack_sizes);
114+
/*
115+
* Adjusted shared heap based addr to simple the calculation
116+
* in the aot code. The value is:
117+
* shared_heap->base_addr - shared_heap->start_off
118+
*/
119+
DefPointer(uint8 *, shared_heap_base_addr_adj);
120+
MemBound shared_heap_start_off;
121+
114122
WASMModuleInstanceExtraCommon common;
115123
AOTFunctionInstance **functions;
116124
uint32 function_count;

core/iwasm/common/wasm_memory.c

+99-18
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ runtime_malloc(uint64 size)
165165
WASMSharedHeap *
166166
wasm_runtime_create_shared_heap(SharedHeapInitArgs *init_args)
167167
{
168-
uint64 heap_struct_size = sizeof(WASMSharedHeap);
168+
uint64 heap_struct_size = sizeof(WASMSharedHeap), map_size;
169169
uint32 size = init_args->size;
170170
WASMSharedHeap *heap;
171171

@@ -192,7 +192,18 @@ wasm_runtime_create_shared_heap(SharedHeapInitArgs *init_args)
192192
goto fail3;
193193
}
194194

195-
if (!(heap->base_addr = wasm_mmap_linear_memory(size, size))) {
195+
#ifndef OS_ENABLE_HW_BOUND_CHECK
196+
map_size = size;
197+
#else
198+
/* Totally 8G is mapped, the opcode load/store address range is 0 to 8G:
199+
* ea = i + memarg.offset
200+
* both i and memarg.offset are u32 in range 0 to 4G
201+
* so the range of ea is 0 to 8G
202+
*/
203+
map_size = 8 * (uint64)BH_GB;
204+
#endif
205+
206+
if (!(heap->base_addr = wasm_mmap_linear_memory(map_size, size))) {
196207
goto fail3;
197208
}
198209
if (!mem_allocator_create_with_struct_and_pool(
@@ -213,7 +224,7 @@ wasm_runtime_create_shared_heap(SharedHeapInitArgs *init_args)
213224
return heap;
214225

215226
fail4:
216-
wasm_munmap_linear_memory(heap->base_addr, size, size);
227+
wasm_munmap_linear_memory(heap->base_addr, size, map_size);
217228
fail3:
218229
wasm_runtime_free(heap->heap_handle);
219230
fail2:
@@ -245,18 +256,52 @@ wasm_runtime_attach_shared_heap_internal(WASMModuleInstanceCommon *module_inst,
245256

246257
#if WASM_ENABLE_INTERP != 0
247258
if (module_inst->module_type == Wasm_Module_Bytecode) {
248-
if (((WASMModuleInstance *)module_inst)->e->shared_heap) {
259+
WASMModuleInstanceExtra *e =
260+
(WASMModuleInstanceExtra *)((WASMModuleInstance *)module_inst)->e;
261+
if (e->shared_heap) {
249262
LOG_WARNING("A shared heap is already attached");
250263
return false;
251264
}
252-
((WASMModuleInstance *)module_inst)->e->shared_heap = shared_heap;
253-
}
265+
e->shared_heap = shared_heap;
266+
#if WASM_ENABLE_JIT != 0
267+
#if UINTPTR_MAX == UINT64_MAX
268+
if (memory->is_memory64)
269+
e->shared_heap_start_off.u64 = shared_heap->start_off_mem64;
270+
else
271+
e->shared_heap_start_off.u64 = shared_heap->start_off_mem32;
272+
e->shared_heap_base_addr_adj =
273+
shared_heap->base_addr - e->shared_heap_start_off.u64;
274+
#else
275+
e->shared_heap_start_off.u32[0] = (uint32)shared_heap->start_off_mem32;
276+
e->shared_heap_base_addr_adj =
277+
shared_heap->base_addr - e->shared_heap_start_off.u32[0];
254278
#endif
279+
#endif /* end of WASM_ENABLE_JIT != 0 */
280+
}
281+
#endif /* end of WASM_ENABLE_INTERP != 0 */
255282
#if WASM_ENABLE_AOT != 0
256283
if (module_inst->module_type == Wasm_Module_AoT) {
257-
// TODO
258-
}
284+
AOTModuleInstanceExtra *e =
285+
(AOTModuleInstanceExtra *)((AOTModuleInstance *)module_inst)->e;
286+
if (e->shared_heap) {
287+
LOG_WARNING("A shared heap is already attached");
288+
return false;
289+
}
290+
e->shared_heap = shared_heap;
291+
#if UINTPTR_MAX == UINT64_MAX
292+
if (memory->is_memory64)
293+
e->shared_heap_start_off.u64 = shared_heap->start_off_mem64;
294+
else
295+
e->shared_heap_start_off.u64 = shared_heap->start_off_mem32;
296+
e->shared_heap_base_addr_adj =
297+
shared_heap->base_addr - e->shared_heap_start_off.u64;
298+
#else
299+
e->shared_heap_start_off.u32[0] = (uint32)shared_heap->start_off_mem32;
300+
e->shared_heap_base_addr_adj =
301+
shared_heap->base_addr - e->shared_heap_start_off.u32[0];
259302
#endif
303+
}
304+
#endif /* end of WASM_ENABLE_AOT != 0 */
260305

261306
return true;
262307
}
@@ -277,14 +322,32 @@ wasm_runtime_detach_shared_heap_internal(WASMModuleInstanceCommon *module_inst)
277322
{
278323
#if WASM_ENABLE_INTERP != 0
279324
if (module_inst->module_type == Wasm_Module_Bytecode) {
280-
((WASMModuleInstance *)module_inst)->e->shared_heap = NULL;
281-
}
325+
WASMModuleInstanceExtra *e =
326+
(WASMModuleInstanceExtra *)((WASMModuleInstance *)module_inst)->e;
327+
e->shared_heap = NULL;
328+
#if WASM_ENABLE_JIT != 0
329+
#if UINTPTR_MAX == UINT64_MAX
330+
e->shared_heap_start_off.u64 = UINT64_MAX;
331+
#else
332+
e->shared_heap_start_off.u32[0] = UINT32_MAX;
333+
#endif
334+
e->shared_heap_base_addr_adj = NULL;
282335
#endif
336+
}
337+
#endif /* end of WASM_ENABLE_INTERP != 0 */
283338
#if WASM_ENABLE_AOT != 0
284339
if (module_inst->module_type == Wasm_Module_AoT) {
285-
// TODO
286-
}
340+
AOTModuleInstanceExtra *e =
341+
(AOTModuleInstanceExtra *)((AOTModuleInstance *)module_inst)->e;
342+
e->shared_heap = NULL;
343+
#if UINTPTR_MAX == UINT64_MAX
344+
e->shared_heap_start_off.u64 = UINT64_MAX;
345+
#else
346+
e->shared_heap_start_off.u32[0] = UINT32_MAX;
287347
#endif
348+
e->shared_heap_base_addr_adj = NULL;
349+
}
350+
#endif /* end of WASM_ENABLE_AOT != 0 */
288351
}
289352

290353
void
@@ -307,13 +370,21 @@ get_shared_heap(WASMModuleInstanceCommon *module_inst_comm)
307370
#endif
308371
#if WASM_ENABLE_AOT != 0
309372
if (module_inst_comm->module_type == Wasm_Module_AoT) {
310-
// TODO
311-
return NULL;
373+
AOTModuleInstanceExtra *e =
374+
(AOTModuleInstanceExtra *)((AOTModuleInstance *)module_inst_comm)
375+
->e;
376+
return e->shared_heap;
312377
}
313378
#endif
314379
return NULL;
315380
}
316381

382+
WASMSharedHeap *
383+
wasm_runtime_get_shared_heap(WASMModuleInstanceCommon *module_inst_comm)
384+
{
385+
return get_shared_heap(module_inst_comm);
386+
}
387+
317388
static bool
318389
is_app_addr_in_shared_heap(WASMModuleInstanceCommon *module_inst,
319390
bool is_memory64, uint64 app_offset, uint32 bytes)
@@ -324,6 +395,10 @@ is_app_addr_in_shared_heap(WASMModuleInstanceCommon *module_inst,
324395
return false;
325396
}
326397

398+
if (bytes == 0) {
399+
bytes = 1;
400+
}
401+
327402
if (!is_memory64) {
328403
if (app_offset >= heap->start_off_mem32
329404
&& app_offset <= UINT32_MAX - bytes + 1) {
@@ -457,17 +532,23 @@ wasm_runtime_memory_init(mem_alloc_type_t mem_alloc_type,
457532

458533
#if WASM_ENABLE_SHARED_HEAP != 0
459534
static void
460-
wasm_runtime_destroy_shared_heaps()
535+
destroy_shared_heaps()
461536
{
462537
WASMSharedHeap *heap = shared_heap_list;
463538
WASMSharedHeap *cur;
539+
uint64 map_size;
464540

465541
while (heap) {
466542
cur = heap;
467543
heap = heap->next;
468544
mem_allocator_destroy(cur->heap_handle);
469545
wasm_runtime_free(cur->heap_handle);
470-
wasm_munmap_linear_memory(cur->base_addr, cur->size, cur->size);
546+
#ifndef OS_ENABLE_HW_BOUND_CHECK
547+
map_size = cur->size;
548+
#else
549+
map_size = 8 * (uint64)BH_GB;
550+
#endif
551+
wasm_munmap_linear_memory(cur->base_addr, cur->size, map_size);
471552
wasm_runtime_free(cur);
472553
}
473554
}
@@ -477,7 +558,7 @@ void
477558
wasm_runtime_memory_destroy(void)
478559
{
479560
#if WASM_ENABLE_SHARED_HEAP != 0
480-
wasm_runtime_destroy_shared_heaps();
561+
destroy_shared_heaps();
481562
#endif
482563

483564
if (memory_mode == MEMORY_MODE_POOL) {
@@ -1178,7 +1259,7 @@ wasm_mremap_linear_memory(void *mapped_mem, uint64 old_size, uint64 new_size,
11781259
}
11791260

11801261
static void *
1181-
wasm_mmap_linear_memory(uint64_t map_size, uint64 commit_size)
1262+
wasm_mmap_linear_memory(uint64 map_size, uint64 commit_size)
11821263
{
11831264
return wasm_mremap_linear_memory(NULL, 0, map_size, commit_size);
11841265
}

core/iwasm/common/wasm_memory.h

+4
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,13 @@ wasm_runtime_attach_shared_heap_internal(WASMModuleInstanceCommon *module_inst,
5454

5555
void
5656
wasm_runtime_detach_shared_heap(WASMModuleInstanceCommon *module_inst);
57+
5758
void
5859
wasm_runtime_detach_shared_heap_internal(WASMModuleInstanceCommon *module_inst);
5960

61+
WASMSharedHeap *
62+
wasm_runtime_get_shared_heap(WASMModuleInstanceCommon *module_inst_comm);
63+
6064
uint64
6165
wasm_runtime_shared_heap_malloc(WASMModuleInstanceCommon *module_inst,
6266
uint64 size, void **p_native_addr);

core/iwasm/common/wasm_runtime_common.c

+18
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,9 @@ static bool
185185
is_sig_addr_in_guard_pages(void *sig_addr, WASMModuleInstance *module_inst)
186186
{
187187
WASMMemoryInstance *memory_inst;
188+
#if WASM_ENABLE_SHARED_HEAP != 0
189+
WASMSharedHeap *shared_heap;
190+
#endif
188191
uint8 *mapped_mem_start_addr = NULL;
189192
uint8 *mapped_mem_end_addr = NULL;
190193
uint32 i;
@@ -202,6 +205,21 @@ is_sig_addr_in_guard_pages(void *sig_addr, WASMModuleInstance *module_inst)
202205
}
203206
}
204207

208+
#if WASM_ENABLE_SHARED_HEAP != 0
209+
shared_heap =
210+
wasm_runtime_get_shared_heap((WASMModuleInstanceCommon *)module_inst);
211+
if (shared_heap) {
212+
mapped_mem_start_addr = shared_heap->base_addr;
213+
mapped_mem_end_addr = shared_heap->base_addr + 8 * (uint64)BH_GB;
214+
if (mapped_mem_start_addr <= (uint8 *)sig_addr
215+
&& (uint8 *)sig_addr < mapped_mem_end_addr) {
216+
/* The address which causes segmentation fault is inside
217+
the shared heap's guard regions */
218+
return true;
219+
}
220+
}
221+
#endif
222+
205223
return false;
206224
}
207225

core/iwasm/common/wasm_shared_memory.c

+6-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
#if WASM_ENABLE_THREAD_MGR != 0
99
#include "../libraries/thread-mgr/thread_manager.h"
1010
#endif
11+
#if WASM_ENABLE_AOT != 0
12+
#include "../aot/aot_runtime.h"
13+
#endif
1114

1215
/*
1316
* Note: this lock can be per memory.
@@ -257,7 +260,9 @@ is_native_addr_in_shared_heap(WASMModuleInstanceCommon *module_inst,
257260
#endif
258261
#if WASM_ENABLE_AOT != 0
259262
if (module_inst->module_type == Wasm_Module_AoT) {
260-
// TODO
263+
AOTModuleInstanceExtra *e =
264+
(AOTModuleInstanceExtra *)((AOTModuleInstance *)module_inst)->e;
265+
shared_heap = e->shared_heap;
261266
}
262267
#endif
263268

0 commit comments

Comments
 (0)