javascript 运行原理
概念
首先我们去去了解几大关键词的概念:
Parse 模块
可以把 JS 代码转成 AST (抽象语法树)
AST 是一个类似下面的数据结构,这里就不展开讲了
词法分析 (将代码转成 token 数组)
语法分析 (分析 token 数组,将其转换成 AST)
{
type: 'Program',
body: [{
type: 'CallExpression',
name: 'add',
params:
[{
type: 'NumberLiteral',
value: '2',
},
{
type: 'CallExpression',
name: 'subtract',
params: [{
type: 'NumberLiteral',
value: '4',
}, {
type: 'NumberLiteral',
value: '2',
}]
}]
}]
}
Ignition
这是一个虚拟机,运行着解释器(Interpreter),解释器会根据 AST 生成字节码,并解释执行 ByteCode(字节码最终也会转为机器码执行),同时收集优化编译所需的信息
解释器:ps:字节码可以直接运行在虚拟机上
解释器(英语:interpreter),是一种计算机程序,能够把解释型语言解释执行。解释器就像一位“中间人”。解释器边解释边执行,因此依赖于解释器的程序运行速度比较缓慢。解释器的好处是它不需要重新编译整个程序,从而减轻了每次程序更新后编译的负担。相对的编译器一次性将所有源代码编译成二进制文件,执行时无需依赖编译器或其他额外的程序。(来自于维基百科)
ByteCode
字节码(英语:Bytecode)通常指的是已经经过编译,但与特定机器代码无关,需要解释器转译后才能成为机器代码的中间代码。字节码通常不像源码一样可以让人阅读,而是编码后的数值常量、引用、指令等构成的序列。
字节码主要为了实现特定软件运行和软件环境、与硬件环境无关。字节码的实现方式是通过编译器和虚拟机。编译器将源码编译成字节码,特定平台上的虚拟机将字节码转译为可以直接执行的指令。字节码的典型应用为 Java bytecode。(来自于维基百科)
TurboFan
TurboFan 是一个编译器,编译器(JIT 编译器 Compiler),如果一个函数被多次调用,那么就会被标记为热点函数,那么就会经过 TurboFan 转换成优化的机器码,提高代码的执行性能;
但是,机器码实际上也会被还原为 ByteCode,这是因为如果后续执行函数的过程中,类型发生了变化(比如 sum 函数原来执行的是 number 类型,后来执行变成了 string 类型),之前优化的机器码并不能正确的处理运算,就会逆向的转换成字节码;
编译器
编译器(compiler)是一种计算机程序,它会将某种编程语言写成的源代码(原始语言)转换成另一种编程语言(目标语言)(来自于维基百科)
JIT
在计算机技术中,即时编译(英语:just-in-time compilation,缩写为 JIT;又译及时编译、实时编译),也称为动态翻译或运行时编译,是一种执行计算机代码的方法,这种方法涉及在程序执行过程中(在执行期)而不是在执行之前进行编译。通常,这包括源代码或更常见的字节码到机器码的转换,然后直接执行。实现 JIT 编译器的系统通常会不断地分析正在执行的代码,并确定代码的某些部分,在这些部分中,编译或重新编译所获得的加速将超过编译该代码的开销。
JIT 编译是两种传统的机器代码翻译方法——提前编译(AOT)和解释器——的结合,它结合了两者的优点和缺点。大致来说,JIT 编译,以解释器的开销以及编译和链接(解释之外)的开销,结合了编译代码的速度与解释的灵活性。JIT 编译是动态编译的一种形式,允许自适应优化,比如动态重编译和特定于微架构的加速——因此,在理论上,JIT 编译比静态编译能够产生更快的执行速度。解释和 JIT 编译特别适合于动态编程语言,因为运行时系统可以处理后期绑定的数据类型并实施安全保证。(来自于维基百科)