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

js引擎v8源码解析之对象第三篇(基于v8 0.1.5)

作者头像
theanarkh
发布2019-11-24 00:58:34
6440
发布2019-11-24 00:58:34
举报
文章被收录于专栏:原创分享

1 TemplateInfo

TemplateInfo是函数和对象模板的基类。

代码语言:javascript
复制
// An abstract superclass, a marker class really, for simple structure classes.
// It doesn't carry much functionality but allows struct classes to me
// identified in the type system.
class Struct: public HeapObject {
 public:
  inline void InitializeBody(int object_size);
  static inline Struct* cast(Object* that);
};

void Struct::InitializeBody(int object_size) {
  for (int offset = kSize; offset < object_size; offset += kPointerSize) {
    WRITE_FIELD(this, offset, Heap::undefined_value());
  }
}

class TemplateInfo: public Struct {
 public:
  DECL_ACCESSORS(tag, Object)
  DECL_ACCESSORS(property_list, Object)

  static const int kTagOffset          = HeapObject::kSize;
  static const int kPropertyListOffset = kTagOffset + kPointerSize;
  static const int kHeaderSize         = kPropertyListOffset + kPointerSize;
 protected:
  friend class AGCCVersionRequiresThisClassToHaveAFriendSoHereItIs;
  DISALLOW_IMPLICIT_CONSTRUCTORS(TemplateInfo);
};

通过前几篇的分析,我觉得这个代码没必要分析了。我们直接看子类。

2 FunctionTemplateInfo

代码语言:javascript
复制
class FunctionTemplateInfo: public TemplateInfo {
 public:
  DECL_ACCESSORS(serial_number, Object)
  DECL_ACCESSORS(call_code, Object)
  DECL_ACCESSORS(property_accessors, Object)
  DECL_ACCESSORS(prototype_template, Object)
  DECL_ACCESSORS(parent_template, Object)
  DECL_ACCESSORS(named_property_handler, Object)
  DECL_ACCESSORS(indexed_property_handler, Object)
  DECL_ACCESSORS(instance_template, Object)
  DECL_ACCESSORS(class_name, Object)
  DECL_ACCESSORS(signature, Object)
  DECL_ACCESSORS(lookup_callback, Object)
  DECL_ACCESSORS(instance_call_handler, Object)
  DECL_ACCESSORS(access_check_info, Object)
  DECL_ACCESSORS(flag, Smi)

  // Following properties use flag bits.
  DECL_BOOLEAN_ACCESSORS(hidden_prototype)
  DECL_BOOLEAN_ACCESSORS(undetectable)
  // If the bit is set, object instances created by this function
  // requires access check.
  DECL_BOOLEAN_ACCESSORS(needs_access_check)

  static inline FunctionTemplateInfo* cast(Object* obj);

#ifdef DEBUG
  void FunctionTemplateInfoPrint();
  void FunctionTemplateInfoVerify();
#endif

  static const int kSerialNumberOffset = TemplateInfo::kHeaderSize;
  static const int kCallCodeOffset = kSerialNumberOffset + kPointerSize;
  static const int kPropertyAccessorsOffset = kCallCodeOffset + kPointerSize;
  static const int kPrototypeTemplateOffset =
      kPropertyAccessorsOffset + kPointerSize;
  static const int kParentTemplateOffset =
      kPrototypeTemplateOffset + kPointerSize;
  static const int kNamedPropertyHandlerOffset =
      kParentTemplateOffset + kPointerSize;
  static const int kIndexedPropertyHandlerOffset =
      kNamedPropertyHandlerOffset + kPointerSize;
  static const int kInstanceTemplateOffset =
      kIndexedPropertyHandlerOffset + kPointerSize;
  static const int kClassNameOffset = kInstanceTemplateOffset + kPointerSize;
  static const int kSignatureOffset = kClassNameOffset + kPointerSize;
  static const int kLookupCallbackOffset = kSignatureOffset + kPointerSize;
  static const int kInstanceCallHandlerOffset =
      kLookupCallbackOffset + kPointerSize;
  static const int kAccessCheckInfoOffset =
      kInstanceCallHandlerOffset + kPointerSize;
  static const int kFlagOffset = kAccessCheckInfoOffset + kPointerSize;
  static const int kSize = kFlagOffset + kPointerSize;

 private:
  DISALLOW_IMPLICIT_CONSTRUCTORS(FunctionTemplateInfo);

