diff mbox

[RFC,C++] Parser: Simplifying tentative firewall

Message ID 1482983015-23722-1-git-send-email-zhouzhouyi@gmail.com
State New
Headers show

Commit Message

Zhouyi Zhou Dec. 29, 2016, 3:43 a.m. UTC
I carefully examined the code of setting up tentative firewalls to guard 
current context in cp/parser.c recent days, and think the code could be 
simplified.

For example, in function cp_parser_start_tentative_firewall,
4427 cp_parser_parse_tentatively (parser); 
4428 cp_parser_commit_to_topmost_tentative_parse (parser);

A) cp_parser_parse_tentatively does following jobs:
1) create a new context
2) save current token
3) push deferring access

B) cp_parser_commit_to_topmost_tentative_parse does following jobs:
1) mark the new context as committed
2) pop current token 

Clearly saving and popping current token is unneccessary.

Push deferring access is also unneccessary after a carefull analysis:
In function cp_parser_parse_definitely,
error_occurred = cp_parser_error_occurred (parser) will always return
false for committed context, so pop_to_parent_deferring_access_checks
is always got called, while pushed deferring access in step (A) won't
affect the result wether or not the access check should delayed to 
parent access level.

Performance evaluation:
orig)  perf stat -e instructions:u ../gcc/cc1plus.orig g++.dg/template/friend28.C
59,171,628      instructions:u 
after) perf stat -e instructions:u ../gcc/cc1plus g++.dg/template/friend28.C
59,171,598      instructions:u

bootstrapped and checked on x86-64 

Signed-off-by: Zhouyi Zhou <yizhouzhou@ict.ac.cn>
---
 gcc/cp/ChangeLog | 14 ++++++++++++++
 gcc/cp/parser.c  | 22 ++++++++++++++++------
 2 files changed, 30 insertions(+), 6 deletions(-)
diff mbox

Patch

diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 7aca3ac..f095b1d 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,17 @@ 
+2016-12-29  Zhouyi Zhou  <yizhouzhou@ict.ac.cn>
+
+	Simplifying tentative firewalls
+	* parser.c (cp_parser_start_tentative_firewall): Simplifying 
+	tentative firewall so that it only do the necessary jobs to
+	guard current context.
+	* parser.c (cp_parser_end_tentative_firewall): Simplifying the
+	end of tentative firewall.
+	* parser.c (tentative_firewall::tentative_firewall): Simplifying 
+	tentative firewall so that it only do the necessary jobs to
+	guard current context.
+	* parser.c (tentative_firewall::~tentative_firewall): Simplifying 
+	the end of tentative firewall.
+	
 2016-12-24  Jakub Jelinek  <jakub@redhat.com>
 
 	PR middle-end/78901
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index e2a0a49..ebcc802 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -4424,8 +4424,8 @@  cp_parser_start_tentative_firewall (cp_parser *parser)
   if (!cp_parser_uncommitted_to_tentative_parse_p (parser))
     return 0;
 
-  cp_parser_parse_tentatively (parser);
-  cp_parser_commit_to_topmost_tentative_parse (parser);
+  parser->context = cp_parser_context_new (parser->context);
+  parser->context->status = CP_PARSER_STATUS_KIND_COMMITTED;
   return cp_lexer_token_position (parser->lexer, false);
 }
 
@@ -4436,11 +4436,16 @@  static void
 cp_parser_end_tentative_firewall (cp_parser *parser, cp_token_position start,
 				  tree expr)
 {
+  cp_parser_context *context;
+
   if (!start)
     return;
 
   /* Finish the firewall level.  */
-  cp_parser_parse_definitely (parser);
+  context = parser->context;
+  parser->context = context->next;
+  context->next = cp_parser_context_free_list;
+  cp_parser_context_free_list = context;
   /* And remember the result of the parse for when we try again.  */
   cp_token *token = cp_lexer_token_at (parser->lexer, start);
   token->type = CPP_PREPARSED_EXPR;
@@ -4465,8 +4470,8 @@  struct tentative_firewall
        firewall and then an inner tentative parse.  */
     if ((set = cp_parser_uncommitted_to_tentative_parse_p (parser)))
       {
-	cp_parser_parse_tentatively (parser);
-	cp_parser_commit_to_topmost_tentative_parse (parser);
+	parser->context = cp_parser_context_new (parser->context);
+	parser->context->status = CP_PARSER_STATUS_KIND_COMMITTED;
 	cp_parser_parse_tentatively (parser);
       }
   }
@@ -4477,9 +4482,14 @@  struct tentative_firewall
       {
 	/* Finish the inner tentative parse and the firewall, propagating any
 	   uncommitted error state to the outer tentative parse.  */
+	cp_parser_context *context;
 	bool err = cp_parser_error_occurred (parser);
 	cp_parser_parse_definitely (parser);
-	cp_parser_parse_definitely (parser);
+	/* Finish the firewall level.  */
+	context = parser->context;
+	parser->context = context->next;
+	context->next = cp_parser_context_free_list;
+	cp_parser_context_free_list = context;
 	if (err)
 	  cp_parser_simulate_error (parser);
       }