v8/test/cctest/test-concurrent-descriptor-array.cc
Georg Neis 04c85d7cf8 Revert "[compiler, heap] Create LocalHeap outside of ExecuteJob"
This reverts commit 44708a5b6f.

Reason for revert: https://ci.chromium.org/p/v8/builders/ci/V8%20Linux64%20TSAN/33692

Original change's description:
> [compiler, heap] Create LocalHeap outside of ExecuteJob
>
> Create LocalHeap directly in the Task or in GetOptimizedCodeNow and
> pass its reference as argument to ExecuteJob. This allows us to create
> LocalHeap differently for the main and background thread, e.g. by
> passing an additional argument to the constructor in the future.
> It will be required in the future anyways when the main thread will
> have its own LocalHeap/LocalIsolate.
>
> Extending the scope of LocalHeap, also made
> HandleBase::IsDereferenceAllowed more precise and uncovered two
> potential issues: heap accesses in
> OptimizingCompileDispatcher::CompileNext and PipelineImpl::AssembleCode
> with --code-comments.
>
> LocalHeap can now be created in the parked state. Also fixed a data
> race with LocalHeap's destructor publishing write barrier entries
> without holding the lock.
>
> Bug: v8:10315
> Change-Id: I9226972601a07b87108cd66efbbb6a0d118af58d
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2460818
> Commit-Queue: Georg Neis <neis@chromium.org>
> Reviewed-by: Leszek Swirski <leszeks@chromium.org>
> Reviewed-by: Santiago Aboy Solanes <solanes@chromium.org>
> Reviewed-by: Georg Neis <neis@chromium.org>
> Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#70521}

TBR=ulan@chromium.org,neis@chromium.org,leszeks@chromium.org,solanes@chromium.org,dinfuehr@chromium.org

Change-Id: I9dd1f8ca6237d5716b6d8938cef0ee3f642f3166
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: v8:10315
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2474118
Reviewed-by: Georg Neis <neis@chromium.org>
Commit-Queue: Georg Neis <neis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#70522}
2020-10-15 07:51:55 +00:00

