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