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

  • 2019 年 11 月 24 日
  • 筆記

1 TemplateInfo

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

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

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

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

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

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> {};  };

我们先看属性的定义。

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里有一个私有类

// 低两位是可读写标记  class AttributesField: public BitField<PropertyAttributes, 2, 3> {};

BitField是一个模板

// 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));    }  };

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

// 判断某个值的比特是否已设置  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里的属性描述符。