Chrome V8基础(一)
字数 1895 2025-08-09 22:00:49

Chrome V8 引擎基础解析

一、V8 引擎概述

Chrome V8 是一个由 Google 开发的高性能 JavaScript 引擎,采用 C++ 编写,用于执行 JavaScript 代码。它是 Google Chrome 浏览器的核心组件之一,也用于 Node.js 等环境。

1.1 V8 在 Chrome 架构中的位置

+------------------------------------------------------------------------------------------+
| Google Chrome                                                                            |
|                                                                                          |
| +----------------------------------------+          +------------------------------+     |
| | Google V8                              |          |            WebAPIs           |     |
| | +-------------+ +---------------+      |          |                              |     |
| | |    Heap     | |     Stack     |      |          |                              |     |
| | |             | |               |      |          |                              |     |
| | +-------------+ +---------------+      |          |                              |     |
| |                                        |          |                              |     |
| +----------------------------------------+          +------------------------------+     |
|                                                                                          |
| +---------------------+     +---------------------------------------+                    |
| |     Event loop      |     |          Task/Callback queue          |                    |
| |                     |     |                                       |                    |
| +---------------------+     +---------------------------------------+                    |
|                             +---------------------------------------+                    |
|                             |          Microtask queue              |                    |
|                             |                                       |                    |
|                             +---------------------------------------+                    |
|                                                                                          |
+------------------------------------------------------------------------------------------+

二、V8 内存机制

V8 的内存管理是其核心功能之一,JavaScript 中声明的变量都由 V8 的内存机制管理,开发者无法直接管理这些内存。

2.1 内存分区

V8 的堆内存分为以下几个主要部分:

+-----------------------------------------------------------------------------------+
|   Young Generation                  Old Generation          Large Object space    |
|  +-------------+--------------+  +-----------+-------------+ +------------------+ |
|  |        NEW_SPACE           |  | MAP_SPACE | OLD_SPACE   | | LO_SPACE         | |
|  +-------------+--------------+  +-----------+-------------+ +------------------+ |
|  |  from_Space   | to_Space   |                                                   |
|  +-------------+--------------+                                                   |
|  +-------------+                 +-----------+               +------------------+ |
|  | NEW_LO_SPACE|                 | CODE_SPACE|               | CODE_LO_SPACE    | |
|  +-------------+                 +-----------+               +------------------+ |
|                                                                                   |
|   Read-only                                                                       |
|  +--------------+                                                                 |
|  | RO_SPACE     |                                                                 |
|  +--------------+                                                                 |
+-----------------------------------------------------------------------------------+
  • 新生代内存区 (Young Generation): 存放基本数据对象,区域小但回收频繁
  • 老生代指针区 (Old Generation): 存放从新生代晋升过来的对象的指针
  • 老生代数据区: 存放老生代对象的数据
  • 大对象区 (Large Object space): 存放体积超过其他区大小的对象
  • 代码区 (Code space): 存放 JIT 编译后的代码对象,唯一拥有执行权限的内存区
  • Cell区、属性Cell区、Map区: 存放 Cell、属性Cell和Map,每个区域存放相同大小的元素

2.2 新生代内存回收 (Scavenge 算法)

新生代内存使用 Scavenge 算法进行回收,其核心思想是将内存一分为二:

ptrs   from_space (evacuation)   to_space
      +----------+            +------------+
----->|marked: * | ---------->|marked: s   |       (s=survived)
      +----------+            +------------+
      |marked:   |      ----->|marked: s   |
      +----------+     /      +------------+
----->|marked: * | ----       |            |
      +----------+            +------------+
      |marked:   |            |            |
      +----------+            +------------+
      |marked:   |            |            |
      +----------+            +------------+

特点:

  1. 内存分为两个 Semispace:From 空间和 To 空间
  2. 分配对象时使用 From 空间
  3. 垃圾回收时检查 From 空间中的存活对象,复制到 To 空间
  4. 回收完成后交换 From 和 To 空间角色

对象晋升条件

  1. 对象已经经历过一次新生代清理
  2. To 空间使用超过 25%

2.3 老生代内存回收

老生代内存主要使用 Mark-Sweep 和 Mark-Compact 结合的方式进行回收:

 Page 1              FreeList                        Page 1
+----------+        +--------------+        +------------+
|marked: * |---\    |    Size 1    |    --------|marked: s   |
+----------+    \   | +----------+ |   /    +------------+
|marked:   |     ---|>|__________| |  /        -|marked: s   |
+----------+        | |__________|<|--        / +------------+
|marked: * |--\     | |__________| |         /  |            |
+----------+   \    |    Size 2    |        /   +------------+
|marked:   |    \   | +----------+ |       /    |            |
+----------+     ---|>|__________|<|------- +------------+
|marked:   |        | |__________| |        |            |
+----------+        | |__________| |            +------------+
                    +--------------+
  • Mark-Sweep (标记清除):

    1. 标记阶段:遍历堆中所有对象,标记存活对象
    2. 清除阶段:清除未被标记的对象
    3. 优点:效率高(只处理死亡对象)
    4. 缺点:产生内存碎片
  • Mark-Compact (标记整理):

    1. 在 Mark-Sweep 基础上增加压缩步骤
    2. 让存活对象尽可能往内存区域前面靠
    3. 优点:避免内存碎片
    4. 缺点:效率比 Mark-Sweep 低
  • 惰性清理: GC 延迟清理死掉的对象,根据需要清理

三、V8 核心概念

3.1 隔离实例 (Isolate)

Isolate 是 V8 引擎的实例,包含完全独立的各种状态(堆管理、垃圾回收等)。一个实例生成的任何对象不能在另一个实例中使用。

// 创建 Isolate 实例
v8::Isolate::CreateParams create_params;
v8::Isolate* isolate = v8::Isolate::New(create_params);

3.2 上下文 (Context)

Context 定义 JavaScript 执行环境,相当于沙箱化的执行上下文环境:

v8::Isolate* isolate = ...;
v8::Local<v8::Context> context = v8::Context::New(isolate);

3.3 脚本 (Script)

Script 对象包含已编译的 JavaScript 代码,与 Context 绑定:

v8::Local<v8::Context> context = ...;
v8::Local<v8::String> source = 一段JavaScript代码;

// 编译
v8::Local<v8::Value> result = v8::Script::Compile(context, source).ToLocalChecked();

// 执行
v8::Local<v8::Value> result = Script->Run(context).ToLocalChecked();

四、句柄 (Handle) 系统

句柄是 V8 中的重要概念,提供对堆内存中 JavaScript 数据对象的引用。GC 会更新句柄引用,确保对象移动后仍能正确访问。

4.1 句柄类型

  1. 本地句柄 (v8::Local): 存在于栈内存中,生命周期由句柄作用域决定
  2. 持久句柄 (v8::Persistent): 提供堆内存中对象的长期引用
  3. 永生句柄 (v8::Eternal): 程序生命周期内不会被删除
  4. 待实本地句柄 (MaybeLocal): 可能为空的本地句柄

4.2 本地句柄 (Local)

template <class T> class Local { 
private:
  T* val_
};

特点:

  • 通过 . 访问句柄方法
  • 通过 *-> 操作符访问对象实体
  • 可使用 AsCast 进行类型转换

4.3 持久句柄 (Persistent)

持久句柄分为:

  • 一般持久句柄 (v8::Persistent)
  • 唯一持久句柄 (v8::UniquePersistent)

创建持久句柄:

Local<Number> local = Number::New(isolate, 2333);
Persistent<Number> persistent_handle(isolate, local);

4.4 待实本地句柄 (MaybeLocal)

用于处理可能返回空句柄的情况:

MaybeLocal<String> s = x.ToString();

if(!s.IsEmpty()){
    Local<String> _s = s.ToLocalChecked();
}

五、总结

V8 引擎通过精细的内存管理和高效的垃圾回收算法实现了 JavaScript 的高性能执行。其核心特点包括:

  1. 分代式垃圾回收:新生代使用 Scavenge 算法,老生代使用 Mark-Sweep 和 Mark-Compact
  2. 隔离实例机制:确保不同实例状态完全独立
  3. 灵活的句柄系统:管理 JavaScript 对象的生命周期
  4. 高效的执行环境:通过 JIT 编译和优化的内存管理提升性能

理解这些基础概念对于深入掌握 V8 工作原理和浏览器安全机制至关重要。

