S_mro_get_linear_isa_c3() doesn't need to call hv_fetch() then
[p5sagit/p5-mst-13.2.git] / mro.c
CommitLineData
e1a479c5 1/* mro.c
2 *
3 * Copyright (c) 2007 Brandon L Black
4 *
5 * You may distribute under the terms of either the GNU General Public
6 * License or the Artistic License, as specified in the README file.
7 *
8 */
9
10/*
cac98860 11 * "Which order shall we go in?" said Frodo. "Eldest first, or quickest first?
12 * You'll be last either way, Master Peregrin."
13 */
14
15/*
e1a479c5 16=head1 MRO Functions
17
18These functions are related to the method resolution order of perl classes
19
20=cut
21*/
22
23#include "EXTERN.h"
4befac30 24#define PERL_IN_MRO_C
e1a479c5 25#include "perl.h"
26
3d76853f 27struct mro_alg {
28 const char *name;
29 AV *(*resolve)(pTHX_ HV* stash, I32 level);
30};
31
32/* First one is the default */
33static struct mro_alg mros[] = {
34 {"dfs", S_mro_get_linear_isa_dfs},
35 {"c3", S_mro_get_linear_isa_c3}
36};
37
38#define NUMBER_OF_MROS (sizeof(mros)/sizeof(struct mro_alg))
39
40static const struct mro_alg *
41S_get_mro_from_name(pTHX_ const char *const name) {
42 const struct mro_alg *algo = mros;
43 const struct mro_alg *const end = mros + NUMBER_OF_MROS;
44 while (algo < end) {
45 if(strEQ(name, algo->name))
46 return algo;
47 ++algo;
48 }
49 return NULL;
50}
51
e1a479c5 52struct mro_meta*
53Perl_mro_meta_init(pTHX_ HV* stash)
54{
9fe4aecf 55 struct mro_meta* newmeta;
e1a479c5 56
57 assert(stash);
58 assert(HvAUX(stash));
59 assert(!(HvAUX(stash)->xhv_mro_meta));
183086be 60 Newxz(newmeta, 1, struct mro_meta);
9fe4aecf 61 HvAUX(stash)->xhv_mro_meta = newmeta;
dd69841b 62 newmeta->cache_gen = 1;
70cd14a1 63 newmeta->pkg_gen = 1;
edf2cad7 64 newmeta->mro_which = mros;
e1a479c5 65
66 return newmeta;
67}
68
69#if defined(USE_ITHREADS)
70
71/* for sv_dup on new threads */
72struct mro_meta*
73Perl_mro_meta_dup(pTHX_ struct mro_meta* smeta, CLONE_PARAMS* param)
74{
e1a479c5 75 struct mro_meta* newmeta;
76
77 assert(smeta);
78
33e12d9d 79 Newx(newmeta, 1, struct mro_meta);
80 Copy(smeta, newmeta, 1, struct mro_meta);
81
82 if (newmeta->mro_linear_dfs)
83 newmeta->mro_linear_dfs
84 = (AV*) SvREFCNT_inc(sv_dup((SV*)newmeta->mro_linear_dfs, param));
85 if (newmeta->mro_linear_c3)
86 newmeta->mro_linear_c3
87 = (AV*) SvREFCNT_inc(sv_dup((SV*)newmeta->mro_linear_c3, param));
33e12d9d 88 if (newmeta->mro_nextmethod)
89 newmeta->mro_nextmethod
90 = (HV*) SvREFCNT_inc(sv_dup((SV*)newmeta->mro_nextmethod, param));
e1a479c5 91
92 return newmeta;
93}
94
95#endif /* USE_ITHREADS */
96
97/*
98=for apidoc mro_get_linear_isa_dfs
99
100Returns the Depth-First Search linearization of @ISA
101the given stash. The return value is a read-only AV*.
102C<level> should be 0 (it is used internally in this
103function's recursion).
104
1c908217 105You are responsible for C<SvREFCNT_inc()> on the
106return value if you plan to store it anywhere
107semi-permanently (otherwise it might be deleted
108out from under you the next time the cache is
109invalidated).
110
e1a479c5 111=cut
112*/
4befac30 113static AV*
114S_mro_get_linear_isa_dfs(pTHX_ HV *stash, I32 level)
e1a479c5 115{
116 AV* retval;
117 GV** gvp;
118 GV* gv;
119 AV* av;
190d0b22 120 const HEK* stashhek;
e1a479c5 121 struct mro_meta* meta;
122
123 assert(stash);
124 assert(HvAUX(stash));
125
190d0b22 126 stashhek = HvNAME_HEK(stash);
127 if (!stashhek)
1e05feb3 128 Perl_croak(aTHX_ "Can't linearize anonymous symbol table");
e1a479c5 129
130 if (level > 100)
131 Perl_croak(aTHX_ "Recursive inheritance detected in package '%s'",
190d0b22 132 HEK_KEY(stashhek));
e1a479c5 133
134 meta = HvMROMETA(stash);
1c908217 135
136 /* return cache if valid */
e1a479c5 137 if((retval = meta->mro_linear_dfs)) {
e1a479c5 138 return retval;
139 }
140
141 /* not in cache, make a new one */
1c908217 142
0fd7ece8 143 retval = (AV*)sv_2mortal((SV *)newAV());
190d0b22 144 av_push(retval, newSVhek(stashhek)); /* add ourselves at the top */
e1a479c5 145
1c908217 146 /* fetch our @ISA */
e1a479c5 147 gvp = (GV**)hv_fetchs(stash, "ISA", FALSE);
148 av = (gvp && (gv = *gvp) && isGV_with_GP(gv)) ? GvAV(gv) : NULL;
149
640da897 150 if(av && AvFILLp(av) >= 0) {
1c908217 151
152 /* "stored" is used to keep track of all of the classnames
153 we have added to the MRO so far, so we can do a quick
154 exists check and avoid adding duplicate classnames to
155 the MRO as we go. */
156
1e05feb3 157 HV* const stored = (HV*)sv_2mortal((SV*)newHV());
ffd8da72 158 SV **svp = AvARRAY(av);
159 I32 items = AvFILLp(av) + 1;
1c908217 160
161 /* foreach(@ISA) */
e1a479c5 162 while (items--) {
163 SV* const sv = *svp++;
164 HV* const basestash = gv_stashsv(sv, 0);
ffd8da72 165 SV *const *subrv_p;
166 I32 subrv_items;
e1a479c5 167
168 if (!basestash) {
1c908217 169 /* if no stash exists for this @ISA member,
170 simply add it to the MRO and move on */
ffd8da72 171 subrv_p = &sv;
172 subrv_items = 1;
e1a479c5 173 }
174 else {
1c908217 175 /* otherwise, recurse into ourselves for the MRO
b1d0c68a 176 of this @ISA member, and append their MRO to ours.
177 The recursive call could throw an exception, which
178 has memory management implications here, hence the use of
179 the mortal. */
ffd8da72 180 const AV *const subrv
181 = mro_get_linear_isa_dfs(basestash, level + 1);
182
183 subrv_p = AvARRAY(subrv);
184 subrv_items = AvFILLp(subrv) + 1;
185 }
186 while(subrv_items--) {
187 SV *const subsv = *subrv_p++;
188 if(!hv_exists_ent(stored, subsv, 0)) {
04fe65b0 189 (void)hv_store_ent(stored, subsv, &PL_sv_undef, 0);
0fd7ece8 190 av_push(retval, newSVsv(subsv));
ffd8da72 191 }
e1a479c5 192 }
193 }
194 }
195
0fd7ece8 196 /* now that we're past the exception dangers, grab our own reference to
197 the AV we're about to use for the result. The reference owned by the
198 mortals' stack will be released soon, so everything will balance. */
199 SvREFCNT_inc_simple_void_NN(retval);
200 SvTEMP_off(retval);
fdef73f9 201
1c908217 202 /* we don't want anyone modifying the cache entry but us,
203 and we do so by replacing it completely */
e1a479c5 204 SvREADONLY_on(retval);
1c908217 205
e1a479c5 206 meta->mro_linear_dfs = retval;
207 return retval;
208}
209
210/*
211=for apidoc mro_get_linear_isa_c3
212
213Returns the C3 linearization of @ISA
214the given stash. The return value is a read-only AV*.
215C<level> should be 0 (it is used internally in this
216function's recursion).
217
1c908217 218You are responsible for C<SvREFCNT_inc()> on the
219return value if you plan to store it anywhere
220semi-permanently (otherwise it might be deleted
221out from under you the next time the cache is
222invalidated).
223
e1a479c5 224=cut
225*/
226
4befac30 227static AV*
228S_mro_get_linear_isa_c3(pTHX_ HV* stash, I32 level)
e1a479c5 229{
230 AV* retval;
231 GV** gvp;
232 GV* gv;
233 AV* isa;
190d0b22 234 const HEK* stashhek;
e1a479c5 235 struct mro_meta* meta;
236
237 assert(stash);
238 assert(HvAUX(stash));
239
190d0b22 240 stashhek = HvNAME_HEK(stash);
241 if (!stashhek)
1e05feb3 242 Perl_croak(aTHX_ "Can't linearize anonymous symbol table");
e1a479c5 243
244 if (level > 100)
245 Perl_croak(aTHX_ "Recursive inheritance detected in package '%s'",
190d0b22 246 HEK_KEY(stashhek));
e1a479c5 247
248 meta = HvMROMETA(stash);
1c908217 249
250 /* return cache if valid */
e1a479c5 251 if((retval = meta->mro_linear_c3)) {
e1a479c5 252 return retval;
253 }
254
255 /* not in cache, make a new one */
256
e1a479c5 257 gvp = (GV**)hv_fetchs(stash, "ISA", FALSE);
258 isa = (gvp && (gv = *gvp) && isGV_with_GP(gv)) ? GvAV(gv) : NULL;
259
1c908217 260 /* For a better idea how the rest of this works, see the much clearer
261 pure perl version in Algorithm::C3 0.01:
262 http://search.cpan.org/src/STEVAN/Algorithm-C3-0.01/lib/Algorithm/C3.pm
263 (later versions go about it differently than this code for speed reasons)
264 */
8638e433 265
e1a479c5 266 if(isa && AvFILLp(isa) >= 0) {
267 SV** seqs_ptr;
268 I32 seqs_items;
1e05feb3 269 HV* const tails = (HV*)sv_2mortal((SV*)newHV());
270 AV* const seqs = (AV*)sv_2mortal((SV*)newAV());
8638e433 271 I32* heads;
272
273 /* This builds @seqs, which is an array of arrays.
274 The members of @seqs are the MROs of
275 the members of @ISA, followed by @ISA itself.
276 */
e1a479c5 277 I32 items = AvFILLp(isa) + 1;
278 SV** isa_ptr = AvARRAY(isa);
279 while(items--) {
1e05feb3 280 SV* const isa_item = *isa_ptr++;
281 HV* const isa_item_stash = gv_stashsv(isa_item, 0);
e1a479c5 282 if(!isa_item_stash) {
8638e433 283 /* if no stash, make a temporary fake MRO
284 containing just itself */
70cd14a1 285 AV* const isa_lin = newAV();
e1a479c5 286 av_push(isa_lin, newSVsv(isa_item));
70cd14a1 287 av_push(seqs, (SV*)isa_lin);
e1a479c5 288 }
289 else {
70cd14a1 290 /* recursion */
291 AV* const isa_lin = mro_get_linear_isa_c3(isa_item_stash, level + 1);
292 av_push(seqs, SvREFCNT_inc_simple_NN((SV*)isa_lin));
e1a479c5 293 }
e1a479c5 294 }
1dcae283 295 av_push(seqs, SvREFCNT_inc_simple_NN((SV*)isa));
8638e433 296
297 /* This builds "heads", which as an array of integer array
298 indices, one per seq, which point at the virtual "head"
299 of the seq (initially zero) */
300 Newxz(heads, AvFILLp(seqs)+1, I32);
301
302 /* This builds %tails, which has one key for every class
303 mentioned in the tail of any sequence in @seqs (tail meaning
304 everything after the first class, the "head"). The value
305 is how many times this key appears in the tails of @seqs.
306 */
e1a479c5 307 seqs_ptr = AvARRAY(seqs);
308 seqs_items = AvFILLp(seqs) + 1;
309 while(seqs_items--) {
1e05feb3 310 AV* const seq = (AV*)*seqs_ptr++;
e1a479c5 311 I32 seq_items = AvFILLp(seq);
312 if(seq_items > 0) {
313 SV** seq_ptr = AvARRAY(seq) + 1;
314 while(seq_items--) {
1e05feb3 315 SV* const seqitem = *seq_ptr++;
694168e2 316 /* LVALUE fetch will create a new undefined SV if necessary
317 */
318 HE* const he = hv_fetch_ent(tails, seqitem, 1, 0);
319 if(he) {
1e05feb3 320 SV* const val = HeVAL(he);
694168e2 321 /* This will increment undef to 1, which is what we
322 want for a newly created entry. */
e1a479c5 323 sv_inc(val);
324 }
325 }
326 }
327 }
328
1dcae283 329 /* Initialize retval to build the return value in */
330 retval = newAV();
190d0b22 331 av_push(retval, newSVhek(stashhek)); /* us first */
1dcae283 332
8638e433 333 /* This loop won't terminate until we either finish building
334 the MRO, or get an exception. */
e1a479c5 335 while(1) {
e1a479c5 336 SV* cand = NULL;
337 SV* winner = NULL;
8638e433 338 int s;
339
340 /* "foreach $seq (@seqs)" */
1e05feb3 341 SV** const avptr = AvARRAY(seqs);
8638e433 342 for(s = 0; s <= AvFILLp(seqs); s++) {
e1a479c5 343 SV** svp;
1e05feb3 344 AV * const seq = (AV*)(avptr[s]);
345 SV* seqhead;
8638e433 346 if(!seq) continue; /* skip empty seqs */
347 svp = av_fetch(seq, heads[s], 0);
348 seqhead = *svp; /* seqhead = head of this seq */
e1a479c5 349 if(!winner) {
1e05feb3 350 HE* tail_entry;
351 SV* val;
8638e433 352 /* if we haven't found a winner for this round yet,
353 and this seqhead is not in tails (or the count
354 for it in tails has dropped to zero), then this
355 seqhead is our new winner, and is added to the
356 final MRO immediately */
e1a479c5 357 cand = seqhead;
358 if((tail_entry = hv_fetch_ent(tails, cand, 0, 0))
359 && (val = HeVAL(tail_entry))
25270bc0 360 && (SvIVX(val) > 0))
e1a479c5 361 continue;
362 winner = newSVsv(cand);
363 av_push(retval, winner);
8638e433 364 /* note however that even when we find a winner,
365 we continue looping over @seqs to do housekeeping */
e1a479c5 366 }
367 if(!sv_cmp(seqhead, winner)) {
8638e433 368 /* Once we have a winner (including the iteration
369 where we first found him), inc the head ptr
370 for any seq which had the winner as a head,
371 NULL out any seq which is now empty,
372 and adjust tails for consistency */
373
1e05feb3 374 const int new_head = ++heads[s];
8638e433 375 if(new_head > AvFILLp(seq)) {
1dcae283 376 SvREFCNT_dec(avptr[s]);
8638e433 377 avptr[s] = NULL;
378 }
379 else {
1e05feb3 380 HE* tail_entry;
381 SV* val;
8638e433 382 /* Because we know this new seqhead used to be
383 a tail, we can assume it is in tails and has
384 a positive value, which we need to dec */
385 svp = av_fetch(seq, new_head, 0);
386 seqhead = *svp;
387 tail_entry = hv_fetch_ent(tails, seqhead, 0, 0);
388 val = HeVAL(tail_entry);
389 sv_dec(val);
390 }
e1a479c5 391 }
392 }
8638e433 393
394 /* if we found no candidates, we are done building the MRO.
395 !cand means no seqs have any entries left to check */
396 if(!cand) {
397 Safefree(heads);
398 break;
399 }
400
401 /* If we had candidates, but nobody won, then the @ISA
402 hierarchy is not C3-incompatible */
e1a479c5 403 if(!winner) {
8638e433 404 /* we have to do some cleanup before we croak */
8638e433 405
e1a479c5 406 SvREFCNT_dec(retval);
8638e433 407 Safefree(heads);
408
e1a479c5 409 Perl_croak(aTHX_ "Inconsistent hierarchy during C3 merge of class '%s': "
190d0b22 410 "merging failed on parent '%"SVf"'", HEK_KEY(stashhek), SVfARG(cand));
e1a479c5 411 }
412 }
413 }
1dcae283 414 else { /* @ISA was undefined or empty */
415 /* build a retval containing only ourselves */
416 retval = newAV();
190d0b22 417 av_push(retval, newSVhek(stashhek));
1dcae283 418 }
e1a479c5 419
1c908217 420 /* we don't want anyone modifying the cache entry but us,
421 and we do so by replacing it completely */
e1a479c5 422 SvREADONLY_on(retval);
1c908217 423
e1a479c5 424 meta->mro_linear_c3 = retval;
425 return retval;
426}
427
428/*
429=for apidoc mro_get_linear_isa
430
431Returns either C<mro_get_linear_isa_c3> or
432C<mro_get_linear_isa_dfs> for the given stash,
433dependant upon which MRO is in effect
434for that stash. The return value is a
435read-only AV*.
436
1c908217 437You are responsible for C<SvREFCNT_inc()> on the
438return value if you plan to store it anywhere
439semi-permanently (otherwise it might be deleted
440out from under you the next time the cache is
441invalidated).
442
e1a479c5 443=cut
444*/
445AV*
446Perl_mro_get_linear_isa(pTHX_ HV *stash)
447{
448 struct mro_meta* meta;
2c7f4b87 449
e1a479c5 450 assert(stash);
2c7f4b87 451 if(!SvOOK(stash))
452 Perl_croak(aTHX_ "Can't linearize anonymous symbol table");
e1a479c5 453
454 meta = HvMROMETA(stash);
3d76853f 455 if (!meta->mro_which)
14f97ce6 456 Perl_croak(aTHX_ "panic: invalid MRO!");
3d76853f 457 return meta->mro_which->resolve(aTHX_ stash, 0);
e1a479c5 458}
459
460/*
461=for apidoc mro_isa_changed_in
462
1c908217 463Takes the necessary steps (cache invalidations, mostly)
e1a479c5 464when the @ISA of the given package has changed. Invoked
465by the C<setisa> magic, should not need to invoke directly.
466
467=cut
468*/
469void
470Perl_mro_isa_changed_in(pTHX_ HV* stash)
471{
472 dVAR;
473 HV* isarev;
474 AV* linear_mro;
475 HE* iter;
476 SV** svp;
477 I32 items;
1e05feb3 478 bool is_universal;
2c7f4b87 479 struct mro_meta * meta;
e1a479c5 480
0fa56319 481 const char * const stashname = HvNAME_get(stash);
482 const STRLEN stashname_len = HvNAMELEN_get(stash);
e1a479c5 483
2c7f4b87 484 if(!stashname)
485 Perl_croak(aTHX_ "Can't call mro_isa_changed_in() on anonymous symbol table");
486
e1a479c5 487 /* wipe out the cached linearizations for this stash */
2c7f4b87 488 meta = HvMROMETA(stash);
e1a479c5 489 SvREFCNT_dec((SV*)meta->mro_linear_dfs);
490 SvREFCNT_dec((SV*)meta->mro_linear_c3);
491 meta->mro_linear_dfs = NULL;
492 meta->mro_linear_c3 = NULL;
493
70cd14a1 494 /* Inc the package generation, since our @ISA changed */
495 meta->pkg_gen++;
496
e1a479c5 497 /* Wipe the global method cache if this package
498 is UNIVERSAL or one of its parents */
dd69841b 499
500 svp = hv_fetch(PL_isarev, stashname, stashname_len, 0);
501 isarev = svp ? (HV*)*svp : NULL;
502
503 if((stashname_len == 9 && strEQ(stashname, "UNIVERSAL"))
504 || (isarev && hv_exists(isarev, "UNIVERSAL", 9))) {
e1a479c5 505 PL_sub_generation++;
dd69841b 506 is_universal = TRUE;
507 }
1e05feb3 508 else { /* Wipe the local method cache otherwise */
dd69841b 509 meta->cache_gen++;
1e05feb3 510 is_universal = FALSE;
511 }
e1a479c5 512
513 /* wipe next::method cache too */
514 if(meta->mro_nextmethod) hv_clear(meta->mro_nextmethod);
1e05feb3 515
e1a479c5 516 /* Iterate the isarev (classes that are our children),
517 wiping out their linearization and method caches */
dd69841b 518 if(isarev) {
e1a479c5 519 hv_iterinit(isarev);
520 while((iter = hv_iternext(isarev))) {
1e05feb3 521 SV* const revkey = hv_iterkeysv(iter);
e1a479c5 522 HV* revstash = gv_stashsv(revkey, 0);
bc2cbbac 523 struct mro_meta* revmeta;
524
525 if(!revstash) continue;
526 revmeta = HvMROMETA(revstash);
e1a479c5 527 SvREFCNT_dec((SV*)revmeta->mro_linear_dfs);
528 SvREFCNT_dec((SV*)revmeta->mro_linear_c3);
529 revmeta->mro_linear_dfs = NULL;
530 revmeta->mro_linear_c3 = NULL;
dd69841b 531 if(!is_universal)
532 revmeta->cache_gen++;
e1a479c5 533 if(revmeta->mro_nextmethod)
534 hv_clear(revmeta->mro_nextmethod);
535 }
536 }
537
1c908217 538 /* Now iterate our MRO (parents), and do a few things:
539 1) instantiate with the "fake" flag if they don't exist
540 2) flag them as universal if we are universal
541 3) Add everything from our isarev to their isarev
542 */
543
544 /* We're starting at the 2nd element, skipping ourselves here */
e1a479c5 545 linear_mro = mro_get_linear_isa(stash);
546 svp = AvARRAY(linear_mro) + 1;
547 items = AvFILLp(linear_mro);
1c908217 548
e1a479c5 549 while (items--) {
550 SV* const sv = *svp++;
e1a479c5 551 HV* mroisarev;
552
1e05feb3 553 HE *he = hv_fetch_ent(PL_isarev, sv, 0, 0);
dd69841b 554 if(!he) {
555 he = hv_store_ent(PL_isarev, sv, (SV*)newHV(), 0);
e1a479c5 556 }
dd69841b 557 mroisarev = (HV*)HeVAL(he);
e1a479c5 558
25270bc0 559 /* This hash only ever contains PL_sv_yes. Storing it over itself is
560 almost as cheap as calling hv_exists, so on aggregate we expect to
561 save time by not making two calls to the common HV code for the
562 case where it doesn't exist. */
563
04fe65b0 564 (void)hv_store(mroisarev, stashname, stashname_len, &PL_sv_yes, 0);
e1a479c5 565
566 if(isarev) {
567 hv_iterinit(isarev);
568 while((iter = hv_iternext(isarev))) {
dd69841b 569 I32 revkeylen;
1e05feb3 570 char* const revkey = hv_iterkey(iter, &revkeylen);
04fe65b0 571 (void)hv_store(mroisarev, revkey, revkeylen, &PL_sv_yes, 0);
e1a479c5 572 }
573 }
574 }
575}
576
577/*
578=for apidoc mro_method_changed_in
579
47c9dd14 580Invalidates method caching on any child classes
581of the given stash, so that they might notice
582the changes in this one.
e1a479c5 583
584Ideally, all instances of C<PL_sub_generation++> in
dd69841b 585perl source outside of C<mro.c> should be
586replaced by calls to this.
587
588Perl automatically handles most of the common
589ways a method might be redefined. However, there
590are a few ways you could change a method in a stash
591without the cache code noticing, in which case you
592need to call this method afterwards:
e1a479c5 593
dd69841b 5941) Directly manipulating the stash HV entries from
595XS code.
e1a479c5 596
dd69841b 5972) Assigning a reference to a readonly scalar
598constant into a stash entry in order to create
599a constant subroutine (like constant.pm
600does).
601
602This same method is available from pure perl
603via, C<mro::method_changed_in(classname)>.
e1a479c5 604
605=cut
606*/
607void
608Perl_mro_method_changed_in(pTHX_ HV *stash)
609{
1e05feb3 610 const char * const stashname = HvNAME_get(stash);
611 const STRLEN stashname_len = HvNAMELEN_get(stash);
dd69841b 612
1e05feb3 613 SV ** const svp = hv_fetch(PL_isarev, stashname, stashname_len, 0);
614 HV * const isarev = svp ? (HV*)*svp : NULL;
e1a479c5 615
2c7f4b87 616 if(!stashname)
617 Perl_croak(aTHX_ "Can't call mro_method_changed_in() on anonymous symbol table");
618
70cd14a1 619 /* Inc the package generation, since a local method changed */
620 HvMROMETA(stash)->pkg_gen++;
621
e1a479c5 622 /* If stash is UNIVERSAL, or one of UNIVERSAL's parents,
623 invalidate all method caches globally */
dd69841b 624 if((stashname_len == 9 && strEQ(stashname, "UNIVERSAL"))
625 || (isarev && hv_exists(isarev, "UNIVERSAL", 9))) {
e1a479c5 626 PL_sub_generation++;
627 return;
628 }
629
630 /* else, invalidate the method caches of all child classes,
631 but not itself */
dd69841b 632 if(isarev) {
1e05feb3 633 HE* iter;
634
e1a479c5 635 hv_iterinit(isarev);
636 while((iter = hv_iternext(isarev))) {
1e05feb3 637 SV* const revkey = hv_iterkeysv(iter);
638 HV* const revstash = gv_stashsv(revkey, 0);
bc2cbbac 639 struct mro_meta* mrometa;
640
641 if(!revstash) continue;
642 mrometa = HvMROMETA(revstash);
dd69841b 643 mrometa->cache_gen++;
e1a479c5 644 if(mrometa->mro_nextmethod)
645 hv_clear(mrometa->mro_nextmethod);
646 }
647 }
648}
649
650/* These two are static helpers for next::method and friends,
651 and re-implement a bunch of the code from pp_caller() in
652 a more efficient manner for this particular usage.
653*/
654
655STATIC I32
656__dopoptosub_at(const PERL_CONTEXT *cxstk, I32 startingblock) {
657 I32 i;
658 for (i = startingblock; i >= 0; i--) {
659 if(CxTYPE((PERL_CONTEXT*)(&cxstk[i])) == CXt_SUB) return i;
660 }
661 return i;
662}
663
e1a479c5 664#include "XSUB.h"
665
666XS(XS_mro_get_linear_isa);
667XS(XS_mro_set_mro);
668XS(XS_mro_get_mro);
669XS(XS_mro_get_isarev);
670XS(XS_mro_is_universal);
c5860d66 671XS(XS_mro_invalidate_method_caches);
e1a479c5 672XS(XS_mro_method_changed_in);
70cd14a1 673XS(XS_mro_get_pkg_gen);
f58cd386 674XS(XS_mro_nextcan);
e1a479c5 675
676void
677Perl_boot_core_mro(pTHX)
678{
679 dVAR;
680 static const char file[] = __FILE__;
681
682 newXSproto("mro::get_linear_isa", XS_mro_get_linear_isa, file, "$;$");
683 newXSproto("mro::set_mro", XS_mro_set_mro, file, "$$");
684 newXSproto("mro::get_mro", XS_mro_get_mro, file, "$");
685 newXSproto("mro::get_isarev", XS_mro_get_isarev, file, "$");
686 newXSproto("mro::is_universal", XS_mro_is_universal, file, "$");
c5860d66 687 newXSproto("mro::invalidate_all_method_caches", XS_mro_invalidate_method_caches, file, "");
e1a479c5 688 newXSproto("mro::method_changed_in", XS_mro_method_changed_in, file, "$");
70cd14a1 689 newXSproto("mro::get_pkg_gen", XS_mro_get_pkg_gen, file, "$");
f58cd386 690 newXS("mro::_nextcan", XS_mro_nextcan, file);
e1a479c5 691}
692
693XS(XS_mro_get_linear_isa) {
694 dVAR;
695 dXSARGS;
696 AV* RETVAL;
697 HV* class_stash;
698 SV* classname;
699
700 PERL_UNUSED_ARG(cv);
701
702 if(items < 1 || items > 2)
703 Perl_croak(aTHX_ "Usage: mro::get_linear_isa(classname [, type ])");
704
705 classname = ST(0);
706 class_stash = gv_stashsv(classname, 0);
e1a479c5 707
70cd14a1 708 if(!class_stash) {
709 /* No stash exists yet, give them just the classname */
710 AV* isalin = newAV();
711 av_push(isalin, newSVsv(classname));
712 ST(0) = sv_2mortal(newRV_noinc((SV*)isalin));
713 XSRETURN(1);
714 }
715 else if(items > 1) {
1e05feb3 716 const char* const which = SvPV_nolen(ST(1));
3d76853f 717 const struct mro_alg *const algo = S_get_mro_from_name(aTHX_ which);
718 if (!algo)
719 Perl_croak(aTHX_ "Invalid mro name: '%s'", which);
84dccb35 720 RETVAL = algo->resolve(aTHX_ class_stash, 0);
e1a479c5 721 }
722 else {
723 RETVAL = mro_get_linear_isa(class_stash);
724 }
725
726 ST(0) = newRV_inc((SV*)RETVAL);
727 sv_2mortal(ST(0));
728 XSRETURN(1);
729}
730
731XS(XS_mro_set_mro)
732{
733 dVAR;
734 dXSARGS;
735 SV* classname;
3d76853f 736 const char* whichstr;
737 const struct mro_alg *which;
e1a479c5 738 HV* class_stash;
739 struct mro_meta* meta;
740
741 PERL_UNUSED_ARG(cv);
742
743 if (items != 2)
744 Perl_croak(aTHX_ "Usage: mro::set_mro(classname, type)");
745
746 classname = ST(0);
747 whichstr = SvPV_nolen(ST(1));
748 class_stash = gv_stashsv(classname, GV_ADD);
749 if(!class_stash) Perl_croak(aTHX_ "Cannot create class: '%"SVf"'!", SVfARG(classname));
750 meta = HvMROMETA(class_stash);
751
3d76853f 752 which = S_get_mro_from_name(aTHX_ whichstr);
753 if (!which)
e1a479c5 754 Perl_croak(aTHX_ "Invalid mro name: '%s'", whichstr);
755
756 if(meta->mro_which != which) {
757 meta->mro_which = which;
758 /* Only affects local method cache, not
759 even child classes */
dd69841b 760 meta->cache_gen++;
e1a479c5 761 if(meta->mro_nextmethod)
762 hv_clear(meta->mro_nextmethod);
763 }
764
765 XSRETURN_EMPTY;
766}
767
768
769XS(XS_mro_get_mro)
770{
771 dVAR;
772 dXSARGS;
773 SV* classname;
774 HV* class_stash;
e1a479c5 775
776 PERL_UNUSED_ARG(cv);
777
778 if (items != 1)
779 Perl_croak(aTHX_ "Usage: mro::get_mro(classname)");
780
781 classname = ST(0);
782 class_stash = gv_stashsv(classname, 0);
e1a479c5 783
3d76853f 784 ST(0) = sv_2mortal(newSVpv(class_stash
785 ? HvMROMETA(class_stash)->mro_which->name
786 : "dfs", 0));
e1a479c5 787 XSRETURN(1);
788}
789
790XS(XS_mro_get_isarev)
791{
792 dVAR;
793 dXSARGS;
794 SV* classname;
73968c7a 795 HE* he;
e1a479c5 796 HV* isarev;
70cd14a1 797 AV* ret_array;
e1a479c5 798
799 PERL_UNUSED_ARG(cv);
800
801 if (items != 1)
802 Perl_croak(aTHX_ "Usage: mro::get_isarev(classname)");
803
804 classname = ST(0);
805
e1a479c5 806 SP -= items;
dd69841b 807
70cd14a1 808
73968c7a 809 he = hv_fetch_ent(PL_isarev, classname, 0, 0);
810 isarev = he ? (HV*)HeVAL(he) : NULL;
70cd14a1 811
812 ret_array = newAV();
dd69841b 813 if(isarev) {
e1a479c5 814 HE* iter;
815 hv_iterinit(isarev);
816 while((iter = hv_iternext(isarev)))
70cd14a1 817 av_push(ret_array, newSVsv(hv_iterkeysv(iter)));
e1a479c5 818 }
70cd14a1 819 XPUSHs(sv_2mortal(newRV_noinc((SV*)ret_array)));
e1a479c5 820
821 PUTBACK;
822 return;
823}
824
825XS(XS_mro_is_universal)
826{
827 dVAR;
828 dXSARGS;
829 SV* classname;
dd69841b 830 HV* isarev;
70cd14a1 831 char* classname_pv;
832 STRLEN classname_len;
73968c7a 833 HE* he;
e1a479c5 834
835 PERL_UNUSED_ARG(cv);
836
837 if (items != 1)
dd69841b 838 Perl_croak(aTHX_ "Usage: mro::is_universal(classname)");
e1a479c5 839
840 classname = ST(0);
e1a479c5 841
cfff9797 842 classname_pv = SvPV(classname,classname_len);
dd69841b 843
73968c7a 844 he = hv_fetch_ent(PL_isarev, classname, 0, 0);
845 isarev = he ? (HV*)HeVAL(he) : NULL;
dd69841b 846
70cd14a1 847 if((classname_len == 9 && strEQ(classname_pv, "UNIVERSAL"))
dd69841b 848 || (isarev && hv_exists(isarev, "UNIVERSAL", 9)))
9edc5bb8 849 XSRETURN_YES;
850 else
851 XSRETURN_NO;
e1a479c5 852}
853
c5860d66 854XS(XS_mro_invalidate_method_caches)
e1a479c5 855{
856 dVAR;
857 dXSARGS;
858
859 PERL_UNUSED_ARG(cv);
860
861 if (items != 0)
862 Perl_croak(aTHX_ "Usage: mro::invalidate_all_method_caches()");
863
864 PL_sub_generation++;
865
866 XSRETURN_EMPTY;
867}
868
e1a479c5 869XS(XS_mro_method_changed_in)
870{
871 dVAR;
872 dXSARGS;
873 SV* classname;
874 HV* class_stash;
875
876 PERL_UNUSED_ARG(cv);
877
878 if(items != 1)
879 Perl_croak(aTHX_ "Usage: mro::method_changed_in(classname)");
880
881 classname = ST(0);
882
883 class_stash = gv_stashsv(classname, 0);
884 if(!class_stash) Perl_croak(aTHX_ "No such class: '%"SVf"'!", SVfARG(classname));
885
886 mro_method_changed_in(class_stash);
887
888 XSRETURN_EMPTY;
889}
890
70cd14a1 891XS(XS_mro_get_pkg_gen)
892{
893 dVAR;
894 dXSARGS;
895 SV* classname;
896 HV* class_stash;
897
898 PERL_UNUSED_ARG(cv);
899
900 if(items != 1)
901 Perl_croak(aTHX_ "Usage: mro::get_pkg_gen(classname)");
902
903 classname = ST(0);
904
905 class_stash = gv_stashsv(classname, 0);
906
907 SP -= items;
908
909 XPUSHs(sv_2mortal(newSViv(
910 class_stash ? HvMROMETA(class_stash)->pkg_gen : 0
911 )));
912
913 PUTBACK;
914 return;
915}
916
f58cd386 917XS(XS_mro_nextcan)
e1a479c5 918{
919 dVAR;
920 dXSARGS;
f58cd386 921 SV* self = ST(0);
922 const I32 throw_nomethod = SvIVX(ST(1));
bbd28cb9 923 register I32 cxix = cxstack_ix;
f58cd386 924 register const PERL_CONTEXT *ccstack = cxstack;
925 const PERL_SI *top_si = PL_curstackinfo;
926 HV* selfstash;
927 SV *stashname;
928 const char *fq_subname;
929 const char *subname;
930 STRLEN stashname_len;
931 STRLEN subname_len;
932 SV* sv;
933 GV** gvp;
934 AV* linear_av;
935 SV** linear_svp;
936 const char *hvname;
937 I32 entries;
938 struct mro_meta* selfmeta;
939 HV* nmcache;
bbd28cb9 940 I32 i;
e1a479c5 941
48fc4736 942 PERL_UNUSED_ARG(cv);
943
f58cd386 944 SP -= items;
945
946 if(sv_isobject(self))
947 selfstash = SvSTASH(SvRV(self));
948 else
949 selfstash = gv_stashsv(self, 0);
950
951 assert(selfstash);
952
953 hvname = HvNAME_get(selfstash);
954 if (!hvname)
955 Perl_croak(aTHX_ "Can't use anonymous symbol table for method lookup");
956
f58cd386 957 /* This block finds the contextually-enclosing fully-qualified subname,
958 much like looking at (caller($i))[3] until you find a real sub that
bbd28cb9 959 isn't ANON, etc (also skips over pureperl next::method, etc) */
960 for(i = 0; i < 2; i++) {
961 cxix = __dopoptosub_at(ccstack, cxix);
962 for (;;) {
963 GV* cvgv;
964 STRLEN fq_subname_len;
965
966 /* we may be in a higher stacklevel, so dig down deeper */
967 while (cxix < 0) {
968 if(top_si->si_type == PERLSI_MAIN)
969 Perl_croak(aTHX_ "next::method/next::can/maybe::next::method must be used in method context");
970 top_si = top_si->si_prev;
971 ccstack = top_si->si_cxstack;
972 cxix = __dopoptosub_at(ccstack, top_si->si_cxix);
973 }
f58cd386 974
bbd28cb9 975 if(CxTYPE((PERL_CONTEXT*)(&ccstack[cxix])) != CXt_SUB
976 || (PL_DBsub && GvCV(PL_DBsub) && ccstack[cxix].blk_sub.cv == GvCV(PL_DBsub))) {
977 cxix = __dopoptosub_at(ccstack, cxix - 1);
978 continue;
979 }
e1a479c5 980
bbd28cb9 981 {
982 const I32 dbcxix = __dopoptosub_at(ccstack, cxix - 1);
983 if (PL_DBsub && GvCV(PL_DBsub) && dbcxix >= 0 && ccstack[dbcxix].blk_sub.cv == GvCV(PL_DBsub)) {
984 if(CxTYPE((PERL_CONTEXT*)(&ccstack[dbcxix])) != CXt_SUB) {
985 cxix = dbcxix;
986 continue;
987 }
f58cd386 988 }
989 }
f58cd386 990
bbd28cb9 991 cvgv = CvGV(ccstack[cxix].blk_sub.cv);
f58cd386 992
bbd28cb9 993 if(!isGV(cvgv)) {
994 cxix = __dopoptosub_at(ccstack, cxix - 1);
995 continue;
996 }
f58cd386 997
bbd28cb9 998 /* we found a real sub here */
999 sv = sv_2mortal(newSV(0));
f58cd386 1000
bbd28cb9 1001 gv_efullname3(sv, cvgv, NULL);
f58cd386 1002
bbd28cb9 1003 fq_subname = SvPVX(sv);
1004 fq_subname_len = SvCUR(sv);
f58cd386 1005
bbd28cb9 1006 subname = strrchr(fq_subname, ':');
1007 if(!subname)
1008 Perl_croak(aTHX_ "next::method/next::can/maybe::next::method cannot find enclosing method");
f58cd386 1009
bbd28cb9 1010 subname++;
1011 subname_len = fq_subname_len - (subname - fq_subname);
1012 if(subname_len == 8 && strEQ(subname, "__ANON__")) {
1013 cxix = __dopoptosub_at(ccstack, cxix - 1);
1014 continue;
1015 }
1016 break;
f58cd386 1017 }
bbd28cb9 1018 cxix--;
e1a479c5 1019 }
f58cd386 1020
1021 /* If we made it to here, we found our context */
1022
1023 /* Initialize the next::method cache for this stash
1024 if necessary */
1025 selfmeta = HvMROMETA(selfstash);
1026 if(!(nmcache = selfmeta->mro_nextmethod)) {
1027 nmcache = selfmeta->mro_nextmethod = newHV();
1028 }
1029 else { /* Use the cached coderef if it exists */
1030 HE* cache_entry = hv_fetch_ent(nmcache, sv, 0, 0);
1031 if (cache_entry) {
1032 SV* const val = HeVAL(cache_entry);
1033 if(val == &PL_sv_undef) {
1034 if(throw_nomethod)
1035 Perl_croak(aTHX_ "No next::method '%s' found for %s", subname, hvname);
1036 XSRETURN_EMPTY;
1037 }
1038 XPUSHs(sv_2mortal(newRV_inc(val)));
1039 XSRETURN(1);
1040 }
e1a479c5 1041 }
1042
f58cd386 1043 /* beyond here is just for cache misses, so perf isn't as critical */
e1a479c5 1044
f58cd386 1045 stashname_len = subname - fq_subname - 2;
1046 stashname = sv_2mortal(newSVpvn(fq_subname, stashname_len));
e1a479c5 1047
f58cd386 1048 linear_av = mro_get_linear_isa_c3(selfstash, 0); /* has ourselves at the top of the list */
e1a479c5 1049
f58cd386 1050 linear_svp = AvARRAY(linear_av);
1051 entries = AvFILLp(linear_av) + 1;
e1a479c5 1052
f58cd386 1053 /* Walk down our MRO, skipping everything up
1054 to the contextually enclosing class */
1055 while (entries--) {
1056 SV * const linear_sv = *linear_svp++;
1057 assert(linear_sv);
1058 if(sv_eq(linear_sv, stashname))
1059 break;
1060 }
e1a479c5 1061
f58cd386 1062 /* Now search the remainder of the MRO for the
1063 same method name as the contextually enclosing
1064 method */
1065 if(entries > 0) {
1066 while (entries--) {
1067 SV * const linear_sv = *linear_svp++;
1068 HV* curstash;
1069 GV* candidate;
1070 CV* cand_cv;
e1a479c5 1071
f58cd386 1072 assert(linear_sv);
1073 curstash = gv_stashsv(linear_sv, FALSE);
1074
1075 if (!curstash) {
1076 if (ckWARN(WARN_SYNTAX))
1077 Perl_warner(aTHX_ packWARN(WARN_SYNTAX), "Can't locate package %"SVf" for @%s::ISA",
1078 (void*)linear_sv, hvname);
1079 continue;
1080 }
1081
1082 assert(curstash);
1083
1084 gvp = (GV**)hv_fetch(curstash, subname, subname_len, 0);
1085 if (!gvp) continue;
1086
1087 candidate = *gvp;
1088 assert(candidate);
1089
1090 if (SvTYPE(candidate) != SVt_PVGV)
1091 gv_init(candidate, curstash, subname, subname_len, TRUE);
1092
1093 /* Notably, we only look for real entries, not method cache
1094 entries, because in C3 the method cache of a parent is not
1095 valid for the child */
1096 if (SvTYPE(candidate) == SVt_PVGV && (cand_cv = GvCV(candidate)) && !GvCVGEN(candidate)) {
1097 SvREFCNT_inc_simple_void_NN((SV*)cand_cv);
04fe65b0 1098 (void)hv_store_ent(nmcache, newSVsv(sv), (SV*)cand_cv, 0);
f58cd386 1099 XPUSHs(sv_2mortal(newRV_inc((SV*)cand_cv)));
1100 XSRETURN(1);
1101 }
1102 }
e1a479c5 1103 }
1104
04fe65b0 1105 (void)hv_store_ent(nmcache, newSVsv(sv), &PL_sv_undef, 0);
f58cd386 1106 if(throw_nomethod)
1107 Perl_croak(aTHX_ "No next::method '%s' found for %s", subname, hvname);
1108 XSRETURN_EMPTY;
e1a479c5 1109}
1110
1111/*
1112 * Local variables:
1113 * c-indentation-style: bsd
1114 * c-basic-offset: 4
1115 * indent-tabs-mode: t
1116 * End:
1117 *
1118 * ex: set ts=8 sts=4 sw=4 noet:
1119 */