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

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

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 读取对象的属性

Object* HeapObject::GetHeapObjectField(HeapObject* obj, int index) {
  return READ_FIELD(obj, HeapObject::kSize + kPointerSize * index);
}

2 存取map对象

// 堆对象的开始地址是一个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 获取堆对象地址

// 封装过的地址,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 遍历对象空间

// 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对象

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对象直接得到。


// 计算对象的大小
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 遍历对象,在各个子类和迭代器中定义。后续额外分析。
堆对象的内存布局。
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值