《各 JavaScript 引擎的简介,及相关资料》

[链接帖] 各 JavaScript 引擎的简介,及相关资料 / 博客收集帖 - 资料 - 高级语言虚拟机 - ITeye 群组之前一直有同学在问,于是开个帖来收集 JavaScript 引擎的资料链接。

之前一直有同学在问,于是开个帖来收集 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 楼: 杂项未整理资料

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 JVMgeecon 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

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

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 的时候靠这些上下文信息来减少麻烦,增加 “预测” 的准确性。

C++ 代码  

  1.   
  2.   
  3.   
  4.   
  5.   
  6.   
  7.   
  8.   
  9.   
  10.   
  11.   
  12.   

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 的常量折叠

Javascript 代码  

  1. function foo() { return 1 + 2 }  

X64 asm 代码  

  1. --- Raw source ---  
  2. () { return 1 + 2 }  
  3.   
  4. --- Optimized code ---  
  5. kind = OPTIMIZED_FUNCTION  
  6. name = foo  
  7. stack_slots = 0  
  8. Instructions (size = 54)  
  9. 0x34af9a343880     0  55             push rbp  
  10. 0x34af9a343881     1  4889e5         REX.W movq rbp,rsp  
  11. 0x34af9a343884     4  56             push rsi  
  12. 0x34af9a343885     5  57             push rdi  
  13.                   ;;; <@0,#0> -------------------- B0 --------------------  
  14.                   ;;; <@4,#4> context  
  15. 0x34af9a343886     6  488bc6         REX.W movq rax,rsi  
  16.                   ;;; <@8,#7> -------------------- B1 --------------------  
  17.                   ;;; <@10,#9> stack-check  
  18. 0x34af9a343889     9  493b6548       REX.W cmpq rsp,[r13+0x48]  
  19. 0x34af9a34388d    13  7305           jnc 20  (0x34af9a343894)  
  20. 0x34af9a34388f    15  e86c7ffcff     call 0x34af9a30b800     ;; code: STUB, StackCheckStub, minor: 0  
  21.                   ;;; <@12,#14> constant-t  
  22. 0x34af9a343894    20  4b8d0464       REX.W leaq rax,[r12+r12*2]  
  23.                   ;;; <@14,#12> return  
  24. 0x34af9a343898    24  488be5         REX.W movq rsp,rbp  
  25. 0x34af9a34389b    27  5d             pop rbp  
  26. 0x34af9a34389c    28  c20800         ret 0x8  
  27. 0x34af9a34389f    31  6690           nop  
  28. 0x34af9a3438a1    33  0f1f00         nop  
  29.                   ;;; Safepoint table.  
  30.   
  31. Deoptimization Input Data (deopt points = 1)  
  32.  index  ast id    argc     pc               
  33.      0       3       0     20  
  34.   
  35. Safepoints (size = 18)  
  36. 0x34af9a343894    20  11111111 (sp -> fp)       0  

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

X64 asm 代码  

  1. 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

引用

Javascript 代码  

  1.   
  2. var model = {};  
  3.   
  4.   
  5. Object.observe(model, function(changes) {  
  6.   
  7.       
  8.     changes.forEach(function(change) {  
  9.   
  10.           
  11.         console.log(change.type, change.name, change.oldValue);  
  12.     });  
  13.   
  14. });  

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.

Javascript 代码  

  1. function make() {  
  2.   function maker() {}  
  3.   return new maker();  
  4. }  
  5.   
  6. var a = make(), b = make();  
  7.   
  8.   

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

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 的行为:

Javascript 代码  

  1. js> function foo () {  return 42 }  
  2. js> foo  
  3. function foo() {return 42;}  
  4. 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

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

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

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 新链接

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

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

全文完

本文由 简悦 SimpRead 优化,用以提升阅读体验
使用了 全新的简悦词法分析引擎 beta点击查看详细说明
 
原文地址:https://www.cnblogs.com/cx2016/p/13197176.html