X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=xs-src%2FMouseAccessor.xs;h=0496f0b794ca28a6749ef3642fd1ee7de2fc0406;hb=4d6296668d881802f473b73fccff010b3b78d9d9;hp=0d0d44818f14de2da0e7a7c43041c26748b380b8;hpb=fad99075beae804374b22c9e356f90daf23bbc05;p=gitmo%2FMouse.git diff --git a/xs-src/MouseAccessor.xs b/xs-src/MouseAccessor.xs index 0d0d448..0496f0b 100644 --- a/xs-src/MouseAccessor.xs +++ b/xs-src/MouseAccessor.xs @@ -2,7 +2,9 @@ #define CHECK_INSTANCE(instance) STMT_START{ \ assert(instance); \ - if(!(SvROK(instance) && SvTYPE(SvRV(instance)) == SVt_PVHV)){ \ + if(UNLIKELY( \ + !(SvROK(instance) \ + && SvTYPE(SvRV(instance)) == SVt_PVHV) )){ \ croak("Invalid object instance: '%"SVf"'", instance); \ } \ } STMT_END @@ -14,16 +16,87 @@ static MGVTBL mouse_accessor_vtbl; /* MAGIC identity */ #define dMOUSE_self SV* const self = mouse_accessor_get_self(aTHX_ ax, items, cv) +/* simple instance slot accessor (or Mouse::Meta::Instance) */ + +SV* +mouse_instance_create(pTHX_ HV* const stash) { + SV* instance; + assert(stash); + assert(SvTYPE(stash) == SVt_PVHV); + instance = sv_bless( newRV_noinc((SV*)newHV()), stash ); + return sv_2mortal(instance); +} + +SV* +mouse_instance_clone(pTHX_ SV* const instance) { + SV* proto; + CHECK_INSTANCE(instance); + assert(SvOBJECT(SvRV(instance))); + + proto = newRV_noinc((SV*)newHVhv((HV*)SvRV(instance))); + sv_bless(proto, SvSTASH(SvRV(instance))); + return sv_2mortal(proto); +} + +bool +mouse_instance_has_slot(pTHX_ SV* const instance, SV* const slot) { + assert(slot); + CHECK_INSTANCE(instance); + return hv_exists_ent((HV*)SvRV(instance), slot, 0U); +} + +SV* +mouse_instance_get_slot(pTHX_ SV* const instance, SV* const slot) { + HE* he; + assert(slot); + CHECK_INSTANCE(instance); + he = hv_fetch_ent((HV*)SvRV(instance), slot, FALSE, 0U); + return he ? HeVAL(he) : NULL; +} + +SV* +mouse_instance_set_slot(pTHX_ SV* const instance, SV* const slot, SV* const value) { + HE* he; + SV* sv; + assert(slot); + assert(value); + CHECK_INSTANCE(instance); + he = hv_fetch_ent((HV*)SvRV(instance), slot, TRUE, 0U); + sv = HeVAL(he); + sv_setsv(sv, value); + SvSETMAGIC(sv); + return sv; +} + +SV* +mouse_instance_delete_slot(pTHX_ SV* const instance, SV* const slot) { + assert(instance); + assert(slot); + CHECK_INSTANCE(instance); + return hv_delete_ent((HV*)SvRV(instance), slot, 0, 0U); +} + +void +mouse_instance_weaken_slot(pTHX_ SV* const instance, SV* const slot) { + HE* he; + assert(slot); + CHECK_INSTANCE(instance); + he = hv_fetch_ent((HV*)SvRV(instance), slot, FALSE, 0U); + if(he){ + sv_rvweaken(HeVAL(he)); + } +} + +/* utilities */ + STATIC_INLINE SV* mouse_accessor_get_self(pTHX_ I32 const ax, I32 const items, CV* const cv) { - if(items < 1){ + if(UNLIKELY( items < 1 )){ croak("Too few arguments for %s", GvNAME(CvGV(cv))); } - /* NOTE: If self has GETMAGIC, $self->accessor will invoke GETMAGIC - * before calling methods, so SvGETMAGIC(self) is not necessarily needed here. + * before calling methods, so SvGETMAGIC(self) is not required here. */ - return ST(0); } @@ -37,12 +110,14 @@ mouse_accessor_generate(pTHX_ SV* const attr, XSUBADDR_t const accessor_impl){ xsub = newXS(NULL, accessor_impl, __FILE__); sv_2mortal((SV*)xsub); - mg = sv_magicext((SV*)xsub, MOUSE_xa_slot(xa), PERL_MAGIC_ext, &mouse_accessor_vtbl, (char*)xa, HEf_SVKEY); + mg = sv_magicext((SV*)xsub, MOUSE_xa_slot(xa), + PERL_MAGIC_ext, &mouse_accessor_vtbl, (char*)xa, HEf_SVKEY); MOUSE_mg_flags(mg) = (U16)MOUSE_xa_flags(xa); /* NOTE: - * although we use MAGIC for gc, we also store mg to CvXSUBANY for efficiency (gfx) + * although we use MAGIC for gc, we also store mg to + * CvXSUBANY for efficiency (gfx) */ CvXSUBANY(xsub).any_ptr = (void*)mg; @@ -50,17 +125,6 @@ mouse_accessor_generate(pTHX_ SV* const attr, XSUBADDR_t const accessor_impl){ } -#define PUSH_VALUE(value, flags) STMT_START { \ - if((flags) & MOUSEf_ATTR_SHOULD_AUTO_DEREF && GIMME_V == G_ARRAY){ \ - mouse_push_values(aTHX_ value, (flags)); \ - } \ - else{ \ - dSP; \ - XPUSHs(value ? value : &PL_sv_undef); \ - PUTBACK; \ - } \ - } STMT_END \ - /* pushes return values, does auto-deref if needed */ static void mouse_push_values(pTHX_ SV* const value, U16 const flags){ @@ -111,7 +175,19 @@ mouse_push_values(pTHX_ SV* const value, U16 const flags){ PUTBACK; } -static void +STATIC_INLINE void +mouse_push_value(pTHX_ SV* const value, U16 const flags) { + if(flags & MOUSEf_ATTR_SHOULD_AUTO_DEREF && GIMME_V == G_ARRAY){ + mouse_push_values(aTHX_ value, flags); + } + else{ + dSP; + XPUSHs(value ? value : &PL_sv_undef); + PUTBACK; + } +} + +STATIC_INLINE void mouse_attr_get(pTHX_ SV* const self, MAGIC* const mg){ U16 const flags = MOUSE_mg_flags(mg); SV* value; @@ -123,7 +199,7 @@ mouse_attr_get(pTHX_ SV* const self, MAGIC* const mg){ value = mouse_xa_set_default(aTHX_ MOUSE_mg_xa(mg), self); } - PUSH_VALUE(value, flags); + mouse_push_value(aTHX_ value, flags); } static void @@ -163,7 +239,7 @@ mouse_attr_set(pTHX_ SV* const self, MAGIC* const mg, SV* value){ assert(SvTYPE(value) != SVTYPEMASK); } - PUSH_VALUE(value, flags); + mouse_push_value(aTHX_ value, flags); } XS(XS_Mouse_accessor) @@ -243,18 +319,21 @@ mouse_simple_accessor_generate(pTHX_ MAGIC* mg; if(!fq_name){ - /* anonymous xsubs need sv_2mortal */ + /* anonymous xsubs need sv_2mortal() */ sv_2mortal((SV*)xsub); } - mg = sv_magicext((SV*)xsub, slot, PERL_MAGIC_ext, &mouse_accessor_vtbl, (char*)dptr, dlen); + mg = sv_magicext((SV*)xsub, slot, + PERL_MAGIC_ext, &mouse_accessor_vtbl, (char*)dptr, dlen); + SvREFCNT_dec(slot); /* sv_magicext() increases refcnt in mg_obj */ if(dlen == HEf_SVKEY){ SvREFCNT_dec(dptr); } /* NOTE: - * although we use MAGIC for gc, we also store mg to CvXSUBANY for efficiency (gfx) + * although we use MAGIC for gc, we also store mg to CvXSUBANY + * for efficiency (gfx) */ CvXSUBANY(xsub).any_ptr = (void*)mg; @@ -342,7 +421,6 @@ XS(XS_Mouse_inheritable_class_accessor) { dMOUSE_self; SV* const slot = MOUSE_mg_slot((MAGIC*)XSANY.any_ptr); SV* value; - SV* stash_ref; HV* stash; if(items == 1){ /* reader */ @@ -357,11 +435,7 @@ XS(XS_Mouse_inheritable_class_accessor) { value = NULL; /* -Wuninitialized */ } - stash_ref= mcall0(self, mouse_namespace); - if(!(SvROK(stash_ref) && SvTYPE(SvRV(stash_ref)) == SVt_PVHV)) { - croak("namespace() didn't return a HASH reference"); - } - stash = (HV*)SvRV(stash_ref); + stash = mouse_get_namespace(aTHX_ self); if(!value) { /* reader */ value = get_slot(self, slot); @@ -394,76 +468,6 @@ XS(XS_Mouse_inheritable_class_accessor) { XSRETURN(1); } -/* simple instance slot accessor (or Mouse::Meta::Instance) */ - -SV* -mouse_instance_create(pTHX_ HV* const stash) { - SV* instance; - assert(stash); - assert(SvTYPE(stash) == SVt_PVHV); - instance = sv_bless( newRV_noinc((SV*)newHV()), stash ); - return sv_2mortal(instance); -} - -SV* -mouse_instance_clone(pTHX_ SV* const instance) { - SV* proto; - CHECK_INSTANCE(instance); - assert(SvOBJECT(SvRV(instance))); - - proto = newRV_noinc((SV*)newHVhv((HV*)SvRV(instance))); - sv_bless(proto, SvSTASH(SvRV(instance))); - return sv_2mortal(proto); -} - -bool -mouse_instance_has_slot(pTHX_ SV* const instance, SV* const slot) { - assert(slot); - CHECK_INSTANCE(instance); - return hv_exists_ent((HV*)SvRV(instance), slot, 0U); -} - -SV* -mouse_instance_get_slot(pTHX_ SV* const instance, SV* const slot) { - HE* he; - assert(slot); - CHECK_INSTANCE(instance); - he = hv_fetch_ent((HV*)SvRV(instance), slot, FALSE, 0U); - return he ? HeVAL(he) : NULL; -} - -SV* -mouse_instance_set_slot(pTHX_ SV* const instance, SV* const slot, SV* const value) { - HE* he; - SV* sv; - assert(slot); - assert(value); - CHECK_INSTANCE(instance); - he = hv_fetch_ent((HV*)SvRV(instance), slot, TRUE, 0U); - sv = HeVAL(he); - sv_setsv(sv, value); - SvSETMAGIC(sv); - return sv; -} - -SV* -mouse_instance_delete_slot(pTHX_ SV* const instance, SV* const slot) { - assert(instance); - assert(slot); - CHECK_INSTANCE(instance); - return hv_delete_ent((HV*)SvRV(instance), slot, 0, 0U); -} - -void -mouse_instance_weaken_slot(pTHX_ SV* const instance, SV* const slot) { - HE* he; - assert(slot); - CHECK_INSTANCE(instance); - he = hv_fetch_ent((HV*)SvRV(instance), slot, FALSE, 0U); - if(he){ - sv_rvweaken(HeVAL(he)); - } -} MODULE = Mouse::Meta::Method::Accessor::XS PACKAGE = Mouse::Meta::Method::Accessor::XS