Skip to content

xvm-again

· xieyuheng

why? ​

我决定用 VM 来实现 x-lisp, 因为对于动态类型语言而言, GC 相关的问题太复杂了。

对于之后要实现的静态类型语言再实现编译器,比如 meta-lisp。

或者更合适地,是对于不需要 GC 的语言来实现编译器, 比如 system-lisp 和 linear-lisp。

[2025-11-23] 现在还不确定要放弃编译到 native code。 xvm 作为备选方案。 再继续调研一下。

行动 ​

新的任务大概是:

  • port x-sexp-tael.js to runtime。

  • port basic-lisp to runtime。

    • 保持现在的极简 instruction, 对于 call 指令和某些 primitive function 做 inline 优化(比如 iadd), basic-lisp 的解释器要能写成一个简单的, 有 switch 和很多 case 的 C 函数。
  • 还是需要 GC,只不过这次 root scanning 问题简单多了。

但是可能不能直接实现 basic-lisp 的 vm。 因为对于底层 vm 或者 native 汇编来说, call 和 assign 应该是两个指令。 而 basic-lisp 中 call 和 assign 到 dest 是一个指令。

也就是说:

  • 要么在 c 的 byte code 解释器中拆分指令;
  • 要么实现一个 basic-lisp 到 vm 的 instruction selection。

我想可能后者更合理一些。

可能要回到 xvm 和 xasm 以及 xrom 或 xexe 的设计。

xvm ​

需求:

  • 我需要 vm 因为 basic-lisp 的 call 指令是带有 dest 变量的,这与 vm 是有差别的。
  • 我不需要指令集编码,因为我不需要稳定的二进制接口。
  • 我不需要类 forth 的栈 vm,而是需要寄存器 vm, 因为 basic-lisp 的函数有很多局部变量。

前面提到,把带有 GC 的纯动态类型语言,编译到 native code,不是很合理。 类似的,为带有 tag 的语言实现 instruction encoding 也不是很合理。 tag encoding 应该在软件层次进行。

行动:

  • 用 c 实现 xvm 的模拟器(类似 inet-lisp 的 worker)。
  • 用 c 实现 xvm.machine 的解释器(lisp 语法)。
  • 编译出来 xvm.machine 文件,然后用 xvm 解释执行。

看之前 xvm 和 x-forth 的笔记, 发现很多设计上的问题都是因为语言没有分层。 现在的分层是:

  • x-lisp -- 负责语言的功能
  • basic-lisp -- 负责优化
  • machine-lisp -- 负责具体执行

目前的计划只是解释 xvm.machine 文件, 之后如果有了稳定的 byte code 编码, 也可以考虑编译到 xrom 或 xexe。

现在 machine-lisp 真的有用了, 因为有 x86.machine 和 xvm.machine。

SPARC ​

[2025-11-23]

了解到了 SPARC 指令集的存在, 它除了支持 tagged value 之外, 也支持正常的 value。

这样思路就打开了, 因为只单独支持 tagged value, imm 之类的初始化数据的指令都不知道应该怎么处理。

而 SPARC 就是正常的一个 RISC 构架, 只不过增加了一些处理带有 tagged value 的指令。

程序员和编译器可以灵活选择。

mmix ​

[2025-11-25]

为了简单的指令集编码,可以模仿 mmix, 但是改为 little-endian 和 at&t operand order。

root scanning ​

[2025-11-29]

但是考虑 vm 实现,是因为 GC 的 root scanning 问题。 但是如果使用了类似 SPARC 的可选 tagged value 设计。 那么不是所有的 value 都有 tag。 root scanning 问题就还是困难的。 这与针对 x86 解决 root scanning 问题没有差异。

[2025-12-03]

但是也可以保证在 gc safepoint, 所有的寄存器都保存着 tagged value。

machine-lisp as assembly language ​

[2025-11-29]

xvm 可以让我们有动机来把 machine-lisp 设计成完整的汇编语言。

其实是要嵌入一个解释器在汇编语言中, 使得汇编语言可以使用变量和表达式。

xvi -- extensible vector instruction set ​

这么说来 xvm 应该不是一个 vm, 而是一个 risc 指令集构架。

作为 指令集构架 是不能用 c 扩展的, 或者说用 c 扩展的方式是系统调用。

xvi project ​

[2025-11-29]

设置 xvi 这个新的项目,用来探索 risc 指令集构架的设计。

  • 学习 mmix 的简单指令集编码。

    但是改为 little-endian 和 at&t operand order。

  • 以 machine-lisp 为汇编语言。

    需要把 machine-lisp 设计成完整的汇编语言。 要嵌入一个解释器在汇编语言中,使得汇编语言可以使用变量和表达式。

  • 学习 SPARC,在正常的 RISC 集之外, 增加处理带有 tagged value 的指令。

  • 探索 vector 相关的指令集。

永恒 ​

[2025-12-03]

knuth 设计 mmix, dev 设计 uxn, 都在于让程序变为永恒。

其实自己设计指令集构架, 如果没有真实硬件的实现, 其意义很小的。

knuth 认为自己设计出了 clean 的指令集构架, 但是就算是我这种人看到了 mmix, 也想把它改成 little-endian 和 at&t operand order。

hacker mindset ​

[2025-12-03]

新的指令集构架是很有趣的项目, 但是对于 x-lisp 目前的项目状态来说是不适合的。

想要用 vm 的方案来取代 native 编译器, 是为了逃避 root scanning 问题, 或者认为 root scanning 问题太难解决。

但是编译器的使命就是 bridging the differences, 写编译器的人如何能抱怨 differences?