Skip to content
This repository was archived by the owner on Jun 1, 2023. It is now read-only.

Commit 2f2a941

Browse files
committed
:const init - constant fold arrays
my @A :const = (1) or (1,2,3) => READONLY,AvSHAPED also our. all at compile-time, so we can constant fold and shape optimize all subsequent accesses.
1 parent 5904e90 commit 2f2a941

File tree

1 file changed

+75
-23
lines changed

1 file changed

+75
-23
lines changed

op.c

Lines changed: 75 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4694,40 +4694,91 @@ Perl_newASSIGNOP_maybe_const(pTHX_ OP *left, I32 optype, OP *right)
46944694
left = OpSIBLING(attr);
46954695
OpMORESIB_set(left, NULL);
46964696
OpMORESIB_set(attr, NULL);
4697-
/* constany folding should probably be deferred to ck_pad or ck_[sa]assign,
4698-
to get proper lhs values. */
4699-
if (IS_PADxV_OP(left) && left->op_targ) {
4700-
if (IS_CONST_OP(right) && left->op_private == OPpLVAL_INTRO) {
4697+
/* Should constany folding be deferred to ck_[sa]assign? */
4698+
if (IS_PADxV_OP(left) && left->op_targ && left->op_private == OPpLVAL_INTRO) {
4699+
if (IS_CONST_OP(right)) {
47014700
SV* lsv = PAD_SV(left->op_targ);
47024701
SV *rsv = cSVOPx_sv(right);
47034702
if (SvTYPE(lsv) == SVt_NULL || SvTYPE(lsv) == SvTYPE(rsv)) {
4704-
DEBUG_k(Perl_deb(aTHX_ "constant fold my %s = %s\n",
4705-
SvPEEK(lsv), SvPEEK(rsv)));
4706-
SvSetMagicSV(lsv, rsv);
4703+
DEBUG_k(Perl_deb(aTHX_ "my %s :const = %s\n",
4704+
PAD_COMPNAME_PV(left->op_targ), SvPEEK(rsv)));
4705+
SvSetMagicSV(lsv, SvREFCNT_inc_NN(rsv));
47074706
left->op_private = 0; /* rm LVINTRO */
47084707
SvREADONLY_on(lsv);
4708+
op_free(right);
4709+
return ck_pad(left);
4710+
} else if (SvTYPE(lsv) == SVt_PVAV) {
4711+
DEBUG_k(Perl_deb(aTHX_ "my %s[1] :const = (%s)\n",
4712+
PAD_COMPNAME_PV(left->op_targ), SvPEEK(rsv)));
4713+
AvSHAPED_on((AV*)lsv); /* XXX we can even type it */
4714+
av_store((AV*)lsv,0,SvREFCNT_inc_NN(rsv));
4715+
SvREADONLY_on(lsv);
4716+
op_free(right);
4717+
return ck_pad(left);
4718+
}
4719+
}
4720+
else if (IS_TYPE(left, PADAV) && IS_TYPE(right, LIST)) {
4721+
SSize_t i;
4722+
AV* lsv = (AV*)PAD_SV(left->op_targ);
4723+
/* check if all rhs elements are const */
4724+
OP *o = OpSIBLING(OpFIRST(right));
4725+
for (;o && IS_CONST_OP(o); o=OpSIBLING(o)) ;
4726+
if (!o) {
4727+
DEBUG_k(Perl_deb(aTHX_ "my %s[1] :const = (...)\n",
4728+
PAD_COMPNAME_PV(left->op_targ)));
4729+
for (i=0,o=OpSIBLING(OpFIRST(right)); o; o=OpSIBLING(o), i++) {
4730+
SV* rsv = cSVOPx_sv(o); /* XXX check for unique types */
4731+
av_store(lsv, i, SvREFCNT_inc_NN(rsv));
4732+
}
4733+
AvSHAPED_on(lsv); /* we can even type it */
4734+
SvREADONLY_on(lsv);
4735+
op_free(right);
47094736
return ck_pad(left);
47104737
}
47114738
}
47124739
}
4713-
/* our, but still a NULL sv */
4714-
else if (IS_RV2ANY_OP(left) && IS_CONST_OP(right)) {
4740+
/* our, but still mostly a NULL sv */
4741+
else if (IS_TYPE(left, RV2SV) && IS_CONST_OP(right)) {
47154742
GV* gv = cGVOPx_gv(OpFIRST(left));
47164743
SV *rsv = cSVOPx_sv(right);
4717-
SV* lsv;
4744+
SV *lsv = GvSV(gv);
47184745
assert(IS_TYPE(OpFIRST(left), GV));
4719-
if (IS_TYPE(left, RV2SV))
4720-
lsv = GvSV(gv);
4721-
else if (IS_TYPE(left, RV2AV))
4722-
lsv = (SV*)GvAV(gv);
4723-
else if (IS_TYPE(left, RV2HV))
4724-
lsv = (SV*)GvHV(gv);
47254746
if (SvTYPE(lsv) == SVt_NULL || SvTYPE(lsv) == SvTYPE(rsv)) {
4726-
DEBUG_k(Perl_deb(aTHX_ "constant fold: our %s = %s\n",
4747+
DEBUG_k(Perl_deb(aTHX_ "our $%s :const = %s\n",
47274748
SvPEEK(lsv), SvPEEK(rsv)));
4728-
SvSetMagicSV(lsv, rsv);
4749+
SvSetMagicSV(lsv, SvREFCNT_inc_NN(rsv));
4750+
SvREADONLY_on(lsv);
4751+
return ck_rvconst(left);
4752+
}
4753+
} else if (IS_TYPE(left, RV2AV)) {
4754+
GV* gv = cGVOPx_gv(OpFIRST(left));
4755+
AV *lsv = GvAV(gv);
4756+
/* check if all rhs elements are const */
4757+
if (IS_CONST_OP(right)) {
4758+
SV *rsv = cSVOPx_sv(right);
4759+
DEBUG_k(Perl_deb(aTHX_ "our @%s[1] :const = %s\n",
4760+
SvPEEK((SV*)lsv), SvPEEK(rsv)));
4761+
AvSHAPED_on(lsv); /* we can even type it */
4762+
av_store(lsv, 0, SvREFCNT_inc_NN(rsv));
47294763
SvREADONLY_on(lsv);
4764+
op_free(right);
47304765
return ck_rvconst(left);
4766+
} else if (IS_TYPE(right, LIST)) {
4767+
SSize_t i;
4768+
OP *o = OpSIBLING(OpFIRST(right));
4769+
for (;o && IS_CONST_OP(o); o=OpSIBLING(o)) ;
4770+
if (!o) {
4771+
DEBUG_k(Perl_deb(aTHX_ "our @%s[1] :const = (...)\n",
4772+
SvPEEK((SV*)lsv)));
4773+
for (i=0,o=OpSIBLING(OpFIRST(right)); o; o=OpSIBLING(o), i++) {
4774+
SV* rsv = cSVOPx_sv(o); /* XXX check for unique types */
4775+
av_store(lsv, i, SvREFCNT_inc_NN(rsv));
4776+
}
4777+
AvSHAPED_on(lsv); /* we can even type it */
4778+
SvREADONLY_on(lsv);
4779+
op_free(right);
4780+
return ck_rvconst(left);
4781+
}
47314782
}
47324783
}
47334784
/* else not constant foldable. like a lhs ref or list. */
@@ -4779,13 +4830,15 @@ S_my_kid(pTHX_ OP *o, OP *attrs, OP **imopsp)
47794830
} else if (attrs) {
47804831
GV * const gv = cGVOPx_gv(OpFIRST(o));
47814832
HV *stash = GvSTASH(gv);
4782-
int num_const;
47834833
if (!stash) stash = (HV*)SV_NO;
47844834
assert(PL_parser);
47854835
PL_parser->in_my = FALSE;
47864836
PL_parser->in_my_stash = NULL;
4787-
num_const = attrs_has_const(attrs, FALSE);
4788-
if (num_const)
4837+
/* We cannot get away without loading attributes.pm
4838+
because our $a :const = $i still needs run-time init.
4839+
It also simplifies newASSIGNOP_maybe_const().
4840+
*/
4841+
if (attrs_has_const(attrs, FALSE))
47894842
apply_attrs_my(stash, o, attrs, imopsp);
47904843
else
47914844
apply_attrs(stash,
@@ -4827,8 +4880,7 @@ S_my_kid(pTHX_ OP *o, OP *attrs, OP **imopsp)
48274880
stash = PAD_COMPNAME_TYPE(o->op_targ);
48284881
if (!stash)
48294882
stash = PL_curstash;
4830-
if (stash != PL_curstash || attrs_has_const(attrs, FALSE) != 1)
4831-
apply_attrs_my(stash, o, attrs, imopsp);
4883+
apply_attrs_my(stash, o, attrs, imopsp);
48324884
}
48334885
o->op_flags |= OPf_MOD;
48344886
o->op_private |= OPpLVAL_INTRO;

0 commit comments

Comments
 (0)