[资料] [链接帖] 各JavaScript引擎的简介,及相关资料/博客收集帖

RednaxelaFX 2013-04-20
之前一直有同学在问,于是开个帖来收集JavaScript引擎的资料链接。每个JavaScript引擎先简单写点我对它的了解,然后是资料和博客的链接。
链接顺序按其描述的功能在产品中出现的时间从新到旧排。
最终能做成个まとめ就好了,hmm。

慢慢更新。把以前收集的链接都转到这帖来。先从我写的发在自己博客和HLLVM群组这边的开始。欢迎回帖补充资料或提问讨论。

读的时候请考虑到发文时间——所有资料都只能代表当时的状况。

以前写过篇杂谈,虽然没直接写JavaScript引擎的具体实现,不过或许会对入门有帮助:虚拟机随谈(一):解释器,树遍历解释器,基于栈与基于寄存器,大杂烩
(抱歉,这系列后面烂尾了没发出来…)
在另一帖里我简单写过几种实现解释器的方式的对比,字节码的作用之类:CPython能否用V8的方式优化性能

有一点想补充的是:关于基于栈与基于寄存器的字节码的对比,如果在字节码的后面是一个非常简易的初级JIT编译器,那基于寄存器的字节码未必比基于栈的字节码有多少优势:
基于栈的字节码的操作数栈(或者叫表达式栈)暗含着表达式中某些临时值的生命周期,而基于寄存器的字节码则要显式分析所有值的生命周期。这会影响到简易寄存器分配的效率。
不过如果前面生成字节码的编译器有做一定优化,那基于寄存器的字节码还是可以重夺优势:假设有条件离线对基于寄存器的字节码做优化,那可以尝试调整其虚拟寄存器的分配,让估计更“热”的值放在更靠近编号为0的虚拟寄存器里,然后在简易JIT编译器里的寄存器分配就可以固定的把虚拟寄存器映射到真实寄存器上,这就比较好。

==========================================================================

Ecma-262 ECMAScript 5.1

Annotated ECMAScript 5.1

ECMAScript 6 draft

Ecma-402 ECMAScript Internationalization API

Ecma-404 The JSON Data Interchange Format

还有一个没怎么见人提起的 Ecma-327 ECMAScript Compact Profile (ES-CP)

看看Mozilla的JavaScript介绍页面上都提到了哪些JavaScript引擎:
https://developer.mozilla.org/en-US/docs/JavaScript/About_JavaScript

==========================================================================

JavaScript与“无处不在的计算”或者说“普适计算”
ubiquitous computing

在学习JavaScript,最好的办法就是多写代码多做实验。现在几乎走到哪儿都能找到设备运行JavaScript,比当年的BASIC还要通用。

在桌面上,主流浏览器(Chrome、Firefox、IE等)都自带开发者控制台,里面就可以直接试用JavaScript。

不在桌面上?在网页上试用JavaScript的好地方:
http://jsconsole.com/
实际上就是在网页中以控制台的形式暴露出浏览器内嵌的JavaScript引擎的功能。在平板电脑之类的不便于打开浏览器自身的控制台的地方特别好用。

iOS上可以试试Jsany - JavaScript Anywhere

与他人在线交流代码的好地方:
http://codechat.net/

==========================================================================

现代JavaScript引擎都有哪些特征呢?跟以前的JavaScript引擎有怎样的差别,为什么变快了那么多?这里简单写下我的理解吧。

有很多同学可能会想从JavaScript引擎的源码着手一探究竟。这里也顺便介绍一下JavaScript引擎大致的组成部分与工作流程。了解这其中涉及的各种术语都是什么意思的话,读源码就能事半功倍,很多时候光看文件名就足以定位到自己关心的那部分实现。 <- TODO

早期JavaScript引擎的实现普遍跟同时代的其它脚本语言一样,比较“偷懒”。反正是“脚本语言”,当时的JavaScript脚本通常只包含很简单的逻辑,只运行很短时间就完事。没啥性能压力,得不到足够的重视与开发资源,性能自然是好不到哪里去,却也足以满足当时的需求。

非常早期的“Mocha”引擎实现得确实非常偷懒。字节码解释器、引用计数方式的自动内存管理、fat discriminated union形式的值表现形式。现在随便找本教写玩具语言实现的书上或许就会这么教…但只能用来写玩具 犀牛书第4版写了点JavaScript与引用计数的历史
到1996年,Brendan Eich新写的SpiderMonkey已经改为使用mark-and-sweep GC、tagged value。

于是其实早期的两个主要的JavaScript引擎实现,Mozilla SpiderMonkey和Microsoft JScript其实都一直在用mark-and-sweep GC。也没啥别的主流JavaScript引擎用过引用计数方式来实现自动内存管理的。这点别被忽悠了。在叫得出名字的JavaScript引擎里只有quad-wheel(没听说过么?不奇怪,非主流嘛)是用引用计数方式实现自动内存管理的。
(老版本IE里JScript虽说是有因为循环引用而导致内存泄漏的问题,但那不是因为JScript自身用引用计数。问题出在JScript与DOM交互的边界上:IE的DOM节点(及其它host对象)是COM对象,而COM对象自身是引用计数的。在JS一侧GC时DOM节点被看作根节点,所以被DOM节点引用的JS对象不会死;反过来,被JS对象引用的DOM节点的引用计数不为0所以也不会死。这导致JScript与DOM交互时有可能被连累引发循环引用->内存泄漏的问题。
IE9/Chakra里已经通过把DOM对象变成由JavaScript一侧的GC来管理解决了这个问题。)

几种较老的JavaScript引擎的特征:
SpiderMonkey JScript KJS
实现语言 C C++ C++
执行模式 解释执行 解释执行 解释执行
解释器 字节码解释器:基于栈的字节码 字节码解释器:基于栈的字节码 树遍历解释器
动态编译器
自动内存管理 mark-and-sweep mark-and-sweep mark-and-sweep
对象布局 ? 基本上是HashTable ?
针对密集数组的优化 ? 无 (JScript < 5.7);有(JScript 5.8) ?
Inline-cache ? ? ?
值表现形式 tagged-value 堆对象 堆对象
Function.prototype.toString() 从字节码反编译 ? ?

