[讨论] 关于一些JavaScript引擎最近的动态

RednaxelaFX 2011-05-03
先占位,回头再更新填充内容。有人补充的话请跟帖放链接或评论。

IonMonkey
David Mandelin's blog: Mozilla JavaScript 2011
InfoQ: IonMonkey: Mozilla’s new JavaScript JIT compiler

Crankshaft
Chromium Blog: A New Crankshaft for V8
David Mandelin's blog: Crankshaft

关键对比点之一就是,Crankshaft主要依靠type profiling来支撑type specialization并进行优化;而IonMonkey则主要依靠type inference来支撑。这个取舍就有趣了——类型推导是件很耗时的事,在运行时做类型推导是否能带来足够好的cost-benifit效果呢。

同样是要获取类型信息,
type inference:纯类型推导的话一次也不用跑,也可以灵活的配合多次运行来收集类型数据
tracing:跑一次
profile:跑多次

Miuraさん看来对此也很感兴趣,连发了几推:
Miura Hideki 写道
@miura1729: モジラの新Javascriptエンジン、インクリメンタルな世代別GCに型推論か。パフォーマンスが出ても出なくても興味深い。 http://blog.mozilla.com/dmandelin/2011/04/22/mozilla-javascript-2011/

@miura1729: ブラウザ内蔵だと型推論の性能向上とコンパイル時間のトレードオフだな。Javascriptで型推論を入れたのは初めてのような気がするけど、あったのかなー?

@miura1729: IonMonkeyはSSAベースのIRか。type specializationとか動的型付け言語に嬉しそうな機能も持っているので、完成度次第ではIonMonkeyのIRをターゲットにしたコンパイラもおもしろそうだ。

@miura1729: crankshaftはプロファイルベースの型付け。次世代Firefoxは型推論による型付け。どっちが速いか見ものだ。


Bug 557407 - Introduce Javascript type inference
https://bugzilla.mozilla.org/show_bug.cgi?id=557407

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

Crankshaft

引用
Crankshaft has four main components:
  • A base compiler which is used for all code initially. The base compiler generates code quickly without heavy optimizations. Compilation with the base compiler is twice as fast as with the V8 compiler in Chrome 9 and generates 30% less code.
  • A runtime profiler which monitors the running system and identifies hot code, i.e., code that we spend a significant amount of the time running.
  • An optimizing compiler which recompiles and optimizes hot code identified by the runtime profiler. It uses static single assignment form to perform optimizations such as loop-invariant code motion, linear-scan register allocation and inlining. The optimization decisions are based on type information collected while running the code produced by the base compiler.
  • Deoptimization support which allows the optimizing compiler to be optimistic in the assumptions it makes when generating code. With deoptimization support, it is possible to bail out to the code generated by the base compiler if the assumptions in the optimized code turn out to be too optimistic.


Crankshaft里的优化编译器里有两个重要组成部分,HydrogenLithium。前者是一种HIR(High-level Intermediate Representation),而后者是一种LIR(Low-level Intermediate Representation);它们名字的由来也应该跟HIR/LIR的首字母相关吧 ^_^

