【问题标题】:Portable opcode generation便携式操作码生成
【发布时间】:2021-08-06 04:47:12
【问题描述】:

我目前正在使用 Python 开发一种非常简单的面向堆栈的编程语言,旨在向新手介绍编程概念。该语言确实允许用户制作自己的功能。虽然速度对我的语言来说不是一个大问题,但我想创建一个“简单”的 JIT 编译器来为用户的函数生成 Python 字节码。

我正在聆听 PyCon 关于如何手工制作字节码并从中制作函数的精彩演讲。但是,演讲者确实添加了一个警告,即 Python 字节码的特定字节值绝不可移植,甚至可以在 3.5.1 和 3.5.2 之间更改。

所以,我调出dis 模块的文档,看到dis.opmap,描述为

字典映射操作名称到字节码。

因此,如果我想将BINARY_ADD 放入字节码对象中,我不需要知道它的具体值。我可以在 dis.opmap 中查找它。

这终于让我想到了我的问题:为了使我的 JIT 编译器与任何版本的 Python 兼容,我是否需要注意任何其他可移植性陷阱(例如,字节序、每个操作码的参数大小/数量) 3?我想会有某些操作码仅在特定版本中可用。然而,当我在头脑中研究我的 JIT 编译器时,除了最基本的指令之外,我看不到自己使用任何东西。

【问题讨论】:

  • 我不是在质疑您的意图,“向新手介绍编程概念”不会是一种更简单有趣的方式吗?
  • 也许吧,但我打算把它作为我女儿的礼物。她现在只有 11 周,但我想自己制作她的第一语言。
  • aww,祝你好运,我正在看这个帖子,因为这个问题我也很感兴趣
  • 我没有使用 Python 3.x 字节码的经验,但是在各种 2.x 版本之间,流控制操作码的工作方式发生了一些重大变化 - 例如,是否有条件跳转操作码将其操作数留在堆栈上。当版本更改需要您以不同的方式使用完全不同的操作时,在 dis.opmap 中查找值的帮助有限!我认为您可能会发现通过生成 Python 源代码并在其上调用 exec() 来更轻松地进行代码生成。

标签: python jit portability opcode


【解决方案1】:

我相当肯定 Python 字节码是无证的。这是一个混乱的地方,也是一个可怕的地方。我会在最后提供一个替代方案,但首先......为什么它很可怕?首先,Python 被解释为字节码,并且该字节码在虚拟机上运行。该虚拟机绝对没有记录。您可以在操作码提交历史中查看here。请注意,它改变了......很多。除此之外,您还实现了诸如 f-strings 之类的东西,这意味着底层 C 代码将发生变化。这是一个非常混乱的地方,因为很多人都在改变它。

现在,这就是我的建议所在。事情之所以复杂,是因为很多人都在改变它。你女儿已经 11 周了,她至少还要再等 3 周才能编程;)。那么,为什么不制作自己的语言呢?我推荐阅读https://craftinginterpreters.com/contents.html。它是完全免费的,并引导您使用 AST 在 Java 中制作解释性语言,然后介绍如何使用字节码和各种块操作(就像 Python 一样)制作虚拟机。这是一本非常容易阅读的书,每章末尾都有很好的发人深省的问题。您可以制作一种完全可定制的语言,并最终由您控制。想要更改操作码?去吧。希望所有用户都在同一个竞争环境中并保证向后兼容性?这是您的编程语言,随心所欲。

归根结底,这对您来说会很有趣。而且,如果您不得不担心添加、更改或过载操作码,您可能不会玩得开心。当最终出现问题时,您将不得不调试您的解释语言、JIT 编译器和 Python 的源代码。这只是一个令人头疼的问题。

【讨论】:

  • 那么,改变的不仅仅是操作码值本身?
  • 正确。看看commit history 的老鼠窝。看一下正在更改的 test_dis.py 内容。有些成为跳转目标,有些得到不同的操作码,等等。关键是因为语言总是在成熟,它总是在变化。因此,如果人们可以进行操作码级别的改进,他们会的。
  • 如果您好奇字节码是如何编译的,请查看compile.c。事情总是在变化,无论是出于优化还是 PEP 的原因,还是完全出于其他原因。
  • 谢谢推荐!这本书太棒了!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-24
  • 1970-01-01
  • 1970-01-01
  • 2011-02-01
  • 2011-02-20
相关资源
最近更新 更多