溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

js引擎v8源碼怎么解析map對(duì)象

發(fā)布時(shí)間:2021-12-09 09:28:01 來(lái)源:億速云 閱讀:163 作者:柒染 欄目:大數(shù)據(jù)

js引擎v8源碼怎么解析map對(duì)象,針對(duì)這個(gè)問(wèn)題,這篇文章詳細(xì)介紹了相對(duì)應(yīng)的分析和解答,希望可以幫助更多想解決這個(gè)問(wèn)題的小伙伴找到更簡(jiǎn)單易行的方法。

首先介紹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)
     宏展開后變成,定義了讀寫某個(gè)屬性的函數(shù)
     Object * prototype();
     void * set_prototype(Object * value);

     屬性的定義如下(宏展開后也是讀寫某個(gè)屬性):
       #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);                                        \
         }

       // 定義各個(gè)類的讀寫某屬性的函數(shù),第三第四個(gè)參數(shù)是類型和偏移
       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對(duì)應(yīng)的一個(gè)字節(jié),下面分別是該一個(gè)字節(jié)各比特位的標(biāo)記
 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的屬性內(nèi)存布局。

js引擎v8源碼怎么解析map對(duì)象

我們逐個(gè)函數(shù)分析他的實(shí)現(xiàn)。首先看objects-inl.h中的實(shí)現(xiàn)。

   
     
 
    
    

// 獲取對(duì)象某個(gè)屬性的地址,p是對(duì)象的首地址,offset是偏移,kHeapObjectTag是對(duì)象的標(biāo)記,算地址的時(shí)候需要減掉
#define FIELD_ADDR(p, offset) \
 (reinterpret_cast<byte*>(p) + offset - kHeapObjectTag)

// 讀寫一個(gè)字節(jié)的內(nèi)容
#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));
}

// 讀寫一個(gè)字節(jié)的內(nèi)容,每個(gè)比特都記錄著一個(gè)標(biāo)記
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) {
   // 設(shè)置該位
   set_bit_field(bit_field() | (1 << kHasNonInstancePrototype));
 } else {
   // 清除該位
   set_bit_field(bit_field() & ~(1 << kHasNonInstancePrototype));
 }
}

// 是否設(shè)置了某位
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());
}

             

從上面的代碼中我們知道,只是對(duì)某些屬性或標(biāo)記進(jìn)行讀寫。

關(guān)于js引擎v8源碼怎么解析map對(duì)象問(wèn)題的解答就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,如果你還有很多疑惑沒(méi)有解開,可以關(guān)注億速云行業(yè)資訊頻道了解更多相關(guān)知識(shí)。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI