| // 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. |
| |
| #ifndef V8_HANDLES_PERSISTENT_HANDLES_H_ |
| #define V8_HANDLES_PERSISTENT_HANDLES_H_ |
| |
| #include <vector> |
| |
| #include "include/v8-internal.h" |
| #include "src/api/api.h" |
| #include "src/base/macros.h" |
| #include "src/objects/visitors.h" |
| #include "testing/gtest/include/gtest/gtest_prod.h" // nogncheck |
| |
| namespace v8 { |
| namespace internal { |
| |
| class Heap; |
| |
| // PersistentHandles serves as a container for handles that can be passed back |
| // and forth between threads. Allocation and deallocation of this class is |
| // thread-safe and the isolate tracks all PersistentHandles containers. |
| class PersistentHandles { |
| public: |
| V8_EXPORT_PRIVATE explicit PersistentHandles(Isolate* isolate); |
| V8_EXPORT_PRIVATE ~PersistentHandles(); |
| |
| PersistentHandles(const PersistentHandles&) = delete; |
| PersistentHandles& operator=(const PersistentHandles&) = delete; |
| |
| V8_EXPORT_PRIVATE void Iterate(RootVisitor* visitor); |
| |
| template <typename T> |
| Handle<T> NewHandle(T obj) { |
| #ifdef DEBUG |
| CheckOwnerIsNotParked(); |
| #endif |
| return Handle<T>(GetHandle(obj.ptr())); |
| } |
| |
| template <typename T> |
| Handle<T> NewHandle(Handle<T> obj) { |
| return NewHandle(*obj); |
| } |
| |
| #ifdef DEBUG |
| V8_EXPORT_PRIVATE bool Contains(Address* location); |
| #endif |
| |
| private: |
| void AddBlock(); |
| V8_EXPORT_PRIVATE Address* GetHandle(Address value); |
| |
| #ifdef DEBUG |
| void Attach(LocalHeap* local_heap); |
| void Detach(); |
| V8_EXPORT_PRIVATE void CheckOwnerIsNotParked(); |
| |
| LocalHeap* owner_ = nullptr; |
| |
| #else |
| void Attach(LocalHeap*) {} |
| void Detach() {} |
| #endif |
| |
| Isolate* isolate_; |
| std::vector<Address*> blocks_; |
| |
| Address* block_next_; |
| Address* block_limit_; |
| |
| PersistentHandles* prev_; |
| PersistentHandles* next_; |
| |
| #ifdef DEBUG |
| std::set<Address*> ordered_blocks_; |
| #endif |
| |
| friend class HandleScopeImplementer; |
| friend class LocalHeap; |
| friend class PersistentHandlesList; |
| |
| FRIEND_TEST(PersistentHandlesTest, OrderOfBlocks); |
| }; |
| |
| class PersistentHandlesList { |
| public: |
| PersistentHandlesList() : persistent_handles_head_(nullptr) {} |
| |
| void Iterate(RootVisitor* visitor, Isolate* isolate); |
| |
| private: |
| void Add(PersistentHandles* persistent_handles); |
| void Remove(PersistentHandles* persistent_handles); |
| |
| base::Mutex persistent_handles_mutex_; |
| PersistentHandles* persistent_handles_head_; |
| |
| friend class PersistentHandles; |
| }; |
| |
| // PersistentHandlesScope sets up a scope in which all created main thread |
| // handles become persistent handles that can be sent to another thread. |
| class PersistentHandlesScope { |
| public: |
| V8_EXPORT_PRIVATE explicit PersistentHandlesScope(Isolate* isolate); |
| V8_EXPORT_PRIVATE ~PersistentHandlesScope(); |
| |
| // Moves all blocks of this scope into PersistentHandles and returns it. |
| V8_EXPORT_PRIVATE std::unique_ptr<PersistentHandles> Detach(); |
| |
| private: |
| Address* prev_limit_; |
| Address* prev_next_; |
| HandleScopeImplementer* const impl_; |
| |
| #ifdef DEBUG |
| bool handles_detached_ = false; |
| int prev_level_; |
| #endif |
| }; |
| |
| } // namespace internal |
| } // namespace v8 |
| |
| #endif // V8_HANDLES_PERSISTENT_HANDLES_H_ |