76372353c1
This reverts commitdbbccae19a
. Reason for revert: Deadlock in TSAN with stress: https://ci.chromium.org/ui/p/v8/builders/ci/V8%20Linux64%20TSAN/44651/overview Original change's description: > Reland "[heap] Invoke allocation observers before limiting the LAB" > > This is a reland of commit39d387bb72
> > Original change's description: > > [heap] Invoke allocation observers before limiting the LAB > > > > Currently whenever we reach a step we get a small LAB the same size as > > the allocated object. This is becuase the remaining step size is smaller > > then the current allocation. > > Invoking observers before limiting the LAB, and thus updating step > > sizes, should eliminate the small LAB we get whenever we reach a step. > > > > Drive-by: remove redundant method arguments. > > > > Bug: v8:12612 > > Change-Id: Ied92a947308368d3b289e246fdb4f40ac5e5981f > > Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4013683 > > Reviewed-by: Dominik Inführ <dinfuehr@chromium.org> > > Reviewed-by: Michael Lippautz <mlippautz@chromium.org> > > Commit-Queue: Omer Katz <omerkatz@chromium.org> > > Cr-Commit-Position: refs/heads/main@{#84157} > > Bug: v8:12612, v8:13465 > Change-Id: I40fb930a755cb5decccd932c4d25ed7d5d224da4 > Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4020177 > Reviewed-by: Dominik Inführ <dinfuehr@chromium.org> > Reviewed-by: Michael Lippautz <mlippautz@chromium.org> > Commit-Queue: Omer Katz <omerkatz@chromium.org> > Cr-Commit-Position: refs/heads/main@{#84328} Bug: v8:12612, v8:13465 Change-Id: I70df00448c7413999b91412343915c503baf0dd3 No-Presubmit: true No-Tree-Checks: true No-Try: true Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4035252 Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com> Commit-Queue: Shu-yu Guo <syg@chromium.org> Owners-Override: Shu-yu Guo <syg@chromium.org> Cr-Commit-Position: refs/heads/main@{#84345}
181 lines
5.2 KiB
C++
181 lines
5.2 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/heap/allocation-observer.h"
|
|
|
|
#include "src/base/logging.h"
|
|
#include "test/unittests/test-utils.h"
|
|
#include "testing/gtest/include/gtest/gtest.h"
|
|
|
|
namespace v8 {
|
|
namespace internal {
|
|
|
|
namespace {
|
|
class UnusedObserver : public AllocationObserver {
|
|
public:
|
|
explicit UnusedObserver(size_t step_size) : AllocationObserver(step_size) {}
|
|
void Step(int bytes_allocated, Address soon_object, size_t size) override {
|
|
CHECK(false);
|
|
}
|
|
};
|
|
} // namespace
|
|
|
|
TEST(AllocationObserverTest, AddAndRemoveUnusedObservers) {
|
|
AllocationCounter counter;
|
|
CHECK(!counter.IsActive());
|
|
|
|
UnusedObserver observer100(100);
|
|
UnusedObserver observer200(200);
|
|
|
|
counter.AddAllocationObserver(&observer200);
|
|
CHECK_EQ(counter.NextBytes(), 200);
|
|
|
|
counter.AddAllocationObserver(&observer100);
|
|
CHECK_EQ(counter.NextBytes(), 100);
|
|
|
|
counter.AdvanceAllocationObservers(90);
|
|
CHECK_EQ(counter.NextBytes(), 10);
|
|
|
|
counter.RemoveAllocationObserver(&observer100);
|
|
CHECK_EQ(counter.NextBytes(), 110);
|
|
|
|
counter.RemoveAllocationObserver(&observer200);
|
|
CHECK(!counter.IsActive());
|
|
}
|
|
|
|
namespace {
|
|
class VerifyStepObserver : public AllocationObserver {
|
|
public:
|
|
explicit VerifyStepObserver(size_t step_size)
|
|
: AllocationObserver(step_size) {}
|
|
|
|
void Step(int bytes_allocated, Address soon_object, size_t size) override {
|
|
CHECK(!do_not_invoke_);
|
|
|
|
invocations_++;
|
|
CHECK_EQ(expected_bytes_allocated_, bytes_allocated);
|
|
CHECK_EQ(expected_size_, size);
|
|
}
|
|
|
|
void ExpectNoInvocation() { do_not_invoke_ = true; }
|
|
void Expect(int expected_bytes_allocated, size_t expected_size) {
|
|
do_not_invoke_ = false;
|
|
expected_bytes_allocated_ = expected_bytes_allocated;
|
|
expected_size_ = expected_size;
|
|
}
|
|
|
|
int Invocations() { return invocations_; }
|
|
|
|
private:
|
|
bool do_not_invoke_ = false;
|
|
int invocations_ = 0;
|
|
int expected_bytes_allocated_ = 0;
|
|
size_t expected_size_ = 0;
|
|
};
|
|
} // namespace
|
|
|
|
TEST(AllocationObserverTest, Step) {
|
|
AllocationCounter counter;
|
|
CHECK(!counter.IsActive());
|
|
const Address kSomeObjectAddress = 8;
|
|
|
|
VerifyStepObserver observer100(100);
|
|
VerifyStepObserver observer200(200);
|
|
|
|
counter.AddAllocationObserver(&observer100);
|
|
counter.AddAllocationObserver(&observer200);
|
|
|
|
observer100.Expect(90, 8);
|
|
observer200.ExpectNoInvocation();
|
|
|
|
counter.AdvanceAllocationObservers(90);
|
|
counter.InvokeAllocationObservers(kSomeObjectAddress, 8, 10);
|
|
CHECK_EQ(observer100.Invocations(), 1);
|
|
CHECK_EQ(observer200.Invocations(), 0);
|
|
CHECK_EQ(counter.NextBytes(),
|
|
10 /* aligned_object_size */ + 100 /* smallest step size*/);
|
|
|
|
observer100.Expect(90, 16);
|
|
observer200.Expect(180, 16);
|
|
|
|
counter.AdvanceAllocationObservers(90);
|
|
counter.InvokeAllocationObservers(kSomeObjectAddress, 16, 20);
|
|
CHECK_EQ(observer100.Invocations(), 2);
|
|
CHECK_EQ(observer200.Invocations(), 1);
|
|
CHECK_EQ(counter.NextBytes(),
|
|
20 /* aligned_object_size */ + 100 /* smallest step size*/);
|
|
}
|
|
|
|
namespace {
|
|
class RecursiveAddObserver : public AllocationObserver {
|
|
public:
|
|
explicit RecursiveAddObserver(size_t step_size, AllocationCounter* counter,
|
|
AllocationObserver* observer)
|
|
: AllocationObserver(step_size), counter_(counter), observer_(observer) {}
|
|
|
|
void Step(int bytes_allocated, Address soon_object, size_t size) override {
|
|
counter_->AddAllocationObserver(observer_);
|
|
}
|
|
|
|
private:
|
|
AllocationCounter* counter_;
|
|
AllocationObserver* observer_;
|
|
};
|
|
} // namespace
|
|
|
|
TEST(AllocationObserverTest, RecursiveAdd) {
|
|
AllocationCounter counter;
|
|
const Address kSomeObjectAddress = 8;
|
|
|
|
UnusedObserver observer50(50);
|
|
RecursiveAddObserver observer100(100, &counter, &observer50);
|
|
|
|
counter.AddAllocationObserver(&observer100);
|
|
|
|
CHECK_EQ(counter.NextBytes(), 100);
|
|
counter.AdvanceAllocationObservers(90);
|
|
counter.InvokeAllocationObservers(kSomeObjectAddress, 10, 10);
|
|
|
|
CHECK_EQ(counter.NextBytes(),
|
|
10 /* aligned_object_size */ + 50 /* smallest step size */);
|
|
}
|
|
|
|
namespace {
|
|
class RecursiveRemoveObserver : public AllocationObserver {
|
|
public:
|
|
explicit RecursiveRemoveObserver(size_t step_size, AllocationCounter* counter,
|
|
AllocationObserver* observer)
|
|
: AllocationObserver(step_size), counter_(counter), observer_(observer) {}
|
|
|
|
void Step(int bytes_allocated, Address soon_object, size_t size) override {
|
|
counter_->RemoveAllocationObserver(observer_);
|
|
}
|
|
|
|
private:
|
|
AllocationCounter* counter_;
|
|
AllocationObserver* observer_;
|
|
};
|
|
} // namespace
|
|
|
|
TEST(AllocationObserverTest, RecursiveRemove) {
|
|
AllocationCounter counter;
|
|
const Address kSomeObjectAddress = 8;
|
|
|
|
UnusedObserver observer75(75);
|
|
RecursiveRemoveObserver observer50(50, &counter, &observer75);
|
|
|
|
counter.AddAllocationObserver(&observer50);
|
|
counter.AddAllocationObserver(&observer75);
|
|
|
|
CHECK_EQ(counter.NextBytes(), 50);
|
|
counter.AdvanceAllocationObservers(40);
|
|
counter.InvokeAllocationObservers(kSomeObjectAddress, 10, 10);
|
|
|
|
CHECK_EQ(counter.NextBytes(),
|
|
10 /* aligned_object_size */ + 50 /* smallest step size */);
|
|
}
|
|
|
|
} // namespace internal
|
|
} // namespace v8
|