Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(100)

Side by Side Diff: src/compiler/wasm-compiler.cc

Issue 1779713009: Implement optional turbofan UnalignedLoad and UnalignedStore operators (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Unaligned access simulate using load/shift/or and store/shift/and Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/compiler/wasm-compiler.h ('k') | src/compiler/x64/instruction-selector-x64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 the V8 project authors. All rights reserved. 1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/compiler/wasm-compiler.h" 5 #include "src/compiler/wasm-compiler.h"
6 6
7 #include "src/isolate-inl.h" 7 #include "src/isolate-inl.h"
8 8
9 #include "src/base/platform/elapsed-timer.h" 9 #include "src/base/platform/elapsed-timer.h"
10 #include "src/base/platform/platform.h" 10 #include "src/base/platform/platform.h"
(...skipping 2362 matching lines...) Expand 10 before | Expand all | Expand 10 after
2373 size_t limit = size - offset - memsize; 2373 size_t limit = size - offset - memsize;
2374 CHECK(limit <= kMaxUInt32); 2374 CHECK(limit <= kMaxUInt32);
2375 cond = graph()->NewNode( 2375 cond = graph()->NewNode(
2376 jsgraph()->machine()->Uint32LessThanOrEqual(), index, 2376 jsgraph()->machine()->Uint32LessThanOrEqual(), index,
2377 jsgraph()->Int32Constant(static_cast<uint32_t>(limit))); 2377 jsgraph()->Int32Constant(static_cast<uint32_t>(limit)));
2378 } 2378 }
2379 2379
2380 trap_->AddTrapIfFalse(wasm::kTrapMemOutOfBounds, cond); 2380 trap_->AddTrapIfFalse(wasm::kTrapMemOutOfBounds, cond);
2381 } 2381 }
2382 2382
2383 Node* WasmGraphBuilder::BuildUnalignedLoad(wasm::LocalType type,
2384 MachineType memtype, Node* index,
2385 uint32_t offset) {
2386 Node* result;
2387 Node* load;
2388 bool extendTo64Bit = false;
2389
2390 wasm::WasmOpcode shiftOpcode;
2391 wasm::WasmOpcode orOpcode;
2392 Node* constEight;
2393
2394 switch (type) {
2395 case wasm::kAstI64:
2396 case wasm::kAstF64:
2397 shiftOpcode = wasm::kExprI64Shl;
2398 orOpcode = wasm::kExprI64Ior;
2399 result = jsgraph()->Int64Constant(0);
2400 constEight = jsgraph()->Int64Constant(8);
2401 extendTo64Bit = true;
2402 break;
2403 case wasm::kAstI32:
2404 case wasm::kAstF32:
2405 shiftOpcode = wasm::kExprI32Shl;
2406 orOpcode = wasm::kExprI32Ior;
2407 result = jsgraph()->Int32Constant(0);
2408 constEight = jsgraph()->Int32Constant(8);
2409 break;
2410 default:
2411 UNREACHABLE();
2412 }
2413
2414 bool signExtend = memtype.IsSigned();
2415
2416 bool isFloat = IsFloatingPoint(memtype.representation());
2417 int numberOfLoads = 1 << ElementSizeLog2Of(memtype.representation());
2418
2419 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
2420 result = Binop(shiftOpcode, result, constEight);
2421 load = graph()->NewNode(
2422 jsgraph()->machine()->Load(signExtend ? MachineType::Int8()
2423 : MachineType::Uint8()),
2424 MemBuffer(offset + numberOfLoads - 1 - i), index, *effect_, *control_);
2425 index->Print();
2426 *effect_ = load;
2427 if (extendTo64Bit) {
2428 if (signExtend) {
2429 load =
2430 graph()->NewNode(jsgraph()->machine()->ChangeInt32ToInt64(), load);
2431 } else {
2432 load = graph()->NewNode(jsgraph()->machine()->ChangeUint32ToUint64(),
2433 load);
2434 }
2435 }
2436 signExtend = false;
2437 result = Binop(orOpcode, result, load);
2438 }
2439
2440 // Convert to float
2441 if (isFloat) {
2442 switch (type) {
2443 case wasm::kAstF32:
2444 result = Unop(wasm::kExprF32ReinterpretI32, result);
2445 break;
2446 case wasm::kAstF64:
2447 result = Unop(wasm::kExprF64ReinterpretI64, result);
2448 break;
2449 default:
2450 UNREACHABLE();
2451 }
2452 }
2453
2454 return result;
2455 }
2383 2456
2384 Node* WasmGraphBuilder::LoadMem(wasm::LocalType type, MachineType memtype, 2457 Node* WasmGraphBuilder::LoadMem(wasm::LocalType type, MachineType memtype,
2385 Node* index, uint32_t offset) { 2458 Node* index, uint32_t offset,
2459 uint32_t alignment) {
2386 Node* load; 2460 Node* load;
2461 bool skip = false;
2387 2462
2388 if (module_ && module_->asm_js()) { 2463 if (module_ && module_->asm_js()) {
2389 // asm.js semantics use CheckedLoad (i.e. OOB reads return 0ish). 2464 // asm.js semantics use CheckedLoad (i.e. OOB reads return 0ish).
2390 DCHECK_EQ(0, offset); 2465 DCHECK_EQ(0, offset);
2391 const Operator* op = jsgraph()->machine()->CheckedLoad(memtype); 2466 const Operator* op = jsgraph()->machine()->CheckedLoad(memtype);
2392 load = graph()->NewNode(op, MemBuffer(0), index, MemSize(0), *effect_, 2467 load = graph()->NewNode(op, MemBuffer(0), index, MemSize(0), *effect_,
2393 *control_); 2468 *control_);
2394 } else { 2469 } else {
2395 // WASM semantics throw on OOB. Introduce explicit bounds check. 2470 // WASM semantics throw on OOB. Introduce explicit bounds check.
2396 BoundsCheckMem(memtype, index, offset); 2471 BoundsCheckMem(memtype, index, offset);
2397 load = graph()->NewNode(jsgraph()->machine()->Load(memtype), 2472 // load =
2398 MemBuffer(offset), index, *effect_, *control_); 2473 // graph()->NewNode(jsgraph()->machine()->UnalignedLoad(memtype).op(),
2474 // MemBuffer(offset), index, *effect_, *control_);
2475 bool aligned = alignment >= ElementSizeLog2Of(memtype.representation());
titzer 2016/04/20 12:59:26 It's probably best to have a machine()->UnalignedL
2476 if (aligned ||
2477 !jsgraph()->machine()->UnalignedLoad(memtype).IsSupported()) {
2478 load = graph()->NewNode(jsgraph()->machine()->Load(memtype),
2479 MemBuffer(offset), index, *effect_, *control_);
2480 } else {
2481 load = BuildUnalignedLoad(type, memtype, index, offset);
2482 skip = true;
2483 }
2399 } 2484 }
2400 2485
2401 *effect_ = load; 2486 if (!skip) {
2487 *effect_ = load;
2488 }
2402 2489
2403 if (type == wasm::kAstI64 && 2490 if (type == wasm::kAstI64 &&
2404 ElementSizeLog2Of(memtype.representation()) < 3) { 2491 ElementSizeLog2Of(memtype.representation()) < 3) {
2405 // TODO(titzer): TF zeroes the upper bits of 64-bit loads for subword sizes. 2492 // TODO(titzer): TF zeroes the upper bits of 64-bit loads for subword sizes.
2406 if (memtype.IsSigned()) { 2493 if (memtype.IsSigned()) {
2407 // sign extend 2494 // sign extend
2408 load = graph()->NewNode(jsgraph()->machine()->ChangeInt32ToInt64(), load); 2495 load = graph()->NewNode(jsgraph()->machine()->ChangeInt32ToInt64(), load);
2409 } else { 2496 } else {
2410 // zero extend 2497 // zero extend
2411 load = 2498 load =
2412 graph()->NewNode(jsgraph()->machine()->ChangeUint32ToUint64(), load); 2499 graph()->NewNode(jsgraph()->machine()->ChangeUint32ToUint64(), load);
2413 } 2500 }
2414 } 2501 }
2415 2502
2416 return load; 2503 return load;
2417 } 2504 }
2418 2505
2506 Node* WasmGraphBuilder::BuildUnalignedStore(MachineType memtype, Node* index,
2507 uint32_t offset, uint32_t alignment,
2508 Node* val) {
2509 Node* store;
2510 Node* newValue;
2511
2512 wasm::WasmOpcode shiftOpcode;
2513
2514 Node* constEight;
2515 Node* mask;
2516 bool extendTo64Bit = false;
2517
2518 if (ElementSizeLog2Of(memtype.representation()) <= 2) {
2519 shiftOpcode = wasm::kExprI32ShrU;
2520 constEight = jsgraph()->Int32Constant(8);
2521 mask = jsgraph()->Int32Constant(0x000000ff);
2522 } else {
2523 shiftOpcode = wasm::kExprI64ShrU;
2524 constEight = jsgraph()->Int64Constant(8);
2525 mask = jsgraph()->Int64Constant(0x00000000000000ff);
2526 extendTo64Bit = true;
2527 }
2528
2529 bool isFloat = IsFloatingPoint(memtype.representation());
2530 int numberOfLoads = 1 << ElementSizeLog2Of(memtype.representation());
2531
2532 StoreRepresentation rep(MachineType::Uint8().representation(),
2533 kNoWriteBarrier);
2534
2535 newValue = val;
2536 if (isFloat) {
2537 switch (memtype.representation()) {
2538 case MachineRepresentation::kFloat64:
2539 newValue = Unop(wasm::kExprI64ReinterpretF64, val);
2540 break;
2541 case MachineRepresentation::kFloat32:
2542 newValue = Unop(wasm::kExprI32ReinterpretF32, val);
2543 break;
2544 default:
2545 UNREACHABLE();
2546 }
2547 }
2548
2549 DCHECK(numberOfLoads >= 2);
2550 for (int i = 0; i < numberOfLoads - 1; i++) {
2551 store = graph()->NewNode(
2552 jsgraph()->machine()->Store(rep), MemBuffer(offset + i), index,
2553 extendTo64Bit ? Unop(wasm::kExprI32ConvertI64, newValue) : newValue,
2554 *effect_, *control_);
2555 newValue = Binop(shiftOpcode, newValue, constEight);
2556 *effect_ = store;
2557 }
2558 store = graph()->NewNode(
2559 jsgraph()->machine()->Store(rep), MemBuffer(offset + numberOfLoads - 1),
2560 index,
2561 extendTo64Bit ? Unop(wasm::kExprI32ConvertI64, newValue) : newValue,
2562 *effect_, *control_);
2563 *effect_ = store;
2564 return val;
2565 }
2419 2566
2420 Node* WasmGraphBuilder::StoreMem(MachineType memtype, Node* index, 2567 Node* WasmGraphBuilder::StoreMem(MachineType memtype, Node* index,
2421 uint32_t offset, Node* val) { 2568 uint32_t offset, uint32_t alignment,
2569 Node* val) {
2422 Node* store; 2570 Node* store;
2571 bool skip = false;
2423 if (module_ && module_->asm_js()) { 2572 if (module_ && module_->asm_js()) {
2424 // asm.js semantics use CheckedStore (i.e. ignore OOB writes). 2573 // asm.js semantics use CheckedStore (i.e. ignore OOB writes).
2425 DCHECK_EQ(0, offset); 2574 DCHECK_EQ(0, offset);
2426 const Operator* op = 2575 const Operator* op =
2427 jsgraph()->machine()->CheckedStore(memtype.representation()); 2576 jsgraph()->machine()->CheckedStore(memtype.representation());
2428 store = graph()->NewNode(op, MemBuffer(0), index, MemSize(0), val, *effect_, 2577 store = graph()->NewNode(op, MemBuffer(0), index, MemSize(0), val, *effect_,
2429 *control_); 2578 *control_);
2430 } else { 2579 } else {
2431 // WASM semantics throw on OOB. Introduce explicit bounds check. 2580 // WASM semantics throw on OOB. Introduce explicit bounds check.
2432 BoundsCheckMem(memtype, index, offset); 2581 BoundsCheckMem(memtype, index, offset);
2433 StoreRepresentation rep(memtype.representation(), kNoWriteBarrier); 2582 StoreRepresentation rep(memtype.representation(), kNoWriteBarrier);
2434 store = 2583 bool aligned = alignment >= ElementSizeLog2Of(memtype.representation());
2435 graph()->NewNode(jsgraph()->machine()->Store(rep), MemBuffer(offset), 2584
2436 index, val, *effect_, *control_); 2585 if (aligned ||
2586 !jsgraph()
2587 ->machine()
2588 ->UnalignedStore(memtype.representation())
2589 .IsSupported()) {
2590 StoreRepresentation rep(memtype.representation(), kNoWriteBarrier);
2591 store =
2592 graph()->NewNode(jsgraph()->machine()->Store(rep), MemBuffer(offset),
2593 index, val, *effect_, *control_);
2594 } else {
2595 store = BuildUnalignedStore(memtype, index, offset, alignment, val);
2596 skip = true;
2597 }
2437 } 2598 }
2438 *effect_ = store; 2599 if (!skip) {
2600 *effect_ = store;
2601 }
2602
2439 return store; 2603 return store;
2440 } 2604 }
2441 2605
2442 2606
2443 void WasmGraphBuilder::PrintDebugName(Node* node) { 2607 void WasmGraphBuilder::PrintDebugName(Node* node) {
2444 PrintF("#%d:%s", node->id(), node->op()->mnemonic()); 2608 PrintF("#%d:%s", node->id(), node->op()->mnemonic());
2445 } 2609 }
2446 2610
2447 2611
2448 Node* WasmGraphBuilder::String(const char* string) { 2612 Node* WasmGraphBuilder::String(const char* string) {
(...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after
2780 static_cast<int>(function.code_end_offset - function.code_start_offset), 2944 static_cast<int>(function.code_end_offset - function.code_start_offset),
2781 decode_ms, static_cast<int>(graph.NodeCount()), compile_ms); 2945 decode_ms, static_cast<int>(graph.NodeCount()), compile_ms);
2782 } 2946 }
2783 return code; 2947 return code;
2784 } 2948 }
2785 2949
2786 2950
2787 } // namespace compiler 2951 } // namespace compiler
2788 } // namespace internal 2952 } // namespace internal
2789 } // namespace v8 2953 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/wasm-compiler.h ('k') | src/compiler/x64/instruction-selector-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698