Chrome V8 引擎基础解析 一、V8 引擎概述 Chrome V8 是一个由 Google 开发的高性能 JavaScript 引擎,采用 C++ 编写,用于执行 JavaScript 代码。它是 Google Chrome 浏览器的核心组件之一,也用于 Node.js 等环境。 1.1 V8 在 Chrome 架构中的位置 二、V8 内存机制 V8 的内存管理是其核心功能之一,JavaScript 中声明的变量都由 V8 的内存机制管理,开发者无法直接管理这些内存。 2.1 内存分区 V8 的堆内存分为以下几个主要部分: 新生代内存区 (Young Generation) : 存放基本数据对象,区域小但回收频繁 老生代指针区 (Old Generation) : 存放从新生代晋升过来的对象的指针 老生代数据区 : 存放老生代对象的数据 大对象区 (Large Object space) : 存放体积超过其他区大小的对象 代码区 (Code space) : 存放 JIT 编译后的代码对象,唯一拥有执行权限的内存区 Cell区、属性Cell区、Map区 : 存放 Cell、属性Cell和Map,每个区域存放相同大小的元素 2.2 新生代内存回收 (Scavenge 算法) 新生代内存使用 Scavenge 算法进行回收,其核心思想是将内存一分为二: 特点: 内存分为两个 Semispace:From 空间和 To 空间 分配对象时使用 From 空间 垃圾回收时检查 From 空间中的存活对象,复制到 To 空间 回收完成后交换 From 和 To 空间角色 对象晋升条件 : 对象已经经历过一次新生代清理 To 空间使用超过 25% 2.3 老生代内存回收 老生代内存主要使用 Mark-Sweep 和 Mark-Compact 结合的方式进行回收: Mark-Sweep (标记清除) : 标记阶段:遍历堆中所有对象,标记存活对象 清除阶段:清除未被标记的对象 优点:效率高(只处理死亡对象) 缺点:产生内存碎片 Mark-Compact (标记整理) : 在 Mark-Sweep 基础上增加压缩步骤 让存活对象尽可能往内存区域前面靠 优点:避免内存碎片 缺点:效率比 Mark-Sweep 低 惰性清理 : GC 延迟清理死掉的对象,根据需要清理 三、V8 核心概念 3.1 隔离实例 (Isolate) Isolate 是 V8 引擎的实例,包含完全独立的各种状态(堆管理、垃圾回收等)。一个实例生成的任何对象不能在另一个实例中使用。 3.2 上下文 (Context) Context 定义 JavaScript 执行环境,相当于沙箱化的执行上下文环境: 3.3 脚本 (Script) Script 对象包含已编译的 JavaScript 代码,与 Context 绑定: 四、句柄 (Handle) 系统 句柄是 V8 中的重要概念,提供对堆内存中 JavaScript 数据对象的引用。GC 会更新句柄引用,确保对象移动后仍能正确访问。 4.1 句柄类型 本地句柄 (v8::Local) : 存在于栈内存中,生命周期由句柄作用域决定 持久句柄 (v8::Persistent) : 提供堆内存中对象的长期引用 永生句柄 (v8::Eternal) : 程序生命周期内不会被删除 待实本地句柄 (MaybeLocal) : 可能为空的本地句柄 4.2 本地句柄 (Local) 特点: 通过 . 访问句柄方法 通过 * 和 -> 操作符访问对象实体 可使用 As 或 Cast 进行类型转换 4.3 持久句柄 (Persistent) 持久句柄分为: 一般持久句柄 (v8::Persistent) 唯一持久句柄 (v8::UniquePersistent) 创建持久句柄: 4.4 待实本地句柄 (MaybeLocal) 用于处理可能返回空句柄的情况: 五、总结 V8 引擎通过精细的内存管理和高效的垃圾回收算法实现了 JavaScript 的高性能执行。其核心特点包括: 分代式垃圾回收:新生代使用 Scavenge 算法,老生代使用 Mark-Sweep 和 Mark-Compact 隔离实例机制:确保不同实例状态完全独立 灵活的句柄系统:管理 JavaScript 对象的生命周期 高效的执行环境:通过 JIT 编译和优化的内存管理提升性能 理解这些基础概念对于深入掌握 V8 工作原理和浏览器安全机制至关重要。