-
Notifications
You must be signed in to change notification settings - Fork 15
Interpreter issues with let #35
Description
The let
instruction is difficult to implement in an interpreter without significant overhead. In particular, a let
instruction introduces a new block scope and binds new local variable indices that are accessible (and writeable) in that scope. This requires the use of a second stack pointer if using the common implementation technique where local variables are preallocated before the operand stack on a single array that increases with the call stack. Secondly, leaving the scope of the let
block must unbind or pop these variable indices. As the scope of a let
is terminated with a normal end
, there is no way for an interpreter to know where the scope ends unless by dynamically tracking control scopes. This is not the case with any of the existing control constructs in Wasm, and is specific to let. Dynamically tracking control scopes is not necessary for any reason currently, and would penalize all functions, even ones without let.
A simple solution to this problem is to require that functions pre-declare all of the space that they will need for let bindings in their bodies. This allows an interpreter to preallocate space for let bindings, doesn't require a second stack pointer, and also benefits JITs, since they must also use a dynamic data structure (e.g. to track SSA values) that would have to grow and shrink with lets. Since the preamble of a function is just a series of local variable declarations with value types, we will probably need to reserve a value from the binary encoding of the value type space to indicate a pre-declaration of let
indexing space.
I think the other alternatives for avoiding this problem (e.g. not having let
, but requiring definite initialization of locals with value types that have no default value such as non-null references) are worse.