Moved Log::Message et al from lib/ to ext/
[p5sagit/p5-mst-13.2.git] / ext / mro / mro.xs
CommitLineData
b2685f0c 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;
b0413f46 69 HV *tails;
b2685f0c 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);
b0413f46 93
a18d9f20 94 if(items == 0 && AvFILLp(seqs) == -1) {
b0413f46 95 /* Only one parent class. For this case, the C3
96 linearisation is this class followed by the parent's
97 inearisation, so don't bother with the expensive
98 calculation. */
99 SV **svp;
100 I32 subrv_items = AvFILLp(isa_lin) + 1;
101 SV *const *subrv_p = AvARRAY(isa_lin);
102
103 /* Hijack the allocated but unused array seqs to be the
104 return value. It's currently mortalised. */
105
106 retval = seqs;
107
108 av_extend(retval, subrv_items);
109 AvFILLp(retval) = subrv_items;
110 svp = AvARRAY(retval);
111
112 /* First entry is this class. We happen to make a shared
113 hash key scalar because it's the cheapest and fastest
114 way to do it. */
115 *svp++ = newSVhek(stashhek);
116
117 while(subrv_items--) {
118 /* These values are unlikely to be shared hash key
119 scalars, so no point in adding code to optimising
120 for a case that is unlikely to be true.
121 (Or prove me wrong and do it.) */
122
123 SV *const val = *subrv_p++;
124 *svp++ = newSVsv(val);
125 }
126
127 SvREFCNT_inc(retval);
128
129 goto done;
130 }
b2685f0c 131 av_push(seqs, SvREFCNT_inc_simple_NN(MUTABLE_SV(isa_lin)));
132 }
133 }
134 av_push(seqs, SvREFCNT_inc_simple_NN(MUTABLE_SV(isa)));
b0413f46 135 tails = MUTABLE_HV(sv_2mortal(MUTABLE_SV(newHV())));
b2685f0c 136
137 /* This builds "heads", which as an array of integer array
138 indices, one per seq, which point at the virtual "head"
139 of the seq (initially zero) */
140 Newxz(heads, AvFILLp(seqs)+1, I32);
141
142 /* This builds %tails, which has one key for every class
143 mentioned in the tail of any sequence in @seqs (tail meaning
144 everything after the first class, the "head"). The value
145 is how many times this key appears in the tails of @seqs.
146 */
147 seqs_ptr = AvARRAY(seqs);
148 seqs_items = AvFILLp(seqs) + 1;
149 while(seqs_items--) {
150 AV *const seq = MUTABLE_AV(*seqs_ptr++);
151 I32 seq_items = AvFILLp(seq);
152 if(seq_items > 0) {
153 SV** seq_ptr = AvARRAY(seq) + 1;
154 while(seq_items--) {
155 SV* const seqitem = *seq_ptr++;
156 /* LVALUE fetch will create a new undefined SV if necessary
157 */
158 HE* const he = hv_fetch_ent(tails, seqitem, 1, 0);
159 if(he) {
160 SV* const val = HeVAL(he);
161 /* This will increment undef to 1, which is what we
162 want for a newly created entry. */
163 sv_inc(val);
164 }
165 }
166 }
167 }
168
169 /* Initialize retval to build the return value in */
170 retval = newAV();
171 av_push(retval, newSVhek(stashhek)); /* us first */
172
173 /* This loop won't terminate until we either finish building
174 the MRO, or get an exception. */
175 while(1) {
176 SV* cand = NULL;
177 SV* winner = NULL;
178 int s;
179
180 /* "foreach $seq (@seqs)" */
181 SV** const avptr = AvARRAY(seqs);
182 for(s = 0; s <= AvFILLp(seqs); s++) {
183 SV** svp;
184 AV * const seq = MUTABLE_AV(avptr[s]);
185 SV* seqhead;
186 if(!seq) continue; /* skip empty seqs */
187 svp = av_fetch(seq, heads[s], 0);
188 seqhead = *svp; /* seqhead = head of this seq */
189 if(!winner) {
190 HE* tail_entry;
191 SV* val;
192 /* if we haven't found a winner for this round yet,
193 and this seqhead is not in tails (or the count
194 for it in tails has dropped to zero), then this
195 seqhead is our new winner, and is added to the
196 final MRO immediately */
197 cand = seqhead;
198 if((tail_entry = hv_fetch_ent(tails, cand, 0, 0))
199 && (val = HeVAL(tail_entry))
200 && (SvIVX(val) > 0))
201 continue;
202 winner = newSVsv(cand);
203 av_push(retval, winner);
204 /* note however that even when we find a winner,
205 we continue looping over @seqs to do housekeeping */
206 }
207 if(!sv_cmp(seqhead, winner)) {
208 /* Once we have a winner (including the iteration
209 where we first found him), inc the head ptr
210 for any seq which had the winner as a head,
211 NULL out any seq which is now empty,
212 and adjust tails for consistency */
213
214 const int new_head = ++heads[s];
215 if(new_head > AvFILLp(seq)) {
216 SvREFCNT_dec(avptr[s]);
217 avptr[s] = NULL;
218 }
219 else {
220 HE* tail_entry;
221 SV* val;
222 /* Because we know this new seqhead used to be
223 a tail, we can assume it is in tails and has
224 a positive value, which we need to dec */
225 svp = av_fetch(seq, new_head, 0);
226 seqhead = *svp;
227 tail_entry = hv_fetch_ent(tails, seqhead, 0, 0);
228 val = HeVAL(tail_entry);
229 sv_dec(val);
230 }
231 }
232 }
233
234 /* if we found no candidates, we are done building the MRO.
235 !cand means no seqs have any entries left to check */
236 if(!cand) {
237 Safefree(heads);
238 break;
239 }
240
241 /* If we had candidates, but nobody won, then the @ISA
242 hierarchy is not C3-incompatible */
243 if(!winner) {
b1172053 244 SV *errmsg;
245 I32 i;
246
247 errmsg = newSVpvf("Inconsistent hierarchy during C3 merge of class '%s':\n\t"
248 "current merge results [\n", HEK_KEY(stashhek));
249 for (i = 0; i <= av_len(retval); i++) {
250 SV **elem = av_fetch(retval, i, 0);
251 sv_catpvf(errmsg, "\t\t%"SVf",\n", SVfARG(*elem));
252 }
253 sv_catpvf(errmsg, "\t]\n\tmerging failed on '%"SVf"'", SVfARG(cand));
254
b2685f0c 255 /* we have to do some cleanup before we croak */
256
257 SvREFCNT_dec(retval);
258 Safefree(heads);
259
b1172053 260 Perl_croak(aTHX_ "%"SVf, SVfARG(errmsg));
b2685f0c 261 }
262 }
263 }
264 else { /* @ISA was undefined or empty */
265 /* build a retval containing only ourselves */
266 retval = newAV();
267 av_push(retval, newSVhek(stashhek));
268 }
269
b0413f46 270 done:
b2685f0c 271 /* we don't want anyone modifying the cache entry but us,
272 and we do so by replacing it completely */
273 SvREADONLY_on(retval);
274
275 return MUTABLE_AV(Perl_mro_set_private_data(aTHX_ meta, &c3_alg,
276 MUTABLE_SV(retval)));
b2685f0c 277}
278
279
280/* These two are static helpers for next::method and friends,
281 and re-implement a bunch of the code from pp_caller() in
282 a more efficient manner for this particular usage.
283*/
284
285static I32
286__dopoptosub_at(const PERL_CONTEXT *cxstk, I32 startingblock) {
287 I32 i;
288 for (i = startingblock; i >= 0; i--) {
289 if(CxTYPE((PERL_CONTEXT*)(&cxstk[i])) == CXt_SUB) return i;
290 }
291 return i;
292}
293
1e9bd118 294MODULE = mro PACKAGE = mro PREFIX = mro_
b2685f0c 295
296void
1e9bd118 297mro_get_linear_isa(...)
298 PROTOTYPE: $;$
299 PREINIT:
300 AV* RETVAL;
301 HV* class_stash;
302 SV* classname;
303 PPCODE:
304 if(items < 1 || items > 2)
305 croak_xs_usage(cv, "classname [, type ]");
306
307 classname = ST(0);
308 class_stash = gv_stashsv(classname, 0);
309
310 if(!class_stash) {
311 /* No stash exists yet, give them just the classname */
312 AV* isalin = newAV();
313 av_push(isalin, newSVsv(classname));
314 ST(0) = sv_2mortal(newRV_noinc(MUTABLE_SV(isalin)));
315 XSRETURN(1);
316 }
317 else if(items > 1) {
318 const struct mro_alg *const algo = Perl_mro_get_from_name(aTHX_ ST(1));
319 if (!algo)
320 Perl_croak(aTHX_ "Invalid mro name: '%"SVf"'", ST(1));
321 RETVAL = algo->resolve(aTHX_ class_stash, 0);
322 }
323 else {
324 RETVAL = mro_get_linear_isa(class_stash);
325 }
326 ST(0) = newRV_inc(MUTABLE_SV(RETVAL));
327 sv_2mortal(ST(0));
328 XSRETURN(1);
329
330void
331mro_set_mro(...)
332 PROTOTYPE: $$
333 PREINIT:
334 SV* classname;
1e9bd118 335 HV* class_stash;
336 struct mro_meta* meta;
337 PPCODE:
338 if (items != 2)
339 croak_xs_usage(cv, "classname, type");
340
341 classname = ST(0);
342 class_stash = gv_stashsv(classname, GV_ADD);
343 if(!class_stash) Perl_croak(aTHX_ "Cannot create class: '%"SVf"'!", SVfARG(classname));
344 meta = HvMROMETA(class_stash);
345
346 Perl_mro_set_mro(aTHX_ meta, ST(1));
347
348 XSRETURN_EMPTY;
349
350void
351mro_get_mro(...)
352 PROTOTYPE: $
353 PREINIT:
354 SV* classname;
355 HV* class_stash;
356 PPCODE:
357 if (items != 1)
358 croak_xs_usage(cv, "classname");
359
360 classname = ST(0);
361 class_stash = gv_stashsv(classname, 0);
362
fbb5a95c 363 if (class_stash) {
364 const struct mro_alg *const meta = HvMROMETA(class_stash)->mro_which;
365 ST(0) = newSVpvn_flags(meta->name, meta->length,
366 SVs_TEMP
367 | ((meta->kflags & HVhek_UTF8) ? SVf_UTF8 : 0));
368 } else {
369 ST(0) = newSVpvn_flags("dfs", 3, SVs_TEMP);
370 }
1e9bd118 371 XSRETURN(1);
372
373void
374mro_get_isarev(...)
375 PROTOTYPE: $
376 PREINIT:
377 SV* classname;
378 HE* he;
379 HV* isarev;
380 AV* ret_array;
381 PPCODE:
382 if (items != 1)
383 croak_xs_usage(cv, "classname");
384
385 classname = ST(0);
386
387 he = hv_fetch_ent(PL_isarev, classname, 0, 0);
388 isarev = he ? MUTABLE_HV(HeVAL(he)) : NULL;
389
390 ret_array = newAV();
391 if(isarev) {
392 HE* iter;
393 hv_iterinit(isarev);
394 while((iter = hv_iternext(isarev)))
395 av_push(ret_array, newSVsv(hv_iterkeysv(iter)));
396 }
397 mXPUSHs(newRV_noinc(MUTABLE_SV(ret_array)));
398
399 PUTBACK;
400
401void
402mro_is_universal(...)
403 PROTOTYPE: $
404 PREINIT:
405 SV* classname;
406 HV* isarev;
407 char* classname_pv;
408 STRLEN classname_len;
409 HE* he;
410 PPCODE:
411 if (items != 1)
412 croak_xs_usage(cv, "classname");
413
414 classname = ST(0);
415
416 classname_pv = SvPV(classname,classname_len);
417
418 he = hv_fetch_ent(PL_isarev, classname, 0, 0);
419 isarev = he ? MUTABLE_HV(HeVAL(he)) : NULL;
420
421 if((classname_len == 9 && strEQ(classname_pv, "UNIVERSAL"))
422 || (isarev && hv_exists(isarev, "UNIVERSAL", 9)))
423 XSRETURN_YES;
424 else
425 XSRETURN_NO;
426
427
428void
a4133167 429mro_invalidate_all_method_caches(...)
1e9bd118 430 PROTOTYPE:
431 PPCODE:
432 if (items != 0)
433 croak_xs_usage(cv, "");
434
435 PL_sub_generation++;
436
437 XSRETURN_EMPTY;
438
439void
440mro_get_pkg_gen(...)
441 PROTOTYPE: $
442 PREINIT:
443 SV* classname;
444 HV* class_stash;
445 PPCODE:
446 if(items != 1)
447 croak_xs_usage(cv, "classname");
448
449 classname = ST(0);
450
451 class_stash = gv_stashsv(classname, 0);
452
453 mXPUSHi(class_stash ? HvMROMETA(class_stash)->pkg_gen : 0);
454
455 PUTBACK;
456
457void
458mro__nextcan(...)
b2685f0c 459 PREINIT:
460 SV* self = ST(0);
461 const I32 throw_nomethod = SvIVX(ST(1));
462 register I32 cxix = cxstack_ix;
463 register const PERL_CONTEXT *ccstack = cxstack;
464 const PERL_SI *top_si = PL_curstackinfo;
465 HV* selfstash;
466 SV *stashname;
467 const char *fq_subname;
468 const char *subname;
469 STRLEN stashname_len;
470 STRLEN subname_len;
471 SV* sv;
472 GV** gvp;
473 AV* linear_av;
474 SV** linear_svp;
475 const char *hvname;
476 I32 entries;
477 struct mro_meta* selfmeta;
478 HV* nmcache;
479 I32 i;
480 PPCODE:
481 PERL_UNUSED_ARG(cv);
482
483 if(sv_isobject(self))
484 selfstash = SvSTASH(SvRV(self));
485 else
486 selfstash = gv_stashsv(self, GV_ADD);
487
488 assert(selfstash);
489
490 hvname = HvNAME_get(selfstash);
491 if (!hvname)
492 Perl_croak(aTHX_ "Can't use anonymous symbol table for method lookup");
493
494 /* This block finds the contextually-enclosing fully-qualified subname,
495 much like looking at (caller($i))[3] until you find a real sub that
496 isn't ANON, etc (also skips over pureperl next::method, etc) */
497 for(i = 0; i < 2; i++) {
498 cxix = __dopoptosub_at(ccstack, cxix);
499 for (;;) {
500 GV* cvgv;
501 STRLEN fq_subname_len;
502
503 /* we may be in a higher stacklevel, so dig down deeper */
504 while (cxix < 0) {
505 if(top_si->si_type == PERLSI_MAIN)
506 Perl_croak(aTHX_ "next::method/next::can/maybe::next::method must be used in method context");
507 top_si = top_si->si_prev;
508 ccstack = top_si->si_cxstack;
509 cxix = __dopoptosub_at(ccstack, top_si->si_cxix);
510 }
511
512 if(CxTYPE((PERL_CONTEXT*)(&ccstack[cxix])) != CXt_SUB
513 || (PL_DBsub && GvCV(PL_DBsub) && ccstack[cxix].blk_sub.cv == GvCV(PL_DBsub))) {
514 cxix = __dopoptosub_at(ccstack, cxix - 1);
515 continue;
516 }
517
518 {
519 const I32 dbcxix = __dopoptosub_at(ccstack, cxix - 1);
520 if (PL_DBsub && GvCV(PL_DBsub) && dbcxix >= 0 && ccstack[dbcxix].blk_sub.cv == GvCV(PL_DBsub)) {
521 if(CxTYPE((PERL_CONTEXT*)(&ccstack[dbcxix])) != CXt_SUB) {
522 cxix = dbcxix;
523 continue;
524 }
525 }
526 }
527
528 cvgv = CvGV(ccstack[cxix].blk_sub.cv);
529
530 if(!isGV(cvgv)) {
531 cxix = __dopoptosub_at(ccstack, cxix - 1);
532 continue;
533 }
534
535 /* we found a real sub here */
8e234d89 536 sv = sv_newmortal();
b2685f0c 537
538 gv_efullname3(sv, cvgv, NULL);
539
9c1314f0 540 if(SvPOK(sv)) {
541 fq_subname = SvPVX(sv);
542 fq_subname_len = SvCUR(sv);
543
544 subname = strrchr(fq_subname, ':');
545 } else {
546 subname = NULL;
547 }
b2685f0c 548
b2685f0c 549 if(!subname)
550 Perl_croak(aTHX_ "next::method/next::can/maybe::next::method cannot find enclosing method");
551
552 subname++;
553 subname_len = fq_subname_len - (subname - fq_subname);
554 if(subname_len == 8 && strEQ(subname, "__ANON__")) {
555 cxix = __dopoptosub_at(ccstack, cxix - 1);
556 continue;
557 }
558 break;
559 }
560 cxix--;
561 }
562
563 /* If we made it to here, we found our context */
564
565 /* Initialize the next::method cache for this stash
566 if necessary */
567 selfmeta = HvMROMETA(selfstash);
568 if(!(nmcache = selfmeta->mro_nextmethod)) {
569 nmcache = selfmeta->mro_nextmethod = newHV();
570 }
571 else { /* Use the cached coderef if it exists */
572 HE* cache_entry = hv_fetch_ent(nmcache, sv, 0, 0);
573 if (cache_entry) {
574 SV* const val = HeVAL(cache_entry);
575 if(val == &PL_sv_undef) {
576 if(throw_nomethod)
577 Perl_croak(aTHX_ "No next::method '%s' found for %s", subname, hvname);
578 XSRETURN_EMPTY;
579 }
580 mXPUSHs(newRV_inc(val));
581 XSRETURN(1);
582 }
583 }
584
585 /* beyond here is just for cache misses, so perf isn't as critical */
586
587 stashname_len = subname - fq_subname - 2;
588 stashname = newSVpvn_flags(fq_subname, stashname_len, SVs_TEMP);
589
590 /* has ourselves at the top of the list */
591 linear_av = S_mro_get_linear_isa_c3(aTHX_ selfstash, 0);
592
593 linear_svp = AvARRAY(linear_av);
594 entries = AvFILLp(linear_av) + 1;
595
596 /* Walk down our MRO, skipping everything up
597 to the contextually enclosing class */
598 while (entries--) {
599 SV * const linear_sv = *linear_svp++;
600 assert(linear_sv);
601 if(sv_eq(linear_sv, stashname))
602 break;
603 }
604
605 /* Now search the remainder of the MRO for the
606 same method name as the contextually enclosing
607 method */
608 if(entries > 0) {
609 while (entries--) {
610 SV * const linear_sv = *linear_svp++;
611 HV* curstash;
612 GV* candidate;
613 CV* cand_cv;
614
615 assert(linear_sv);
616 curstash = gv_stashsv(linear_sv, FALSE);
617
618 if (!curstash) {
619 if (ckWARN(WARN_SYNTAX))
620 Perl_warner(aTHX_ packWARN(WARN_SYNTAX), "Can't locate package %"SVf" for @%s::ISA",
621 (void*)linear_sv, hvname);
622 continue;
623 }
624
625 assert(curstash);
626
627 gvp = (GV**)hv_fetch(curstash, subname, subname_len, 0);
628 if (!gvp) continue;
629
630 candidate = *gvp;
631 assert(candidate);
632
633 if (SvTYPE(candidate) != SVt_PVGV)
634 gv_init(candidate, curstash, subname, subname_len, TRUE);
635
636 /* Notably, we only look for real entries, not method cache
637 entries, because in C3 the method cache of a parent is not
638 valid for the child */
639 if (SvTYPE(candidate) == SVt_PVGV && (cand_cv = GvCV(candidate)) && !GvCVGEN(candidate)) {
640 SvREFCNT_inc_simple_void_NN(MUTABLE_SV(cand_cv));
59d8e2ce 641 (void)hv_store_ent(nmcache, sv, MUTABLE_SV(cand_cv), 0);
b2685f0c 642 mXPUSHs(newRV_inc(MUTABLE_SV(cand_cv)));
643 XSRETURN(1);
644 }
645 }
646 }
647
59d8e2ce 648 (void)hv_store_ent(nmcache, sv, &PL_sv_undef, 0);
b2685f0c 649 if(throw_nomethod)
650 Perl_croak(aTHX_ "No next::method '%s' found for %s", subname, hvname);
651 XSRETURN_EMPTY;
652
653BOOT:
654 Perl_mro_register(aTHX_ &c3_alg);