node/deps/v8/test/unittests/api/gc-callbacks-unittest.cc
Michaël Zasso 6bd756d7c6
deps: update V8 to 10.7.193.13
PR-URL: https://github.com/nodejs/node/pull/44741
Fixes: https://github.com/nodejs/node/issues/44650
Fixes: https://github.com/nodejs/node/issues/37472
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: Jiawen Geng <technicalcute@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
2022-10-11 07:24:33 +02:00

168 lines
5.9 KiB
C++

// Copyright 2017 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/heap/heap-utils.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace v8 {
namespace {
namespace {
class GCCallbacksTest : public internal::TestWithHeapInternalsAndContext {
public:
static void PrologueCallbackAlloc(v8::Isolate* isolate, v8::GCType,
v8::GCCallbackFlags flags) {
v8::HandleScope scope(isolate);
CHECK_EQ(flags, v8::kNoGCCallbackFlags);
CHECK_EQ(current_test_->gc_callbacks_isolate_, isolate);
++current_test_->prologue_call_count_alloc_;
if (!v8::internal::FLAG_single_generation) {
// Simulate full heap to see if we will reenter this callback
current_test_->SimulateFullSpace(current_test_->heap()->new_space());
}
Local<Object> obj = Object::New(isolate);
CHECK(!obj.IsEmpty());
current_test_->PreciseCollectAllGarbage();
}
static void EpilogueCallbackAlloc(v8::Isolate* isolate, v8::GCType,
v8::GCCallbackFlags flags) {
v8::HandleScope scope(isolate);
CHECK_EQ(flags, v8::kNoGCCallbackFlags);
CHECK_EQ(current_test_->gc_callbacks_isolate_, isolate);
++current_test_->epilogue_call_count_alloc_;
if (!v8::internal::FLAG_single_generation) {
// Simulate full heap to see if we will reenter this callback
current_test_->SimulateFullSpace(current_test_->heap()->new_space());
}
Local<Object> obj = Object::New(isolate);
CHECK(!obj.IsEmpty());
current_test_->PreciseCollectAllGarbage();
}
static void PrologueCallback(v8::Isolate* isolate, v8::GCType,
v8::GCCallbackFlags flags) {
CHECK_EQ(flags, v8::kNoGCCallbackFlags);
CHECK_EQ(current_test_->gc_callbacks_isolate_, isolate);
++current_test_->prologue_call_count_;
}
static void EpilogueCallback(v8::Isolate* isolate, v8::GCType,
v8::GCCallbackFlags flags) {
CHECK_EQ(flags, v8::kNoGCCallbackFlags);
CHECK_EQ(current_test_->gc_callbacks_isolate_, isolate);
++current_test_->epilogue_call_count_;
}
static void PrologueCallbackSecond(v8::Isolate* isolate, v8::GCType,
v8::GCCallbackFlags flags) {
CHECK_EQ(flags, v8::kNoGCCallbackFlags);
CHECK_EQ(current_test_->gc_callbacks_isolate_, isolate);
++current_test_->prologue_call_count_second_;
}
static void EpilogueCallbackSecond(v8::Isolate* isolate, v8::GCType,
v8::GCCallbackFlags flags) {
CHECK_EQ(flags, v8::kNoGCCallbackFlags);
CHECK_EQ(current_test_->gc_callbacks_isolate_, isolate);
++current_test_->epilogue_call_count_second_;
}
static void PrologueCallbackNew(v8::Isolate* isolate, v8::GCType,
v8::GCCallbackFlags flags, void* data) {
CHECK_EQ(flags, v8::kNoGCCallbackFlags);
CHECK_EQ(current_test_->gc_callbacks_isolate_, isolate);
++*static_cast<int*>(data);
}
static void EpilogueCallbackNew(v8::Isolate* isolate, v8::GCType,
v8::GCCallbackFlags flags, void* data) {
CHECK_EQ(flags, v8::kNoGCCallbackFlags);
CHECK_EQ(current_test_->gc_callbacks_isolate_, isolate);
++*static_cast<int*>(data);
}
protected:
void SetUp() override {
internal::TestWithHeapInternalsAndContext::SetUp();
DCHECK_NULL(current_test_);
current_test_ = this;
}
void TearDown() override {
DCHECK_NOT_NULL(current_test_);
current_test_ = nullptr;
internal::TestWithHeapInternalsAndContext::TearDown();
}
static GCCallbacksTest* current_test_;
v8::Isolate* gc_callbacks_isolate_ = nullptr;
int prologue_call_count_ = 0;
int epilogue_call_count_ = 0;
int prologue_call_count_second_ = 0;
int epilogue_call_count_second_ = 0;
int prologue_call_count_alloc_ = 0;
int epilogue_call_count_alloc_ = 0;
};
GCCallbacksTest* GCCallbacksTest::current_test_ = nullptr;
} // namespace
TEST_F(GCCallbacksTest, GCCallbacks) {
// For SimulateFullSpace in PrologueCallbackAlloc and EpilogueCallbackAlloc.
i::FLAG_stress_concurrent_allocation = false;
v8::Isolate* isolate = context()->GetIsolate();
gc_callbacks_isolate_ = isolate;
isolate->AddGCPrologueCallback(PrologueCallback);
isolate->AddGCEpilogueCallback(EpilogueCallback);
CHECK_EQ(0, prologue_call_count_);
CHECK_EQ(0, epilogue_call_count_);
CollectAllGarbage();
CHECK_EQ(1, prologue_call_count_);
CHECK_EQ(1, epilogue_call_count_);
isolate->AddGCPrologueCallback(PrologueCallbackSecond);
isolate->AddGCEpilogueCallback(EpilogueCallbackSecond);
CollectAllGarbage();
CHECK_EQ(2, prologue_call_count_);
CHECK_EQ(2, epilogue_call_count_);
CHECK_EQ(1, prologue_call_count_second_);
CHECK_EQ(1, epilogue_call_count_second_);
isolate->RemoveGCPrologueCallback(PrologueCallback);
isolate->RemoveGCEpilogueCallback(EpilogueCallback);
CollectAllGarbage();
CHECK_EQ(2, prologue_call_count_);
CHECK_EQ(2, epilogue_call_count_);
CHECK_EQ(2, prologue_call_count_second_);
CHECK_EQ(2, epilogue_call_count_second_);
isolate->RemoveGCPrologueCallback(PrologueCallbackSecond);
isolate->RemoveGCEpilogueCallback(EpilogueCallbackSecond);
CollectAllGarbage();
CHECK_EQ(2, prologue_call_count_);
CHECK_EQ(2, epilogue_call_count_);
CHECK_EQ(2, prologue_call_count_second_);
CHECK_EQ(2, epilogue_call_count_second_);
CHECK_EQ(0, prologue_call_count_alloc_);
CHECK_EQ(0, epilogue_call_count_alloc_);
isolate->AddGCPrologueCallback(PrologueCallbackAlloc);
isolate->AddGCEpilogueCallback(EpilogueCallbackAlloc);
PreciseCollectAllGarbage();
CHECK_EQ(1, prologue_call_count_alloc_);
CHECK_EQ(1, epilogue_call_count_alloc_);
isolate->RemoveGCPrologueCallback(PrologueCallbackAlloc);
isolate->RemoveGCEpilogueCallback(EpilogueCallbackAlloc);
}
} // namespace
} // namespace v8