X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=gv.c;h=418e08c7d276ef60d783faba5493c3e784af8329;hb=4df4e287246babaf287cf6336ca862ceeead8e46;hp=2b94c276c9bcb8b13093c06d01803013153173bf;hpb=5c284bb074748eab0ba4ff8e53eb1eeeb0f7a962;p=p5sagit%2Fp5-mst-13.2.git diff --git a/gv.c b/gv.c index 2b94c27..418e08c 100644 --- a/gv.c +++ b/gv.c @@ -122,6 +122,25 @@ Perl_gv_fetchfile(pTHX_ const char *name) return gv; } +/* +=for apidoc gv_const_sv + +If C is a typeglob whose subroutine entry is a constant sub eligible for +inlining, or C is a placeholder reference that would be promoted to such +a typeglob, then returns the value returned by the sub. Otherwise, returns +NULL. + +=cut +*/ + +SV * +Perl_gv_const_sv(pTHX_ GV *gv) +{ + if (SvTYPE(gv) == SVt_PVGV) + return cv_const_sv(GvCVu(gv)); + return SvROK(gv) ? SvRV(gv) : NULL; +} + void Perl_gv_init(pTHX_ GV *gv, HV *stash, const char *name, STRLEN len, int multi) { @@ -129,6 +148,24 @@ Perl_gv_init(pTHX_ GV *gv, HV *stash, const char *name, STRLEN len, int multi) register GP *gp; const bool doproto = SvTYPE(gv) > SVt_NULL; const char * const proto = (doproto && SvPOK(gv)) ? SvPVX_const(gv) : NULL; + SV *const has_constant = doproto && SvROK(gv) ? SvRV(gv) : NULL; + + assert (!(proto && has_constant)); + + if (has_constant) { + /* The constant has to be a simple scalar type. */ + switch (SvTYPE(has_constant)) { + case SVt_PVAV: + case SVt_PVHV: + case SVt_PVCV: + case SVt_PVFM: + case SVt_PVIO: + Perl_croak(aTHX_ "Cannot convert a reference to %s to typeglob", + sv_reftype(has_constant, 0)); + } + SvRV_set(gv, NULL); + SvROK_off(gv); + } sv_upgrade((SV*)gv, SVt_PVGV); if (SvLEN(gv)) { @@ -163,9 +200,14 @@ Perl_gv_init(pTHX_ GV *gv, HV *stash, const char *name, STRLEN len, int multi) if (doproto) { /* Replicate part of newSUB here. */ SvIOK_off(gv); ENTER; - /* XXX unsafe for threads if eval_owner isn't held */ - (void) start_subparse(0,0); /* Create empty CV in compcv. */ - GvCV(gv) = PL_compcv; + if (has_constant) { + /* newCONSTSUB takes ownership of the reference from us. */ + GvCV(gv) = newCONSTSUB(stash, name, has_constant); + } else { + /* XXX unsafe for threads if eval_owner isn't held */ + (void) start_subparse(0,0); /* Create empty CV in compcv. */ + GvCV(gv) = PL_compcv; + } LEAVE; PL_sub_generation++; @@ -699,7 +741,8 @@ Perl_gv_fetchpvn_flags(pTHX_ const char *nambeg, STRLEN full_len, I32 flags, I32 len; register const char *namend; HV *stash = 0; - const I32 add = flags & ~SVf_UTF8; + const I32 no_init = flags & (GV_NOADD_NOINIT | GV_NOINIT); + const I32 add = flags & ~SVf_UTF8 & ~ GV_NOADD_NOINIT; PERL_UNUSED_ARG(full_len); @@ -864,7 +907,7 @@ Perl_gv_fetchpvn_flags(pTHX_ const char *nambeg, STRLEN full_len, I32 flags, require_errno(gv); } return gv; - } else if (add & GV_NOINIT) { + } else if (no_init) { return gv; } @@ -1189,7 +1232,7 @@ Perl_newIO(pTHX) SvOBJECT_on(io); /* Clear the stashcache because a new IO could overrule a package name */ hv_clear(PL_stashcache); - iogv = gv_fetchpv("FileHandle::", FALSE, SVt_PVHV); + iogv = gv_fetchpv("FileHandle::", 0, SVt_PVHV); /* unless exists($main::{FileHandle}) and defined(%main::FileHandle::) */ if (!(iogv && GvHV(iogv) && HvARRAY(GvHV(iogv)))) iogv = gv_fetchpv("IO::Handle::", TRUE, SVt_PVHV);