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