Archive

Archive for September, 2012

SunSpider 0.9.1 Test

September 26th, 2012 No comments

在线测试了一下笔记本上Windows环境下三个浏览器的 SunSpider 0.9.1 跑分,竟然是 Chrome 落后。不过绝对的分值看起来都差不多。具体的数据如下:

Browser Score(ms)
Firefox 15.0.1 400.2ms +/- 2.1%
IE 9.0.10 408.3ms +/- 2.0%
Chrome 22.0.1229.79 426.9ms +/- 7.8%
Firefox 14.0.1 471.9ms +/- 2.7%

实验用的机器是老机器,所以跑出来的时间都比较长。

如果你有兴趣,可以点击这里测试一下你的浏览器得分

SpiderMonkey代码变动:jskeyword.tbl被删除

September 20th, 2012 No comments

今天更新 Mozilla-Central 代码的时候发现 jskeyword.tbl 文件没有了。这个文件用于定义 JavaScript 输入文件中的关键字信息。删除后 Keyword 信息还是需要的,所以应该定义到别处了。查看了使用关键字信息的 frontend/ 下的文件,并没有增加相应的代码。使用 hg log 搜索了一下发现了改动来自这个patch:

这个 patch 将 jskeyword.tbl 中的内容移动到了 vm/Keywords.sh 中,使用的宏定义看起来也不比之前可读性好。
另外不太明白为什么要把 Keyword.h 放在 vm/ 目录下。

参考

通过网页方式查看该 Patch
Mozilla Bugzilla #790349 链接

IonMonkey分析:目录结构

September 16th, 2012 No comments

本文的内容整理自 https://wiki.mozilla.org/IonMonkey/Overview

IonMonkey的代码位于“Mozilla-central/js/src/ion”目录下,目前有149个文件,4个子目录,代码43679行。从编译器的角度来说这个代码的规模还不算大,结构相对简单。根据Mozilla Wiki的这张结构图可以看到IonMonkey使用了MIR和LIR两层IR结构:

Ionmonkey_overview

IonMonkey结构

