// 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 "src/handles/persistent-handles.h" #include "test/unittests/test-utils.h" #include "testing/gtest/include/gtest/gtest.h" namespace v8 { namespace internal { using PersistentHandlesTest = TestWithIsolate; TEST_F(PersistentHandlesTest, OrderOfBlocks) { Isolate* isolate = i_isolate(); Heap* heap = isolate->heap(); HandleScope scope(isolate); handle(ReadOnlyRoots(heap).empty_string(), isolate); HandleScopeData* data = isolate->handle_scope_data(); Address* next; Address* limit; Handle first_empty, last_empty; std::unique_ptr ph; { PersistentHandlesScope persistent_scope(isolate); // fill block first_empty = handle(ReadOnlyRoots(heap).empty_string(), isolate); while (data->next < data->limit) { handle(ReadOnlyRoots(heap).empty_string(), isolate); } // add second block and two more handles on it handle(ReadOnlyRoots(heap).empty_string(), isolate); last_empty = handle(ReadOnlyRoots(heap).empty_string(), isolate); // remember next and limit in second block next = data->next; limit = data->limit; ph = persistent_scope.Detach(); } CHECK_EQ(ph->block_next_, next); CHECK_EQ(ph->block_limit_, limit); CHECK_EQ(first_empty->length(), 0); CHECK_EQ(last_empty->length(), 0); CHECK_EQ(*first_empty, *last_empty); } namespace { class CounterDummyVisitor : public RootVisitor { public: void VisitRootPointers(Root root, const char* description, FullObjectSlot start, FullObjectSlot end) override { counter += end - start; } size_t counter = 0; }; size_t count_handles(Isolate* isolate) { CounterDummyVisitor visitor; isolate->handle_scope_implementer()->Iterate(&visitor); return visitor.counter; } size_t count_handles(PersistentHandles* ph) { CounterDummyVisitor visitor; ph->Iterate(&visitor); return visitor.counter; } } // namespace TEST_F(PersistentHandlesTest, Iterate) { Isolate* isolate = i_isolate(); Heap* heap = isolate->heap(); v8::HandleScope scope(reinterpret_cast(isolate)); HandleScopeData* data = isolate->handle_scope_data(); size_t handles_in_empty_scope = count_handles(isolate); Handle init(ReadOnlyRoots(heap).empty_string(), isolate); Address* old_limit = data->limit; CHECK_EQ(count_handles(isolate), handles_in_empty_scope + 1); std::unique_ptr ph; Handle verify_handle; { PersistentHandlesScope persistent_scope(isolate); verify_handle = handle(ReadOnlyRoots(heap).empty_string(), isolate); CHECK_NE(old_limit, data->limit); CHECK_EQ(count_handles(isolate), handles_in_empty_scope + 2); ph = persistent_scope.Detach(); } #if DEBUG CHECK(ph->Contains(verify_handle.location())); #else USE(verify_handle); #endif ph->NewHandle(ReadOnlyRoots(heap).empty_string()); CHECK_EQ(count_handles(ph.get()), 2); CHECK_EQ(count_handles(isolate), handles_in_empty_scope + 1); } } // namespace internal } // namespace v8