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

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里的属性描述符。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
hydra_base-0.1.5-py3-none-any.whl 是一个Python第三方库的文件,其命名遵循一定规则。下面对其进行解释: - "hydra_base" 是第三方库的名称,表示该库为一个基础库,可能为一个框架或工具。 - "0.1.5" 是该库的版本号,表示该库的开发者在不同的时间或代码更新中对其进行了更新和改进。版本号的命名通常遵循主版本号.次版本号.修订版本号的格式,其中主版本号表示较大的功能或架构改动,次版本号表示较小的功能增加或修改,修订版本号表示Bug修复或其他细微改动。 - "py3" 表示该库是为Python 3版本编写的,有些库可能同时支持Python 2和Python 3,会在名称中做区分。 - "none" 表示该库适用于任何操作系统平台,没有特定的平台限制。 - "any" 表示该库不依赖于特定的Python解释器类型,可以在CPython、IronPython、PyPy等各种类型的Python解释器上运行。 在Python中,.whl文件是Python Wheels(Python软件包的一种二进制分发格式)的文件扩展名。它是一种方便Python库的分发和安装的文件格式。.whl文件可以包含用于特定平台(如Windows、Linux等)的已编译的二进制库,以及库的源代码文件和其他必要文件。 综上所述,hydra_base-0.1.5-py3-none-any.whl代表了一个名为hydra_base的Python第三方库,版本号为0.1.5,适用于Python 3的任何操作系统平台,可以在任何类型的Python解释器上运行。可以使用pip等工具安装这个库,并使用其中的功能来开发Python应用程序。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值