  // Bit position in the flag, from least significant bit position.
  static const int kHiddenPrototypeBit   = 0;
  static const int kUndetectableBit      = 1;
  static const int kNeedsAccessCheckBit  = 2;
};

ACCESSORS(FunctionTemplateInfo, serial_number, Object, kSerialNumberOffset)
ACCESSORS(FunctionTemplateInfo, call_code, Object, kCallCodeOffset)
ACCESSORS(FunctionTemplateInfo, property_accessors, Object,
          kPropertyAccessorsOffset)
ACCESSORS(FunctionTemplateInfo, prototype_template, Object,
          kPrototypeTemplateOffset)
ACCESSORS(FunctionTemplateInfo, parent_template, Object, kParentTemplateOffset)
ACCESSORS(FunctionTemplateInfo, named_property_handler, Object,
          kNamedPropertyHandlerOffset)
ACCESSORS(FunctionTemplateInfo, indexed_property_handler, Object,
          kIndexedPropertyHandlerOffset)
ACCESSORS(FunctionTemplateInfo, instance_template, Object,
          kInstanceTemplateOffset)
ACCESSORS(FunctionTemplateInfo, class_name, Object, kClassNameOffset)
ACCESSORS(FunctionTemplateInfo, signature, Object, kSignatureOffset)
ACCESSORS(FunctionTemplateInfo, lookup_callback, Object, kLookupCallbackOffset)
ACCESSORS(FunctionTemplateInfo, instance_call_handler, Object,
          kInstanceCallHandlerOffset)
ACCESSORS(FunctionTemplateInfo, access_check_info, Object,
          kAccessCheckInfoOffset)
ACCESSORS(FunctionTemplateInfo, flag, Smi, kFlagOffset)

BOOL_ACCESSORS(FunctionTemplateInfo, flag, hidden_prototype,
               kHiddenPrototypeBit)
BOOL_ACCESSORS(FunctionTemplateInfo, flag, undetectable, kUndetectableBit)
BOOL_ACCESSORS(FunctionTemplateInfo, flag, needs_access_check,
               kNeedsAccessCheckBit)

3 ObjectTemplateInfo

代码语言:javascript
复制
class ObjectTemplateInfo: public TemplateInfo {
 public:
  DECL_ACCESSORS(constructor, Object)
  DECL_ACCESSORS(internal_field_count, Object)

  static inline ObjectTemplateInfo* cast(Object* obj);

#ifdef DEBUG
  void ObjectTemplateInfoPrint();
  void ObjectTemplateInfoVerify();
#endif

  static const int kConstructorOffset = TemplateInfo::kHeaderSize;
  static const int kInternalFieldCountOffset =
      kConstructorOffset + kPointerSize;
  static const int kSize = kInternalFieldCountOffset + kHeaderSize;
};

ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset)
ACCESSORS(ObjectTemplateInfo, internal_field_count, Object,
          kInternalFieldCountOffset)

我们从代码可以知道,这几个类没有太多的逻辑,都有一系列的属性和对应的读写函数。对号入座就行。

4 BooleanBit

代码语言:javascript
复制
// BooleanBit is a helper class for setting and getting a bit in an
// integer or Smi.
// 比特位读写类
class BooleanBit : public AllStatic {
 public:
  static inline bool get(Smi* smi, int bit_position) {
    return get(smi->value(), bit_position);
  }

  static inline bool get(int value, int bit_position) {
    return (value & (1 << bit_position)) != 0;
  }

  static inline Smi* set(Smi* smi, int bit_position, bool v) {
    return Smi::FromInt(set(smi->value(), bit_position, v));
  }

  static inline int set(int value, int bit_position, bool v) {
    if (v) {
      // 设置
      value |= (1 << bit_position);
    } else {
      // 清除
      value &= ~(1 << bit_position);
    }
    return value;
  }
};

} }

5 AccessorInfo

代码语言:javascript
复制
class AccessorInfo: public Struct {
 public:
  DECL_ACCESSORS(getter, Object)
  DECL_ACCESSORS(setter, Object)
  DECL_ACCESSORS(data, Object)
  DECL_ACCESSORS(name, Object)
  DECL_ACCESSORS(flag, Smi)

  inline bool all_can_read();
  inline void set_all_can_read(bool value);

  inline bool all_can_write();
  inline void set_all_can_write(bool value);

  inline PropertyAttributes property_attributes();
  inline void set_property_attributes(PropertyAttributes attributes);

  static inline AccessorInfo* cast(Object* obj);

