首页 > 其他 > 详细

v8的HeapObject解析

时间:2014-03-03 16:53:13      阅读:554      评论:0      收藏:0      [点我收藏+]
一.HeapObject之内存结构
v8使用HeapObject作为js object的基类,其优点是一方面可以加快访问速度,另外还可以通过垃圾回收进行管理,所有从HeapObject派生的类,都是原始的struct结构,它使用四字节作为一个字段,第一个四字节字段是map指针,指向一个map对象,当然这个map对象也是从HeapObject派生的,我们可以从这样的派生类定义中看到其内存结构。以StringObject为例,可参看 StringObject的内存布局 JSReceiver及其派生类的内存布局

二.HeapObject中字段的设置与获取
HeapObject及其派生类对象中的字段是靠getter和setter来获取和设置的,但是在他们的定义中却找不到getter和setter函数,那么它们定义在哪里呢?
在objects.h中,宏DECL_ACCESSORS定义如下:
#define DECL_ACCESSORS(name, type)                                      \
  inline type* name();                                                  \
  inline void set_##name(type* value,                                   \
                         WriteBarrierMode mode = UPDATE_WRITE_BARRIER); \
每个HeapObject中必然有该宏来声明getter和setter函数

在objects-inl.h,宏ACCESSORS定义了getter和setter函数
#define ACCESSORS(holder, name, type, offset)                           \
  type* holder::name() { return type::cast(READ_FIELD(this, offset)); } \
  void holder::set_##name(type* value, WriteBarrierMode mode) {         \
    WRITE_FIELD(this, offset, value);                                   \
    CONDITIONAL_WRITE_BARRIER(GetHeap(), this, offset, value, mode);    \
  }
另外,在该头文件中,还有大量类使用ACCESSORS宏定义其getter和setter函数
该宏中使用了READ_FIELD和WRITE_FIELD宏来读写指定offset的内容
#define FIELD_ADDR(p, offset) \
  (reinterpret_cast<byte*>(p) + offset - kHeapObjectTag)

#define READ_FIELD(p, offset) \
  (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)))

#define WRITE_FIELD(p, offset, value) \
  (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)) = value)

三.TypeChecker and Cast
由于使用了Struct的内存结构,无法像C++那样在运行期保证Object的类型,v8定义了如下的宏来保证类型和转换的正确性(在objects-inl.h中定义)
#define TYPE_CHECKER(type, instancetype)                                \
  bool Object::Is##type() {                                             \
  return Object::IsHeapObject() &&                                      \
      HeapObject::cast(this)->map()->instance_type() == instancetype;   \
  }
判断type是否是instancetype

#define CAST_ACCESSOR(type)                     \
  type* type::cast(Object* object) {            \
    ASSERT(object->Is##type());                 \
    return reinterpret_cast<type*>(object);     \
  }
把Object指针强制转换为type*类型

我们可以看到这里使用了map的instance_type进行实例的类型判断,它们实际上定义了两类函数,TYPE_CHECKER宏为Object类定义IsType函数,CAST_ACCESSOR宏为不同的类定义cast函数,同样在该文件中,若干个类使用了这两个宏来定义IsType和cast函数

四.注意事项
这里特别需要提到的一点是在计算地址的时候,使用到了kHeapObjectTag,该值为1,而且在调试过程中我们发现这里用到计算地址的this指针都不是四字节对齐的,显然在要求四字节对齐的C/C++语言中是不可想象的,所以这个this指针一定会是做了处理,通过分析我们发现在创建Struct对象的时候,Heap分配内存后,会调用HeapObject::FromAddress函数,给四字节对齐加上一个kHeapObjectTag,所以在这里计算地址的时候,要减去这个kHeapObjectTag,否则会发生访问违例。
HeapObject* HeapObject::FromAddress(Address address) {
  ASSERT_TAG_ALIGNED(address);
  return reinterpret_cast<HeapObject*>(address + kHeapObjectTag);
}

Address HeapObject::address() {
  return reinterpret_cast<Address>(this) - kHeapObjectTag;
}

还有另外一点,set和get函数对成员变量操作的时候,传入的类型都是指针,需要特别注意,因为每个成员变量都是4字节的,所以他们被get出来,或者被set的时候,都是以指针的形式,当然这并不意味着它的值就一定是一个真实的地址,也可能是一个数值,被强转为指针

v8的HeapObject解析,布布扣,bubuko.com

v8的HeapObject解析

原文:http://blog.csdn.net/sunbxonline/article/details/20311131

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!