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