[WebKit] JavaScriptCore解析--高级篇(二) 类型推导(Type Inference)

类型推导是DFG JIT最重要的一个基础,WebKit官网对此做了一点解释,翻译如下做为学习参考。


Type inference通过profiling values来做到的,先是预测对哪些类型操作进行分析,再添加类型检查,最后基于类型检查的结果建立类型统计数据。


用下面的例子来说明这个过程:

o.x * o.x + o.y * o.y


其中o是一个对象,x和y是它的属性,它们不是访问器(accessor),只是一般的属性。我们也可以说这两个属性值会返回double类型数值,但也有时会返回整型数据。JavaScriptCore通过用int32来表现整型数据,而不是用double类型。

  1. 对于表达式o.x,先要检查o有没有任何特殊的访问属性的处理。比如是一个DOM对象,那么它的属性访问操作就不是可见的。如果没有特殊的处理,JSC会在对象的属性中找出名字为'x'的属性。对象都一个将字串映射到值或访问器(accessor)的表,如果所找的字串指向一个访问器,那么这个访问器就会被调用,如果指一个值,那就直接返回。如'x'没能在对象o中找到,就到它的原型中依次找下去。类型推导对这部分操作没有什么作用。


  2. 二元的相乘操作,如'o.x * o.x',首先检查操作数(operands)的类型。如果操作数是个对象,就是调用它的valueOf方法。如果操作数是个字串,就要先转换为数值。当两个操作数已经被转为等价的数值(如果可以的话)后,JSC会再检查它们是不是全是整数,如果是则执行整型的相乘。如果溢出,就会用double类型的相乘再算一次。如果有一个操作数是double数值,它们都会转为double型,并执行double型的相乘操作。因此'o.x*o.x'所返回的结果,要么是整数,要么是浮点数(double)。


  3. 对于表达式'o.x*o.x + o.y*o.y'和上面类似,只是要多考虑一下操作数是字串的情况,中间的'+'可能会是字串合并的操作。不过在这里,我们可以很容易地确定,返回值仍然要么是整数,要么是浮点数(double)。


JSC的类型推导就是如果我可以猜到输入的数据类型,就可以给出数值操作后最可能返回的类型,以及其路径。这里使用了一系列归纳步骤, 如果我们可以预计它的输入就可以预计它的输出。对于一些非局部变量,比如从堆中取出的值(如o.x),和函数返回值,我们都称为堆值(heap values), 所有将heap values赋给局部变量的操作都视为堆操作(heap oerpations). 类型预测使用到了value profiling, LLInt和Baseline JIT都会记录在任何heap oerpation中记录下最常用的数值。每个堆操作都有一个对应的value profile bucket, 每一个value profile bucket都会存储一个最近值。


简单的看,JSC的类型推导就是把value profile中最常用的值的类型作为其以后要使用的类型。这样所有的变量都变成是可以进行类型预测的了。 事实上,在每个value profile中还有第二个内容,它是能包括已出现的一部分数据值的数据类型。这个类型使用了SpeculatedType(或SpecType)类型系统,实现在SpeculatedType.h中。每个value profile中这个类型会先设为SpecNone(就是没有数据)。当Baseline JIT执行次数超出阀值(JIT.cpp中的JIT::emitOptimizationCheck),它会生成一个新的类型,可以同时让最后一次的类型和最常用的数值符合这个类型。它或许会触发DFG,也可以让Baseline再多执行几次。当进入DFG JITF后,每个value profile通常会有一个这样可以包容多个不同值的类型。


SpecTypes之所以可行,源自于函数中的操作和变量都会使用标准的前置数据流( forward data flow )规范,实现了所谓的流程无关的不动点(fixpoint). 这是DFG编译的第一个阶段,由Baseline JIT基于执行次数决定是否激活(DFGPredictionPropagationPhase.cpp)。


在每个使用了预测数据类型的函数中,我们插入了基于预测的类型检查操作。如果类型检查失败,就会回退到Baseline JIT中。下面分解下'a+b'的附加操作是如何执行的, 假设a和b都被预测为SpecInt32类型:


check if a is Int32 -> 否则 OSR exit to Baseline JIT

check if b is Int32 -> 否则 OSR exit to Baseline JIT

result = a + b // integer addition

check if 溢出 -> 否则 OSR exit to Baseline JIT


操作执行完成后,我们可以知道:

  • 'a' 是整数.
  • 'b' 是整理.
  • 结果也是整数.

后面的操作就不用再检查'a' or 'b'的类型了这有一个消除类型检查的操作,是通过第二个数据流分析来完成的,被称为DFG CFA (DFGCFAPhase.cpp DFGAbstractState.cpp) . 它也实现了稀疏条件传播(sparse conditional constant propagation),让它可以有能力像确定类型一样确定某些值是不是常量。


对于表达式 'o.x * o.x + o.y * o.y',只需要在取o.x和o.y时进行类型检查。然后我们就知道它们的值是doubles, 就是只需触发double的相乘和相加。DFG绝大多数的类型检查通常是在加载堆数据时发生的。


深入阅读:

 Fast and Precise Hybrid Type Inference for JavaScript

 动态查看Type Inference的结果

 Type Inference in SpiderMonkey


原文地址: http://trac.webkit.org/wiki/JavaScriptCore

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

系列索引:

基础篇 (一)JSC与WebCore

基础篇(二)解释器基础与JSC核心组件

基础篇(三)从脚本代码到JIT编译的代码实现

基础篇(四) 页面解析与JavaScript元素的执行

高级篇(一) SSA (static single assignment)

高级篇(二) 类型推导(Type Inference)

高级篇(三) Register Allocation & Trampoline



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用 JavaScript 编写的记忆游戏(附源代码)   项目:JavaScript 记忆游戏(附源代码) 记忆检查游戏是一个使用 HTML5、CSS 和 JavaScript 开发的简单项目。这个游戏是关于测试你的短期 记忆技能。玩这个游戏 时,一系列图像会现在一个盒子形状的区域中 。玩家必须找到两个相同的图像并单击它们以使它们消失。 如何运行游戏? 记忆游戏项目仅包含 HTML、CSS 和 JavaScript。谈到此游戏的功能,用户必须单击两个相同的图像才能使它们消失。 点击卡片或按下键盘键,通过 2 乘 2 旋转来重建鸟儿对,并发现隐藏在下面的图像! 如果翻开的牌面相同(一对),您就赢了,并且该对牌将从游戏中消失! 否则,卡片会自动翻面朝下,您需要重新尝试! 该游戏包含大量的 javascript 以确保游戏正常运行。 如何运行该项目? 要运行此游戏,您不需要任何类型的本地服务器,但需要浏览器。我们建议您使用现代浏览器,如 Google Chrome 和 Mozilla Firefox, 以获得更好、更优化的游戏体验。要玩游戏,首先,通过单击 memorygame-index.html 文件在浏览器中打开游戏。 演示: 该项目为国外大神项目,可以作为毕业设计的项目,也可以作为大作业项目,不用担心代码重复,设计重复等,如果需要对项目进行修改,需要具备一定基础知识。 注意:如果装有360等杀毒软件,可能会现误报的情况,源码本身并无病毒,使用源码时可以关闭360,或者添加信任。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值