IonMonkey的代码可以按照这张结构图分成以下几个部分:

  • 前端,将JavaScript字节码翻译到MIR:
    • IonBuilder.* 将字节码翻译到MIR,比较大,6801行代码;
    • MIR.* 组成MIR的类,共6979行代码;
    • MIRGenerator.h :不到一百行代码,不知道是什么东西;
    • MIRGraph.* :1407行代码,基本块和控制流图构建与维护;
    • MOpcodes.h:MIR操作码,定义了117个opcode。SpiderMonkey的其它模块都将操作码等数据放在*.tbl文件中,或许该文件也会在后续被分拆出来。
  • 在MIR上进行的分析和优化;
    • IonAnalysis.{cpp,h} :一些小的分析算法,例如计算DominatorTree,计算Phi节点等。1052行代码;
    • LICM.{h,cpp}:循环不变量外提代码,总共661行代码;
    • TypeOracle.h:Type Oracle的接口文件,379行代码;
    • TypePolicy.{h,cpp}:定义类型具体化的规则,共739行代码;
    • ValueNumbering.{h,cpp} :全局值编号算法;
  • 将MIR转译到LIR的Lowering过程;
    • Lowering.* 生成LIR结构。
    • LIR-Common.h:硬件平台通用的LIR指令,三千多行;
    • LOpcodes.* :平台通用的LIR opcode。
      • shared/Lowering-x86-shared.* :x86和x64共用的LIR代码;
      • <arch>/Lowering-<arch>.* :平台特定的LIR代码;
      • <arch>/LIR-<arch>.h : 平台特定的LIR指令;
      • <arch>/LOpcodes-<arch>.h :平台特定的LIR opcode;
  • 寄存器分配、指令调度、代码生成;
    • GreedyAllocator.* – 贪心寄存器分配算法.目前还没有出现在主分支中;
    • LinearScan.* – 线性扫描分配器算法;
    • CodeGenerator.* :代码生成功能入口,包含了很多共用代码;
      • shared/CodeGenerator-shared.* :可以被所有平台使用的代码生成逻辑;
      • shared/CodeGenerator-x86-shared.* :x64和x86平台共用的代码;
      • <arch>/CodeGenerator-<arch>.* :特定平台的代码;
    • MoveResolver.* :目前不清楚是干什么的,Mozilla Wiki的原文是“Performs cycle detection and topological sorting of parallel moves.”;
    • shared/MoveEmitter-x86-shared.*: 目前不清楚是干什么的,Mozilla Wiki的原文是“Emits a sequence of parallel moves that have been cycle-detected and topologically sorted.”
    • <arch>/StackAssignment-<arch>.h:RA算法用到的辅助类,用于在栈上分配空间。
    • <arch>/Architecture-<arch>.h:硬件平台信息,例如寄存器数量和名字,调用规范等。
    • IonRegisters.h:寄存器交互相关的C++辅助类。
    • IonMacroAssembler.h:平台无关的汇编辅助类。
    • shared/MacroAssembler-x86-shared.h:x86和x64共享的抽象汇编器类。
    • <arch>/MacroAssembler-<arch>.h:x86的汇编类。
    • Assembler-shared.h:用于进行代码汇编的数据结构。
    • shared/Assembler-x86-shared.h:x86和x64共享的指令集辅助类。
    • <arch>/Assembler-<arch>.*:平台相关的指令集辅助类。
    • IonLinker.h*:将生成好的代码移动到可执行内存页中。
  • 运行时支持:
    • Bailouts.* :当遇到类型推测失败等情况时使用。David在邮件列表中说“A guard failure, type-inference invalidation, or GC can cause a “bailout”. A bailout is when an Ion frame on the stack must be converted back into an interpreter frame. When this happens, interpreter frames are created for each JS frame in the Ion frame (there can be multiple because of inlining), and we resume running the function in the interpreter instead.”
      • <arch>/Bailouts-<arch>.* – 平台相关的bailout辅助类。
    • <arch>/Trampolines-<arch>.cpp – 平台相关的trampolines类.
  • 数据结构及其它辅助代码:
    • IonCode.h :IonCode、IonScript的声明;
    • IonCompartment.h :IonCompartment的声明;
    • IonFrames.h :Ion frames布局声明;
    • BitSet.* :一个任意大小的比特集合实现。
    • C1Spewer.*:调试用的一个工具;
    • FixedArityList.h :模板,生成固定大小的向量类;
    • InlineList.h :来对象之间内建链表结构;
    • IonAllocPolicy.h :基于内存池的分配实现;
    • IonSpewer.* :调试用工具;
    • JSONSpewer.* :JSON调试用工具。

[译]IonMonkey in Firefox 18

September 13th, 2012 No comments

注:本文是对David Anderson这篇博客文章的翻译。David介绍了IonMonkey的性能提升的内部架构,同时表示将在未来几周写更多的文章介绍IonMonkey。本博客将持续关注并翻译。

今天我们在Firefox 18中启用了我们最新的JavaScript JIT编译器,IonMonkey。IonMonkey不仅对JavaScript的执行性能有很大的提高,也是我们的编译器架构有了很大的进步。IonMonkey花费了超过一年的时间开发,我们都超级兴奋。

SpiderMonkey跟JIT的关系源远流长,但是你会发现SpiderMonkey的JIT编译器中缺少一个现代编译器,例如Java或C++编译器中都有的步骤。无论是老的TraceMonkey(作者注1)还是新的JaegerMonkey,都基本上是直接把JavaScript(从字节码)翻译到机器码。没有中间步骤,所以编译器也就没有办法看到翻译的结果,也就无法进一步的优化它们。

IonMonkey提供了一个全新的框架,使得我们可以做到这一点。它可以分成以下三步:

  1. 将JavaScript翻译成中间表示(IR);
  2. 运行多种算法优化IR;
  3. 将IR翻译成机器码。

让我们开心的不仅仅是性能和可维护性的提升,而且使得未来的JS编译器研究更加的简便。现在,有了IonMonkey,你就能够写一个新的优化,插入到流水线中,看看效果如何了。(译注:估计是受到了LLVM的启发?)

性能测试

IonMonkey针对的是长时间运行的程序,对于短程序还是用JaegerMonkey。我(David Anderson)在我跑着Windows 7专业版的MAC Pro笔记本上(译注1)运行了Google的V8基准测试和Kraken基准测试,性能提升了26%。Firefox 17运行了2602ms,Firefox 18运行了1921ms。效果如下图所示,越高越好。