188 lines
6.4 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/api/api.h"
#include "src/base/platform/semaphore.h"
#include "src/handles/handles-inl.h"
#include "src/handles/local-handles-inl.h"
#include "src/handles/persistent-handles.h"
#include "src/heap/heap.h"
#include "src/heap/local-heap-inl.h"
#include "src/heap/local-heap.h"
#include "test/cctest/cctest.h"
#include "test/cctest/heap/heap-utils.h"
namespace v8 {
namespace internal {
static constexpr int kNumHandles = kHandleBlockSize * 2 + kHandleBlockSize / 2;
namespace {
class ConcurrentSearchThread final : public v8::base::Thread {
public:
ConcurrentSearchThread(Heap* heap, std::vector<Handle<JSObject>> handles,
std::unique_ptr<PersistentHandles> ph,
Handle<Name> name, base::Semaphore* sema_started)
: v8::base::Thread(base::Thread::Options("ThreadWithLocalHeap")),
heap_(heap),
handles_(std::move(handles)),
ph_(std::move(ph)),
name_(name),
sema_started_(sema_started) {}
void Run() override {
LocalHeap local_heap(heap_, std::move(ph_));
LocalHandleScope scope(&local_heap);
for (int i = 0; i < kNumHandles; i++) {
handles_.push_back(local_heap.NewPersistentHandle(handles_[0]));
}
sema_started_->Signal();
for (Handle<JSObject> handle : handles_) {
// Lookup the named property on the {map}.
CHECK(name_->IsUniqueName());
Handle<Map> map(handle->map(), &local_heap);
Handle<DescriptorArray> descriptors(
map->instance_descriptors(kAcquireLoad), &local_heap);
bool is_background_thread = true;
InternalIndex const number =
descriptors->Search(*name_, *map, is_background_thread);
CHECK(number.is_found());
}
CHECK_EQ(handles_.size(), kNumHandles * 2);
}
private:
Heap* heap_;
std::vector<Handle<JSObject>> handles_;
std::unique_ptr<PersistentHandles> ph_;
Handle<Name> name_;
base::Semaphore* sema_started_;
};
// Uses linear search on a flat object, with up to 8 elements.
TEST(LinearSearchFlatObject) {
heap::EnsureFlagLocalHeapsEnabled();
CcTest::InitializeVM();
Isolate* isolate = CcTest::i_isolate();
std::unique_ptr<PersistentHandles> ph = isolate->NewPersistentHandles();
std::vector<Handle<JSObject>> handles;
auto factory = isolate->factory();
HandleScope handle_scope(isolate);
Handle<JSFunction> function =
factory->NewFunctionForTest(factory->empty_string());
Handle<JSObject> js_object = factory->NewJSObject(function);
Handle<String> name = CcTest::MakeString("property");
Handle<Object> value = CcTest::MakeString("dummy_value");
// For the default constructor function no in-object properties are reserved
// hence adding a single property will initialize the property-array.
JSObject::DefinePropertyOrElementIgnoreAttributes(js_object, name, value,
NONE)
.Check();
for (int i = 0; i < kNumHandles; i++) {
handles.push_back(ph->NewHandle(js_object));
}
Handle<Name> persistent_name = ph->NewHandle(name);
base::Semaphore sema_started(0);
// Pass persistent handles to background thread.
std::unique_ptr<ConcurrentSearchThread> thread(new ConcurrentSearchThread(
isolate->heap(), std::move(handles), std::move(ph), persistent_name,
&sema_started));
CHECK(thread->Start());
sema_started.Wait();
// Exercise descriptor in main thread too.
for (int i = 0; i < 7; ++i) {
Handle<String> filler_name = CcTest::MakeName("filler_property_", i);
Handle<Object> filler_value = CcTest::MakeString("dummy_value");
JSObject::DefinePropertyOrElementIgnoreAttributes(js_object, filler_name,
filler_value, NONE)
.Check();
}
CHECK_EQ(js_object->map().NumberOfOwnDescriptors(), 8);
thread->Join();
}
// Uses linear search on a flat object, which has more than 8 elements.
TEST(LinearSearchFlatObject_ManyElements) {
heap::EnsureFlagLocalHeapsEnabled();
CcTest::InitializeVM();
Isolate* isolate = CcTest::i_isolate();
std::unique_ptr<PersistentHandles> ph = isolate->NewPersistentHandles();
std::vector<Handle<JSObject>> handles;
auto factory = isolate->factory();
HandleScope handle_scope(isolate);
Handle<JSFunction> function =
factory->NewFunctionForTest(factory->empty_string());
Handle<JSObject> js_object = factory->NewJSObject(function);
Handle<String> name = CcTest::MakeString("property");
Handle<Object> value = CcTest::MakeString("dummy_value");
// For the default constructor function no in-object properties are reserved
// hence adding a single property will initialize the property-array.
JSObject::DefinePropertyOrElementIgnoreAttributes(js_object, name, value,
NONE)
.Check();
// If we have more than 8 properties we would do a binary search. However,
// since we are going search in a background thread, we force a linear search
// that is safe to do in the background.
for (int i = 0; i < 10; ++i) {
Handle<String> filler_name = CcTest::MakeName("filler_property_", i);
Handle<Object> filler_value = CcTest::MakeString("dummy_value");
JSObject::DefinePropertyOrElementIgnoreAttributes(js_object, filler_name,
filler_value, NONE)
.Check();
}
CHECK_GT(js_object->map().NumberOfOwnDescriptors(), 8);
for (int i = 0; i < kNumHandles; i++) {
handles.push_back(ph->NewHandle(js_object));
}
Handle<Name> persistent_name = ph->NewHandle(name);
base::Semaphore sema_started(0);
// Pass persistent handles to background thread.
std::unique_ptr<ConcurrentSearchThread> thread(new ConcurrentSearchThread(
isolate->heap(), std::move(handles), std::move(ph), persistent_name,
&sema_started));
CHECK(thread->Start());
sema_started.Wait();
// Exercise descriptor in main thread too.
for (int i = 10; i < 20; ++i) {
Handle<String> filler_name = CcTest::MakeName("filler_property_", i);
Handle<Object> filler_value = CcTest::MakeString("dummy_value");
JSObject::DefinePropertyOrElementIgnoreAttributes(js_object, filler_name,
filler_value, NONE)
.Check();
}
thread->Join();
}
} // anonymous namespace
} // namespace internal
} // namespace v8