JavaScriptCore, WebKit的JS实现(一)

简介: 什么是method JIT? 什么是DFG JIT? JSC的DFG JIT与V8 Crankshaft相比有何优劣? JIT:一个方法式的JIT(a method jit) *关于method JIT,可以参考另一份档案。

什么是method JIT? 什么是DFG JIT? JSC的DFG JIT与V8 Crankshaft相比有何优劣?

JIT:一个方法式的JIT(a method jit)

*关于method JIT,可以参考另一份档案

关于解释器(interpreter)和堆栈(stack,也就是寄存器文件,register file)都是应用了方法式JIT(method JIT). 所谓简单方法JIT(确实没什么特别的名字)做得事和字节码解释器完全一样,只不过它的结果是机器码,而不是虚拟的机令集。

 

也没什么好说的,JIT的结果可以减少调度的开销,特别是允许对特定上下文进行编译时(原文:jitting the code has the result you would expect, reducing dispatching overhead, while at the same time allowing some context-specific compilation), 就比如当给一个变量赋个整数常量。这个JIT只能算是凑合(quick-and dirty), 所以传统的Method JIT,像HotSopt C1及C2, 并没有明显的好处。相对而言,寄存器式的VM字节码却保证可以为JSC带来显著的提升,不过到目前为止,JSC在这个方向上并没做什么。

 

再思考一下,我认为对于JavaScript而言,CSE只有在你知道类型时才可能有作用,毕竟JS的valueOf()并不那么靠谱!

 

DFG:JSC的Crankshaft? (dfg: a new crankshaft for jsc)?

由Gavin Barraclough和Filip Pizlo开发的数据流图JIT(data flow graph,DFG JIT)是一种推测性优化技术。比如,当有如下JS代码:

a[i++] = 0.7*x;

那么a很可能是一个浮点型数组,而i则很可能是一个整数。你应该可以想到,如果使用原始的数组和整数操作,就能达到很好的性能,于是尝试着将这份代码按照这个假设编译出了一个新的版本。如果这个方法最终失败了(有不符先前假设的情况发生了),就把这份代码中全身而退(bail out),再回到原先的method JIT。

 

事实上,解释器(interpreter)和simple method JIT有一个清晰的字节码语义模型来确保在必要时从DFG JIT中轻易地退出来。只需要重建虚拟寄存器和Register Windows(奇怪的名字,和register file一样. ^_^)的状态,然后跳转回原先的代码即可。 (V8 称之为"逆优化(deoptimization)"; DFG则称之为"投机不成(speculation failure)".)

 

还有另一种从simple JIT跳转到DFG JIT的方法,叫栈上替换(on-stack replacement, OSR). DFG JIT就是这样做的。我就听说用了OSR就可以在Kraken(一个JS性能测试器)测试中胜出,这个测试器会使用大量紧凑的循环,所以你必须能够在不依赖函数的反复进入的情况下优化你的代码(Method JIT就是这么干的!)。

 

当DFG JIT启用后,解释器(如果有的话)和简单方法(simple method) JIT会对性能数据进行判断,它会记录代码各部分的流转类型(flow types)。如果一个循环被执行相当次数(目前是大于1000次),或者一个函数会调用了很多次(目前是70次), DFG JIT就会行动了。它将相应的字节码解析为SSA(Static Single Assignment)形式, 然后沿着执行路径收集类型信息。这个过程很像我在另一篇文章中所说明的情形。

 

JSC和Crankshaft的区别在于Crankshaft从Inline Caches中直接获得类型信息,而不是从代码中检测。我认为Crankshaft的实现更为优雅一些,但当GC(垃圾回收,garbage collection)释放了缓存(cache)后,它就会得很弱了。

 

我以前提到过inlining,  DFG JIT就会使用它,并且像HotSpot一样在解析时使用。类型分析(type profiling) (也称为value profiling)组合运用一些简易的静态分析技术,使得DFG可以使int32和双精度数据类型区分开来。

 

有一件事DFG JIT目前还做不到,就是代码移动中一些情况(code motion,又是一个编译领域的名词)。它虽然可以做去除死代码和公共表达式,但它的前提条件是必须能做类型分析(value profile)。而针对循环不变量的code motion,这是做不到的(因为值不变嘛)。

 

