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);
};
通过前几篇的分析,我觉得这个代码没必要分析了。我们直接看子类。
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)
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)
我们从代码可以知道,这几个类没有太多的逻辑,都有一系列的属性和对应的读写函数。对号入座就行。
// 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;
}
};
} }
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里的属性描述符。