写点什么

D8 调试工具——jsvu 的使用细则

作者:甜点cc
  • 2023-06-07
    河南
  • 本文字数:4521 字

    阅读完需:约 15 分钟

d8 is V8’s own developer shell.

D8 是一个非常有用的调试工具,你可以把它看成是 debug for V8 的缩写。我们可以使用 d8 来查看 V8 在执行 JavaScript 过程中的各种中间数据,比如作用域、AST、字节码、优化的二进制代码、垃圾回收的状态,还可以使用 d8 提供的私有 API 查看一些内部信息。

前言

jsvu 是 JavaScript 引擎版本管理工具


以下是在 Windows10 下的操作,建议在 CMD 窗口里面操作。

1、安装

前提:node V14+


npm install -g jsvu
复制代码


运行 jsvu,交互式命令行选择需要安装的平台和引擎


安装指定版本的引擎可以参考下面的命令

jsvu --os=win64 --engines=v8,v8-debug



执行 jsvu 安装引擎,可在 %USERPROFILE% /.jsvu 目录下查看安装的引擎



安装 v8-debug


jsvu --os=win64 --engines=v8-debug
复制代码


操作系统支持的引擎

查看 jsvu 版本

jsvu -h
📦 jsvu v1.13.3 — the JavaScript engine Version Updater 📦[<engine>@<version>][--os={mac64,mac64arm,linux32,linux64,win32,win64,default}][--engines={chakra,graaljs,hermes,javascriptcore,quickjs,spidermonkey,v8,v8-debug,xs},…]
Complete documentation is online:https://github.com/GoogleChromeLabs/jsvu#readme
复制代码

2、安装 eshost-cli(这个不安装也不影响使用)

管理 js 引擎,可以调用多个引擎执行 js 代码,更加方便调试不同引擎下的代码


npm install -g eshost-cli
复制代码

Windows 下配置

eshost --add <host name> <host type> <host path> --args <optional arguments>
复制代码


根据需要使用的引擎,自行配置,如下


eshost --add "Chakra" ch "%USERPROFILE%.jsvu\chakra.cmd"eshost --add "GraalJS" graaljs "%USERPROFILE%.jsvu\graaljs.cmd"eshost --add "JavaScriptCore" jsc "%USERPROFILE%.jsvu\javascriptcore.cmd"eshost --add "SpiderMonkey" jsshell "%USERPROFILE%.jsvu\spidermonkey.cmd"eshost --add "V8 --harmony" d8 "%USERPROFILE%.jsvu\v8.cmd" --args "--harmony"eshost --add "V8" d8 "%USERPROFILE%.jsvu\v8.cmd"eshost --add "XS" xs "%USERPROFILE%.jsvu\xs.cmd"
复制代码


这里我个人配置如下(有没有这个配置貌似没什么影响,)


eshost --add "V8" d8 "C:\Users\xiao.jsvu\v8.cmd"eshost --add "V8-debug" d8 "C:\Users\xiao.jsvu\v8-debug.cmd"eshost --add "V8 --harmony" d8 "C:\Users\xiao.jsvu\v8.cmd" --args "--harmony"
复制代码

查看

C:\Users\xiao.jsvu>eshost --configure-jsvuUsing config "C:\Users\xiao.eshost-config.json"┌──────────────┬──────┬──────────────────────────────────┬───────────┬─────────────┐│ name         │ type │ path                             │ args      │ tags        │├──────────────┼──────┼──────────────────────────────────┼───────────┼─────────────┤│ ChakraCore   │ ch   │ C:\Users\xiao.jsvu\chakra.cmd   │           │ 1.11.24,web │├──────────────┼──────┼──────────────────────────────────┼───────────┼─────────────┤│ V8 --harmony │ d8   │ C:\Users\xiao.jsvu\v8.cmd       │ --harmony │             │├──────────────┼──────┼──────────────────────────────────┼───────────┼─────────────┤│ V8           │ d8   │ C:\Users\xiao.jsvu\v8.cmd       │           │             │├──────────────┼──────┼──────────────────────────────────┼───────────┼─────────────┤│ V8-debug     │ d8   │ C:\Users\xiao.jsvu\v8-debug.cmd │           │             │└──────────────┴──────┴──────────────────────────────────┴───────────┴─────────────┘
C:\Users\xiao.jsvu>
复制代码



有大佬知道上面问题在哪,麻烦您指点一下,感谢😊

说明:

  1. %USERPROFILE% =C:\Users\用户名

  2. win+r,输入 cmd 回车

  3. 在 cmd 窗口下输入 set 回车,可以查看系统变量(想要了解更多 set 命令请看👉 这里


3、先简单了解一下抽象语法树

在传统的编译语言的流程中,程序的一段源代码在执行之前会经历三个步骤,统称为"编译":


  1. 分词/词法分析


这个过程会将由字符组成的字符串分解成有意义的代码块,这些代码块统称为词法单元(token)


举个例子: let a = 1; 这段程序通常会被分解成为下面这些词法单元: let 、a、=、1、 ;空格是否被当成词法单元,取决于空格在这门语言中的意义。


  1. 解析/语法分析


这个过程是将词法单元流转换成一个由元素嵌套所组成的代表了程序语法结构的树,这个树被称为"抽象语法树"(abstract syntax code,AST)


  1. 代码生成


将 AST 转换成可执行代码的过程被称为代码生成。



<p align=center>图片来源网络(侵删)</p>


下面看一下在线解析AST的示例👇


4、使用 V8 调试分析代码

文档查看

由于文档较长,可以使用命令输出一份本地的帮助文档,方便查看


# 进入到要输出文档的目录下,生成v8-help.txt、v8-debug-help.txt
v8 --help >> v8-help.txtv8-debug --help >> v8-debug-help.txt
复制代码


主要使用的命令参数如下👇


v8-debug --help


Synopsis:  shell [options] [--shell] [<file>...]  d8 [options] [-e <string>] [--shell] [[--module|--web-snapshot] <file>...]
-e execute a string in V8 --shell run an interactive JavaScript shell --module execute a file as a JavaScript module --web-snapshot execute a file as a web snapshot
SSE3=1 SSSE3=1 SSE4_1=1 SSE4_2=1 SAHF=1 AVX=1 AVX2=1 FMA3=1 BMI1=1 BMI2=1 LZCNT=1 POPCNT=1 ATOM=0The following syntax for options is accepted (both '-' and '--' are ok): --flag (bool flags only) --no-flag (bool flags only) --flag=value (non-bool flags only, no spaces around '=') --flag value (non-bool flags only) -- (captures all remaining args in JavaScript)
Options: # 打印生成的字节码 --print-bytecode (print bytecode generated by ignition interpreter) type: bool default: --noprint-bytecode
# 跟踪被优化的信息 --trace-opt (trace optimized compilation) type: bool default: --notrace-opt --trace-opt-verbose (extra verbose optimized compilation tracing) type: bool default: --notrace-opt-verbose --trace-opt-stats (trace optimized compilation statistics) type: bool default: --notrace-opt-stats
# 跟踪去优化的信息 --trace-deopt (trace deoptimization) type: bool default: --notrace-deopt --log-deopt (log deoptimization) type: bool default: --nolog-deopt --trace-deopt-verbose (extra verbose deoptimization tracing) type: bool default: --notrace-deopt-verbose --print-deopt-stress (print number of possible deopt points)
# 查看编译生成的 AST --print-ast (print source AST) type: bool default: --noprint-ast
# 查看编译生成的代码 --print-code (print generated code) type: bool default: --noprint-code
# 查看优化后的代码 --print-opt-code (print optimized code) type: bool default: --noprint-opt-code
# 允许在源代码中使用 V8 提供的原生 API 语法 # 在代码中配和加入 %DebugPrint(); 可以查看详细的运行时信息 --allow-natives-syntax (allow natives syntax) type: bool default: --noallow-natives-syntax
复制代码

4.1、查看 ast

v8-debug -e --print-ast "const name='xiao'"
复制代码


接收到代码后,第一步就是“解释”,即解释器生成 AST 和作用域。


C:\Users\xiao>v8-debug -e --print-ast "const name='xiao'"[generating bytecode for function: ]--- AST ---FUNC at 0. KIND 0. LITERAL ID 0. SUSPEND COUNT 0. NAME "". INFERRED NAME "". DECLS. . VARIABLE (000001FA12EFAF80) (mode = CONST, assigned = false) "name". BLOCK NOCOMPLETIONS at -1. . EXPRESSION STATEMENT at 11. . . INIT at 11. . . . VAR PROXY context[2] (000001FA12EFAF80) (mode = CONST, assigned = false) "name". . . . LITERAL "xiao"

C:\Users\xiao>
复制代码


4.2、查看作用域

v8-debug -e --print-scopes "const name='xiao'"
复制代码


C:\Users\xiao>v8-debug -e --print-scopes "const name='xiao'"Global scope:global { // (000001DB6010D600) (0, 17)  // will be compiled  // NormalFunction  // 1 stack slots  // 3 heap slots  // temporary vars:  TEMPORARY .result;  // (000001DB6010D910) local[0]  // local vars:  CONST name;  // (000001DB6010D820) context[2], never assigned}
C:\Users\xiao>
复制代码

4.3、查看生成的字节码

v8-debug -e --print-bytecode "const name='xiao'"
复制代码


C:\Users\xiao>v8-debug -e --print-bytecode "const name='xiao'"[generated bytecode for function:  (0x0113002538bd <SharedFunctionInfo>)]Bytecode length: 6Parameter count 1Register count 1Frame size 8Bytecode age: 0         000001130025393A @    0 : 13 00             LdaConstant [0]         000001130025393C @    2 : 25 02             StaCurrentContextSlot [2]         000001130025393E @    4 : 0e                LdaUndefined         000001130025393F @    5 : a9                ReturnConstant pool (size = 1)000001130025390D: [FixedArray] in OldSpace - map: 0x011300002229 <Map(FIXED_ARRAY_TYPE)> - length: 1           0: 0x0113002538a1 <String[4]: #xiao>Handler Table (size = 0)Source Position Table (size = 0)
C:\Users\xiao>
复制代码

4.4、查看详细的运行时信息

通过 --allow-natives-syntax 参数可以在 JavaScript 中调用 %DebugPrint 底层的 Native API


function testV8(properties, elements) {  //添加可索引属性    for (let i = 0; i < elements; i++) {    this[i] = `element${i}`;  }    //添加常规属性    for (let i = 0; i < properties; i++) {    const prop = `property${i}`;        this[prop] = prop;  }}
const testobj1 = new testV8(12, 13);
// 打印 testobj1 详细的运行时信息%DebugPrint(testobj1);
复制代码


执行


v8-debug --allow-natives-syntax .\src\libs\demo.js
复制代码


输出


相关文章一览




发布于: 刚刚阅读数: 7
用户头像

甜点cc

关注

微信公众号:看见另一种可能 2020-04-30 加入

https://blog.i-xiao.space/

评论

发布
暂无评论
D8调试工具——jsvu的使用细则_6 月优质更文活动_甜点cc_InfoQ写作社区