This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
pp_return: optimise a couple of conditions
authorDavid Mitchell <davem@iabyn.com>
Thu, 11 Jun 2015 10:11:19 +0000 (11:11 +0100)
committerDavid Mitchell <davem@iabyn.com>
Fri, 19 Jun 2015 07:44:18 +0000 (08:44 +0100)
Change:

    if (cxix < 0) {
        A; return;
    }
    if (cxix < cxstack_ix)
        B;

to

    if (cxix < cxstack_ix) {
        if (cxix < 0) {
            A; return;
        }
        B;
    }

This is functionally the same, since cxstack_ix is always positive at
this point, and makes for a quicker code path (one less test and branch)
in the reasonably common case of a return from a sub which doesn't
have any extra nested contexts to pop.

pp_ctl.c

index e0caf6f..5726893 100644 (file)
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -2418,27 +2418,28 @@ PP(pp_return)
     dSP; dMARK;
     PERL_CONTEXT *cx;
     SV **oldsp;
-
     const I32 cxix = dopoptosub(cxstack_ix);
 
-    if (cxix < 0) {
-       if (CxMULTICALL(cxstack)) { /* In this case we must be in a
-                                    * sort block, which is a CXt_NULL
-                                    * not a CXt_SUB */
-           dounwind(0);
-            /* if we were in list context, we would have to splice out
-             * any junk before the return args, like we do in the general
-             * pp_return case, e.g.
-             *   sub f { for (junk1, junk2) { return arg1, arg2 }}
-             */
-            assert(cxstack[0].blk_gimme == G_SCALAR);
-           return 0;
-       }
-       else
-           DIE(aTHX_ "Can't return outside a subroutine");
-    }
-    if (cxix < cxstack_ix)
+    assert(cxstack_ix >= 0);
+    if (cxix < cxstack_ix) {
+        if (cxix < 0) {
+            if (CxMULTICALL(cxstack)) { /* In this case we must be in a
+                                         * sort block, which is a CXt_NULL
+                                         * not a CXt_SUB */
+                dounwind(0);
+                /* if we were in list context, we would have to splice out
+                 * any junk before the return args, like we do in the general
+                 * pp_return case, e.g.
+                 *   sub f { for (junk1, junk2) { return arg1, arg2 }}
+                 */
+                assert(cxstack[0].blk_gimme == G_SCALAR);
+                return 0;
+            }
+            else
+                DIE(aTHX_ "Can't return outside a subroutine");
+        }
        dounwind(cxix);
+    }
 
     cx = &cxstack[cxix];