首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >v8源码解析之ByteArray(v8 0.1.5)

v8源码解析之ByteArray(v8 0.1.5)

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

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;
}
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-10-18,如有侵权请联系 cloudcommunity@tencent.com 删除

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

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云硬盘
云硬盘(Cloud Block Storage,CBS)为您提供用于 CVM 的持久性数据块级存储服务。云硬盘中的数据自动地在可用区内以多副本冗余方式存储,避免数据的单点故障风险,提供高达99.9999999%的数据可靠性。同时提供多种类型及规格,满足稳定低延迟的存储性能要求。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档