3 个版本

0.1.2 2022年11月4日
0.1.1 2021年11月13日
0.1.0 2021年11月13日

608编程语言

每月 21 次下载

MIT 许可证

34KB
1.5K SLoC

这是我收集的 Befunge 虚拟机。我将按时间顺序解释它们的演变。

marsh

2010年3月,我创建了 marsh

它包括一些微优化,例如对 GCC 的汇编进行后处理,因为 GCC 生成 'set rax to L1,跳转到 L2,这间接跳转到 rax'。还包括一个 spawn 脚本,它将二进制文件中的 2000 个空格替换为 befunge 源代码,允许自我托管 befunge 可执行文件。

一个月后,我将索引优化为使一个维度是 2 的幂。选择是 128x25 与 80x32。后者要小得多,但有些不直观,因为内存布局将垂直文本并排放置。我还观察到,如果我复制虚拟机 4 次,我可以将指令调度减少到不需要检查方向。改变方向通过改变虚拟机来实现。

中场休息

在这段时间里,我搬了家,读了《源泉》和《阿特拉斯耸耸肩》,并开始上大学。

bejit

到了12月,我第一次尝试制作 bejit。它是一个没有任何窥孔优化的 malloc 洋,而且它比 marsh 快得多。不久之后,我开始编写一个优化器,当替换节点时,它会迭代整个 10240 个循环缓存单元格。有很多错误。到了2月,我放弃了,将其重写为使用无优化的字节码,发现性能与 marsh 相当。优化解决了这个问题,然后我继续前进。

年复一年,直到2015年9月

在这段时间里,我退学了,回到了家乡,玩 elementsthegame,制作了 openEtG,在买房后不久失业,最近从地板业回到了编程。我在夏天忙于打磨和涂漆房屋(不要油漆雪松)的同时,开始离线工作,在 Befunge 到 Python 字节码 JIT 上。我真的很感谢在房屋上的帮助。我还开始使用 vim。

funge.py

我不记得是什么让我想回到 Python 字节码的混乱中,但我一直很想做类似的事情,但 CLR 和 JVM 都对非静态堆栈深度很挑剔。我很快了解到处理下溢(CPython 将崩溃)非常重要,这意味着需要跟踪堆栈深度。

我意识到g的边界检查可以优化为只检查0<=x<2560,因此这也被回滚到marsh和bejit

二月份,我花了三次尝试来减少操作码定义的冗余。模板化背后的想法是,操作码块将主要是常数,我可以省略很多LOAD/ADD/STORE指令。唯一可变的部分将是跳转偏移量。我在一个死胡同里试图以优化编译器的方式使beer6更快。由于beer6是一个特殊的基准测试,它会触发几百次重新编译。为了实验peepholing,我创建了一个分支

二月份,我开始思考Python字节码的优化。我发现abarnert有一个实验性的存储库,所以我加入了进来,对funge.py进行战略优化

我试图找出如何删除栈保护器。我还决定funge.py将使用无界空间。能够删除边界检查使其没有性能损失。为了使指令能够处理部分常量传播,必须彻底修改模板。指令被移动到类中以开始分组变得过于分散的数据。发现使用类来解决差异比在op上查找性能更好。修改类稍微慢一点,但总体上是赢的

现在我已经与Befunge合作了半年,我开始考虑如何在vim中制作一个Befunge IDE。bef.vim还有很多工作要做,我真的很失望于vimscript的运行速度

五月份,我将wfunge.py作为唯一的funge.py。在新的字节码中,有一些有趣的微优化,比如加载0比复制非零栈深度和一元非它更好

bejit-elvm

2016年11月,我发现所有深度为1的堆栈的实现中的\都坏了。我还找到了如何通过在栈上留空而不是推入0来使marsh/bejit有更紧密的代码。我还发现了一个很酷的项目ELVM,所以我创建了bejit-elvm,因为他们的解释器像大多数解释器一样。我还花了一些时间改进他们的常量构造,包括除以9的编码

funge.js

我将事情放下直到三月,并在这时写这个readme,因为WASM在Firefox和Chrome中可用。在接下来的几周里,创建了一个优化的wasm jit。它跟踪操作符应该从哪个堆栈中获取值,而不是跟踪部分应用

barfs

2018年12月1日,我发布了barfs,我不知道为什么我包括了它。JIT坏了,所以它只能与evalcfg一起工作。一个月后,我去了旧金山面试,我的生活发生了彻底的变化。文件处理花了几个月时间,但我在喝酒、看电影、并试图在Luwa上取得进展(我没有)

三年后,我现在做得很好,因为我不再需要向人们解释我不喜欢握手。一个周末决定再次尝试barfs。Cranelift文档似乎已经改善,或者可能只是我花了一些时间来吸收。我有些麻烦弄清楚他们迁移到了扩展基本块之外。我修复了funge.js中长期存在的问题#2,哇,调试依赖于我记住所有wasm操作码的代码很难,花了我很长时间才弄清楚depi是一组标志,用于指定哪些堆栈槽位被用作输入,直到我躺下来和我的猫玩耍,才注意到像3/7这样的数字意味着标志。我还养了一只黑猫,她很可爱

依赖关系

~6–16MB
~200K SLoC