6 /* Most of this code is backported from the bleadperl patch's
7 mro.c, and then modified to work with Class::C3's
12 __mro_linear_isa_c3(pTHX_ HV* stash, HV* cache, I32 level)
18 const char* stashname;
20 I32 made_mortal_cache = 0;
25 stashname = HvNAME(stash);
26 stashname_len = strlen(stashname);
29 "Can't linearize anonymous symbol table");
32 Perl_croak(aTHX_ "Recursive inheritance detected in package '%s'",
36 cache = (HV*)sv_2mortal((SV*)newHV());
37 made_mortal_cache = 1;
40 SV** cache_entry = hv_fetch(cache, stashname, stashname_len, 0);
42 return (AV*)SvREFCNT_inc(*cache_entry);
45 /* not in cache, make a new one */
47 gvp = (GV**)hv_fetch(stash, "ISA", 3, FALSE);
48 isa = (gvp && (gv = *gvp) && gv != (GV*)&PL_sv_undef) ? GvAV(gv) : NULL;
50 if(isa && AvFILLp(isa) >= 0) {
53 HV* const tails = (HV*)sv_2mortal((SV*)newHV());
54 AV* const seqs = (AV*)sv_2mortal((SV*)newAV());
57 I32 items = AvFILLp(isa) + 1;
58 SV** isa_ptr = AvARRAY(isa);
60 SV* const isa_item = *isa_ptr++;
61 HV* const isa_item_stash = gv_stashsv(isa_item, 0);
63 AV* const isa_lin = newAV();
64 av_push(isa_lin, newSVsv(isa_item));
65 av_push(seqs, (SV*)isa_lin);
68 AV* const isa_lin = __mro_linear_isa_c3(aTHX_ isa_item_stash, cache, level + 1); /* recursion */
69 av_push(seqs, (SV*)isa_lin);
72 av_push(seqs, SvREFCNT_inc((SV*)isa));
74 /* This builds "heads", which as an array of integer array
75 indices, one per seq, which point at the virtual "head"
76 of the seq (initially zero) */
78 Newz(0xdead, heads, AvFILLp(seqs)+1, I32);
80 /* This builds %tails, which has one key for every class
81 mentioned in the tail of any sequence in @seqs (tail meaning
82 everything after the first class, the "head"). The value
83 is how many times this key appears in the tails of @seqs.
85 seqs_ptr = AvARRAY(seqs);
86 seqs_items = AvFILLp(seqs) + 1;
88 AV* const seq = (AV*)*seqs_ptr++;
89 I32 seq_items = AvFILLp(seq);
91 SV** seq_ptr = AvARRAY(seq) + 1;
93 SV* const seqitem = *seq_ptr++;
94 HE* const he = hv_fetch_ent(tails, seqitem, 0, 0);
96 hv_store_ent(tails, seqitem, newSViv(1), 0);
99 SV* const val = HeVAL(he);
106 /* Initialize retval to build the return value in */
108 av_push(retval, newSVpvn(stashname, stashname_len)); /* us first */
115 SV** const avptr = AvARRAY(seqs);
116 for(s = 0; s <= AvFILLp(seqs); s++) {
118 AV * const seq = (AV*)(avptr[s]);
121 svp = av_fetch(seq, heads[s], 0);
127 if((tail_entry = hv_fetch_ent(tails, cand, 0, 0))
128 && (val = HeVAL(tail_entry))
131 winner = newSVsv(cand);
132 av_push(retval, winner);
134 if(!sv_cmp(seqhead, winner)) {
135 const int new_head = ++heads[s];
136 if(new_head > AvFILLp(seq)) {
137 SvREFCNT_dec(avptr[s]);
143 /* Because we know this new seqhead used to be
144 a tail, we can assume it is in tails and has
145 a positive value, which we need to dec */
146 svp = av_fetch(seq, new_head, 0);
148 tail_entry = hv_fetch_ent(tails, seqhead, 0, 0);
149 val = HeVAL(tail_entry);
159 SvREFCNT_dec(retval);
161 Perl_croak(aTHX_ "Inconsistent hierarchy during C3 merge of class '%s': "
162 "merging failed on parent '%s'", stashname, SvPV_nolen(cand));
166 else { /* @ISA does not exist, or was empty */
168 av_push(retval, newSVpvn(stashname, stashname_len)); /* us first */
171 SvREADONLY_on(retval);
173 if(!made_mortal_cache) {
174 SvREFCNT_inc(retval);
175 hv_store(cache, stashname, stashname_len, (SV*)retval, 0);
182 __dopoptosub_at(const PERL_CONTEXT *cxstk, I32 startingblock) {
184 for (i = startingblock; i >= 0; i--) {
185 if(CxTYPE((PERL_CONTEXT*)(&cxstk[i])) == CXt_SUB) return i;
191 __nextcan(pTHX_ SV* self, I32 throw_nomethod)
194 register const PERL_CONTEXT *ccstack = cxstack;
195 const PERL_SI *top_si = PL_curstackinfo;
199 const char *fq_subname;
201 STRLEN fq_subname_len;
202 STRLEN stashname_len;
210 GV* candidate = NULL;
218 if(sv_isobject(self))
219 selfstash = SvSTASH(SvRV(self));
221 selfstash = gv_stashsv(self, 0);
225 hvname = HvNAME(selfstash);
227 Perl_croak(aTHX_ "Can't use anonymous symbol table for method lookup");
229 cxix = __dopoptosub_at(cxstack, cxstack_ix);
231 /* This block finds the contextually-enclosing fully-qualified subname,
232 much like looking at (caller($i))[3] until you find a real sub that
235 /* we may be in a higher stacklevel, so dig down deeper */
237 if(top_si->si_type == PERLSI_MAIN)
238 Perl_croak(aTHX_ "next::method/next::can/maybe::next::method must be used in method context");
239 top_si = top_si->si_prev;
240 ccstack = top_si->si_cxstack;
241 cxix = __dopoptosub_at(ccstack, top_si->si_cxix);
244 if(CxTYPE((PERL_CONTEXT*)(&ccstack[cxix])) != CXt_SUB
245 || (PL_DBsub && GvCV(PL_DBsub) && ccstack[cxix].blk_sub.cv == GvCV(PL_DBsub))) {
246 cxix = __dopoptosub_at(ccstack, cxix - 1);
251 const I32 dbcxix = __dopoptosub_at(ccstack, cxix - 1);
252 if (PL_DBsub && GvCV(PL_DBsub) && dbcxix >= 0 && ccstack[dbcxix].blk_sub.cv == GvCV(PL_DBsub)) {
253 if(CxTYPE((PERL_CONTEXT*)(&ccstack[dbcxix])) != CXt_SUB) {
260 cvgv = CvGV(ccstack[cxix].blk_sub.cv);
263 cxix = __dopoptosub_at(ccstack, cxix - 1);
267 /* we found a real sub here */
268 sv = sv_2mortal(newSV(0));
270 gv_efullname3(sv, cvgv, NULL);
272 fq_subname = SvPVX(sv);
273 fq_subname_len = SvCUR(sv);
275 subname = strrchr(fq_subname, ':');
277 Perl_croak(aTHX_ "next::method/next::can/maybe::next::method cannot find enclosing method");
280 subname_len = fq_subname_len - (subname - fq_subname);
281 if(subname_len == 8 && strEQ(subname, "__ANON__")) {
282 cxix = __dopoptosub_at(ccstack, cxix - 1);
288 /* If we made it to here, we found our context */
290 /* cachekey = "objpkg|context::method::name" */
291 cachekey = sv_2mortal(newSVpv(hvname, 0));
292 sv_catpvn(cachekey, "|", 1);
293 sv_catsv(cachekey, sv);
295 nmcache = get_hv("next::METHOD_CACHE", 1);
296 if((cache_entry = hv_fetch_ent(nmcache, cachekey, 0, 0))) {
297 SV* val = HeVAL(cache_entry);
298 if(val == &PL_sv_undef) {
300 Perl_croak(aTHX_ "No next::method '%s' found for %s", subname, hvname);
303 return SvREFCNT_inc(val);
306 /* beyond here is just for cache misses, so perf isn't as critical */
308 stashname_len = subname - fq_subname - 2;
309 stashname = sv_2mortal(newSVpvn(fq_subname, stashname_len));
311 linear_av = __mro_linear_isa_c3(aTHX_ selfstash, NULL, 0);
313 linear_svp = AvARRAY(linear_av);
314 items = AvFILLp(linear_av) + 1;
317 linear_sv = *linear_svp++;
319 if(sv_eq(linear_sv, stashname))
324 SV* sub_sv = sv_2mortal(newSVpv(subname, subname_len));
325 HV* cc3_mro = get_hv("Class::C3::MRO", 0);
328 linear_sv = *linear_svp++;
332 HE* he_cc3_mro_class = hv_fetch_ent(cc3_mro, linear_sv, 0, 0);
333 if(he_cc3_mro_class) {
334 SV* cc3_mro_class_sv = HeVAL(he_cc3_mro_class);
335 if(SvROK(cc3_mro_class_sv)) {
336 HV* cc3_mro_class = (HV*)SvRV(cc3_mro_class_sv);
337 SV** svp_cc3_mro_class_methods = hv_fetch(cc3_mro_class, "methods", 7, 0);
338 if(svp_cc3_mro_class_methods) {
339 SV* cc3_mro_class_methods_sv = *svp_cc3_mro_class_methods;
340 if(SvROK(cc3_mro_class_methods_sv)) {
341 HV* cc3_mro_class_methods = (HV*)SvRV(cc3_mro_class_methods_sv);
342 if(hv_exists_ent(cc3_mro_class_methods, sub_sv, 0))
350 cstash = gv_stashsv(linear_sv, FALSE);
353 if (ckWARN(WARN_MISC))
354 Perl_warner(aTHX_ packWARN(WARN_MISC), "Can't locate package %"SVf" for @%s::ISA",
355 (void*)linear_sv, hvname);
361 gvp = (GV**)hv_fetch(cstash, subname, subname_len, 0);
367 if (SvTYPE(candidate) != SVt_PVGV)
368 gv_init(candidate, cstash, subname, subname_len, TRUE);
369 if (SvTYPE(candidate) == SVt_PVGV && (cand_cv = GvCV(candidate)) && !GvCVGEN(candidate)) {
370 SvREFCNT_dec(linear_av);
371 SvREFCNT_inc((SV*)cand_cv);
372 hv_store_ent(nmcache, newSVsv(cachekey), (SV*)cand_cv, 0);
378 SvREFCNT_dec(linear_av);
379 hv_store_ent(nmcache, newSVsv(cachekey), &PL_sv_undef, 0);
381 Perl_croak(aTHX_ "No next::method '%s' found for %s", subname, hvname);
385 XS(XS_Class_C3_XS_calculateMRO);
386 XS(XS_Class_C3_XS_calculateMRO)
402 if(items < 1 || items > 2)
403 croak("Usage: calculateMRO(classname[, cache])");
406 if(items == 2) cache = (HV*)SvRV(ST(1));
408 class_stash = gv_stashsv(classname, 0);
410 Perl_croak(aTHX_ "No such class: '%s'!", SvPV_nolen(classname));
412 res = __mro_linear_isa_c3(aTHX_ class_stash, cache, 0);
414 res_items = ret_items = AvFILLp(res) + 1;
415 res_ptr = AvARRAY(res);
420 SV* res_item = *res_ptr++;
421 XPUSHs(sv_2mortal(newSVsv(res_item)));
430 XS(XS_Class_C3_XS_plsubgen);
431 XS(XS_Class_C3_XS_plsubgen)
440 XPUSHs(sv_2mortal(newSViv(PL_sub_generation)));
445 XS(XS_Class_C3_XS_calc_mdt);
446 XS(XS_Class_C3_XS_calc_mdt)
458 HV* our_c3mro; /* $Class::C3::MRO{classname} */
468 if(items < 1 || items > 2)
469 croak("Usage: calculate_method_dispatch_table(classname[, cache])");
472 class_stash = gv_stashsv(classname, 0);
474 Perl_croak(aTHX_ "No such class: '%s'!", SvPV_nolen(classname));
476 if(items == 2) cache = (HV*)SvRV(ST(1));
478 class_mro = __mro_linear_isa_c3(aTHX_ class_stash, cache, 0);
481 hv_store(our_c3mro, "MRO", 3, (SV*)newRV_noinc((SV*)class_mro), 0);
483 hv = get_hv("Class::C3::MRO", 1);
484 hv_store_ent(hv, classname, (SV*)newRV_noinc((SV*)our_c3mro), 0);
488 /* skip first entry */
489 mroitems = AvFILLp(class_mro);
490 svp = AvARRAY(class_mro) + 1;
492 SV* mro_class = *svp++;
493 HV* mro_stash = gv_stashsv(mro_class, 0);
495 if(!mro_stash) continue;
498 SV** ovfp = hv_fetch(mro_stash, "()", 2, 0);
499 if(ovfp) has_ovf = *ovfp;
502 hv_iterinit(mro_stash);
503 while(he = hv_iternext(mro_stash)) {
511 mskey = hv_iterkeysv(he);
512 if(hv_exists_ent(methods, mskey, 0)) continue;
514 msval = hv_iterval(mro_stash, he);
515 if(SvTYPE(msval) != SVt_PVGV || !(code = GvCVu(msval)))
518 if((ourent = hv_fetch_ent(class_stash, mskey, 0, 0))) {
519 SV* val = HeVAL(ourent);
520 if(val && SvTYPE(val) == SVt_PVGV && GvCVu(val))
525 orig = newSVsv(mro_class);
526 sv_catpvn(orig, "::", 2);
527 sv_catsv(orig, mskey);
528 hv_store(meth_hash, "orig", 4, orig, 0);
529 hv_store(meth_hash, "code", 4, newRV_inc((SV*)code), 0);
530 hv_store_ent(methods, mskey, newRV_noinc((SV*)meth_hash), 0);
534 hv_store(our_c3mro, "methods", 7, newRV_noinc((SV*)methods), 0);
535 if(has_ovf) hv_store(our_c3mro, "has_overload_fallback", 21, SvREFCNT_inc(has_ovf), 0);
549 SV* methcv = __nextcan(aTHX_ self, 0);
551 PERL_UNUSED_VAR(items);
553 if(methcv == &PL_sv_undef) {
554 ST(0) = &PL_sv_undef;
557 ST(0) = sv_2mortal(newRV_inc(methcv));
569 SV* methcv = __nextcan(aTHX_ self, 1);
572 call_sv(methcv, GIMME_V);
575 XS(XS_maybe_next_method);
576 XS(XS_maybe_next_method)
581 SV* methcv = __nextcan(aTHX_ self, 0);
583 if(methcv == &PL_sv_undef) {
584 ST(0) = &PL_sv_undef;
589 call_sv(methcv, GIMME_V);
592 MODULE = Class::C3::XS PACKAGE = Class::C3::XS
595 newXS("Class::C3::XS::calculateMRO", XS_Class_C3_XS_calculateMRO, __FILE__);
596 newXS("Class::C3::XS::_plsubgen", XS_Class_C3_XS_plsubgen, __FILE__);
597 newXS("Class::C3::XS::_calculate_method_dispatch_table", XS_Class_C3_XS_calc_mdt, __FILE__);
598 newXS("next::can", XS_next_can, __FILE__);
599 newXS("next::method", XS_next_method, __FILE__);
600 newXS("maybe::next::method", XS_maybe_next_method, __FILE__);