Chromium Code Reviews| 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; |
| } |