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

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

  1. Node.js和Chrome V8 引擎了解

    说起Node就不得不先介绍一个Chrome V8 引擎. 随着Web相关技术的发展,JavaScript所要承担的工作也越来越多,早就超越了“表单验证”的范畴,这就更需要快速的解析和执行JavaScr ...

  2. JavaScript深入浅出第4课:V8引擎是如何工作的?

    摘要: 性能彪悍的V8引擎. <JavaScript深入浅出>系列: JavaScript深入浅出第1课:箭头函数中的this究竟是什么鬼? JavaScript深入浅出第2课:函数是一等 ...

  3. JavaScript引擎研究与C、C++与互调用(转)

    本文转自:ice6015的专栏.为什么有些招聘需要熟悉JS和C++,这或许就是原因. 1.  概要 JavaScript是一种广泛用于Web客户端开发的脚本语言,常用来控制浏览器的DOM树,给HTML ...

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

    概述 JavaScript引擎是一个执行JavaScript代码的程序或解释器.JavaScript引擎可以被实现为标准解释器,或者实现为以某种形式将JavaScript编译为字节码的即时编译器. 下 ...

  5. 使用 D8 分析 javascript 如何被 V8 引擎优化的

    在上一篇文章中我们讲了如何使用 GN 编译 V8 源码,文章最后编译完成的可执行文件并不是 V8,而是 D8.这篇我们讲一下如何使用 D8 调试 javascript 代码. 如果没有 d8,可以使用 ...

  6. How Javascript works (Javascript工作原理) (二) 引擎,运行时,如何在 V8 引擎中书写最优代码的 5 条小技巧

    个人总结: 一个Javascript引擎由一个标准解释程序,或者即时编译器来实现. 解释器(Interpreter): 解释一行,执行一行. 编译器(Compiler): 全部编译成机器码,统一执行. ...

  7. v8引擎详解(摘)-- V8引擎是一个JavaScript引擎实现

    随着Web相关技术的发展,JavaScript所要承担的工作也越来越多,早就超越了“表单验证”的范畴,这就更需要快速的解析和执行JavaScript脚本.V8引擎就是为解决这一问题而生,在node中也 ...

  8. JavaScript是如何工作的02:深入V8引擎&编写优化代码的5个技巧

    概述 JavaScript引擎是执行 JavaScript 代码的程序或解释器.JavaScript引擎可以实现为标准解释器,或者以某种形式将JavaScript编译为字节码的即时编译器. 以为实现J ...

  9. JavaScript(二)——在 V8 引擎中书写最优代码

    概述 一个 JavaScript 引擎就是一个程序或者一个解释程序,它运行 JavaScript 代码.一个 JavaScript 引擎可以用标准解释程序或者即时编译器来实现,即时编译器即以某种形式把 ...

随机推荐

  1. c++浅拷贝与深拷贝(LeetCode669)

    之前上C++/C#课上老师讲过这个问题,只不过当时主要是跟着老师的节奏与情形,从理论上基本了解了其原理.不过当自己写代码的时候,还是遇到了这个非常坑的问题.因此再来分析一下. 今天第一次做LeetCo ...

  2. Python入门:类与类的继承

    类,是一些有共同特征和行为事物的抽象概念的总和. 1. 定义一个类: 我们使用class来定义一个类,和之前说过的定义函数用def类似.在类里面给变量赋值时,专业术语称之为类的属性. 比如拿可口可乐来 ...

  3. pycharm安装jpype报错及解决方法

    安装jpype时发生报错: 按照提示去装了Microsoft visual C++,结果重新安装还是报错,根据https://blog.csdn.net/qq_38934189/article/det ...

  4. linux ls文件颜色和底色设置

    转帖 :linux ls文件颜色和底色设置 白色:表示普通文件蓝色:表示目录绿色:表示可执行文件红色:表示压缩文件浅蓝色:链接文件红色闪烁:表示链接的文件有问题黄色:表示设备文件灰色:表示其他文件 这 ...

  5. python自动化之正则

    import re phoneNumRegex=re.compile(r'\d\d\d-\d\d\d-\d\d\d\d') mo=phoneNumRegex.search('My number is ...

  6. java 对象的解释过程

  7. JDBC数据库连接技术

    [学习笔记]JDBC数据库连接技术(Java Database Connectivity) 一.JDBC简介 Java是通过JDBC技术实现对各种数据库的访问的,JDBC是Java数据库连接技术的简称 ...

  8. 题解 P1208 【[USACO1.3]混合牛奶 Mixing Milk】

    其实根本没有一楼dalao描述的那么麻烦...... 一楼dalao其实吧,采用了一种纯属模拟的方式. 下面是我的大跃进思想 但是一个个地做减法是不是太慢了?(大跃进思想) 于是我们是不是可以直接进行 ...

  9. 利用VRID/VMAC实现更安全的netscaler HA故障切换

    利用VRID/VMAC实现更安全的netscaler HA故障切换 virtual MAC在故障切换(failover)中的作用.    在一个HA模式中,首要节点(primary node)拥有所有 ...

  10. STL 算法介绍

    STL 算法介绍 算法概述 算法部分主要由头文件<algorithm>,<numeric>和<functional>组成.        <algorithm ...