GlobalHandles是实现v8中持久句柄功能的类。GlobalHandles主要是维护一个链表,每个节点维护堆对象的状态。我们先看看节点的定义。
class GlobalHandles::Node : public Malloced {
public:
void Initialize(Object* object) {
// 指向堆对象地址
object_ = object;
state_ = NORMAL;
parameter_or_next_free_.parameter = NULL;
callback_ = NULL;
}
explicit Node(Object* object) {
Initialize(object);
next_ = NULL;
}
~Node() {
if (state_ != DESTROYED) Destroy();
}
void Destroy() {
if (state_ == WEAK || IsNearDeath()) {
GlobalHandles::number_of_weak_handles_--;
if (object_->IsJSGlobalObject()) {
GlobalHandles::number_of_global_object_weak_handles_--;
}
}
state_ = DESTROYED;
}
Node* next() { return next_; }
void set_next(Node* value) { next_ = value; }
// 指针的地址
Node** next_addr() { return &next_; }
// 用于销毁状态的时候,在空闲链表的操作
Node* next_free() {
ASSERT(state_ == DESTROYED);
return parameter_or_next_free_.next_free;
}
void set_next_free(Node* value) {
ASSERT(state_ == DESTROYED);
parameter_or_next_free_.next_free = value;
}
// location指向Node对象的object_属性的地址
static Node* FromLocation(Object** location) {
// object_属性在Node对象的首地址
ASSERT(OFFSET_OF(Node, object_) == 0);
// 直接转成Node指针,因为object_就是Node对象的首地址
return reinterpret_cast<Node*>(location);
}
// 返回object_属性的地址,即对象的首地址
Handle<Object> handle() { return Handle<Object>(&object_); }
// Make this handle weak.
void MakeWeak(void* parameter, WeakReferenceCallback callback) {
// 更新统计数据
if (state_ != WEAK && !IsNearDeath()) {
GlobalHandles::number_of_weak_handles_++;
if (object_->IsJSGlobalObject()) {
GlobalHandles::number_of_global_object_weak_handles_++;
}
}
// 修改状态和待销毁时执行的回调和参数
state_ = WEAK;
set_parameter(parameter);
callback_ = callback;
}
// 和上面的函数相反
void ClearWeakness() {
if (state_ == WEAK || IsNearDeath()) {
GlobalHandles::number_of_weak_handles_--;
if (object_->IsJSGlobalObject()) {
GlobalHandles::number_of_global_object_weak_handles_--;
}
}
state_ = NORMAL;
set_parameter(NULL);
}
bool IsNearDeath() {
return state_ == PENDING || state_ == NEAR_DEATH;
}
bool IsWeak() {
return state_ == WEAK;
}
// 参数的存取
void set_parameter(void* parameter) {
ASSERT(state_ != DESTROYED);
parameter_or_next_free_.parameter = parameter;
}
void* parameter() {
ASSERT(state_ != DESTROYED);
return parameter_or_next_free_.parameter;
}
WeakReferenceCallback callback() { return callback_; }
// gc相关
void PostGarbageCollectionProcessing() {
if (state_ != Node::PENDING) return;
void* par = parameter();
state_ = NEAR_DEATH;
set_parameter(NULL);
WeakReferenceCallback func = callback();
if (func != NULL) {
func(v8::Persistent<v8::Object>(ToApi<v8::Object>(handle())), par);
}
}
Object* object_; // Storage for object pointer.
// Transition diagram:
// NORMAL <-> WEAK -> PENDING -> NEAR_DEATH -> { NORMAL, WEAK, DESTROYED }
enum State {
NORMAL, // Normal global handle.
WEAK, // Flagged as weak but not yet finalized.
PENDING, // Has been recognized as only reachable by weak handles.
NEAR_DEATH, // Callback has informed the handle is near death.
DESTROYED
};
State state_;
private:
// 待销毁时执行的回调
WeakReferenceCallback callback_;
// next_free是用于销毁状态的node,这时候parameter已经不需要了,不是销毁状态的时候,next_free也不会用到
union {
void* parameter;
Node* next_free;
} parameter_or_next_free_;
Node* next_;
public:
TRACK_MEMORY("GlobalHandles::Node")
};
Node类对象保存了堆对象的地址、销毁前执行的回调和参数。管理堆对象的状态。下面看一下GlobalHandles的定义,我们是通过GlobalHandles使用Node类的。下面的注释解释的比较好,所以保留。
// Structure for tracking global handles.
// A single list keeps all the allocated global handles.
// Destroyed handles stay in the list but is added to the free list.
// At GC the destroyed global handles are removed from the free list
// and deallocated.
// Callback function on handling weak global handles.
// typedef bool (*WeakSlotCallback)(Object** pointer);
// An object group is indexed by an id. An object group is treated like
// a single JS object: if one of object in the group is alive,
// all objects in the same group are considered alive.
// An object group is used to simulate object relationship in a DOM tree.
class ObjectGroup : public Malloced {
public:
explicit ObjectGroup(void* id) : id_(id), objects_(4) {}
void* id_;
List<Object**> objects_;
};
class GlobalHandles : public AllStatic {
public:
// Creates a new global handle that is alive until Destroy is called.
static Handle<Object> Create(Object* value);
// Destroy a global handle.
static void Destroy(Object** location);
// Make the global handle weak and set the callback parameter for the
// handle. When the garbage collector recognizes that only weak global
// handles point to an object the handles are cleared and the callback
// function is invoked (for each handle) with the handle and corresponding
// parameter as arguments. Note: cleared means set to Smi::FromInt(0). The
// reason is that Smi::FromInt(0) does not change during garage collection.
static void MakeWeak(Object** location,void* parameter,WeakReferenceCallback callback);
// Returns the current number of weak handles.
static int NumberOfWeakHandles() { return number_of_weak_handles_; }
// Returns the current number of weak handles to global objects.
// These handles are also included in NumberOfWeakHandles().
static int NumberOfGlobalObjectWeakHandles() {
return number_of_global_object_weak_handles_;
}
// Clear the weakness of a global handle.
static void ClearWeakness(Object** location);
// Tells whether global handle is near death.
static bool IsNearDeath(Object** location);
// Tells whether global handle is weak.
static bool IsWeak(Object** location);
// Process pending weak handles.
static void PostGarbageCollectionProcessing();
// Iterates over all handles.
static void IterateRoots(ObjectVisitor* v);
// Iterates over all weak roots in heap.
static void IterateWeakRoots(ObjectVisitor* v);
// Mark the weak pointers based on the callback.
static void MarkWeakRoots(WeakSlotCallback f);
// Add an object to a group indexed by an id.
// Should only used in GC callback function before a collection.
// All groups are destroyed after a mark-compact collection.
static void AddToGroup(void* id, Object** location);
// Returns the object groups.
static List<ObjectGroup*>& ObjectGroups() {
return object_groups_;
}
// Remove bags, this should only happen after GC.
static void RemoveObjectGroups();
// Tear down the global handle structure.
static void TearDown();
private:
// Internal node structure, one for each global handle.
class Node;
// Field always containing the number of weak and near-death handles.
static int number_of_weak_handles_;
// Field always containing the number of weak and near-death handles
// to global objects. These objects are also included in
// number_of_weak_handles_.
static int number_of_global_object_weak_handles_;
// Global handles are kept in a single linked list pointed to by head_.
static Node* head_;
static Node* head() { return head_; }
static void set_head(Node* value) { head_ = value; }
// Free list for DESTROYED global handles not yet deallocated.
static Node* first_free_;
static Node* first_free() { return first_free_; }
static void set_first_free(Node* value) { first_free_ = value; }
// A list of object groups.
static List<ObjectGroup*> object_groups_;
};
int GlobalHandles::number_of_weak_handles_ = 0;
int GlobalHandles::number_of_global_object_weak_handles_ = 0;
// 初始化这两个头指针
GlobalHandles::Node* GlobalHandles::head_ = NULL;
GlobalHandles::Node* GlobalHandles::first_free_ = NULL;
List<ObjectGroup*> GlobalHandles::object_groups_(4);
内存结构图。
GlobalHandles的方法看起来比较多,很多都是对Node类的封装。我们继续看一下GlobalHandles的实现。
1 创建一个持久句柄。
持久句柄里保存了Node对象的地址。Node对象的地址由Create函数返回。
// 一个handle对应一个Node
Handle<Object> GlobalHandles::Create(Object* value) {
Counters::global_handles.Increment();
Node* result;
/*
有一个free_list,保存着DESTROYED状态但还没有被释放的Node,
first_free指向第一个节点,为NULL说明没有待回收的节点,即没有可重用的节点
*/
if (first_free() == NULL) {
// 没有可重用的节点则分配一个新的
result = new Node(value);
// 头插法,设置新增的node的下一个节点是当前头结点
result->set_next(head());
// 头指针指向新增的node
set_head(result);
} else {
// Take the first node in the free list.
// 获取一个可以重用的节点
result = first_free();
// 获取重用节点在free_list中的第一个节点,first_free指向新的可重用节点
set_first_free(result->next_free());
// 重新初始化该节点
result->Initialize(value);
}
// 返回Node对象的首地址
return result->handle();
}
2 销毁一个节点
修改节点的状态,把节点插入到空闲链表等待复用。
void GlobalHandles::Destroy(Object** location) {
Counters::global_handles.Decrement();
if (location == NULL) return;
Node* node = Node::FromLocation(location);
node->Destroy();
// Link the destroyed.
// 设置待销毁节点在free_list链表里的下一个节点是当前的头结点
node->set_next_free(first_free());
// 头指针指向待销毁的节点,
set_first_free(node);
}
3 节点状态相关
// 更新node的状态
void GlobalHandles::MakeWeak(Object** location, void* parameter,
WeakReferenceCallback callback) {
Node::FromLocation(location)->MakeWeak(parameter, callback);
}
// 恢复node的状态
void GlobalHandles::ClearWeakness(Object** location) {
Node::FromLocation(location)->ClearWeakness();
}
bool GlobalHandles::IsNearDeath(Object** location) {
return Node::FromLocation(location)->IsNearDeath();
}
bool GlobalHandles::IsWeak(Object** location) {
return Node::FromLocation(location)->IsWeak();
}
4 遍历
// gc相关,在分析gc的时候讲
void GlobalHandles::MarkWeakRoots(WeakSlotCallback f) {
for (Node* current = head_; current != NULL; current = current->next()) {
if (current->state_ == Node::WEAK) {
if (f(¤t->object_)) {
current->state_ = Node::PENDING;
}
}
}
}
// 遍历链表,ObjectVisitor是基类,传进来的是具体的子类(多态)
void GlobalHandles::IterateWeakRoots(ObjectVisitor* v) {
// Traversal of GC roots in the global handle list that are marked as
// WEAK or PENDING.
for (Node* current = head_; current != NULL; current = current->next()) {
if (current->state_ == Node::WEAK
|| current->state_ == Node::PENDING
|| current->state_ == Node::NEAR_DEATH) {
v->VisitPointer(¤t->object_);
}
}
}
// 遍历链表
void GlobalHandles::IterateRoots(ObjectVisitor* v) {
// Traversal of global handles marked as NORMAL or NEAR_DEATH.
for (Node* current = head_; current != NULL; current = current->next()) {
if (current->state_ == Node::NORMAL) {
v->VisitPointer(¤t->object_);
}
}
}
5 销毁链表
// 销毁所有节点,重置头指针
void GlobalHandles::TearDown() {
// Delete all the nodes in the linked list.
Node* current = head_;
while (current != NULL) {
Node* n = current;
current = current->next();
delete n;
}
// Reset the head and free_list.
set_head(NULL);
set_first_free(NULL);
}
6 组相关
参考上面的结构体
void GlobalHandles::AddToGroup(void* id, Object** handle) {
for (int i = 0; i < object_groups_.length(); i++) {
ObjectGroup* entry = object_groups_[i];
if (entry->id_ == id) {
entry->objects_.Add(handle);
return;
}
}
// not found
ObjectGroup* new_entry = new ObjectGroup(id);
new_entry->objects_.Add(handle);
object_groups_.Add(new_entry);
}
void GlobalHandles::RemoveObjectGroups() {
for (int i = 0; i< object_groups_.length(); i++) {
delete object_groups_[i];
}
object_groups_.Clear();
}
7 gc相关
// 垃圾回收的时候处理已经销毁的handle
void GlobalHandles::PostGarbageCollectionProcessing() {
// 垃圾回收完之后
ASSERT(Heap::gc_state() == Heap::NOT_IN_GC);
Node** p = &head_;
while (*p != NULL) {
// 调用Node的函数,可能会更新node的状态
(*p)->PostGarbageCollectionProcessing();
// 销毁的节点会放到free链表
if ((*p)->state_ == Node::DESTROYED) {
// Delete the link.
Node* node = *p;
// 指向下一个节点,即从链表中删除该节点
*p = node->next(); // Update the link.
// 释放node的内存
delete node;
} else {
// 因为p是二级指针,说明指向node的next域的地址。*p取得node的下一个节点地址
p = (*p)->next_addr();
}
}
// 重置free队列的头指针,因为链表的节点都被释放了
set_first_free(NULL);
}
总结,主要介绍了v8中实现持久句柄的基本原理(可结合分析handle那一篇一起看)。有一部分是gc相关的,等后分析gc的时候再分析。