blob: b1c18649d805386c887477242b53815a95d83311 [file] [log] [blame]
// 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_