(几个术语:
树遍历解释器:tree-walking interpreter。遍历抽象语法树来解释执行的解释器。
对象布局: object representation 或者 object layout。指在堆上分配的JavaScript对象的在内存中的布局。
值表现形式: value representation。注意跟“对象布局”说的不是一件事。这个指的是原始类型数据、指向堆上分配的对象的指针之类的值的表现形式。对某些JavaScript引擎来说这是指“JSValue”背后在内存中的表现形式。

TODO 加上对parser的描述
SpiderMonkey KJS JavaScriptCore V8 Managed JScript
手写纯递归下降式 bison生成LALR(1) bison生成的LALR(1) 手写的递归下降+运算符优先级混合式 手写的纯运算符优先级式


早期JavaScript引擎得到的投入实在不足,而当时的Java虚拟机(JVM)却得到了大量资源实现各种优化,包括JIT编译器之类。这使得用Java写的Rhino一度能比用C写的SpiderMonkey跑得还快,因为Rhino得益于JVM里优秀的JIT编译器和GC,而SpiderMonkey还在用简易的解释器和GC。

这个阶段中,JavaScript对象的布局或者说表现方式通常可以叫做“property bag”,本质上就跟hashmap一样。

在Google推出V8之后,业界受到巨大冲击。V8的性能远高于当时所有其它JavaScript引擎,可以有效支撑起当时兴起的大量使用JavaScript的Web应用。
各大JavaScript引擎的实现者都坐不住了,像打了鸡血似的使劲优化优化再优化。先是把已在其它HLLVM上得到充分验证的优化技术引入到JavaScript引擎中,然后再针对JavaScript语言的特点做专项优化。

现在(2013-04)几种主流的JavaScript引擎的特征:
V8 SpiderMonkey Chakra Nitro Nashorn
实现语言 C++/汇编 C++ C++ C++/汇编 Java
执行模式 纯编译: 两层编译 解释/编译混合式: 3层执行模式 解释/编译混合: 2层执行模式,后台编译 解释/编译混合: 3层执行模式 纯编译
解释器 字节码解释器 字节码解释器:基于寄存器的字节码 字节码解释器 LLInt:基于寄存器的字节码
动态编译器 初级编译器 + 优化编译器 初级编译器 Baseline + 优化编译器 IonMonkey 初级编译器 method JIT + 优化编译器 DFG JIT
自动内存管理 分代式GC: 初生代: copying收集器; 年老代: 增量式mark-and-sweep, 可选compact 分代式GC 分代式GC: 初生代: copying收集; 年老代: 并发式mark-and-sweep 分代式GC 依赖于底层JVM的GC
对象布局 紧凑+隐藏类 Map 紧凑+隐藏类 Shape 紧凑+隐藏类 紧凑+隐藏类 Structure 紧凑+隐藏类 PropertyMap
针对密集数组的优化
Inline-cache MIC/PIC PIC PIC PIC MIC/PIC
值表现形式 tagged-pointer / IEEE 754 double / integer pun-boxing tagged-value NaN-boxing   堆对象 / integer
正则表达式 编译 Irregexp 编译 编译 编译 WREC 混合
Function. prototype. toString() 保留源码原文 (2012年7月前) 从字节码反编译; (761723后) 保留源码原文  ? ? 保留源码原文

(几个缩写:
copying GC: 也叫scavenger
MIC: monomorphic inline-cache
PIC: polymorphic inline-cache
pun-boxing: Packed NaN unboxing)

SpiderMonkey和LuaJIT似乎都在用pun boxing

所以说这年头是个JavaScript引擎都得有JIT编译器了…没有都不好意思出来混。受到平台限制(例如iOS、Windows Phone)而无法实现JIT编译器的“第三方JavaScript引擎“只好哭了。

TODO

--------------------------------------------------------------------------

当代JavaScript引擎之间有许多共通的实现技巧。多数优化会对JavaScript程序的行为做一定猜测(speculate),并基于猜测做激进优化(speculative optimization)。
下面挑几个简单介绍一下。

从源语言到中间表示的编译器(source-to-IR compiler)
  也叫做编译器的“前端”。
  递归下降式语法分析器(recursive-descent parser)
  运算符优先级式语法分析器(operator precedence parser)
  deferred parser / diet parser(延迟语法分析)
 

从中间表示到目标代码的编译器(IR-to-target-code compiler)
  也叫做编译器的“后端”。但因为这部分编译器经常被叫做“JIT”编译器,所以单独拿出来写
  JIT style compiler: “just-in-time编译”狭义的定义是“即时编译”,也就是在某段代码即将第一次被执行时才对其编译。太早或太迟都不符合这个狭义版定义。所谓“JIT风格的编译器”通常意味着“编译是同步进行的”。这就自然的引出几个特征:1、编译速度必须很快;2、编译只能做有限的优化,只能选效费比高的来做。
  optimizing compiler
  多层编译(tiered compilation)
  后台编译(background compilation)
  类型反馈(type feedback)
  类型特化(type specialization)
  SSA-form IR

自动内存管理
  分代式GC(generational GC)
  增量式GC(incremental GC)
  并发式GC(concurrent GC)
  准确式GC(exact / accurate / type exact / type accurate / precise GC)

对象布局
  紧凑对象布局 + 隐藏类

值表现形式
  tagger-pointer 或 tagged-value
  NaN-boxing

运行时系统
  inline-cache
  on-stack replacement
  deoptimization
  用native stack实现VM stack
  cons-string 或者叫 rope 来优化字符串拼接
  dependent string/sliced string 来优化字符串的子串操作
  sparse array
    B-tree

TODO

--------------------------------------------------------------------------

上面介绍的JavaScript引擎实现技巧也影响了“如何写出更高效的JavaScript代码”:尽量让代码的行为符合JavaScript引擎的猜测,效率就会高。

写类型稳定的代码
  在构造器函数里声明和初始化所有属性
  尽量不要delete属性;不要通过delete属性来把某个属性重置,赋值为undefined都好
  不要把数组当一般对象用;不要把一般对象当数组用

TODO

Kevin Gadd
JavaScript Performance For Madmen

--------------------------------------------------------------------------

JavaScript引擎在安全性方面面临的挑战

JIT hardening

Matasano Security - Attacking Clientside JIT Compilers

http://www.accuvant.com/sites/default/files/images/webbrowserresearch_v1_0.pdf

Alexander Sotirov
Heap Feng Shui in JavaScript

2013-02-19: Corelan Team (corelanc0d3r)
DEPS – Precise Heap Spray on Firefox and IE10

有尝试从语言级别修正部分安全问题的,例如从capability based security方向入手的Caja

==========================================================================

接下来介绍各JavaScript的具体情况。请允许我抱有私心的先从Oracle自家的JavaScript实现,Nashorn开始;然后介绍一个较简单干净的新JavaScript实现,lv5;接下来再介绍其它引擎,哈哈

这些JavaScript引擎就微软和Opera的不开源,其它都是开源的。
其实现在实现高性能JavaScript引擎的技术都不是秘密了,死守源码实在是…诶。
结果Opera Carakan挂了,现在就剩微软系JavaScript引擎不开源。

1楼: Oracle Nashorn
2楼: lv5
3楼: Google V8
4楼: Mozilla SpiderMonkey系 (包括SpiderMonkey / Tamarin / TraceMonkey / JaegerMonkey / IonMonkey / Baseline)
5楼: Microsoft Chakra
6楼: Apple JavaScriptCore系 (包括JavaScriptCore / SquirrleFish / SquirrelFish Extreme (SFX) / Nitro)
7楼: Opera Carakan
8楼: KDE KJS
9楼: IronJS
10楼: Jurassic
11楼: dynjs
12楼: Microsoft SPUR
13楼: Mozilla Rhino
14楼: Digital Mars DMDScript
15楼: Microsoft JScript (特指Chakra之前的微软的JScript)
16楼: Microsoft Managed JScript
17楼: Mozilla Narcissus
18楼: Continuum

19楼: 杂项未整理资料
RednaxelaFX 2013-04-21
Nashorn


官方网站: http://openjdk.java.net/projects/nashorn/
官方博客: http://blogs.oracle.com/nashorn/
官网Wiki: https://wiki.openjdk.java.net/display/Nashorn/Main
邮件列表: http://mail.openjdk.java.net/mailman/listinfo/nashorn-dev
兼容标准: ECMAScript 5.1
实现语言: Java
代码: http://hg.openjdk.java.net/nashorn/jdk8/nashorn
代码版本控制工具: Mercurial
开源许可证: GPLv2
--------------------------------------------------------------------------

我的评论:

Nashorn(读作Naz-horn)是Oracle全新开发的JavaScript实现。高度兼容ECMAScript 5标准,并尽可能兼容Rhino。它使用Java语言实现,运行在JVM上,借助JDK7开始包含的JSR 292(invokedynamic)新功能达到较高的性能,同时保持代码的相对整洁,适合对JavaScript内部实现感兴趣的同学阅读。

在2012年底Nashorn就已经达到可以完全通过test262测试套件的兼容性,就这点说它甚至比SpiderMonkey、V8更佳兼容于标准。

Nashorn起初是Oracle内部一个实验项目,用于验证JSR 292功能的完整性、可用性、易用性。后来得到了内部的关注,决定将其产品化,作为默认的JavaScript实现替换掉从JDK6开始包含在JDK之中的Rhino

John Rose对Rhino做的现代化改造可以算是Nashorn的一种先驱: http://cr.openjdk.java.net/~jrose/pres/201009-ThunderingRhinos.pdf
Nashorn显然从中获取了不少经验,但并未以Rhino的代码为基础来开发,而是完全重新写了。原因是Rhino本身的代码已经非常老旧,架构很难适应在现代JVM上高效实现JavaScript的需求,没啥值得复用的代码。

只从JVM以上的层面看,Nashorn是一种单层的纯编译型JavaScript实现。所有JavaScript代码在首次实际执行前都会被编译为Java字节码交由JVM执行。
(当然JVM自身可能是混合执行模式的,例如HotSpot VM与J9 VM。所以Nashorn在实际运行中可能需要一定预热才会达到最高速度)

Nashorn不但可以执行JavaScript,还可以当作库为其它工具提供一些基础服务。例如说它现在为NetBeans IDE中的JavaScript编辑器提供语法高亮支持和调试支持

从Oracle JDK 8 build 82开始,Nashorn已经作为JDK8的一部分包含在安装包中。安装后可以在JDK安装目录的jre/lib/ext/nashorn.jar找到Nashorn的实现。正式版的JDK8里jrunscript等工具都会由Nashorn提供执行JavaScript语言的支持;通过JSR 223 API获取默认的JavaScript引擎也会是Nashorn。

直接使用Java类的实例来容纳JavaScript对象的字段,在对象内嵌入字段而不放在spill array里的好处是:
1、对象更加紧凑,数据离得更近,局部性更好
2、数组访问有边界检查,而对象字段访问则没有,后者效率更高

PropertyMap
JDK-8006220: Faster creation of properties

Nashorn的hidden class transition记录在PropertyMap的“history”字段里,是个LinkedHashMap<Property, PropertyMap>。
所有同系列的PropertyMap都共享一个history。

Function.prototype.toString()由jdk.nashorn.internal.runtime.ScriptFunction.toSource()实现;具体来说由ScriptFunctionData的子类实现。其中由对应源码的(例如RecompilableScriptFunctionData)里会引用着FunctionNode,里面记录着起始和结束位置,通过这个信息到FunctionNode引用的Source里去找char[]的内容。

关于在现有VM平台上实现JavaScript或其它动态语言的讨论
Peng Wu Reusing JITs are from Mars, Dynamic Scripting Languages are from Venus

--------------------------------------------------------------------------

2014-03-14: Jim Laskey
Latest news from the Nashorn team

2013-07: Marcus Lagergren
Nashorn Was Stories (from a battle scarred veteran of invokedynamic), JVMLS 2013
video

2013-07: Attila Szegedi
Fitting Nashorn on the JVM
video

2013-07-09: Jim Laskey
Nashorn Multithreading and MT-safety

2013-06-24: Dalibor Topic
PodFodder: Project Nashorn Everywhere

2013-05-29: Jim Laskey reposting Gerrit Grunwald
Repost: Taming the Nashorn (first impressions)..., Nashorn Blog

2013-05-15: Marcus Lagergren
Nashorn: Implementing Dynamic Languages on the JVM, geecon 2013

https://oraclein.activeevents.com/connect/sessionDetail.ww?SESSION_ID=1143
https://oraclein.activeevents.com/connect/fileDownload/session/AB2BAC9C20881CFB16F17F359CAA0E4E/CON1143_Arora-akhil-nashorn-node.pdf

2013-05-08: Hannes Wallnoefer
CON1200 - Project Nashorn in Java 8 - Javascript As a First Class Language on The JVM, JavaOne 2013 India
Slides

2013-04-24: Claudia Fröhling and Marcus Lagergren
JavaScript for the JVM - say hello to Nashorn!, JAX 2013
presentation video

2013-04-13: Attila Szegedi
Project Nashorn in Java 8 - Javascript as a first class language on the JVM, Devoxx UK 2013
Slides

http://www.meetup.com/Londonjavacommunity/events/109436382/

2013-01-17: Abhay Bakshi
Nashorn Voted In as a Successor to Rhino in the OpenJDK Project, InfoQ

2013-03-28: Jim Laskey
Nashorn, JavaScript for the JVM (Commonwealth Complex), EclipseCon 2013
Slides (pptx) Video

2013-01-30: Yolande Poirier, Marcus Lagergren
Nashorn, the JavaScript Implementation in Java 8

2013-01-16: Marcus Lagergren
Implementing Dynamic Languages on the JVM

2012-12-21: Jim Laskey
Open For Business

2012-11-14: Marcus Lagergren
Nashorn: Optimizing JavaScript and Dynamic Language Execution on the JVM, Devoxx 2012
Slides

2012-10-01: Staffan Friberg and Marcus Lagergren
Optimizing JavaScript and Dynamic Languages on the JVM, JavaOne 2012

2012-10-10: Jim Laskey
Welcome To The Nashorn Blog
这帖里有很多介绍Nashorn的技术演讲的链接,主要是JavaOne 2012的session。值得一看。

2012-07-12: Dalibor Topic, Jim Laskey
PodFodder: Jim Laskey on Nashorn JavaScript Engine

2011-07-19: Jim Laskey
Nashorn: Adventures in JSR-292 or How To Be A Duck Without Really Trying, JVM Language Summit 2011
RednaxelaFX 2013-04-21
lv5

代码: https://github.com/Constellation/iv
代码版本控制工具: Git

主要人物: 鈴木勇介 (@Constellation)

--------------------------------------------------------------------------

我的评论:

立志成为“最符合ECMAScript标准的JavaScript引擎实现”。其早期版本几乎是直接把规范里的条款翻译为可执行的代码,不管运行效率如何。后来渐渐加入优化提升性能。

它的研发历程是本活生生的教科书,从非常简单的AST解释器一直进化到带有一定优化的JIT编译器,对test262的兼容性也一直维持在很高的水平,值得对自己实现JavaScript引擎感兴趣的同学阅读学习。

在Mac OS X上构建lv5非常方便。基本上有正常的C++构造环境、Python、SCons和Boehm GC就好了。在代码树的根目录执行scons,构建好之后在obj/lv5就能找到名为lv5的可执行文件,也就是lv5的shell。
Boehm GC用MacPorts装的话名字是boehmgc。

这个JavaScript引擎里到处都是炮姐里的角色名。看不懂neta的话可能会晕掉。
eleporter -> 白井黒子/空間移動(テレポート) -> 老的AST解释器
railgun -> 御坂美琴/超電磁砲(レールガン) -> Stack VM -> Register VM
aero (Aero Hand Project) -> 婚后光子/空力使い(エアロハンド) -> 正则表达式引擎
breaker (Imagine Breaker Project) -> 上条当麻/幻想殺し(イマジンブレイカー) -> Context-threading JIT编译器
radio (Radio Noise Project) -> 妹達(シスターズ)/欠陥電気(レディオノイズ) -> 准确式GC
phonic -> ? -> ruby binding for iv AST API
accelerator -> 一方通行(アクセラレータ) -> ?
melt (Meltdowner) -> 麦野沈利/原子崩し(メルトダウナー) -> ECMAScript扩展
Lv6 Shift Project -> 絶対能力者進化(レベル6シフト) -> 性能提升的大项目
Level Upper Project -> 幻想御手(レベルアッパー) -> ES6 version

动态编译器用了Xbyak库。作者把这个叫做online assembler,也对。

偷懒不想自己写GC的话就可以像lv5一样用Boehm GC。不过许多开始用Boehm GC的项目最终都转为自己写了——例如说Mono
使用Boehm GC使得lv5的设计受到了限制,例如说它在选择tag数据的实现时就只能选择tagged value而不能用tagged pointer,否则如果指针被tag了的话Boehm GC就认不出那是有用的指针了。

另外他还有一个叫做Shibuya(涩谷)的ES.next实现,用ES5.1来实现:https://github.com/Constellation/shibuya
所以这也是个元循环虚拟机,与Narcissus的方案有相似之处。

--------------------------------------------------------------------------

2012-12-22: 鈴木勇介
Polymorphic Inline Cache implementation of iv / lv5
http://qiita.com/advent-calendar/2012/vm

2012-08-04: 鈴木勇介
lv5: The most precise ECMAScript engine

2012-01-28: 鈴木勇介
Announcing Lv5 new RegisterVM
lv5 version 0.0.2: RegisterVM

2011-12-18: 鈴木勇介
lv5.current 2011/12/18

2011-10-19: 鈴木勇介
iv / lv5, ECMA262 5.1th full support

2011-09-26: 鈴木勇介
固定長配列
所以ES5.1里只要把数组的length设成{ writable: false }就变成定长数组了orz

2011-07-27: 鈴木勇介
iv / lv5 VM engine
RednaxelaFX 2013-04-21
V8


官方网站: http://code.google.com/p/v8
官方博客: http://blog.chromium.org/search/label/v8 (Chromium的官方博客包含V8的内容)
邮件列表: http://groups.google.com/group/v8-users
文档: https://developers.google.com/v8/intro
代码: https://code.google.com/p/v8/wiki/Source?tm=4
兼容标准: ECMAScript 5
实现语言: C++
开源许可证: New BSD License
代码版本控制工具: Subversion/Git

Shell: d8

相关工具:
C1Visualizer: https://java.net/projects/c1visualizer/
IRHydra: https://code.google.com/p/irhydra/

主要人物:
Lars Bak: 参与过Self、Strongtalk、HotSpot、CLDC HotSpot Implementation、OOVM、V8、Dart的研发
Kasper Lund: 参与过CLDC HotSpot Implementation、OOVM、V8、Dart的研发
Søren Gjesse
Daniel Clifford
Vyacheslav Egorov
Erik Corry

--------------------------------------------------------------------------

我的评论:

最初的V8就是现代化版的Self VM,套上了JavaScript语言的皮。

V8的tagged pointer形式也与Self/Strongtalk采用了同样的取舍:小整数(Smi)的tag为0,方便小整数的直接加减/位运算;而对象指针按4字节对齐后带有非0的tag:0x01。这与许多其它采用tagged value的VM正好相反,其它VM让对象对齐分配后指针不带特殊tag,这样便于对象指针直接使用;而V8则更注重小整数的运算性能,稍微牺牲指针的性能。
V8的选择的合理之处在于:像x86这样有复杂寻址模式的指令集里,指针加1可以用base+offset的形式来直接嵌在地址里,这样的话指针加1并不需要为地址运算而付出额外指令的代价。而由于小整数tag为0,小整数的加减等运算不需要位移也不需要mask就可以直接做,整体上看开销比较小。也正是这个原因,Self一直下来的血统一直使用这种tag方式。
不过这种编码方式也有弊端,例如说如果想用ARM/Thumb-16来实现这种tagging scheme,就无法把指针加1直接放进地址运算里,因为它的寻址无法只加1。

参见Self的tag: https://github.com/russellallen/self/blob/master/vm/src/any/objects/tag.hh
Strongtalk的tag: http://code.google.com/p/strongtalk/wiki/VMTypesForSmalltalkObjects

Heap里有个Object* roots_[kRootListLength]存着所有从VM里能直接访问到的非Handle的root。这跟HotSpot VM的Universe里的一大堆成员变量当作root的意义一样,但处理起来更方便一些:GC的扫描代码不需要一个个root按名字去遍历,只要遍历这个roots_数组即可。

PreParser用于加速后续parse过程。
实际上可以看成V8的基础parsing就用了2-pass方式,先收集一些上下文信息但并不生成AST,然后再做真的parse的时候靠这些上下文信息来减少麻烦,增加“预测”的准确性。
// Preparsing checks a JavaScript program and emits preparse-data that helps
// a later parsing to be faster.
// See preparse-data-format.h for the data format.

// The PreParser checks that the syntax follows the grammar for JavaScript,
// and collects some information about the program along the way.
// The grammar check is only performed in order to understand the program
// sufficiently to deduce some information about it, that can be used
// to speed up later parsing. Finding errors is not the goal of pre-parsing,
// rather it is to speed up properly written and correct programs.
// That means that contextual checks (like a label being declared where
// it is used) are generally omitted.

http://ariya.ofilabs.com/2012/07/lazy-parsing-in-javascript-engines.html
类似的技巧在Dart中也有应用:
https://www.dartlang.org/slides/2012/10/gotoaarhus/translating-dart-to-efficient-javascript-kasper-lund.pdf

为什么V8不用字节码,直接把JavaScript编译到机器码呢?
Florian Loitsch和Bob Nystrom所写的Why Not a Bytecode VM?虽然主要说的是Dart VM的设计考量,但对V8也适用。

concurrent recompilation(之前叫parallel recompilation)

演示V8的常量折叠
function foo() { return 1 + 2 }

--- Raw source ---
() { return 1 + 2 }

--- Optimized code ---
kind = OPTIMIZED_FUNCTION
name = foo
stack_slots = 0
Instructions (size = 54)
0x34af9a343880     0  55             push rbp
0x34af9a343881     1  4889e5         REX.W movq rbp,rsp
0x34af9a343884     4  56             push rsi
0x34af9a343885     5  57             push rdi
                  ;;; <@0,#0> -------------------- B0 --------------------
                  ;;; <@4,#4> context
0x34af9a343886     6  488bc6         REX.W movq rax,rsi
                  ;;; <@8,#7> -------------------- B1 --------------------
                  ;;; <@10,#9> stack-check
0x34af9a343889     9  493b6548       REX.W cmpq rsp,[r13+0x48]
0x34af9a34388d    13  7305           jnc 20  (0x34af9a343894)
0x34af9a34388f    15  e86c7ffcff     call 0x34af9a30b800     ;; code: STUB, StackCheckStub, minor: 0
                  ;;; <@12,#14> constant-t
0x34af9a343894    20  4b8d0464       REX.W leaq rax,[r12+r12*2]
                  ;;; <@14,#12> return
0x34af9a343898    24  488be5         REX.W movq rsp,rbp
0x34af9a34389b    27  5d             pop rbp
0x34af9a34389c    28  c20800         ret 0x8
0x34af9a34389f    31  6690           nop
0x34af9a3438a1    33  0f1f00         nop
                  ;;; Safepoint table.

Deoptimization Input Data (deopt points = 1)
 index  ast id    argc     pc             
     0       3       0     20

Safepoints (size = 18)
0x34af9a343894    20  11111111 (sp -> fp)       0

(测试在V8 3.18.6,x64上运行)
r12在V8/x64上是Smi常量寄存器,初始化为Smi的单位元(数值为1),具体实现是Smi::FromInt(kSmiConstantRegisterValue)也就是说底层表现是0x2。要获取一个数值为3的Smi的代码是:
leaq rax,[r12+r12*2]

意思是rax = r12 * 3。可见源码里的1+2被折叠为常量3了。

Deferred parsing
跟HotSpot Client Compiler非常相似的新编译器

编译器内部使用的类型系统:types.h

Inobject slack tracking: objects.h

不知道Google Chrome for Android (Chrome Mobile)里的V8跟桌面的V8有多大差异呢?
另外一提的是iOS版Chrome里没有使用V8,而是用UIWebView里自带的没有JIT的JavaScriptCore。Apple自己的Safari则可以用带有JIT版的JavaScriptCore。

关于浮点数转换的Grisu3算法:
やっぱりdoubleでは「76287755398823936」は表現できない
Printing floating-point numbers quickly and accurately with integers, Florian Loitsch, 2010

--------------------------------------------------------------------------

https://codereview.chromium.org/25254002/
V8也要有flow-sensitive analysis了啊厉害⋯

http://cs.au.dk/~jmi/VM/GC.pdf

https://docs.google.com/a/chromium.org/presentation/d/1OFG81taxgjOGU43sv9WHvPZkt5--KnM6gSijWN8NMcU/edit?disco=AAAAAECHbXY#slide=id.p
V8 Binding Explained
这是Webkit时代的了。Blink时代的binding机制有改变。

https://code.google.com/p/chromium/issues/detail?id=112386

TurboFan - Land the Fan (disabled), Chromium Code Reviews

Daniel Clifford, Hannes Payer, Michael Starzinger, Ben L. Titzer
Allocation Folding Based on Dominance, Google V8 Team

Crankshaft介绍文(日文)
http://nothingcosmos.github.io/V8Crankshaft/src/blog.html
写到了Crankshaft与HotSpot C1的关系 。没错,就是同根生。

Create Wiki - V8 Cookbook


2015-04-12: Vyacheslav Egorov
jsunderhood digest (in Russian)
http://mrale.ph/talks/techtalksnsu2014/images/slides/slide-2-014.png

2014-10-09: Mounir Lamouri
Chrome 39 Beta: JS Generators, Animation Playback Control, and the WebApp Manifest, The Chromium Blog

2014-09-13: Vyacheslav Egorov
Vyacheslav Egorov: invokedynamic.js, JSConf.EU

2014-08-28: Andreas Rossberg
Chrome 38 Beta: New primitives for the next-generation web, The Chromium Blog
Map, Set, Iterator, Symbol

2014-05-30: Ben Titzer
New Optimizations of Google Chrome's V8, InfoQ, mloc.js 2014

2014-05-22: Shane Stephens, Doug Stockwell
Chrome 36 Beta: element.animate(), HTML Imports, and Object.observe(), The Chromium Blog
引用
// Let's say we have a model with data
var model = {};

// Which we then observe
Object.observe(model, function(changes) {

    // This asynchronous callback runs and aggregates changes
    changes.forEach(function(change) {

        // Letting us know what changed
        console.log(change.type, change.name, change.oldValue);
    });

});


2014-04-10: Rick Byers
Chrome 35 Beta: More developer control over touch input, new JavaScript features, and unprefixed Shadow DOM, The Chromium Blog

2014-02-13, Yang Guo
Compiling in the background for a smoother user experience, TheChromium Blog

2013-09-23: Jay Conrod
A tour of V8: Garbage Collection

2013-08: Marja Hölttä (Google)
Crankshafting from the ground up

2013-08-14: Vyacheslav Egorov
Hidden classes vs jsPerf
最重要的takeaway是这段:
Vyacheslav Egorov 写道
Important thing to understand from this is that the code below will produce objects with different hidden classes because their constructors are different closures.
function make() {
  function maker() { }
  return new maker();
}

var a = make(), b = make();
// a and b have different hidden classes because a new maker is created
// every time you execute make.


2013-06-06:
Working with arrays in V8 (performance issue), StackOverflow
引用
@Esailija Actually what you write is not entirely correct. ArrayPush built-in tries to keep elements in fast mode if they were in fast mode. See the logic in https://code.google.com/p/v8/source/browse/trunk/src/builtins.cc#547 – Vyacheslav Egorov
@yttrium the difference happens due to how heuristics for going back into fast mode from dictionary mode work. if your array is in dictionary mode then every time when it needs to grow V8 checks whether it is dense enough and whether it can win space by using a continuous (C-like) array instead of dictionary. With 180000 as starting point heuristics hit fast and with 181000 heuristic hits very late. Hence the difference. Heuristic is here: https://code.google.com/p/v8/source/browse/trunk/src/objects.cc?r=14954#12483 – Vyacheslav Egorov


2013-05-16: Lars Bak, Kasper Lund
Web Languages and VMs: Fast Code is Always in Fashion, Google I/O 2013
Video Slides

2013-05-16: John McCutchan
Accelerating Oz with V8: Follow the Yellow Brick Road to JavaScript Performance, Google I/O 2013
Slides

2013-05-08: Andy Wingo
generators in v8

2013-04-29: Vyacheslav Egorov
Performance tuning as the art of weather forecast

2013-04-18: Andy Wingo
inside full-codegen, v8's baseline compiler

2013-04-11: Ariya Hidayat
JavaScript: Need for Speed, SF Web Performance Group

2013-02-17: Vyacheslav Egorov
Release the IRHydra!

2012-11-05: Addy Osmani
Writing Fast, Memory-Efficient JavaScript

2012-10-16: Charles Torre, Lars Bak and Steve Lucco
Lars Bak and Steve Lucco: Chakra, V8, JavaScript, Open Source, Channel 9

2012-10-11: Chris Wilson, Daniel Clifford
Performance Tips for JavaScript in V8

2012-09-23: Vyacheslav Egorov
Grokking V8 closures for fun (and profit?)
<- 关注一下https://code.google.com/p/v8/issues/detail?id=2206,它在V8里还没实现,现在的owner是Ben Titzer

2012-07-03: Ariya Hidayat
Lazy Parsing in JavaScript Engines

2012-06-27: Daniel Clifford
Breaking the JavaScript Speed Limit with V8, Google I/O 2012
土豆源
Slides

2012-06-03: Vyacheslav Egorov
Explaining JavaScript VMs in JavaScript - Inline Caches

2012-05-24: Vyacheslav Egorov
V8 Inside Out, Web Rebels 2012

2012-05-02: Jakob Kummerow
Chromium Blog: Better code optimization decisions for V8

2012-04-19: Florian Schneider
Compiling Dart to Efficient Machine Code
这篇虽然主题是如何将Dart语言编译为高效的机器码,但里面也穿插着一些有用的V8相关的介绍。

2012-04-02: Vyacheslav Egorov
Can V8 do that?!, JSConf US 2012

2012-03-15: Florian Loitsch
Optimizing for V8 series
作者通过实验来分析V8新的(Crankshaft里的)优化编译器的实现。

2012-02-28:
In V8: pointer tagging

2012-02-02: Nikita Popov
Pointer magic for efficient dynamic value representations

2011-12-18: Vyacheslav Egorov
I-want-to-optimize-my-JS-application-on-V8 checklist

2011-11-21: Vyacheslav Egorov and Erik Corry
A game changer for interactive performance.
介绍V8的新GC:对年老代的增量式mark-and-sweep收集。

2011-10-11: Kasper Lund
Crankshaft: Turbocharging the next generation of web applications., GOTO Conference 2011 Aarhus
V8的核心开发Kasper Lund介绍新的Crankshaft编译架构。
此时的Crankshaft还在使用每毫秒取一次sample的方式来profile程序获取热点。后来的Crankshaft已改为较传统的基于计数器的方式。

2011-09-05: Andy Wingo
from ssa to native code: v8's lithium language

2011-08-02: Andy Wingo
a closer look at crankshaft, v8's optimizing compiler

2011-07-24: Jay Conrod
Polymorphic Inline Caches explained
介绍V8的PIC的好文

2011-07-05: Andy Wingo
v8: a tale of two compilers

2011-06-20: Andy Wingo
on-stack replacement in v8

2011-06-11: Vyacheslav Egorov
Understanding V8

2011-06-10: Andy Wingo
V8 is faster than GCC
表喷…作者知道他说的是什么意思

2011-06-08: Andy Wingo
what does v8 do with that loop?
提到了V8 Crankshaft的sampling-based profiler触发Crankshaft编译的设计

2011-05-18: Andy Wingo
value representation in javascript implementations

2011-05-03: 莫枢
关于一些JavaScript引擎最近的动态, HLLVM群组

https://codereview.chromium.org/7189066
simple non-incremental compaction

https://groups.google.com/forum/#!msg/v8-dev/9Ke8H6Kv5cM/FRnlw91N9m8J
Prototype of mark-and-compact support for Harmony weak maps.

http://www.mail-archive.com/v8-dev@googlegroups.com/msg27971.html
从老的card marking改为store buffer的讨论帖

2010-12-08: David Mandelin
Crankshaft

2010-12-08: Kevin Millikin and Florian Schneider
Chromium Blog: A New Crankshaft for V8

2010-09-29: Hannes Wallnöfer
Update on my Node.js Memory and GC Benchmark

2010-02-19: 莫枢
Cpython能否用V8的方式优化性能, HLLVM群组
可以关注这帖里我的几个回复。

http://comments.gmane.org/gmane.comp.lang.javascript.v8.general/1897
关于external string。外部字符串如果是ASCII或者UTF-16编码的话可以直接暴露给V8当作一个JavaScript String。对UTF-8编码或者其它编码的则不行。进一步参考讨论帖:https://code.google.com/p/v8/issues/detail?id=27

2009-08-21: 莫枢
[草稿帖][2009-08-21][JavaScript][V8][Nitro] 响应号召,放一个V8/Nitro相关的草稿出来, HLLVM群组

2009-05-27: Mads Ager, Lars Bak, Anders Sandholm
V8: Building a High Performance JavaScript Engine, Google I/O 2009
优酷源
Slides

2009-04-29: Erik Meijer, Lars Bak
Inside V8: A JavaScript Virtual Machine, Channel 9

2009-02-04: Erik Corry, Christian Plesner Hansen and Lasse Reichstein Holst Nielsen
Irregexp, Google Chrome's New Regexp Implementation

2009-01-13: Hajime Morita
Why Is the New Google V8 Engine So Fast?
一个5 part的系列文。相当详细的介绍了初期V8的各种特点。不愧是日本同行,分析加上成文的速度和深度都相当赞。我当时也靠读这篇才开始真正深钻进V8的实现里。

2008-10-08: 莫枢
在WinXP上构建V8
这篇提了下在Windows XP上用VC2008来构建V8的步骤,以及V8与
要注意现在(2013-04-20)V8的构建方式以及跟2008年的时候很不一样了,用了新的工具。

2008-09-07: Hajime Morrita
V8 祭り

2008-09-03: 莫枢
简记V8与SquirrleFish/Tamarin的对比点

2008-09-03: Brendan Eich
TraceMonkey Update

2008-09-02: Lars Bak
Google Chrome's Need for Speed, Chromium Blog
RednaxelaFX 2013-04-21
SpiderMonkey系
(包括SpiderMonkey/Tamarin/Tamarin Tracing (TT) /TraceMonkey/JaegerMonkey/IonMonkey/Baseline)

官方网站: https://developer.mozilla.org/en-US/docs/SpiderMonkey
官方博客: https://blog.mozilla.org/javascript/
https://air.mozilla.org/?tag=javascript
代码: http://hg.mozilla.org/mozilla-central/file/tip/js/src
(repo地址是 http://hg.mozilla.org/mozilla-central/,包括完整的Gecko、Firefox源码)
代码版本控制工具: Mercurial / Git
开源许可证: MPL2

内部实现的描述: https://developer.mozilla.org/en-US/docs/SpiderMonkey/Internals
字节码格式文档: https://developer.mozilla.org/en-US/docs/SpiderMonkey/Bytecodes
IonMonkey文档: https://wiki.mozilla.org/Platform/Features/IonMonkey

老版本(还在用C而未迁移到C++时的)SpiderMonkey的文档: http://www-archive.mozilla.org/js/spidermonkey/

在V8出现前,SpiderMonkey是native application嵌入JavaScript的最流行选择。如果大家没留意过的话,UltraEdit就内嵌了SpiderMonkey来让用户使用JavaScript写宏与插件[/url];Adobe Acrobat也类似。

准确说Tamarin不是SpiderMonkey系的VM,而是Adobe捐赠给Mozilla的开源版AVM2 (ActionScript Virtual Machine 2)。但它与同时期的TraceMonkey有一定关系,而且既然是属于Mozilla的VM了也就一并放在这边吧。
Mozilla对这个VM并不满意,认为Tamarin的解释器比SpiderMonkey的慢,而JIT也没有特别值得用的部分,最后只把Tamarin的JIT编译器里的汇编器nanojit拿出来塞进了TraceMonkey里。
然后TraceMonkey也被抛弃,SpiderMonkey里现在应该一点Tamarin的影子都没有了。

到底SpiderMonkey指的是啥,后来Mozilla推出的各*Monkey跟SpiderMonkey有啥关系,Chris Leary写的这篇博客说得很清楚:Mapping the monkeysphere
Chris Leary 写道


JaegerMonkey与Nitro的关系可以参加David Mandelin画的示意图:


JaegerMonkey chunked compilation

SpiderMonkey里隐藏类叫做Shape。
Property cache与PIC。
现在只有解释器还在用原本的简易property cache,新的IonMonkey转用更多依赖type inference和另外实现的PIC。

SpiderMonkey一个相对奇葩的地方是,它的Function.prototype.toString是通过反编译字节码得到,而不是把真实的源码记录着返回出来。
看2011年底的SpiderMonkey 1.8.5的行为:
js> function foo () { /* ... */ return 42 }
js> foo
function foo() {return 42;}
js>

可以看到foo被反编译出来得到的字符串里注释、空白之类的都跟真正的源码不一样。
在2012年中的761723之后,SpiderMonkey也改为跟其它大多数JavaScript引擎一样直接返回实际源码了。Brendan Eich有篇介绍ECMAScript Harmony的blog也提到了这个改动。

ECMAScript 6 support in Mozilla

--------------------------------------------------------------------------

http://rfrn.org/~shu/
Shu-yu Guo

https://bugzilla.mozilla.org/show_bug.cgi?id=634503
Investigate V8's GC
谁能说这不是一个可爱的bug…

2014-01-14: Luke Wagner
asm.js AOT compilation and startup performance

2013-07-18: Steve Fink
Clawing Our Way Back To Precision Mozilla JavaScript Blog
讲SpiderMonkey从保守式GC变回准确式GC

2013-06-24: Steve Fink
Sfink/Draft - GC Pointer Handling, Mozilla Wiki

2013-04-05: Kannan Vijayan
The Baseline Compiler Has Landed, Mozilla JavaScript Blog
中文翻译 by 编译路漫漫

2013-02-03: Jon Coppeard
Spider Monkey Garbage Collection, Air Mozilla

2013-01-03: Jim Blandy
Support for debugging SpiderMonkey with GDB now landed, Mozilla JavaScript Blog

2012-12-05: 编译路漫漫
如何得到SpiderMonkey引擎的字节码(bytecode)

2012-12-04: 编译路漫漫
SpiderMonkey内部的字符串表示

2012-11-16: 编译路漫漫
IonMonkey 中可能的研究点

2012-10-15: Kannan Vijayan
The Ins and Outs of Invalidation, Mozilla JavaScript Blog
Type inference of IonMonkey, invalidation vs. guarding, etc

2012-10-08: Luke Wagner
Optimizing JavaScript variable access

2012-10-04: Mihai Bazon
UglifyJS — why not switching to SpiderMonkey AST
这里所说的SpiderMonkey AST的文档请参考  https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API

2012-09-16: 编译路漫漫
IonMonkey分析:目录结构

2012-09-12: David Anderson
IonMonkey in Firefox 18, Mozilla JavaScript Blog
中文翻译 by 编译路漫漫

2012-08-28: Bill McCloskey
Incremental GC in Firefox 16!, Mozilla JavaScript Blog

2012-07-20: David Mandelin
Incremental GC now in Firefox Aurora

2012-05-09: David Mandelin
SpiderMonkey API Futures

2012-02-01: David Mandelin
Mozilla JS Development Newsletter 1/25/2012-2/29/2012

2012-01-25: Jeff Walden
SpiderMonkey no longer supports sharp variables
回复里Jeff还很批了一通E4X。这功能真悲催啊…

2012-01-24: Luke Wagner
JSRuntime is now officially single-threaded

2012-01-24: David Mandelin
Mozilla JS Development Newsletter 12/07-1/24

2012-01-06: Chris Leary
String representation in SpiderMonkey

2011-11-01: Nicholas Nethercote
SpiderMonkey is on a diet

2011-09-01: Jesse Ruderman
Lessons from JS engine bugs

2011-08-26: Kailas Patil
JaegerMonkey Architecture

2011-08-12: Luke Wagner
Old Dijkstra Essays Considered

2011-07-15: Steve Webster
Firefox doesn’t hoist function declarations in blocks

2011-06-16: David Mandelin
Know Your Engines at O’Reilly Velocity 2011

2011-06-08: Chris Leary
Mapping the monkeysphere

2011-06-06: Jeff Walden
I feel the need…the need for JSON parsing correctness and speed!

2011-06-05: Gregor Wagnery, Andreas Gal, Christian Wimmer, Brendan Eich and Michael Franzy
Compartmental Memory Management in a Modern Web Browser, ISMM'11

2011-05-18: Andy Wingo
value representation in javascript implementations

2011-05-03: 莫枢
关于一些JavaScript引擎最近的动态, HLLVM群组

2011-04-22: David Mandelin
Mozilla JavaScript 2011

2011-03-16: Jeff Walden
JavaScript change for Firefox 5 (not 4): class, enum, export, extends, import, and super are once again reserved words per ECMAScript 5

2011-03-06: Jeff Walden
JavaScript change in Firefox 5 (not 4), and in other browsers: regular expressions can’t be called like functions

2010-12-08:
SpiderMonkey 1.8.5 for Windows, Kahu Security
方便懒得自己编译的人(逃
源码版本是2010-11-24从http://hg.mozilla.org/mozilla-central/下载的当时最新版。

2010-10-13: Andreas Gal
Compartments

2010-09-27: Chris Leary
PICing on JavaScript for fun and profit

2010-09-08: David Anderson
Land Ho, Fast JavaScript!
JaegerMonkey对外发布测试版本

2010-09-08: David Mandelin
Jägermonkey: it’s in ur browser!!!

2010-08-25: Dave Herman
An API for parsing JavaScript

2010-08-02: Rob Sayre
Mozilla’s New JavaScript Value Representation

2010-07-19: David Mandelin
JägerMonkey Update: Getting Faster

2010-07-13: David Anderson
JägerMonkey has Crossed the Streams

2010-05-10: David Mandelin
JägerMonkey: the “halfway” point

2010-05-07: Jeff Walden
SpiderMonkey change du jour: the special __parent__ property has been removed

2010-04-16: Jeff Walden
More SpiderMonkey changes: ancient, esoteric, very rarely used syntax for creating getters and setters is being removed

2010-04-06: Jeff Walden
More changes coming to SpiderMonkey: the magical __count__ property is being removed

2010-03-15: David Mandelin
JägerMonkey & Nitro Components

2010-02-26: David Anderson
JaegerMonkey – Fast JavaScript, Always!

2010-02-26: David Mandelin
Starting JägerMonkey

2010-01-15: Jeff Walden
More ES5 backwards-incompatible changes: regular expressions now evaluate to a new object, not the same object, each time they’re encountered

2010-01-13: David Mandelin
JavaScript speedups in Firefox 3.6, Mozilla Hacks
用一些能被优化的JavaScript的代码例子来讲解Firefox 3.6里GC和TraceMonkey所做的事情

2010-01-12: Jeff Walden
More ES5 backwards-incompatible changes: the global properties undefined, NaN, and Infinity are now immutable

2009-12-21: Jeff Walden
ECMA-262 ed. 5 backwards-incompatible change coming to SpiderMonkey and to Gecko-based browsers

2009-11-02: David Mandelin
There’s more than one way to null a pointer

2009-09-15: David Anderson
64-bit TraceMonkey!

2009-09-01: David Anderson
Trace Compilation and Recursion, Part 1

2009-07-17: David Mandelin
an overview of TraceMonkey, Mozilla Hacks

2009-06-02: David Mandelin
TraceMonkey@PLDI

2009-05-15: David Mandelin
OSQ: Dynamic language optimization
提到了Bill McCloskey做的优化Python的项目。后来他也去了Mozilla。

2009-02-26: David Mandelin
TraceVis: performance visualization for TraceMonkey

2009-02-25: David Anderson
A Divine TraceMonkey Bug

2009-01-26: David Anderson
More Type Instability and Specialization in JavaScript

2009-01-09: David Mandelin
A History of Insanity in the Age of x86

2008-12-23: Jesse Ruderman
Some differences between JavaScript engines

2008-12-23: Jesse Ruderman
Fuzzing TraceMonkey

2008-10-27: David Anderson
TraceMonkey and Type Instability in JavaScript

2008-09-03: 莫枢
简记V8与SquirrleFish/Tamarin的对比点

2008-09-03: Brendan Eich
TraceMonkey Update

2008-08-27: David Mandelin
Inline threading, TraceMonkey, etc.

2008-08-22: Andreas Gal
Tracing the Web

2008-06-16: David Anderson
Tamarin Tracing, Intro to Tracing JITs

2008-05-28: David Mandelin
Tamarin Tracing Internals V: Running Compiled Traces

2008-05-28: David Mandelin
Tamarin Tracing Internals IV: Trace Optimization

2008-05-23: David Mandelin
Tamarin Tracing Internals III: LIR

2008-05-21: David Mandelin
Tamarin Tracing Interals, Part II: Forth

2008-05-16: David Mandelin
Tamarin Tracing Internals, Part I

2007-11-12: James Polanco
Flash Internals: Just-in-time (JIT) compilation (part four)
这个系列是介绍Tamarin/AVM2的。这篇介绍了AVM2的JIT编译器。

--------------------------------------------------------------------------

关于benchmark

2009-02-06: David Mandelin
SunSpider Statistics, Part II

2009-02-06: David Mandelin
SunSpider Statistics, Part I: Questions
RednaxelaFX 2013-04-21
Chakra
(新版(>= 9.0)JScript的代号。为了与老旧的JScript区分开来,这帖里只叫它Chakra)

官方博客: http://blogs.msdn.com/b/ie/ (IE Blog里包含Chakra的内容)
兼容标准: ECMAScript 5.1 / ECMAScript 2015

2016年1月以MIT许可证开源:https://github.com/Microsoft/ChakraCore

--------------------------------------------------------------------------

我的评论:

Chakra问世后的JScript已非当日吴下阿蒙。不要再拿“JScript跑得慢”来黑微软了!
即便Chakra的解释器也是字节码解释器,它的字节码设计与老版本JScript的已经相当不同,解释器自身的速度都已经有所提升。

Chakra里的隐藏类变迁机制叫做“type evolution”。每个产品都必须发明些新名词
IE9版Chakra里字段数量不超过16个的对象可以使用紧凑布局;IE10版Chakra将这限制放宽到30多个字段。

IE9 Chakra的对象布局是对象头与property数组分离的。IE10版则将构造器函数里赋值的属性直接跟对象头粘在一起分配。

Chakra里的value representation跟V8的比较类似,都是在最低的几位放tag;不过Chakra的是tagged-value,也就是在小整数的后面带上一个0x1的tag,而对象地址是8字节对齐的于是对象指针的最低3位为0。打tag的取舍正好与V8的tagged-pointer相反,而与更多其它用tagged-value的VM相似,例如说更传统的Smalltalk实现,包括现在还可以用到的Squeak,或者是像Ruby等受Smalltalk影响的VM。

注意:IE9在x64上的版本里的Chakra只有解释器,没实现JIT编译器;到IE10才开始在x64版上提供JIT编译器。

同样只有字节码解释器,IE9 64-bit的Chakra仍然可以比IE8 64-bit的JScript 5.8快近10倍:https://gist.github.com/rednaxelafx/5581610
可以想像为啥大家以前都要吐槽JScript慢了…

在.NET用Chakra的例子

Parser
ParseNode
FuncInfo
ByteCodeGenerator
  Js::ByteCodeReader
  Js::ByteCodeWriter
BackgroundCodeGenThread
IR
  Js::OpCode
IRBuilder
BasicBlock
Lowerer
FlowGraph
FlowEdge
BackwardPass
GlobOpt
  CopyProp
  IsTypeSpecialized
LinearScan
SCCLiveness
NativeCodeGenerator
Js::InlineCache
DefferedTypeHandler<>
Js::DynamicObject
  ChangeType
Js::Int31
  OverflowHelper -> box to a Js::JavascriptNumber
Js::InterpreterStackFrame

Js::StringBuilderString
Js::SubString

--------------------------------------------------------------------------

2015-02-18: Gaurav Seth, Ed Maurer
Bringing asm.js to the Chakra JavaScript engine in Windows 10, IE Blog

2014-12-15: Tom Care (@tcare_), Brian Terlson (@bterlson), Suwei Chen
Classes in JavaScript: Exploring the Implementation in Chakra, IE Blog

2014-10-09: John-David Dalton, Gaurav Seth, Louis Lafreniere
Announcing key advances to JavaScript performance in Windows 10 Technical Preview, IE Blog
IE11:

Windows 10 Preview:


2013-11-07: Rob Mauceri, Sandeep Singhal
IE11 for Windows 7 Globally Available for Consumers and Businesses, IE Blog
引用
The updated Chakra JIT compiler in IE11 supports more optimizations including inline caches for polymorphic property access, in-lining of functions at polymorphic call sites, and compilation support for specific ECMAScript5 constructs like getters/setters, so even more code is JIT’ed and less time is spent in JavaScript computation. Garbage collection utilizes the background thread much more efficiently, substantially reducing the frequency and amount of time the UI thread is blocked doing garbage collection.


2013-07-25: Sandeep Singhal, Rob Mauceri
IE11 Developer Preview for Windows 7: Enabling Next Generation Sites and Apps - Faster, IE Blog
看,IE11的Chakra也支持对象上的__proto__属性了。真好~
let、const、Set、Map、WeakMap等ES6标准特性也开始支持了。

2013-04-29: Larry Larsen, Andrew Richards, Amanda Silver
Defrag Tools: #38 - JavaScript - Part 2, Channel 9
提到Windows Store app中的bytecode caching。相关的MSDN文档在:Reducing your app's loading time (Windows Store apps using JavaScript and HTML)

2013-04-22: Larry Larsen, Andrew Richards, Amanda Silver
Defrag Tools: #37 - JavaScript - Part 1, Channel 9

2012-11-29:
Writing efficient JavaScript (Windows Store apps using JavaScript and HTML), MSDN

2012-11-01: Scott Hanselman and Luke Hoban
Modern JavaScript, BUILD 2012, Channel 9

2012-10-31: John-David Dalton and Amanda Silver
Building High-Performing JavaScript for Modern Engines, BUILD 2012, Channel 9

2012-10-16: Charles Torre, Lars Bak and Steve Lucco
Lars Bak and Steve Lucco: Chakra, V8, JavaScript, Open Source, Channel 9

2012-10-01: Steve Lucco
The Inner Workings of the Chakra Javascript Engine, GOTO Conference 2012 Aarhus
Slides Video
这组投影片值得一读。一开始就提到了几种JIT hardening的技巧在Chakra里都有实现。后面也形象的描述了IE9与IE10里的Chakra的GC、JIT等组件的实现方式和优化效果。

2012-07-03: Ariya Hidayat
Lazy Parsing in JavaScript Engines

2012-06-14: Andrew Miadowicz
Advances in JavaScript Performance in IE10 and Windows 8, IE Blog, MSDN
10比9的浮点数运算快了50%左右。咋弄的呢?

2012-03-12: Forbes Higman
Enhanced Memory Protections in IE10

2012-01-31:
What is the ProgId or CLSID for IE9's Javascript engine (code-named “Chakra”), StackOverflow
引用
The CLSID for the Chakra Javascript engine installed with IE9 is {16d51579-a30b-4c8b-a276-0ff4dc41e755}

只要指定合适的ID就可以在Windows Scripting Host里使用Chakra。

但要留意的是这样在WSH里使用的Chakra工作于“Quirks模式”(“杂项模式”)而非“IE9模式”。这帖也提到了这行为。
这个模式下的Chakra许多诡异的行为与老JScript一致而与规范或其它JavaScript引擎不同;另外Quirks模式的Chakra也不支持ECMAScript 5。大概有个什么变量能设一下指定Chakra以IE9模式工作,但我还不知道是啥变量。

2011-03-24: Gaurav Seth and Paul Chapman
IE9’s Document Modes and JavaScript, IE Blog

2011-03-10: Steven J. Vaughan-Nichols
Chrome 10 vs. Internet Explorer 9 Reconsidered
主要就是吐槽64-bit的IE9的Chakra没JIT编译器而已

2010-12-08: 黄继佳
IE9及高效互联网体验, Velocity China 2010

2010-11-19: Peter Bright
Lies, damned lies, and benchmarks: is IE9 cheating at SunSpider?

2010-11-18: Dean Hachamovitch
HTML5, and Real World Site Performance: Seventh IE9 Platform Preview Available for Developers
Rob Sayre对此文的后续分析现在找不到了⋯名字是 Dead Code Elimination for Beginners

2010-11-17: Charles Torre, Dean Hachamovitch
Dean Hachamovitch: IE9 - Questions and Answers, Channel 9

2010-10-29: Gaurav Seth
Unlocking the JavaScript Opportunity with Internet Explorer 9

2010-06-26: Allen Wirfs-Brock
Enhanced Scripting in IE9: ECMAScript 5 Support and More, IE Blog

2010-04-09: Charles Torre, Shanku Niyogi, Steve Lucco and GPM John Montgomery
Inside IE 9’s High Performance JavaScript Engine, Channel 9

2010-03-18: Shanku Niyogi
The New JavaScript Engine in Internet Explorer 9, IE Blog

2009-11-18: Charles Torre, John Montgomery, Steve Lucco and Shanku Niyogi
IE 9: First look at the new JS Engine, Channel 9

http://channel9.msdn.com/Blogs/Charles/In-your-hands-IE-9-Performance-From-JS-to-COM-to-DOM-to-HTML5-on-GPU
http://channel9.msdn.com/Shows/Going+Deep/Allen-Wirfs-Brock-and-Chris-Wilson-EcmaScript-5
RednaxelaFX 2013-04-21
JavaScriptCore系
(包括JavaScriptCore/SquirrleFish/SquirrelFish Extreme (SFX)/Nitro/Nitro Extreme)

代码: http://trac.webkit.org/browser/trunk/Source/JavaScriptCore
文档: http://trac.webkit.org/wiki/JavaScriptCore
Bugs: https://bugs.webkit.org/buglist.cgi?query_format=specific&order=relevance+desc&bug_status=__all__&product=WebKit&content=JavaScriptCore
Stack Overflow tag: http://stackoverflow.com/questions/tagged/javascriptcore

参与人物
Filip Pizlo

--------------------------------------------------------------------------

我的评论:

JavaScriptCore源自KJS,但持续得到苹果的大力投入,终而青出于蓝胜于蓝,已经完全超越了它的前身。

QtScript背后也使用JavaScriptCore。
2009-06-16: Kent Hansen
Using JavaScriptCore as the QtScript Back-end

Register-based bytecode SquirrelFish Bytecode Specification
Direct-threaded interpreter

隐藏类叫做Structure,隐藏类迁移叫做structure transition,记录在StructureTransitionTable里。

虽然iOS的Safari和UIWebView控件里跑的都是JavaScriptCore,但只有Apple自己的程序才可以启用JIT编译,而第三方的则不行。所以Mobile Chrome for iOS就用不了JavaScriptCore的JIT。呃呵呵。
不过通过jailbreak可以让iOS上的第三方应用都用上这JIT:http://www.idownloadblog.com/2012/07/30/nitrous/

新解释器LLint是用汇编写的。老解释器也还可以用,但是如果要用JIT的话在新版JavaScriptCore里只能跟LLint搭配而不能跟老解释器搭配使用了

JavaScriptCore的tiered compilation: Bug 67176: JavaScriptCore does not have tiered compilation
然后确定为三层:
Bug 75812: JSC should be a triple-tier VM

JavaScriptCore还准备要有一个“第四层JIT编译器”(FTL,Fourth-tier LLVM),拿LLVM作为JIT的后端,期望在DFG的基础上进一步提升优化效果。
http://trac.webkit.org/wiki/FTLJIT

http://trac.webkit.org/attachment/wiki/JavaScriptCore/JavaScriptCore%20slides.pdf
Optimizing JavaScript

--------------------------------------------------------------------------

2014-07-16: Andrew Trick
FTL: WebKit’s LLVM based JIT, LLVM Project Blog

2014-05-13: Filip Pizlo
Introducing the WebKit FTL JIT, Safari Blog

2013-05-08: Gabor Rapcsanyi
Comparison of JavaScript execution modes of the WebKit browser engine

2013-02-07: Aaron M Brown
JavaScriptCore Value Encoding

2012-12-06: 鈴木勇介
JSC Array optimization for adding new property

2012-11-07: Andy Wingo
Andy Wingo: JavaScriptCore's DFG JIT, JSConf EU 2012, YouTube

2012-07-03: Ariya Hidayat
Lazy Parsing in JavaScript Engines

2012-06-27: Andy Wingo
inside javascriptcore's low-level interpreter

2012-03-01: Daniel Eran Dilger
New low level JavaScript interpreter to boost WebKit performance more than 200%, Apple Insider

2011-10-28: Andy Wingo
JavaScriptCore, the WebKit JS implementation

2011-05-18: Andy Wingo
value representation in javascript implementations

2009-08-21: 莫枢
[草稿帖][2009-08-21][JavaScript][V8][Nitro] 响应号召,放一个V8/Nitro相关的草稿出来, HLLVM群组

2009-01-10: Mason Chang
The Art of SquirrelFish's Bytecode Generation

2008-10-06: David Mandelin
Squirrelfishing regexp-dna.js

2008-09-20: 莫枢
Webkit的SquirrelFish Extreme

2008-09-18: Maciej Stachowiak
Introducing SquirrelFish Extreme, Surfin' Safari Blog

2008-09-03: 莫枢
简记V8与SquirrleFish/Tamarin的对比点

2008-06-03: David Mandelin
SquirrelFish

2008-06-02: Geoffrey Garen
Announcing SquirrelFish, Surfin' Safari Blog
RednaxelaFX 2013-04-21
Carakan

--------------------------------------------------------------------------

我的评论:

“大篷车”JavaScript引擎…好含蓄的名字。
基本上是Jens Lindström单兵作战的产物。能短时间内写出那么多代码的都是神啊。
(顺带:才留意到Opera是挪威公司…)

Opera今年决定放弃自行研发浏览器的渲染引擎和JavaScript引擎,转而投向基于Chromium来做定制开发。Carakan的生命也就基本到此为止,目前Opera只有非常少量的产品(例如Sphinx)还在使用Presto/Carakan,其它主线产品都改为使用Blink/V8的组合了。
可惜Opera没发发善心把Carakan开源出来。

前身有
Linear A
Linear B
Futhark

Register-based bytecode
有polymorphic inline cache,每个cache最多记录10个隐藏类。

有独特的地方在于它有pseudothread,看起来跟green thread相似。

--------------------------------------------------------------------------

2013-02-12: Bruce Lawson
300 million users and move to WebKit

2010-02-28: 莫枢
JägerMonkey与Carakan动态更新

2009-12-22: Jens Lindström
Carakan Revisited 新链接

2009-02-04: Jens Lindström
Carakan 新链接
RednaxelaFX 2013-04-21
KJS

文档: http://api.kde.org/4.x-api/kdelibs-apidocs/tier1/kjs/src/kjs/html/index.html
http://api.kde.org/4.0-api/kdelibs-apidocs/kjs/html/index.html
兼容标准: ECMAScript 3
开源许可证: LGPLv2
代码: https://projects.kde.org/projects/kde/kdelibs/repository/revisions/master/show/kjs
代码版本控制工具: Git

Shell: kjscmd

--------------------------------------------------------------------------

我的评论:

Apple把KHTML拿去演化出了WebKit,其中的KJS演化成了JavaScriptCore。但现在KJS已经远不如JavaScriptCore。可能是现在还能算得上主流的JavaScript引擎里唯一一个没有JIT编译器的。好吧KJS要说现在还是主流或许还是太勉强了。

现在要获取最新的KJS源码要通过Git把整个kdslibs给clone下来,要单独clone出KJS那个目录挺麻烦的。

JavaScript对象的实现类是JSObject。属性存在hashmap里,PropertyMap。

对一般JSObject,整数下标访问对象属性时整数先被转换为字符串然后转换为Identifier(一种驻留字符串)然后再拿到PropertyMap(概念上是一个Identifier -> PropertySlot的映射的hashmap,内部实际上是Identifier -> JSValue的映射)去访问。
拿到PropertySlot之后倒是有专门针对unsigned下标的访问特化,但跟Identifier版重载基本上一样。
class KJS_EXPORT PropertySlot {
  JSValue *getValue(ExecState *exec, JSObject *originalObject, unsigned propertyName) const { … }
}

其实已经有足够基础设施来实现针对整数下标的属性访问和存储的优化。
对JSArray,整数下标的访问就有优化了。
ALWAYS_INLINE bool ArrayInstance::inlineGetOwnPropertySlot(ExecState* exec, unsigned i, PropertySlot& slot)
存储也有优化,同时针对密集数组与稀疏数组。紧密数组的内容存在ArrayStorage对象末位的vector里,稀疏数组内容存在一个HashMap<unsigned, ArrayEntity>里

PropertySlot是一个用来统一存储在不同地方的属性的flyweight object。

RefPtr<T>与STL的shared_ptr<T>类似。

Function.prototype.toString()
  -> FunctionImp::toSource() decompiles the AST to source form; lossy (comments lost); can be used as a JavaScript source formatter / pretty-printer. There's even an API exposed for that purpose: Interpreter::normalizeCode()

Interpreter limits recursion count to 20 (weird?)

AST is kept around. Compilation to bytecode is lazy, compile function body to bytecode upon first invocation of the function

--------------------------------------------------------------------------

2008-03-10: Maksim Orlovich
Say hello to KJS/Frostbyte -40.9° and Icemaker

2008-02-09: 莫枢
KJS的一些简略笔记

2005-07-14: Martijn Klingens
Apple reduced the diff between JavaScriptCore's and KHTML's kjs
RednaxelaFX 2013-04-21
IronJS

官方网站: http://ironjs.wordpress.com/
代码:https://github.com/fholm/IronJS
兼容标准: ECMAScript 3.0
实现语言: F# (parser)/C# (runtime)

主要人物: Fredrik Holmström

--------------------------------------------------------------------------

我的评论:

IronJS原本完全使用F#实现,后来改为只用F#来实现parser,而用C#来实现runtime部分。这是个非常妙的搭配。F#(以及许多函数式语言)天生就非常适合用来写需要大量模式匹配的程序,写parser最适合不过。而runtime部分更多是与.NET的其它部分打交道,这里用C#就会更顺手些。

IronJS的parser整体采用top-down operator precedence(TDOP)方式,在JavaScript的引擎实现中比较少见。不过却正好与微软自家的Managed JScript相似。不知道作者在写IronJS时是否有受Managed JScript的思路影响呢?
如果采用TDOP不是Managed JScript的影响,那或许是受Douglas Crockford大神那篇TDOP教程的影响了。

最初的IronJS其实用的是基于ANTLR生成的parser。不过后来用F#新写的parser比老的ANTLR生成的parser快得多。

不过作者决定在下一版IronJS里改为完全使用C#,主要是出于性能方面的考虑。并不是F#本身不够快,而是F#的各种方便简洁的功能容易引人写出不那么快的代码,而要写比较高效的代码样子会跟C#看起来很像。于是还不如直接用C#好了。

IronJS的对象模型有采用hidden class,叫做Schema,记录着属性名到属性数组下标的映射关系。基本对象由CommonObject实现,里面装属性值的是一个Descriptor数组。有实现monomorphic inline cache

IronJS使用了Nan-boxing,只不过比起那些用C/C++之类的native语言所实现的NaN-boxing tagged pointer而言,IronJS版的比较“肥”一些——例如说JavaScriptCore的一个tagged pointer在x86-64上就是64位,跟一个double一样大,指针类型的值跟值类型的值可以重叠在同一个位置上;而在IronJS的则要128位,其中值类型的值与tag在头64位,而指针类型在后64位。
虽然肥一些,作为Nan-boxing的思路和效果还是类似的。用了tagged pointer之后至少那些值类型的值的内存开销都变小了——不用tagged pointer的话自动装箱的double在32位CLR上也至少得要16字节,外加引用它的指针4字节也得要20字节了,而IronJS的BoxedValue则总共只要16字节而且不会有额外指针带来的间接层,在内存局部性上也比不用tagged pointer好。

--------------------------------------------------------------------------

2012-07-11: Nikos Vaggalis
IronJS - In Conversation with Fredrik Holmström

2012-04-19: Fredrik Holmström
Why not F#?

2011-08-30: Niladri Biswas
A basic tour of IronJS

2011-06-29:
CoffeeDemo - A Simple Demo of IronJS, using CoffeeScript

2011-06-21: Scott Hanselman
Hanselminutes Podcast 271 - Inside IronJS - A complete JavaScript/ECMAScript open source implementation on the .NET DLR

2011-06-02: Wynn Netherland
Episode 0.6.2 – IronJS with Fredrik Holmström, The Changelog

2011-04-26:
IronJS on Ubuntu/Mono

2011-04-25: Fredrik Holmström
IronJS is now faster than IE8

2011-04-19: Fredrik Holmström
IronJS 0.2 is out

2011-03-28: Rob Paveza
A Recent Discovery: IronJS

2011-03-26: Fredrik Holmström
JavaScript Quotations

2011-03-22: Fredrik Holmström
Analyzer: Single-Pass vs. Multi-Pass

2011-03-19: Fredrik Holmström
New lexer and parser in IronJS

2011-03-13:
Embedding IronJS
Global site tag (gtag.js) - Google Analytics