From a07cd4913cc682e0675362421990d7579d248960 Mon Sep 17 00:00:00 2001 From: Christoph Urlacher Date: Fri, 5 Jun 2026 20:15:19 +0200 Subject: [PATCH] Allow configuring which memory for pool/usage allocators is placed where --- flake.nix | 2 - scripts/build.pl | 206 +++++++++++++++++++++++++--------- targets/linker.ld | 27 +++-- targets/wasm-host/wasm_host.c | 54 ++++++--- 4 files changed, 208 insertions(+), 81 deletions(-) diff --git a/flake.nix b/flake.nix index 96b3d33..7aed1c9 100644 --- a/flake.nix +++ b/flake.nix @@ -6,9 +6,7 @@ rec { flake-utils.url = "github:numtide/flake-utils"; }; - # TODO: Merge wasm_host_pool/_allocator and use #define flags instead # TODO: Rewrite all perl scripts -> modularize common code and unify menu actions - # TODO: Write a test suite that verifies the build process (against the produced .elf, check if the expected stuff is in there) outputs = { diff --git a/scripts/build.pl b/scripts/build.pl index 397e82e..cf56283 100755 --- a/scripts/build.pl +++ b/scripts/build.pl @@ -49,34 +49,10 @@ my @selected_modes = TUI::select_from_list( "Select Execution Modes", 1, @modes ); die "No mode selected" unless @selected_modes; -# Select .text.wamr_aot section variant -my @aot_section_variants = ( - "Place AOT array in .text.wamr_aot", - "Let the linker decide where the AOT array is located", -); -my ($selected_aot_variant) = - TUI::select_from_list( "Select WAMR Array.Text Variant", - 0, @aot_section_variants ); -die "No AOT section variant selected" unless $selected_aot_variant; -local $ENV{WAMR_USE_AOT_IN_TEXT} = - ( $selected_aot_variant eq $aot_section_variants[0] ) - ? "true" - : "false"; - -# Select WAMR mmap variant -my @mmap_variants = ( - "Place mmap_space in .text.wamr_mmap", - "Let the linker decide where mmap_space is located" -); -my ($selected_mmap_variant) = - TUI::select_from_list( "Select WAMR Mmap.Text Variant", 0, @mmap_variants ); -die "No variant selected" unless $selected_mmap_variant; -local $ENV{WAMR_USE_MMAP_IN_TEXT} = - ( $selected_mmap_variant eq $mmap_variants[0] ) - ? "true" - : "false"; - +# ========================================================================================= # # Select WAMR allocator variant +# ========================================================================================= # + my @allocator_variants = ( "Pool allocator (Alloc_With_Pool)", "Allocator with usage (Alloc_With_Allocator)", @@ -90,17 +66,123 @@ local $ENV{WAMR_USE_ALLOCATOR} = ? "false" : "true"; +# ========================================================================================= # # Select XIP variant +# ========================================================================================= # + my @xip_variants = ( "Compile AOT with --xip", "Compile AOT without --xip" ); -my ($selected_xip_variant) = - TUI::select_from_list( "Select WAMRC XIP Variant", 0, @xip_variants ); -die "No XIP variant selected" unless $selected_xip_variant; -local $ENV{WAMR_USE_XIP} = - ( $selected_xip_variant eq $xip_variants[0] ) +my $selected_xip_variant; +if ( grep { $_ eq "aot" } @selected_modes ) { + ($selected_xip_variant) = + TUI::select_from_list( "Select WAMRC XIP Variant", 0, @xip_variants ); + die "No XIP variant selected" unless $selected_xip_variant; + local $ENV{WAMR_USE_XIP} = + ( $selected_xip_variant eq $xip_variants[0] ) + ? "true" + : "false"; +} + +# ========================================================================================= # +# Select .text.wamr_mmap variant +# ========================================================================================= # + +my @mmap_variants = ( + "Place mmap_space in .text.wamr_mmap", + "Let the linker decide where mmap_space is located" +); +my ($selected_mmap_variant) = + TUI::select_from_list( "Select WAMR Mmap.Text Variant", 0, @mmap_variants ); +die "No variant selected" unless $selected_mmap_variant; +local $ENV{WAMR_USE_MMAP_IN_TEXT} = + ( $selected_mmap_variant eq $mmap_variants[0] ) ? "true" : "false"; +# ========================================================================================= # +# Select .text.wamr_aot variant +# ========================================================================================= # + +my @aot_section_variants = ( + "Place AOT array in .text.wamr_aot", + "Let the linker decide where the AOT array is located", +); +my $selected_aot_variant; +if ( grep { $_ eq "aot" } @selected_modes ) { + ($selected_aot_variant) = + TUI::select_from_list( "Select WAMR Array.Text Variant", + 0, @aot_section_variants ); + die "No AOT section variant selected" unless $selected_aot_variant; + local $ENV{WAMR_USE_AOT_IN_TEXT} = + ( $selected_aot_variant eq $aot_section_variants[0] ) + ? "true" + : "false"; +} + +# ========================================================================================= # +# Select .text.wamr_global_heap variant +# ========================================================================================= # + +my @global_heap_variants = ( + "Place pool allocator's global_heap in .text.wamr_global_heap", + "Let the linker decide where global_heap is located" +); +my $selected_global_heap_variant; +if ( $selected_allocator_variant eq $allocator_variants[0] ) { + ($selected_global_heap_variant) = + TUI::select_from_list( "Select WAMR Global Heap Variant", + 0, @global_heap_variants ); + die "No global heap variant selected" unless $selected_global_heap_variant; + local $ENV{WAMR_USE_GLOBAL_HEAP_IN_TEXT} = + ( $selected_global_heap_variant eq $global_heap_variants[0] ) + ? "true" + : "false"; +} + +# ========================================================================================= # +# Select .text.wamr_runtime_pool variant +# ========================================================================================= # + +my @runtime_pool_variants = ( + "Place usage allocator's runtime_pool in .text.wamr_runtime_pool", + "Let the linker decide where runtime_pool is located" +); +my $selected_runtime_pool_variant; +if ( $selected_allocator_variant eq $allocator_variants[1] ) { + ($selected_runtime_pool_variant) = + TUI::select_from_list( "Select WAMR Runtime Pool Variant", + 0, @runtime_pool_variants ); + die "No runtime pool variant selected" + unless $selected_runtime_pool_variant; + local $ENV{WAMR_USE_RUNTIME_POOL_IN_TEXT} = + ( $selected_runtime_pool_variant eq $runtime_pool_variants[0] ) + ? "true" + : "false"; +} + +# ========================================================================================= # +# Select .text.wamr_linear_pool variant +# ========================================================================================= # + +my @linear_pool_variants = ( + "Place usage allocator's linear_pool in .text.wamr_linear_pool", + "Let the linker decide where linear_pool is located" +); +my $selected_linear_pool_variant; +if ( $selected_allocator_variant eq $allocator_variants[1] ) { + ($selected_linear_pool_variant) = + TUI::select_from_list( "Select WAMR Linear Pool Variant", + 0, @linear_pool_variants ); + die "No linear pool variant selected" unless $selected_linear_pool_variant; + local $ENV{WAMR_USE_LINEAR_POOL_IN_TEXT} = + ( $selected_linear_pool_variant eq $linear_pool_variants[0] ) + ? "true" + : "false"; +} + +# ========================================================================================= # # Select FAIL catch flags (written to runner_flags in each build dir) +# ========================================================================================= # + my %catch_flag_map = ( "--catch-outer" => "--catch-outerspace", "--catch-text" => "--catch-write-textsegment", @@ -108,15 +190,30 @@ my %catch_flag_map = ( my @selected_catch_tags = TUI::select_from_list( "Select FAIL Flags", 1, sort keys %catch_flag_map ); +# ========================================================================================= # # Build everything +# ========================================================================================= # + # TODO: linux-baremetal target is broken system( "mkdir", "-p", "$local_builds_dir" ); foreach my $experiment (@selected_experiments) { foreach my $target (@selected_targets) { foreach my $mode (@selected_modes) { + my $allocator_info = + ( ( $mode eq "aot" || $mode eq "interp" ) + && $selected_allocator_variant eq $allocator_variants[0] ) + ? "alloc_pool" + : "alloc_usage"; + my $xip_info = + ( $mode eq "aot" + && $selected_xip_variant + && $selected_xip_variant eq $xip_variants[0] ) + ? "xip" + : ""; my $aot_info = ( $mode eq "aot" + && $selected_aot_variant && $selected_aot_variant eq $aot_section_variants[0] ) ? "wamr_aot" : ""; @@ -125,20 +222,32 @@ foreach my $experiment (@selected_experiments) { && $selected_mmap_variant eq $mmap_variants[0] ) ? "wamr_mmap" : ""; - my $allocator_info = - ( ( $mode eq "aot" || $mode eq "interp" ) - && $selected_allocator_variant eq $allocator_variants[0] ) - ? "alloc_pool" - : "alloc_usage"; - my $xip_info = - ( $mode eq "aot" && $selected_xip_variant eq $xip_variants[0] ) - ? "xip" + my $global_heap_info = + ( ( $mode eq "aot" || $mode eq "interp" ) + && $selected_global_heap_variant + && $selected_global_heap_variant eq $global_heap_variants[0] ) + ? "wamr_global_heap" + : ""; + my $runtime_pool_info = + ( ( $mode eq "aot" || $mode eq "interp" ) + && $selected_runtime_pool_variant + && $selected_runtime_pool_variant eq + $runtime_pool_variants[0] ) + ? "wamr_runtime_pool" + : ""; + my $linear_pool_info = + ( ( $mode eq "aot" || $mode eq "interp" ) + && $selected_linear_pool_variant + && $selected_linear_pool_variant eq $linear_pool_variants[0] ) + ? "wamr_linear_pool" : ""; my $flags_info = join " ", @selected_catch_tags; - my $info_str = join " ", + + my $info_str = join " ", grep { length } ( - $mode, $aot_info, $mmap_info, - $allocator_info, $xip_info, $flags_info + $mode, $aot_info, $mmap_info, + $allocator_info, $global_heap_info, $runtime_pool_info, + $linear_pool_info, $xip_info, $flags_info ); # Build experiment @@ -156,21 +265,12 @@ foreach my $experiment (@selected_experiments) { print $fhandle "$catch_flag_map{$_}\n" for @selected_catch_tags; close($fhandle); - my $aot_name = $aot_info ? "_aot-text" : ""; - my $mmap_name = $mmap_info ? "_mmap-text" : ""; - my $allocator_name = $allocator_info ? "_alloc-usage" : ""; - my $xip_name = $xip_info ? "_xip" : ""; system( join " ", ( "mv", "$local_root/build-$experiment", - join "", - ( - "$local_builds_dir/", - "${date}_${experiment}_${mode}_${target}", - "${aot_name}${mmap_name}${allocator_name}${xip_name}", - ) + "$local_builds_dir/${date}_${experiment}_${mode}_${target}", ) ); } diff --git a/targets/linker.ld b/targets/linker.ld index b895d0f..ccbd533 100644 --- a/targets/linker.ld +++ b/targets/linker.ld @@ -46,20 +46,31 @@ SECTIONS { KEEP (*(".text.startup")) - /* .wamr_aot and .wamr_mmap have to be placed before .text, - * otherwise they'll be caught by the wildcard */ + /* place before .text, otherwise they'll be caught by the wildcard */ - /* _wamr_aot_start = .; */ + _wamr_aot_start = .; *(".text.wamr_aot") - /* _wamr_aot_end = .; */ + _wamr_aot_end = .; - /* _wamr_mmap_start = .; */ + _wamr_mmap_start = .; *(".text.wamr_mmap") - /* _wamr_mmap_end = .; */ + _wamr_mmap_end = .; - /* _text_start = .; */ + _wamr_runtime_pool_start = .; + *(".text.wamr_runtime_pool") + _wamr_runtime_pool_end = .; + + _wamr_linear_pool_start = .; + *(".text.wamr_linear_pool") + _wamr_linear_pool_end = .; + + _wamr_global_heap_start = .; + *(".text.wamr_global_heap") + _wamr_global_heap_end = .; + + _text_start = .; *(".text*") - /* _text_end = .; */ + _text_end = .; *(".rodata*") } diff --git a/targets/wasm-host/wasm_host.c b/targets/wasm-host/wasm_host.c index 9645b0c..5c98121 100644 --- a/targets/wasm-host/wasm_host.c +++ b/targets/wasm-host/wasm_host.c @@ -36,19 +36,35 @@ void host_print(wasm_exec_env_t exec_env, const char *msg) { #if WASM_MEM_ALLOC_WITH_USAGE -// Bump allocator +// Another bump allocator #define WASM_LINEAR_MEMORY_SIZE (64 * 1024) // Need to match --initial-memory? -#define ALLOCATOR_POOL_SIZE (WASM_LINEAR_MEMORY_SIZE + 2 * 1024 * 1024) +#define RUNTIME_POOL_SIZE (2 * 1024 * 1024) +#define LINEAR_POOL_SIZE (WASM_LINEAR_MEMORY_SIZE + 512 * 1024) #define ALIGNMENT 8 -static char allocator_pool[ALLOCATOR_POOL_SIZE]; -static size_t pool_offset = 0; +typedef struct { + char *buf; + size_t size; + size_t offset; +} BumpPool; + +#if WAMR_RUNTIME_POOL_IN_TEXT +__attribute__((section(".text.wamr_runtime_pool"), aligned(4096))) +#endif +static char runtime_pool_buf[RUNTIME_POOL_SIZE]; + +#if WAMR_LINEAR_POOL_IN_TEXT +__attribute__((section(".text.wamr_linear_pool"), aligned(4096))) +#endif +static char linear_pool_buf[LINEAR_POOL_SIZE]; + +// mem_alloc_usage_t: 0 = Alloc_For_Runtime, 1 = Alloc_For_LinearMemory +static BumpPool pools[] = { + { runtime_pool_buf, RUNTIME_POOL_SIZE, 0 }, + { linear_pool_buf, LINEAR_POOL_SIZE, 0 }, +}; static size_t align_up(size_t x, size_t a) { - // a is a power of two, e.g., 8: - // x+a-1: Shift value upwards to the next alignment "bucket" - // a-1: 00000111, ~(a-1): 11111000 - Clears the lower bits/alignment - // remainder return (x + a - 1) & ~(a - 1); } @@ -57,26 +73,25 @@ static size_t alloc_size(void *ptr) { return *(size_t *)((char *)ptr - header_size); } -static void *bump_alloc(unsigned int size) { - // Reserve space for a size_t header before the user pointer +static void *bump_alloc(BumpPool *pool, unsigned int size) { size_t header_size = align_up(sizeof(size_t), ALIGNMENT); - size_t start = align_up(pool_offset, ALIGNMENT); + size_t start = align_up(pool->offset, ALIGNMENT); size_t end = start + header_size + align_up(size, ALIGNMENT); - if (end > ALLOCATOR_POOL_SIZE) { + if (end > pool->size) { return NULL; } - *(size_t *)&allocator_pool[start] = size; - void *ptr = &allocator_pool[start + header_size]; - pool_offset = end; + *(size_t *)&pool->buf[start] = size; + void *ptr = &pool->buf[start + header_size]; + pool->offset = end; return ptr; } void *wamr_malloc(mem_alloc_usage_t usage, unsigned int size) { PRINT("wamr_malloc: usage=%d size=%u\n", usage, size); - return bump_alloc(size); + return bump_alloc(&pools[usage], size); } void *wamr_realloc(mem_alloc_usage_t usage, bool full_size_mmaped, void *ptr, @@ -84,7 +99,7 @@ void *wamr_realloc(mem_alloc_usage_t usage, bool full_size_mmaped, void *ptr, PRINT("wamr_realloc: usage=%d full_size_mmaped=%d ptr=%p new_size=%u\n", usage, full_size_mmaped, ptr, new_size); - void *new_addr = bump_alloc(new_size); + void *new_addr = bump_alloc(&pools[usage], new_size); if (!new_addr) { return NULL; } @@ -98,13 +113,16 @@ void *wamr_realloc(mem_alloc_usage_t usage, bool full_size_mmaped, void *ptr, } void wamr_free(mem_alloc_usage_t usage, void *ptr) { - PRINT("wamr_free: usage=%d ptr=%p\n", usage, ptr); + // PRINT("wamr_free: usage=%d ptr=%p\n", usage, ptr); } #else #define RUNTIME_POOL_SIZE (4 * STACK_SIZE) +#if WAMR_GLOBAL_HEAP_IN_TEXT +__attribute__((section(".text.wamr_global_heap"), aligned(4096))) +#endif static char global_heap_buf[RUNTIME_POOL_SIZE]; #endif // WASM_MEM_ALLOC_WITH_USAGE