温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

js引擎HeapObject怎么实现

发布时间:2021-12-17 09:35:39 阅读:165 作者:iii 栏目:大数据
前端开发者测试专用服务器限时活动,0元免费领,库存有限,领完即止! 点击查看>>

这篇文章主要介绍“js引擎HeapObject怎么实现”,在日常操作中,相信很多人在js引擎HeapObject怎么实现问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”js引擎HeapObject怎么实现”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

v8的对象基类是Object。我们先看一下他的类定义。下面只列出重要的函数。

   
     
 
    
    // 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的函数  // 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:  // 禁止对象在堆中创建  /*      宏展开是      Object();      Object(const TypeName&);      void operator=(const Object&)  */  DISALLOW_IMPLICIT_CONSTRUCTORS(Object);};
   
     
 
    
    AI代码助手复制代码

我们看到类中有一个静态属性kSize,这个属性是标记该类的对象,属性需要占据的内存字节大小。下面我们看第一个继承于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);};
   
     
 
    
    AI代码助手复制代码

Smi的实现。主要有两个函数。

   
     
 
    
    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);}
   
     
 
    
    AI代码助手复制代码

我们看到Smi的实现比较简单。我们接着看继承关系中的下一个类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);};
   
     
 
    
    AI代码助手复制代码

我们先看一下HeapObject类的对象的内存布局。

   
     
 
    
    static const int kMapOffset = Object::kSize; // 0 static const int kSize = kMapOffset + kPointerSize; // kPointerSize表示一个指针变量的大小
   
     
 
    
    AI代码助手复制代码

下面我们开始HeapObject的实现。从之前的分析我们知道,v8很多对象的属性不是和传统的C++那样,直接定义一个类型的。而且通过给属性分配字节数去控制的。所以分析之前我们要先了解一个东西,就是如何读写对象的一个属性。

   
     
 
    
    // 获取对象某个属性的地址,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)
   
     
 
    
    AI代码助手复制代码

然后我们接着看HeapObject的实现。

   
     
 
    
    // 堆对象的开始地址是一个Map对象Map* HeapObject::map() {  return reinterpret_cast<Map*> READ_FIELD(this, kMapOffset);}// 设置堆对象的map对象void HeapObject::set_map(Map* value) {  WRITE_FIELD(this, kMapOffset, value);}
   
     
 
    
    AI代码助手复制代码

上面就是读写对象的某个属性的例子(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;}
   
     
 
    
    AI代码助手复制代码

上面是对对象地址的封装,低一位表示类型。即堆对象。

到此,关于“js引擎HeapObject怎么实现”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注亿速云网站,小编会继续努力为大家带来更多实用的文章!

亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

原文链接:https://my.oschina.net/u/4217331/blog/4379418

AI

开发者交流群×