Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
deps: V8: backport 1e4b71d99fea
Original commit message:

    [heap] Move the Stack object from ThreadLocalTop to Isolate

    Stack information is thread-specific and, until now, it was stored in a
    field in ThreadLocalTop. This CL moves stack information to the isolate
    and makes sure to update the stack start whenever a main thread enters
    the isolate. At the same time, the Stack object is refactored and
    simplified.

    As a side effect, after removing the Stack object, ThreadLocalTop
    satisfies the std::standard_layout trait; this fixes some issues
    observed with different C++ compilers.

    Bug: v8:13630
    Bug: v8:13257
    Change-Id: I026a35af3bc6999a09b21f277756d4454c086343
    Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4152476
    Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
    Reviewed-by: Omer Katz <omerkatz@chromium.org>
    Commit-Queue: Nikolaos Papaspyrou <nikolaos@chromium.org>
    Cr-Commit-Position: refs/heads/main@{#85445}

Refs: v8/v8@1e4b71d
Refs: https://chromium-review.googlesource.com/c/v8/v8/+/4200636
Co-Authored-By: Nikolaos Papaspyrou <nikolaos@chromium.org>
  • Loading branch information
targos and nickie committed Jan 30, 2023
commit ebea4f10914194a5ef478fc9dde734ee20753565
2 changes: 1 addition & 1 deletion common.gypi
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@

# Reset this number to 0 on major V8 upgrades.
# Increment by one for each non-official patch applied to deps/v8.
'v8_embedder_string': '-node.3',
'v8_embedder_string': '-node.4',

##### V8 defaults for Node.js #####

Expand Down
36 changes: 17 additions & 19 deletions deps/v8/src/execution/isolate.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3074,22 +3074,23 @@ void Isolate::AddSharedWasmMemory(Handle<WasmMemoryObject> memory_object) {
void Isolate::RecordStackSwitchForScanning() {
Object current = root(RootIndex::kActiveContinuation);
DCHECK(!current.IsUndefined());
thread_local_top()->stack_.ClearStackSegments();
wasm::StackMemory* stack = Managed<wasm::StackMemory>::cast(
WasmContinuationObject::cast(current).stack())
.get()
.get();
stack().ClearStackSegments();
wasm::StackMemory* wasm_stack =
Managed<wasm::StackMemory>::cast(
WasmContinuationObject::cast(current).stack())
.get()
.get();
current = WasmContinuationObject::cast(current).parent();
thread_local_top()->stack_.SetStackStart(
reinterpret_cast<void*>(stack->base()));
heap()->SetStackStart(reinterpret_cast<void*>(wasm_stack->base()));
// We don't need to add all inactive stacks. Only the ones in the active chain
// may contain cpp heap pointers.
while (!current.IsUndefined()) {
auto cont = WasmContinuationObject::cast(current);
auto* stack = Managed<wasm::StackMemory>::cast(cont.stack()).get().get();
thread_local_top()->stack_.AddStackSegment(
reinterpret_cast<const void*>(stack->base()),
reinterpret_cast<const void*>(stack->jmpbuf()->sp));
auto* wasm_stack =
Managed<wasm::StackMemory>::cast(cont.stack()).get().get();
stack().AddStackSegment(
reinterpret_cast<const void*>(wasm_stack->base()),
reinterpret_cast<const void*>(wasm_stack->jmpbuf()->sp));
current = cont.parent();
}
}
Expand Down Expand Up @@ -3377,20 +3378,13 @@ void Isolate::Delete(Isolate* isolate) {
Isolate* saved_isolate = isolate->TryGetCurrent();
SetIsolateThreadLocals(isolate, nullptr);
isolate->set_thread_id(ThreadId::Current());
isolate->thread_local_top()->stack_ =
saved_isolate ? std::move(saved_isolate->thread_local_top()->stack_)
: ::heap::base::Stack(base::Stack::GetStackStart());
isolate->heap()->SetStackStart(base::Stack::GetStackStart());

bool owns_shared_isolate = isolate->owns_shared_isolate_;
Isolate* maybe_shared_isolate = isolate->shared_isolate_;

isolate->Deinit();

// Restore the saved isolate's stack.
if (saved_isolate)
saved_isolate->thread_local_top()->stack_ =
std::move(isolate->thread_local_top()->stack_);

#ifdef DEBUG
non_disposed_isolates_--;
#endif // DEBUG
Expand Down Expand Up @@ -4647,6 +4641,10 @@ bool Isolate::Init(SnapshotData* startup_snapshot_data,
void Isolate::Enter() {
Isolate* current_isolate = nullptr;
PerIsolateThreadData* current_data = CurrentPerIsolateThreadData();

// Set the stack start for the main thread that enters the isolate.
heap()->SetStackStart(base::Stack::GetStackStart());

if (current_data != nullptr) {
current_isolate = current_data->isolate_;
DCHECK_NOT_NULL(current_isolate);
Expand Down
6 changes: 6 additions & 0 deletions deps/v8/src/execution/isolate.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include "src/execution/stack-guard.h"
#include "src/handles/handles.h"
#include "src/handles/traced-handles.h"
#include "src/heap/base/stack.h"
#include "src/heap/factory.h"
#include "src/heap/heap.h"
#include "src/heap/read-only-heap.h"
Expand Down Expand Up @@ -2022,6 +2023,8 @@ class V8_EXPORT_PRIVATE Isolate final : private HiddenFactory {
SimulatorData* simulator_data() { return simulator_data_; }
#endif

::heap::base::Stack& stack() { return stack_; }

#ifdef V8_ENABLE_WEBASSEMBLY
wasm::StackMemory*& wasm_stacks() { return wasm_stacks_; }
// Update the thread local's Stack object so that it is aware of the new stack
Expand Down Expand Up @@ -2520,6 +2523,9 @@ class V8_EXPORT_PRIVATE Isolate final : private HiddenFactory {
// The mutex only guards adding pages, the retrieval is signal safe.
base::Mutex code_pages_mutex_;

// Stack information for the main thread.
::heap::base::Stack stack_;

#ifdef V8_ENABLE_WEBASSEMBLY
wasm::StackMemory* wasm_stacks_;
#endif
Expand Down
2 changes: 0 additions & 2 deletions deps/v8/src/execution/thread-local-top.cc
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,12 @@ void ThreadLocalTop::Clear() {
current_embedder_state_ = nullptr;
failed_access_check_callback_ = nullptr;
thread_in_wasm_flag_address_ = kNullAddress;
stack_ = ::heap::base::Stack();
}

void ThreadLocalTop::Initialize(Isolate* isolate) {
Clear();
isolate_ = isolate;
thread_id_ = ThreadId::Current();
stack_.SetStackStart(base::Stack::GetStackStart());
#if V8_ENABLE_WEBASSEMBLY
thread_in_wasm_flag_address_ = reinterpret_cast<Address>(
trap_handler::GetThreadInWasmThreadLocalAddress());
Expand Down
6 changes: 1 addition & 5 deletions deps/v8/src/execution/thread-local-top.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
#include "include/v8-unwinder.h"
#include "src/common/globals.h"
#include "src/execution/thread-id.h"
#include "src/heap/base/stack.h"
#include "src/objects/contexts.h"
#include "src/utils/utils.h"

Expand All @@ -30,7 +29,7 @@ class ThreadLocalTop {
// TODO(all): This is not particularly beautiful. We should probably
// refactor this to really consist of just Addresses and 32-bit
// integer fields.
static constexpr uint32_t kSizeInBytes = 30 * kSystemPointerSize;
static constexpr uint32_t kSizeInBytes = 25 * kSystemPointerSize;

// Does early low-level initialization that does not depend on the
// isolate being present.
Expand Down Expand Up @@ -147,9 +146,6 @@ class ThreadLocalTop {

// Address of the thread-local "thread in wasm" flag.
Address thread_in_wasm_flag_address_;

// Stack information.
::heap::base::Stack stack_;
};

} // namespace internal
Expand Down
4 changes: 1 addition & 3 deletions deps/v8/src/heap/heap.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5851,9 +5851,7 @@ void Heap::SetStackStart(void* stack_start) {
stack().SetStackStart(stack_start);
}

::heap::base::Stack& Heap::stack() {
return isolate_->thread_local_top()->stack_;
}
::heap::base::Stack& Heap::stack() { return isolate_->stack(); }

void Heap::RegisterExternallyReferencedObject(Address* location) {
Object object = TracedHandles::Mark(location, TracedHandles::MarkMode::kAll);
Expand Down
28 changes: 21 additions & 7 deletions deps/v8/test/cctest/test-api.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13043,12 +13043,13 @@ bool ApiTestFuzzer::NextThread() {


void ApiTestFuzzer::Run() {
// When it is our turn...
// Wait until it is our turn.
gate_.Wait();
{
// ... get the V8 lock
// Get the V8 lock.
v8::Locker locker(CcTest::isolate());
// ... and start running the test.
// Start running the test, which will enter the isolate and exit it when it
// finishes.
CallTest();
}
// This test finished.
Expand Down Expand Up @@ -13089,11 +13090,18 @@ static void CallTestNumber(int test_number) {


void ApiTestFuzzer::RunAllTests() {
// This method is called when running each THREADING_TEST, which is an
// initialized test and has entered the isolate at this point. We need to exit
// the isolate, so that the fuzzer threads can enter it in turn, while running
// their tests.
CcTest::isolate()->Exit();
// Set off the first test.
current_ = -1;
NextThread();
// Wait till they are all done.
all_tests_done_.Wait();
// We enter the isolate again, to prepare for teardown.
CcTest::isolate()->Enter();
}


Expand All @@ -13111,10 +13119,16 @@ int ApiTestFuzzer::GetNextTestNumber() {
void ApiTestFuzzer::ContextSwitch() {
// If the new thread is the same as the current thread there is nothing to do.
if (NextThread()) {
// Now it can start.
v8::Unlocker unlocker(CcTest::isolate());
// Wait till someone starts us again.
gate_.Wait();
// Exit the isolate from this thread.
CcTest::i_isolate()->Exit();
{
// Now the new thread can start.
v8::Unlocker unlocker(CcTest::isolate());
// Wait till someone starts us again.
gate_.Wait();
}
// Enter the isolate from this thread again.
CcTest::i_isolate()->Enter();
// And we're off.
}
}
Expand Down
10 changes: 8 additions & 2 deletions deps/v8/test/cctest/test-cpu-profiler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3448,8 +3448,12 @@ TEST(MultipleThreadsSingleIsolate) {
env, "YieldIsolate", [](const v8::FunctionCallbackInfo<v8::Value>& info) {
v8::Isolate* isolate = info.GetIsolate();
if (!info[0]->IsTrue()) return;
v8::Unlocker unlocker(isolate);
v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(1));
isolate->Exit();
{
v8::Unlocker unlocker(isolate);
v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(1));
}
isolate->Enter();
});

CompileRun(varying_frame_size_script);
Expand All @@ -3461,11 +3465,13 @@ TEST(MultipleThreadsSingleIsolate) {

// For good measure, profile on our own thread
UnlockingThread::Profile(env, 0);
isolate->Exit();
{
v8::Unlocker unlocker(isolate);
thread1.Join();
thread2.Join();
}
isolate->Enter();
}

// Tests that StopProfiling doesn't wait for the next sample tick in order to
Expand Down
6 changes: 6 additions & 0 deletions deps/v8/test/cctest/test-debug.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4204,6 +4204,12 @@ class ArchiveRestoreThread : public v8::base::Thread,
// child.GetBreakCount() will return 1 if the debugger fails to stop
// on the `next()` line after the grandchild thread returns.
CHECK_EQ(child.GetBreakCount(), 5);

// This test on purpose unlocks the isolate without exiting and
// re-entering. It must however update the stack start, which would have
// been done automatically if the isolate was properly re-entered.
reinterpret_cast<i::Isolate*>(isolate_)->heap()->SetStackStart(
v8::base::Stack::GetStackStart());
}
}

Expand Down
2 changes: 2 additions & 0 deletions deps/v8/test/cctest/test-lockers.cc
Original file line number Diff line number Diff line change
Expand Up @@ -871,7 +871,9 @@ TEST(LockUnlockLockDefaultIsolateMultithreaded) {
threads.push_back(new LockUnlockLockDefaultIsolateThread(context));
}
}
CcTest::isolate()->Exit();
StartJoinAndDeleteThreads(threads);
CcTest::isolate()->Enter();
}


Expand Down