File Coverage

autobox.xs
Criterion Covered Total %
statement 152 182 83.5
branch 105 152 69.0
condition n/a
subroutine n/a
pod n/a
total 257 334 76.9


line stmt bran cond sub pod time code
1             #ifdef WIN32 /* Win32 doesn't get PERL_CORE, so use the next best thing */
2             #define PERL_NO_GET_CONTEXT
3             #endif
4              
5             #include "EXTERN.h"
6             #include "perl.h"
7              
8             /*
9             * chocolateboy 2009-02-08
10             *
11             * for binary compatibility (see perlapi.h), XS modules perform a function call to
12             * access each and every interpreter variable. So, for instance, an innocuous-looking
13             * reference to PL_op becomes:
14             *
15             * (*Perl_Iop_ptr(my_perl))
16             *
17             * This (obviously) impacts performance. Internally, PL_op is accessed as:
18             *
19             * my_perl->Iop
20             *
21             * (in threaded/multiplicity builds (see intrpvar.h)), which is significantly faster.
22             *
23             * defining PERL_CORE gets us the fast version, at the expense of a future maintenance release
24             * possibly breaking things: https://groups.google.com/group/perl.perl5.porters/browse_thread/thread/9ec0da3f02b3b5a
25             *
26             * Rather than globally defining PERL_CORE, which pokes its fingers into various headers, exposing
27             * internals we'd rather not see, just define it for XSUB.h, which includes
28             * perlapi.h, which imposes the speed limit.
29             */
30              
31             #ifdef WIN32 /* thanks to Andy Grundman for pointing out problems with this on ActivePerl >= 5.10 */
32             #include "XSUB.h"
33             #else /* not WIN32 */
34             #define PERL_CORE
35             #include "XSUB.h"
36             #undef PERL_CORE
37             #endif
38              
39             #define NEED_sv_2pv_flags
40             #include "ppport.h"
41              
42             #include "ptable.h"
43              
44             static PTABLE_t *AUTOBOX_OP_MAP = NULL;
45             static U32 AUTOBOX_SCOPE_DEPTH = 0;
46             static OP *(*autobox_old_check_entersub)(pTHX_ OP *op) = NULL;
47              
48             static SV * autobox_method_common(pTHX_ SV *method, U32 *hashp);
49             static const char * autobox_type(pTHX_ SV * const sv, STRLEN *len);
50             static void autobox_cleanup(pTHX_ void * unused);
51              
52             OP * autobox_check_entersub(pTHX_ OP *o);
53             OP * autobox_method_named(pTHX);
54             OP * autobox_method(pTHX);
55              
56             void auto_ref(pTHX_ OP *invocant, UNOP *parent, OP *prev);
57              
58             #define AUTOBOX_TYPE_RETURN(type) STMT_START { \
59             *len = (sizeof(type) - 1); return type; \
60             } STMT_END
61              
62 528           static const char *autobox_type(pTHX_ SV * const sv, STRLEN *len) {
63 528           switch (SvTYPE(sv)) {
64 0           case SVt_NULL:
65 0           AUTOBOX_TYPE_RETURN("UNDEF");
66              
67 126           case SVt_IV:
68             /*
69             * as of perl v5.10.1, references (e.g. \[]), which were previously
70             * SVt_RV, are now SVt_IV with the SVf_ROK flag set
71             */
72 126 50         if (SvROK(sv)) {
73 0           AUTOBOX_TYPE_RETURN("REF");
74             } else {
75 126           AUTOBOX_TYPE_RETURN("INTEGER");
76             }
77              
78 71           case SVt_NV:
79 71 50         if (SvIOK(sv) || SvUOK(sv)) { /* XXX not sure this is ever true */
    50          
80 0           AUTOBOX_TYPE_RETURN("INTEGER");
81             } else {
82 71           AUTOBOX_TYPE_RETURN("FLOAT");
83             }
84              
85 19           case SVt_PVIV:
86 19 100         if (SvIOK(sv) || SvUOK(sv)) {
    50          
87 16           AUTOBOX_TYPE_RETURN("INTEGER");
88             } else {
89 3           AUTOBOX_TYPE_RETURN("STRING");
90             }
91              
92 23           case SVt_PVNV:
93             /*
94             * integer before float:
95             * https://rt.cpan.org/Ticket/Display.html?id=46814
96             */
97 23 100         if (SvIOK(sv) || SvUOK(sv)) {
    50          
98 3           AUTOBOX_TYPE_RETURN("INTEGER");
99 20 100         } else if (SvNOK(sv)) {
100 17           AUTOBOX_TYPE_RETURN("FLOAT");
101             } else {
102 3           AUTOBOX_TYPE_RETURN("STRING");
103             }
104              
105             /*
106             * as of perl v5.10.1, this is an alias for SVt_IV (with the SVf_ROK
107             * flag set)
108             */
109             #if PERL_BCDVERSION < 0x5010001
110             case SVt_RV:
111             #endif
112              
113 118           case SVt_PV:
114             case SVt_PVMG:
115              
116             #ifdef SvVOK
117 118 50         if (SvVOK(sv)) {
    0          
118 0           AUTOBOX_TYPE_RETURN("VSTRING");
119             }
120             #endif
121              
122 118 50         if (SvROK(sv)) {
123 0           AUTOBOX_TYPE_RETURN("REF");
124             } else {
125 118           AUTOBOX_TYPE_RETURN("STRING");
126             }
127              
128             /*
129             * XXX this can actually represent any SV type
130             */
131 0           case SVt_PVLV:
132 0 0         if (SvROK(sv)) {
133 0           AUTOBOX_TYPE_RETURN("REF");
134 0 0         } else if (LvTYPE(sv) == 't' || LvTYPE(sv) == 'T') { /* tied lvalue */
    0          
135 0 0         if (SvIOK(sv) || SvUOK(sv)) {
    0          
136 0           AUTOBOX_TYPE_RETURN("INTEGER");
137 0 0         } else if (SvNOK(sv)) {
138 0           AUTOBOX_TYPE_RETURN("FLOAT");
139             } else {
140 0           AUTOBOX_TYPE_RETURN("STRING");
141             }
142             } else {
143 0           AUTOBOX_TYPE_RETURN("LVALUE");
144             }
145              
146 63           case SVt_PVAV:
147 63           AUTOBOX_TYPE_RETURN("ARRAY");
148              
149 51           case SVt_PVHV:
150 51           AUTOBOX_TYPE_RETURN("HASH");
151              
152 57           case SVt_PVCV:
153 57           AUTOBOX_TYPE_RETURN("CODE");
154              
155 0           case SVt_PVGV:
156 0           AUTOBOX_TYPE_RETURN("GLOB");
157              
158 0           case SVt_PVFM:
159 0           AUTOBOX_TYPE_RETURN("FORMAT");
160              
161 0           case SVt_PVIO:
162 0           AUTOBOX_TYPE_RETURN("IO");
163              
164             #ifdef SVt_BIND
165             case SVt_BIND:
166             AUTOBOX_TYPE_RETURN("BIND");
167             #endif
168              
169             #ifdef SVt_REGEXP
170             case SVt_REGEXP:
171             AUTOBOX_TYPE_RETURN("REGEXP");
172             #endif
173              
174 0           default:
175 0           AUTOBOX_TYPE_RETURN("UNKNOWN");
176             }
177             }
178              
179             /*
180             * convert array/hash invocants to arrayref/hashref, e.g.:
181             *
182             * @foo->bar -> (\@foo)->bar
183             */
184 25           void auto_ref(pTHX_ OP *invocant, UNOP *parent, OP *prev) {
185             #ifndef op_sibling_splice
186             OP *refgen;
187             #endif
188              
189             /*
190             * perlref:
191             *
192             * As a special case, "\(@foo)" returns a list of references to the
193             * contents of @foo, not a reference to @foo itself. Likewise for %foo,
194             * except that the key references are to copies (since the keys are just
195             * strings rather than full-fledged scalars).
196             *
197             * we don't want that (it results in the invocant being a reference to the
198             * last element in the list), so we toggle the parentheses off while creating
199             * the reference then toggle them back on in case they're needed elsewhere
200             *
201             */
202 25           bool toggled = FALSE;
203              
204 25 100         if (invocant->op_flags & OPf_PARENS) {
205 8           invocant->op_flags &= ~OPf_PARENS;
206 8           toggled = TRUE;
207             }
208              
209             #ifdef op_sibling_splice
210 25           op_sibling_splice(
211             (OP *)parent,
212             prev,
213             0,
214             newUNOP(
215             OP_REFGEN,
216             0,
217             op_sibling_splice(
218             (OP *)parent,
219             prev,
220             1,
221             NULL
222             )
223             )
224             );
225             #else
226             /* XXX if this (old?) way works, why do we need both? */
227             PERL_UNUSED_ARG(parent); /* silence warning on perl v5.8 */
228             refgen = newUNOP(OP_REFGEN, 0, invocant);
229             prev->op_sibling = refgen;
230             refgen->op_sibling = invocant->op_sibling;
231             invocant->op_sibling = NULL;
232             #endif
233              
234             /* Restore the parentheses in case something else expects them */
235 25 100         if (toggled) {
236 8           invocant->op_flags |= OPf_PARENS;
237             }
238 25           }
239              
240 2978           OP * autobox_check_entersub(pTHX_ OP *o) {
241             UNOP *parent;
242             OP *prev, *invocant, *cvop;
243             SV **svp;
244             HV *hh;
245 2978           bool has_bindings = FALSE;
246              
247             /*
248             * XXX note: perl adopts a convention of calling the OP `o` and has shortcut
249             * macros based on this convention like cUNOPo, among others. if the name
250             * changes, the macro will need to change as well e.g. to cUNOPx(op)
251             */
252              
253             /*
254             * work around a %^H scoping bug by checking that PL_hints (which is
255             * properly scoped) & an unused PL_hints bit (0x100000) is true
256             *
257             * XXX this is fixed in #33311:
258             *
259             * https://www.nntp.perl.org/group/perl.perl5.porters/2008/02/msg134131.html
260             */
261 2978 100         if ((PL_hints & 0x80020000) != 0x80020000) {
262 1565           goto done;
263             }
264              
265             /*
266             * the OP which yields the CV is the last OP in the ENTERSUB OP's list of
267             * children. navigate to it by following the `op_sibling` pointers from the
268             * first child in the list (the invocant)
269             */
270 1413 100         parent = OpHAS_SIBLING(cUNOPo->op_first) ? cUNOPo : ((UNOP *)cUNOPo->op_first);
271 1413           prev = parent->op_first;
272 1413 50         invocant = OpSIBLING(prev);
273              
274 3970 50         for (cvop = invocant; OpHAS_SIBLING(cvop); cvop = OpSIBLING(cvop));
    100          
275              
276             /*
277             * now we have the CV OP, we can check if it's a method lookup.
278             * bail out if it's not
279             */
280 1413 100         if ((cvop->op_type != OP_METHOD) && (cvop->op_type != OP_METHOD_NAMED)) {
    100          
281 672           goto done;
282             }
283              
284             /* bail out if the invocant is a bareword e.g. Foo->bar or Foo->$bar */
285 741 100         if ((invocant->op_type == OP_CONST) && (invocant->op_private & OPpCONST_BARE)) {
    100          
286 20           goto done;
287             }
288              
289             /*
290             * the bareword flag is not set on the invocants of the `import`, `unimport`
291             * and `VERSION` methods faked up by `use` and `no` [1]. we have no other way
292             * to detect if an OP_CONST invocant is a bareword for these methods,
293             * so we have no choice but to assume it is and bail out so that we don't
294             * break `use`, `no` etc.
295             *
296             * (this is documented: the solution/workaround is to use
297             * $native->autobox_class instead.)
298             *
299             * note: we exempt all invocant types from these methods rather than just
300             * the invocants we can't be sure about (i.e. OP_CONST). we *could* allow
301             * e.g. []->VERSION or {}->import, but we don't, for consistency. even if
302             * OP_CONST invocants had the correct bareword flags, it's far more likely
303             * to be a bug for e.g. []->VERSION to differ from ARRAY->VERSION than
304             * a deliberate feature. [2]
305             *
306             * likewise, we also exempt $native->can and $native->isa here, neither
307             * of which are well-defined as instance methods.
308             *
309             * [1] XXX this is a bug (in perl)
310             *
311             * [2] although if these barewords did have the correct flag, we could
312             * forward (non-bareword) calls to these methods to autobox_class
313             * automatically rather than requiring the user to do it manually
314             */
315 721 100         if (cvop->op_type == OP_METHOD_NAMED) {
316             /* SvPVX_const should be sane for the method name */
317 702           const char * method_name = SvPVX_const(((SVOP *)cvop)->op_sv);
318              
319 702           if (
320 702 100         strEQ(method_name, "can") ||
321 639 50         strEQ(method_name, "DOES") ||
322 639 100         strEQ(method_name, "import") ||
323 606 100         strEQ(method_name, "isa") ||
324 525 100         strEQ(method_name, "unimport") ||
325 504 100         strEQ(method_name, "VERSION")
326             ) {
327 205           goto done;
328             }
329             }
330              
331 516           hh = GvHV(PL_hintgv); /* the hints hash (%^H) */
332              
333             /* is there a bindings hashref for this scope? */
334 516           has_bindings = hh
335 516 50         && (svp = hv_fetch(hh, "autobox", 7, FALSE))
336 516 50         && *svp
337 1032 50         && SvROK(*svp);
    50          
338              
339 516 50         if (!has_bindings) {
340 0           goto done;
341             }
342              
343             /*
344             * if the invocant is an @array, %hash, @{ ... } or %{ ... }, then
345             * "auto-ref" it, i.e. the optree equivalent of inserting a backslash
346             * before it:
347             *
348             * @foo->bar -> (\@foo)->bar
349             */
350 516 100         switch (invocant->op_type) {
351 25           case OP_PADAV:
352             case OP_PADHV:
353             case OP_RV2AV:
354             case OP_RV2HV:
355 25           auto_ref(aTHX_ invocant, parent, prev);
356             }
357              
358 516           cvop->op_flags |= OPf_SPECIAL;
359 1032           cvop->op_ppaddr = cvop->op_type == OP_METHOD
360             ? autobox_method
361 516 100         : autobox_method_named;
362              
363 516           PTABLE_store(AUTOBOX_OP_MAP, cvop, SvRV(*svp));
364              
365 2978           done:
366 2978           return autobox_old_check_entersub(aTHX_ o);
367             }
368              
369             /* returns either the method, or NULL, meaning delegate to the original op */
370 508           static SV * autobox_method_common(pTHX_ SV * method, U32* hashp) {
371 508           SV * const invocant = *(PL_stack_base + TOPMARK + 1);
372             SV * packsv;
373             HV * autobox_bindings;
374             HV * stash;
375             const char * reftype; /* autobox_bindings key */
376             SV **svp; /* pointer to autobox_bindings value */
377 508           STRLEN typelen = 0, packlen = 0;
378             const char * packname;
379             GV * gv;
380              
381             /* if autobox isn't enabled (in scope) for this op, bail out */
382 508 50         if (!(PL_op->op_flags & OPf_SPECIAL)) {
383 0           return NULL;
384             }
385              
386             /*
387             * bail out if the invocant is NULL (not to be confused with undef), e.g.
388             * from a buggy XS module
389             */
390 508 50         if (!invocant) {
391 0           return NULL;
392             }
393              
394             /*
395             * if the invocant's an object (blessed reference), bail out.
396             *
397             * XXX don't use sv_isobject - we don't want to call SvGETMAGIC twice
398             */
399 508 100         if (SvROK(invocant) && SvOBJECT(SvRV(invocant))) {
    100          
400 10           return NULL;
401             }
402              
403             /* XXX do non-objects have magic attached? */
404 498 50         SvGETMAGIC(invocant);
    0          
405              
406             /* the "bindings hash", which maps the names of native types to package names */
407 498           autobox_bindings = (HV *)(PTABLE_fetch(AUTOBOX_OP_MAP, PL_op));
408              
409 498 50         if (!autobox_bindings) {
410 0           return NULL;
411             }
412              
413             /*
414             * the type is either the invocant's reftype(), a subtype of
415             * SCALAR if it's not a ref, or UNDEF if it's not defined
416             */
417 498 100         if (SvOK(invocant)) {
418 474           reftype = autobox_type(
419 474 100         aTHX_ (SvROK(invocant) ? SvRV(invocant) : invocant),
420             &typelen
421             );
422             } else {
423 24           reftype = "UNDEF";
424 24           typelen = sizeof("UNDEF") - 1;
425             }
426              
427 498           svp = hv_fetch(autobox_bindings, reftype, typelen, 0);
428              
429 498 100         if (!(svp && SvOK(*svp))) {
    50          
430 60           return NULL;
431             }
432              
433 438           packsv = *svp;
434 438           packname = SvPV_const(packsv, packlen);
435 438           stash = gv_stashpvn(packname, packlen, FALSE);
436              
437 438 100         if (hashp) { /* shortcut for simple names */
438 427           const HE * const he = hv_fetch_ent(stash, method, 0, *hashp);
439              
440 427 100         if (he) {
441             U32 cvgen;
442              
443             #ifdef HvMROMETA /* introduced in v5.10 */
444 422 50         cvgen = PL_sub_generation + HvMROMETA(stash)->cache_gen;
445             #else
446             cvgen = PL_sub_generation;
447             #endif
448              
449 422           gv = MUTABLE_GV(HeVAL(he));
450              
451             /*
452             * GvCVGEN(gv) is almost always 0, so the global and local cache
453             * invalidation (above) seldom comes into play
454             */
455 422 50         if (isGV(gv) && GvCV(gv) && (!GvCVGEN(gv) || GvCVGEN(gv) == cvgen)) {
    50          
    100          
    50          
456 422           return MUTABLE_SV(GvCV(gv));
457             }
458             }
459             }
460              
461             /*
462             * SvPV_nolen_const returns the method name as a const char *,
463             * stringifying names that are not strings (e.g. undef, SvIV,
464             * SvNV etc.) - see name.t
465             */
466 16 50         gv = gv_fetchmethod(
467             stash ? stash : (HV*)packsv,
468             SvPV_nolen_const(method)
469             );
470              
471 16 100         if (gv) {
472 13 50         return isGV(gv) ? MUTABLE_SV(GvCV(gv)) : MUTABLE_SV(gv);
473             }
474              
475 3           return NULL;
476             }
477              
478 19           OP* autobox_method(pTHX) {
479 19           dVAR; dSP;
480 19           SV * const sv = TOPs;
481             SV * cv;
482              
483 19 100         if (SvROK(sv)) {
484 8           cv = SvRV(sv);
485              
486 8 50         if (SvTYPE(cv) == SVt_PVCV) {
487 8           SETs(cv);
488 8           RETURN;
489             }
490             }
491              
492 11           cv = autobox_method_common(aTHX_ sv, NULL);
493              
494 11 100         if (cv) {
495 8           SETs(cv);
496 8           RETURN;
497             } else {
498 3           return PL_ppaddr[OP_METHOD](aTHXR);
499             }
500             }
501              
502 497           OP* autobox_method_named(pTHX) {
503 497           dVAR; dSP;
504 497           SV * const sv = cSVOP_sv;
505 497           U32 hash = SvSHARED_HASH(sv);
506             SV * cv;
507              
508 497           cv = autobox_method_common(aTHX_ sv, &hash);
509              
510 497 100         if (cv) {
511 427 50         XPUSHs(cv);
512 427           RETURN;
513             } else {
514 70           return PL_ppaddr[OP_METHOD_NAMED](aTHXR);
515             }
516             }
517              
518 23           static void autobox_cleanup(pTHX_ void * unused) {
519             PERL_UNUSED_ARG(unused); /* silence warning on perl v5.8 */
520              
521 23 50         if (AUTOBOX_OP_MAP) {
522 23           PTABLE_free(AUTOBOX_OP_MAP);
523 23           AUTOBOX_OP_MAP = NULL;
524             }
525 23           }
526              
527             MODULE = autobox PACKAGE = autobox
528              
529             PROTOTYPES: ENABLE
530              
531             BOOT:
532             /*
533             * XXX the BOOT section extends to the next blank line, so don't add one
534             * for readability
535             */
536             PERL_UNUSED_ARG(cv); /* silence warning on perl v5.8 */
537 23           AUTOBOX_OP_MAP = PTABLE_new();
538 23 50         if (AUTOBOX_OP_MAP) {
539 23           Perl_call_atexit(aTHX_ autobox_cleanup, NULL);
540             } else {
541 0           Perl_croak(aTHX_ "Can't initialize OP map");
542             }
543              
544             void
545             _enter()
546             PROTOTYPE:
547             CODE:
548             PERL_UNUSED_ARG(cv); /* silence warning on perl v5.8 */
549              
550 82 100         if (AUTOBOX_SCOPE_DEPTH > 0) {
551 9           ++AUTOBOX_SCOPE_DEPTH;
552             } else {
553 73           AUTOBOX_SCOPE_DEPTH = 1;
554             /*
555             * capture the check routine in scope when autobox is used.
556             * usually, this will be Perl_ck_subr, though, in principle,
557             * it could be a bespoke checker spliced in by another module.
558             */
559 73           autobox_old_check_entersub = PL_check[OP_ENTERSUB];
560 73           PL_check[OP_ENTERSUB] = autobox_check_entersub;
561             }
562              
563             void
564             _leave()
565             PROTOTYPE:
566             CODE:
567             PERL_UNUSED_ARG(cv); /* silence warning on perl v5.8 */
568              
569 82 50         if (AUTOBOX_SCOPE_DEPTH == 0) {
570 0           Perl_warn(aTHX_ "scope underflow");
571             }
572              
573 82 100         if (AUTOBOX_SCOPE_DEPTH > 1) {
574 9           --AUTOBOX_SCOPE_DEPTH;
575             } else {
576 73           AUTOBOX_SCOPE_DEPTH = 0;
577 73           PL_check[OP_ENTERSUB] = autobox_old_check_entersub;
578             }
579              
580             void
581             _scope()
582             PROTOTYPE:
583             CODE:
584             PERL_UNUSED_ARG(cv); /* silence warning on perl v5.8 */
585 107           XSRETURN_UV(PTR2UV(GvHV(PL_hintgv)));
586              
587             MODULE = autobox PACKAGE = autobox::universal
588              
589             SV *
590             type(SV * sv)
591             PROTOTYPE:$
592             PREINIT:
593 66 100         STRLEN len = 0;
594             const char *type;
595             CODE:
596             PERL_UNUSED_ARG(cv); /* silence warning on perl v5.8 */
597              
598 66 100         if (SvOK(sv)) {
599 54 100         type = autobox_type(aTHX_ (SvROK(sv) ? SvRV(sv) : sv), &len);
600 54           RETVAL = newSVpv(type, len);
601             } else {
602 12           RETVAL = newSVpv("UNDEF", sizeof("UNDEF") - 1);
603             }
604             OUTPUT:
605             RETVAL