mop_get_package_symbols (stash, filter, collect_all_symbols, ret);
return ret;
}
+
+/* the order of these has to match with those in mop.h */
+static struct {
+ const char *name;
+ const char *value;
+ SV *key;
+ U32 hash;
+} prehashed_keys[key_last] = {
+ DECLARE_KEY(name),
+ DECLARE_KEY(package),
+ DECLARE_KEY(package_name),
+ DECLARE_KEY(body),
+ DECLARE_KEY_WITH_VALUE(package_cache_flag, "_package_cache_flag"),
+ DECLARE_KEY(methods),
+ DECLARE_KEY(VERSION),
+ DECLARE_KEY(ISA)
+};
+
+inline SV *
+mop_prehashed_key_for (mop_prehashed_key_t key)
+{
+ return prehashed_keys[key].key;
+}
+
+inline U32
+mop_prehashed_hash_for (mop_prehashed_key_t key)
+{
+ return prehashed_keys[key].hash;
+}
+
+void
+mop_prehash_keys ()
+{
+ int i;
+
+ for (i = 0; i < key_last; i++) {
+ const char *value = prehashed_keys[i].value;
+ prehashed_keys[i].key = newSVpv(value, strlen(value));
+ PERL_HASH(prehashed_keys[i].hash, value, strlen(value));
+ }
+}
void mop_call_xs (pTHX_ void (*subaddr) (pTHX_ CV *), CV *cv, SV **mark);
-#define DECLARE_KEY(name) SV *key_##name; U32 hash_##name;
-#define NEEDS_KEY(name) extern SV *key_##name; extern U32 hash_##name;
-
-#define PREHASH_KEY_WITH_VALUE(name, value) do { \
- key_##name = newSVpvs(value); \
- PERL_HASH(hash_##name, value, sizeof(value) - 1); \
-} while (0)
-
-/* this is basically the same as the above macro, except that the value will be
- * the stringified name. However, we can't just implement this in terms of
- * PREHASH_KEY_WITH_VALUE as that'd cause macro expansion on the value of
- * 'name' when it's being passed to the other macro. suggestions on how to make
- * this more elegant would be much appreciated */
-
-#define PREHASH_KEY(name) do { \
- key_##name = newSVpvs(#name); \
- PERL_HASH(hash_##name, #name, sizeof(#name) - 1); \
-} while (0)
+#define DECLARE_KEY(name) { #name, #name, NULL, 0 }
+#define DECLARE_KEY_WITH_VALUE(name, value) { #name, value, NULL, 0 }
+
+typedef enum {
+ KEY_name,
+ KEY_package,
+ KEY_package_name,
+ KEY_body,
+ KEY_package_cache_flag,
+ KEY_methods,
+ KEY_VERSION,
+ KEY_ISA,
+ key_last,
+} mop_prehashed_key_t;
+
+#define KEY_FOR(name) mop_prehashed_key_for(KEY_ ##name)
+#define HASH_FOR(name) mop_prehashed_hash_for(KEY_ ##name)
+
+void mop_prehash_keys (void);
+inline SV *mop_prehashed_key_for (mop_prehashed_key_t key);
+inline U32 mop_prehashed_hash_for (mop_prehashed_key_t key);
extern SV *mop_method_metaclass;
extern SV *mop_associated_metaclass;
#include "mop.h"
-NEEDS_KEY(name);
-
MODULE = Class::MOP::Attribute PACKAGE = Class::MOP::Attribute
PROTOTYPES: DISABLE
die("Cannot call name as a class method");
}
- if ( (he = hv_fetch_ent((HV *)SvRV(self), key_name, 0, hash_name)) )
+ if ( (he = hv_fetch_ent((HV *)SvRV(self), KEY_FOR(name), 0, HASH_FOR(name))) )
XPUSHs(HeVAL(he));
else
ST(0) = &PL_sv_undef;
#include "mop.h"
-NEEDS_KEY(name);
-NEEDS_KEY(body);
-NEEDS_KEY(methods);
-NEEDS_KEY(package);
-NEEDS_KEY(package_name);
-NEEDS_KEY(package_cache_flag);
-
static void
mop_update_method_map(pTHX_ SV *const self, SV *const class_name, HV *const stash, HV *const map)
{
method_slot = *hv_fetch(map, method_name, method_name_len, TRUE);
if ( SvOK(method_slot) ) {
- SV *const body = mop_call0(aTHX_ method_slot, key_body); /* $method_object->body() */
+ SV *const body = mop_call0(aTHX_ method_slot, KEY_FOR(body)); /* $method_object->body() */
if ( SvROK(body) && ((CV *) SvRV(body)) == cv ) {
continue;
}
mPUSHs(newRV_inc((SV *)cv));
PUSHs(mop_associated_metaclass);
PUSHs(self);
- PUSHs(key_package_name);
+ PUSHs(KEY_FOR(package_name));
PUSHs(class_name);
- PUSHs(key_name);
+ PUSHs(KEY_FOR(name));
mPUSHs(newSVpv(method_name, method_name_len));
PUTBACK;
SV *self
PREINIT:
HV *const obj = (HV *)SvRV(self);
- SV *const class_name = HeVAL( hv_fetch_ent(obj, key_package, 0, hash_package) );
+ SV *const class_name = HeVAL( hv_fetch_ent(obj, KEY_FOR(package), 0, HASH_FOR(package)) );
HV *const stash = gv_stashsv(class_name, 0);
UV const current = mop_check_package_cache_flag(aTHX_ stash);
- SV *const cache_flag = HeVAL( hv_fetch_ent(obj, key_package_cache_flag, TRUE, hash_package_cache_flag));
- SV *const map_ref = HeVAL( hv_fetch_ent(obj, key_methods, TRUE, hash_methods));
+ SV *const cache_flag = HeVAL( hv_fetch_ent(obj, KEY_FOR(package_cache_flag), TRUE, HASH_FOR(package_cache_flag)));
+ SV *const map_ref = HeVAL( hv_fetch_ent(obj, KEY_FOR(methods), TRUE, HASH_FOR(methods)));
PPCODE:
/* in $self->{methods} does not yet exist (or got deleted) */
if ( !SvROK(map_ref) || SvTYPE(SvRV(map_ref)) != SVt_PVHV ) {
return FALSE;
}
-DECLARE_KEY(name);
-DECLARE_KEY(package);
-DECLARE_KEY(package_name);
-DECLARE_KEY(body);
-DECLARE_KEY(package_cache_flag);
-DECLARE_KEY(methods);
-DECLARE_KEY(VERSION);
-DECLARE_KEY(ISA);
-
SV *mop_method_metaclass;
SV *mop_associated_metaclass;
SV *mop_wrap;
PROTOTYPES: DISABLE
BOOT:
- PREHASH_KEY(name);
- PREHASH_KEY(body);
- PREHASH_KEY(package);
- PREHASH_KEY(package_name);
- PREHASH_KEY(methods);
- PREHASH_KEY(ISA);
- PREHASH_KEY(VERSION);
- PREHASH_KEY_WITH_VALUE(package_cache_flag, "_package_cache_flag");
+ mop_prehash_keys();
mop_method_metaclass = newSVpvs("method_metaclass");
mop_wrap = newSVpvs("wrap");
XSRETURN_NO;
}
- if (hv_exists_ent (stash, key_VERSION, hash_VERSION)) {
- HE *version = hv_fetch_ent(stash, key_VERSION, 0, hash_VERSION);
+ if (hv_exists_ent (stash, KEY_FOR(VERSION), HASH_FOR(VERSION))) {
+ HE *version = hv_fetch_ent(stash, KEY_FOR(VERSION), 0, HASH_FOR(VERSION));
SV *version_sv;
if (version && HeVAL(version) && (version_sv = GvSV(HeVAL(version)))) {
if (SvROK(version_sv)) {
}
}
- if (hv_exists_ent (stash, key_ISA, hash_ISA)) {
- HE *isa = hv_fetch_ent(stash, key_ISA, 0, hash_ISA);
+ if (hv_exists_ent (stash, KEY_FOR(ISA), HASH_FOR(ISA))) {
+ HE *isa = hv_fetch_ent(stash, KEY_FOR(ISA), 0, HASH_FOR(ISA));
if (isa && HeVAL(isa) && GvAV(HeVAL(isa))) {
XSRETURN_YES;
}
#include "mop.h"
-NEEDS_KEY(name);
-NEEDS_KEY(body);
-NEEDS_KEY(package_name);
-
MODULE = Class::MOP::Method PACKAGE = Class::MOP::Method
PROTOTYPES: DISABLE
die("Cannot call name as a class method");
}
- if ( (he = hv_fetch_ent((HV *)SvRV(self), key_name, 0, hash_name)) )
+ if ( (he = hv_fetch_ent((HV *)SvRV(self), KEY_FOR(name), 0, HASH_FOR(name))) )
XPUSHs(HeVAL(he));
else
ST(0) = &PL_sv_undef;
die("Cannot call package_name as a class method");
}
- if ( (he = hv_fetch_ent((HV *)SvRV(self), key_package_name, 0, hash_package_name)) )
+ if ( (he = hv_fetch_ent((HV *)SvRV(self), KEY_FOR(package_name), 0, HASH_FOR(package_name))) )
XPUSHs(HeVAL(he));
else
ST(0) = &PL_sv_undef;
die("Cannot call body as a class method");
}
- if ( (he = hv_fetch_ent((HV *)SvRV(self), key_body, 0, hash_body)) )
+ if ( (he = hv_fetch_ent((HV *)SvRV(self), KEY_FOR(body), 0, HASH_FOR(body))) )
XPUSHs(HeVAL(he));
else
ST(0) = &PL_sv_undef;
#include "mop.h"
-NEEDS_KEY(package);
-
MODULE = Class::MOP::Package PACKAGE = Class::MOP::Package
PROTOTYPES: DISABLE
PUTBACK;
- if ( (he = hv_fetch_ent((HV *)SvRV(self), key_package, 0, hash_package)) ) {
+ if ( (he = hv_fetch_ent((HV *)SvRV(self), KEY_FOR(package), 0, HASH_FOR(package))) ) {
stash = gv_stashsv(HeVAL(he), 0);
}
die("Cannot call name as a class method");
}
- if ( (he = hv_fetch_ent((HV *)SvRV(self), key_package, 0, hash_package)) )
+ if ( (he = hv_fetch_ent((HV *)SvRV(self), KEY_FOR(package), 0, HASH_FOR(package))) )
XPUSHs(HeVAL(he));
else
ST(0) = &PL_sv_undef;