In struct mro_meta, rename mro_linear_c3 to mro_linear_current, and change it
[p5sagit/p5-mst-13.2.git] / mro.c
CommitLineData
e1a479c5 1/* mro.c
2 *
3 * Copyright (c) 2007 Brandon L Black
1129b882 4 * Copyright (c) 2007, 2008 Larry Wall and others
e1a479c5 5 *
6 * You may distribute under the terms of either the GNU General Public
7 * License or the Artistic License, as specified in the README file.
8 *
9 */
10
11/*
4ac71550 12 * 'Which order shall we go in?' said Frodo. 'Eldest first, or quickest first?
13 * You'll be last either way, Master Peregrin.'
14 *
15 * [p.101 of _The Lord of the Rings_, I/iii: "A Conspiracy Unmasked"]
cac98860 16 */
17
18/*
e1a479c5 19=head1 MRO Functions
20
21These functions are related to the method resolution order of perl classes
22
23=cut
24*/
25
26#include "EXTERN.h"
4befac30 27#define PERL_IN_MRO_C
e1a479c5 28#include "perl.h"
29
a3e6e81e 30static const struct mro_alg dfs_alg =
31 {S_mro_get_linear_isa_dfs, "dfs", 3, 0, 0};
3d76853f 32
fa60396f 33SV *
34Perl_mro_get_private_data(pTHX_ struct mro_meta *const smeta,
35 const struct mro_alg *const which)
36{
37 SV **data;
38 PERL_ARGS_ASSERT_MRO_GET_PRIVATE_DATA;
39
40 data = Perl_hv_common(aTHX_ MUTABLE_HV(smeta->mro_linear_dfs), NULL,
41 which->name, which->length, which->kflags,
42 HV_FETCH_JUST_SV, NULL, which->hash);
43 if (!data)
44 return NULL;
45
46 /* If we've been asked to look up the private data for the current MRO, then
47 cache it. */
48 if (smeta->mro_which == which)
3a6fa573 49 smeta->mro_linear_current = *data;
fa60396f 50
51 return *data;
52}
53
54SV *
55Perl_mro_set_private_data(pTHX_ struct mro_meta *const smeta,
56 const struct mro_alg *const which, SV *const data)
57{
58 PERL_ARGS_ASSERT_MRO_SET_PRIVATE_DATA;
59
fa60396f 60 if (!smeta->mro_linear_dfs) {
553e831a 61 if (smeta->mro_which == which) {
62 /* If all we need to store is the current MRO's data, then don't use
63 memory on a hash with 1 element - store it direct, and signal
64 this by leaving the would-be-hash NULL. */
3a6fa573 65 smeta->mro_linear_current = data;
553e831a 66 return data;
67 } else {
68 HV *const hv = newHV();
69 /* Start with 2 buckets. It's unlikely we'll need more. */
70 HvMAX(hv) = 1;
71 smeta->mro_linear_dfs = MUTABLE_AV(hv);
72
3a6fa573 73 if (smeta->mro_linear_current) {
553e831a 74 /* If we were storing something directly, put it in the hash
75 before we lose it. */
76 Perl_mro_set_private_data(aTHX_ smeta, smeta->mro_which,
3a6fa573 77 smeta->mro_linear_current);
553e831a 78 }
79 }
80 }
81
82 /* We get here if we're storing more than one linearisation for this stash,
83 or the linearisation we are storing is not that if its current MRO. */
84
85 if (smeta->mro_which == which) {
86 /* If we've been asked to store the private data for the current MRO,
87 then cache it. */
3a6fa573 88 smeta->mro_linear_current = data;
fa60396f 89 }
90
91 if (!Perl_hv_common(aTHX_ MUTABLE_HV(smeta->mro_linear_dfs), NULL,
92 which->name, which->length, which->kflags,
93 HV_FETCH_ISSTORE, data, which->hash)) {
94 Perl_croak(aTHX_ "panic: hv_store() failed in set_mro_private_data() "
95 "for '%.*s' %d", (int) which->length, which->name,
96 which->kflags);
97 }
98
99 return data;
100}
101
a3e6e81e 102const struct mro_alg *
103Perl_mro_get_from_name(pTHX_ SV *name) {
104 SV **data;
105
106 PERL_ARGS_ASSERT_MRO_GET_FROM_NAME;
107
108 data = Perl_hv_common(aTHX_ PL_registered_mros, name, NULL, 0, 0,
109 HV_FETCH_JUST_SV, NULL, 0);
110 if (!data)
111 return NULL;
112 assert(SvTYPE(*data) == SVt_IV);
113 assert(SvIOK(*data));
114 return INT2PTR(const struct mro_alg *, SvUVX(*data));
115}
116
117void
118Perl_mro_register(pTHX_ const struct mro_alg *mro) {
119 SV *wrapper = newSVuv(PTR2UV(mro));
120
121 PERL_ARGS_ASSERT_MRO_REGISTER;
122
123
124 if (!Perl_hv_common(aTHX_ PL_registered_mros, NULL,
125 mro->name, mro->length, mro->kflags,
126 HV_FETCH_ISSTORE, wrapper, mro->hash)) {
127 SvREFCNT_dec(wrapper);
128 Perl_croak(aTHX_ "panic: hv_store() failed in mro_register() "
129 "for '%.*s' %d", (int) mro->length, mro->name, mro->kflags);
3d76853f 130 }
3d76853f 131}
132
e1a479c5 133struct mro_meta*
134Perl_mro_meta_init(pTHX_ HV* stash)
135{
9fe4aecf 136 struct mro_meta* newmeta;
e1a479c5 137
7918f24d 138 PERL_ARGS_ASSERT_MRO_META_INIT;
e1a479c5 139 assert(HvAUX(stash));
140 assert(!(HvAUX(stash)->xhv_mro_meta));
183086be 141 Newxz(newmeta, 1, struct mro_meta);
9fe4aecf 142 HvAUX(stash)->xhv_mro_meta = newmeta;
dd69841b 143 newmeta->cache_gen = 1;
70cd14a1 144 newmeta->pkg_gen = 1;
a3e6e81e 145 newmeta->mro_which = &dfs_alg;
e1a479c5 146
147 return newmeta;
148}
149
150#if defined(USE_ITHREADS)
151
152/* for sv_dup on new threads */
153struct mro_meta*
154Perl_mro_meta_dup(pTHX_ struct mro_meta* smeta, CLONE_PARAMS* param)
155{
e1a479c5 156 struct mro_meta* newmeta;
157
7918f24d 158 PERL_ARGS_ASSERT_MRO_META_DUP;
e1a479c5 159
33e12d9d 160 Newx(newmeta, 1, struct mro_meta);
161 Copy(smeta, newmeta, 1, struct mro_meta);
162
553e831a 163 if (newmeta->mro_linear_dfs) {
33e12d9d 164 newmeta->mro_linear_dfs
ad64d0ec 165 = MUTABLE_AV(SvREFCNT_inc(sv_dup((const SV *)newmeta->mro_linear_dfs, param)));
553e831a 166 /* This is just acting as a shortcut pointer, and will be automatically
167 updated on the first get. */
3a6fa573 168 newmeta->mro_linear_current = NULL;
169 } else if (newmeta->mro_linear_current) {
553e831a 170 /* Only the current MRO is stored, so this owns the data. */
3a6fa573 171 newmeta->mro_linear_current
172 = SvREFCNT_inc(sv_dup((const SV *)newmeta->mro_linear_current,
173 param));
553e831a 174 }
175
33e12d9d 176 if (newmeta->mro_nextmethod)
177 newmeta->mro_nextmethod
ad64d0ec 178 = MUTABLE_HV(SvREFCNT_inc(sv_dup((const SV *)newmeta->mro_nextmethod, param)));
a49ba3fc 179 if (newmeta->isa)
180 newmeta->isa
ad64d0ec 181 = MUTABLE_HV(SvREFCNT_inc(sv_dup((const SV *)newmeta->isa, param)));
e1a479c5 182
183 return newmeta;
184}
185
186#endif /* USE_ITHREADS */
187
a49ba3fc 188HV *
189Perl_get_isa_hash(pTHX_ HV *const stash)
190{
191 dVAR;
192 struct mro_meta *const meta = HvMROMETA(stash);
193
194 PERL_ARGS_ASSERT_GET_ISA_HASH;
195
6e4aef59 196 if (!meta->isa) {
197 AV *const isa = mro_get_linear_isa(stash);
198 if (!meta->isa) {
199 HV *const isa_hash = newHV();
200 /* Linearisation didn't build it for us, so do it here. */
201 SV *const *svp = AvARRAY(isa);
202 SV *const *const svp_end = svp + AvFILLp(isa) + 1;
203 const HEK *const canon_name = HvNAME_HEK(stash);
204
205 while (svp < svp_end) {
206 (void) hv_store_ent(isa_hash, *svp++, &PL_sv_undef, 0);
207 }
208
209 (void) hv_common(isa_hash, NULL, HEK_KEY(canon_name),
210 HEK_LEN(canon_name), HEK_FLAGS(canon_name),
211 HV_FETCH_ISSTORE, &PL_sv_undef,
212 HEK_HASH(canon_name));
213 (void) hv_store(isa_hash, "UNIVERSAL", 9, &PL_sv_undef, 0);
214
ed09b296 215 SvREADONLY_on(isa_hash);
216
6e4aef59 217 meta->isa = isa_hash;
218 }
219 }
a49ba3fc 220 return meta->isa;
221}
222
e1a479c5 223/*
224=for apidoc mro_get_linear_isa_dfs
225
226Returns the Depth-First Search linearization of @ISA
227the given stash. The return value is a read-only AV*.
228C<level> should be 0 (it is used internally in this
229function's recursion).
230
1c908217 231You are responsible for C<SvREFCNT_inc()> on the
232return value if you plan to store it anywhere
233semi-permanently (otherwise it might be deleted
234out from under you the next time the cache is
235invalidated).
236
e1a479c5 237=cut
238*/
4befac30 239static AV*
94d1e706 240S_mro_get_linear_isa_dfs(pTHX_ HV *stash, U32 level)
e1a479c5 241{
242 AV* retval;
243 GV** gvp;
244 GV* gv;
245 AV* av;
190d0b22 246 const HEK* stashhek;
e1a479c5 247 struct mro_meta* meta;
a49ba3fc 248 SV *our_name;
249 HV *stored;
e1a479c5 250
7918f24d 251 PERL_ARGS_ASSERT_MRO_GET_LINEAR_ISA_DFS;
e1a479c5 252 assert(HvAUX(stash));
253
190d0b22 254 stashhek = HvNAME_HEK(stash);
255 if (!stashhek)
1e05feb3 256 Perl_croak(aTHX_ "Can't linearize anonymous symbol table");
e1a479c5 257
258 if (level > 100)
259 Perl_croak(aTHX_ "Recursive inheritance detected in package '%s'",
190d0b22 260 HEK_KEY(stashhek));
e1a479c5 261
262 meta = HvMROMETA(stash);
1c908217 263
264 /* return cache if valid */
a3e6e81e 265 if((retval = MUTABLE_AV(MRO_GET_PRIVATE_DATA(meta, &dfs_alg)))) {
e1a479c5 266 return retval;
267 }
268
269 /* not in cache, make a new one */
1c908217 270
ad64d0ec 271 retval = MUTABLE_AV(sv_2mortal(MUTABLE_SV(newAV())));
a49ba3fc 272 /* We use this later in this function, but don't need a reference to it
273 beyond the end of this function, so reference count is fine. */
274 our_name = newSVhek(stashhek);
275 av_push(retval, our_name); /* add ourselves at the top */
e1a479c5 276
1c908217 277 /* fetch our @ISA */
e1a479c5 278 gvp = (GV**)hv_fetchs(stash, "ISA", FALSE);
279 av = (gvp && (gv = *gvp) && isGV_with_GP(gv)) ? GvAV(gv) : NULL;
280
a49ba3fc 281 /* "stored" is used to keep track of all of the classnames we have added to
282 the MRO so far, so we can do a quick exists check and avoid adding
283 duplicate classnames to the MRO as we go.
284 It's then retained to be re-used as a fast lookup for ->isa(), by adding
285 our own name and "UNIVERSAL" to it. */
286
ad64d0ec 287 stored = MUTABLE_HV(sv_2mortal(MUTABLE_SV(newHV())));
1c908217 288
a49ba3fc 289 if(av && AvFILLp(av) >= 0) {
1c908217 290
ffd8da72 291 SV **svp = AvARRAY(av);
292 I32 items = AvFILLp(av) + 1;
1c908217 293
294 /* foreach(@ISA) */
e1a479c5 295 while (items--) {
296 SV* const sv = *svp++;
297 HV* const basestash = gv_stashsv(sv, 0);
ffd8da72 298 SV *const *subrv_p;
299 I32 subrv_items;
e1a479c5 300
301 if (!basestash) {
1c908217 302 /* if no stash exists for this @ISA member,
303 simply add it to the MRO and move on */
ffd8da72 304 subrv_p = &sv;
305 subrv_items = 1;
e1a479c5 306 }
307 else {
1c908217 308 /* otherwise, recurse into ourselves for the MRO
b1d0c68a 309 of this @ISA member, and append their MRO to ours.
310 The recursive call could throw an exception, which
311 has memory management implications here, hence the use of
312 the mortal. */
ffd8da72 313 const AV *const subrv
314 = mro_get_linear_isa_dfs(basestash, level + 1);
315
316 subrv_p = AvARRAY(subrv);
317 subrv_items = AvFILLp(subrv) + 1;
318 }
319 while(subrv_items--) {
320 SV *const subsv = *subrv_p++;
8e45cc2b 321 /* LVALUE fetch will create a new undefined SV if necessary
322 */
323 HE *const he = hv_fetch_ent(stored, subsv, 1, 0);
324 assert(he);
325 if(HeVAL(he) != &PL_sv_undef) {
326 /* It was newly created. Steal it for our new SV, and
327 replace it in the hash with the "real" thing. */
328 SV *const val = HeVAL(he);
f46ee248 329 HEK *const key = HeKEY_hek(he);
8e45cc2b 330
331 HeVAL(he) = &PL_sv_undef;
f46ee248 332 /* Save copying by making a shared hash key scalar. We
333 inline this here rather than calling Perl_newSVpvn_share
334 because we already have the scalar, and we already have
335 the hash key. */
336 assert(SvTYPE(val) == SVt_NULL);
337 sv_upgrade(val, SVt_PV);
338 SvPV_set(val, HEK_KEY(share_hek_hek(key)));
339 SvCUR_set(val, HEK_LEN(key));
340 SvREADONLY_on(val);
341 SvFAKE_on(val);
342 SvPOK_on(val);
343 if (HEK_UTF8(key))
344 SvUTF8_on(val);
345
8e45cc2b 346 av_push(retval, val);
ffd8da72 347 }
e1a479c5 348 }
349 }
350 }
351
ed09b296 352 (void) hv_store_ent(stored, our_name, &PL_sv_undef, 0);
353 (void) hv_store(stored, "UNIVERSAL", 9, &PL_sv_undef, 0);
354
355 SvREFCNT_inc_simple_void_NN(stored);
356 SvTEMP_off(stored);
357 SvREADONLY_on(stored);
358
359 meta->isa = stored;
360
0fd7ece8 361 /* now that we're past the exception dangers, grab our own reference to
362 the AV we're about to use for the result. The reference owned by the
363 mortals' stack will be released soon, so everything will balance. */
364 SvREFCNT_inc_simple_void_NN(retval);
365 SvTEMP_off(retval);
fdef73f9 366
1c908217 367 /* we don't want anyone modifying the cache entry but us,
368 and we do so by replacing it completely */
e1a479c5 369 SvREADONLY_on(retval);
1c908217 370
a3e6e81e 371 return MUTABLE_AV(Perl_mro_set_private_data(aTHX_ meta, &dfs_alg,
fa60396f 372 MUTABLE_SV(retval)));
e1a479c5 373}
374
375/*
e1a479c5 376=for apidoc mro_get_linear_isa
377
378Returns either C<mro_get_linear_isa_c3> or
379C<mro_get_linear_isa_dfs> for the given stash,
380dependant upon which MRO is in effect
381for that stash. The return value is a
382read-only AV*.
383
1c908217 384You are responsible for C<SvREFCNT_inc()> on the
385return value if you plan to store it anywhere
386semi-permanently (otherwise it might be deleted
387out from under you the next time the cache is
388invalidated).
389
e1a479c5 390=cut
391*/
392AV*
393Perl_mro_get_linear_isa(pTHX_ HV *stash)
394{
395 struct mro_meta* meta;
2c7f4b87 396
7918f24d 397 PERL_ARGS_ASSERT_MRO_GET_LINEAR_ISA;
2c7f4b87 398 if(!SvOOK(stash))
399 Perl_croak(aTHX_ "Can't linearize anonymous symbol table");
e1a479c5 400
401 meta = HvMROMETA(stash);
3d76853f 402 if (!meta->mro_which)
14f97ce6 403 Perl_croak(aTHX_ "panic: invalid MRO!");
3d76853f 404 return meta->mro_which->resolve(aTHX_ stash, 0);
e1a479c5 405}
406
407/*
408=for apidoc mro_isa_changed_in
409
1c908217 410Takes the necessary steps (cache invalidations, mostly)
e1a479c5 411when the @ISA of the given package has changed. Invoked
412by the C<setisa> magic, should not need to invoke directly.
413
414=cut
415*/
416void
417Perl_mro_isa_changed_in(pTHX_ HV* stash)
418{
419 dVAR;
420 HV* isarev;
421 AV* linear_mro;
422 HE* iter;
423 SV** svp;
424 I32 items;
1e05feb3 425 bool is_universal;
2c7f4b87 426 struct mro_meta * meta;
e1a479c5 427
0fa56319 428 const char * const stashname = HvNAME_get(stash);
429 const STRLEN stashname_len = HvNAMELEN_get(stash);
e1a479c5 430
7918f24d 431 PERL_ARGS_ASSERT_MRO_ISA_CHANGED_IN;
432
2c7f4b87 433 if(!stashname)
434 Perl_croak(aTHX_ "Can't call mro_isa_changed_in() on anonymous symbol table");
435
e1a479c5 436 /* wipe out the cached linearizations for this stash */
2c7f4b87 437 meta = HvMROMETA(stash);
553e831a 438 if (meta->mro_linear_dfs) {
439 SvREFCNT_dec(MUTABLE_SV(meta->mro_linear_dfs));
440 meta->mro_linear_dfs = NULL;
441 /* This is just acting as a shortcut pointer. */
3a6fa573 442 meta->mro_linear_current = NULL;
443 } else if (meta->mro_linear_current) {
553e831a 444 /* Only the current MRO is stored, so this owns the data. */
3a6fa573 445 SvREFCNT_dec(meta->mro_linear_current);
446 meta->mro_linear_current = NULL;
553e831a 447 }
5782d502 448 if (meta->isa) {
449 SvREFCNT_dec(meta->isa);
450 meta->isa = NULL;
451 }
e1a479c5 452
70cd14a1 453 /* Inc the package generation, since our @ISA changed */
454 meta->pkg_gen++;
455
e1a479c5 456 /* Wipe the global method cache if this package
457 is UNIVERSAL or one of its parents */
dd69841b 458
459 svp = hv_fetch(PL_isarev, stashname, stashname_len, 0);
85fbaab2 460 isarev = svp ? MUTABLE_HV(*svp) : NULL;
dd69841b 461
462 if((stashname_len == 9 && strEQ(stashname, "UNIVERSAL"))
463 || (isarev && hv_exists(isarev, "UNIVERSAL", 9))) {
e1a479c5 464 PL_sub_generation++;
dd69841b 465 is_universal = TRUE;
466 }
1e05feb3 467 else { /* Wipe the local method cache otherwise */
dd69841b 468 meta->cache_gen++;
1e05feb3 469 is_universal = FALSE;
470 }
e1a479c5 471
472 /* wipe next::method cache too */
473 if(meta->mro_nextmethod) hv_clear(meta->mro_nextmethod);
1e05feb3 474
e1a479c5 475 /* Iterate the isarev (classes that are our children),
476 wiping out their linearization and method caches */
dd69841b 477 if(isarev) {
e1a479c5 478 hv_iterinit(isarev);
479 while((iter = hv_iternext(isarev))) {
ec49eb61 480 I32 len;
481 const char* const revkey = hv_iterkey(iter, &len);
482 HV* revstash = gv_stashpvn(revkey, len, 0);
bc2cbbac 483 struct mro_meta* revmeta;
484
485 if(!revstash) continue;
486 revmeta = HvMROMETA(revstash);
553e831a 487 if (revmeta->mro_linear_dfs) {
488 SvREFCNT_dec(MUTABLE_SV(revmeta->mro_linear_dfs));
489 revmeta->mro_linear_dfs = NULL;
490 /* This is just acting as a shortcut pointer. */
3a6fa573 491 revmeta->mro_linear_current = NULL;
492 } else if (revmeta->mro_linear_current) {
553e831a 493 /* Only the current MRO is stored, so this owns the data. */
3a6fa573 494 SvREFCNT_dec(revmeta->mro_linear_current);
495 revmeta->mro_linear_current = NULL;
553e831a 496 }
dd69841b 497 if(!is_universal)
498 revmeta->cache_gen++;
e1a479c5 499 if(revmeta->mro_nextmethod)
500 hv_clear(revmeta->mro_nextmethod);
501 }
502 }
503
1c908217 504 /* Now iterate our MRO (parents), and do a few things:
505 1) instantiate with the "fake" flag if they don't exist
506 2) flag them as universal if we are universal
507 3) Add everything from our isarev to their isarev
508 */
509
510 /* We're starting at the 2nd element, skipping ourselves here */
e1a479c5 511 linear_mro = mro_get_linear_isa(stash);
512 svp = AvARRAY(linear_mro) + 1;
513 items = AvFILLp(linear_mro);
1c908217 514
e1a479c5 515 while (items--) {
516 SV* const sv = *svp++;
e1a479c5 517 HV* mroisarev;
518
117b69ca 519 HE *he = hv_fetch_ent(PL_isarev, sv, TRUE, 0);
520
521 /* That fetch should not fail. But if it had to create a new SV for
4ea50411 522 us, then will need to upgrade it to an HV (which sv_upgrade() can
523 now do for us. */
117b69ca 524
85fbaab2 525 mroisarev = MUTABLE_HV(HeVAL(he));
e1a479c5 526
ad64d0ec 527 SvUPGRADE(MUTABLE_SV(mroisarev), SVt_PVHV);
117b69ca 528
25270bc0 529 /* This hash only ever contains PL_sv_yes. Storing it over itself is
530 almost as cheap as calling hv_exists, so on aggregate we expect to
531 save time by not making two calls to the common HV code for the
532 case where it doesn't exist. */
533
04fe65b0 534 (void)hv_store(mroisarev, stashname, stashname_len, &PL_sv_yes, 0);
e1a479c5 535
536 if(isarev) {
537 hv_iterinit(isarev);
538 while((iter = hv_iternext(isarev))) {
dd69841b 539 I32 revkeylen;
1e05feb3 540 char* const revkey = hv_iterkey(iter, &revkeylen);
04fe65b0 541 (void)hv_store(mroisarev, revkey, revkeylen, &PL_sv_yes, 0);
e1a479c5 542 }
543 }
544 }
545}
546
547/*
548=for apidoc mro_method_changed_in
549
47c9dd14 550Invalidates method caching on any child classes
551of the given stash, so that they might notice
552the changes in this one.
e1a479c5 553
554Ideally, all instances of C<PL_sub_generation++> in
dd69841b 555perl source outside of C<mro.c> should be
556replaced by calls to this.
557
558Perl automatically handles most of the common
559ways a method might be redefined. However, there
560are a few ways you could change a method in a stash
561without the cache code noticing, in which case you
562need to call this method afterwards:
e1a479c5 563
dd69841b 5641) Directly manipulating the stash HV entries from
565XS code.
e1a479c5 566
dd69841b 5672) Assigning a reference to a readonly scalar
568constant into a stash entry in order to create
569a constant subroutine (like constant.pm
570does).
571
572This same method is available from pure perl
573via, C<mro::method_changed_in(classname)>.
e1a479c5 574
575=cut
576*/
577void
578Perl_mro_method_changed_in(pTHX_ HV *stash)
579{
1e05feb3 580 const char * const stashname = HvNAME_get(stash);
581 const STRLEN stashname_len = HvNAMELEN_get(stash);
dd69841b 582
1e05feb3 583 SV ** const svp = hv_fetch(PL_isarev, stashname, stashname_len, 0);
85fbaab2 584 HV * const isarev = svp ? MUTABLE_HV(*svp) : NULL;
e1a479c5 585
7918f24d 586 PERL_ARGS_ASSERT_MRO_METHOD_CHANGED_IN;
587
2c7f4b87 588 if(!stashname)
589 Perl_croak(aTHX_ "Can't call mro_method_changed_in() on anonymous symbol table");
590
70cd14a1 591 /* Inc the package generation, since a local method changed */
592 HvMROMETA(stash)->pkg_gen++;
593
e1a479c5 594 /* If stash is UNIVERSAL, or one of UNIVERSAL's parents,
595 invalidate all method caches globally */
dd69841b 596 if((stashname_len == 9 && strEQ(stashname, "UNIVERSAL"))
597 || (isarev && hv_exists(isarev, "UNIVERSAL", 9))) {
e1a479c5 598 PL_sub_generation++;
599 return;
600 }
601
602 /* else, invalidate the method caches of all child classes,
603 but not itself */
dd69841b 604 if(isarev) {
1e05feb3 605 HE* iter;
606
e1a479c5 607 hv_iterinit(isarev);
608 while((iter = hv_iternext(isarev))) {
ec49eb61 609 I32 len;
610 const char* const revkey = hv_iterkey(iter, &len);
611 HV* const revstash = gv_stashpvn(revkey, len, 0);
bc2cbbac 612 struct mro_meta* mrometa;
613
614 if(!revstash) continue;
615 mrometa = HvMROMETA(revstash);
dd69841b 616 mrometa->cache_gen++;
e1a479c5 617 if(mrometa->mro_nextmethod)
618 hv_clear(mrometa->mro_nextmethod);
619 }
620 }
621}
622
31b9005d 623void
624Perl_mro_set_mro(pTHX_ struct mro_meta *const meta, SV *const name)
625{
626 const struct mro_alg *const which = Perl_mro_get_from_name(aTHX_ name);
627
628 PERL_ARGS_ASSERT_MRO_SET_MRO;
629
630 if (!which)
631 Perl_croak(aTHX_ "Invalid mro name: '%"SVf"'", name);
632
633 if(meta->mro_which != which) {
3a6fa573 634 if (meta->mro_linear_current && !meta->mro_linear_dfs) {
31b9005d 635 /* If we were storing something directly, put it in the hash before
636 we lose it. */
637 Perl_mro_set_private_data(aTHX_ meta, meta->mro_which,
3a6fa573 638 MUTABLE_SV(meta->mro_linear_current));
31b9005d 639 }
640 meta->mro_which = which;
641 /* Scrub our cached pointer to the private data. */
3a6fa573 642 meta->mro_linear_current = NULL;
31b9005d 643 /* Only affects local method cache, not
644 even child classes */
645 meta->cache_gen++;
646 if(meta->mro_nextmethod)
647 hv_clear(meta->mro_nextmethod);
648 }
649}
650
e1a479c5 651#include "XSUB.h"
652
653XS(XS_mro_get_linear_isa);
654XS(XS_mro_set_mro);
655XS(XS_mro_get_mro);
656XS(XS_mro_get_isarev);
657XS(XS_mro_is_universal);
c5860d66 658XS(XS_mro_invalidate_method_caches);
e1a479c5 659XS(XS_mro_method_changed_in);
70cd14a1 660XS(XS_mro_get_pkg_gen);
e1a479c5 661
662void
663Perl_boot_core_mro(pTHX)
664{
665 dVAR;
666 static const char file[] = __FILE__;
667
a3e6e81e 668 Perl_mro_register(aTHX_ &dfs_alg);
a3e6e81e 669
e1a479c5 670 newXSproto("mro::get_linear_isa", XS_mro_get_linear_isa, file, "$;$");
671 newXSproto("mro::set_mro", XS_mro_set_mro, file, "$$");
672 newXSproto("mro::get_mro", XS_mro_get_mro, file, "$");
673 newXSproto("mro::get_isarev", XS_mro_get_isarev, file, "$");
674 newXSproto("mro::is_universal", XS_mro_is_universal, file, "$");
c5860d66 675 newXSproto("mro::invalidate_all_method_caches", XS_mro_invalidate_method_caches, file, "");
e1a479c5 676 newXSproto("mro::method_changed_in", XS_mro_method_changed_in, file, "$");
70cd14a1 677 newXSproto("mro::get_pkg_gen", XS_mro_get_pkg_gen, file, "$");
e1a479c5 678}
679
680XS(XS_mro_get_linear_isa) {
681 dVAR;
682 dXSARGS;
683 AV* RETVAL;
684 HV* class_stash;
685 SV* classname;
686
e1a479c5 687 if(items < 1 || items > 2)
afa74d42 688 croak_xs_usage(cv, "classname [, type ]");
e1a479c5 689
690 classname = ST(0);
691 class_stash = gv_stashsv(classname, 0);
e1a479c5 692
70cd14a1 693 if(!class_stash) {
694 /* No stash exists yet, give them just the classname */
695 AV* isalin = newAV();
696 av_push(isalin, newSVsv(classname));
ad64d0ec 697 ST(0) = sv_2mortal(newRV_noinc(MUTABLE_SV(isalin)));
70cd14a1 698 XSRETURN(1);
699 }
700 else if(items > 1) {
a3e6e81e 701 const struct mro_alg *const algo = Perl_mro_get_from_name(aTHX_ ST(1));
3d76853f 702 if (!algo)
a3e6e81e 703 Perl_croak(aTHX_ "Invalid mro name: '%"SVf"'", ST(1));
84dccb35 704 RETVAL = algo->resolve(aTHX_ class_stash, 0);
e1a479c5 705 }
706 else {
707 RETVAL = mro_get_linear_isa(class_stash);
708 }
709
ad64d0ec 710 ST(0) = newRV_inc(MUTABLE_SV(RETVAL));
e1a479c5 711 sv_2mortal(ST(0));
712 XSRETURN(1);
713}
714
715XS(XS_mro_set_mro)
716{
717 dVAR;
718 dXSARGS;
719 SV* classname;
e1a479c5 720 HV* class_stash;
721 struct mro_meta* meta;
722
e1a479c5 723 if (items != 2)
afa74d42 724 croak_xs_usage(cv, "classname, type");
e1a479c5 725
726 classname = ST(0);
e1a479c5 727 class_stash = gv_stashsv(classname, GV_ADD);
728 if(!class_stash) Perl_croak(aTHX_ "Cannot create class: '%"SVf"'!", SVfARG(classname));
729 meta = HvMROMETA(class_stash);
730
31b9005d 731 Perl_mro_set_mro(aTHX_ meta, ST(1));
e1a479c5 732
733 XSRETURN_EMPTY;
734}
735
736
737XS(XS_mro_get_mro)
738{
739 dVAR;
740 dXSARGS;
741 SV* classname;
742 HV* class_stash;
e1a479c5 743
e1a479c5 744 if (items != 1)
afa74d42 745 croak_xs_usage(cv, "classname");
e1a479c5 746
747 classname = ST(0);
748 class_stash = gv_stashsv(classname, 0);
e1a479c5 749
3d76853f 750 ST(0) = sv_2mortal(newSVpv(class_stash
751 ? HvMROMETA(class_stash)->mro_which->name
752 : "dfs", 0));
e1a479c5 753 XSRETURN(1);
754}
755
756XS(XS_mro_get_isarev)
757{
758 dVAR;
759 dXSARGS;
760 SV* classname;
73968c7a 761 HE* he;
e1a479c5 762 HV* isarev;
70cd14a1 763 AV* ret_array;
e1a479c5 764
e1a479c5 765 if (items != 1)
afa74d42 766 croak_xs_usage(cv, "classname");
e1a479c5 767
768 classname = ST(0);
769
e1a479c5 770 SP -= items;
dd69841b 771
70cd14a1 772
73968c7a 773 he = hv_fetch_ent(PL_isarev, classname, 0, 0);
85fbaab2 774 isarev = he ? MUTABLE_HV(HeVAL(he)) : NULL;
70cd14a1 775
776 ret_array = newAV();
dd69841b 777 if(isarev) {
e1a479c5 778 HE* iter;
779 hv_iterinit(isarev);
780 while((iter = hv_iternext(isarev)))
70cd14a1 781 av_push(ret_array, newSVsv(hv_iterkeysv(iter)));
e1a479c5 782 }
ad64d0ec 783 mXPUSHs(newRV_noinc(MUTABLE_SV(ret_array)));
e1a479c5 784
785 PUTBACK;
786 return;
787}
788
789XS(XS_mro_is_universal)
790{
791 dVAR;
792 dXSARGS;
793 SV* classname;
dd69841b 794 HV* isarev;
70cd14a1 795 char* classname_pv;
796 STRLEN classname_len;
73968c7a 797 HE* he;
e1a479c5 798
e1a479c5 799 if (items != 1)
afa74d42 800 croak_xs_usage(cv, "classname");
e1a479c5 801
802 classname = ST(0);
e1a479c5 803
cfff9797 804 classname_pv = SvPV(classname,classname_len);
dd69841b 805
73968c7a 806 he = hv_fetch_ent(PL_isarev, classname, 0, 0);
85fbaab2 807 isarev = he ? MUTABLE_HV(HeVAL(he)) : NULL;
dd69841b 808
70cd14a1 809 if((classname_len == 9 && strEQ(classname_pv, "UNIVERSAL"))
dd69841b 810 || (isarev && hv_exists(isarev, "UNIVERSAL", 9)))
9edc5bb8 811 XSRETURN_YES;
812 else
813 XSRETURN_NO;
e1a479c5 814}
815
c5860d66 816XS(XS_mro_invalidate_method_caches)
e1a479c5 817{
818 dVAR;
819 dXSARGS;
820
e1a479c5 821 if (items != 0)
afa74d42 822 croak_xs_usage(cv, "");
e1a479c5 823
824 PL_sub_generation++;
825
826 XSRETURN_EMPTY;
827}
828
e1a479c5 829XS(XS_mro_method_changed_in)
830{
831 dVAR;
832 dXSARGS;
833 SV* classname;
834 HV* class_stash;
835
e1a479c5 836 if(items != 1)
afa74d42 837 croak_xs_usage(cv, "classname");
e1a479c5 838
839 classname = ST(0);
840
841 class_stash = gv_stashsv(classname, 0);
842 if(!class_stash) Perl_croak(aTHX_ "No such class: '%"SVf"'!", SVfARG(classname));
843
844 mro_method_changed_in(class_stash);
845
846 XSRETURN_EMPTY;
847}
848
70cd14a1 849XS(XS_mro_get_pkg_gen)
850{
851 dVAR;
852 dXSARGS;
853 SV* classname;
854 HV* class_stash;
855
70cd14a1 856 if(items != 1)
afa74d42 857 croak_xs_usage(cv, "classname");
70cd14a1 858
859 classname = ST(0);
860
861 class_stash = gv_stashsv(classname, 0);
862
863 SP -= items;
864
6e449a3a 865 mXPUSHi(class_stash ? HvMROMETA(class_stash)->pkg_gen : 0);
70cd14a1 866
867 PUTBACK;
868 return;
869}
870
e1a479c5 871/*
872 * Local variables:
873 * c-indentation-style: bsd
874 * c-basic-offset: 4
875 * indent-tabs-mode: t
876 * End:
877 *
878 * ex: set ts=8 sts=4 sw=4 noet:
879 */