Index: src/compiler/wasm-compiler.cc |
diff --git a/src/compiler/wasm-compiler.cc b/src/compiler/wasm-compiler.cc |
index ff80f953eb1ffd9737fc5af809d5b89c394cb1e4..05005bdb2457428bdb088bd71822cde9c453f3e8 100644 |
--- a/src/compiler/wasm-compiler.cc |
+++ b/src/compiler/wasm-compiler.cc |
@@ -2380,10 +2380,85 @@ void WasmGraphBuilder::BoundsCheckMem(MachineType memtype, Node* index, |
trap_->AddTrapIfFalse(wasm::kTrapMemOutOfBounds, cond); |
} |
+Node* WasmGraphBuilder::BuildUnalignedLoad(wasm::LocalType type, |
+ MachineType memtype, Node* index, |
+ uint32_t offset) { |
+ Node* result; |
+ Node* load; |
+ bool extendTo64Bit = false; |
+ |
+ wasm::WasmOpcode shiftOpcode; |
+ wasm::WasmOpcode orOpcode; |
+ Node* constEight; |
+ |
+ switch (type) { |
+ case wasm::kAstI64: |
+ case wasm::kAstF64: |
+ shiftOpcode = wasm::kExprI64Shl; |
+ orOpcode = wasm::kExprI64Ior; |
+ result = jsgraph()->Int64Constant(0); |
+ constEight = jsgraph()->Int64Constant(8); |
+ extendTo64Bit = true; |
+ break; |
+ case wasm::kAstI32: |
+ case wasm::kAstF32: |
+ shiftOpcode = wasm::kExprI32Shl; |
+ orOpcode = wasm::kExprI32Ior; |
+ result = jsgraph()->Int32Constant(0); |
+ constEight = jsgraph()->Int32Constant(8); |
+ break; |
+ default: |
+ UNREACHABLE(); |
+ } |
+ |
+ bool signExtend = memtype.IsSigned(); |
+ |
+ bool isFloat = IsFloatingPoint(memtype.representation()); |
+ int numberOfLoads = 1 << ElementSizeLog2Of(memtype.representation()); |
+ |
+ for (int i = 0; i < numberOfLoads; i++) { |
titzer
2016/04/20 12:59:26
This is good enough for a first cut, since it does
|
+ result = Binop(shiftOpcode, result, constEight); |
+ load = graph()->NewNode( |
+ jsgraph()->machine()->Load(signExtend ? MachineType::Int8() |
+ : MachineType::Uint8()), |
+ MemBuffer(offset + numberOfLoads - 1 - i), index, *effect_, *control_); |
+ index->Print(); |
+ *effect_ = load; |
+ if (extendTo64Bit) { |
+ if (signExtend) { |
+ load = |
+ graph()->NewNode(jsgraph()->machine()->ChangeInt32ToInt64(), load); |
+ } else { |
+ load = graph()->NewNode(jsgraph()->machine()->ChangeUint32ToUint64(), |
+ load); |
+ } |
+ } |
+ signExtend = false; |
+ result = Binop(orOpcode, result, load); |
+ } |
+ |
+ // Convert to float |
+ if (isFloat) { |
+ switch (type) { |
+ case wasm::kAstF32: |
+ result = Unop(wasm::kExprF32ReinterpretI32, result); |
+ break; |
+ case wasm::kAstF64: |
+ result = Unop(wasm::kExprF64ReinterpretI64, result); |
+ break; |
+ default: |
+ UNREACHABLE(); |
+ } |
+ } |
+ |
+ return result; |
+} |
Node* WasmGraphBuilder::LoadMem(wasm::LocalType type, MachineType memtype, |
- Node* index, uint32_t offset) { |
+ Node* index, uint32_t offset, |
+ uint32_t alignment) { |
Node* load; |
+ bool skip = false; |
if (module_ && module_->asm_js()) { |
// asm.js semantics use CheckedLoad (i.e. OOB reads return 0ish). |
@@ -2394,11 +2469,23 @@ Node* WasmGraphBuilder::LoadMem(wasm::LocalType type, MachineType memtype, |
} else { |
// WASM semantics throw on OOB. Introduce explicit bounds check. |
BoundsCheckMem(memtype, index, offset); |
- load = graph()->NewNode(jsgraph()->machine()->Load(memtype), |
- MemBuffer(offset), index, *effect_, *control_); |
+ // load = |
+ // graph()->NewNode(jsgraph()->machine()->UnalignedLoad(memtype).op(), |
+ // MemBuffer(offset), index, *effect_, *control_); |
+ bool aligned = alignment >= ElementSizeLog2Of(memtype.representation()); |
titzer
2016/04/20 12:59:26
It's probably best to have a machine()->UnalignedL
|
+ if (aligned || |
+ !jsgraph()->machine()->UnalignedLoad(memtype).IsSupported()) { |
+ load = graph()->NewNode(jsgraph()->machine()->Load(memtype), |
+ MemBuffer(offset), index, *effect_, *control_); |
+ } else { |
+ load = BuildUnalignedLoad(type, memtype, index, offset); |
+ skip = true; |
+ } |
} |
- *effect_ = load; |
+ if (!skip) { |
+ *effect_ = load; |
+ } |
if (type == wasm::kAstI64 && |
ElementSizeLog2Of(memtype.representation()) < 3) { |
@@ -2416,10 +2503,72 @@ Node* WasmGraphBuilder::LoadMem(wasm::LocalType type, MachineType memtype, |
return load; |
} |
+Node* WasmGraphBuilder::BuildUnalignedStore(MachineType memtype, Node* index, |
+ uint32_t offset, uint32_t alignment, |
+ Node* val) { |
+ Node* store; |
+ Node* newValue; |
+ |
+ wasm::WasmOpcode shiftOpcode; |
+ |
+ Node* constEight; |
+ Node* mask; |
+ bool extendTo64Bit = false; |
+ |
+ if (ElementSizeLog2Of(memtype.representation()) <= 2) { |
+ shiftOpcode = wasm::kExprI32ShrU; |
+ constEight = jsgraph()->Int32Constant(8); |
+ mask = jsgraph()->Int32Constant(0x000000ff); |
+ } else { |
+ shiftOpcode = wasm::kExprI64ShrU; |
+ constEight = jsgraph()->Int64Constant(8); |
+ mask = jsgraph()->Int64Constant(0x00000000000000ff); |
+ extendTo64Bit = true; |
+ } |
+ |
+ bool isFloat = IsFloatingPoint(memtype.representation()); |
+ int numberOfLoads = 1 << ElementSizeLog2Of(memtype.representation()); |
+ |
+ StoreRepresentation rep(MachineType::Uint8().representation(), |
+ kNoWriteBarrier); |
+ |
+ newValue = val; |
+ if (isFloat) { |
+ switch (memtype.representation()) { |
+ case MachineRepresentation::kFloat64: |
+ newValue = Unop(wasm::kExprI64ReinterpretF64, val); |
+ break; |
+ case MachineRepresentation::kFloat32: |
+ newValue = Unop(wasm::kExprI32ReinterpretF32, val); |
+ break; |
+ default: |
+ UNREACHABLE(); |
+ } |
+ } |
+ |
+ DCHECK(numberOfLoads >= 2); |
+ for (int i = 0; i < numberOfLoads - 1; i++) { |
+ store = graph()->NewNode( |
+ jsgraph()->machine()->Store(rep), MemBuffer(offset + i), index, |
+ extendTo64Bit ? Unop(wasm::kExprI32ConvertI64, newValue) : newValue, |
+ *effect_, *control_); |
+ newValue = Binop(shiftOpcode, newValue, constEight); |
+ *effect_ = store; |
+ } |
+ store = graph()->NewNode( |
+ jsgraph()->machine()->Store(rep), MemBuffer(offset + numberOfLoads - 1), |
+ index, |
+ extendTo64Bit ? Unop(wasm::kExprI32ConvertI64, newValue) : newValue, |
+ *effect_, *control_); |
+ *effect_ = store; |
+ return val; |
+} |
Node* WasmGraphBuilder::StoreMem(MachineType memtype, Node* index, |
- uint32_t offset, Node* val) { |
+ uint32_t offset, uint32_t alignment, |
+ Node* val) { |
Node* store; |
+ bool skip = false; |
if (module_ && module_->asm_js()) { |
// asm.js semantics use CheckedStore (i.e. ignore OOB writes). |
DCHECK_EQ(0, offset); |
@@ -2431,11 +2580,26 @@ Node* WasmGraphBuilder::StoreMem(MachineType memtype, Node* index, |
// WASM semantics throw on OOB. Introduce explicit bounds check. |
BoundsCheckMem(memtype, index, offset); |
StoreRepresentation rep(memtype.representation(), kNoWriteBarrier); |
- store = |
- graph()->NewNode(jsgraph()->machine()->Store(rep), MemBuffer(offset), |
- index, val, *effect_, *control_); |
+ bool aligned = alignment >= ElementSizeLog2Of(memtype.representation()); |
+ |
+ if (aligned || |
+ !jsgraph() |
+ ->machine() |
+ ->UnalignedStore(memtype.representation()) |
+ .IsSupported()) { |
+ StoreRepresentation rep(memtype.representation(), kNoWriteBarrier); |
+ store = |
+ graph()->NewNode(jsgraph()->machine()->Store(rep), MemBuffer(offset), |
+ index, val, *effect_, *control_); |
+ } else { |
+ store = BuildUnalignedStore(memtype, index, offset, alignment, val); |
+ skip = true; |
+ } |
} |
- *effect_ = store; |
+ if (!skip) { |
+ *effect_ = store; |
+ } |
+ |
return store; |
} |