summaryrefslogtreecommitdiff
path: root/perly.c
diff options
context:
space:
mode:
authorDavid Mitchell <davem@iabyn.com>2016-12-03 20:58:37 +0000
committerDavid Mitchell <davem@iabyn.com>2016-12-05 11:54:03 +0000
commitb2c9b6ee5d402c923568f214f2e2606287c912d3 (patch)
tree0c5f13f99d2a2bd4ab5191c94ce68120a0a5e80c /perly.c
parentddbfb8f680c952529cc9849a6e461bbfeb703526 (diff)
downloadperl-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.c50
1 files changed, 28 insertions, 22 deletions
diff --git a/perly.c b/perly.c
index 8f3c5c8f02..af44956ff5 100644
--- a/perly.c
+++ b/perly.c
@@ -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".