File Coverage

xs/HasMethods.xs
Criterion Covered Total %
statement 36 37 97.3
branch 23 30 76.6
condition n/a
subroutine n/a
pod n/a
total 59 67 88.0


line stmt bran cond sub pod time code
1             #include "mop.h"
2             #include "ppport.h"
3              
4             SV *mop_method_metaclass;
5             SV *mop_associated_metaclass;
6             SV *mop_wrap;
7              
8             static void
9 45058           mop_update_method_map(pTHX_ HV *const stash, HV *const map)
10             {
11             char *method_name;
12             I32 method_name_len;
13             SV *method;
14             HV *symbols;
15              
16 45058           symbols = mop_get_all_package_symbols(stash, TYPE_FILTER_CODE);
17 45058           sv_2mortal((SV*)symbols);
18              
19 45058           (void)hv_iterinit(map);
20 89031 100         while ((method = hv_iternextsv(map, &method_name, &method_name_len))) {
21             SV *body;
22             SV *stash_slot;
23              
24 43973 50         if (!SvROK(method)) {
25 0           continue;
26             }
27              
28 43973 100         if (sv_derived_from(method, "Class::MOP::Method")) {
29             /* $method_object->body() */
30 43942           body = mop_call0(aTHX_ method, KEY_FOR(body));
31             }
32             else {
33 31           body = method;
34             }
35              
36 43973           stash_slot = *hv_fetch(symbols, method_name, method_name_len, TRUE);
37 43973 100         if (SvROK(stash_slot) && ((CV*)SvRV(body)) == ((CV*)SvRV(stash_slot))) {
    100          
38 43968           continue;
39             }
40              
41             /* delete $map->{$method_name} */
42 5           (void)hv_delete(map, method_name, method_name_len, G_DISCARD);
43             }
44 45058           }
45              
46             MODULE = Class::MOP::Mixin::HasMethods PACKAGE = Class::MOP::Mixin::HasMethods
47              
48             PROTOTYPES: DISABLE
49              
50             void
51             _method_map(self)
52             SV *self
53             PREINIT:
54 454468           HV *const obj = (HV *)SvRV(self);
55 454468           SV *const class_name = HeVAL( hv_fetch_ent(obj, KEY_FOR(package), 0, HASH_FOR(package)) );
56 454468           HV *const stash = gv_stashsv(class_name, 0);
57             UV current;
58             SV *cache_flag;
59             SV *map_ref;
60             PPCODE:
61 454468 100         if (!stash) {
62 13 50         mXPUSHs(newRV_noinc((SV *)newHV()));
63 13           return;
64             }
65              
66 454455           current = mop_check_package_cache_flag(aTHX_ stash);
67 454455           cache_flag = HeVAL( hv_fetch_ent(obj, KEY_FOR(package_cache_flag), TRUE, HASH_FOR(package_cache_flag)));
68 454455           map_ref = HeVAL( hv_fetch_ent(obj, KEY_FOR(methods), TRUE, HASH_FOR(methods)));
69              
70             /* $self->{methods} does not yet exist (or got deleted) */
71 454455 100         if ( !SvROK(map_ref) || SvTYPE(SvRV(map_ref)) != SVt_PVHV ) {
    50          
72 4069           SV *new_map_ref = newRV_noinc((SV *)newHV());
73 4069           sv_2mortal(new_map_ref);
74 4069           sv_setsv(map_ref, new_map_ref);
75             }
76              
77 454455 100         if ( !SvOK(cache_flag) || SvUV(cache_flag) != current ) {
    50          
    50          
    50          
    100          
78 45058           mop_update_method_map(aTHX_ stash, (HV *)SvRV(map_ref));
79 45058           sv_setuv(cache_flag, mop_check_package_cache_flag(aTHX_ stash)); /* update_cache_flag() */
80             }
81              
82 454455 50         XPUSHs(map_ref);
83              
84             BOOT:
85 463           mop_method_metaclass = newSVpvs("method_metaclass");
86 463           mop_associated_metaclass = newSVpvs("associated_metaclass");
87 463           mop_wrap = newSVpvs("wrap");
88 463           INSTALL_SIMPLE_READER(Mixin::HasMethods, method_metaclass);
89 463           INSTALL_SIMPLE_READER(Mixin::HasMethods, wrapped_method_metaclass);