千家信息网

js引擎v8源码怎么解析map对象

发表于:2025-02-04 作者:千家信息网编辑
千家信息网最后更新 2025年02月04日,js引擎v8源码怎么解析map对象,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。首先介绍Map类。下面先看类定义
千家信息网最后更新 2025年02月04日js引擎v8源码怎么解析map对象

js引擎v8源码怎么解析map对象,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。

首先介绍Map类。下面先看类定义

                 
// All heap objects have a Map that describes their structure.
// A Map contains information about:
// - Size information about the object
// - How to iterate over an object (for garbage collection)
class Map: public HeapObject {
public:
// instance size.
inline int instance_size();
inline void set_instance_size(int value);

// instance type.
inline InstanceType instance_type();
inline void set_instance_type(InstanceType value);

// tells how many unused property fields are available in the instance.
// (only used for JSObject in fast mode).
inline int unused_property_fields();
inline void set_unused_property_fields(int value);

// bit field.
inline byte bit_field();
inline void set_bit_field(byte value);

// Tells whether this object has a special lookup behavior.
void set_special_lookup() {
set_bit_field(bit_field() | (1 << kHasSpecialLookup));
}

bool has_special_lookup() {
return ((1 << kHasSpecialLookup) & bit_field()) != 0;
}

// Tells whether the object in the prototype property will be used
// for instances created from this function. If the prototype
// property is set to a value that is not a JSObject, the prototype
// property will not be used to create instances of the function.
// See ECMA-262, 13.2.2.
inline void set_non_instance_prototype(bool value);
inline bool has_non_instance_prototype();

// Tells whether the instance with this map should be ignored by the
// __proto__ accessor.
inline void set_is_hidden_prototype() {
set_bit_field(bit_field() | (1 << kIsHiddenPrototype));
}

inline bool is_hidden_prototype() {
return ((1 << kIsHiddenPrototype) & bit_field()) != 0;
}

// Tells whether the instance has a named interceptor.
inline void set_has_named_interceptor() {
set_bit_field(bit_field() | (1 << kHasNamedInterceptor));
}

inline bool has_named_interceptor() {
return ((1 << kHasNamedInterceptor) & bit_field()) != 0;
}

// Tells whether the instance has a named interceptor.
inline void set_has_indexed_interceptor() {
set_bit_field(bit_field() | (1 << kHasIndexedInterceptor));
}

inline bool has_indexed_interceptor() {
return ((1 << kHasIndexedInterceptor) & bit_field()) != 0;
}

// Tells whether the instance is undetectable.
// An undetectable object is a special class of JSObject: 'typeof' operator
// returns undefined, ToBoolean returns false. Otherwise it behaves like
// a normal JS object. It is useful for implementing undetectable
// document.all in Firefox & Safari.
// See https://bugzilla.mozilla.org/show_bug.cgi?id=248549.
inline void set_is_undetectable() {
set_bit_field(bit_field() | (1 << kIsUndetectable));
}

inline bool is_undetectable() {
return ((1 << kIsUndetectable) & bit_field()) != 0;
}

// Tells whether the instance has a call-as-function handler.
inline void set_has_instance_call_handler() {
set_bit_field(bit_field() | (1 << kHasInstanceCallHandler));
}

inline bool has_instance_call_handler() {
return ((1 << kHasInstanceCallHandler) & bit_field()) != 0;
}

// Tells whether the instance needs security checks when accessing its
// properties.
inline void set_needs_access_check() {
set_bit_field(bit_field() | (1 << kNeedsAccessCheck));
}

inline bool needs_access_check() {
return ((1 << kNeedsAccessCheck) & bit_field()) != 0;
}

// [prototype]: implicit prototype object.
/*
#define DECL_ACCESSORS(name, type) \
inline type* name(); \
inline void set_##name(type* value)
宏展开后变成,定义了读写某个属性的函数
Object * prototype();
void * set_prototype(Object * value);

属性的定义如下(宏展开后也是读写某个属性):
#define ACCESSORS(holder, name, type, offset) \
type* holder::name() { return type::cast(READ_FIELD(this, offset)); } \
void holder::set_##name(type* value) { \
WRITE_FIELD(this, offset, value); \
WRITE_BARRIER(this, offset); \
}

// 定义各个类的读写某属性的函数,第三第四个参数是类型和偏移
ACCESSORS(Map, instance_descriptors, DescriptorArray,
kInstanceDescriptorsOffset)
ACCESSORS(Map, code_cache, FixedArray, kCodeCacheOffset)
ACCESSORS(Map, constructor, Object, kConstructorOffset
*/
DECL_ACCESSORS(prototype, Object)

// [constructor]: points back to the function responsible for this map.
DECL_ACCESSORS(constructor, Object)

// [instance descriptors]: describes the object.
DECL_ACCESSORS(instance_descriptors, DescriptorArray)

// [stub cache]: contains stubs compiled for this map.
DECL_ACCESSORS(code_cache, FixedArray)

// Returns a copy of the map.
Object* Copy();

// Returns the property index for name (only valid for FAST MODE).
int PropertyIndexFor(String* name);

// Returns the next free property index (only valid for FAST MODE).
int NextFreePropertyIndex();

// Returns the number of properties described in instance_descriptors.
int NumberOfDescribedProperties();

// Casting.
static inline Map* cast(Object* obj);

// Locate an accessor in the instance descriptor.
AccessorDescriptor* FindAccessor(String* name);

// Make sure the instance descriptor has no map transitions
Object* EnsureNoMapTransitions();

// Code cache operations.

// Clears the code cache.
inline void ClearCodeCache();

// Update code cache.
Object* UpdateCodeCache(String* name, Code* code);

// Returns the found code or undefined if absent.
Object* FindInCodeCache(String* name, Code::Flags flags);

// Tells whether code is in the code cache.
bool IncludedInCodeCache(Code* code);

// Dispatched behavior.
void MapIterateBody(ObjectVisitor* v);
#ifdef DEBUG
void MapPrint();
void MapVerify();
#endif

// Layout description.
static const int kInstanceAttributesOffset = HeapObject::kSize;
static const int kPrototypeOffset = kInstanceAttributesOffset + kIntSize;
static const int kConstructorOffset = kPrototypeOffset + kPointerSize;
static const int kInstanceDescriptorsOffset =
kConstructorOffset + kPointerSize;
static const int kCodeCacheOffset = kInstanceDescriptorsOffset + kPointerSize;
static const int kSize = kCodeCacheOffset + kIntSize;

// Byte offsets within kInstanceAttributesOffset attributes.
static const int kInstanceSizeOffset = kInstanceAttributesOffset + 0;
static const int kInstanceTypeOffset = kInstanceAttributesOffset + 1;
static const int kUnusedPropertyFieldsOffset = kInstanceAttributesOffset + 2;
static const int kBitFieldOffset = kInstanceAttributesOffset + 3;

// kBitFieldOffset对应的一个字节,下面分别是该一个字节各比特位的标记
static const int kHasSpecialLookup = 0;
static const int kHasNonInstancePrototype = 1;
static const int kIsHiddenPrototype = 2;
static const int kHasNamedInterceptor = 3;
static const int kHasIndexedInterceptor = 4;
static const int kIsUndetectable = 5;
static const int kHasInstanceCallHandler = 6;
static const int kNeedsAccessCheck = 7;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(Map);
};



