【问题标题】:Mechanism by which Common Lisp compiles and loads code into imageCommon Lisp 将代码编译并加载到图像中的机制
【发布时间】:2018-12-06 05:23:55
【问题描述】:

最近我一直在阅读有关现代操作系统如何加载可执行程序并为它们分配内存的文章。不幸的是,我只有一本俄语的计算机科学书籍作为参考,所以,如果我错了,请纠正我,但现代操作系统似乎在可执行程序中有不同的部分用于数据和实际的处理器命令。此外,不可能将控制权交给数据部分,即不能将命令存储在那里。也无法在可执行 (text) 部分更改处理器命令。

因此,问题是:现代编译的 CL(SBCL、Clozure-CL)是如何做到的?据我所知,它会创建已编译的 FASL 文件,然后加载它们。但是在编译文件时会创建可见的 FASL 文件。评估函数形式时会发生什么?其次,CL 如何加载它们(在机器/操作系统命令级别)以便为它们分配正确的内存?此外,必须以某种方式卸载旧代码。

PS。当然,这对于解释型语言来说不是问题。对于 JIT 编译器来说,事情变得更加复杂。

【问题讨论】:

  • 我不能给出完整的答案,但大致的步骤是:源代码 -> 阅读 -> 宏扩展 -> 编译 -> 链接 -> 加载 -> 运行。处理顶级表单的一种典型方法是将它们编译成一些匿名的顶级函数,该函数被调用以完成加载。例如 GC 和查找符号需要链接。在操作系统中,可以执行和不可以执行的实际分离是内存页面的属性。这在操作系统加载二进制文件时会自动适当地设置。 JIT 编译语言可以使用例如mprotect 来执行此操作。
  • 当你说 JIT 编译器的事情更复杂时,你是什么意思? Common Lisp (fasl or not) 编译成原生代码与 JIT 有何不同?
  • @DanRobertson 使用 JIT,事物以中间形式(字节码)存在并编译。最重要的是,JVM,例如,监视代码执行并尝试“动态”优化代码(如何成功是另一个问题)。 CL 路由更加静态。
  • 当然可以考虑 fasl 这样的字节码。至少对于某些实现?即使 JavaScript 实现输入源代码,它们是否不被视为 JIT 编译器?我不知道是否有任何跟踪 CL 编译器,但跟踪 JIT 与一般的 JIT 不同
  • @DanRobertson 是的,确实,当我在这种情况下说“JIT”时,我的意思是“跟踪 JIT”。至于 FASL 作为字节码:据我所知,SBCL 和 CCL 生成本机代码,CLISP 没有 JIT。不确定 ECL,我无法访问其他编译器。

标签: compilation common-lisp sbcl language-implementation ccl


【解决方案1】:

也许这可以澄清一些事情:Google Groups

与 C 不同,您不需要编译程序,然后执行它们。相反,您正在 lisp 环境中工作。当你 如上所述将您的文件加载到 sbcl 中,您只需键入

(你好)

你的代码将被执行,你运行的代码被编译,并且 不解释。在 SBCL 中,您不需要先显式编译, 因为您键入或加载到 sbcl 中的所有代码都是即时编译的。在 事实上,sbcl 中没有解释器。在其他 lisp 系统中,您可以 需要显式编译才能编译代码。

fasl文件不能单独执行,必须配合使用 与 sbcl。

【讨论】:

  • 不幸的是,它没有。这仍然是一张大图。我对机械很感兴趣。 FASL 文件需要以指令指针可以到达的方式加载。只需加载一个文件就会将其加载到数据部分 —你不能在那里得到控制指针。
  • @mobiuseng 一旦某些东西在主内存中,文本和数据之间就没有这种区别。是否可以执行某事由页表中的权限位决定。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-12-03
  • 1970-01-01
  • 1970-01-01
  • 2012-07-31
  • 1970-01-01
  • 1970-01-01
  • 2010-10-24
相关资源
最近更新 更多