另外,DFG的寄存器分配器(register allocator)不及Crankshaft的好。这是由于JSC汇编造成的的阻碍。在构造良好的、健壮的代码片段的同时,JSC的汇编程序使用双地址的接口(interface)而不是三址的。这意味着,不需要像add(dest,op1,op2)的方法,而是add(op1,op2),其结果被默认存在第一个操作数中。它是针对x86指令集的,但对于有更多寄存器的系统(如x86 - 64),这并不算什么。

 

对于计算结果,需要更多代码的基于计数的优化触发方式并不是绝对必要, 但这种策略确实有个很好的特性:DFG的性能是可预见的且可衡量的。而另一方面的Crankshaft则使用统计方式触发,其性能是一种统计式的分布

 

对于性能,因为DFG仅在Mac OS 64位版本可用,所以可以使用AWFY on the mac进行测试。你一定要使用正确的工具进行性能评测。

看看结果就知道,JSC对V8基准(benchmark)的表现很不错。有趣的是,对于SunSpider测试,JSC打败了V8。不过V8一旦热身后,仍然是表现最好的. JSC做得很不错,而且正在逐渐改进中。 

 

未来(future)

这就是JavaScriptCore. 当前团队的三个人(是的),正专注在DFG JIT上。其中最关键的是什么时候可以将DFG JIT运行到其它系统上。

JSC的另一个工作是新一代的垃圾回收器(new generational garbage collector)。它确实在做,但很慢。虽然有了Card-Marking write barriers(这是一垃圾回收领域的专业名词)的预留函数(stubs),但目前为止并没有相应的实现。不过,至少JSC提供了Handle API, 盖过了SpiderMonkey。

 

上一篇: JavaScriptCore, WebKit的JS实现(一)

转载请注明出处: http://blog.csdn.net/horkychen

目录
相关文章
|
8月前
|
移动开发 JavaScript 前端开发
专为webkit内核而生的javascript库mango正式发布
专为webkit内核而生的javascript库mango正式发布
|
JavaScript 算法 前端开发
【前端算法】JS实现数字千分位格式化
JS实现数字千分位格式化的几种思路,以及它们之间的性能比较
384 1
|
存储 前端开发 算法
一行代码解决LeetCode实现 strStr()使用JavaScript解题|前端学算法
一行代码解决LeetCode实现 strStr()使用JavaScript解题|前端学算法
216 0
一行代码解决LeetCode实现 strStr()使用JavaScript解题|前端学算法
|
存储 机器学习/深度学习 JavaScript
JS 你最少用几行代码实现深拷贝?
JS 你最少用几行代码实现深拷贝?
JS 你最少用几行代码实现深拷贝?
|
JavaScript 前端开发 算法
JavaScript实现一段时间之后关闭广告
简介:通过JavaScript实现在一段时间之后,广告消失。
160 0
JavaScript实现一段时间之后关闭广告
|
JavaScript 前端开发 算法
JS实现鼠标悬停变色
本文实现的是利用JS实现当鼠标悬停在表格上的时候,表格发生变色。 CSS渲染 JS逻辑 `
255 0
JS实现鼠标悬停变色
|
JavaScript 前端开发 数据安全/隐私保护
JS实现关闭图片窗口
通过事件的绑定来实现,关闭二维码的效果。
196 0
JS实现关闭图片窗口
|
前端开发 JavaScript Windows
js实现body背景图自动扩缩 光靠css几乎无法实现这样的效果
js实现body背景图自动扩缩 光靠css几乎无法实现这样的效果
272 0
js实现body背景图自动扩缩 光靠css几乎无法实现这样的效果
|
JavaScript 前端开发
利用JavaScript实现二级联动
利用JavaScript实现二级联动 要实现JavaScript二级联动效果,首先要确定需要哪些技术: 二维数组 for in循环 new Option(text,value,true,true) add(option,null) onchange() 表单事件 HTML代码: <!-- <input type="text" id="text"> --> 请选择省份: <select name="" id="provinces"> <!-- <option value="江苏省">江苏省</option>
|
JavaScript 前端开发
JavaScript函数柯里化的实现原理,进来教你完成一个自己的自动实现柯里化方法
JavaScript函数柯里化的实现原理,进来教你完成一个自己的自动实现柯里化方法
209 0
下一篇
oss创建bucket