溫馨提示×

溫馨提示×

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

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

js引擎HeapObject怎么實現(xiàn)

發(fā)布時間:2021-12-17 09:35:39 來源:億速云 閱讀:141 作者:iii 欄目:大數(shù)據

這篇文章主要介紹“js引擎HeapObject怎么實現(xiàn)”,在日常操作中,相信很多人在js引擎HeapObject怎么實現(xiàn)問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”js引擎HeapObject怎么實現(xiàn)”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

v8的對象基類是Object。我們先看一下他的類定義。下面只列出重要的函數(shù)。

   
     
 
    
    

// Object is the abstract superclass for all classes in the
// object hierarchy.
// Object does not use any virtual functions to avoid the
// allocation of the C++ vtable.
// Since Smi and Failure are subclasses of Object no
// data members can be present in Object.
class Object BASE_EMBEDDED {
public:
 // Type testing.
 inline bool IsSmi();
 // 下面是一些列isXX的函數(shù)
 // Extract the number.
 inline double Number();

 Object* ToObject();             // ECMA-262 9.9.
 Object* ToBoolean();            // ECMA-262 9.2.

 // Convert to a JSObject if needed.
 // global_context is used when creating wrapper object.
 Object* ToObject(Context* global_context);

 // Converts this to a Smi if possible.
 // Failure is returned otherwise.
 inline Object* ToSmi();

 void Lookup(String* name, LookupResult* result);

 // Property access.
 inline Object* GetProperty(String* key);
 inline Object* GetProperty(String* key, PropertyAttributes* attributes);
 Object* GetPropertyWithReceiver(Object* receiver,
                                 String* key,
                                 PropertyAttributes* attributes);
 Object* GetProperty(Object* receiver,
                     LookupResult* result,
                     String* key,
                     PropertyAttributes* attributes);
 Object* GetPropertyWithCallback(Object* receiver,
                                 Object* structure,
                                 String* name,
                                 Object* holder);

 inline Object* GetElement(uint32_t index);
 Object* GetElementWithReceiver(Object* receiver, uint32_t index);

 // Return the object's prototype (might be Heap::null_value()).
 Object* GetPrototype();

 // Returns true if this is a JSValue containing a string and the index is
 // < the length of the string.  Used to implement [] on strings.
 inline bool IsStringObjectWithCharacterAt(uint32_t index);

 // Casting: This cast is only needed to satisfy macros in objects-inl.h.
 static Object* cast(Object* value) { return value; }

 // Layout description.
 static const int kSize = 0;  // Object does not take up any space.

private:
 // 禁止對象在堆中創(chuàng)建
 /*
     宏展開是
     Object();
     Object(const TypeName&);
     void operator=(const Object&)
 */
 DISALLOW_IMPLICIT_CONSTRUCTORS(Object);
};

             

我們看到類中有一個靜態(tài)屬性kSize,這個屬性是標記該類的對象,屬性需要占據的內存字節(jié)大小。下面我們看第一個繼承于Object的類Smi。Smi是表示小整形。我們看他的定義。

   
     
 
    
    

class Smi: public Object {
public:
 // Returns the integer value.
 inline int value();

 // Convert a value to a Smi object.
 static inline Smi* FromInt(int value);

 // Returns whether value can be represented in a Smi.
 static inline bool IsValid(int value);

 // Casting.
 static inline Smi* cast(Object* object);
 // Min and max limits for Smi values.
 static const int kMinValue = -(1 << (kBitsPerPointer - (kSmiTagSize + 1)));
 static const int kMaxValue = (1 << (kBitsPerPointer - (kSmiTagSize + 1))) - 1;

private:
 DISALLOW_IMPLICIT_CONSTRUCTORS(Smi);
};

             

Smi的實現(xiàn)。主要有兩個函數(shù)。

   
     
 
    
    

int Smi::value() {
 return reinterpret_cast<int>(this) >> kSmiTagSize;
}


Smi* Smi::FromInt(int value) {
 ASSERT(Smi::IsValid(value));
 // kSmiTagSize是類型標記,表示是小整形。值是1.kSmiTag是0
 return reinterpret_cast<Smi*>((value << kSmiTagSize) | kSmiTag);
}

             

我們看到Smi的實現(xiàn)比較簡單。我們接著看繼承關系中的下一個類HeapObject。HeapObject類是表示他的對象是在堆中分配內存的。下面是類定義。

   
     
 
    
    

