This changes registers to be temporarily stored in wasm locals, across
each complete wasm module. Registers are moved from memory to locals
upon entering the wasm module and moved from locals to memory upon
leaving. Additionally, calls to functions that modify registers are
wrapped between moving registers to memory before and moving back to
locals after. This affects:
1. All non-custom instructions
2. safe_{read,write}_slow, since it may page fault (the slow path of all memory accesses)
3. task_switch_test* and trigger_ud
4. All block boundaries
5. The fallback functions of gen_safe_read_write (read-modify-write memory accesses)
The performance benefits are currently mostly eaten up by 1. and 4. (if
one calculates the total number of read/writes to registers in memory,
they are higher after this patch, as each instructions of typ 1. or 4.
requires moving all 8 register twice). This can be improved later by the
relatively mechanical work of making instructions custom (not
necessarily full code generation, only the part of the instruction where
registers are accessed). Multi-page wasm module generation will
significantly reduce the number of type 4. instructions.
Due to 2., the overall code size has significantly increased. This case
(the slow path of memory access) is often generated but rarely executed.
These moves can be removed in a later patch by a different scheme for
safe_{read,write}_slow, which has been left out of this patch for
simplicity of reviewing.
This also simplifies our code generation for storing registers, as
instructions_body.const_i32(register_offset);
// some computations ...
instruction_body.store_i32();
turns into:
// some computations ...
write_register(register_index);
I.e., a prefix is not necessary anymore as locals are indexed directly.
Further patches will allow getting rid of some temporary locals, as
registers now can be used directly.
Reusing the naming scheme of
sha256sum
sha256sum-0
sha256sum-1
sha256sum-2
etc
but the extra metadata such as total file size and block count are no
longer needed in the first block.
IndexedDB uses the StructuredSerializeForStorage algorithm to store
records into the database.
It appears that the html5 spec defines the StructuredSerializeForStorage
algorithm in a way that, when we serialize a TypedArray, the associated
ArrayBuffer is also serialized. Meaning even if the TypedArray is a view
of a single byte in the ArrayBuffer, the potentially-megabytes of data
in the ArrayBuffer are also copied over.
This makes sense. After deserialization, you'd expect the TypedArray to
function the same way as before meaning it should have the same
`.byteOffset` and `.buffer` properties.
However, it is easy to overlook this and think that a TypedArray viewing
2 bytes will only have the 2 bytes stored in the database.
This commit fixes a source of crashes. When calling
IndexedDBFileStorage#set() with a 3Mb file, the file is to be stored as
approx 800 lots of 4k blocks. However, in reality, 800 lots of 3 Mb array
buffers are being stored into the database. As the transaction is not
committed until the last request has been placed, I suspect that Chrome was
trying to store those 2.4 Gb worth of data in memory and did not handle
this case properly, leading to out-of-memory.
This commit also fixes a source of poor performance. When calling
IndexedDBFileStorage#read() to read 4k of a 48 Mb file, the browser seems
to be deserializing the entire 48 Mb into memory and garbage collecting
it even though only 4k is needed.
Now that WASM_TABLE_SIZE may be capped, we set it slightly below the
limit under which chromium crashes: https://bugs.chromium.org/p/v8/issues/detail?id=8427
JIT_THRESHOLD is also reduced due to two reasons:
- With the lower WASM_TABLE_SIZE, we want to avoid compiling too many
modules
- It has occasionally been observed that under node, the engine's wasm
compiler can't catch up with the number of modules we produce, thus
resulting in 100s of pending compiled modules. This most likely
happens only under node as we don't render the screen and
the main loop (based on setImmediate) is faster.
The new value doesn't seem to exhibit this problem, but we may want to
increase the threshold further if the problem appears again
Also fix jit_empty_cache when callbacks are pending (fixes#53)
This is also a preparation for setting WASM_TABLE_SIZE to a low value to
work around memory limitations in browsers.
- More like passing the same reference to it when calling db_get/set.
- In reality, it was still the same store object being accessed, but
this commit improves the coherence of the db_get/set helper methods.
- Integrate new FileStorage interface with lib/filesystem.js
- Simplify the FileStorage interface with the intention that it only
serves read-only files.
Simplifies both the filestorage.js code as well as the starter.js code
that uses these FileStorage classes.
Now, the ServerFileStorageWrapper decorates the other FileStorage
classes by loading from the server when the file is not available.
Moreover, the previous starter.js was incorrectly passing the `baseurl`
parameter (it was passing it when baseurl was not defined nor needed).
Fallback logic is moved to the caller's responsibility.
Empty FileStorages and FileStorages that load from the server are
separated into different classes. This is to avoid faults where the
caller of the constructor forgets to pass in a `baseurl` parameter and
leads to some confusing bug.