  static const int kGetterOffset = HeapObject::kSize;
  static const int kSetterOffset = kGetterOffset + kPointerSize;
  static const int kDataOffset = kSetterOffset + kPointerSize;
  static const int kNameOffset = kDataOffset + kPointerSize;
  static const int kFlagOffset = kNameOffset + kPointerSize;
  static const int kSize = kFlagOffset + kPointerSize;

 private:
  DISALLOW_IMPLICIT_CONSTRUCTORS(AccessorInfo);

  // Bit positions in flag.
  static const int kAllCanReadBit  = 0;
  static const int kAllCanWriteBit = 1;
  class AttributesField: public BitField<PropertyAttributes, 2, 3> {};
};

我们先看属性的定义。

代码语言:javascript
复制
ACCESSORS(AccessorInfo, getter, Object, kGetterOffset)
ACCESSORS(AccessorInfo, setter, Object, kSetterOffset)
ACCESSORS(AccessorInfo, data, Object, kDataOffset)
ACCESSORS(AccessorInfo, name, Object, kNameOffset)
ACCESSORS(AccessorInfo, flag, Smi, kFlagOffset)

接着看函数的实现。我们发现private里有一个私有类

代码语言:javascript
复制
// 低两位是可读写标记
class AttributesField: public BitField<PropertyAttributes, 2, 3> {};

BitField是一个模板

代码语言:javascript
复制
// BitField is a help template for encoding and decode bitfield with unsigned
// content.
template<class T, int shift, int size>
class BitField {
 public:
  // Tells whether the provided value fits into the bit field.
  // 判断低几位之外的其他位是否都等于0
  static bool is_valid(T value) {
    return (static_cast<uint32_t>(value) & ~((1U << (size)) - 1)) == 0;
  }

  // Returns a uint32_t mask of bit field.
  // 从第shift+1到shift+size位为1,其他位为0。这里是3到5位
  static uint32_t mask() {
    return (1U << (size + shift)) - (1U << shift);
  }

  // Returns a uint32_t with the bit field value encoded.
  // 设置某位的值,这里是跳过低2位,因为低两位是可读写标记
  static uint32_t encode(T value) {
    ASSERT(is_valid(value));
    return static_cast<uint32_t>(value) << shift;
  }

  // Extracts the bit field from the value.
  // 取某位的值,需要屏蔽其他不相关的位的值,这里值的范围是小于等于7
  static T decode(uint32_t value) {
    return static_cast<T>((value >> shift) & ((1U << (size)) - 1));
  }
};

最后看一下其他函数的实现。

代码语言:javascript
复制
// 判断某个值的比特是否已设置
bool AccessorInfo::all_can_read() {
  return BooleanBit::get(flag(), kAllCanReadBit);
}

// 设置某个值的某个比特
void AccessorInfo::set_all_can_read(bool value) {
  set_flag(BooleanBit::set(flag(), kAllCanReadBit, value));
}


bool AccessorInfo::all_can_write() {
  return BooleanBit::get(flag(), kAllCanWriteBit);
}


void AccessorInfo::set_all_can_write(bool value) {
  set_flag(BooleanBit::set(flag(), kAllCanWriteBit, value));
}

// 获flag里取某位的值
PropertyAttributes AccessorInfo::property_attributes() {
  return AttributesField::decode(static_cast<uint32_t>(flag()->value()));
}

/*
  // Ecma-262 3rd 8.6.1
  enum PropertyAttributes {
    NONE              = v8::None,
    READ_ONLY         = v8::ReadOnly,
    DONT_ENUM         = v8::DontEnum,
    DONT_DELETE       = v8::DontDelete,
    INTERCEPTED       = 1 << 3,
    ABSENT            = 16  // Used in runtime to indicate a property is absent.
  };

 设置flag某位的值,见AttributesField
 */
void AccessorInfo::set_property_attributes(PropertyAttributes attributes) {
  ASSERT(AttributesField::is_valid(attributes));
  // 清除相关的位
  int rest_value = flag()->value() & ~AttributesField::mask();
  // 重新设置某位
  set_flag(Smi::FromInt(rest_value | AttributesField::encode(attributes)));
}

我们看到因为PropertyAttributes是3个比特可以表示全部值的。所以flag中划出3-5三位记录着三个比特。每次设置的时候,需要把之前的清除。AccessorInfo就是我们在js里的属性描述符。

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

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

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1 TemplateInfo
  • 2 FunctionTemplateInfo
  • 3 ObjectTemplateInfo
  • 4 BooleanBit
  • 5 AccessorInfo
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档