diff options
author | David Mitchell <davem@iabyn.com> | 2016-12-03 20:58:37 +0000 |
---|---|---|
committer | David Mitchell <davem@iabyn.com> | 2016-12-05 11:54:03 +0000 |
commit | b2c9b6ee5d402c923568f214f2e2606287c912d3 (patch) | |
tree | 0c5f13f99d2a2bd4ab5191c94ce68120a0a5e80c /perly.c | |
parent | ddbfb8f680c952529cc9849a6e461bbfeb703526 (diff) | |
download | perl-b2c9b6ee5d402c923568f214f2e2606287c912d3.tar.gz |
yyparse(): only check stack size in outer loop
Rather than checking before each individual shift whether the parse stack
needs extending, only check once per rule, making sure there's enough
space to shift all the items for the longest possible rule
Diffstat (limited to 'perly.c')
-rw-r--r-- | perly.c | 50 |
1 files changed, 28 insertions, 22 deletions
@@ -58,6 +58,15 @@ typedef signed char yysigned_char; # define YYSIZE_T size_t +/* the max number of RHS shifted elements that can make up a rule. + * This should really be auto-generated from the max value in yyr2[] + * but that involves extra work, so set it slightly higher than the + * current max, and assert each time yyr2[] is accessed. + * Used to determine if the parse stack needs extending. + */ + +#define YY_MAXRULE 15 + #define YYEOF 0 #define YYTERROR 1 @@ -275,7 +284,7 @@ Perl_yyparse (pTHX_ int gramtype) SAVEINT(parser->yyerrstatus); SAVEINT(parser->yylen); SAVEVPTR(parser->stack); - SAVEVPTR(parser->stack_max1); + SAVEVPTR(parser->stack_maxbase); SAVEVPTR(parser->ps); /* initialise state for this parse */ @@ -283,7 +292,7 @@ Perl_yyparse (pTHX_ int gramtype) parser->yyerrstatus = 0; parser->yylen = 0; Newx(parser->stack, YYINITDEPTH, yy_stack_frame); - parser->stack_max1 = parser->stack + YYINITDEPTH - 1; + parser->stack_maxbase = parser->stack + YYINITDEPTH - YY_MAXRULE; ps = parser->ps = parser->stack; ps->state = 0; SAVEDESTRUCTOR_X(S_clear_yystack, parser); @@ -291,35 +300,31 @@ Perl_yyparse (pTHX_ int gramtype) while (1) { /* main loop: shift some tokens, then reduce when possible */ + /* grow the stack to accommodate longest possible rule */ + if (ps >= parser->stack_maxbase) { + Size_t pos = ps - parser->stack; + Size_t newsize = 2 * (parser->stack_maxbase + YY_MAXRULE + - parser->stack); + /* this will croak on insufficient memory */ + Renew(parser->stack, newsize, yy_stack_frame); + ps = parser->ps = parser->stack + pos; + parser->stack_maxbase = parser->stack + newsize - YY_MAXRULE; + + YYDPRINTF((Perl_debug_log, + "parser stack size increased to %lu frames\n", + (unsigned long int)newsize)); + } + while (1) { /* shift a token, or quit when it's possible to reduce */ + assert(ps < parser->stack_maxbase + YY_MAXRULE); yystate = ps->state; YYDPRINTF ((Perl_debug_log, "Entering state %d\n", yystate)); parser->yylen = 0; - { - /* grow the stack? We always leave 1 spare slot, - * 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 (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 */ - 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)newsize)); - } - } - /* Do appropriate processing given the current state. */ /* Read a lookahead token if we need one and don't already have one. */ @@ -407,6 +412,7 @@ Perl_yyparse (pTHX_ int gramtype) /* yyn is the number of a rule to reduce with. */ parser->yylen = yyr2[yyn]; + assert(parser->yylen <= YY_MAXRULE); /* see defn of YY_MAXRULE above */ /* If YYLEN is nonzero, implement the default value of the action: "$$ = $1". |