介绍
当我在阅读“为什么 JavaScript 中的 Math.Pow 这么快?”这个问题时,我发现 V8 的内置函数使用了一种名为“Torque”的语言的描述。
一种只在程序语言处理系统中使用的程序语言,用于加速……我不禁感到了浪漫.让我们实际运行 Torque。
版本
V8:撰写本文时的主分支 (2022/9/18)
语言概览
Torque 用于描述 V8 内置函数的优化。似乎使用另一种语言而不是 C++ 的目的是提高逻辑的可读性。
V8 Torque 编程语言允许为 V8 项目做出贡献的开发人员专注于意图并表达他们对 VM 的更改,而不会陷入不相关的实现细节中。该语言旨在促进将 ECMAScript 规范直接转换为 V8 实现,同时以稳健的方式应用低级 V8 优化(基于特定对象类型测试的快速通过)。
V8 Torque 是一种语言,它允许开发人员为 V8 项目做出贡献,通过关注他们对 VM 的更改意图来表达 VM 中的更改,而不是专注于无关的实现细节。很容易将 ECMAScript 规范直接翻译成V8 中的一个实现,但功能强大到足以以稳健的方式表达低级 V8 优化技巧,例如基于特定对象形状的测试创建快速路径。
它是一种静态类型语言,语法被设计为更接近 TypeScript。
@export macro PrintHelloWorld(): void { Print('Hello world!'); }
它还具有泛型和联合等丰富的类型操作,可以直接访问V8实现的内置类型。
环境设置
我按照参考。但是,它原本不应该单独运行,所以运行起来花费了很多时间。
既然麻烦,就转成Docker镜像。如果你喜欢,请使用它(小心,因为它是 12GB!)。
以下是设置环境以创建图像的过程。 (如果你想触摸它,请跳过它!)
设置概览
参考资料中的“入门”展示了如何将 HelloWorld 添加到测试用例中,因此请遵循此方法。
步骤大致如下。
- 克隆 V8,更新依赖模块
- 将要运行的进程添加到测试用例中,测试Torque源码
- 构建测试二进制文件
- 运行测试
克隆 V8
不幸的是,
git clone
无法使用,需要专用工具(来自参考)。
第一的仓库工具安装
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git PATH=/depot_tools:$PATH gclient
现在您可以使用
gclient
并克隆 v8。
后面我们会用到 Python,所以我们把它放进去。然后克隆 V8。运行 depot_tools
fetch
而不是git clone
。cd /v8 fetch v8 cd v8 # 最初はdetached headにいるので、mainに移動してからpull git checkout main && git pull # 依存関係をアップデート gclient sync
补丁测试功能及测试Torque源码
接下来,让我们让这次创建的 Torque 源代码可以从测试中执行。
首先,创建一个测试用例来执行本次添加的源代码。将其添加到
test/cctest/torque/test-torque.cc
的测试用例列表的末尾。测试/cctest/torque/test-torque.cc// ... namespace v8 { namespace internal { namespace compiler { // ... // 末尾のテストケースとして追記。 `Main` という名前の関数を実行するようにする TEST(Main) { Isolate* isolate(CcTest::InitIsolateOnce()); CodeAssemblerTester asm_tester(isolate, 0); TestTorqueAssembler m(asm_tester.state()); { m.Main(); m.Return(m.UndefinedConstant()); } FunctionTester ft(asm_tester.GenerateCode(), 0); ft.Call(); } } // namespace compiler } // namespace internal } // namespace v8
然后将源代码本身添加到
test/torque/test-torque.tq
。这时候如果删除已有的代码,现有的测试用例会掉下来,构建会失败,所以要小心。测试/扭矩/测试扭矩.tqnamespace test { # 関数を追加 @export macro Main(): void { Print('Hello world!'); } // ... (既存のコード) }
在Dockerfile中,代码是sed强行插入的。
# テストファイルのパッチ # 内側のsedでパッチファイルの改行を"\n"に変換して1行表示 # その後外側のsedで "} // namespace compiler" の行の直前に挿入 cat test-torque.cc | sed "/\} \/\/ namespace compiler/i $(cat test-torque-patch.cc | sed -z 's/\n/\\n/g')" > test-torque.cc # 同様に、tqファイルでも "namespace test {" の行の直後に挿入 cat test-torque.original.tq | sed "/namespace test {/a $(cat ${tq_file_path} | sed -z 's/\n/\\n/g')" > test-torque.tq
我第一次了解到 sed 不仅可以替换,还可以插入(
sed //i
紧接在前面,sed //a
紧接在紧接之后)。构建测试二进制文件
我已经修补了测试文件并构建了它(它是用 c++ 编写的,所以我不能按原样运行它)。用于构建的 V8 构建工具通用汽车使用。参考中介绍了
gm x64.debug.check
方法,但推荐x64.debug.tests
(只构建测试文件),因为这里也执行测试。alias gm=/v8/v8/tools/dev/gm.py # デバッグ用ツール一式ビルド gm x64.debug.tests
(参考) gm 选项
$ gm -h ... - all (build all binaries) - tests (build test binaries) - check (build test binaries, run most tests) - checkall (build all binaries, run more tests)
如果构建成功,会在V8目录下生成
out/x64.debug/cctest
。测试运行
执行“Patch Test Function and Torque Source Code for Test”中创建的测试用例
Main
。# cctestの引数にテストケース名を指定すると単体で実行可能 root@3083bb2e4a26:/v8/v8# out/x64.debug/cctest test-torque/Main Hello world!
执行成功
尝试运行 FizzBuzz
你终于准备好玩 Torque 了。
一个人无法掌握HelloWorld的特点,所以写了FizzBuzz。(如果您使用的是 VSCode,V8 扭矩语言支持建议您通过插入使用语法高亮
// 分かりやすいようにMainと付けたが、エントリーポイントの概念はない @export macro Main(): void { for (let i: int32 = 1; i <= 30; i++) { FizzBuzz(i); } } macro FizzBuzz(n: int32): void { if (n % 15 == 0) { Print("fizzbuzz"); return; } if (n % 3 == 0) { Print("fizz"); return; } if (n % 5 == 0) { Print("buzz"); return; } Print(Convert<Smi>(n)); }
到目前为止还没有特殊的语法,它变成了一个通用的(?)FizzBuzz。
但是,在处理数字类型时必须小心。
String
或Object
并且不能传递int32
或数字文字(constexpr IntegerLiteral
类型)。
严格区分常量和变量的类型(其值可以在运行时改变)这一事实是嵌入式系统的语言。candidates are: Cast(implicit class Context)(MaybeObject): Smi labels CastError Cast(implicit class Context)(Object): Smi labels CastError Cast(class String): Smi labels CastError
在上面,它在被传递之前被转换为
Smi
(小整数)。DebugPrint: Smi: 0x1 (1) DebugPrint: Smi: 0x2 (2) fizz DebugPrint: Smi: 0x4 (4) buzz fizz DebugPrint: Smi: 0x7 (7) ...
顺便提一下,“如果
FizzBuzz
函数的返回值设置为Union( | )
,会不会变成纯函数?”在没有通用基类型的情况下,似乎无法使用 Union(这与 TypeScript 不同)。macro FizzBuzz(n: Smi): (Smi | constexpr String) { if (n % 15 == 0) { return "fizzbuzz"; } if (n % 3 == 0) { return "fizz"; } if (n % 5 == 0) { return "buzz"; } return n; }
test/torque/test-torque.tq:23:1: Torque Error: types Smi and constexpr String have no common supertype
综上所述
以上是运行在 V8 内部的 Torque 语言的介绍。
环境搭建好辛苦,还没来得及探索语言就筋疲力尽了……我想再借一次机会,研究一下语法和语言的特点。
原创声明:本文系作者授权爱码网发表,未经许可,不得转载;
原文地址:https://www.likecs.com/show-308626190.html