b9eeaf1b88
Reland of https://crrev.com/c/3998633. Each thread has its own MarkingBarrier instance for incremental marking. A thread local variable is used to get the current thread's instance on background threads. However on main threads this thread local variable was always set to nullptr. The main thread would get to its own instance through the heap_ field in the host object's page header. This was solved this way because setting current_marking_barrier on the main thread seemed quite complex. Multiple isolates may be run on the same thread and isolates may even be migrated between threads. However, with --shared-space loading the heap_ field for a shared object would return the main isolate's heap and we end up with the wrong MarkingBarrier instance on client isolates. So this CL makes main and background threads more uniform by setting the thread local field also on the main thread. The field is set by the already existing v8::Isolate::Scope API. Some embedders might have to add these scopes if they don't use them properly already. Bug: v8:13267 Change-Id: Idc257ecf6b6af09a379bdd7cd7c1d4a5e46689c9 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4016715 Reviewed-by: Michael Lippautz <mlippautz@chromium.org> Commit-Queue: Dominik Inführ <dinfuehr@chromium.org> Reviewed-by: Jakob Kummerow <jkummerow@chromium.org> Cr-Commit-Position: refs/heads/main@{#84237}
114 lines
3.9 KiB
C++
114 lines
3.9 KiB
C++
// Copyright 2014 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 "test/unittests/test-utils.h"
|
|
|
|
#include "include/libplatform/libplatform.h"
|
|
#include "include/v8-isolate.h"
|
|
#include "src/api/api-inl.h"
|
|
#include "src/base/platform/time.h"
|
|
#include "src/execution/isolate.h"
|
|
#include "src/flags/flags.h"
|
|
#include "src/init/v8.h"
|
|
#include "src/objects/objects-inl.h"
|
|
|
|
namespace v8 {
|
|
|
|
namespace {
|
|
// counter_lookup_callback doesn't pass through any state information about
|
|
// the current Isolate, so we have to store the current counter map somewhere.
|
|
// Fortunately tests run serially, so we can just store it in a static global.
|
|
CounterMap* kCurrentCounterMap = nullptr;
|
|
} // namespace
|
|
|
|
IsolateWrapper::IsolateWrapper(CountersMode counters_mode)
|
|
: array_buffer_allocator_(
|
|
v8::ArrayBuffer::Allocator::NewDefaultAllocator()) {
|
|
CHECK_NULL(kCurrentCounterMap);
|
|
|
|
v8::Isolate::CreateParams create_params;
|
|
create_params.array_buffer_allocator = array_buffer_allocator_.get();
|
|
|
|
if (counters_mode == kEnableCounters) {
|
|
counter_map_ = std::make_unique<CounterMap>();
|
|
kCurrentCounterMap = counter_map_.get();
|
|
|
|
create_params.counter_lookup_callback = [](const char* name) {
|
|
CHECK_NOT_NULL(kCurrentCounterMap);
|
|
// If the name doesn't exist in the counter map, operator[] will default
|
|
// initialize it to zero.
|
|
return &(*kCurrentCounterMap)[name];
|
|
};
|
|
} else {
|
|
create_params.counter_lookup_callback = [](const char* name) -> int* {
|
|
return nullptr;
|
|
};
|
|
}
|
|
|
|
isolate_ = v8::Isolate::New(create_params);
|
|
CHECK_NOT_NULL(isolate());
|
|
}
|
|
|
|
IsolateWrapper::~IsolateWrapper() {
|
|
v8::Platform* platform = internal::V8::GetCurrentPlatform();
|
|
CHECK_NOT_NULL(platform);
|
|
isolate_->Enter();
|
|
while (platform::PumpMessageLoop(platform, isolate())) continue;
|
|
isolate_->Exit();
|
|
isolate_->Dispose();
|
|
if (counter_map_) {
|
|
CHECK_EQ(kCurrentCounterMap, counter_map_.get());
|
|
kCurrentCounterMap = nullptr;
|
|
} else {
|
|
CHECK_NULL(kCurrentCounterMap);
|
|
}
|
|
}
|
|
|
|
namespace internal {
|
|
|
|
SaveFlags::SaveFlags() {
|
|
// For each flag, save the current flag value.
|
|
#define FLAG_MODE_APPLY(ftype, ctype, nam, def, cmt) \
|
|
SAVED_##nam = v8_flags.nam.value();
|
|
#include "src/flags/flag-definitions.h"
|
|
#undef FLAG_MODE_APPLY
|
|
}
|
|
|
|
SaveFlags::~SaveFlags() {
|
|
// For each flag, set back the old flag value if it changed (don't write the
|
|
// flag if it didn't change, to keep TSAN happy).
|
|
#define FLAG_MODE_APPLY(ftype, ctype, nam, def, cmt) \
|
|
if (SAVED_##nam != v8_flags.nam.value()) { \
|
|
v8_flags.nam = SAVED_##nam; \
|
|
}
|
|
#include "src/flags/flag-definitions.h" // NOLINT
|
|
#undef FLAG_MODE_APPLY
|
|
}
|
|
|
|
ManualGCScope::ManualGCScope(i::Isolate* isolate) {
|
|
// Some tests run threaded (back-to-back) and thus the GC may already be
|
|
// running by the time a ManualGCScope is created. Finalizing existing marking
|
|
// prevents any undefined/unexpected behavior.
|
|
if (isolate && isolate->heap()->incremental_marking()->IsMarking()) {
|
|
ScanStackModeScopeForTesting no_stack_scanning(isolate->heap(),
|
|
Heap::ScanStackMode::kNone);
|
|
isolate->heap()->CollectGarbage(OLD_SPACE,
|
|
GarbageCollectionReason::kTesting);
|
|
// Make sure there is no concurrent sweeping running in the background.
|
|
isolate->heap()->CompleteSweepingFull();
|
|
}
|
|
|
|
i::v8_flags.concurrent_marking = false;
|
|
i::v8_flags.concurrent_sweeping = false;
|
|
i::v8_flags.concurrent_minor_mc_marking = false;
|
|
i::v8_flags.stress_incremental_marking = false;
|
|
i::v8_flags.stress_concurrent_allocation = false;
|
|
// Parallel marking has a dependency on concurrent marking.
|
|
i::v8_flags.parallel_marking = false;
|
|
i::v8_flags.detect_ineffective_gcs_near_heap_limit = false;
|
|
}
|
|
|
|
} // namespace internal
|
|
} // namespace v8
|