optimising yyparse: replace stack_size with a ptr
authorDavid Mitchell <davem@iabyn.com>
Sat, 3 Dec 2016 14:01:19 +0000 (14:01 +0000)
committerDavid Mitchell <davem@iabyn.com>
Mon, 5 Dec 2016 11:54:03 +0000 (11:54 +0000)
Makes testing whether the parser stack needs extending cheaper

parser.h
perly.c
sv.c
toke.c

index 9c22094..c5a59ab 100644 (file)
--- a/parser.h
+++ b/parser.h
@@ -42,9 +42,9 @@ typedef struct yy_parser {
     /* Number of tokens to shift before error messages enabled.  */
     int                    yyerrstatus;
 
-    int                    stack_size;
     int                    yylen;      /* length of active reduction */
     yy_stack_frame  *stack;    /* base of stack */
+    yy_stack_frame  *stack_max1;/* (top-1)th element of alloacted stack */
     yy_stack_frame  *ps;       /* current stack frame */
 
     /* lexer state */
diff --git a/perly.c b/perly.c
index 2d5857d..d20e4e3 100644 (file)
--- a/perly.c
+++ b/perly.c
@@ -273,17 +273,17 @@ Perl_yyparse (pTHX_ int gramtype)
     SAVEPPTR(parser->yylval.pval);
     SAVEINT(parser->yychar);
     SAVEINT(parser->yyerrstatus);
-    SAVEINT(parser->stack_size);
     SAVEINT(parser->yylen);
     SAVEVPTR(parser->stack);
+    SAVEVPTR(parser->stack_max1);
     SAVEVPTR(parser->ps);
 
     /* initialise state for this parse */
     parser->yychar = gramtype;
     parser->yyerrstatus = 0;
-    parser->stack_size = YYINITDEPTH;
     parser->yylen = 0;
     Newx(parser->stack, YYINITDEPTH, yy_stack_frame);
+    parser->stack_max1 = parser->stack + YYINITDEPTH - 1;
     ps = parser->ps = parser->stack;
     ps->state = 0;
     SAVEDESTRUCTOR_X(S_clear_yystack, parser);
@@ -300,20 +300,22 @@ Perl_yyparse (pTHX_ int gramtype)
     parser->yylen = 0;
 
     {
-       size_t size = ps - parser->stack + 1;
-
        /* grow the stack? We always leave 1 spare slot,
-        * in case of a '' -> 'foo' reduction */
+        * in case of a '' -> 'foo' reduction.
+         * Note that stack_max1 points to the (top-1)th allocated stack
+         * element to make this check fast */
 
-       if (size >= (size_t)parser->stack_size - 1) {
+       if (ps >= parser->stack_max1) {
+            Size_t pos = ps - parser->stack;
+            Size_t newsize = 2 * (parser->stack_max1 + 2 - parser->stack);
            /* this will croak on insufficient memory */
-           parser->stack_size *= 2;
-           Renew(parser->stack, parser->stack_size, yy_stack_frame);
-           ps = parser->ps = parser->stack + size -1;
+           Renew(parser->stack, newsize, yy_stack_frame);
+           ps = parser->ps = parser->stack + pos;
+           parser->stack_max1 = parser->stack + newsize - 1;
 
            YYDPRINTF((Perl_debug_log,
                            "parser stack size increased to %lu frames\n",
-                           (unsigned long int)parser->stack_size));
+                           (unsigned long int)newsize));
        }
     }
 
diff --git a/sv.c b/sv.c
index 6a17049..1eff364 100644 (file)
--- a/sv.c
+++ b/sv.c
@@ -13130,7 +13130,7 @@ Perl_parser_dup(pTHX_ const yy_parser *const proto, CLONE_PARAMS *const param)
     parser->old_parser = NULL;
     parser->stack = NULL;
     parser->ps = NULL;
-    parser->stack_size = 0;
+    parser->stack_max1 = 0;
     /* XXX parser->stack->state = 0; */
 
     /* XXX eventually, just Copy() most of the parser struct ? */
diff --git a/toke.c b/toke.c
index 1c88d8a..c09302b 100644 (file)
--- a/toke.c
+++ b/toke.c
@@ -705,8 +705,8 @@ Perl_lex_start(pTHX_ SV *line, PerlIO *rsfp, U32 flags)
     PL_parser = parser;
 
     parser->stack = NULL;
+    parser->stack_max1 = NULL;
     parser->ps = NULL;
-    parser->stack_size = 0;
 
     /* on scope exit, free this parser and restore any outer one */
     SAVEPARSER(parser);