Hydrogen采用了SSA形式。SSA即静态单赋值(Static Single Assignment)。多数平台无关的优化都在这一层实现。
追溯V8的Crankshaft的血缘发现貌似能跟Modula-2/Oberon扯上关系。至少Hydrogen跟HotSpot C1的HIR改为SSA形式后很像。不过HIR用(BlockBegin,BlockEnd)标识基本块,而Hydrogen有显式的HBasicBlock
简单收集了一下Hydrogen IR的类层次结构:
HValue
  HPhi
  HInstruction
    HSimulate
    HControlInstruction
      HTemplateControlInstruction
        HTemplateControlInstruction<0>
          HGoto
          HAbnormalExit
        HTemplateControlInstruction<1>
          HUnaryControlInstruction
            HTest
            HCompareMap
            HReturn
      HDeoptimize
    HTemplateInstruction
      HTemplateInstruction<0>
        HBlockEntry
        HStackCheck
        HEnterInlined
        HLeaveInlined
        HContext
        HCheckPrototypeMaps
        HArgumentsObject
        HConstant
        HArgumentsElements
        HIsConstructCall
        HOsrEntry
        HParameter
        HUnknownOSRValue
        HLoadGlobalCell
      HTemplateInstruction<1>
        HUnaryOperation
          HThrow
          HChange
          HPushArgument
          HOuterContext
          HGlobalObject
          HGlobalReceiver
          HJSArrayLength
          HFixedArrayLength
          HExternalArrayLength
          HBitNot
          HUnaryMathOperation
          HLoadElements
          HLoadExternalArrayPointer
          HCheckMap
          HCheckFunction
          HCheckInstanceType
          HCheckNonSmi
          HCheckSmi
          HArgumentsLength
          HUnaryPredicate
            HIsNull
            HIsObject
            HIsSmi
            HHasInstanceType
            HHasCachedArrayIndex
            HGetCachedArrayIndex
            HClassOfTest
            HTypeofIs
          HInstanceOfKnownGlobal
          HStoreGlobalCell
          HLoadContextSlot
          HLoadNamedField
          HLoadNamedFieldPolymorphic
          HLoadFunctionPrototype
          HStringCharFromCode
          HStringLength
          HTypeof
          HToFastProperties
          HValueOf
      HTemplateInstruction<2>
        HBinaryOperation
          HArithmeticBinaryOperation
            HAdd
            HSub
            HMul
            HMod
            HDiv
          HBitwiseBinaryOperation
            HBitAnd
            HBitXor
            HBitOr
            HShl
            HShr
            HSar
          HPower
          HBoundsCheck
          HCompare
          HCompareJSObjectEq
          HLoadGlobalGeneric
          HStoreContextSlot
          HLoadNamedGeneric
          HLoadKeyedFastElement
          HLoadKeyedSpecializedArrayElement
          HStoreNamedField
          HStringAdd
          HStringCharCodeAt
          HDeleteProperty
        HIn
      HTemplateInstruction<3>
        HAccessArgumentsAt
        HInstanceOf
        HStoreGlobalGeneric
        HLoadKeyedGeneric
        HStoreNamedGeneric
        HStoreKeyedFastElement
        HStoreKeyedSpecializedArrayElement
      HTemplateInstruction<4>
        HApplyArguments
        HStoreKeyedGeneric
      HTemplateInstruction<V>
        HCall
          HCall<0>
            HCallConstantFunction
            HCallKnownGlobal
            HCallRuntime
          HCall<1>
            HUnaryCall
              HCallNamed
              HCallFunction
              HCallGlobal
              HCallStub
          HCall<2>
            HBinaryCall
              HInvokeFunction
              HCallKeyed
              HCallNew
        HMaterializedLiteral
          HMaterializedLiteral<0>
            HArrayLiteral
            HRegExpLiteral
            HFunctionLiteral
          HMaterializedLiteral<1>
            HObjectLiteral

Hydrogen IR的组织方式跟HotSpot VM的C1里的HIR有相似之处,但除了类型系统及语言功能的差异外,但看IR的组织方式两者也有显著不同的地方:在Hydrogen里HBasicBlock不是HInstruction的派生类,而在HIR里BlockBegin是Instruction的派生类。

Lithium则用于平台相关优化以及最终的代码生成。平台相关优化中最典型的一部分就是寄存器分配,这里Lithium采用的是线性扫描寄存器分配(Linear-Scan Register Allocation)算法。

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

顺带一提,JavaScript的犀牛书出第六版了。对EcmaScript 5感兴趣的同学们可以关注一下。

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

顺便把最近几个tagged pointer相关链接放上来。
value representation in javascript implementations, 2011-05-18
NS: 高空间利用率的Tagged Pointer的浮点数表示, 2011-06-01 <- 编辑:链接已死,用名字来搜出镜像吧
mozilla.dev.tech.js-engine: jsval/JSAPI changes Options, 2010-07-14

还有一篇对最佳的JS引擎发展的评论:
javascript in 2011
Global site tag (gtag.js) - Google Analytics