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