IonMonkey-Kraken-result

Kraken基准测试结果

Google V8测试上Firefox 15得分为8474,Firefox 17得分为9511.Firefox 18得分最高,为10188,比Firefox 17快7%,比Firefox 15快50%。

V8基准测试结果

我们还有很多的工作需要去做。未来的一段时间我们将继续对IonMonkey进行测试,包括基准测试和真实的程序。

团队

对于我们而言IonMonkey最酷的部分就是我们是一个高度协作的团队。2011年6月的时候我们创建了一个大概的计划,然后估计大概需要一年的时间完成。我们招了四个实习生——Andrew Drake, Ryan Pearl, Andy ScheFirefox , 和 Hannes Verschore ——他们都参与实现了IonMonkey的核心组件,现在代码库中还有他们的代码。

2011年8月下旬我们开始组建全职团队,包括Jan de Mooij, Nicolas Pierron, Marty Rosenberg, Sean Stangl, Kannan Vijayan,还有我自己。(还有原SpiderMonkey开发者Chris Leary,2012年暑期实习生Eric Faust)。过去一年中我们齐头并进,搭出了总体的架构,确保其设计和代码质量都达到了最好,并且确实提升了JS的性能。

感谢我们所有的团队成员,大家为了一个目标一起合作的感觉太棒了。

技术

未来的几周我们将会发一些帖子介绍IonMonkey的主要组成以及工作原理。简而言之我将着重介绍IonMonkey中现有的优化技术:

  • Loop-Invariant Code Motion (LICM)(循环不变量外提);
  • Sparse Global Value Numbering (GVN), (稀疏全局值编号?);
  • Linear Scan Register Allocation (LSRA), 线性扫描式寄存器分配算法;
  • Dead Code Elimination (DCE), 死代码删除;
  • Range Analysis; 边界分析(译注2);

另外,我想指出IonMonkey能够运行在所有的Tier-1平台(译注3)上。编译器架构在设计上考虑了平台移植性的问题,大多数平台无关的代码都被抽取了出来,基本上只有汇编器是需要平台相关的。我们对此深感自豪。

何时,何地?

IonMonkey将在Firefox 18默认开始,Firefox 18现在是Firefox Nightly状态,将在10月8号变成Aurora,在11月10号进入beta版本。

作者注1:TM其实是有一个中间层额,但是能力非常的有限(limited),无法处理after-the-fact类型的优化。

译者注1:这个配置,想起来“普通青年Thinkpad+Windows,文艺青年Mac Pro + Mac OS……”

译者注2:参见Ryan Pearl和Michael Sullivan的这篇论文(PDF)

译者注3:Tier-1平台包括以下配置

  • Android Linux/ARMv7 and ARMv6 (gcc)
  • Linux/x86 and x86-64 (gcc)
  • OS X/x86 and x86-64 (clang)
  • Windows/x86 (msvc)

 

IonMonkey并入Mozilla-Central主分支

September 12th, 2012 No comments

根据Firefox JS Engine邮件列表中的这封邮件(墙),Mozilla的(第三个)JavaScript编译器IonMonkey已经基本成熟,在昨天并入了Mozilla-Central主分支。在更新了mozilla代码库之后能够看到js/src目录下新增加了一个“ion”目录,里面包含了IonMonkey的代码。

目前IonMonkey目录中包含了148个文件,其中C++头文件91个。代码共43613行。

使用hg命令可以看到是Ehsan Akhgari(博客)进行的合并:
changeset: 106839:d50bf1edaabe
parent: 106838:7612ff8a7fce
parent: 106791:fdfaef738a00
user: Ehsan Akhgari <ehsan AT mozilla.com>
date: Tue Sep 11 16:38:44 2012 -0400
summary: Merge IonMonkey into mozilla-inbound

目前IonMonkey已经能够在Firefox中默认使用,但是单独编译的JS Shell还无法启用,虽然在测试的时候可以用“–ion”(默认开启)和“–no-ion”来开启或关闭IonMonkey。

IonMonkey是Mozilla开发的下一代JS编译器,主要的设计目标有两个

  1. 良好的工程设计,能够方便的添加新的优化;
  2. 允许为了生成高效的代码而进行的Specializaion。

关于IonMonkey的介绍可以看这里这里,和这里