ae1eee10fa
There are still a few cases remaining that seem more controversial; I'll upload those separately. Bug: chromium:1066980 Change-Id: Iabbaf23f9bbe97781857c0c589f2b3db685dfdc2 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2994804 Commit-Queue: Peter Kasting <pkasting@chromium.org> Auto-Submit: Peter Kasting <pkasting@chromium.org> Reviewed-by: Ross McIlroy <rmcilroy@chromium.org> Cr-Commit-Position: refs/heads/master@{#75494}
125 lines
3.0 KiB
C++
125 lines
3.0 KiB
C++
// Copyright 2020 the V8 project authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#include "src/codegen/aligned-slot-allocator.h"
|
|
|
|
#include "src/base/bits.h"
|
|
#include "src/base/logging.h"
|
|
|
|
namespace v8 {
|
|
namespace internal {
|
|
|
|
int AlignedSlotAllocator::NextSlot(int n) const {
|
|
DCHECK(n == 1 || n == 2 || n == 4);
|
|
if (n <= 1 && IsValid(next1_)) return next1_;
|
|
if (n <= 2 && IsValid(next2_)) return next2_;
|
|
DCHECK(IsValid(next4_));
|
|
return next4_;
|
|
}
|
|
|
|
int AlignedSlotAllocator::Allocate(int n) {
|
|
DCHECK(n == 1 || n == 2 || n == 4);
|
|
// Check invariants.
|
|
DCHECK_EQ(0, next4_ & 3);
|
|
DCHECK_IMPLIES(IsValid(next2_), (next2_ & 1) == 0);
|
|
|
|
// The sentinel value kInvalidSlot is used to indicate no slot.
|
|
// next1_ is the index of the 1 slot fragment, or kInvalidSlot.
|
|
// next2_ is the 2-aligned index of the 2 slot fragment, or kInvalidSlot.
|
|
// next4_ is the 4-aligned index of the next 4 slot group. It is always valid.
|
|
// In order to ensure we only have a single 1- or 2-slot fragment, we greedily
|
|
// use any fragment that satisfies the request.
|
|
int result = kInvalidSlot;
|
|
switch (n) {
|
|
case 1: {
|
|
if (IsValid(next1_)) {
|
|
result = next1_;
|
|
next1_ = kInvalidSlot;
|
|
} else if (IsValid(next2_)) {
|
|
result = next2_;
|
|
next1_ = result + 1;
|
|
next2_ = kInvalidSlot;
|
|
} else {
|
|
result = next4_;
|
|
next1_ = result + 1;
|
|
next2_ = result + 2;
|
|
next4_ += 4;
|
|
}
|
|
break;
|
|
}
|
|
case 2: {
|
|
if (IsValid(next2_)) {
|
|
result = next2_;
|
|
next2_ = kInvalidSlot;
|
|
} else {
|
|
result = next4_;
|
|
next2_ = result + 2;
|
|
next4_ += 4;
|
|
}
|
|
break;
|
|
}
|
|
case 4: {
|
|
result = next4_;
|
|
next4_ += 4;
|
|
break;
|
|
}
|
|
default:
|
|
UNREACHABLE();
|
|
}
|
|
DCHECK(IsValid(result));
|
|
size_ = std::max(size_, result + n);
|
|
return result;
|
|
}
|
|
|
|
int AlignedSlotAllocator::AllocateUnaligned(int n) {
|
|
DCHECK_GE(n, 0);
|
|
// Check invariants.
|
|
DCHECK_EQ(0, next4_ & 3);
|
|
DCHECK_IMPLIES(IsValid(next2_), (next2_ & 1) == 0);
|
|
|
|
// Reserve |n| slots at |size_|, invalidate fragments below the new |size_|,
|
|
// and add any new fragments beyond the new |size_|.
|
|
int result = size_;
|
|
size_ += n;
|
|
switch (size_ & 3) {
|
|
case 0: {
|
|
next1_ = next2_ = kInvalidSlot;
|
|
next4_ = size_;
|
|
break;
|
|
}
|
|
case 1: {
|
|
next1_ = size_;
|
|
next2_ = size_ + 1;
|
|
next4_ = size_ + 3;
|
|
break;
|
|
}
|
|
case 2: {
|
|
next1_ = kInvalidSlot;
|
|
next2_ = size_;
|
|
next4_ = size_ + 2;
|
|
break;
|
|
}
|
|
case 3: {
|
|
next1_ = size_;
|
|
next2_ = kInvalidSlot;
|
|
next4_ = size_ + 1;
|
|
break;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
int AlignedSlotAllocator::Align(int n) {
|
|
DCHECK(base::bits::IsPowerOfTwo(n));
|
|
DCHECK_LE(n, 4);
|
|
int mask = n - 1;
|
|
int misalignment = size_ & mask;
|
|
int padding = (n - misalignment) & mask;
|
|
AllocateUnaligned(padding);
|
|
return padding;
|
|
}
|
|
|
|
} // namespace internal
|
|
} // namespace v8
|