前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >js引擎v8源码分析之HeapObject(基于v8 0.1.5)

js引擎v8源码分析之HeapObject(基于v8 0.1.5)

作者头像
theanarkh
发布2020-02-25 15:16:11
9400
发布2020-02-25 15:16:11
举报
文章被收录于专栏:原创分享

HeapObject是Object的子类。是所有基于堆分配的对象的基类。

代码语言:javascript
复制
class HeapObject: public Object {
 public:
  // 每个堆对象都有一个map对象,记录对象的类型,大小等信息
  inline Map* map();
  inline void set_map(Map* value);

  // 对象的地址+对象标记
  static inline HeapObject* FromAddress(Address address);

  // 对象的真正地址
  inline Address address();

  void Iterate(ObjectVisitor* v);

  void IterateBody(InstanceType type, int object_size, ObjectVisitor* v);

  void IterateStructBody(int object_size, ObjectVisitor* v);

  inline void CopyBody(JSObject* from);

  inline int Size();

  inline int SizeFromMap(Map* map);

  static inline Object* GetHeapObjectField(HeapObject* obj, int index);

  static inline HeapObject* cast(Object* obj);
  // 内存布局信息,v8不定义对象的属性,而是通过offset来定义每个属性的位置
  static const int kMapOffset = Object::kSize;
  static const int kSize = kMapOffset + kPointerSize;

 protected:
  // 遍历
  inline void IteratePointers(ObjectVisitor* v, int start, int end);
  inline void IteratePointer(ObjectVisitor* v, int offset);

  int SlowSizeFromMap(Map* map);

 private:
  // 禁止直接创建对象
  DISALLOW_IMPLICIT_CONSTRUCTORS(HeapObject);
};

下面是定义

1 读取对象的属性

代码语言:javascript
复制
Object* HeapObject::GetHeapObjectField(HeapObject* obj, int index) {
  return READ_FIELD(obj, HeapObject::kSize + kPointerSize * index);
}

2 存取map对象

代码语言:javascript
复制
// 堆对象的开始地址是一个Map对象
Map* HeapObject::map() {
  return reinterpret_cast<Map*> READ_FIELD(this, kMapOffset);
}

// 设置堆对象的map对象
void HeapObject::set_map(Map* value) {
  WRITE_FIELD(this, kMapOffset, value);
}

3 获取堆对象地址

代码语言:javascript
复制
// 封装过的地址,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;
}

4 遍历对象空间

代码语言:javascript
复制
// FIELD_ADDR算出开始的虚拟地址
void HeapObject::IteratePointers(ObjectVisitor* v, int start, int end) {
  v->VisitPointers(reinterpret_cast<Object**>(FIELD_ADDR(this, start)),
                   reinterpret_cast<Object**>(FIELD_ADDR(this, end)));
}

void HeapObject::IteratePointer(ObjectVisitor* v, int offset) {
  v->VisitPointer(reinterpret_cast<Object**>(FIELD_ADDR(this, offset)));
}

5 复制对象的内容,不包括map对象

代码语言:javascript
复制
void HeapObject::CopyBody(JSObject* from) {
  ASSERT(map() == from->map());
  ASSERT(Size() == from->Size());
  int object_size = Size();
  // 从map对象指针后面开始复制
  for (int offset = kSize; offset < object_size;  offset += kPointerSize) {
    Object* value = READ_FIELD(from, offset);
    WRITE_FIELD(this, offset, value);
    // 写屏障,用于gc
    WRITE_BARRIER(this, offset);
  }
}

6 计算对象大小,子类定义或者可以从map对象直接得到。

代码语言:javascript
复制
// 计算对象的大小
int HeapObject::Size() {
  return SizeFromMap(map());
}

int HeapObject::SizeFromMap(Map* map) {
  InstanceType instance_type = map->instance_type();
  // Only inline the two most frequent cases.
  if (instance_type == JS_OBJECT_TYPE) return  map->instance_size();
  if (instance_type == FIXED_ARRAY_TYPE) {
    // 数组对象大小,包括元数据和存储数据的部分
    return reinterpret_cast<FixedArray*>(this)->FixedArraySize();
  }
  // Otherwise do the general size computation.
  return SlowSizeFromMap(map);
}

int HeapObject::SlowSizeFromMap(Map* map) {
  InstanceType instance_type = map->instance_type();

  if (instance_type < FIRST_NONSTRING_TYPE && (reinterpret_cast<String*>(this)->map_representation_tag(map) == kSeqStringTag)) {
    if (reinterpret_cast<String*>(this)->is_ascii_map(map)) {
      return reinterpret_cast<AsciiString*>(this)->AsciiStringSize(map);
    } else {
      return reinterpret_cast<TwoByteString*>(this)->TwoByteStringSize(map);
    }
  }

  switch (instance_type) {
    case FIXED_ARRAY_TYPE:
      return reinterpret_cast<FixedArray*>(this)->FixedArraySize();
    case BYTE_ARRAY_TYPE:
      return reinterpret_cast<ByteArray*>(this)->ByteArraySize();
    case CODE_TYPE:
      return reinterpret_cast<Code*>(this)->CodeSize();
    case MAP_TYPE:
      return Map::kSize;
    default:
      return map->instance_size();
  }
}

7 遍历对象,在各个子类和迭代器中定义。后续额外分析。 堆对象的内存布局。

在这里插入图片描述

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-02-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 编程杂技 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1 读取对象的属性
  • 2 存取map对象
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档