| // 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 "test/unittests/heap/unified-heap-utils.h" |
| |
| #include "include/cppgc/platform.h" |
| #include "src/api/api-inl.h" |
| #include "src/heap/cppgc-js/cpp-heap.h" |
| #include "src/objects/objects-inl.h" |
| |
| namespace v8 { |
| namespace internal { |
| |
| UnifiedHeapTest::UnifiedHeapTest() |
| : saved_incremental_marking_wrappers_(FLAG_incremental_marking_wrappers) { |
| FLAG_incremental_marking_wrappers = false; |
| cppgc::InitializeProcess(V8::GetCurrentPlatform()->GetPageAllocator()); |
| cpp_heap_ = std::make_unique<CppHeap>( |
| v8_isolate(), std::vector<std::unique_ptr<cppgc::CustomSpaceBase>>()); |
| heap()->SetEmbedderHeapTracer(&cpp_heap()); |
| } |
| |
| UnifiedHeapTest::~UnifiedHeapTest() { |
| heap()->SetEmbedderHeapTracer(nullptr); |
| FLAG_incremental_marking_wrappers = saved_incremental_marking_wrappers_; |
| cppgc::ShutdownProcess(); |
| } |
| |
| void UnifiedHeapTest::CollectGarbageWithEmbedderStack() { |
| heap()->SetEmbedderStackStateForNextFinalization( |
| EmbedderHeapTracer::EmbedderStackState::kMayContainHeapPointers); |
| CollectGarbage(OLD_SPACE); |
| } |
| |
| void UnifiedHeapTest::CollectGarbageWithoutEmbedderStack() { |
| heap()->SetEmbedderStackStateForNextFinalization( |
| EmbedderHeapTracer::EmbedderStackState::kNoHeapPointers); |
| CollectGarbage(OLD_SPACE); |
| } |
| |
| CppHeap& UnifiedHeapTest::cpp_heap() const { return *cpp_heap_.get(); } |
| |
| cppgc::AllocationHandle& UnifiedHeapTest::allocation_handle() { |
| return cpp_heap().object_allocator(); |
| } |
| |
| // static |
| v8::Local<v8::Object> WrapperHelper::CreateWrapper( |
| v8::Local<v8::Context> context, void* wrappable_object, |
| const char* class_name) { |
| v8::EscapableHandleScope scope(context->GetIsolate()); |
| v8::Local<v8::FunctionTemplate> function_t = |
| v8::FunctionTemplate::New(context->GetIsolate()); |
| if (strlen(class_name) != 0) { |
| function_t->SetClassName( |
| v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), class_name) |
| .ToLocalChecked()); |
| } |
| v8::Local<v8::ObjectTemplate> instance_t = function_t->InstanceTemplate(); |
| instance_t->SetInternalFieldCount(2); |
| v8::Local<v8::Function> function = |
| function_t->GetFunction(context).ToLocalChecked(); |
| v8::Local<v8::Object> instance = |
| function->NewInstance(context).ToLocalChecked(); |
| instance->SetAlignedPointerInInternalField(0, wrappable_object); |
| instance->SetAlignedPointerInInternalField(1, wrappable_object); |
| CHECK(!instance.IsEmpty()); |
| i::Handle<i::JSReceiver> js_obj = v8::Utils::OpenHandle(*instance); |
| CHECK_EQ(i::JS_API_OBJECT_TYPE, js_obj->map().instance_type()); |
| return scope.Escape(instance); |
| } |
| |
| // static |
| void WrapperHelper::ResetWrappableConnection(v8::Local<v8::Object> api_object) { |
| api_object->SetAlignedPointerInInternalField(0, nullptr); |
| api_object->SetAlignedPointerInInternalField(1, nullptr); |
| } |
| |
| } // namespace internal |
| } // namespace v8 |