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);};
AI代码助手复制代码
下面的map的属性内存布局。
我们逐个函数分析他的实现。首先看objects-inl.h中的实现。
// 获取对象某个属性的地址,p是对象的首地址,offset是偏移,kHeapObjectTag是对象的标记,算地址的时候需要减掉#define FIELD_ADDR(p, offset) \ (reinterpret_cast<byte*>(p) + offset - kHeapObjectTag)// 读写一个字节的内容#define READ_BYTE_FIELD(p, offset) \ (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)))#define WRITE_BYTE_FIELD(p, offset, value) \ (*reinterpret_cast<byte*>(FIELD_ADDR(p, offset)) = value)void Map::set_instance_size(int value) { ASSERT(0 <= value && value < 256); WRITE_BYTE_FIELD(this, kInstanceSizeOffset, static_cast<byte>(value));}InstanceType Map::instance_type() { return static_cast<InstanceType>(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());}
AI代码助手复制代码
从上面的代码中我们知道,只是对某些属性或标记进行读写。
关于js引擎v8源码怎么解析map对象问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注亿速云行业资讯频道了解更多相关知识。
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。
原文链接:https://my.oschina.net/u/4217331/blog/4379423