编译流水线

204 阅读2分钟

执行过程

image.png

运行时环境

在执行代码之前,V8准备了代码运行环境,包括:堆栈空间,全局执行上下文,全局作用域,宿主环境提供的扩展函数和对象,内置的内建函数。

v8实现语言本身方面的标准和垃圾回收,宿主提供API

image.png

栈空间和堆空间

  • 栈空间

内存中连续空间,先进先出

一般用于函数调用

内存中很难分配到一块拦蓄空间,V8对栈大小有限制,函数调用过深会触发栈溢出

  • 堆空间

树形存储结构,用于存储对象和离散数据

全局执行上下文和全局作用域

初始化完堆栈空间后,初始化全局执行上下文和全局作用域。

全局执行上下文包括:

  • 变量环境
  • 词法环境(let、const)
  • this

image.png

全局执行上下文不会被销毁

全局作用域和全局执行上下文关系

同一个全局执行上下文中可能存在多个作用域

var x=5
{
    let y=2,
    const z=3
}

image.png

当V8调用一个函数时,就会进入函数的执行上下文,形成一个栈结构

image.png

执行上下文和作用域

执行上下文可以理解为栈帧,作用域是函数在定义或者声明时确定的。

惰性解析和预解析

解析器在遇到函数声明时,会跳过函数内部代码,不会为其生成AST和字节码

function foo(a, b) {
  var m = 1;
  var n = 2;
  return a + b + m + n;
}

var a = 1;
var b = 4;

foo(1, 2);

image.png

如果只执行惰性解析,那么闭包闭包又是如何解决的、

function bar() {
  var a = 1;
  var b = 2;
  return function inner(m, n) {
    return a + b + m + n;
  };
}
f = bar();

执行到bar里面时,如果仅仅只是惰性解析,inner里是不知道引用了a,b的,所以除了惰性解析,还存在预解析的过程

预解析目的主要有两个:

  • 判断是否有语法错误
  • 检查函数是否引用了外部变量,如果引用了外部变量,将栈中引用的外部变量复制到堆中,执行该函数的时候,直接从堆中引用