Commit 94cf4347 authored by Santiago Aboy Solanes's avatar Santiago Aboy Solanes Committed by Commit Bot

[compiler] Test transition from Uninitialized to kFullTransitionArray

Since we have an uninitialized TransitionArray that we want to insert
an element (map1), we can't guarantee that said element would exist at
the point of the search. Then, we search for an element guaranteed not
to be (map2) and we check that we did not find it.

If we have a data race, this would also trigger it.

Bug: v8:7790
Change-Id: Ib90044d7c0901d599aed041f608f2c0bce506d67
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2319995
Commit-Queue: Santiago Aboy Solanes <solanes@chromium.org>
Reviewed-by: 's avatarNico Hartmann <nicohartmann@chromium.org>
Cr-Commit-Position: refs/heads/master@{#69099}
parent 367da305
......@@ -23,7 +23,7 @@ class ConcurrentSearchThread final : public v8::base::Thread {
ConcurrentSearchThread(Heap* heap, base::Semaphore* sema_started,
std::unique_ptr<PersistentHandles> ph,
Handle<Name> name, Handle<Map> map,
Handle<Map> result_map)
base::Optional<Handle<Map>> result_map)
: v8::base::Thread(base::Thread::Options("ThreadWithLocalHeap")),
heap_(heap),
sema_started_(sema_started),
......@@ -39,7 +39,7 @@ class ConcurrentSearchThread final : public v8::base::Thread {
CHECK_EQ(TransitionsAccessor(CcTest::i_isolate(), map_, true)
.SearchTransition(*name_, kData, NONE),
*result_map_);
result_map_ ? **result_map_ : Map());
CHECK(!ph_);
ph_ = local_heap.DetachPersistentHandles();
......@@ -50,7 +50,7 @@ class ConcurrentSearchThread final : public v8::base::Thread {
std::unique_ptr<PersistentHandles> ph_;
Handle<Name> name_;
Handle<Map> map_;
Handle<Map> result_map_;
base::Optional<Handle<Map>> result_map_;
};
// Search on the main thread and in the background thread at the same time.
......@@ -79,15 +79,15 @@ TEST(FullFieldTransitions_OnlySearch) {
std::unique_ptr<PersistentHandles> ph = isolate->NewPersistentHandles();
Handle<Name> persistent_name = ph->NewHandle(name);
Handle<Map> persistent_map = ph->NewHandle(map0);
Handle<Map> persistent_result_map = ph->NewHandle(map1);
Handle<Map> persistent_map0 = ph->NewHandle(map0);
Handle<Map> persistent_result_map1 = ph->NewHandle(map1);
base::Semaphore sema_started(0);
// Pass persistent handles to background thread.
std::unique_ptr<ConcurrentSearchThread> thread(new ConcurrentSearchThread(
isolate->heap(), &sema_started, std::move(ph), persistent_name,
persistent_map, persistent_result_map));
persistent_map0, persistent_result_map1));
CHECK(thread->Start());
sema_started.Wait();
......@@ -130,16 +130,16 @@ TEST(FullFieldTransitions) {
std::unique_ptr<PersistentHandles> ph = isolate->NewPersistentHandles();
Handle<Name> persistent_name = ph->NewHandle(name1);
Handle<Map> persistent_map = ph->NewHandle(map0);
Handle<Map> persistent_result_map = ph->NewHandle(map1);
Handle<Name> persistent_name1 = ph->NewHandle(name1);
Handle<Map> persistent_map0 = ph->NewHandle(map0);
Handle<Map> persistent_result_map1 = ph->NewHandle(map1);
base::Semaphore sema_started(0);
// Pass persistent handles to background thread.
std::unique_ptr<ConcurrentSearchThread> thread(new ConcurrentSearchThread(
isolate->heap(), &sema_started, std::move(ph), persistent_name,
persistent_map, persistent_result_map));
isolate->heap(), &sema_started, std::move(ph), persistent_name1,
persistent_map0, persistent_result_map1));
CHECK(thread->Start());
sema_started.Wait();
......@@ -187,16 +187,16 @@ TEST(WeakRefToFullFieldTransitions) {
std::unique_ptr<PersistentHandles> ph = isolate->NewPersistentHandles();
Handle<Name> persistent_name = ph->NewHandle(name1);
Handle<Map> persistent_map = ph->NewHandle(map0);
Handle<Map> persistent_result_map = ph->NewHandle(map1);
Handle<Name> persistent_name1 = ph->NewHandle(name1);
Handle<Map> persistent_map0 = ph->NewHandle(map0);
Handle<Map> persistent_result_map1 = ph->NewHandle(map1);
base::Semaphore sema_started(0);
// Pass persistent handles to background thread.
std::unique_ptr<ConcurrentSearchThread> thread(new ConcurrentSearchThread(
isolate->heap(), &sema_started, std::move(ph), persistent_name,
persistent_map, persistent_result_map));
isolate->heap(), &sema_started, std::move(ph), persistent_name1,
persistent_map0, persistent_result_map1));
CHECK(thread->Start());
sema_started.Wait();
......@@ -255,16 +255,16 @@ TEST(FullFieldTransitions_withSlack) {
std::unique_ptr<PersistentHandles> ph = isolate->NewPersistentHandles();
Handle<Name> persistent_name = ph->NewHandle(name1);
Handle<Map> persistent_map = ph->NewHandle(map0);
Handle<Map> persistent_result_map = ph->NewHandle(map1);
Handle<Name> persistent_name1 = ph->NewHandle(name1);
Handle<Map> persistent_map0 = ph->NewHandle(map0);
Handle<Map> persistent_result_map1 = ph->NewHandle(map1);
base::Semaphore sema_started(0);
// Pass persistent handles to background thread.
std::unique_ptr<ConcurrentSearchThread> thread(new ConcurrentSearchThread(
isolate->heap(), &sema_started, std::move(ph), persistent_name,
persistent_map, persistent_result_map));
isolate->heap(), &sema_started, std::move(ph), persistent_name1,
persistent_map0, persistent_result_map1));
CHECK(thread->Start());
sema_started.Wait();
......@@ -286,6 +286,57 @@ TEST(FullFieldTransitions_withSlack) {
thread->Join();
}
// Search and insert on the main thread which changes the encoding from
// kUninitialized to kFullTransitionArray, while the background thread searches
// at the same time.
TEST(UninitializedToFullFieldTransitions) {
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
Isolate* isolate = CcTest::i_isolate();
Handle<String> name1 = CcTest::MakeString("name1");
Handle<String> name2 = CcTest::MakeString("name2");
const PropertyAttributes attributes = NONE;
const PropertyKind kind = kData;
// Set map0 to be a full transition array with transition 'name1' to map1.
Handle<Map> map0 = Map::Create(isolate, 0);
Handle<Map> map1 =
Map::CopyWithField(isolate, map0, name1, FieldType::Any(isolate),
attributes, PropertyConstness::kMutable,
Representation::Tagged(), OMIT_TRANSITION)
.ToHandleChecked();
{
TestTransitionsAccessor transitions(isolate, map0);
CHECK(transitions.IsUninitializedEncoding());
}
std::unique_ptr<PersistentHandles> ph = isolate->NewPersistentHandles();
Handle<Name> persistent_name2 = ph->NewHandle(name2);
Handle<Map> persistent_map0 = ph->NewHandle(map0);
base::Semaphore background_thread_started(0);
// Pass persistent handles to background thread.
// Background thread will search for name2, guaranteed to *not* be on the map.
std::unique_ptr<ConcurrentSearchThread> thread(new ConcurrentSearchThread(
isolate->heap(), &background_thread_started, std::move(ph),
persistent_name2, persistent_map0, base::nullopt));
CHECK(thread->Start());
background_thread_started.Wait();
TransitionsAccessor(isolate, map0).Insert(name1, map1, PROPERTY_TRANSITION);
CHECK_EQ(*map1, TransitionsAccessor(isolate, map0)
.SearchTransition(*name1, kind, attributes));
{
TestTransitionsAccessor transitions(isolate, map0);
CHECK(transitions.IsFullTransitionArrayEncoding());
}
thread->Join();
}
} // anonymous namespace
} // namespace internal
......
......@@ -19,6 +19,7 @@ class TestTransitionsAccessor : public TransitionsAccessor {
: TransitionsAccessor(isolate, map) {}
// Expose internals for tests.
bool IsUninitializedEncoding() { return encoding() == kUninitialized; }
bool IsWeakRefEncoding() { return encoding() == kWeakRef; }
bool IsFullTransitionArrayEncoding() {
......
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