This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Remove duplicate return in S_mro_get_linear_isa_c3() accidentally added by
[perl5.git] / ext / mro / mro.xs
CommitLineData
b2685f0c
NC
1#include "EXTERN.h"
2#include "perl.h"
3#include "XSUB.h"
4
5static AV*
6S_mro_get_linear_isa_c3(pTHX_ HV* stash, U32 level);
7
8static const struct mro_alg c3_alg =
9 {S_mro_get_linear_isa_c3, "c3", 2, 0, 0};
10
11/*
12=for apidoc mro_get_linear_isa_c3
13
14Returns the C3 linearization of @ISA
15the given stash. The return value is a read-only AV*.
16C<level> should be 0 (it is used internally in this
17function's recursion).
18
19You are responsible for C<SvREFCNT_inc()> on the
20return value if you plan to store it anywhere
21semi-permanently (otherwise it might be deleted
22out from under you the next time the cache is
23invalidated).
24
25=cut
26*/
27
28static AV*
29S_mro_get_linear_isa_c3(pTHX_ HV* stash, U32 level)
30{
31 AV* retval;
32 GV** gvp;
33 GV* gv;
34 AV* isa;
35 const HEK* stashhek;
36 struct mro_meta* meta;
37
38 assert(HvAUX(stash));
39
40 stashhek = HvNAME_HEK(stash);
41 if (!stashhek)
42 Perl_croak(aTHX_ "Can't linearize anonymous symbol table");
43
44 if (level > 100)
45 Perl_croak(aTHX_ "Recursive inheritance detected in package '%s'",
46 HEK_KEY(stashhek));
47
48 meta = HvMROMETA(stash);
49
50 /* return cache if valid */
51 if((retval = MUTABLE_AV(MRO_GET_PRIVATE_DATA(meta, &c3_alg)))) {
52 return retval;
53 }
54
55 /* not in cache, make a new one */
56
57 gvp = (GV**)hv_fetchs(stash, "ISA", FALSE);
58 isa = (gvp && (gv = *gvp) && isGV_with_GP(gv)) ? GvAV(gv) : NULL;
59
60 /* For a better idea how the rest of this works, see the much clearer
61 pure perl version in Algorithm::C3 0.01:
62 http://search.cpan.org/src/STEVAN/Algorithm-C3-0.01/lib/Algorithm/C3.pm
63 (later versions go about it differently than this code for speed reasons)
64 */
65
66 if(isa && AvFILLp(isa) >= 0) {
67 SV** seqs_ptr;
68 I32 seqs_items;
69 HV* const tails = MUTABLE_HV(sv_2mortal(MUTABLE_SV(newHV())));
70 AV *const seqs = MUTABLE_AV(sv_2mortal(MUTABLE_SV(newAV())));
71 I32* heads;
72
73 /* This builds @seqs, which is an array of arrays.
74 The members of @seqs are the MROs of
75 the members of @ISA, followed by @ISA itself.
76 */
77 I32 items = AvFILLp(isa) + 1;
78 SV** isa_ptr = AvARRAY(isa);
79 while(items--) {
80 SV* const isa_item = *isa_ptr++;
81 HV* const isa_item_stash = gv_stashsv(isa_item, 0);
82 if(!isa_item_stash) {
83 /* if no stash, make a temporary fake MRO
84 containing just itself */
85 AV* const isa_lin = newAV();
86 av_push(isa_lin, newSVsv(isa_item));
87 av_push(seqs, MUTABLE_SV(isa_lin));
88 }
89 else {
90 /* recursion */
91 AV* const isa_lin
92 = S_mro_get_linear_isa_c3(aTHX_ isa_item_stash, level + 1);
93 av_push(seqs, SvREFCNT_inc_simple_NN(MUTABLE_SV(isa_lin)));
94 }
95 }
96 av_push(seqs, SvREFCNT_inc_simple_NN(MUTABLE_SV(isa)));
97
98 /* This builds "heads", which as an array of integer array
99 indices, one per seq, which point at the virtual "head"
100 of the seq (initially zero) */
101 Newxz(heads, AvFILLp(seqs)+1, I32);
102
103 /* This builds %tails, which has one key for every class
104 mentioned in the tail of any sequence in @seqs (tail meaning
105 everything after the first class, the "head"). The value
106 is how many times this key appears in the tails of @seqs.
107 */
108 seqs_ptr = AvARRAY(seqs);
109 seqs_items = AvFILLp(seqs) + 1;
110 while(seqs_items--) {
111 AV *const seq = MUTABLE_AV(*seqs_ptr++);
112 I32 seq_items = AvFILLp(seq);
113 if(seq_items > 0) {
114 SV** seq_ptr = AvARRAY(seq) + 1;
115 while(seq_items--) {
116 SV* const seqitem = *seq_ptr++;
117 /* LVALUE fetch will create a new undefined SV if necessary
118 */
119 HE* const he = hv_fetch_ent(tails, seqitem, 1, 0);
120 if(he) {
121 SV* const val = HeVAL(he);
122 /* This will increment undef to 1, which is what we
123 want for a newly created entry. */
124 sv_inc(val);
125 }
126 }
127 }
128 }
129
130 /* Initialize retval to build the return value in */
131 retval = newAV();
132 av_push(retval, newSVhek(stashhek)); /* us first */
133
134 /* This loop won't terminate until we either finish building
135 the MRO, or get an exception. */
136 while(1) {
137 SV* cand = NULL;
138 SV* winner = NULL;
139 int s;
140
141 /* "foreach $seq (@seqs)" */
142 SV** const avptr = AvARRAY(seqs);
143 for(s = 0; s <= AvFILLp(seqs); s++) {
144 SV** svp;
145 AV * const seq = MUTABLE_AV(avptr[s]);
146 SV* seqhead;
147 if(!seq) continue; /* skip empty seqs */
148 svp = av_fetch(seq, heads[s], 0);
149 seqhead = *svp; /* seqhead = head of this seq */
150 if(!winner) {
151 HE* tail_entry;
152 SV* val;
153 /* if we haven't found a winner for this round yet,
154 and this seqhead is not in tails (or the count
155 for it in tails has dropped to zero), then this
156 seqhead is our new winner, and is added to the
157 final MRO immediately */
158 cand = seqhead;
159 if((tail_entry = hv_fetch_ent(tails, cand, 0, 0))
160 && (val = HeVAL(tail_entry))
161 && (SvIVX(val) > 0))
162 continue;
163 winner = newSVsv(cand);
164 av_push(retval, winner);
165 /* note however that even when we find a winner,
166 we continue looping over @seqs to do housekeeping */
167 }
168 if(!sv_cmp(seqhead, winner)) {
169 /* Once we have a winner (including the iteration
170 where we first found him), inc the head ptr
171 for any seq which had the winner as a head,
172 NULL out any seq which is now empty,
173 and adjust tails for consistency */
174
175 const int new_head = ++heads[s];
176 if(new_head > AvFILLp(seq)) {
177 SvREFCNT_dec(avptr[s]);
178 avptr[s] = NULL;
179 }
180 else {
181 HE* tail_entry;
182 SV* val;
183 /* Because we know this new seqhead used to be
184 a tail, we can assume it is in tails and has
185 a positive value, which we need to dec */
186 svp = av_fetch(seq, new_head, 0);
187 seqhead = *svp;
188 tail_entry = hv_fetch_ent(tails, seqhead, 0, 0);
189 val = HeVAL(tail_entry);
190 sv_dec(val);
191 }
192 }
193 }
194
195 /* if we found no candidates, we are done building the MRO.
196 !cand means no seqs have any entries left to check */
197 if(!cand) {
198 Safefree(heads);
199 break;
200 }
201
202 /* If we had candidates, but nobody won, then the @ISA
203 hierarchy is not C3-incompatible */
204 if(!winner) {
205 /* we have to do some cleanup before we croak */
206
207 SvREFCNT_dec(retval);
208 Safefree(heads);
209
210 Perl_croak(aTHX_ "Inconsistent hierarchy during C3 merge of class '%s': "
211 "merging failed on parent '%"SVf"'", HEK_KEY(stashhek), SVfARG(cand));
212 }
213 }
214 }
215 else { /* @ISA was undefined or empty */
216 /* build a retval containing only ourselves */
217 retval = newAV();
218 av_push(retval, newSVhek(stashhek));
219 }
220
221 /* we don't want anyone modifying the cache entry but us,
222 and we do so by replacing it completely */
223 SvREADONLY_on(retval);
224
225 return MUTABLE_AV(Perl_mro_set_private_data(aTHX_ meta, &c3_alg,
226 MUTABLE_SV(retval)));
b2685f0c
NC
227}
228
229
230/* These two are static helpers for next::method and friends,
231 and re-implement a bunch of the code from pp_caller() in
232 a more efficient manner for this particular usage.
233*/
234
235static I32
236__dopoptosub_at(const PERL_CONTEXT *cxstk, I32 startingblock) {
237 I32 i;
238 for (i = startingblock; i >= 0; i--) {
239 if(CxTYPE((PERL_CONTEXT*)(&cxstk[i])) == CXt_SUB) return i;
240 }
241 return i;
242}
243
1e9bd118 244MODULE = mro PACKAGE = mro PREFIX = mro_
b2685f0c
NC
245
246void
1e9bd118
NC
247mro_get_linear_isa(...)
248 PROTOTYPE: $;$
249 PREINIT:
250 AV* RETVAL;
251 HV* class_stash;
252 SV* classname;
253 PPCODE:
254 if(items < 1 || items > 2)
255 croak_xs_usage(cv, "classname [, type ]");
256
257 classname = ST(0);
258 class_stash = gv_stashsv(classname, 0);
259
260 if(!class_stash) {
261 /* No stash exists yet, give them just the classname */
262 AV* isalin = newAV();
263 av_push(isalin, newSVsv(classname));
264 ST(0) = sv_2mortal(newRV_noinc(MUTABLE_SV(isalin)));
265 XSRETURN(1);
266 }
267 else if(items > 1) {
268 const struct mro_alg *const algo = Perl_mro_get_from_name(aTHX_ ST(1));
269 if (!algo)
270 Perl_croak(aTHX_ "Invalid mro name: '%"SVf"'", ST(1));
271 RETVAL = algo->resolve(aTHX_ class_stash, 0);
272 }
273 else {
274 RETVAL = mro_get_linear_isa(class_stash);
275 }
276 ST(0) = newRV_inc(MUTABLE_SV(RETVAL));
277 sv_2mortal(ST(0));
278 XSRETURN(1);
279
280void
281mro_set_mro(...)
282 PROTOTYPE: $$
283 PREINIT:
284 SV* classname;
285 const struct mro_alg *which;
286 HV* class_stash;
287 struct mro_meta* meta;
288 PPCODE:
289 if (items != 2)
290 croak_xs_usage(cv, "classname, type");
291
292 classname = ST(0);
293 class_stash = gv_stashsv(classname, GV_ADD);
294 if(!class_stash) Perl_croak(aTHX_ "Cannot create class: '%"SVf"'!", SVfARG(classname));
295 meta = HvMROMETA(class_stash);
296
297 Perl_mro_set_mro(aTHX_ meta, ST(1));
298
299 XSRETURN_EMPTY;
300
301void
302mro_get_mro(...)
303 PROTOTYPE: $
304 PREINIT:
305 SV* classname;
306 HV* class_stash;
307 PPCODE:
308 if (items != 1)
309 croak_xs_usage(cv, "classname");
310
311 classname = ST(0);
312 class_stash = gv_stashsv(classname, 0);
313
fbb5a95c
NC
314 if (class_stash) {
315 const struct mro_alg *const meta = HvMROMETA(class_stash)->mro_which;
316 ST(0) = newSVpvn_flags(meta->name, meta->length,
317 SVs_TEMP
318 | ((meta->kflags & HVhek_UTF8) ? SVf_UTF8 : 0));
319 } else {
320 ST(0) = newSVpvn_flags("dfs", 3, SVs_TEMP);
321 }
1e9bd118
NC
322 XSRETURN(1);
323
324void
325mro_get_isarev(...)
326 PROTOTYPE: $
327 PREINIT:
328 SV* classname;
329 HE* he;
330 HV* isarev;
331 AV* ret_array;
332 PPCODE:
333 if (items != 1)
334 croak_xs_usage(cv, "classname");
335
336 classname = ST(0);
337
338 he = hv_fetch_ent(PL_isarev, classname, 0, 0);
339 isarev = he ? MUTABLE_HV(HeVAL(he)) : NULL;
340
341 ret_array = newAV();
342 if(isarev) {
343 HE* iter;
344 hv_iterinit(isarev);
345 while((iter = hv_iternext(isarev)))
346 av_push(ret_array, newSVsv(hv_iterkeysv(iter)));
347 }
348 mXPUSHs(newRV_noinc(MUTABLE_SV(ret_array)));
349
350 PUTBACK;
351
352void
353mro_is_universal(...)
354 PROTOTYPE: $
355 PREINIT:
356 SV* classname;
357 HV* isarev;
358 char* classname_pv;
359 STRLEN classname_len;
360 HE* he;
361 PPCODE:
362 if (items != 1)
363 croak_xs_usage(cv, "classname");
364
365 classname = ST(0);
366
367 classname_pv = SvPV(classname,classname_len);
368
369 he = hv_fetch_ent(PL_isarev, classname, 0, 0);
370 isarev = he ? MUTABLE_HV(HeVAL(he)) : NULL;
371
372 if((classname_len == 9 && strEQ(classname_pv, "UNIVERSAL"))
373 || (isarev && hv_exists(isarev, "UNIVERSAL", 9)))
374 XSRETURN_YES;
375 else
376 XSRETURN_NO;
377
378
379void
380mro_invalidate_method_caches(...)
381 PROTOTYPE:
382 PPCODE:
383 if (items != 0)
384 croak_xs_usage(cv, "");
385
386 PL_sub_generation++;
387
388 XSRETURN_EMPTY;
389
390void
391mro_get_pkg_gen(...)
392 PROTOTYPE: $
393 PREINIT:
394 SV* classname;
395 HV* class_stash;
396 PPCODE:
397 if(items != 1)
398 croak_xs_usage(cv, "classname");
399
400 classname = ST(0);
401
402 class_stash = gv_stashsv(classname, 0);
403
404 mXPUSHi(class_stash ? HvMROMETA(class_stash)->pkg_gen : 0);
405
406 PUTBACK;
407
408void
409mro__nextcan(...)
b2685f0c
NC
410 PREINIT:
411 SV* self = ST(0);
412 const I32 throw_nomethod = SvIVX(ST(1));
413 register I32 cxix = cxstack_ix;
414 register const PERL_CONTEXT *ccstack = cxstack;
415 const PERL_SI *top_si = PL_curstackinfo;
416 HV* selfstash;
417 SV *stashname;
418 const char *fq_subname;
419 const char *subname;
420 STRLEN stashname_len;
421 STRLEN subname_len;
422 SV* sv;
423 GV** gvp;
424 AV* linear_av;
425 SV** linear_svp;
426 const char *hvname;
427 I32 entries;
428 struct mro_meta* selfmeta;
429 HV* nmcache;
430 I32 i;
431 PPCODE:
432 PERL_UNUSED_ARG(cv);
433
434 if(sv_isobject(self))
435 selfstash = SvSTASH(SvRV(self));
436 else
437 selfstash = gv_stashsv(self, GV_ADD);
438
439 assert(selfstash);
440
441 hvname = HvNAME_get(selfstash);
442 if (!hvname)
443 Perl_croak(aTHX_ "Can't use anonymous symbol table for method lookup");
444
445 /* This block finds the contextually-enclosing fully-qualified subname,
446 much like looking at (caller($i))[3] until you find a real sub that
447 isn't ANON, etc (also skips over pureperl next::method, etc) */
448 for(i = 0; i < 2; i++) {
449 cxix = __dopoptosub_at(ccstack, cxix);
450 for (;;) {
451 GV* cvgv;
452 STRLEN fq_subname_len;
453
454 /* we may be in a higher stacklevel, so dig down deeper */
455 while (cxix < 0) {
456 if(top_si->si_type == PERLSI_MAIN)
457 Perl_croak(aTHX_ "next::method/next::can/maybe::next::method must be used in method context");
458 top_si = top_si->si_prev;
459 ccstack = top_si->si_cxstack;
460 cxix = __dopoptosub_at(ccstack, top_si->si_cxix);
461 }
462
463 if(CxTYPE((PERL_CONTEXT*)(&ccstack[cxix])) != CXt_SUB
464 || (PL_DBsub && GvCV(PL_DBsub) && ccstack[cxix].blk_sub.cv == GvCV(PL_DBsub))) {
465 cxix = __dopoptosub_at(ccstack, cxix - 1);
466 continue;
467 }
468
469 {
470 const I32 dbcxix = __dopoptosub_at(ccstack, cxix - 1);
471 if (PL_DBsub && GvCV(PL_DBsub) && dbcxix >= 0 && ccstack[dbcxix].blk_sub.cv == GvCV(PL_DBsub)) {
472 if(CxTYPE((PERL_CONTEXT*)(&ccstack[dbcxix])) != CXt_SUB) {
473 cxix = dbcxix;
474 continue;
475 }
476 }
477 }
478
479 cvgv = CvGV(ccstack[cxix].blk_sub.cv);
480
481 if(!isGV(cvgv)) {
482 cxix = __dopoptosub_at(ccstack, cxix - 1);
483 continue;
484 }
485
486 /* we found a real sub here */
487 sv = sv_2mortal(newSV(0));
488
489 gv_efullname3(sv, cvgv, NULL);
490
491 fq_subname = SvPVX(sv);
492 fq_subname_len = SvCUR(sv);
493
494 subname = strrchr(fq_subname, ':');
495 if(!subname)
496 Perl_croak(aTHX_ "next::method/next::can/maybe::next::method cannot find enclosing method");
497
498 subname++;
499 subname_len = fq_subname_len - (subname - fq_subname);
500 if(subname_len == 8 && strEQ(subname, "__ANON__")) {
501 cxix = __dopoptosub_at(ccstack, cxix - 1);
502 continue;
503 }
504 break;
505 }
506 cxix--;
507 }
508
509 /* If we made it to here, we found our context */
510
511 /* Initialize the next::method cache for this stash
512 if necessary */
513 selfmeta = HvMROMETA(selfstash);
514 if(!(nmcache = selfmeta->mro_nextmethod)) {
515 nmcache = selfmeta->mro_nextmethod = newHV();
516 }
517 else { /* Use the cached coderef if it exists */
518 HE* cache_entry = hv_fetch_ent(nmcache, sv, 0, 0);
519 if (cache_entry) {
520 SV* const val = HeVAL(cache_entry);
521 if(val == &PL_sv_undef) {
522 if(throw_nomethod)
523 Perl_croak(aTHX_ "No next::method '%s' found for %s", subname, hvname);
524 XSRETURN_EMPTY;
525 }
526 mXPUSHs(newRV_inc(val));
527 XSRETURN(1);
528 }
529 }
530
531 /* beyond here is just for cache misses, so perf isn't as critical */
532
533 stashname_len = subname - fq_subname - 2;
534 stashname = newSVpvn_flags(fq_subname, stashname_len, SVs_TEMP);
535
536 /* has ourselves at the top of the list */
537 linear_av = S_mro_get_linear_isa_c3(aTHX_ selfstash, 0);
538
539 linear_svp = AvARRAY(linear_av);
540 entries = AvFILLp(linear_av) + 1;
541
542 /* Walk down our MRO, skipping everything up
543 to the contextually enclosing class */
544 while (entries--) {
545 SV * const linear_sv = *linear_svp++;
546 assert(linear_sv);
547 if(sv_eq(linear_sv, stashname))
548 break;
549 }
550
551 /* Now search the remainder of the MRO for the
552 same method name as the contextually enclosing
553 method */
554 if(entries > 0) {
555 while (entries--) {
556 SV * const linear_sv = *linear_svp++;
557 HV* curstash;
558 GV* candidate;
559 CV* cand_cv;
560
561 assert(linear_sv);
562 curstash = gv_stashsv(linear_sv, FALSE);
563
564 if (!curstash) {
565 if (ckWARN(WARN_SYNTAX))
566 Perl_warner(aTHX_ packWARN(WARN_SYNTAX), "Can't locate package %"SVf" for @%s::ISA",
567 (void*)linear_sv, hvname);
568 continue;
569 }
570
571 assert(curstash);
572
573 gvp = (GV**)hv_fetch(curstash, subname, subname_len, 0);
574 if (!gvp) continue;
575
576 candidate = *gvp;
577 assert(candidate);
578
579 if (SvTYPE(candidate) != SVt_PVGV)
580 gv_init(candidate, curstash, subname, subname_len, TRUE);
581
582 /* Notably, we only look for real entries, not method cache
583 entries, because in C3 the method cache of a parent is not
584 valid for the child */
585 if (SvTYPE(candidate) == SVt_PVGV && (cand_cv = GvCV(candidate)) && !GvCVGEN(candidate)) {
586 SvREFCNT_inc_simple_void_NN(MUTABLE_SV(cand_cv));
587 (void)hv_store_ent(nmcache, newSVsv(sv), MUTABLE_SV(cand_cv), 0);
588 mXPUSHs(newRV_inc(MUTABLE_SV(cand_cv)));
589 XSRETURN(1);
590 }
591 }
592 }
593
594 (void)hv_store_ent(nmcache, newSVsv(sv), &PL_sv_undef, 0);
595 if(throw_nomethod)
596 Perl_croak(aTHX_ "No next::method '%s' found for %s", subname, hvname);
597 XSRETURN_EMPTY;
598
599BOOT:
600 Perl_mro_register(aTHX_ &c3_alg);