From 0918d83d23aa421e956dfbcaeefd9faeae94237e Mon Sep 17 00:00:00 2001 From: Luke Wagner Date: Wed, 30 Mar 2016 18:11:50 -0500 Subject: [PATCH 1/2] Change max to optional and hard --- AstSemantics.md | 8 ++++++-- Modules.md | 13 +++++++++---- Rationale.md | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 6 deletions(-) diff --git a/AstSemantics.md b/AstSemantics.md index cb73c637..9296087a 100644 --- a/AstSemantics.md +++ b/AstSemantics.md @@ -202,11 +202,15 @@ Out of bounds accesses trap. In the MVP, linear memory can be resized by a `grow_memory` operator. The operand to this operator is in units of the WebAssembly page size, -which is 64KiB on all engines (though large page support may be added in +which is defined to be 64KiB (though large page support may be added in the [future](FutureFeatures.md#large-page-support)). * `grow_memory` : grow linear memory by a given unsigned delta of pages. - Return the previous memory size in bytes. + Return the previous memory size in units of pages or -1 on failure. + +`grow_memory` must fail when attempting to grow past the maximum declared +size, if one is specified in the [memory section](Module.md#linear-memory-section). +`grow_memory` may also fail if an underlying system allocation fails. As stated [above](AstSemantics.md#linear-memory), linear memory is contiguous, meaning there are no "holes" in the linear address space. After the diff --git a/Modules.md b/Modules.md index b303eddf..5c52792e 100644 --- a/Modules.md +++ b/Modules.md @@ -161,15 +161,20 @@ by the module. If the section is absent, the linear memory operators The linear memory section declares the initial [memory size](AstSemantics.md#linear-memory) (which may be subsequently increased by [`grow_memory`](AstSemantics.md#resizing)). +The linear memory section may optionally declare a maximum memory size. +[`grow_memory`](AstSemantics.md#resizing) is guaranteed to fail if attempting to +grow past the declared maximum. When declared, implementations *should* +(non-normative) attempt to reserve virtual memory up to the maximum size. While +failure to allocate the *initial* memory size is a runtime error, failure to +reserve up to the *maximum* is not. When a maximum memory size is *not* declared, +on architectures with limited virtual address space, engines should allocate +only the initial size and reallocate on demand. + The initial contents of linear memory are zero by default. However, the memory section contains a possibly-empty array of *segments* (analogous to `.data`) which can specify the initial contents of fixed `(offset, length)` ranges of memory. -The linear memory section may also contain an optional hint declaring the expected -maximum heap usage. This hint is not semantically visible but can help a -WebAssembly engine to optimize `grow_memory`. - The linear memory section may optionally declare that the instance's linear memory is *externally aliasable*. How linear memory is aliased is up to the host environment (as with all module exports). The diff --git a/Rationale.md b/Rationale.md index e4cf8ec8..c225d3a3 100644 --- a/Rationale.md +++ b/Rationale.md @@ -124,6 +124,38 @@ already be communicating between threads in order to properly allocate the sum of the allocation requests, so it's expected that they can provide the needed information without significant extra effort. +The [optional maximum size](Modules.md#linear-memory-section) is designed to +address a number of competing constraints: +1. Allow WebAssembly modules to grab large regions of contiguous memory in a + 32-bit address space early in an application's startup before the virtual + address space becomes fragmented by execution of the application. +2. Allow many small WebAssembly instances to execute in a single 32-bit process. + (For example, it is common for a single web application to use dozens of + libraries, each of which may, over time, include WebAssembly modules as + implementation details.) +3. Avoid *forcing* every developer using WebAssembly to understand their precise + maximum heap usage. +4. When threading and shared memory are added to WebAssembly + [post-MVP](PostMVP.md#threads), the design should not require memory growth + to `realloc` since this implies significant implementation complexity, + security hazards, and optimization challenges. + +The optional maximum addresses these constraints: +* (1) is addressed by specifying a large maximum memory size. Simply setting a + large *initial* memory size has problems due to (3) and the fact that a + failure to allocate initial is a fatal error which makes the choice of "how + big?" difficult. +* (2) and (3) are addressed by making the maximum optional combined with the + implied implementation that, on 32-bit, engines will not allocate + significantly more than the current memory size, *and* the compiler sets the + initial size to just enough to hold static data. +* (4) is addressed assuming that, when threading is added, a new, optional + "shared" flag is added to the memory section that must be set to enable shared + memory and the shared flag forces the maximum to be specified. In this case, + shared memory never moves; the only thing that changes is that the bounds + grows which does not have all the abovementioned hazards. In particular, any + extant `SharedArrayBuffer`s that alias linear memory stay valid without + any updates. ## Linear memory disabled if no linear memory section From 3c5d2052a6febae095192d1ff652a54a553b3d00 Mon Sep 17 00:00:00 2001 From: Luke Wagner Date: Thu, 31 Mar 2016 13:45:37 -0500 Subject: [PATCH 2/2] Clarify failure conditions in AstSemantics.md --- AstSemantics.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/AstSemantics.md b/AstSemantics.md index 9296087a..f1031a83 100644 --- a/AstSemantics.md +++ b/AstSemantics.md @@ -208,9 +208,12 @@ the [future](FutureFeatures.md#large-page-support)). * `grow_memory` : grow linear memory by a given unsigned delta of pages. Return the previous memory size in units of pages or -1 on failure. -`grow_memory` must fail when attempting to grow past the maximum declared -size, if one is specified in the [memory section](Module.md#linear-memory-section). -`grow_memory` may also fail if an underlying system allocation fails. +When a maximum memory size is declared in the [memory section](Module.md#linear-memory-section), +`grow_memory` must fail if it would grow past the maximum. However, +`grow_memory` may still fail before the maximum if it was not possible to +reserve the space up front or if enabling the reserved memory fails. +When there is no maximum memory size declared, `grow_memory` is expected +to perform a system allocation which may fail. As stated [above](AstSemantics.md#linear-memory), linear memory is contiguous, meaning there are no "holes" in the linear address space. After the