summaryrefslogtreecommitdiff
path: root/pp_hot.c
diff options
context:
space:
mode:
authorsyber <syber@crazypanda.ru>2014-12-01 23:20:27 +0300
committerFather Chrysostomos <sprout@cpan.org>2014-12-02 17:56:48 -0800
commit810bd8b704e337dfba3e46eaea33244c1b0afce3 (patch)
tree1b45d1d145ccd5b7eecbb14ef57f69da2e5bdb3f /pp_hot.c
parent11f9ab1a291e36ad40cb66d0bd0aedce897c06c3 (diff)
downloadperl-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.c75
1 files changed, 53 insertions, 22 deletions
diff --git a/pp_hot.c b/pp_hot.c
index 48cc1cbea7..35493eb1b4 100644
--- a/pp_hot.c
+++ b/pp_hot.c
@@ -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);