温馨提示×

温馨提示×

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

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

js引擎HeadNumber类是怎么实现的

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

本篇内容介绍了“js引擎HeadNumber类是怎么实现的”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

1 HeadNumber

HeadNumber类的代码比较少。

   
     
 
    
    // The HeapNumber class describes heap allocated numbers that cannot be// represented in a Smi (small integer)// 存储了数字的堆对象class HeapNumber: public HeapObject { public:  // [value]: number value.  inline double value();  inline void set_value(double value);  // Casting.  static inline HeapNumber* cast(Object* obj);  // Dispatched behavior.  Object* HeapNumberToBoolean();  // Layout description.  // kSize之前的空间存储map对象的指针  static const int kValueOffset = HeapObject::kSize;  // kValueOffset - kSize之间存储数字的值  static const int kSize = kValueOffset + kDoubleSize; private:  DISALLOW_IMPLICIT_CONSTRUCTORS(HeapNumber);};
   
     
 
    
    AI代码助手复制代码

我们看看他的实现。

   
     
 
    
    // 读出double类型的值#define READ_DOUBLE_FIELD(p, offset) \  (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)))// 写入double类型的值#define WRITE_DOUBLE_FIELD(p, offset, value) \  (*reinterpret_cast<double*>(FIELD_ADDR(p, offset)) = value)// 读写属性的值double HeapNumber::value() {  return READ_DOUBLE_FIELD(this, kValueOffset);}// 写double值到对象void HeapNumber::set_value(double value) {  WRITE_DOUBLE_FIELD(this, kValueOffset, value);}Object* HeapNumber::HeapNumberToBoolean() {  // NaN, +0, and -0 should return the false object  switch (fpclassify(value())) {    case FP_NAN:  // fall through    case FP_ZERO: return Heap::false_value();    default: return Heap::true_value();  }}
   
     
 
    
    AI代码助手复制代码

还有一个函数就是cast,实现如下:

   
     
 
    
    CAST_ACCESSOR(HeapNumber)#define CAST_ACCESSOR(type)                     \  type* type::cast(Object* object) {            \    ASSERT(object->Is##type());                 \    return reinterpret_cast<type*>(object);     \CAST_ACCESSOR(HeapNumber);宏展开后HeapNumber* HeapNumber::cast(Object* object) {            \    ASSERT(object->IsHeapNumber());                 \    return reinterpret_cast<HeapNumber*>(object);     \
   
     
 
    
    AI代码助手复制代码

至此HeapNumber分析完了。接着看下一个类Array。

2 Array

   
     
 
    
    // Abstract super class arrays. It provides length behavior.class Array: public HeapObject { public:  // [length]: length of the array.  inline int length();  inline void set_length(int value);  // Convert an object to an array index.  // Returns true if the conversion succeeded.  static inline bool IndexFromObject(Object* object, uint32_t* index);  // Layout descriptor.  static const int kLengthOffset = HeapObject::kSize;  static const int kHeaderSize = kLengthOffset + kIntSize; private:  DISALLOW_IMPLICIT_CONSTRUCTORS(Array);};
   
     
 
    
    AI代码助手复制代码

我们发现数组的对象内存布局中,只有一个属性。就是保存length大小的。首先看看读写length属性的实现。

   
     
 
    
    #define INT_ACCESSORS(holder, name, offset)                             \  int holder::name() { return READ_INT_FIELD(this, offset); }           \  void holder::set_##name(int value) { WRITE_INT_FIELD(this, offset, value); }// 定义数组的length和set_length函数,属性在对象的偏移的kLengthOffset,紧跟着map指针INT_ACCESSORS(Array, length, kLengthOffset);
   
     
 
    
    AI代码助手复制代码

再继续看IndexFromObject的实现。

   
     
 
    
    bool Array::IndexFromObject(Object* object, uint32_t* index) {  if (object->IsSmi()) {    int value = Smi::cast(object)->value();    if (value < 0) return false;    *index = value;    return true;  }  if (object->IsHeapNumber()) {    double value = HeapNumber::cast(object)->value();    uint32_t uint_value = static_cast<uint32_t>(value);    if (value == static_cast<double>(uint_value)) {      *index = uint_value;      return true;    }  }  return false;}
   
     
 
    
    AI代码助手复制代码

该函数就是把一个对象(底层是表示数字的)转成一个数组索引。数组类也分析完了。我们继续。

3 ByteArray

   
     
 
    
    // ByteArray represents fixed sized byte arrays.  Used by the outside world,// such as PCRE, and also by the memory allocator and garbage collector to// fill in free blocks in the heap.class ByteArray: public Array { public:  // Setter and getter.  inline byte get(int index);  inline void set(int index, byte value);  // Treat contents as an int array.  inline int get_int(int index);  /*    ByteArray类没有定义自己的属性,他是根据length算出对象的大小,    然后在分配内存的时候,多分配一块存储数组元素的内存    const int kObjectAlignmentBits = 2;    const int kObjectAlignmentMask = (1 << kObjectAlignmentBits) - 1;    #define OBJECT_SIZE_ALIGN(value)  ((value + kObjectAlignmentMask) & ~kObjectAlignmentMask)    由此可知,按四个字节对齐。OBJECT_SIZE_ALIGN的作用的是不够4字节的,会多分配几个字节,使得按四字节对齐。~kObjectAlignmentMask是低两位是0,即按四字节对齐。比如value已经4字节对齐了,则(4 + 0 +3) & ~3 =4,如果value没有对齐,假设是5,则(4 + 1 +3) & ~3 = 8;如果value等于6,(4 + 2 + 3) & ~3 = 8;以此类推。  */  static int SizeFor(int length) {    return kHeaderSize + OBJECT_SIZE_ALIGN(length);  }  // We use byte arrays for free blocks in the heap.  Given a desired size in  // bytes that is a multiple of the word size and big enough to hold a byte  // array, this function returns the number of elements a byte array should  // have.  static int LengthFor(int size_in_bytes) {    ASSERT(IsAligned(size_in_bytes, kPointerSize));    ASSERT(size_in_bytes >= kHeaderSize);    return size_in_bytes - kHeaderSize;  }  // Returns data start address.  inline Address GetDataStartAddress();  // Returns a pointer to the ByteArray object for a given data start address.  static inline ByteArray* FromDataStartAddress(Address address);  // Casting.  static inline ByteArray* cast(Object* obj);  // Dispatched behavior.  int ByteArraySize() { return SizeFor(length()); } private:  DISALLOW_IMPLICIT_CONSTRUCTORS(ByteArray);};
   
     
 
    
    AI代码助手复制代码

在分析实现之前我们先看一下ByteArray的对象是怎么被分配的。

   
     
 
    
    Handle<ByteArray> Factory::NewByteArray(int length) {  ASSERT(0 <= length);  CALL_HEAP_FUNCTION(Heap::AllocateByteArray(length), ByteArray);}Object* Heap::AllocateByteArray(int length) {  int size = ByteArray::SizeFor(length);  AllocationSpace space = size > MaxHeapObjectSize() ? LO_SPACE : NEW_SPACE;  Object* result = AllocateRaw(size, space);  if (result->IsFailure()) return result;  reinterpret_cast<Array*>(result)->set_map(byte_array_map());  reinterpret_cast<Array*>(result)->set_length(length);  return result;}
   
     
 
    
    AI代码助手复制代码

我们看到,首先通过ByteArray::SizeFor算出对象所需的内存大小size。然后分配一块大小为size的内存。然后返回这块内存的地址。这时候我们就可以使用这块内存。我们看看怎么使用的。内存布局如下。

js引擎HeadNumber类是怎么实现的

   
     
 
    
    byte ByteArray::get(int index) {  ASSERT(index >= 0 && index < this->length());  // 根据索引返回数组中对应元素的值,kHeaderSize是第一个元素的地址,kCharSize是1,即一个字节  return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);}void ByteArray::set(int index, byte value) {  ASSERT(index >= 0 && index < this->length());  WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value);}// 把四个元素(四个字节)的内容作为一个值。即ByteArray变成IntArrayint ByteArray::get_int(int index) {  ASSERT(index >= 0 && (index * kIntSize) < this->length());  return READ_INT_FIELD(this, kHeaderSize + index * kIntSize);}ByteArray* ByteArray::FromDataStartAddress(Address address) {  ASSERT_TAG_ALIGNED(address);  return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag);}// 返回数组元素的首地址,地址的低位是用作标记,要先减掉。kHeaderSize是第一个元素在对象内存空间的偏移Address ByteArray::GetDataStartAddress() {  /*    typedef uint8_t byte;    typedef byte* Address;  */  return reinterpret_cast<Address>(this) - kHeapObjectTag + kHeaderSize;}
   
     
 
    
    AI代码助手复制代码

“js引擎HeadNumber类是怎么实现的”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注亿速云网站,小编将为大家输出更多高质量的实用文章!

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

向AI问一下细节

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

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

AI

开发者交流群×