了解 Google 的 V8 C++ 代码库中的继承

Understanding inheritance in Google's V8 C++ code base

我无法理解 Google 的 V8 JavaScript 引擎中继承的实现。它显然(?)实现了继承层次结构,但似乎完全取消了虚函数。

这是 objects.h header file 中详述的继承层次结构:

// Inheritance hierarchy:
// - Object
//   - Smi          (immediate small integer)
//   - HeapObject   (superclass for everything allocated in the heap)
//     - JSReceiver  (suitable for property access)
//       - JSObject
//         - JSArray
// ... and many more entries

大部分对象类型派生自Object,声明如下:

// Object is the abstract superclass for all classes in the
// object hierarchy.
// Object does not use any virtual functions to avoid the
// allocation of the C++ vtable.
// Since both Smi and HeapObject are subclasses of Object no
// data members can be present in Object.
class Object {
// ... bunch of method declarations and definitions
};

比较简单的Smiclass接下来声明:

class Smi: public Object {
 public:
 // methods declarations and static member definitions
};

等等。

对于我的生活,我无法理解 Smi 的实例怎么可以用作 Object没有虚函数并且我在the implementation file, objects.cc中找不到覆盖。但是,在 17,290 行中,试图了解正在发生的事情证明是一项艰巨的任务。

作为另一个困难,我在同一个头文件中发现了一个ObjectVisitor class(这个更classical;它由虚拟方法组成)。但是我在 Object 基础 class.

中找不到等效的 Accept(Visitor*) (或类似的)方法

我具体要问的是一个最小的例子来说明这种继承模式是如何工作的。

查看 Object::IsPromise() 以了解其工作原理的完美示例:

bool Object::IsPromise(Handle<Object> object) {
  if (!object->IsJSObject()) return false;
  auto js_object = Handle<JSObject>::cast(object);
  // Promises can't have access checks.
  if (js_object->map()->is_access_check_needed()) return false;
  auto isolate = js_object->GetIsolate();
  // TODO(dcarney): this should just be read from the symbol registry so as not
  // to be context dependent.
  auto key = isolate->promise_status();
  // Shouldn't be possible to throw here.
  return JSObject::HasRealNamedProperty(js_object, key).FromJust();
}

这里使用的继承方式是静态的。也就是说,类型查询是由代理或容器完成的(使用一些隐藏的魔法,乍一看就像他们在使用引用来查询标签),以及从 Object 到派生的 [=28] 的转换=] 由 static_cast<>() 完成。这样就可以调用派生的class的成员函数了

请注意,在上面的函数中,类型查询和转换是由 Handle<> class 间接执行的,而不是 Object 或其派生的任何 class es.

另请注意,接受ObjectVisitor作为参数的函数比较统一地称为Iterate,并且这些函数都出现在代理或句柄上.

objects.h 中的 类 实际上并没有定义真正的 C++ 类。他们没有任何领域。 类 只是 V8 JavaScript 堆上管理的对象的外观。因此它们也不能有任何虚函数,因为那需要将 vtable 指针放入 JS 堆中。相反,所有调度都是通过显式类型检查和向下转换手动完成的。

方法内部的 this 指针也不是真实的。对于 smis,this 只是一个整数。对于其他所有内容,它都是一个指向 V8 堆的指针,为了标记而减一。任何实际的访问器方法都会屏蔽此指针并添加偏移量以访问堆中的适当地址。每个字段的偏移量也在 类.

中手动定义