Compilation Common Lisp编译代码并将代码加载到映像中的机制

Compilation Common Lisp编译代码并将代码加载到映像中的机制,compilation,common-lisp,sbcl,language-implementation,ccl,Compilation,Common Lisp,Sbcl,Language Implementation,Ccl,最近我一直在阅读现代操作系统如何加载可执行程序并为其分配内存。不幸的是,我只有一本俄文的计算机科学书籍作为参考,所以,如果我错了,请纠正我,但现代操作系统在可执行程序中似乎有不同的数据和实际处理器命令部分。此外,不可能将控制权授予数据部分,即不能将命令存储在那里。在可执行文件(text)部分也无法更改处理器命令 因此,问题是:现代编译CL(SBCL,Clozure CL)是如何实现的?据我所知,它创建编译的FASL文件,然后加载它们。但可见的FASL文件是在编译文件时创建的。计算函数形式时会发生

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

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


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

也许这澄清了一些问题:

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

(你好)

您的代码将被执行,您运行的代码将被编译 没有解释。在SBCL中,不需要先显式编译, 因为您输入或加载到sbcl中的所有代码都是动态编译的。在里面 事实上,sbcl中没有翻译。在其他lisp系统中,您可以 需要显式编译才能编译代码

fasl文件本身不可执行,必须一起使用 与sbcl


我不能给出一个完整的答案,但大致的步骤是:源代码->阅读->宏扩展->编译->链接->加载->运行。处理顶级表单的一种典型方法是将它们编译成匿名顶级函数,然后调用该函数来完成加载。链接是eg GC和查找符号所必需的。在操作系统中,可以执行和不能执行的内容的实际分离是内存页的属性。当操作系统加载二进制文件时,会自动进行相应设置。JIT编译语言可以使用eg
mprotect
来实现这一点。你说JIT编译器的事情更复杂是什么意思?通用Lisp(fasl与否)编译到本机代码与JIT有何不同?@DanRobertson With JIT things以中间形式(字节码)存在并编译。最重要的是,JVM监控代码执行,并尝试“动态”优化代码(如何成功是另一个问题)。CL路由有点静态。当然可以考虑FASL这样的字节码。至少对于某些实现而言?JavaScript实现即使输入源代码也不被视为JIT编译器吗?我不知道是否有跟踪CL编译器,但跟踪JIT与中的JIT不同general@DanRobertson是的,事实上,当我在这里说“JIT”时,我的意思是“跟踪JIT”。至于FASL作为字节码:据我所知,SBCL和CCL生成本机代码,CLISP没有JIT。我对ECL不太清楚,而且我没有访问其他编译器的权限。不幸的是,它没有。这仍然是一幅大图。我对力学感兴趣。FASL文件需要以指令指针可以到达的方式加载。只需加载一个文件即可将其加载到数据部分—您无法在那里获取控制指针。@mobiuseng一旦主内存中有内容,文本和数据之间就没有这种区别。是否可以执行某些操作取决于页表中的权限位。