cod*_*ons 7 bytecode compilation rakudo raku
考虑以下两个程序:
unit module Comp;
say 'Hello, world!'
Run Code Online (Sandbox Code Playgroud)
和
unit module Comp;
CHECK { if $*DISTRO.is-win { say 'compiling on Windows' }}
say 'Hello, world!'
Run Code Online (Sandbox Code Playgroud)
天真地,我希望两个程序编译成完全相同的字节码:CHECK块指定在编译结束时运行的代码;检查一个变量然后什么都不做对程序的运行时行为没有影响,因此(我原以为)不需要包含在编译的字节码中。
然而,编译这两个方案并没有产生相同的字节码。具体来说,编译没有CHECK块的版本会创建 24K 的字节码,而带有它的版本则是 60K。为什么这两个版本的字节码不同?字节码中的这种差异是否具有(或可能具有)运行时成本?(似乎必须如此,但我想确定一下)。
还有一个相关的问题:DOC CHECK块如何与上述内容相适应?我的理解是,即使编译器DOC CHECK在不使用--doc标志运行时也会跳过块。与此一致,当给定一个像上面那样的块时,hello-world 程序的字节码不会增加大小DOC CHECK。但是,如果块包含语句,它的大小确实会增加use。由此,我得出结论,这use是某种特殊情况,即使在DOC CHECK块中也能执行。那是对的吗?如果是这样,还有其他类似的特殊形式我应该知道吗?
一个CHECKorBEGIN块(或其他BEGIN时间结构)可能包含转义代码。例如:
BEGIN SomeClass.^add_method('foo', anon method foo() { 42 })
Run Code Online (Sandbox Code Playgroud)
向存在于BEGIN块边界之外的类添加方法。因此,在编译输出中需要该方法的字节码。目前,Rakudo 保守地将所有内容的字节码包含在BEGINorCHECK块中。在未来的一些简单情况下,可能会避免这种情况。
就运行时成本而言,实现在一定程度上最大限度地减少了永远不会运行的字节码的成本(在这种情况下不是那么多,而是因为标准库很大,但许多程序只使用其中的一小部分)。例如:
mmap'd,所以它的一些未使用部分实际上可能不会被分页到内存中就目前use而言,它的动作在解析后立即执行。位于DOC CHECK块内并不能抑制这一点——通常也不能,因为这use可能会带来一些需要知道的东西,以便完成对该块内容的解析。