File Coverage

Tail.xs
Criterion Covered Total %
statement 95 119 79.8
branch 55 94 58.5
condition n/a
subroutine n/a
pod n/a
total 150 213 70.4


line stmt bran cond sub pod time code
1             /* ex: set sw=4 et: */
2              
3             #include "EXTERN.h"
4             #include "perl.h"
5             #include "XSUB.h"
6              
7             #define NEED_sv_2pv_flags
8             #include "ppport.h"
9              
10             #ifndef AvREIFY_only
11             #define AvREIFY_only(av) (AvREAL_off(av), AvREIFY_on(av))
12             #endif
13              
14             #include "hook_op_check_entersubforcv.h"
15              
16 0           STATIC OP * error_op (pTHX) {
17 0           croak("panic: tail call modifier called as subroutine");
18             }
19              
20              
21             STATIC OP *
22 41046           goto_entersub (pTHX) {
23 41046           dVAR; dSP; dMARK; dPOPss;
24             GV *gv;
25             CV *cv;
26             AV *av;
27 41046           IV items = SP - MARK;
28 41046           IV cxix = cxstack_ix;
29 41046           PERL_CONTEXT *cx = NULL;
30              
31 41048 50         while ( cxix > 0 ) {
32 41048 100         if ( CxTYPE(&cxstack[cxix]) == CXt_SUB ) {
33 41046           cx = &cxstack[cxix];
34 41046           break;
35             } else {
36 2           cxix--;
37             }
38             }
39              
40 41046 50         if (cx == NULL)
41 0           DIE(aTHX_ "Can't goto subroutine outside a subroutine");
42              
43             /* this first steaming hunk of cargo cult is copypasted from entersub...
44             * it's pretty the original but the ENTER/LEAVE or the actual execution */
45              
46 41046 50         if (!sv)
47 0           DIE(aTHX_ "Not a CODE reference");
48              
49 41046           switch (SvTYPE(sv)) {
50             /* This is overwhelming the most common case: */
51             case SVt_PVGV:
52 41036 50         if (!isGV_with_GP(sv))
    50          
    0          
53 0           DIE(aTHX_ "Not a CODE reference");
54 41036 50         if (!(cv = GvCVu((const GV *)sv))) {
    100          
55             HV *stash;
56 2           cv = sv_2cv(sv, &stash, &gv, 0);
57             }
58 41036 100         if (!cv) {
59 2           goto try_autoload;
60             }
61 41034           break;
62             default:
63 4 100         if (!SvROK(sv)) {
64             const char *sym;
65             STRLEN len;
66 1 50         if (SvGMAGICAL(sv)) {
67 0           mg_get(sv);
68 0 0         if (SvROK(sv))
69 0           goto got_rv;
70 0 0         if (SvPOKp(sv)) {
71 0           sym = SvPVX_const(sv);
72 0           len = SvCUR(sv);
73             } else {
74 0           sym = NULL;
75 0           len = 0;
76             }
77             }
78             else {
79 1 50         sym = SvPV_const(sv, len);
80             }
81 1 50         if (!sym)
82 0           DIE(aTHX_ PL_no_usym, "a subroutine");
83 1 50         if (PL_op->op_private & HINT_STRICT_REFS)
84 0           DIE(aTHX_ "Can't use string (\"%.32s\") as %s ref while \"strict refs\" in use",
85             sym, "a subroutine");
86 1           cv = get_cv(sym, GV_ADD|SvUTF8(sv));
87 1           break;
88             }
89             got_rv:
90             {
91 3           SV * const * sp = &sv; /* Used in tryAMAGICunDEREF macro. */
92 3           tryAMAGICunDEREF(to_cv);
93             }
94 3           cv = (CV *)SvRV(sv);
95 3 100         if (SvTYPE(cv) == SVt_PVCV)
96 2           break;
97             /* FALL THROUGH */
98             case SVt_PVHV:
99             case SVt_PVAV:
100 1           DIE(aTHX_ "Not a CODE reference");
101             /* This is the second most common case: */
102             case SVt_PVCV:
103 6           cv = (CV *)sv;
104 6           break;
105             }
106              
107             retry:
108 41044 50         if (!CvROOT(cv) && !CvXSUB(cv)) {
    0          
109             GV* autogv;
110             SV* sub_name;
111              
112             /* anonymous or undef'd function leaves us no recourse */
113 0 0         if (CvANON(cv) || !(gv = CvGV(cv)))
    0          
114 0           DIE(aTHX_ "Undefined subroutine called");
115              
116             /* autoloaded stub? */
117 0 0         if (cv != GvCV(gv)) {
118 0           cv = GvCV(gv);
119             }
120             /* should call AUTOLOAD now? */
121             else {
122             try_autoload:
123 2 100         if ((autogv = gv_autoload4(GvSTASH(gv), GvNAME(gv), GvNAMELEN(gv),
124             FALSE)))
125             {
126 1           cv = GvCV(autogv);
127             }
128             /* sorry */
129             else {
130 1           sub_name = sv_newmortal();
131 1           gv_efullname3(sub_name, gv, NULL);
132 1           DIE(aTHX_ "Undefined subroutine &%"SVf" called", SVfARG(sub_name));
133             }
134             }
135 1 50         if (!cv)
136 0           DIE(aTHX_ "Not a CODE reference");
137 1           goto retry;
138             }
139              
140              
141             /* this next steaming hunk of cargo cult is the code that sets up @_ in
142             * entersub. We set it up so that defgv is pointing at the pushed args as
143             * set up by the entersub call, this will let pp_goto work unmodified */
144              
145             #if PERL_VERSION_GE(5,23,8)
146 41044           av = MUTABLE_AV(PAD_SVl(0));
147             #else
148             av = cx->blk_sub.argarray;
149             #endif
150              
151             /* abandon @_ if it got reified */
152 41044 100         if (AvREAL(av)) {
153 6167           SvREFCNT_dec(av);
154 6167           av = newAV();
155 6167           AvREIFY_only(av);
156              
157             #if PERL_VERSION_LT(5,23,8)
158             cx->blk_sub.argarray = av;
159             #endif
160 6167           PAD_SVl(0) = (SV *)av;
161             }
162              
163 41044 100         if (GvAV(PL_defgv) != av) {
164 6167           AV *olddefav = GvAV(PL_defgv);
165 6167           SvREFCNT_inc((SV*)av);
166 6167           GvAV(PL_defgv) = av;
167 6167           SvREFCNT_dec((SV*)olddefav);
168             }
169              
170             /* copy items from the stack to defgv */
171 41044           ++MARK;
172              
173 41044           av_extend(av, items-1);
174              
175 41044 50         Copy(MARK,AvARRAY(av),items,SV*);
176 41044           AvFILLp(av) = items - 1;
177              
178 82057 100         while (MARK <= SP) {
179 41044 50         if (*MARK) {
180             /* if we find a lexical (PADMY) or a TEMP it's probably from
181             * the scope being destroyed, so we should reify @_ to increase
182             * the refcnt (this is suboptimal for tail foo($_[0]) or
183             * something but that's just a minor refcounting cost */
184              
185 41044 100         if ( SvTEMP(*MARK) || SvPADMY(*MARK) ) {
    100          
186             I32 key;
187              
188 31           key = AvMAX(av) + 1;
189 63 100         while (key > AvFILLp(av) + 1)
190 32           AvARRAY(av)[--key] = &PL_sv_undef;
191 286 100         while (key) {
192 255           SV * const sv = AvARRAY(av)[--key];
193             assert(sv);
194 255 50         if (sv != &PL_sv_undef)
195 255           SvREFCNT_inc_simple_void_NN(sv);
196             }
197 31           key = AvARRAY(av) - AvALLOC(av);
198 37 100         while (key)
199 6           AvALLOC(av)[--key] = &PL_sv_undef;
200 31           AvREIFY_off(av);
201 31           AvREAL_on(av);
202              
203 31           break;
204             }
205             }
206 41013           MARK++;
207             }
208              
209 41044           SP -= items;
210              
211             /* finally, execute goto. goto uses a ref to the cv, and takes the args out
212             * of the context stack frame */
213              
214 41044 50         PUSHMARK(SP);
215 41044 50         XPUSHs(sv_2mortal(newRV_inc((SV *)cv)));
216 41044           PUTBACK;
217              
218 41044           return PL_ppaddr[OP_GOTO](aTHX);
219             }
220              
221             STATIC OP *
222 36           convert_to_tailcall (pTHX_ OP *o, CV *cv, void *user_data) {
223             /* find the nested entersub */
224 36 50         UNOP *entersub = (UNOP *)OpSIBLING(((LISTOP *)cUNOPo->op_first)->op_first);
225              
226 36 50         if ( entersub->op_type != OP_ENTERSUB )
227 0           croak("The tail call modifier must be applied to a subroutine or method invocation");
228              
229 36 50         if ( OpHAS_SIBLING(entersub) && OpHAS_SIBLING(OpSIBLING(entersub)) )
    50          
    50          
230 0           croak("The tail call modifier must not be given additional arguments");
231              
232 36 50         if ( entersub->op_ppaddr == error_op )
233 0           croak("The tail call modifier cannot be applied to itself");
234              
235 36 50         if ( entersub->op_ppaddr != PL_ppaddr[OP_ENTERSUB] )
236 0           croak("The tail call modifier can only be applied to normal subroutine calls");
237              
238 36 100         if ( !(entersub->op_flags & OPf_STACKED) ) {
239 2 50         OpMORESIB_set( ((LISTOP *)cUNOPo->op_first)->op_first, OpSIBLING(entersub) );
240 2           OpMAYBESIB_set( entersub, NULL, NULL );
241 2           op_free(o);
242 2           entersub->op_private &= ~(OPpENTERSUB_INARGS|OPpENTERSUB_NOPAREN);
243 2           return newLOOPEX(OP_GOTO, (OP*)entersub);
244             }
245              
246             /* change the ppaddr of the inner entersub to become a custom goto op that
247             * takes its args like entersub does */
248 34           entersub->op_ppaddr = goto_entersub;
249 34           o->op_ppaddr = error_op;
250              
251             /* the rest is unmodified, this code will not actually be run (except for
252             * the pushmark), but allows deparsing etc to work correctly */
253 34           return o;
254             }
255              
256             MODULE = Sub::Call::Tail PACKAGE = Sub::Call::Tail
257             PROTOTYPES: disable
258              
259             BOOT:
260             {
261 4           hook_op_check_entersubforcv(get_cv("Sub::Call::Tail::tail", TRUE), convert_to_tailcall, NULL);
262             }
263