首页 文章

V8何时开始编译并执行与事件循环堆栈相关的代码?

提问于
浏览
0

我一直很好奇从开始到结束执行js代码 .

我已经阅读了关于事件循环并看到了这个great video,堆栈帧看起来如何here,还读到了V8引擎如何编译js代码here .

题 :

When does V8 starts compiling and executing the code in relation to the event loop stack ?

当函数即将弹出堆栈时是什么时候?

或者在将它们放入堆栈之前编译所有函数?

因此,将其他功能放在最上面的过程实际上只是处理机器代码,如果是这样,当从堆栈弹出函数时会发生该机器代码的执行?

如果我的问题没有被理解,我相信通过这个例子可以更好地理解

示例:

function foo() {
    var name=`foo`;
    var obj = {
        number: 6
    }
    console.log(obj.number);
}

function baz() {
    var name = `baz`;
    console.log(a);
    foo();
}

baz();
  • 发生的第一个进程是lazy parsing,其中所有文件都被解析为语法错误,但未完全解析,因此花费的时间更少 .

  • 通过功能解决

  • v8引擎现在是否将函数声明代码编译为机器代码?还是轮到他了......

调用

  • baz,将baz放在堆栈的底部,并在其堆栈帧中存储名称变量值(因为它是一个原语) .

  • 什么时候buz被解析并转换为机器码?在它放在堆栈之前?还是当它弹出来的时候?

  • console.log放在baz之上并执行, - 控制台显示 baz

  • 这是将console.log js代码编译为机器代码并执行的地方吗?

  • console.logs堆栈的弹出窗口 .

  • foo放在baz之上,obj放在堆中(因为它是引用类型), name=foo 放在foo的堆栈框架中 .

  • console.log在foo之上,并且执行,控制台显示6 .

  • console.log弹出 .

  • foo弹出,连同其局部变量值 .

  • baz随着 name=baz 局部变量弹出

1 回答

  • 1

    没有“事件循环堆栈”之类的东西 .

    一个概念是“调用堆栈”,它是一个术语,当函数相互调用时,它们形成类似堆栈的当前状态 . 这主要是一个理论概念,但实际上,存在一个称为“堆栈”的内存区域,用于函数的局部变量,但它不是具有推/弹界面的数据结构:调用函数的行为将其数据放在此堆栈上,并从函数返回将其再次删除,将控制权返回给调用函数 .

    这回答了你的部分功能:开始执行一个函数与把这个函数放在调用堆栈上完全一样 . 这是同一件事的两个描述 .

    另一个概念是事件队列 . 您可以将其视为等待执行的函数队列;只要没有其他函数正在执行,就会调用此队列中的下一个函数 . 将函数放入队列不需要对其进行解析或编译 . 在示例代码段中,根本不使用事件队列 .

    编译功能与所有这些无关 . 当一个函数被调用(通过另一个函数,或者通过事件循环)时,它必须以某种形式执行 - 但是根据你的JavaScript引擎,它可以在没有任何编译的情况下被解释,或者它可以被编译为字节码,或者它可以编译成机器代码,或者引擎可以利用这个机会从一个切换到另一个 .

    因为你特别询问了V8:在当前版本中,当V8看到像 function f() { ... } 这样的函数定义时,它不会像之前的调用那样't do anything anything yet (except for a few cases where V8 guesses that the function will be executed soon, in which case it creates bytecode for it immediately). If the function gets queued as a callback, still no parsing or compilation happens. When a function is called for the first time, V8 creates bytecode for it. When the function is called again, the bytecode exists already, so no additional work is required. When a function runs hot enough, V8 eventually decides to compile optimized machine code for it, usually on a background thread. Additional calls to it are opportunities for V8 to check whether the background thread is done producing machine code already; if so, then the next call will use that optimized code instead of interpreting the function'字节码 . 请注意,这些实现细节可能会随着时间而变化 .

    还有一点需要澄清:

    在其堆栈帧中存储名称变量值(因为它是一个原语) .

    不完全的 . 变量本身存储在堆栈帧中,但仅作为参考 . 它是否指原始值无关紧要;字符串和对象都在堆上分配 . 当函数返回并且其堆栈帧被拆除时,局部变量将被销毁;堆上的相应对象或字符串将(最终在某些不确定的时间)由垃圾收集器清理 .

相关问题