File Coverage

hax/ckcall_constfold.c.inc
Criterion Covered Total %
statement 44 44 100.0
branch 33 50 66.0
condition n/a
subroutine n/a
pod n/a
total 77 94 81.9


line stmt bran cond sub pod time code
1             /* vi: set ft=c : */
2              
3 137           static bool op_is_const(OP *o)
4             {
5 137           switch(o->op_type) {
6             case OP_CONST:
7             return true;
8              
9 2           case OP_LIST:
10             {
11 2           OP *oelem = cLISTOPo->op_first;
12 2 50         if(oelem->op_type == OP_PUSHMARK)
13 2 50         oelem = OpSIBLING(oelem);
14 12 100         for(; oelem; oelem = OpSIBLING(oelem))
    100          
15 6 50         if(oelem->op_type != OP_CONST)
16             return false;
17             return true;
18             }
19              
20             default:
21             return false;
22             }
23             }
24              
25 143           static OP *ckcall_constfold(pTHX_ OP *o, GV *namegv, SV *ckobj)
26             {
27             assert(o->op_type == OP_ENTERSUB);
28              
29 143           OP *kid = cUNOPo->op_first;
30             /* The first kid is usually an ex-list whose ->op_first begins the actual args list */
31 143 50         if(kid->op_type == OP_NULL && kid->op_targ == OP_LIST)
    50          
32 143           kid = cUNOPx(kid)->op_first;
33              
34             /* First actual arg is likely a OP_PUSHMARK */
35 143 50         if(kid->op_type == OP_PUSHMARK)
36 143 50         kid = OpSIBLING(kid);
37             OP *firstarg = kid;
38              
39 276 50         for(; kid && OpSIBLING(kid); kid = OpSIBLING(kid)) {
    100          
    50          
40 137 100         if(op_is_const(kid))
41             continue;
42              
43             return o;
44             }
45              
46 139           CV *cv = GvCV(namegv);
47             assert(SvTYPE(cv) == SVt_PVCV);
48              
49             /* We've not rejected it now, so lets invoke it and inline the result */
50              
51             /* TODO: I tried invoking the actual optree by linking it, setting it as
52             * PL_op and invoking CALLRUNOPS(), but it seems the pad isn't set up
53             * correctly yet to permit this for OP_PADCV ops.
54             * Instead, we'll simulated it by PUSHs()ing ourselves
55             */
56              
57 139           dSP;
58 139           ENTER;
59 139           SAVETMPS;
60 139 50         PUSHMARK(SP);
61              
62 405 50         for(OP *oarg = firstarg; oarg && OpSIBLING(oarg); oarg = OpSIBLING(oarg)) {
    50          
    100          
    50          
63 133           switch(oarg->op_type) {
64 131           case OP_CONST:
65 131           PUSHs(cSVOPx(oarg)->op_sv);
66 131           break;
67              
68 2           case OP_LIST:
69             {
70 2           OP *oelem = cUNOPx(oarg)->op_first;
71 2 50         if(oelem->op_type == OP_PUSHMARK)
72 2 50         oelem = OpSIBLING(oelem);
73 12 100         for(; oelem; oelem = OpSIBLING(oelem)) {
74             assert(oelem->op_type == OP_CONST);
75 6 100         PUSHs(cSVOPx(oelem)->op_sv);
76             }
77             break;
78             }
79             }
80             }
81              
82 139           PUTBACK;
83              
84             /* TODO: Currently always presume scalar context */
85 139           I32 count = call_sv((SV *)cv, G_SCALAR|G_EVAL);
86 139           bool got_err = SvTRUE(GvSV(PL_errgv));
87              
88 139           SPAGAIN;
89              
90 139 50         SV *retval = SvREFCNT_inc(POPs);
91              
92 139           PUTBACK;
93              
94 139 50         FREETMPS;
95 139           LEAVE;
96              
97 139 100         if(got_err)
98             /* Error was raised; abort */
99             return o;
100              
101 138           op_free(o);
102              
103 138           o = newSVOP(OP_CONST, 0, retval);
104 138           return o;
105             }