Skip to content

Commit 8e013e7

Browse files
SingleAccretionwangxiang090105
authored andcommitted
[lld][WebAssembly] Add an --initial-heap option (#75594)
It is beneficial to preallocate a certain number of pages in the linear memory (i. e. use the "minimum" field of WASM memories) so that fewer "memory.grow"s are needed at startup. So far, the way to do that has been to pass the "--initial-memory" option to the linker. It works, but has the very significant downside of requiring the user to know the size of static data beforehand, as it must not exceed the number of bytes passed-in as "--initial-memory". The new "--initial-heap" option avoids this downside by simply appending the specified number of pages to static data (and stack), regardless of how large they already are. Ref: emscripten-core/emscripten#20888.
1 parent 3ad6086 commit 8e013e7

File tree

6 files changed

+49
-3
lines changed

6 files changed

+49
-3
lines changed

lld/docs/WebAssembly.rst

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,9 +123,13 @@ WebAssembly-specific options:
123123
is not possible for undefined data symbols. Undefined data symbols will
124124
still be reported as normal (in accordance with ``--unresolved-symbols``).
125125

126+
.. option:: --initial-heap=<value>
127+
128+
Initial size of the heap. Default: zero.
129+
126130
.. option:: --initial-memory=<value>
127131

128-
Initial size of the linear memory. Default: static data size.
132+
Initial size of the linear memory. Default: the sum of stack, static data and heap sizes.
129133

130134
.. option:: --max-memory=<value>
131135

lld/test/wasm/initial-heap.test

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown %p/Inputs/start.s -o %t.o
2+
3+
; The initial heap size will be added to the stack size
4+
RUN: wasm-ld %t.o -o %t1.wasm --stack-first -z stack-size=65536 --initial-heap=131072
5+
RUN: obj2yaml %t1.wasm | FileCheck %s --check-prefixes=CHECK,CHECK-2P
6+
7+
; Also test that we can parse and process a large size correctly
8+
RUN: wasm-ld %t.o -o %t2.wasm --stack-first -z stack-size=65536 --initial-heap=4294901760
9+
RUN: obj2yaml %t2.wasm | FileCheck %s --check-prefixes=CHECK,CHECK-4G
10+
11+
CHECK: - Type: MEMORY
12+
CHECK-NEXT: Memories:
13+
CHECK-2P-NEXT: Minimum: 0x3
14+
CHECK-4G-NEXT: Minimum: 0x10000
15+
16+
; Test various error cases.
17+
RUN: not wasm-ld %t.o -o %t3.wasm --initial-heap=131073 2>&1 | FileCheck %s --check-prefix NOT-PAGE-MULTIPLE
18+
RUN: not wasm-ld %t.o -o %t4.wasm --stack-first -z stack-size=65536 --initial-heap=4295032832 2>&1 | FileCheck %s --check-prefix TOO-LARGE-BY-ITSELF
19+
RUN: not wasm-ld %t.o -o %t5.wasm --stack-first -z stack-size=131072 --initial-heap=4294901760 2>&1 | FileCheck %s --check-prefix TOO-LARGE-WITH-STACK
20+
RUN: not wasm-ld %t.o -o %t6.wasm --stack-first -z stack-size=65536 --initial-heap=131072 --initial-memory=131072 2>&1 | FileCheck %s --check-prefix INITIAL-MEMORY-TOO-SMALL
21+
RUN: not wasm-ld %t.o -o %t7.wasm --stack-first -z stack-size=65536 --initial-heap=131072 --max-memory=131072 2>&1 | FileCheck %s --check-prefix MAX-MEMORY-TOO-SMALL
22+
23+
NOT-PAGE-MULTIPLE: initial heap must be 65536-byte aligned
24+
TOO-LARGE-BY-ITSELF: initial heap too large, cannot be greater than 4294901760
25+
TOO-LARGE-WITH-STACK: initial heap too large, cannot be greater than 4294836224
26+
INITIAL-MEMORY-TOO-SMALL: initial memory too small, 196608 bytes needed
27+
MAX-MEMORY-TOO-SMALL: maximum memory too small, 196608 bytes needed

lld/wasm/Config.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ struct Configuration {
6868
bool isStatic = false;
6969
bool trace;
7070
uint64_t globalBase;
71+
uint64_t initialHeap;
7172
uint64_t initialMemory;
7273
uint64_t maxMemory;
7374
uint64_t zStackSize;

lld/wasm/Driver.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -502,9 +502,10 @@ static void readConfigs(opt::InputArgList &args) {
502502
errorHandler().verbose = args.hasArg(OPT_verbose);
503503
LLVM_DEBUG(errorHandler().verbose = true);
504504

505-
config->initialMemory = args::getInteger(args, OPT_initial_memory, 0);
506-
config->globalBase = args::getInteger(args, OPT_global_base, 0);
507505
config->tableBase = args::getInteger(args, OPT_table_base, 0);
506+
config->globalBase = args::getInteger(args, OPT_global_base, 0);
507+
config->initialHeap = args::getInteger(args, OPT_initial_heap, 0);
508+
config->initialMemory = args::getInteger(args, OPT_initial_memory, 0);
508509
config->maxMemory = args::getInteger(args, OPT_max_memory, 0);
509510
config->zStackSize =
510511
args::getZOptionValue(args, OPT_z, "stack-size", WasmPageSize);

lld/wasm/Options.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,9 @@ defm soname: Eq<"soname", "Set the module name in the generated name section">;
215215
def import_table: FF<"import-table">,
216216
HelpText<"Import function table from the environment">;
217217

218+
def initial_heap: JJ<"initial-heap=">,
219+
HelpText<"Initial size of the heap">;
220+
218221
def initial_memory: JJ<"initial-memory=">,
219222
HelpText<"Initial size of the linear memory">;
220223

lld/wasm/Writer.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,16 @@ void Writer::layoutMemory() {
439439
maxMemorySetting = 1ULL << 34;
440440
}
441441

442+
if (config->initialHeap != 0) {
443+
if (config->initialHeap != alignTo(config->initialHeap, WasmPageSize))
444+
error("initial heap must be " + Twine(WasmPageSize) + "-byte aligned");
445+
uint64_t maxInitialHeap = maxMemorySetting - memoryPtr;
446+
if (config->initialHeap > maxInitialHeap)
447+
error("initial heap too large, cannot be greater than " +
448+
Twine(maxInitialHeap));
449+
memoryPtr += config->initialHeap;
450+
}
451+
442452
if (config->initialMemory != 0) {
443453
if (config->initialMemory != alignTo(config->initialMemory, WasmPageSize))
444454
error("initial memory must be " + Twine(WasmPageSize) + "-byte aligned");

0 commit comments

Comments
 (0)