Commit ea6bcbc0 authored by Ben L. Titzer's avatar Ben L. Titzer Committed by Commit Bot

[asmjs] Implement asm.js stores in terms of regular branches.

The CheckedLoad and CheckedStore machine operators are a form of
macro node used in the backend of TurboFan. They express bounds-checked
accesses to typed arrays in the asm.js style. While their semantics
can be expressed as normal machine operations and branches in the
graph, they were originally used to save compile time when graphs
were very big. ASM->WASM->TF graphs are smaller.

This CL implements asm.js bounds checks for stores using normal
branch nodes and removes the need for CheckedStore, improving
maintainability at some small cost to compilation time.

R=mstarzinger@chromium.org
CC=​bradnelson@chromium.org

Bug: 
Change-Id: I928689cfe33acac5a422f32cb014850ba09196f1
Reviewed-on: https://chromium-review.googlesource.com/822471
Commit-Queue: Ben Titzer <titzer@chromium.org>
Reviewed-by: 's avatarMichael Starzinger <mstarzinger@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50044}
parent dad3338b
...@@ -3731,22 +3731,35 @@ Node* WasmGraphBuilder::BuildAsmjsLoadMem(MachineType type, Node* index) { ...@@ -3731,22 +3731,35 @@ Node* WasmGraphBuilder::BuildAsmjsLoadMem(MachineType type, Node* index) {
Node* WasmGraphBuilder::BuildAsmjsStoreMem(MachineType type, Node* index, Node* WasmGraphBuilder::BuildAsmjsStoreMem(MachineType type, Node* index,
Node* val) { Node* val) {
// TODO(turbofan): fold bounds checks for constant asm.js stores.
// asm.js semantics use CheckedStore (i.e. ignore OOB writes).
DCHECK_NOT_NULL(context_cache_); DCHECK_NOT_NULL(context_cache_);
Node* mem_start = context_cache_->mem_start; Node* mem_start = context_cache_->mem_start;
Node* mem_size = context_cache_->mem_size; Node* mem_size = context_cache_->mem_size;
DCHECK_NOT_NULL(mem_start); DCHECK_NOT_NULL(mem_start);
DCHECK_NOT_NULL(mem_size); DCHECK_NOT_NULL(mem_size);
const Operator* cmp_op = jsgraph()->machine()->Uint32LessThan();
if (jsgraph()->machine()->Is64()) { if (jsgraph()->machine()->Is64()) {
index = index =
graph()->NewNode(jsgraph()->machine()->ChangeUint32ToUint64(), index); graph()->NewNode(jsgraph()->machine()->ChangeUint32ToUint64(), index);
} cmp_op = jsgraph()->machine()->Uint64LessThan();
const Operator* op = }
jsgraph()->machine()->CheckedStore(type.representation());
Node* store = graph()->NewNode(op, mem_start, index, mem_size, val, *effect_, // Asm.js semantics are to ignore OOB writes.
*control_); // Note that we check against the memory size ignoring the size of the
*effect_ = store; // stored value, which is conservative if misaligned. Technically, asm.js
// should never have misaligned accesses.
Diamond bounds_check(graph(), jsgraph()->common(),
graph()->NewNode(cmp_op, index, mem_size),
BranchHint::kTrue);
bounds_check.Chain(*control_);
const Operator* store_op = jsgraph()->machine()->Store(StoreRepresentation(
type.representation(), WriteBarrierKind::kNoWriteBarrier));
Node* store = graph()->NewNode(store_op, mem_start, index, val, *effect_,
bounds_check.if_true);
Node* effect_phi = graph()->NewNode(jsgraph()->common()->EffectPhi(2), store,
*effect_, bounds_check.merge);
*effect_ = effect_phi;
*control_ = bounds_check.merge;
return val; return val;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment