js引擎v8源码解析之对象第一篇(基于v8 0.1.5)

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);
};

我们看到类中有一个静态属性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);
};

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);
}

我们看到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);
};

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

 static const int kMapOffset = Object::kSize; // 0
 static const int kSize = kMapOffset + kPointerSize; // kPointerSize表示一个指针变量的大小

下面我们开始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)

然后我们接着看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);
}

上面就是读写对象的某个属性的例子(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;
}

上面是对对象地址的封装,低一位表示类型。即堆对象。这篇先分析到这里,下一篇分析完Map类后再继续分析HeapObject类的实现,因为他用到了Map类。
在这里插入图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 要下载elasticsearchhead0.1.5谷歌插件,您可以按照以下步骤进行操作: 1. 首先,打开您的Chrome浏览器,并在地址栏中输入"Chrome网上应用店"。 2. 在搜索栏中,输入"elasticsearchhead0.1.5"并点击搜索按钮。 3. 在搜索结果中,应该能找到相关的插件。请确保选择的插件是"elasticsearchhead0.1.5"。 4. 点击插件的名称或图标,进入插件的详情页面。 5. 在详情页面,您将看到一个"添加至Chrome"的按钮。点击该按钮以安装插件。 6. 安装完成后,您将收到一个确认消息,并且插件的图标将出现在Chrome浏览器的工具栏或扩展程序区域。 7. 现在,您已成功下载并安装了elasticsearchhead0.1.5谷歌插件。 请注意,插件的下载和安装过程可能因不同的Chrome浏览器版本而有所不同。如果您遇到任何问题,请参考官方文档或在相关论坛寻求帮助。 ### 回答2: Elasticsearch Head是一个用于查看和管理Elasticsearch集群的插件。虽然插件名称中包含谷歌,但实际上Elasticsearch Head插件不是谷歌官方出品的插件,它是开源社区开发的一个插件。要下载Elasticsearch Head插件,可以按照以下步骤进行操作: 1. 打开谷歌浏览器,进入插件商店。 2. 在插件商店搜索框中输入“Elasticsearch Head”并回车。 3. 在搜索结果中选择合适的插件,通常是由mobz开发的插件。 4. 点击插件卡片上的“添加至Chrome”按钮,开始下载和安装插件。 5. 下载完成后,浏览器右上角会出现一个新的插件图标。 6. 点击插件图标,弹出一个新的页面,输入Elasticsearch集群的地址和端口号。 7. 输入正确的地址和端口号后,点击连接按钮,即可访问和管理Elasticsearch集群。 需要注意的是,Elasticsearch Head插件只适用于谷歌浏览器,其他浏览器可能无法使用该插件。此外,插件下载和使用需要一定的网络条件和相关知识,对于不熟悉的用户,可以参考相关教程或向社区寻求帮助。 ### 回答3: 要下载elasticsearch-head 0.1.5插件,可以按照以下步骤进行操作: 1. 打开谷歌浏览器,并在地址栏中输入“elasticsearch-head 0.1.5谷歌插件下载”。 2. 在搜索结果页面,可以找到elasticsearch-head插件的官方下载页面或第三方站点提供的下载链接。 3. 点击相关链接,进入插件下载页面。 4. 在插件下载页面,可以选择合适的插件版本,确认选择0.1.5版本。 5. 阅读下载页面上的相关信息,了解插件的功能和适用版本。 6. 确认无误后,点击下载按钮开始下载插件。 7. 下载完成后,根据提示,将下载的插件文件保存到本地计算机的特定文件夹中。 8. 在谷歌浏览器中,点击浏览器右上方三个点的菜单按钮,选择“更多工具”->“扩展程序”。 9. 在打开的扩展程序页面上,找到“elasticsearch-head”插件,并启用它。 10. 完成上述操作后,elasticsearch-head插件将被成功安装,并在浏览器的工具栏上显示图标,点击图标即可使用该插件进行Elasticsearch相关操作。 请注意,在下载和安装插件的过程中,要确保从官方或可信赖的第三方网站下载插件,以避免安全隐患。另外,确认插件的兼容性和适用版本,以确保它能够正常运行在您的谷歌浏览器上。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值