Eva*_*oll 4 perl internals opcode
使用Perl,我有两个类似的语法,
if ($a && $b) { exit() }
do { exit() } if ($a && $b)
Run Code Online (Sandbox Code Playgroud)
我认为这些应该是相同的,但最上面的一个创建一个null vK操作码,
<1> null vK*/1 ->-
Run Code Online (Sandbox Code Playgroud)
它的意义是null vK什么,它有什么作用?
$ perl -MO=Concise -e'if ($a && $b) { exit() }'
8 <@> leave[1 ref] vKP/REFC ->(end)
1 <0> enter ->2
2 <;> nextstate(main 1 -e:1) v:{ ->3
- <1> null vK/1 ->8
6 <|> and(other->7) vK/1 ->8
- <1> null sK/1 ->6
4 <|> and(other->5) sK/1 ->8
- <1> ex-rv2sv sK/1 ->4
3 <#> gvsv[*a] s ->4
- <1> ex-rv2sv sK/1 ->-
5 <#> gvsv[*b] s ->6
- <@> scope vK ->-
- <;> ex-nextstate(main 3 -e:1) v ->7
7 <0> exit v* ->8
-e syntax OK
Run Code Online (Sandbox Code Playgroud)
以下是经文,
$ perl -MO=Concise -e'do { exit() } if ($a && $b)'
8 <@> leave[1 ref] vKP/REFC ->(end)
1 <0> enter ->2
2 <;> nextstate(main 1 -e:1) v:{ ->3
- <1> null vK/1 ->8
6 <|> and(other->7) vK/1 ->8
- <1> null sKP/1 ->6
4 <|> and(other->5) sK/1 ->8
- <1> ex-rv2sv sK/1 ->4
3 <#> gvsv[*a] s ->4
- <1> ex-rv2sv sK/1 ->-
5 <#> gvsv[*b] s ->6
- <1> null vK*/1 ->-
- <@> scope vK ->-
- <;> ex-nextstate(main 2 -e:1) v ->7
7 <0> exit v* ->8
Run Code Online (Sandbox Code Playgroud)
该行开头的" - "表示操作不会被执行,也可以使用perl -MO=Concise,-exec.
也就是说,B :: Concise输出中的null vK...或null sK...操作码并不意味着某些操作已经被优化掉了.perldoc在B :: Concise上清楚地表明这种优化ex-在输出中表示:
Nullops显示为"ex-opname",其中opname是由perl优化的op.它们显示的序列号为" - ",因为它们没有被执行(它们没有出现在前面的例子中),它们在这里打印,因为它们反映了解析.
例如:
> perl -MO=Concise -e "$a"
4 <@> leave[1 ref] vKP/REFC ->(end)
1 <0> enter ->2
2 <;> nextstate(main 1 -e:1) v:{ ->3
- **<1> ex-rv2sv vK/1 ->4**
3 <#> gvsv[*a] s ->4
Run Code Online (Sandbox Code Playgroud)
那么这些空值是什么呢?
它们是来自Perl用于解析代码的yacc语法的真正空值,并且它们从一开始就不打算执行.
在你的情况下,超出部分null vk直接来自以下do BLOCK语法规则(perly.y):
termdo : DO term %prec UNIOP /* do $filename */
{ $$ = dofile($2, $1);}
| DO block %prec '(' /* do { code */
{ $$ = newUNOP(OP_NULL, OPf_SPECIAL, op_scope($2));}
;
Run Code Online (Sandbox Code Playgroud)
我们可以在这里看到它:
>perl -MO=Concise -e "do{}"
4 <@> leave[1 ref] vKP/REFC ->(end)
1 <0> enter ->2
2 <;> nextstate(main 2 -e:1) v:{ ->3
- <1> null vK*/1 ->4
- <@> scope vK ->-
3 <0> stub v ->4
Run Code Online (Sandbox Code Playgroud)
在其他情况下,空值来自yacc操作.显然,这些空值用于帮助管理操作树,因为它们永远不会执行,我认为Perl开发人员不会为他们的存在而烦恼.
以下是解析布尔表达式产生的null操作示例:
>perl -MO=Concise -e "$a||$b"
6 <@> leave[1 ref] vKP/REFC ->(end)
1 <0> enter ->2
2 <;> nextstate(main 1 -e:1) v:{ ->3
- <1> null vK/1 ->6
4 <|> or(other->5) vK/1 ->6
- <1> ex-rv2sv sK/1 ->4
3 <#> gvsv[*a] s ->4
- <1> ex-rv2sv vK/1 ->-
5 <#> gvsv[*b] s ->6
Run Code Online (Sandbox Code Playgroud)
为什么这里为空?另一个片段有助于说清楚:
>perl -MO=Concise -e "!$a&&!$b"
7 <@> leave[1 ref] vKP/REFC ->(end)
1 <0> enter ->2
2 <;> nextstate(main 1 -e:1) v:{ ->3
6 <1> not vK/1 ->7
4 <|> or(other->5) sK/1 ->6
- <1> ex-not sK/1 ->4
- <1> ex-rv2sv sK/1 ->-
3 <#> gvsv[*a] s ->4
- <1> ex-not sK/1 ->6
- <1> ex-rv2sv sK/1 ->-
5 <#> gvsv[*b] s ->6
Run Code Online (Sandbox Code Playgroud)
它似乎null vK已成为not vK.仔细看,我们可以看到的Perl优化!$a&&!$b到!($a||$b)与not(!)正在发生的null.事实证明,Perl总是保留逻辑表达式的父操作码,并且如果表达式可以简化,外部not
Perl放入not父操作码,null否则.
总结:通过显示NULL操作码ex-的B::Concise输出是由优化程序和NULL操作码以表示null来自语法分析器.它们都不会被执行,也不会带来任何性能损失.