Commit 6b32e7d1 authored by Dominik Inführ's avatar Dominik Inführ Committed by V8 LUCI CQ

[heap] Fix concurrent allocation in shared map space

Two DCHECKS had to updated to allow for concurrent MAP_SPACE
allocations.

Bug: v8:11708
Change-Id: I8a059d2e5942f511802a95ec27cf566414dd740e
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2951724Reviewed-by: 's avatarMichael Lippautz <mlippautz@chromium.org>
Commit-Queue: Dominik Inführ <dinfuehr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#75105}
parent a5667321
......@@ -1599,15 +1599,17 @@ Handle<AllocationSite> Factory::NewAllocationSite(bool with_weak_next) {
}
Handle<Map> Factory::NewMap(InstanceType type, int instance_size,
ElementsKind elements_kind,
int inobject_properties) {
ElementsKind elements_kind, int inobject_properties,
AllocationType allocation_type) {
STATIC_ASSERT(LAST_JS_OBJECT_TYPE == LAST_TYPE);
DCHECK_IMPLIES(InstanceTypeChecker::IsJSObject(type) &&
!Map::CanHaveFastTransitionableElementsKind(type),
IsDictionaryElementsKind(elements_kind) ||
IsTerminalElementsKind(elements_kind));
DCHECK(allocation_type == AllocationType::kMap ||
allocation_type == AllocationType::kSharedMap);
HeapObject result = isolate()->heap()->AllocateRawWith<Heap::kRetryOrFail>(
Map::kSize, AllocationType::kMap);
Map::kSize, allocation_type);
DisallowGarbageCollection no_gc;
result.set_map_after_allocation(*meta_map(), SKIP_WRITE_BARRIER);
return handle(InitializeMap(Map::cast(result), type, instance_size,
......
......@@ -411,7 +411,8 @@ class V8_EXPORT_PRIVATE Factory : public FactoryBase<Factory> {
// Allocates and initializes a new Map.
Handle<Map> NewMap(InstanceType type, int instance_size,
ElementsKind elements_kind = TERMINAL_FAST_ELEMENTS_KIND,
int inobject_properties = 0);
int inobject_properties = 0,
AllocationType allocation_type = AllocationType::kMap);
// Initializes the fields of a newly created Map. Exposed for tests and
// heap setup; other code should just call NewMap which takes care of it.
Map InitializeMap(Map map, InstanceType type, int instance_size,
......
......@@ -555,7 +555,8 @@ bool PagedSpace::TryAllocationFromFreeListMain(size_t size_in_bytes,
base::Optional<std::pair<Address, size_t>> PagedSpace::RawRefillLabBackground(
LocalHeap* local_heap, size_t min_size_in_bytes, size_t max_size_in_bytes,
AllocationAlignment alignment, AllocationOrigin origin) {
DCHECK(!is_compaction_space() && identity() == OLD_SPACE);
DCHECK(!is_compaction_space());
DCHECK(identity() == OLD_SPACE || identity() == MAP_SPACE);
DCHECK_EQ(origin, AllocationOrigin::kRuntime);
auto result = TryAllocationFromFreeListBackground(
......@@ -625,7 +626,7 @@ PagedSpace::TryAllocationFromFreeListBackground(LocalHeap* local_heap,
AllocationOrigin origin) {
base::MutexGuard lock(&space_mutex_);
DCHECK_LE(min_size_in_bytes, max_size_in_bytes);
DCHECK_EQ(identity(), OLD_SPACE);
DCHECK(identity() == OLD_SPACE || identity() == MAP_SPACE);
size_t new_node_size = 0;
FreeSpace new_node =
......
......@@ -15,21 +15,33 @@ namespace internal {
namespace {
const int kNumIterations = 2000;
class SharedSpaceAllocationThread final : public v8::base::Thread {
template <typename Callback>
void SetupClientIsolateAndRunCallback(Isolate* shared_isolate,
Callback callback) {
std::unique_ptr<v8::ArrayBuffer::Allocator> allocator(
v8::ArrayBuffer::Allocator::NewDefaultAllocator());
v8::Isolate::CreateParams create_params;
create_params.array_buffer_allocator = allocator.get();
v8::Isolate* client_isolate = v8::Isolate::New(create_params);
Isolate* i_client_isolate = reinterpret_cast<Isolate*>(client_isolate);
i_client_isolate->AttachToSharedIsolate(shared_isolate);
callback(client_isolate, i_client_isolate);
client_isolate->Dispose();
}
class SharedOldSpaceAllocationThread final : public v8::base::Thread {
public:
explicit SharedSpaceAllocationThread(Isolate* shared)
: v8::base::Thread(base::Thread::Options("SharedSpaceAllocationThread")),
explicit SharedOldSpaceAllocationThread(Isolate* shared)
: v8::base::Thread(
base::Thread::Options("SharedOldSpaceAllocationThread")),
shared_(shared) {}
void Run() override {
v8::Isolate::CreateParams create_params;
allocator_.reset(v8::ArrayBuffer::Allocator::NewDefaultAllocator());
create_params.array_buffer_allocator = allocator_.get();
v8::Isolate* client_isolate = v8::Isolate::New(create_params);
Isolate* i_client_isolate = reinterpret_cast<Isolate*>(client_isolate);
i_client_isolate->AttachToSharedIsolate(shared_);
{
SetupClientIsolateAndRunCallback(shared_, [](v8::Isolate* client_isolate,
Isolate* i_client_isolate) {
HandleScope scope(i_client_isolate);
for (int i = 0; i < kNumIterations; i++) {
......@@ -41,13 +53,10 @@ class SharedSpaceAllocationThread final : public v8::base::Thread {
v8::platform::PumpMessageLoop(i::V8::GetCurrentPlatform(),
client_isolate);
}
client_isolate->Dispose();
});
}
Isolate* shared_;
std::unique_ptr<v8::ArrayBuffer::Allocator> allocator_;
};
} // namespace
......@@ -59,11 +68,67 @@ UNINITIALIZED_TEST(ConcurrentAllocationInSharedOldSpace) {
create_params.array_buffer_allocator = allocator.get();
Isolate* shared_isolate = Isolate::NewShared(create_params);
std::vector<std::unique_ptr<SharedSpaceAllocationThread>> threads;
std::vector<std::unique_ptr<SharedOldSpaceAllocationThread>> threads;
const int kThreads = 4;
for (int i = 0; i < kThreads; i++) {
auto thread =
std::make_unique<SharedOldSpaceAllocationThread>(shared_isolate);
CHECK(thread->Start());
threads.push_back(std::move(thread));
}
for (auto& thread : threads) {
thread->Join();
}
Isolate::Delete(shared_isolate);
}
namespace {
class SharedMapSpaceAllocationThread final : public v8::base::Thread {
public:
explicit SharedMapSpaceAllocationThread(Isolate* shared)
: v8::base::Thread(
base::Thread::Options("SharedMapSpaceAllocationThread")),
shared_(shared) {}
void Run() override {
SetupClientIsolateAndRunCallback(
shared_, [](v8::Isolate* client_isolate, Isolate* i_client_isolate) {
HandleScope scope(i_client_isolate);
for (int i = 0; i < kNumIterations; i++) {
i_client_isolate->factory()->NewMap(
NATIVE_CONTEXT_TYPE, kVariableSizeSentinel,
TERMINAL_FAST_ELEMENTS_KIND, 0, AllocationType::kSharedMap);
}
CcTest::CollectGarbage(OLD_SPACE, i_client_isolate);
v8::platform::PumpMessageLoop(i::V8::GetCurrentPlatform(),
client_isolate);
});
}
Isolate* shared_;
};
} // namespace
UNINITIALIZED_TEST(ConcurrentAllocationInSharedMapSpace) {
std::unique_ptr<v8::ArrayBuffer::Allocator> allocator(
v8::ArrayBuffer::Allocator::NewDefaultAllocator());
v8::Isolate::CreateParams create_params;
create_params.array_buffer_allocator = allocator.get();
Isolate* shared_isolate = Isolate::NewShared(create_params);
std::vector<std::unique_ptr<SharedMapSpaceAllocationThread>> threads;
const int kThreads = 4;
for (int i = 0; i < kThreads; i++) {
auto thread = std::make_unique<SharedSpaceAllocationThread>(shared_isolate);
auto thread =
std::make_unique<SharedMapSpaceAllocationThread>(shared_isolate);
CHECK(thread->Start());
threads.push_back(std::move(thread));
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment