Javascript的V8引擎研究

1.针对上下文的Snapshot技术

什么是上下文(Contexts)?实际是JS应用程序的运行环境,避免应用程序的修改相互影响,例如一个页面js修改内置对象方法toString,不应该影响到另外页面。chrome浏览器每个process只有一个V8引擎实例,浏览器中的每个窗口、iframe都对应一个上下文。

V8启动时(在执行client js前),需要对全局上下文(第一个context)初始化,读取和解析自实现的内置JS代码(另一种技术,第2点),建立起function、array、string等内置对象及方法(参见bootstrapper中的Genesis类);后续context的创建只需要创建内置对象即可;为了减少全局上下文创建时的CPU、内存消耗,V8使用了Snapshot技术(参见v8_mksnapshot工程),(1)全局上下文初始化后,将目前堆内存序列化为字节代码,保存至磁盘文件;这个过程最重要的是空间地址和对象保存,具体操作(参见serialize文件)是:模拟线性内存空间的分配,遍历堆内存中的所有JS对象,并在模拟空间分配内存(实际是记录对象相对偏移地址),然后序列化对象大小、偏移地址、子对象、对象内容;最后是序列化global handler和stack上的context;(2)加载时,将该snapshot文件反序列化进内存,避免第一个上下文初始化,从而加快V8的启动。

2. Built-in的js代码

‍(1)利用JS自表达内置对象、方法,如上面代码实现Math.min方法,从而V8在实现代码转译时只需注重基本操作,以%符号开头的函数来自V8运行时函数(参见runtime和codegen);

(2)如何把js嵌入到V8中?利用python工具,将JS文件代码转为const char[]变量(字节代码),存到natives.cc;在执行期间首次访问相关方法时,取相关js代码进行lazy-compile。

(题外话:让面试者实现JS的一些常用函数,也是考察其基本功方法之一。)

3. 建立AST(Abstract SyntaxTree)时内存的管理

V8在建立AST后,对其进行汇编生成动态机器语言,所以AST在code generated后需要回收;针对AST建立过程中多结点内存申请和一次性回收的特点,V8使用了内存段链表管理,并结合scopelock模式,实现少数申请(Segment,8KB~1MB)、多次分配AST结点、一次回收各个Segment的管理方式,既能避免内存碎片,又可以避免遍历AST结点逐个回收内存。

‍4. CompileCache避免相同代码重复编译

对于一段JS代码,在开始进行词法分析前,会从编译缓存区CompilationCache查找该段代码是否已经被编译过,如果是,则直接取出编译过的机器代码,并返回,这样降低CPU的使用率,换来内存空间一定的占用;如果一个页面中重复加载JS文件,这方法的提速是很明显的;这种做法应该有平衡对比过。

下面先来看下这个缓存区的具体实现:

(1)数据结构采用CompilationCacheTableàHashTable,它为三种不同的JS语句类型(普通script,Eval语句,RegExp正则表达式),并使用了不太雅观的全局变量‍‍记录各种table。用三种table记录的原因:相同的script和Eval语句,编译出来的机器代码是不同的(来自annotation),因为Eval语句和执行期的上下文相关,所以缓存的时候还需要加上context作为key,所以三种类型生成的key方式不一样。一开始table数组的各个值为空,直到有编译代码需要加入时才生成hashtable。‍‍

(2)Key的生成,需要保证相同语句生成的key是稳定的:

a)普通script语句,使用StringHasher生成key,并保存到String对象中(因为该key不只是用到该处);生成规则是:当语句长度超过16K时,将直接使用它的长度作为key(经过偏移变为32位长度并确保为奇数),否则使用Bob Jenkins hash算法逐个读取语句的每个字符,计算组成一个uint的key;

b)Eval语句,同样使用到StringHasher,在这基础上结合上下文的share info(同样是语句hash,再加上语句的位置信息,详见StringSharedHashHelper)来更新hash值;

c)RegExp语句,同样使用到StringHasher,在这基础上结合RegExp的flag信息(i/g等)来更新hash值(详见RegExpObjectHash),具体见RegExpKey。

这几种key都派生自HashTableKey,后者定义了些公共接口,供hashtable统一使用。

(3)查找方式:使用hash算法,并用线性侦测来解决key的冲突,这是由HashTable继承自FixedArray的特性决定。

5. 属性的快速访问

C++、Java等语言有着类的概念,且属性、方法和类绑定在一起,访问时可根据对象地址+位移快速获得;而JS对象并没有类概念,它实际为hash map,属性可以动态增加、删除,而且在执行时才能获知对象类型。

V8没有像其它JS Engine使用词典结构或红黑树实现的map来管理属性,而是在每个对象附加一个指针,指向hidden class(如果第一次创建该类型对象,则新建hidden class);当对象每添加一个属性时,将新建一个class(记录了每个属性的位移/位置),而原来的class指向新class,即建立起一个hidden class的转换链表。

6. Heap堆内存管理

详见:

http://hi.baidu.com/hycjk/blog/item/20c9ecf87d3d1004d8f9fd6e.html

http://hi.baidu.com/hycjk/blog/item/86b2bf0e000d34ec37d1221e.html

7. Inline caching减少函数调用开销

详见http://en.wikipedia.org/wiki/Inline_caching。JS函数绑定发生在运行时,所以无法通过method tables定位函数入口;通过该技术可以记录函数入口,避免重复查找。

8. 一次性编译生成机器语言

一般JS engine会在AST生成后,将之编译为中间语言(bytecode),在执行时候再解析这些bytecode;Java 也同样编译为这些bytecode,再采用VM(实现跨平台)作为解释器,为了提高效能,Java采用混杂方式,把无关平台、常用的代码编译为机器代码。V8则是一次性把AST编译为机器语言。从assembler相关文件头的Copyright可以看出,这些不同平台(ia32, arm)下的编译器,原型来自Sun Microsystems。

附:

一、一些JS engine设计的考虑点:

1、 快速——解析、建构语法树、执行等多个方面,例如属性访问,避免字典查找;优化代码,编译生成动态机器码,而非按语句解释执行,且机器码可以存放cache后重复执行;

2、 小巧——占用内存低,分配回收内存及时和有效;

3、 安全——运行上下文切换和检查;

4、 容错性高

5、 易于与浏览器集成;

6、 跨平台;

7、 提供api接口;

8、 支持调试;

9、 其它细节:正则表达式的解析和实现、hash对象的实现(大多此类对象size较小),需要考虑JS本身特性和目的。

二、一些JS语言特性

1、对象为hash map,属性可以随时添加、修改、删除,对象类型在执行时才可知;

2、prototyp chain在执行时可以修改

3、eval能改变执行上下文

4、with动态添加对象到scope chain(作用域)

三、词法分析器

四、V8引用的第三方代码:

1、正则引擎:刚开始使用webkit项目中的JSCRE(基于剑桥大学Philip Hazel开发的,被广泛使用的PCRE库),后来替换为全新的Irregexp(Automata理论);

2、dtoa,double转为字符串,David M. Gay,under an MIT license;

3、Strongtalk assembler,是个以 C++ 封裝的 JIT (Just-In-Time) Assemble。

五、一些资料地址

http://code.google.com/intl/zh-CN/apis/v8/design.html

http://code.google.com/intl/zh-CN/apis/v8/embed.html

http://www.docin.com/p-46635034.html

http://www.greenpublishers.com/neat/200901/3coverstory.pdf

http://www.cnblogs.com/RicCC/archive/2008/02/15/javascript-object-model-execution-model.html

http://www.cnblogs.com/duguguiyu/archive/2008/10/02/1303095.html tagged pointer?

http://hllvm.group.javaeye.com/group/topic/17840

时间: 2024-10-27 04:52:02

Javascript的V8引擎研究的相关文章

V8 JavaScript引擎研究(一)简介

V8 JavaScript引擎简介 V8是Google公司的高效JavaScript引擎.它使用C++开发,完全开源,最著名的是使用在Chrome浏览器中作为JavaScript解析引擎. V8实现了ECMAScript-262标准,可以运行在Windows(XP及以上).Mac OS X(10.5及以上)以及使用IA-32.x64或ARM处理器的Linux系统. V8通常使用在浏览器中作为JavaScript的解析引擎,也可以嵌入到任何应用程序中使用. 基于C++的应用程序通过V8可以暴露任何

V8 JavaScript引擎研究(三)垃圾回收器的实现

V8垃圾回收机制简介 V8垃圾回收器的实现,是V8高效的一个非常重要的原因. V8在运行时自动回收不再需要使用的对象内存,也即是垃圾回收. V8使用了全暂停式(stop-the-world).分代式(generational).精确(accurate)等组合的垃圾回收机制,来确保更快的对象内存分配.更短的垃圾回收时触发的暂停以及没有内存碎片. V8的垃圾回收有如下几个特点: 当处理一个垃圾回收周期时,暂停所有程序的执行. 在大多数垃圾回收周期,每次仅处理部分堆中的对象,使暂停程序所带来的影响降至

JavaScript工作机制:V8 引擎内部机制及如何编写优化代码的5个诀窍

概述 JavaScript引擎是一个执行JavaScript代码的程序或解释器.JavaScript引擎可以被实现为标准解释器,或者实现为以某种形式将JavaScript编译为字节码的即时编译器. 下面是实现了JavaScript引擎的一个热门项目列表: V8- 开源,由Google开发,用C++编写的 Rhino - 由Mozilla基金所管理,开源,完全用Java开发 SpiderMonkey-第一个JavaScript引擎,最早用在Netscape Navigator上,现在用在Firef

JavaScript V8引擎

一.浏览器内核-渲染引擎 渲染,就是根据描述或者定义构建数学模型,生成图像的过程. 浏览器内核主要的作用是将页面转变成可视化/可听化的多媒体结果,通常也被称为渲染引擎.将HTML/CSS/JavaScript文本及其他相应的媒体类型资源文件转换成网页. 上图中实线框内模块是所有移植的共有部分,虚线框内不同的厂商可以自己实现.下面进行介绍: WebCore 是各个浏览器使用的共享部分,包括HTML解析器.CSS解析器.DOM和SVG等. JavaScriptCore是WebKit的默认引擎,在谷歌

V8引擎——详解

前言 JavaScript绝对是最火的编程语言之一,一直具有很大的用户群,随着在服务端的使用(NodeJs),更是爆发了极强的生命力.编程语言分为编译型语言和解释型语言两类,编译型语言在执行之前要先进行完全编译,而解释型语言一边编译一边执行,很明显解释型语言的执行速度是慢于编译型语言的,而JavaScript就是一种解释型脚本语言,支持动态类型.弱类型.基于原型的语言,内置支持类型.鉴于JavaScript都是在前端执行,而且需要及时响应用户,这就要求JavaScript可以快速的解析及执行.

探究JS V8引擎下的“数组”底层实现

本文首发于 vivo互联网技术 微信公众号? 链接:https://mp.weixin.qq.com/s/np9Yoo02pEv9n_LCusZn3Q 作者:李超 JavaScript 中的数组有很多特性:存放不同类型元素.数组长度可变等等,这与数据结构中定义的数组结构或者C++.Java等语言中的数组不太一样,那么JS数组的这些特性底层是如何实现的呢,我们打开V8引擎的源码,从中寻找到了答案.V8中对数组做了一层封装,使其有两种实现方式:快数组和慢数组,快数组底层是连续内存,通过索引直接定位,

Node.js背后的V8引擎优化技术

Node.js的执行速度远超Ruby.Python等脚本语言,这背后都是V8引擎的功劳.本文将介绍如何编写高性能Node.js代码.V8是Chrome背后的JavaScript引擎,因此本文的相关优化经验也适用于基于Chrome浏览器的JavaScript引擎. V8优化技术概述 V8引擎在虚拟机与语言性能优化上做了很多工作.不过按照Lars Bak的说法,所有这些优化技术都不是他们创造的,只是在前人的基础上做的改进. 隐藏类(Hidden Class) 为了减少JavaScript中访问属性所

V8引擎之从webcore到V8

这里不想讲什么是V8,请自行百度.自己搞webkit,故以后的V8学习研究都是基于webkit与V8的结合(目前没有研究blink,仅仅是把webkit官方的JavaScriptCore引擎换作了V8),不是纯粹的V8. 这里仅介绍从webcore的入口处 先从webcore的js入口说起,在html词法解析的时候,有一个这个函数: bool HTMLDocumentParser::canTakeNextToken(SynchronousMode mode, PumpSession& sessi

V8引擎介绍

V8是什么? V8是谷歌在德国研发中心开发的一个JavaScript引擎.开源并且用C++实现.可以用于运行于客户端和服务端的Javascript程序. V8设计的初衷是为了提高浏览器上JavaScript脚本的执行效率.为了提高速度,V8把JavaScript代码转换成更有效率的机器代码执行,而不像以往是通过解释器执行.像现在大多数的JavaScript引擎一样,比如SpiderMonkey 或者 Rhino (Mozilla),V8实现了一个JIT (Just-In-Time) 编译器,可以