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

简介: 类型推导是DFG JIT最重要的一个基础,WebKit官网对此做了一点解释,翻译如下做为学习参考。 Type inference通过profiling values来做到的,先是预测对哪些类型操作进行分析,再添加类型检查,最后基于类型检查的结果建立类型统计数据。

类型推导是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



目录
相关文章
|
26天前
|
Shell Linux 开发工具
【Shell 命令集合 文件管理】Linux 高级的文件管理器 mc 命令解析
【Shell 命令集合 文件管理】Linux 高级的文件管理器 mc 命令解析
38 0
|
2月前
|
运维 监控 网络协议
QT实现TCP通信:从基础到高级的全面解析
QT实现TCP通信:从基础到高级的全面解析
161 0
|
22天前
|
JSON JavaScript 前端开发
C++ 智能指针与 JSON 处理:高级编程技巧与常见问题解析
C++ 智能指针与 JSON 处理:高级编程技巧与常见问题解析
252 0
|
22天前
|
机器学习/深度学习 算法 编译器
【C++ 泛型编程 中级篇】深度解析C++:类型模板参数与非类型模板参数
【C++ 泛型编程 中级篇】深度解析C++:类型模板参数与非类型模板参数
46 0
|
22天前
|
存储 JSON 安全
【C++ 泛型编程 综合篇】泛型编程深度解析:C++中的五种类型泛型策略综合对比
【C++ 泛型编程 综合篇】泛型编程深度解析:C++中的五种类型泛型策略综合对比
64 1
|
4天前
|
Java 关系型数据库 MySQL
高级对象装配:解析Spring创建复杂对象的秘诀
高级对象装配:解析Spring创建复杂对象的秘诀
19 0
高级对象装配:解析Spring创建复杂对象的秘诀
|
13天前
|
存储 编译器 Linux
解析编程中不可或缺的基础:深入了解结构体类型
解析编程中不可或缺的基础:深入了解结构体类型
31 2
|
22天前
|
算法 Serverless 数据安全/隐私保护
【C++ 函数 基本教程 第三篇 】深度解析C++函数类型:探寻全局函数、成员函数与静态函数的奥秘
【C++ 函数 基本教程 第三篇 】深度解析C++函数类型:探寻全局函数、成员函数与静态函数的奥秘
34 1
|
25天前
|
设计模式 算法 编译器
【C++ 泛型编程 高级篇】 C++ 17 解析std::apply 的多种应用场景(三)
【C++ 泛型编程 高级篇】 C++ 17 解析std::apply 的多种应用场景
23 0
|
25天前
|
设计模式 存储 程序员
【C++ 泛型编程 高级篇】 C++ 17 解析std::apply 的多种应用场景(二)
【C++ 泛型编程 高级篇】 C++ 17 解析std::apply 的多种应用场景
39 0

推荐镜像

更多