下面的map的属性内存布局。

我们逐个函数分析他的实现。首先看objects-inl.h中的实现。

                 
// 获取对象某个属性的地址,p是对象的首地址,offset是偏移,kHeapObjectTag是对象的标记,算地址的时候需要减掉
#define FIELD_ADDR(p, offset) \
(reinterpret_cast(p) + offset - kHeapObjectTag)

// 读写一个字节的内容
#define READ_BYTE_FIELD(p, offset) \
(*reinterpret_cast(FIELD_ADDR(p, offset)))

#define WRITE_BYTE_FIELD(p, offset, value) \
(*reinterpret_cast(FIELD_ADDR(p, offset)) = value)


void Map::set_instance_size(int value) {
ASSERT(0 <= value && value < 256);
WRITE_BYTE_FIELD(this, kInstanceSizeOffset, static_cast(value));
}


InstanceType Map::instance_type() {
return static_cast(READ_BYTE_FIELD(this, kInstanceTypeOffset));
}


void Map::set_instance_type(InstanceType value) {
ASSERT(0 <= value && value < 256);
WRITE_BYTE_FIELD(this, kInstanceTypeOffset, value);
}


int Map::unused_property_fields() {
return READ_BYTE_FIELD(this, kUnusedPropertyFieldsOffset);
}


void Map::set_unused_property_fields(int value) {
WRITE_BYTE_FIELD(this, kUnusedPropertyFieldsOffset, Min(value, 255));
}

// 读写一个字节的内容,每个比特都记录着一个标记
byte Map::bit_field() {
return READ_BYTE_FIELD(this, kBitFieldOffset);
}


void Map::set_bit_field(byte value) {
WRITE_BYTE_FIELD(this, kBitFieldOffset, value);
}


void Map::set_non_instance_prototype(bool value) {
if (value) {
// 设置该位
set_bit_field(bit_field() | (1 << kHasNonInstancePrototype));
} else {
// 清除该位
set_bit_field(bit_field() & ~(1 << kHasNonInstancePrototype));
}
}

// 是否设置了某位
bool Map::has_non_instance_prototype() {
return ((1 << kHasNonInstancePrototype) & bit_field()) != 0;
}

void Map::ClearCodeCache() {
// No write barrier is needed since empty_fixed_array is not in new space.
// Please note this function is used during marking:
// - MarkCompactCollector::MarkUnmarkedObject
ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
WRITE_FIELD(this, kCodeCacheOffset, Heap::empty_fixed_array());
}



从上面的代码中我们知道,只是对某些属性或标记进行读写。

关于js引擎v8源码怎么解析map对象问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注行业资讯频道了解更多相关知识。

0