Skip to content

Commit 352b9ec

Browse files
Bill BudgeCommit Bot
authored andcommitted
Reland "Reland "[compiler][wasm] Align Frame slots to value size""
This is a reland of 1694925 Minor fix to linkage for constexpr. TBR=ahaas@chromium.org,neis@chromium.org Original change's description: > Reland "[compiler][wasm] Align Frame slots to value size" > > This is a reland of cddaf66 > > Original change's description: > > [compiler][wasm] Align Frame slots to value size > > > > - Adds an AlignedSlotAllocator class and tests, to unify slot > > allocation. This attempts to use alignment holes for smaller > > values. > > - Reworks Frame to use the new allocator for stack slots. > > - Reworks LinkageAllocator to use the new allocator for stack > > slots and for ARMv7 FP register aliasing. > > - Fixes the RegisterAllocator to align spill slots. > > - Fixes InstructionSelector to align spill slots. > > > > Bug: v8:9198 > > > > Change-Id: Ida148db428be89ef95de748ec5fc0e7b0358f523 > > Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2512840 > > Commit-Queue: Bill Budge <bbudge@chromium.org> > > Reviewed-by: Georg Neis <neis@chromium.org> > > Reviewed-by: Andreas Haas <ahaas@chromium.org> > > Cr-Commit-Position: refs/heads/master@{#71644} > > Bug: v8:9198 > Change-Id: Ib91fa6746370c38496706341e12d05c7bf999389 > Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2633390 > Commit-Queue: Bill Budge <bbudge@chromium.org> > Reviewed-by: Andreas Haas <ahaas@chromium.org> > Reviewed-by: Georg Neis <neis@chromium.org> > Cr-Commit-Position: refs/heads/master@{#72195} Bug: v8:9198 Change-Id: I91e02b823af8ec925dacf075388fb22e3eeb3384 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2640890 Reviewed-by: Bill Budge <bbudge@chromium.org> Commit-Queue: Bill Budge <bbudge@chromium.org> Cr-Commit-Position: refs/heads/master@{#72209}
1 parent 5603f5c commit 352b9ec

16 files changed

Lines changed: 477 additions & 111 deletions

BUILD.gn

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2519,6 +2519,8 @@ v8_source_set("v8_base_without_compiler") {
25192519
"src/builtins/constants-table-builder.cc",
25202520
"src/builtins/constants-table-builder.h",
25212521
"src/builtins/profile-data-reader.h",
2522+
"src/codegen/aligned-slot-allocator.cc",
2523+
"src/codegen/aligned-slot-allocator.h",
25222524
"src/codegen/assembler-arch.h",
25232525
"src/codegen/assembler-inl.h",
25242526
"src/codegen/assembler.cc",
@@ -4384,6 +4386,7 @@ v8_component("v8_libbase") {
43844386

43854387
if (is_tsan && !build_with_chromium) {
43864388
data += [ "tools/sanitizers/tsan_suppressions.txt" ]
4389+
43874390
# llvm-symbolizer uses libstdc++ from the clang package.
43884391
data += [ "//third_party/llvm-build/Release+Asserts/lib/libstdc++.so.6" ]
43894392
}
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
// Copyright 2020 the V8 project authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#include "src/codegen/aligned-slot-allocator.h"
6+
7+
#include "src/base/bits.h"
8+
#include "src/base/logging.h"
9+
10+
namespace v8 {
11+
namespace internal {
12+
13+
// Define storage so we can use things like std::min that may take an address.
14+
constexpr int AlignedSlotAllocator::kSlotSize;
15+
16+
int AlignedSlotAllocator::NextSlot(int n) const {
17+
DCHECK(n == 1 || n == 2 || n == 4);
18+
if (n <= 1 && IsValid(next1_)) return next1_;
19+
if (n <= 2 && IsValid(next2_)) return next2_;
20+
DCHECK(IsValid(next4_));
21+
return next4_;
22+
}
23+
24+
int AlignedSlotAllocator::Allocate(int n) {
25+
DCHECK(n == 1 || n == 2 || n == 4);
26+
// Check invariants.
27+
DCHECK_EQ(0, next4_ & 3);
28+
DCHECK_IMPLIES(IsValid(next2_), (next2_ & 1) == 0);
29+
30+
// The sentinel value kInvalidSlot is used to indicate no slot.
31+
// next1_ is the index of the 1 slot fragment, or kInvalidSlot.
32+
// next2_ is the 2-aligned index of the 2 slot fragment, or kInvalidSlot.
33+
// next4_ is the 4-aligned index of the next 4 slot group. It is always valid.
34+
// In order to ensure we only have a single 1- or 2-slot fragment, we greedily
35+
// use any fragment that satisfies the request.
36+
int result = kInvalidSlot;
37+
switch (n) {
38+
case 1: {
39+
if (IsValid(next1_)) {
40+
result = next1_;
41+
next1_ = kInvalidSlot;
42+
} else if (IsValid(next2_)) {
43+
result = next2_;
44+
next1_ = result + 1;
45+
next2_ = kInvalidSlot;
46+
} else {
47+
result = next4_;
48+
next1_ = result + 1;
49+
next2_ = result + 2;
50+
next4_ += 4;
51+
}
52+
break;
53+
}
54+
case 2: {
55+
if (IsValid(next2_)) {
56+
result = next2_;
57+
next2_ = kInvalidSlot;
58+
} else {
59+
result = next4_;
60+
next2_ = result + 2;
61+
next4_ += 4;
62+
}
63+
break;
64+
}
65+
case 4: {
66+
result = next4_;
67+
next4_ += 4;
68+
break;
69+
}
70+
default:
71+
UNREACHABLE();
72+
break;
73+
}
74+
DCHECK(IsValid(result));
75+
size_ = std::max(size_, result + n);
76+
return result;
77+
}
78+
79+
int AlignedSlotAllocator::AllocateUnaligned(int n) {
80+
DCHECK_GE(n, 0);
81+
// Check invariants.
82+
DCHECK_EQ(0, next4_ & 3);
83+
DCHECK_IMPLIES(IsValid(next2_), (next2_ & 1) == 0);
84+
85+
// Reserve |n| slots at |size_|, invalidate fragments below the new |size_|,
86+
// and add any new fragments beyond the new |size_|.
87+
int result = size_;
88+
size_ += n;
89+
switch (size_ & 3) {
90+
case 0: {
91+
next1_ = next2_ = kInvalidSlot;
92+
next4_ = size_;
93+
break;
94+
}
95+
case 1: {
96+
next1_ = size_;
97+
next2_ = size_ + 1;
98+
next4_ = size_ + 3;
99+
break;
100+
}
101+
case 2: {
102+
next1_ = kInvalidSlot;
103+
next2_ = size_;
104+
next4_ = size_ + 2;
105+
break;
106+
}
107+
case 3: {
108+
next1_ = size_;
109+
next2_ = kInvalidSlot;
110+
next4_ = size_ + 1;
111+
break;
112+
}
113+
}
114+
return result;
115+
}
116+
117+
int AlignedSlotAllocator::Align(int n) {
118+
DCHECK(base::bits::IsPowerOfTwo(n));
119+
DCHECK_LE(n, 4);
120+
int mask = n - 1;
121+
int misalignment = size_ & mask;
122+
int padding = (n - misalignment) & mask;
123+
AllocateUnaligned(padding);
124+
return padding;
125+
}
126+
127+
} // namespace internal
128+
} // namespace v8
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
// Copyright 2020 the V8 project authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#ifndef V8_CODEGEN_ALIGNED_SLOT_ALLOCATOR_H_
6+
#define V8_CODEGEN_ALIGNED_SLOT_ALLOCATOR_H_
7+
8+
#include "src/base/macros.h"
9+
#include "src/base/platform/platform.h"
10+
#include "src/common/globals.h"
11+
12+
namespace v8 {
13+
namespace internal {
14+
15+
// An aligned slot allocator. Allocates groups of 1, 2, or 4 slots such that the
16+
// first slot of the group is aligned to the group size. The allocator can also
17+
// allocate unaligned groups of arbitrary size, and an align the number of slots
18+
// to 1, 2, or 4 slots. The allocator tries to be as thrifty as possible by
19+
// reusing alignment padding slots in subsequent smaller slot allocations.
20+
class V8_EXPORT_PRIVATE AlignedSlotAllocator {
21+
public:
22+
// Slots are always multiples of pointer-sized units.
23+
static constexpr int kSlotSize = kSystemPointerSize;
24+
25+
static int NumSlotsForWidth(int bytes) {
26+
DCHECK_GT(bytes, 0);
27+
return (bytes + kSlotSize - 1) / kSlotSize;
28+
}
29+
30+
AlignedSlotAllocator() = default;
31+
32+
// Allocates |n| slots, where |n| must be 1, 2, or 4. Padding slots may be
33+
// inserted for alignment.
34+
// Returns the starting index of the slots, which is evenly divisible by |n|.
35+
int Allocate(int n);
36+
37+
// Gets the starting index of the slots that would be returned by Allocate(n).
38+
int NextSlot(int n) const;
39+
40+
// Allocates the given number of slots at the current end of the slot area,
41+
// and returns the starting index of the slots. This resets any fragment
42+
// slots, so subsequent allocations will be after the end of this one.
43+
// AllocateUnaligned(0) can be used to partition the slot area, for example
44+
// to make sure tagged values follow untagged values on a Frame.
45+
int AllocateUnaligned(int n);
46+
47+
// Aligns the slot area so that future allocations begin at the alignment.
48+
// Returns the number of slots needed to align the slot area.
49+
int Align(int n);
50+
51+
// Returns the size of the slot area, in slots. This will be greater than any
52+
// already allocated slot index.
53+
int Size() const { return size_; }
54+
55+
private:
56+
static constexpr int kInvalidSlot = -1;
57+
58+
static bool IsValid(int slot) { return slot > kInvalidSlot; }
59+
60+
int next1_ = kInvalidSlot;
61+
int next2_ = kInvalidSlot;
62+
int next4_ = 0;
63+
int size_ = 0;
64+
65+
DISALLOW_NEW_AND_DELETE()
66+
};
67+
68+
} // namespace internal
69+
} // namespace v8
70+
71+
#endif // V8_CODEGEN_ALIGNED_SLOT_ALLOCATOR_H_

src/compiler/backend/arm/instruction-selector-arm.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -499,7 +499,7 @@ void VisitPairAtomicBinOp(InstructionSelector* selector, Node* node,
499499

500500
void InstructionSelector::VisitStackSlot(Node* node) {
501501
StackSlotRepresentation rep = StackSlotRepresentationOf(node->op());
502-
int slot = frame_->AllocateSpillSlot(rep.size());
502+
int slot = frame_->AllocateSpillSlot(rep.size(), rep.alignment());
503503
OperandGenerator g(this);
504504

505505
Emit(kArchStackSlot, g.DefineAsRegister(node),

src/compiler/backend/arm64/instruction-selector-arm64.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -566,7 +566,7 @@ int32_t LeftShiftForReducedMultiply(Matcher* m) {
566566

567567
void InstructionSelector::VisitStackSlot(Node* node) {
568568
StackSlotRepresentation rep = StackSlotRepresentationOf(node->op());
569-
int slot = frame_->AllocateSpillSlot(rep.size());
569+
int slot = frame_->AllocateSpillSlot(rep.size(), rep.alignment());
570570
OperandGenerator g(this);
571571

572572
Emit(kArchStackSlot, g.DefineAsRegister(node),

src/compiler/backend/ia32/instruction-selector-ia32.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -398,7 +398,7 @@ void VisitRROI8x16SimdShift(InstructionSelector* selector, Node* node,
398398

399399
void InstructionSelector::VisitStackSlot(Node* node) {
400400
StackSlotRepresentation rep = StackSlotRepresentationOf(node->op());
401-
int slot = frame_->AllocateSpillSlot(rep.size());
401+
int slot = frame_->AllocateSpillSlot(rep.size(), rep.alignment());
402402
OperandGenerator g(this);
403403

404404
Emit(kArchStackSlot, g.DefineAsRegister(node),

src/compiler/backend/ppc/instruction-selector-ppc.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ void VisitBinop(InstructionSelector* selector, Node* node,
155155

156156
void InstructionSelector::VisitStackSlot(Node* node) {
157157
StackSlotRepresentation rep = StackSlotRepresentationOf(node->op());
158-
int slot = frame_->AllocateSpillSlot(rep.size());
158+
int slot = frame_->AllocateSpillSlot(rep.size(), rep.alignment());
159159
OperandGenerator g(this);
160160

161161
Emit(kArchStackSlot, g.DefineAsRegister(node),

src/compiler/backend/register-allocator.cc

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4519,9 +4519,11 @@ void OperandAssigner::AssignSpillSlots() {
45194519
for (SpillRange* range : spill_ranges) {
45204520
data()->tick_counter()->TickAndMaybeEnterSafepoint();
45214521
if (range == nullptr || range->IsEmpty()) continue;
4522-
// Allocate a new operand referring to the spill slot.
45234522
if (!range->HasSlot()) {
4524-
int index = data()->frame()->AllocateSpillSlot(range->byte_width());
4523+
// Allocate a new operand referring to the spill slot, aligned to the
4524+
// operand size.
4525+
int width = range->byte_width();
4526+
int index = data()->frame()->AllocateSpillSlot(width, width);
45254527
range->set_assigned_slot(index);
45264528
}
45274529
}

src/compiler/backend/s390/instruction-selector-s390.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -680,7 +680,7 @@ void VisitBinOp(InstructionSelector* selector, Node* node,
680680

681681
void InstructionSelector::VisitStackSlot(Node* node) {
682682
StackSlotRepresentation rep = StackSlotRepresentationOf(node->op());
683-
int slot = frame_->AllocateSpillSlot(rep.size());
683+
int slot = frame_->AllocateSpillSlot(rep.size(), rep.alignment());
684684
OperandGenerator g(this);
685685

686686
Emit(kArchStackSlot, g.DefineAsRegister(node),

src/compiler/backend/x64/instruction-selector-x64.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,7 @@ ArchOpcode GetStoreOpcode(StoreRepresentation store_rep) {
336336

337337
void InstructionSelector::VisitStackSlot(Node* node) {
338338
StackSlotRepresentation rep = StackSlotRepresentationOf(node->op());
339-
int slot = frame_->AllocateSpillSlot(rep.size());
339+
int slot = frame_->AllocateSpillSlot(rep.size(), rep.alignment());
340340
OperandGenerator g(this);
341341

342342
Emit(kArchStackSlot, g.DefineAsRegister(node),

0 commit comments

Comments
 (0)