From: gfx Date: Sun, 19 Jul 2009 02:35:41 +0000 (+0900) Subject: Optimize symbol manipulators X-Git-Tag: 0.92_01~30 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=e2e116c2657fd5eae8734b395bc31f81c1aaaee3;p=gitmo%2FClass-MOP.git Optimize symbol manipulators --- diff --git a/lib/Class/MOP/Package.pm b/lib/Class/MOP/Package.pm index c0ebb07..38269d2 100644 --- a/lib/Class/MOP/Package.pm +++ b/lib/Class/MOP/Package.pm @@ -95,6 +95,7 @@ sub namespace { # we could just store a ref and it would # Just Work, but oh well :\ no strict 'refs'; + no warnings 'uninitialized'; \%{$_[0]->{'package'} . '::'} } diff --git a/mop.h b/mop.h index 288c8ad..1b1960b 100644 --- a/mop.h +++ b/mop.h @@ -49,6 +49,7 @@ XS(mop_xs_simple_reader); extern SV *mop_method_metaclass; extern SV *mop_associated_metaclass; extern SV *mop_wrap; +extern SV *mop_namespace; UV mop_check_package_cache_flag(pTHX_ HV *stash); int mop_get_code_info (SV *coderef, char **pkg, char **name); diff --git a/xs/MOP.xs b/xs/MOP.xs index 5dfc0cd..a699836 100644 --- a/xs/MOP.xs +++ b/xs/MOP.xs @@ -3,6 +3,7 @@ SV *mop_method_metaclass; SV *mop_associated_metaclass; SV *mop_wrap; +SV *mop_namespace; static bool find_method (const char *key, STRLEN keylen, SV *val, void *ud) @@ -30,6 +31,7 @@ BOOT: mop_method_metaclass = newSVpvs("method_metaclass"); mop_wrap = newSVpvs("wrap"); mop_associated_metaclass = newSVpvs("associated_metaclass"); + mop_namespace = newSVpvs("namespace"); MOP_CALL_BOOT (boot_Class__MOP__Package); MOP_CALL_BOOT (boot_Class__MOP__Class); diff --git a/xs/Package.xs b/xs/Package.xs index 6e907f3..c552f56 100644 --- a/xs/Package.xs +++ b/xs/Package.xs @@ -5,9 +5,13 @@ #define VARIABLE_CREATE 0x02 -static const char* -mop_deconstruct_variable_name(pTHX_ SV* const variable, svtype* const type, const char** const type_name, I32* const flags) { - const char* name; +static void +mop_deconstruct_variable_name(pTHX_ SV* const variable, + const char** const var_name, STRLEN* const var_name_len, + svtype* const type, + const char** const type_name, + I32* const flags) { + if(SvROK(variable) && SvTYPE(SvRV(variable)) == SVt_PVHV){ /* e.g. variable = { type => "SCALAR", name => "foo" } */ @@ -20,7 +24,8 @@ mop_deconstruct_variable_name(pTHX_ SV* const variable, svtype* const type, cons if(!(svp && SvOK(*svp))){ croak("You must pass a variable name"); } - name = SvPV_const(*svp, len); + *var_name = SvPV_const(*svp, len); + *var_name_len = len; if(len < 1){ croak("You must pass a variable name"); } @@ -70,6 +75,9 @@ mop_deconstruct_variable_name(pTHX_ SV* const variable, svtype* const type, cons croak("You must pass a variable name including a sigil"); } + *var_name = pv + 1; + *var_name_len = len - 1; + switch(pv[0]){ case '$': *type = SVt_PV; /* for all the types of scalars */ @@ -94,11 +102,7 @@ mop_deconstruct_variable_name(pTHX_ SV* const variable, svtype* const type, cons default: croak("I do not recognize that sigil '%c'", pv[0]); } - - name = pv + 1; } - - return name; } MODULE = Class::MOP::Package PACKAGE = Class::MOP::Package @@ -143,6 +147,7 @@ BOOT: #define S_GET 0 #define S_ADD GV_ADDMULTI + SV* add_package_symbol(SV* self, SV* variable, SV* ref = &PL_sv_undef) ALIAS: @@ -153,25 +158,49 @@ PREINIT: svtype type; const char* type_name; const char* var_name; - SV* package_name; - const char* fq_name; - I32 flags = 0; /* not used */ + STRLEN var_name_len; + I32 flags = 0; + GV** gvp; + GV* gv; CODE: - var_name = mop_deconstruct_variable_name(aTHX_ variable, &type, &type_name, &flags); + if(items == 3 && ix != S_ADD){ + croak("Too many arguments for %s", GvNAME(CvGV(cv))); + } + + mop_deconstruct_variable_name(aTHX_ variable, &var_name, &var_name_len, &type, &type_name, &flags); - package_name = mop_call0(aTHX_ self, KEY_FOR(name)); - if(!SvOK(package_name)){ - croak("name() did not return a defined value"); + + if(ix != S_ADD){ /* for shortcut fetching */ + SV* const ns = mop_call0(aTHX_ self, mop_namespace); + HV* stash; + if(!(SvROK(ns) && SvTYPE(SvRV(ns)) == SVt_PVHV)){ + croak("namespace() did not return a hash reference"); + } + stash = (HV*)SvRV(ns); + gvp = (GV**)hv_fetch(stash, var_name, var_name_len, FALSE); + } + else{ + gvp = NULL; } - fq_name = Perl_form(aTHX_ "%"SVf"::%s", package_name, var_name); - if(items == 3 && ix != S_ADD){ - croak("Too many arguments for %s", GvNAME(CvGV(cv))); + if(gvp && isGV(*gvp)){ + gv = *gvp; } + else{ + SV* const package_name = mop_call0(aTHX_ self, KEY_FOR(name)); + const char* fq_name; - if(SvOK(ref)){ /* add_package_symbol with a value */ - GV* gv; + if(!SvOK(package_name)){ + croak("name() did not return a defined value"); + } + fq_name = Perl_form(aTHX_ "%"SVf"::%s", package_name, var_name); + gv = gv_fetchpv(fq_name, ix | (flags & GLOB_CREATE ? GV_ADDMULTI : 0), type); + } + + + + if(SvOK(ref)){ /* add_package_symbol with a value */ if(type == SVt_PV){ if(!SvROK(ref)){ ref = newRV_noinc(newSVsv(ref)); @@ -181,7 +210,6 @@ CODE: else if(!(SvROK(ref) && SvTYPE(SvRV(ref)) == type)){ croak("You must pass a reference of %s for the value of %s", type_name, GvNAME(CvGV(cv))); } - gv = gv_fetchpv(fq_name, GV_ADDMULTI, type); if(type == SVt_PVCV && GvCV(gv)){ /* XXX: should introduce an option { redefine => 1 } ? */ @@ -192,7 +220,6 @@ CODE: RETVAL = ref; } else { /* no values */ - GV* const gv = gv_fetchpv(fq_name, ix | (flags & GLOB_CREATE ? GV_ADDMULTI : 0), type); SV* sv; if(!gv){