diff options
author | syber <syber@crazypanda.ru> | 2014-12-01 23:20:27 +0300 |
---|---|---|
committer | Father Chrysostomos <sprout@cpan.org> | 2014-12-02 17:56:48 -0800 |
commit | 810bd8b704e337dfba3e46eaea33244c1b0afce3 (patch) | |
tree | 1b45d1d145ccd5b7eecbb14ef57f69da2e5bdb3f /pp_hot.c | |
parent | 11f9ab1a291e36ad40cb66d0bd0aedce897c06c3 (diff) | |
download | perl-810bd8b704e337dfba3e46eaea33244c1b0afce3.tar.gz |
Speed up method calls like $o->Other::method() and $o->Other::SUPER::method().
It was done by adding new OP_METHOD_REDIR and OP_METHOD_REDIR_SUPER optypes.
Class name to redirect is saved into METHOP as a shared hash string.
Method name is changed (class name removed) an saved into op_meth_sv as
a shared string hash.
So there is no need now to scan for '::' and calculate class and method names
at runtime (in gv_fetchmethod_*) and searching cache HV without precomputed hash.
B::* modules are changed to support new op types.
method_redir is now printed by Concise like (for threaded perl)
$obj->AAA::meth
5 <.> method_redir[PACKAGE "AAA", PV "meth"] ->6
Diffstat (limited to 'pp_hot.c')
-rw-r--r-- | pp_hot.c | 75 |
1 files changed, 53 insertions, 22 deletions
@@ -3083,6 +3083,18 @@ PP(pp_method) RETURN; } +#define METHOD_CHECK_CACHE(stash,cache,meth) \ + const HE* const he = hv_fetch_ent(cache, meth, 0, 0); \ + if (he) { \ + gv = MUTABLE_GV(HeVAL(he)); \ + if (isGV(gv) && GvCV(gv) && (!GvCVGEN(gv) || GvCVGEN(gv) \ + == (PL_sub_generation + HvMROMETA(stash)->cache_gen))) \ + { \ + XPUSHs(MUTABLE_SV(GvCV(gv))); \ + RETURN; \ + } \ + } \ + PP(pp_method_named) { dSP; @@ -3091,17 +3103,7 @@ PP(pp_method_named) HV* const stash = opmethod_stash(meth); if (LIKELY(SvTYPE(stash) == SVt_PVHV)) { - const HE* const he = hv_fetch_ent(stash, meth, 0, 0); - if (he) { - gv = MUTABLE_GV(HeVAL(he)); - if (isGV(gv) && GvCV(gv) && - (!GvCVGEN(gv) || GvCVGEN(gv) - == (PL_sub_generation + HvMROMETA(stash)->cache_gen))) - { - XPUSHs(MUTABLE_SV(GvCV(gv))); - RETURN; - } - } + METHOD_CHECK_CACHE(stash, stash, meth); } gv = gv_fetchmethod_sv_flags(stash, meth, GV_AUTOLOAD|GV_CROAK); @@ -3124,17 +3126,46 @@ PP(pp_method_super) opmethod_stash(meth); if ((cache = HvMROMETA(stash)->super)) { - const HE* const he = hv_fetch_ent(cache, meth, 0, 0); - if (he) { - gv = MUTABLE_GV(HeVAL(he)); - if (isGV(gv) && GvCV(gv) && - (!GvCVGEN(gv) || GvCVGEN(gv) - == (PL_sub_generation + HvMROMETA(stash)->cache_gen))) - { - XPUSHs(MUTABLE_SV(GvCV(gv))); - RETURN; - } - } + METHOD_CHECK_CACHE(stash, cache, meth); + } + + gv = gv_fetchmethod_sv_flags(stash, meth, GV_AUTOLOAD|GV_CROAK|GV_SUPER); + assert(gv); + + XPUSHs(isGV(gv) ? MUTABLE_SV(GvCV(gv)) : MUTABLE_SV(gv)); + RETURN; +} + +PP(pp_method_redir) +{ + dSP; + GV* gv; + SV* const meth = cMETHOPx_meth(PL_op); + HV* stash = gv_stashsv(cMETHOPx_rclass(PL_op), 0); + opmethod_stash(meth); /* not used but needed for error checks */ + + if (stash) { METHOD_CHECK_CACHE(stash, stash, meth); } + else stash = MUTABLE_HV(cMETHOPx_rclass(PL_op)); + + gv = gv_fetchmethod_sv_flags(stash, meth, GV_AUTOLOAD|GV_CROAK); + assert(gv); + + XPUSHs(isGV(gv) ? MUTABLE_SV(GvCV(gv)) : MUTABLE_SV(gv)); + RETURN; +} + +PP(pp_method_redir_super) +{ + dSP; + GV* gv; + HV* cache; + SV* const meth = cMETHOPx_meth(PL_op); + HV* stash = gv_stashsv(cMETHOPx_rclass(PL_op), 0); + opmethod_stash(meth); /* not used but needed for error checks */ + + if (UNLIKELY(!stash)) stash = MUTABLE_HV(cMETHOPx_rclass(PL_op)); + else if ((cache = HvMROMETA(stash)->super)) { + METHOD_CHECK_CACHE(stash, cache, meth); } gv = gv_fetchmethod_sv_flags(stash, meth, GV_AUTOLOAD|GV_CROAK|GV_SUPER); |