X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=xs-src%2FMouse.xs;h=831e522b8d60430a78b20b96197e014a53dbc369;hb=53142eda803bb80d2a4edb8b8c264a40390abf4b;hp=b8951c13a58332cc39e5c4d8463370ac54431bc7;hpb=abbcd124154fda138a43e996d4a521c79d16d72d;p=gitmo%2FMouse.git diff --git a/xs-src/Mouse.xs b/xs-src/Mouse.xs index b8951c1..831e522 100644 --- a/xs-src/Mouse.xs +++ b/xs-src/Mouse.xs @@ -49,6 +49,15 @@ enum mouse_modifier_t { static MGVTBL mouse_xc_vtbl; /* for identity */ +HV* +mouse_get_namespace(pTHX_ SV* const meta) { + SV* const package = get_slot(meta, mouse_package); + if(!(package && SvOK(package))){ + croak("No package name defined for metaclass"); + } + return gv_stashsv(package, GV_ADDMULTI); +} + static AV* mouse_calculate_all_attributes(pTHX_ SV* const metaclass) { SV* const avref = mcall0s(metaclass, "_calculate_all_attributes"); @@ -67,8 +76,9 @@ mouse_class_has_custom_buildargs(pTHX_ HV* const stash) { return buildargs && CvXSUB(GvCV(buildargs)) != XS_Mouse__Object_BUILDARGS; } -static void -mouse_class_update_xc(pTHX_ SV* const metaclass PERL_UNUSED_DECL, HV* const stash, AV* const xc) { +static AV* +mouse_class_update_xc(pTHX_ SV* const metaclass PERL_UNUSED_DECL, AV* const xc) { + HV* const stash = MOUSE_xc_stash(xc); AV* const linearized_isa = mro_get_linear_isa(stash); I32 const len = AvFILLp(linearized_isa) + 1; I32 i; @@ -136,13 +146,12 @@ mouse_class_update_xc(pTHX_ SV* const metaclass PERL_UNUSED_DECL, HV* const stas LEAVE; sv_setuv(MOUSE_xc_gen(xc), mro_get_pkg_gen(stash)); + return xc; } static AV* -mouse_get_xc(pTHX_ SV* const metaclass) { +mouse_get_xc_wo_check(pTHX_ SV* const metaclass) { AV* xc; - SV* gen; - HV* stash; MAGIC* mg; if(!IsObject(metaclass)){ @@ -151,21 +160,18 @@ mouse_get_xc(pTHX_ SV* const metaclass) { mg = mouse_mg_find(aTHX_ SvRV(metaclass), &mouse_xc_vtbl, 0x00); if(!mg){ - SV* const package = get_slot(metaclass, mouse_package); - STRLEN len; - const char* const pv = SvPV_const(package, len); - - stash = gv_stashpvn(pv, len, TRUE); + /* cache stash for performance */ + HV* const stash = mouse_get_namespace(aTHX_ metaclass); xc = newAV(); - mg = sv_magicext(SvRV(metaclass), (SV*)xc, PERL_MAGIC_ext, &mouse_xc_vtbl, pv, len); + mg = sv_magicext(SvRV(metaclass), (SV*)xc, PERL_MAGIC_ext, + &mouse_xc_vtbl, NULL, 0); SvREFCNT_dec(xc); /* refcnt++ in sv_magicext */ av_extend(xc, MOUSE_XC_last - 1); av_store(xc, MOUSE_XC_GEN, newSVuv(0U)); av_store(xc, MOUSE_XC_STASH, (SV*)stash); - SvREFCNT_inc_simple_void_NN(stash); } else{ @@ -174,20 +180,33 @@ mouse_get_xc(pTHX_ SV* const metaclass) { assert(xc); assert(SvTYPE(xc) == SVt_PVAV); } + return xc; +} - gen = MOUSE_xc_gen(xc); - - if(SvUVX(gen) != 0U && MOUSE_xc_flags(xc) & MOUSEf_XC_IS_IMMUTABLE){ - return xc; +static int +mouse_xc_is_fresh(pTHX_ AV* const xc) { + HV* const stash = MOUSE_xc_stash(xc); + SV* const gen = MOUSE_xc_gen(xc); + if(SvUVX(gen) != 0U && MOUSE_xc_flags(xc) & MOUSEf_XC_IS_IMMUTABLE) { + return TRUE; } + return SvUVX(gen) == mro_get_pkg_gen(stash); +} - stash = MOUSE_xc_stash(xc); - - if(SvUVX(gen) != mro_get_pkg_gen(stash)){ - mouse_class_update_xc(aTHX_ metaclass, stash, xc); - } +STATIC_INLINE AV* +mouse_get_xc(pTHX_ SV* const metaclass) { + AV* const xc = mouse_get_xc_wo_check(aTHX_ metaclass); + return mouse_xc_is_fresh(aTHX_ xc) + ? xc + : mouse_class_update_xc(aTHX_ metaclass, xc); +} - return xc; +static AV* +mouse_get_xc_if_fresh(pTHX_ SV* const metaclass) { + AV* const xc = mouse_get_xc_wo_check(aTHX_ metaclass); + return mouse_xc_is_fresh(aTHX_ xc) + ? xc + : NULL; } static HV* @@ -417,8 +436,8 @@ mouse_get_modifier_storage(pTHX_ return (AV*)SvRV(storage_ref); } -static void -XS_Mouse_value_holder(pTHX_ CV* const cv PERL_UNUSED_DECL) { +static +XSPROTO(XS_Mouse_value_holder) { dVAR; dXSARGS; SV* const value = (SV*)XSANY.any_ptr; assert(value); @@ -464,11 +483,7 @@ HV* namespace(SV* self) CODE: { - SV* const package = get_slot(self, mouse_package); - if(!(package && SvOK(package))){ - croak("No package name defined"); - } - RETVAL = gv_stashsv(package, GV_ADDMULTI); + RETVAL = mouse_get_namespace(aTHX_ self); } OUTPUT: RETVAL @@ -539,14 +554,12 @@ void linearized_isa(SV* self) PPCODE: { - SV* const stash_ref = mcall0(self, mouse_namespace); /* $self->namespace */ - AV* linearized_isa; + /* MOUSE_xc_stash() is not available because the xc system depends on + linearized_isa() */ + HV* const stash = mouse_get_namespace(aTHX_ self); + AV* const linearized_isa = mro_get_linear_isa(stash); I32 len; I32 i; - if(!(SvROK(stash_ref) && SvTYPE(SvRV(stash_ref)) == SVt_PVHV)){ - croak("namespace() didn't return a HASH reference"); - } - linearized_isa = mro_get_linear_isa((HV*)SvRV(stash_ref)); len = AvFILLp(linearized_isa) + 1; EXTEND(SP, len); for(i = 0; i < len; i++){ @@ -611,6 +624,19 @@ CODE: mouse_class_initialize_object(aTHX_ meta, object, args, is_cloning); } +void +_invalidate_metaclass_cache(SV* meta) +CODE: +{ + AV* const xc = mouse_get_xc_if_fresh(aTHX_ meta); + if(xc) { + SV* const gen = MOUSE_xc_gen(xc); + sv_setuv(gen, 0U); + } + delete_slot(meta, newSVpvs_flags("_mouse_cache_", SVs_TEMP)); +} + + MODULE = Mouse PACKAGE = Mouse::Meta::Role BOOT: @@ -719,17 +745,17 @@ ALIAS: CODE: { SV* const meta = get_metaclass(object); + AV* xc; AV* demolishall; - I32 len, i; + I32 len; + I32 i; if(!IsObject(object)){ croak("You must not call %s as a class method", ix == 0 ? "DESTROY" : "DEMOLISHALL"); } - if(SvOK(meta)){ - AV* const xc = mouse_get_xc(aTHX_ meta); - + if(SvOK(meta) && (xc = mouse_get_xc_if_fresh(aTHX_ meta))) { demolishall = MOUSE_xc_demolishall(xc); } else { /* The metaclass is already destroyed */ @@ -748,7 +774,7 @@ CODE: } } - len = AvFILLp(demolishall) + 1; + len = AvFILLp(demolishall) + 1; if(len > 0){ SV* const in_global_destruction = boolSV(PL_dirty); SAVEI32(PL_statusvalue); /* local $? */