make sv_2bool_flags() non-recursive on overload
authorDaniel Dragan <bulk88@hotmail.com>
Mon, 21 Oct 2013 14:43:06 +0000 (15:43 +0100)
committerDavid Mitchell <davem@iabyn.com>
Mon, 21 Oct 2013 14:43:06 +0000 (15:43 +0100)
When Perl_sv_2bool_flags() has an overloaded arg, it calls SvTRUE()
on the SV returned from the overload method. This indirectly calls
sv_2bool_flags() again.

Change it so that sv_2bool_flags() just iterates the new overload value
each time.

2 callsites were converted to gotos. A SvTRUE_common was expanded so goto
can be used.  This function's machine code size on VC2003 32 bits dropped
by 0x24 bytes after this patch.

embed.fnc
proto.h
sv.c

index 8ffecaf..ccb637b 100644 (file)
--- a/embed.fnc
+++ b/embed.fnc
@@ -1276,7 +1276,7 @@ Ap        |I32    |start_subparse |I32 is_format|U32 flags
 : Used in pp_ctl.c
 p      |void   |sub_crush_depth|NN CV* cv
 Amd    |bool   |sv_2bool       |NN SV *const sv
-Apd    |bool   |sv_2bool_flags |NN SV *const sv|const I32 flags
+Apd    |bool   |sv_2bool_flags |NN SV *sv|I32 flags
 Apd    |CV*    |sv_2cv         |NULLOK SV* sv|NN HV **const st|NN GV **const gvp \
                                |const I32 lref
 Apd    |IO*    |sv_2io         |NN SV *const sv
diff --git a/proto.h b/proto.h
index 54c6b4f..b81b526 100644 (file)
--- a/proto.h
+++ b/proto.h
@@ -3866,7 +3866,7 @@ PERL_CALLCONV void        Perl_sub_crush_depth(pTHX_ CV* cv)
 /* PERL_CALLCONV bool  sv_2bool(pTHX_ SV *const sv)
                        __attribute__nonnull__(pTHX_1); */
 
-PERL_CALLCONV bool     Perl_sv_2bool_flags(pTHX_ SV *const sv, const I32 flags)
+PERL_CALLCONV bool     Perl_sv_2bool_flags(pTHX_ SV *sv, I32 flags)
                        __attribute__nonnull__(pTHX_1);
 #define PERL_ARGS_ASSERT_SV_2BOOL_FLAGS        \
        assert(sv)
diff --git a/sv.c b/sv.c
index 2c272f2..489c5ec 100644 (file)
--- a/sv.c
+++ b/sv.c
@@ -3152,12 +3152,13 @@ contain SV_GMAGIC, then it does an mg_get() first.
 */
 
 bool
-Perl_sv_2bool_flags(pTHX_ SV *const sv, const I32 flags)
+Perl_sv_2bool_flags(pTHX_ SV *sv, I32 flags)
 {
     dVAR;
 
     PERL_ARGS_ASSERT_SV_2BOOL_FLAGS;
 
+    restart:
     if(flags & SV_GMAGIC) SvGETMAGIC(sv);
 
     if (!SvOK(sv))
@@ -3165,8 +3166,30 @@ Perl_sv_2bool_flags(pTHX_ SV *const sv, const I32 flags)
     if (SvROK(sv)) {
        if (SvAMAGIC(sv)) {
            SV * const tmpsv = AMG_CALLunary(sv, bool__amg);
-           if (tmpsv && (!SvROK(tmpsv) || (SvRV(tmpsv) != SvRV(sv))))
-               return cBOOL(SvTRUE(tmpsv));
+           if (tmpsv && (!SvROK(tmpsv) || (SvRV(tmpsv) != SvRV(sv)))) {
+                bool svb;
+                sv = tmpsv;
+                if(SvGMAGICAL(sv)) {
+                    flags = SV_GMAGIC;
+                    goto restart; /* call sv_2bool */
+                }
+                /* expanded SvTRUE_common(sv, (flags = 0, goto restart)) */
+                else if(!SvOK(sv)) {
+                    svb = 0;
+                }
+                else if(SvPOK(sv)) {
+                    svb = SvPVXtrue(sv);
+                }
+                else if((SvFLAGS(sv) & (SVf_IOK|SVf_NOK))) {
+                    svb = (SvIOK(sv) && SvIVX(sv) != 0)
+                        || (SvNOK(sv) && SvNVX(sv) != 0.0);
+                }
+                else {
+                    flags = 0;
+                    goto restart; /* call sv_2bool_nomg */
+                }
+                return cBOOL(svb);
+            }
        }
        return SvRV(sv) != 0;
     }