V8 实际上在哪里使用原始 javascript 代码?

Luc*_*ord 3 javascript v8 blink chromium embedded-v8

我试图了解 v8 是如何工作的,但我无法找到代码中的位置,它实际上获取输入原始 js 脚本来解析它并将其编译为 C++。

\n

我看过 api.cc 并尝试在编译器函数中设置断点,但没有运气(我使用 chromium 来这样做),它永远不会命中这个函数。

\n
MaybeLocal<Script> ScriptCompiler::Compile(Local<Context> context,\n                                      Source* source,\n                                      CompileOptions options,\n                                      NoCacheReason no_cache_reason)\n\n
Run Code Online (Sandbox Code Playgroud)\n

***** 更新 ****

\n

在 @jmrk 回复之后,我一直在试图弄清楚 JS 实际上是从哪里开始进来的,我真正感兴趣的是了解网站如何呈现,然后将脚本传递到 V8 中进行编译。\n我发现有关该主题的大量信息,但我仍然无法理解整个情况:

\n

结果第一步不是解析器而是扫描器,它获取 UTF-16 流作为输入。

\n
\n

源代码首先被分成块;每个块可能与不同的编码相关联。然后,流将所有块统一为 UTF-16 编码。

\n

在解析之前,扫描器会将 UTF-16 流分解为令牌。标记是具有语义的脚本的最小单元。标记有多种类别,包括空格\n(用于自动分号插入)、标识符、关键字和代理对(仅当该对不被识别为其他内容时才组合起来形成标识符)。然后,这些标记首先被馈送到预解析器,然后再馈送到解析器。

\n
\n

https://blog.logrocket.com/how-javascript-works-optimizing-for-parsing-efficiency/

\n

我还发现它确实从 Blink 获取了这个流:

\n

在此输入图像描述

\n
\n

UTF16CharacterStream 提供了 V8 从 Chrome 接收的底层 Latin1、UTF-8 或 UTF-16 编码的(可能是缓冲的)UTF-16 视图,而 Chrome 又从网络接收这些编码。除了支持多种编码之外,扫描仪和字符流之间的分离允许 V8 透明地扫描,就好像整个源都可用一样,即使到目前为止我们可能只通过网络收到了一部分数据。

\n
\n

https://v8.dev/blog/scanner

\n

扫描仪似乎也将标记提供给解析器:

\n
\n

V8\xe2\x80\x99s 解析器使用 \xe2\x80\x98scanner\xe2\x80\x99 提供的 \xe2\x80\x98tokens\xe2\x80\x99 。标记是\n由一个或多个字符组成的块,具有单一语义:\n字符串、标识符、++ 等运算符。扫描器通过组合底层字符流中的连续字符来构造这些标记。

\n
\n

但问题仍然存在,Javascript 原始代码从眨眼进入 V8 的位置在哪里?\n我如何才能看到 chrome 读取的内容以及它在哪里初始化 v8

\n

jmr*_*mrk 6

情况很复杂 :-)

ScriptCompiler::Compile作为最外面的入口点通常是正确的。请注意,它有两个重载。此外,Chrome 会尝试在可能的情况下进行流式编译,这采用了不同的路径。另外,在使用 Chrome/Chromium 时,请注意,您必须在渲染器进程中设置断点,而不是在浏览器进程中。

d8在探索 V8 时,使用 shell 更容易。在 d8.cc 中查找Shell::ExecuteString(调用)。ScriptCompiler::Compile

另外,需要澄清的是,V8 不会将 JavaScript 编译为 C++。它首先将其编译为自己的内部字节码格式,由“Ignition”解释器执行;热函数随后由“Turbofan”优化编译器编译为机器代码。

如果您无法理解整个管道,请不要灰心。没有一个人这样做;V8 太大而且太复杂。专注于您感兴趣的内容(解析器?解释器?优化编译器?)并深入研究。