// HeapObject is the superclass for all classes describing heap allocated
// objects.
class HeapObject: public Object {
public:
 // [map]: contains a Map which contains the objects reflective information.
 inline Map* map();
 inline void set_map(Map* value);

 // Converts an address to a HeapObject pointer.
 // 對象的地址+對象標記
 static inline HeapObject* FromAddress(Address address);

 // Returns the address of this HeapObject.
 // 對象的真正地址
 inline Address address();

 // Iterates over pointers contained in the object (including the Map)
 void Iterate(ObjectVisitor* v);

 // Iterates over all pointers contained in the object except the
 // first map pointer.  The object type is given in the first
 // parameter. This function does not access the map pointer in the
 // object, and so is safe to call while the map pointer is modified.
 void IterateBody(InstanceType type, int object_size, ObjectVisitor* v);

 // This method only applies to struct objects.  Iterates over all the fields
 // of this struct.
 void IterateStructBody(int object_size, ObjectVisitor* v);

 // Copy the body from the 'from' object to this.
 // Please note the two object must have the same map prior to the call.
 inline void CopyBody(JSObject* from);

 // Returns the heap object's size in bytes
 inline int Size();

 // Given a heap object's map pointer, returns the heap size in bytes
 // Useful when the map pointer field is used for other purposes.
 // GC internal.
 inline int SizeFromMap(Map* map);

 static inline Object* GetHeapObjectField(HeapObject* obj, int index);

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

 // Dispatched behavior.
 void HeapObjectShortPrint(StringStream* accumulator);

 // Layout description.
 // First field in a heap object is map.
 static const int kMapOffset = Object::kSize;
 static const int kSize = kMapOffset + kPointerSize;

protected:
 // helpers for calling an ObjectVisitor to iterate over pointers in the
 // half-open range [start, end) specified as integer offsets
 inline void IteratePointers(ObjectVisitor* v, int start, int end);
 // as above, for the single element at "offset"
 inline void IteratePointer(ObjectVisitor* v, int offset);

 // Computes the object size from the map.
 // Should only be used from SizeFromMap.
 int SlowSizeFromMap(Map* map);

private:
 DISALLOW_IMPLICIT_CONSTRUCTORS(HeapObject);
};

             

我們先看一下HeapObject類的對象的內存布局。

   
     
 
    
    

static const int kMapOffset = Object::kSize; // 0
static const int kSize = kMapOffset + kPointerSize; // kPointerSize表示一個指針變量的大小

             

下面我們開始HeapObject的實現(xiàn)。從之前的分析我們知道,v8很多對象的屬性不是和傳統(tǒng)的C++那樣,直接定義一個類型的。而且通過給屬性分配字節(jié)數(shù)去控制的。所以分析之前我們要先了解一個東西,就是如何讀寫對象的一個屬性。

   
     
 
    
    

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

// 讀取對象中某個屬性的值,指向對象地址空間的某個地址,轉成對象指針
#define READ_FIELD(p, offset) \
 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)))

// 給對象的某個屬性賦值
#define WRITE_FIELD(p, offset, value) \
 (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)) = value)

             

然后我們接著看HeapObject的實現(xiàn)。

   
     
 
    
    

// 堆對象的開始地址是一個Map對象
Map* HeapObject::map() {
 return reinterpret_cast<Map*> READ_FIELD(this, kMapOffset);
}

// 設置堆對象的map對象
void HeapObject::set_map(Map* value) {
 WRITE_FIELD(this, kMapOffset, value);
}

             

上面就是讀寫對象的某個屬性的例子(heapObject只有一個map屬性)。首先根據屬性在對象內存布局中的偏移找到屬性的地址,然后把他轉成Object對象(基類),然后把value寫進去,這里是一個Map對象。讀取的時候也是先轉成Object對象。然后再轉成Map對象。map屬性在所有對象中都是在第一個位置。

   
     
 
    
    

// 封裝過的地址,kHeapObjectTag表示是一個堆對象
HeapObject* HeapObject::FromAddress(Address address) {
 ASSERT_TAG_ALIGNED(address);
 return reinterpret_cast<HeapObject*>(address + kHeapObjectTag);
}

// 對象的真正地址
Address HeapObject::address() {
 return reinterpret_cast<Address>(this) - kHeapObjectTag;
}

             

上面是對對象地址的封裝,低一位表示類型。即堆對象。

到此,關于“js引擎HeapObject怎么實現(xiàn)”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續(xù)學習更多相關知識,請繼續(xù)關注億速云網站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI