3 个版本
| 0.1.2 | 2022年11月4日 |
|---|---|
| 0.1.1 | 2021年11月13日 |
| 0.1.0 | 2021年11月13日 |
608 在 编程语言 中
每月 21 次下载
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