v8源码解析之ByteArray(v8 0.1.5)

ByteArray是字节数组的实现,顾名思义,该数组的元素大小的一个字节,不过类似js的Uint16Array,Uint32Array数组一样,我们可以把多个元素看做一个,把多个字节合并成一个元素看待。下面我们看一下实现。

class ByteArray: public Array {
 public:
  // 按照一个元素一个字节的方式存取
  inline byte get(int index);
  inline void set(int index, byte value);
  // 按照一个元素四字节方式取
  inline int get_int(int index);
  /*
    计算长度为length的数组需要多少内存,在分配内存的时候,除了kHeaderSize,
    多分配一块存储数组元素的内存
    const int kObjectAlignmentBits = 2;
    const int kObjectAlignmentMask = (1 << kObjectAlignmentBits) - 1;
    #define OBJECT_SIZE_ALIGN(value)  ((value + kObjectAlignmentMask) & ~kObjectAlignmentMask)
    由此可知,按四个字节对齐。OBJECT_SIZE_ALIGN的作用的是不够4字节的,会多分配几个字节,使得按四字节对齐。~kObjectAlignmentMask是低两位是0,即按四字节对齐。比如value已经4字节对齐了,则(4 + 0 +3) & ~3 =4,如果value没有对齐,假设是5,则(4 + 1 +3) & ~3 = 8;如果value等于6,(4 + 2 + 3) & ~3 = 8;以此类推。
  */
  static int SizeFor(int length) {
    return kHeaderSize + OBJECT_SIZE_ALIGN(length);
  }
  // 元素个数
  static int LengthFor(int size_in_bytes) {
    ASSERT(IsAligned(size_in_bytes, kPointerSize));
    ASSERT(size_in_bytes >= kHeaderSize);
    return size_in_bytes - kHeaderSize;
  }

  // 返回数据部分的的虚拟地址,因为数据由元数据和有效数据部分组成,这里返回有效数据部分的首地址
  inline Address GetDataStartAddress();

  // 根据有效数据的地址address算出对象本身的首地址
  static inline ByteArray* FromDataStartAddress(Address address);

  // Casting.
  static inline ByteArray* cast(Object* obj);

  // 自己需要的内存
  int ByteArraySize() { return SizeFor(length()); }

 private:
  DISALLOW_IMPLICIT_CONSTRUCTORS(ByteArray);
};

1 数据按字节存取
kCharSize表示按字节操作

byte ByteArray::get(int index) {
  ASSERT(index >= 0 && index < this->length());
  // 根据索引返回数组中对应元素的值,kHeaderSize是第一个元素的地址,kCharSize是1,即一个字节
  return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
}

void ByteArray::set(int index, byte value) {
  ASSERT(index >= 0 && index < this->length());
  WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value);
}

2 数据按四字节读取
把四个元素(四个字节)的内容作为一个值。即ByteArray变成IntArray。

int ByteArray::get_int(int index) {
  ASSERT(index >= 0 && (index * kIntSize) < this->length());
  return READ_INT_FIELD(this, kHeaderSize + index * kIntSize);
}

3 地址计算
kHeapObjectTag是堆对象的标记,对象是四字节对齐的,所以地址的后两位不使用,而是用于保存一些标记。

// 获取对象首地址。address是数据部分首地址
ByteArray* ByteArray::FromDataStartAddress(Address address) {
  ASSERT_TAG_ALIGNED(address);
  return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag);
}
// 获取数据部分首地址
Address ByteArray::GetDataStartAddress() {
  /*
    typedef uint8_t byte;
    typedef byte* Address;
  */
  return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值