ppport stuff to support 5.6.0
[gitmo/Class-C3-XS.git] / XS.xs
1
2 #include "EXTERN.h"
3 #include "perl.h"
4 #include "XSUB.h"
5
6 /* *********** ppport stuff */
7
8 #ifndef PERL_UNUSED_VAR
9 #  define PERL_UNUSED_VAR(x) ((void)x)
10 #endif
11
12 #if defined(PERL_GCC_PEDANTIC)
13 #  ifndef PERL_GCC_BRACE_GROUPS_FORBIDDEN
14 #    define PERL_GCC_BRACE_GROUPS_FORBIDDEN
15 #  endif
16 #endif
17
18 #if defined(__GNUC__) && !defined(PERL_GCC_BRACE_GROUPS_FORBIDDEN) && !defined(__cplusplus)
19 #  ifndef PERL_USE_GCC_BRACE_GROUPS
20 #    define PERL_USE_GCC_BRACE_GROUPS
21 #  endif
22 #endif
23
24 #ifndef SvREFCNT_inc
25 #  ifdef PERL_USE_GCC_BRACE_GROUPS
26 #    define SvREFCNT_inc(sv)            \
27       ({                                \
28           SV * const _sv = (SV*)(sv);   \
29           if (_sv)                      \
30                (SvREFCNT(_sv))++;       \
31           _sv;                          \
32       })
33 #  else
34 #    define SvREFCNT_inc(sv)    \
35           ((PL_Sv=(SV*)(sv)) ? (++(SvREFCNT(PL_Sv)),PL_Sv) : NULL)
36 #  endif
37 #endif
38
39 #ifndef dAX
40 #  define dAX                            I32 ax = MARK - PL_stack_base + 1
41 #endif
42
43 #ifndef dVAR
44 #  define dVAR                           dNOOP
45 #endif
46
47 #ifndef packWARN
48 #  define packWARN(a)                    (a)
49 #endif
50
51 /* *********** end ppport.h stuff */
52
53 /* Most of this code is backported from the bleadperl patch's
54    mro.c, and then modified to work with Class::C3's
55    internals.
56 */
57
58 AV*
59 __mro_linear_isa_c3(pTHX_ HV* stash, HV* cache, I32 level)
60 {
61     AV* retval;
62     GV** gvp;
63     GV* gv;
64     AV* isa;
65     const char* stashname;
66     STRLEN stashname_len;
67     I32 made_mortal_cache = 0;
68
69     assert(stash);
70     assert(HvAUX(stash));
71
72     stashname = HvNAME(stash);
73     stashname_len = strlen(stashname);
74     if (!stashname)
75       Perl_croak(aTHX_
76                  "Can't linearize anonymous symbol table");
77
78     if (level > 100)
79         Perl_croak(aTHX_ "Recursive inheritance detected in package '%s'",
80               stashname);
81
82     if(!cache) {
83         cache = (HV*)sv_2mortal((SV*)newHV());
84         made_mortal_cache = 1;
85     }
86     else {
87         SV** cache_entry = hv_fetch(cache, stashname, stashname_len, 0);
88         if(cache_entry)
89             return (AV*)SvREFCNT_inc(*cache_entry);
90     }
91
92     /* not in cache, make a new one */
93
94     gvp = (GV**)hv_fetch(stash, "ISA", 3, FALSE);
95     isa = (gvp && (gv = *gvp) && gv != (GV*)&PL_sv_undef) ? GvAV(gv) : NULL;
96     if(isa && AvFILLp(isa) >= 0) {
97         SV** seqs_ptr;
98         I32 seqs_items;
99         HV* const tails = (HV*)sv_2mortal((SV*)newHV());
100         AV* const seqs = (AV*)sv_2mortal((SV*)newAV());
101         I32* heads;
102
103         /* This builds @seqs, which is an array of arrays.
104            The members of @seqs are the MROs of
105            the members of @ISA, followed by @ISA itself.
106         */
107         I32 items = AvFILLp(isa) + 1;
108         SV** isa_ptr = AvARRAY(isa);
109         while(items--) {
110             SV* const isa_item = *isa_ptr++;
111             HV* const isa_item_stash = gv_stashsv(isa_item, 0);
112             if(!isa_item_stash) {
113                 /* if no stash, make a temporary fake MRO
114                    containing just itself */
115                 AV* const isa_lin = newAV();
116                 av_push(isa_lin, newSVsv(isa_item));
117                 av_push(seqs, (SV*)isa_lin);
118             }
119             else {
120                 /* recursion */
121                 AV* const isa_lin = __mro_linear_isa_c3(aTHX_ isa_item_stash, cache, level + 1);
122                 av_push(seqs, (SV*)isa_lin);
123             }
124         }
125         av_push(seqs, SvREFCNT_inc((SV*)isa));
126
127         /* This builds "heads", which as an array of integer array
128            indices, one per seq, which point at the virtual "head"
129            of the seq (initially zero) */
130         Newz(0xdead, heads, AvFILLp(seqs)+1, I32);
131
132         /* This builds %tails, which has one key for every class
133            mentioned in the tail of any sequence in @seqs (tail meaning
134            everything after the first class, the "head").  The value
135            is how many times this key appears in the tails of @seqs.
136         */
137         seqs_ptr = AvARRAY(seqs);
138         seqs_items = AvFILLp(seqs) + 1;
139         while(seqs_items--) {
140             AV* const seq = (AV*)*seqs_ptr++;
141             I32 seq_items = AvFILLp(seq);
142             if(seq_items > 0) {
143                 SV** seq_ptr = AvARRAY(seq) + 1;
144                 while(seq_items--) {
145                     SV* const seqitem = *seq_ptr++;
146                     HE* const he = hv_fetch_ent(tails, seqitem, 0, 0);
147                     if(!he) {
148                         hv_store_ent(tails, seqitem, newSViv(1), 0);
149                     }
150                     else {
151                         SV* const val = HeVAL(he);
152                         sv_inc(val);
153                     }
154                 }
155             }
156         }
157
158         /* Initialize retval to build the return value in */
159         retval = newAV();
160         av_push(retval, newSVpvn(stashname, stashname_len)); /* us first */
161
162         /* This loop won't terminate until we either finish building
163            the MRO, or get an exception. */
164         while(1) {
165             SV* cand = NULL;
166             SV* winner = NULL;
167             int s;
168
169             /* "foreach $seq (@seqs)" */
170             SV** const avptr = AvARRAY(seqs);
171             for(s = 0; s <= AvFILLp(seqs); s++) {
172                 SV** svp;
173                 AV * const seq = (AV*)(avptr[s]);
174                 SV* seqhead;
175                 if(!seq) continue; /* skip empty seqs */
176                 svp = av_fetch(seq, heads[s], 0);
177                 seqhead = *svp; /* seqhead = head of this seq */
178                 if(!winner) {
179                     HE* tail_entry;
180                     SV* val;
181                     /* if we haven't found a winner for this round yet,
182                        and this seqhead is not in tails (or the count
183                        for it in tails has dropped to zero), then this
184                        seqhead is our new winner, and is added to the
185                        final MRO immediately */
186                     cand = seqhead;
187                     if((tail_entry = hv_fetch_ent(tails, cand, 0, 0))
188                        && (val = HeVAL(tail_entry))
189                        && (SvIVX(val) > 0))
190                            continue;
191                     winner = newSVsv(cand);
192                     av_push(retval, winner);
193                     /* note however that even when we find a winner,
194                        we continue looping over @seqs to do housekeeping */
195                 }
196                 if(!sv_cmp(seqhead, winner)) {
197                     /* Once we have a winner (including the iteration
198                        where we first found him), inc the head ptr
199                        for any seq which had the winner as a head,
200                        NULL out any seq which is now empty,
201                        and adjust tails for consistency */
202
203                     const int new_head = ++heads[s];
204                     if(new_head > AvFILLp(seq)) {
205                         SvREFCNT_dec(avptr[s]);
206                         avptr[s] = NULL;
207                     }
208                     else {
209                         HE* tail_entry;
210                         SV* val;
211                         /* Because we know this new seqhead used to be
212                            a tail, we can assume it is in tails and has
213                            a positive value, which we need to dec */
214                         svp = av_fetch(seq, new_head, 0);
215                         seqhead = *svp;
216                         tail_entry = hv_fetch_ent(tails, seqhead, 0, 0);
217                         val = HeVAL(tail_entry);
218                         sv_dec(val);
219                     }
220                 }
221             }
222
223             /* if we found no candidates, we are done building the MRO.
224                !cand means no seqs have any entries left to check */
225             if(!cand) {
226                 Safefree(heads);
227                 break;
228             }
229
230             /* If we had candidates, but nobody won, then the @ISA
231                hierarchy is not C3-incompatible */
232             if(!winner) {
233                 /* we have to do some cleanup before we croak */
234
235                 SvREFCNT_dec(retval);
236                 Safefree(heads);
237
238                 Perl_croak(aTHX_ "Inconsistent hierarchy during C3 merge of class '%s': "
239                     "merging failed on parent '%s'", stashname, SvPV_nolen(cand));
240             }
241         }
242     }
243     else { /* @ISA was undefined or empty */
244         /* build a retval containing only ourselves */
245         retval = newAV();
246         av_push(retval, newSVpvn(stashname, stashname_len));
247     }
248
249     /* we don't want anyone modifying the cache entry but us,
250        and we do so by replacing it completely */
251     SvREADONLY_on(retval);
252
253     if(!made_mortal_cache) {
254         SvREFCNT_inc(retval);
255         hv_store(cache, stashname, stashname_len, (SV*)retval, 0);
256     }
257
258     return retval;
259 }
260
261 STATIC I32
262 __dopoptosub_at(const PERL_CONTEXT *cxstk, I32 startingblock) {
263     I32 i;
264     for (i = startingblock; i >= 0; i--) {
265         if(CxTYPE((PERL_CONTEXT*)(&cxstk[i])) == CXt_SUB) return i;
266     }
267     return i;
268 }
269
270 STATIC SV*
271 __nextcan(pTHX_ SV* self, I32 throw_nomethod)
272 {
273     register I32 cxix;
274     register const PERL_CONTEXT *ccstack = cxstack;
275     const PERL_SI *top_si = PL_curstackinfo;
276     HV* selfstash;
277     GV* cvgv;
278     SV *stashname;
279     const char *fq_subname;
280     const char *subname;
281     STRLEN fq_subname_len;
282     STRLEN stashname_len;
283     STRLEN subname_len;
284     SV* sv;
285     GV** gvp;
286     AV* linear_av;
287     SV** linear_svp;
288     HV* cstash;
289     GV* candidate = NULL;
290     CV* cand_cv = NULL;
291     const char *hvname;
292     I32 items;
293     HV* nmcache;
294     HE* cache_entry;
295     SV* cachekey;
296
297     if(sv_isobject(self))
298         selfstash = SvSTASH(SvRV(self));
299     else
300         selfstash = gv_stashsv(self, 0);
301
302     assert(selfstash);
303
304     hvname = HvNAME(selfstash);
305     if (!hvname)
306         Perl_croak(aTHX_ "Can't use anonymous symbol table for method lookup");
307
308     cxix = __dopoptosub_at(cxstack, cxstack_ix);
309
310     /* This block finds the contextually-enclosing fully-qualified subname,
311        much like looking at (caller($i))[3] until you find a real sub that
312        isn't ANON, etc */
313     for (;;) {
314         /* we may be in a higher stacklevel, so dig down deeper */
315         while (cxix < 0) {
316             if(top_si->si_type == PERLSI_MAIN)
317                 Perl_croak(aTHX_ "next::method/next::can/maybe::next::method must be used in method context");
318             top_si = top_si->si_prev;
319             ccstack = top_si->si_cxstack;
320             cxix = __dopoptosub_at(ccstack, top_si->si_cxix);
321         }
322
323         if(CxTYPE((PERL_CONTEXT*)(&ccstack[cxix])) != CXt_SUB
324           || (PL_DBsub && GvCV(PL_DBsub) && ccstack[cxix].blk_sub.cv == GvCV(PL_DBsub))) {
325             cxix = __dopoptosub_at(ccstack, cxix - 1);
326             continue;
327         }
328
329         {
330             const I32 dbcxix = __dopoptosub_at(ccstack, cxix - 1);
331             if (PL_DBsub && GvCV(PL_DBsub) && dbcxix >= 0 && ccstack[dbcxix].blk_sub.cv == GvCV(PL_DBsub)) {
332                 if(CxTYPE((PERL_CONTEXT*)(&ccstack[dbcxix])) != CXt_SUB) {
333                     cxix = dbcxix;
334                     continue;
335                 }
336             }
337         }
338
339         cvgv = CvGV(ccstack[cxix].blk_sub.cv);
340
341         if(!isGV(cvgv)) {
342             cxix = __dopoptosub_at(ccstack, cxix - 1);
343             continue;
344         }
345
346         /* we found a real sub here */
347         sv = sv_2mortal(newSV(0));
348
349         gv_efullname3(sv, cvgv, NULL);
350
351         fq_subname = SvPVX(sv);
352         fq_subname_len = SvCUR(sv);
353
354         subname = strrchr(fq_subname, ':');
355         if(!subname)
356             Perl_croak(aTHX_ "next::method/next::can/maybe::next::method cannot find enclosing method");
357
358         subname++;
359         subname_len = fq_subname_len - (subname - fq_subname);
360         if(subname_len == 8 && strEQ(subname, "__ANON__")) {
361             cxix = __dopoptosub_at(ccstack, cxix - 1);
362             continue;
363         }
364         break;
365     }
366
367     /* If we made it to here, we found our context */
368
369     /* cachekey = "objpkg|context::method::name" */
370     cachekey = sv_2mortal(newSVpv(hvname, 0));
371     sv_catpvn(cachekey, "|", 1);
372     sv_catsv(cachekey, sv);
373
374     nmcache = get_hv("next::METHOD_CACHE", 1);
375     if((cache_entry = hv_fetch_ent(nmcache, cachekey, 0, 0))) {
376         SV* val = HeVAL(cache_entry);
377         if(val == &PL_sv_undef) {
378             if(throw_nomethod)
379                 Perl_croak(aTHX_ "No next::method '%s' found for %s", subname, hvname);
380             return &PL_sv_undef;
381         }
382         return SvREFCNT_inc(val);
383     }
384
385     /* beyond here is just for cache misses, so perf isn't as critical */
386
387     stashname_len = subname - fq_subname - 2;
388     stashname = sv_2mortal(newSVpvn(fq_subname, stashname_len));
389
390     linear_av = __mro_linear_isa_c3(aTHX_ selfstash, NULL, 0);
391
392     linear_svp = AvARRAY(linear_av);
393     items = AvFILLp(linear_av) + 1;
394
395     while (items--) {
396         SV* const linear_sv = *linear_svp++;
397         assert(linear_sv);
398         if(sv_eq(linear_sv, stashname))
399             break;
400     }
401
402     if(items > 0) {
403         SV* sub_sv = sv_2mortal(newSVpv(subname, subname_len));
404         HV* cc3_mro = get_hv("Class::C3::MRO", 0);
405
406         while (items--) {
407             SV* const linear_sv = *linear_svp++;
408             assert(linear_sv);
409
410             if(cc3_mro) {
411                 HE* he_cc3_mro_class = hv_fetch_ent(cc3_mro, linear_sv, 0, 0);
412                 if(he_cc3_mro_class) {
413                     SV* cc3_mro_class_sv = HeVAL(he_cc3_mro_class);
414                     if(SvROK(cc3_mro_class_sv)) {
415                         HV* cc3_mro_class = (HV*)SvRV(cc3_mro_class_sv);
416                         SV** svp_cc3_mro_class_methods = hv_fetch(cc3_mro_class, "methods", 7, 0);
417                         if(svp_cc3_mro_class_methods) {
418                             SV* cc3_mro_class_methods_sv = *svp_cc3_mro_class_methods;
419                             if(SvROK(cc3_mro_class_methods_sv)) {
420                                 HV* cc3_mro_class_methods = (HV*)SvRV(cc3_mro_class_methods_sv);
421                                 if(hv_exists_ent(cc3_mro_class_methods, sub_sv, 0))
422                                     continue;
423                             }
424                         }
425                     }
426                 }
427             }
428
429             cstash = gv_stashsv(linear_sv, FALSE);
430
431             if (!cstash) {
432                 if (ckWARN(WARN_MISC))
433                     Perl_warner(aTHX_ packWARN(WARN_MISC), "Can't locate package %"SVf" for @%s::ISA",
434                         (void*)linear_sv, hvname);
435                 continue;
436             }
437
438             assert(cstash);
439
440             gvp = (GV**)hv_fetch(cstash, subname, subname_len, 0);
441             if (!gvp) continue;
442
443             candidate = *gvp;
444             assert(candidate);
445
446             if (SvTYPE(candidate) != SVt_PVGV)
447                 gv_init(candidate, cstash, subname, subname_len, TRUE);
448             if (SvTYPE(candidate) == SVt_PVGV && (cand_cv = GvCV(candidate)) && !GvCVGEN(candidate)) {
449                 SvREFCNT_dec(linear_av);
450                 SvREFCNT_inc((SV*)cand_cv);
451                 hv_store_ent(nmcache, newSVsv(cachekey), (SV*)cand_cv, 0);
452                 return (SV*)cand_cv;
453             }
454         }
455     }
456
457     SvREFCNT_dec(linear_av);
458     hv_store_ent(nmcache, newSVsv(cachekey), &PL_sv_undef, 0);
459     if(throw_nomethod)
460         Perl_croak(aTHX_ "No next::method '%s' found for %s", subname, hvname);
461     return &PL_sv_undef;
462 }
463
464 XS(XS_Class_C3_XS_calculateMRO);
465 XS(XS_Class_C3_XS_calculateMRO)
466 {
467     dVAR; dXSARGS;
468
469     SV* classname;
470     HV* class_stash;
471     HV* cache = NULL;
472     AV* res;
473     I32 res_items;
474     I32 ret_items;
475     SV** res_ptr;
476
477     if(items < 1 || items > 2)
478         croak("Usage: calculateMRO(classname[, cache])");
479
480     classname = ST(0);
481     if(items == 2) cache = (HV*)SvRV(ST(1));
482
483     class_stash = gv_stashsv(classname, 0);
484     if(!class_stash)
485         Perl_croak(aTHX_ "No such class: '%s'!", SvPV_nolen(classname));
486
487     res = __mro_linear_isa_c3(aTHX_ class_stash, cache, 0);
488
489     res_items = ret_items = AvFILLp(res) + 1;
490     res_ptr = AvARRAY(res);
491
492     SP -= items;
493
494     while(res_items--) {
495         SV* res_item = *res_ptr++;
496         XPUSHs(sv_2mortal(newSVsv(res_item)));
497     }
498     SvREFCNT_dec(res);
499
500     PUTBACK;
501
502     return;
503 }
504
505 XS(XS_Class_C3_XS_plsubgen);
506 XS(XS_Class_C3_XS_plsubgen)
507 {
508     dVAR; dXSARGS;
509
510     SP -= items;
511     XPUSHs(sv_2mortal(newSViv(PL_sub_generation)));
512     PUTBACK;
513     return;
514 }
515
516 XS(XS_Class_C3_XS_calc_mdt);
517 XS(XS_Class_C3_XS_calc_mdt)
518 {
519     dVAR; dXSARGS;
520
521     SV* classname;
522     HV* cache;
523     HV* class_stash;
524     AV* class_mro;
525     HV* our_c3mro; /* $Class::C3::MRO{classname} */
526     SV* has_ovf = NULL;
527     HV* methods;
528     I32 mroitems;
529
530     /* temps */
531     HV* hv;
532     HE* he;
533     SV** svp;
534
535     if(items < 1 || items > 2)
536         croak("Usage: calculate_method_dispatch_table(classname[, cache])");
537
538     classname = ST(0);
539     class_stash = gv_stashsv(classname, 0);
540     if(!class_stash)
541         Perl_croak(aTHX_ "No such class: '%s'!", SvPV_nolen(classname));
542
543     if(items == 2) cache = (HV*)SvRV(ST(1));
544
545     class_mro = __mro_linear_isa_c3(aTHX_ class_stash, cache, 0);
546
547     our_c3mro = newHV();
548     hv_store(our_c3mro, "MRO", 3, (SV*)newRV_noinc((SV*)class_mro), 0);
549
550     hv = get_hv("Class::C3::MRO", 1);
551     hv_store_ent(hv, classname, (SV*)newRV_noinc((SV*)our_c3mro), 0);
552
553     methods = newHV();
554
555     /* skip first entry */
556     mroitems = AvFILLp(class_mro);
557     svp = AvARRAY(class_mro) + 1;
558     while(mroitems--) {
559         SV* mro_class = *svp++;
560         HV* mro_stash = gv_stashsv(mro_class, 0);
561
562         if(!mro_stash) continue;
563
564         if(!has_ovf) {
565             SV** ovfp = hv_fetch(mro_stash, "()", 2, 0);
566             if(ovfp) has_ovf = *ovfp;
567         }
568
569         hv_iterinit(mro_stash);
570         while(he = hv_iternext(mro_stash)) {
571             CV* code;
572             SV* mskey;
573             SV* msval;
574             HE* ourent;
575             HV* meth_hash;
576             SV* orig;
577
578             mskey = hv_iterkeysv(he);
579             if(hv_exists_ent(methods, mskey, 0)) continue;
580
581             msval = hv_iterval(mro_stash, he);
582             if(SvTYPE(msval) != SVt_PVGV || !(code = GvCVu(msval)))
583                 continue;
584
585             if((ourent = hv_fetch_ent(class_stash, mskey, 0, 0))) {
586                 SV* val = HeVAL(ourent);
587                 if(val && SvTYPE(val) == SVt_PVGV && GvCVu(val))
588                     continue;
589             }
590
591             meth_hash = newHV();
592             orig = newSVsv(mro_class);
593             sv_catpvn(orig, "::", 2);
594             sv_catsv(orig, mskey);
595             hv_store(meth_hash, "orig", 4, orig, 0);
596             hv_store(meth_hash, "code", 4, newRV_inc((SV*)code), 0);
597             hv_store_ent(methods, mskey, newRV_noinc((SV*)meth_hash), 0);
598         }
599     }
600
601     hv_store(our_c3mro, "methods", 7, newRV_noinc((SV*)methods), 0);
602     if(has_ovf) hv_store(our_c3mro, "has_overload_fallback", 21, SvREFCNT_inc(has_ovf), 0);
603     XSRETURN_EMPTY;
604 }
605
606 XS(XS_next_can);
607 XS(XS_next_can)
608 {
609     dVAR; dXSARGS;
610
611     SV* self = ST(0);
612     SV* methcv = __nextcan(aTHX_ self, 0);
613
614     PERL_UNUSED_VAR(items);
615
616     if(methcv == &PL_sv_undef) {
617         ST(0) = &PL_sv_undef;
618     }
619     else {
620         ST(0) = sv_2mortal(newRV_inc(methcv));
621     }
622
623     XSRETURN(1);
624 }
625
626 XS(XS_next_method);
627 XS(XS_next_method)
628 {
629     dMARK;
630     dAX;
631     SV* self = ST(0);
632     SV* methcv = __nextcan(aTHX_ self, 1);
633
634     PL_markstack_ptr++;
635     call_sv(methcv, GIMME_V);
636 }
637
638 XS(XS_maybe_next_method);
639 XS(XS_maybe_next_method)
640 {
641     dMARK;
642     dAX;
643     SV* self = ST(0);
644     SV* methcv = __nextcan(aTHX_ self, 0);
645
646     if(methcv == &PL_sv_undef) {
647         ST(0) = &PL_sv_undef;
648         XSRETURN(1);
649     }
650
651     PL_markstack_ptr++;
652     call_sv(methcv, GIMME_V);
653 }
654
655 MODULE = Class::C3::XS  PACKAGE = Class::C3::XS
656
657 BOOT:
658     newXS("Class::C3::XS::calculateMRO", XS_Class_C3_XS_calculateMRO, __FILE__);
659     newXS("Class::C3::XS::_plsubgen", XS_Class_C3_XS_plsubgen, __FILE__);
660     newXS("Class::C3::XS::_calculate_method_dispatch_table", XS_Class_C3_XS_calc_mdt, __FILE__);
661     newXS("next::can", XS_next_can, __FILE__);
662     newXS("next::method", XS_next_method, __FILE__);
663     newXS("maybe::next::method", XS_maybe_next_method, __FILE__);
664