内联内置文件的文档?
Documentation for inlining of built-ins?
我遇到了无法以直观方式抑制警告的情况,因为 perl 正在内联对内置函数的调用。例如
use strict;
use warnings;
{
no warnings 'substr'; # no effect
foo(substr('123', 4, 6)); # out of range but shouldn't emit a warning
}
sub foo {
my $s = shift; # warning reported here
# do something
}
运行此代码会导致
substr outside of string at c:\temp\foo.pl line 10.
为了禁止警告,我必须将 no warnings 'substr'
移到函数内部。
sub foo {
no warnings 'substr'; # works here, but there's no call to substr
my $s = shift; # no warnings here
# do something
}
我可以看到,通过 perl -MO=Terse
传递代码,正在内联对 substr
的调用
LISTOP (0x27dcaa8) leave [1]
OP (0x27a402c) enter
COP (0x27dcac8) nextstate
BINOP (0x27dcb00) leaveloop
LOOP (0x27dcb20) enterloop
LISTOP (0x27dcb68) lineseq
COP (0x27dcb88) nextstate
UNOP (0x27dcbc0) entersub [5] # entry point for foo
UNOP (0x27dcbf4) null [148]
OP (0x27dcbdc) pushmark
LISTOP (0x27dcc48) substr [4] # substr gets called here
OP (0x27dcc30) null [3]
SVOP (0x27dcc84) const [6] PV (0x2319944) "123"
SVOP (0x27dcc68) const [7] IV (0x2319904) 4
SVOP (0x27dcc14) const [8] IV (0x231944c) 6
UNOP (0x27dcca0) null [17]
PADOP (0x27dccf4) gv GV (0x2318e5c) *foo
是否在任何地方记录了此优化器行为? perlsub
只提到常量函数的内联。鉴于警告是在错误的行上报告的,并且 no warnings
在进行调用的词法范围内不起作用,我倾向于将其报告为错误,尽管我想不出如何在保持优化的同时合理地修复它。
注意:此行为是在 Perl 5.16.1 下观察到的。
这是记录在案的行为(在 perldiag 中):
substr outside of string
(W substr),(F) You tried to reference a substr() that pointed
outside of a string. That is, the absolute value of the offset was
larger than the length of the string. See "substr" in perlfunc.
This warning is fatal if substr is used in an lvalue context (as
the left hand side of an assignment or as a subroutine argument for
example).
强调我的。
将电话改为
foo(my $o = substr('123', 4, 6));
使警告消失。
将 no warnings
移动到 sub 中不会改变我的行为。你有什么 Perl 版本? (此处为 5.14.4)。
我用来测试的代码:
#!/usr/bin/perl
use strict;
use warnings;
$| = 1;
print 1, foo(my $s1 = substr('abc', 4, 6));
print 2, bar(my $s2 = substr('def', 4, 6));
{
no warnings 'substr';
print 3, foo(my $s3 = substr('ghi', 4, 6));
print 4, bar(my $s4 = substr('jkl', 4, 6));
print 5, bar(substr('mno', 4, 6)); # Stops here, reports line 12.
print 6, foo(substr('pqr', 4, 6));
}
print "ok\n";
sub foo {
my $s = shift;
}
sub bar {
no warnings 'substr';
my $s = shift;
}
更新:
我在 5.10.1 中得到了相同的行为,但在 5.20.1 中,行为与您描述的一样。
如您在 B::Terse 中所见,substr
未内联。
$ perl -MO=Concise,-exec -e'f(substr($_, 3, 4))'
1 <0> enter
2 <;> nextstate(main 1 -e:1) v:{
3 <0> pushmark s
4 <#> gvsv[*_] s
5 <$> const[IV 3] s
6 <$> const[IV 4] s
7 <@> substr[t4] sKM/3 <-- The substr operator is evaluated first.
8 <#> gv[*f] s/EARLYCV
9 <1> entersub[t5] vKS/TARG <-- The sub call second.
a <@> leave[1 ref] vKP/REFC
-e syntax OK
当 substr
作为左值上下文调用时,substr
returns 包含传递给 substr
.
的操作数的神奇标量
$ perl -MDevel::Peek -e'$_ = "abcdef"; Dump(${\ substr($_, 3, 4) })'
SV = PVLV(0x2865d60) at 0x283fbd8
REFCNT = 2
FLAGS = (GMG,SMG) <--- Gets and sets are magical.
IV = 0 GMG: A function that mods the scalar
NV = 0 is called before fetches.
PV = 0 SMG: A function is called after the
MAGIC = 0x2856810 scalar is modified.
MG_VIRTUAL = &PL_vtbl_substr
MG_TYPE = PERL_MAGIC_substr(x)
TYPE = x
TARGOFF = 3 <--- substr's second arg
TARGLEN = 4 <--- substr's third arg
TARG = 0x287bfd0 <--- substr's first arg
FLAGS = 0
SV = PV(0x28407f0) at 0x287bfd0 <--- A dump of substr's first arg
REFCNT = 2
FLAGS = (POK,IsCOW,pPOK)
PV = 0x2865d20 "abcdef"[=11=]
CUR = 6
LEN = 10
COW_REFCNT = 1
子程序参数在左值上下文中计算,因为在 Perl 中子程序参数总是通过引用传递[1].
$ perl -E'sub f { $_[0] = "def"; } $x = "abc"; f($x); say $x;'
def
访问神奇标量时发生子字符串操作。
$ perl -E'$x = "abc"; $r = \substr($x, 0, 1); $x = "def"; say $$r;'
d
这样做是为了让substr(...) = "abc";
- 这可能是使用类似于以下的语言记录的:"The elements of
@_
are aliased to the subroutine arguments."
我遇到了无法以直观方式抑制警告的情况,因为 perl 正在内联对内置函数的调用。例如
use strict;
use warnings;
{
no warnings 'substr'; # no effect
foo(substr('123', 4, 6)); # out of range but shouldn't emit a warning
}
sub foo {
my $s = shift; # warning reported here
# do something
}
运行此代码会导致
substr outside of string at c:\temp\foo.pl line 10.
为了禁止警告,我必须将 no warnings 'substr'
移到函数内部。
sub foo {
no warnings 'substr'; # works here, but there's no call to substr
my $s = shift; # no warnings here
# do something
}
我可以看到,通过 perl -MO=Terse
substr
的调用
LISTOP (0x27dcaa8) leave [1]
OP (0x27a402c) enter
COP (0x27dcac8) nextstate
BINOP (0x27dcb00) leaveloop
LOOP (0x27dcb20) enterloop
LISTOP (0x27dcb68) lineseq
COP (0x27dcb88) nextstate
UNOP (0x27dcbc0) entersub [5] # entry point for foo
UNOP (0x27dcbf4) null [148]
OP (0x27dcbdc) pushmark
LISTOP (0x27dcc48) substr [4] # substr gets called here
OP (0x27dcc30) null [3]
SVOP (0x27dcc84) const [6] PV (0x2319944) "123"
SVOP (0x27dcc68) const [7] IV (0x2319904) 4
SVOP (0x27dcc14) const [8] IV (0x231944c) 6
UNOP (0x27dcca0) null [17]
PADOP (0x27dccf4) gv GV (0x2318e5c) *foo
是否在任何地方记录了此优化器行为? perlsub
只提到常量函数的内联。鉴于警告是在错误的行上报告的,并且 no warnings
在进行调用的词法范围内不起作用,我倾向于将其报告为错误,尽管我想不出如何在保持优化的同时合理地修复它。
注意:此行为是在 Perl 5.16.1 下观察到的。
这是记录在案的行为(在 perldiag 中):
substr outside of string
(W substr),(F) You tried to reference a substr() that pointed outside of a string. That is, the absolute value of the offset was larger than the length of the string. See "substr" in perlfunc. This warning is fatal if substr is used in an lvalue context (as the left hand side of an assignment or as a subroutine argument for example).
强调我的。
将电话改为
foo(my $o = substr('123', 4, 6));
使警告消失。
将 no warnings
移动到 sub 中不会改变我的行为。你有什么 Perl 版本? (此处为 5.14.4)。
我用来测试的代码:
#!/usr/bin/perl
use strict;
use warnings;
$| = 1;
print 1, foo(my $s1 = substr('abc', 4, 6));
print 2, bar(my $s2 = substr('def', 4, 6));
{
no warnings 'substr';
print 3, foo(my $s3 = substr('ghi', 4, 6));
print 4, bar(my $s4 = substr('jkl', 4, 6));
print 5, bar(substr('mno', 4, 6)); # Stops here, reports line 12.
print 6, foo(substr('pqr', 4, 6));
}
print "ok\n";
sub foo {
my $s = shift;
}
sub bar {
no warnings 'substr';
my $s = shift;
}
更新:
我在 5.10.1 中得到了相同的行为,但在 5.20.1 中,行为与您描述的一样。
如您在 B::Terse 中所见,substr
未内联。
$ perl -MO=Concise,-exec -e'f(substr($_, 3, 4))'
1 <0> enter
2 <;> nextstate(main 1 -e:1) v:{
3 <0> pushmark s
4 <#> gvsv[*_] s
5 <$> const[IV 3] s
6 <$> const[IV 4] s
7 <@> substr[t4] sKM/3 <-- The substr operator is evaluated first.
8 <#> gv[*f] s/EARLYCV
9 <1> entersub[t5] vKS/TARG <-- The sub call second.
a <@> leave[1 ref] vKP/REFC
-e syntax OK
当 substr
作为左值上下文调用时,substr
returns 包含传递给 substr
.
$ perl -MDevel::Peek -e'$_ = "abcdef"; Dump(${\ substr($_, 3, 4) })'
SV = PVLV(0x2865d60) at 0x283fbd8
REFCNT = 2
FLAGS = (GMG,SMG) <--- Gets and sets are magical.
IV = 0 GMG: A function that mods the scalar
NV = 0 is called before fetches.
PV = 0 SMG: A function is called after the
MAGIC = 0x2856810 scalar is modified.
MG_VIRTUAL = &PL_vtbl_substr
MG_TYPE = PERL_MAGIC_substr(x)
TYPE = x
TARGOFF = 3 <--- substr's second arg
TARGLEN = 4 <--- substr's third arg
TARG = 0x287bfd0 <--- substr's first arg
FLAGS = 0
SV = PV(0x28407f0) at 0x287bfd0 <--- A dump of substr's first arg
REFCNT = 2
FLAGS = (POK,IsCOW,pPOK)
PV = 0x2865d20 "abcdef"[=11=]
CUR = 6
LEN = 10
COW_REFCNT = 1
子程序参数在左值上下文中计算,因为在 Perl 中子程序参数总是通过引用传递[1].
$ perl -E'sub f { $_[0] = "def"; } $x = "abc"; f($x); say $x;'
def
访问神奇标量时发生子字符串操作。
$ perl -E'$x = "abc"; $r = \substr($x, 0, 1); $x = "def"; say $$r;'
d
这样做是为了让substr(...) = "abc";
- 这可能是使用类似于以下的语言记录的:"The elements of
@_
are aliased to the subroutine arguments."