Google V8 引擎 原理详解

V8 引擎概览

V8 引擎简介

Google V8 引擎使用 C++ 代码编写,实现了 ECMAScript 规范的第五版,可以运行在所有的主流

操作系统中,甚至可以运行在移动终端 ( 基于 ARM 的处理器,如 HTC G7 等 )。V8 最早被开发用以嵌入到 Google 的开源浏览器 Chrome 中,但是 V8 是一个可以独立的模块,完全可以嵌入您自己的应用,著名的 Node.js( 一个异步的服务器框架,可以在服务端使用 JavaScript 写出高效的网络服务器 ) 就是基于 V8 引擎的。

和其他 JavaScript 引擎一样,V8 会编译 / 执行 JavaScript 代码,管理内存,负责垃圾回收,与宿主语言的交互等。V8 的垃圾回收器采用了众多技术,使得其运行效率大大提高。通过暴露宿主对象 ( 变量,函数等 ) 到 JavaScript,JavaScript 可以访问宿主环境中的对象,并在脚本中完成对宿主对象的操作。


V8 引擎基本概念


图 1. V8 引擎基本概念关系图 ( 根据 Google V8 官方文档 )

handle

handle 是指向对象的指针,在 V8 中,所有的对象都通过 handle 来引用,handle 主要用于 V8 的垃圾回收机制。

在 V8 中,handle 分为两种:持久化 (Persistent)handle 和本地 (Local)handle,持久化 handle 存放在堆上,而本地 handle 存放在栈上。这个与 C/C++ 中的堆和栈的意义相同 ( 简而言之,堆上的空间需要开发人员自己申请,使用完成之后显式的释放;而栈上的为自动变量,在退出函数 / 方法之后自动被释放 )。持久化 handle 与本地 handle 都是 Handle 的子类。在 V8 中,所有数据访问均需要通过 handle。需要注意的是,使用持久化 handle 之后,需要显式的调用 Dispose() 来通知垃圾回收机制。

作用域 (scope)

scope 是 handle 的集合,可以包含若干个 handle,这样就无需将每个 handle 逐次释放,而是直接释放整个 scope。

在使用本地 handle 时,需要声明一个 HandleScope 的实例,scope 是 handle 的容器,使用 scope,则无需依次释放 handle。

 HandleScope handle_scope; 
 Local temp; 

上下文 (context)

context 是一个执行器环境,使用 context 可以将相互分离的 JavaScript 脚本在同一个 V8 实例中运行,而互不干涉。在运行 JavaScript 脚本是,需要显式的指定 context 对象。

数据及模板

由于 C++ 原生数据类型与 JavaScript 中数据类型有很大差异,因此 V8 提供了 Data 类,从 JavaScript 到 C++,从 C++ 到 JavaScrpt 都会用到这个类及其子类,比如:

 Handle Add(const Arguments& args){ 
	 int a = args[0]->Uint32Value(); 
	 int b = args[1]->Uint32Value(); 

	 return Integer::New(a+b); 
 } 

Integer 即为 Data 的一个子类。

V8 中,有两个模板 (Template) 类 ( 并非 C++ 中的模板类 ):对象模板 (ObjectTempalte) 和函数模板 (FunctionTemplate),这两个模板类用以定义 JavaScript 对象和 JavaScript 函数。我们在后续的小节部分将会接触到模板类的实例。通过使用 ObjectTemplate,可以将 C++ 中的对象暴露给脚本环境,类似的,FunctionTemplate 用以将 C++ 函数暴露给脚本环境,以供脚本使用。

初始化 context 是使用 V8 引擎所必需的过程,代码非常简单:

 Persistent context = Context::New(); 


V8 引擎使用示例

有了上面所述的基本概念之后,我们来看一下一个使用 V8 引擎的应用程序的基本流程:

  1. 创建 HandleScope 实例
  2. 创建一个持久化的 Context
  3. 进入 Context
  4. 创建脚本字符串
  5. 创建 Script 对象,通过 Script::Compile()
  6. 执行脚本对象的 Run 方法
  7. 获取 / 处理结果
  8. 显式的调用 Context 的 Dispose 方法

基本代码模板


清单 1. 代码模块
				
 #include  

 using namespace v8; 

 int main(int argc, char *argv[]) { 
	 // 创建一个句柄作用域 ( 在栈上 ) 
	 HandleScope handle_scope; 

	 // 创建一个新的上下文对象
	 Persistent context = Context::New(); 

	 // 进入上一步创建的上下文,用于编译执行 helloworld 
	 Context::Scope context_scope(context); 

	 // 创建一个字符串对象,值为'Hello, Wrold!', 字符串对象被 JS 引擎
	 // 求值后,结果为'Hello, World!'
	 Handle source = String::New("'Hello' + ', World!'"); 

	 // 编译字符串对象为脚本对象
	 Handle
                    
                    

你可能感兴趣的:(Node.js)