C++ PATCH: Parser speedup
Mark Mitchell
mark@codesourcery.com
Mon Dec 30 16:13:00 GMT 2002
This patch gets me about 17% on Paolo's first test case.
Tested on i686-pc-linux-gnu, applied on the mainline.
--
Mark Mitchell mark@codesourcery.com
CodeSourcery, LLC http://www.codesourcery.com
2002-12-30 Mark Mitchell <mark@codesourcery.com>
* parser.c (cp_parser_context_free_list): New variable.
(cp_parser_context_new): Use it.
(cp_parser_error): Check return code from
cp_parser_simulate_error.
(cp_parser_simulate_error): Return a value.
(cp_parser_id_expression): Optimize common case.
(cp_parser_class_name): Likewise.
(cp_parser_class_specifier): Adjust call to
cp_parser_late_parsing_default_args.
(cp_parser_lookup_name): Optimize common case.
(cp_parser_late_parsing_for_member): Adjust call to
cp_parser_late_parsing_default_args.
(cp_parser_late_parsing_default_args): Add scope parameter.
(cp_parser_require): Avoid creating the error message unless it's
needed.
(cp_parser_parse_definitely): Place free'd contexts on the free
list.
Index: parser.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/parser.c,v
retrieving revision 1.6
diff -c -p -r1.6 parser.c
*** parser.c 30 Dec 2002 20:18:38 -0000 1.6
--- parser.c 31 Dec 2002 00:02:37 -0000
*************** typedef struct cp_parser_context GTY (()
*** 1196,1201 ****
--- 1196,1205 ----
static cp_parser_context *cp_parser_context_new
PARAMS ((cp_parser_context *));
+ /* Class variables. */
+
+ static GTY(()) cp_parser_context* cp_parser_context_free_list;
+
/* Constructors and destructors. */
/* Construct a new context. The context below this one on the stack
*************** cp_parser_context_new (next)
*** 1208,1215 ****
cp_parser_context *context;
/* Allocate the storage. */
! context = ((cp_parser_context *)
! ggc_alloc_cleared (sizeof (cp_parser_context)));
/* No errors have occurred yet in this context. */
context->status = CP_PARSER_STATUS_KIND_NO_ERROR;
/* If this is not the bottomost context, copy information that we
--- 1212,1227 ----
cp_parser_context *context;
/* Allocate the storage. */
! if (cp_parser_context_free_list != NULL)
! {
! /* Pull the first entry from the free list. */
! context = cp_parser_context_free_list;
! cp_parser_context_free_list = context->next;
! memset ((char *)context, 0, sizeof (*context));
! }
! else
! context = ((cp_parser_context *)
! ggc_alloc_cleared (sizeof (cp_parser_context)));
/* No errors have occurred yet in this context. */
context->status = CP_PARSER_STATUS_KIND_NO_ERROR;
/* If this is not the bottomost context, copy information that we
*************** static tree cp_parser_functional_cast
*** 1704,1710 ****
static void cp_parser_late_parsing_for_member
PARAMS ((cp_parser *, tree));
static void cp_parser_late_parsing_default_args
! PARAMS ((cp_parser *, tree));
static tree cp_parser_sizeof_operand
PARAMS ((cp_parser *, enum rid));
static bool cp_parser_declares_only_class_p
--- 1716,1722 ----
static void cp_parser_late_parsing_for_member
PARAMS ((cp_parser *, tree));
static void cp_parser_late_parsing_default_args
! (cp_parser *, tree, tree);
static tree cp_parser_sizeof_operand
PARAMS ((cp_parser *, enum rid));
static bool cp_parser_declares_only_class_p
*************** static bool cp_parser_committed_to_tenta
*** 1741,1747 ****
PARAMS ((cp_parser *));
static void cp_parser_error
PARAMS ((cp_parser *, const char *));
! static void cp_parser_simulate_error
PARAMS ((cp_parser *));
static void cp_parser_check_type_definition
PARAMS ((cp_parser *));
--- 1753,1759 ----
PARAMS ((cp_parser *));
static void cp_parser_error
PARAMS ((cp_parser *, const char *));
! static bool cp_parser_simulate_error
PARAMS ((cp_parser *));
static void cp_parser_check_type_definition
PARAMS ((cp_parser *));
*************** cp_parser_error (parser, message)
*** 2213,2236 ****
cp_parser *parser;
const char *message;
{
- /* Remember that we have issued an error. */
- cp_parser_simulate_error (parser);
/* Output the MESSAGE -- unless we're parsing tentatively. */
! if (!cp_parser_parsing_tentatively (parser)
! || cp_parser_committed_to_tentative_parse (parser))
error (message);
}
/* If we are parsing tentatively, remember that an error has occurred
! during this tentative parse. */
! static void
cp_parser_simulate_error (parser)
cp_parser *parser;
{
if (cp_parser_parsing_tentatively (parser)
&& !cp_parser_committed_to_tentative_parse (parser))
! parser->context->status = CP_PARSER_STATUS_KIND_ERROR;
}
/* This function is called when a type is defined. If type
--- 2225,2250 ----
cp_parser *parser;
const char *message;
{
/* Output the MESSAGE -- unless we're parsing tentatively. */
! if (!cp_parser_simulate_error (parser))
error (message);
}
/* If we are parsing tentatively, remember that an error has occurred
! during this tentative parse. Returns true if the error was
! simulated; false if a messgae should be issued by the caller. */
! static bool
cp_parser_simulate_error (parser)
cp_parser *parser;
{
if (cp_parser_parsing_tentatively (parser)
&& !cp_parser_committed_to_tentative_parse (parser))
! {
! parser->context->status = CP_PARSER_STATUS_KIND_ERROR;
! return true;
! }
! return false;
}
/* This function is called when a type is defined. If type
*************** cp_parser_id_expression (cp_parser *pars
*** 3117,3124 ****
cp_token *token;
tree id;
! /* We don't know yet whether or not this will be a
! template-id. */
cp_parser_parse_tentatively (parser);
/* Try a template-id. */
id = cp_parser_template_id (parser,
--- 3131,3146 ----
cp_token *token;
tree id;
! /* Peek at the next token. */
! token = cp_lexer_peek_token (parser->lexer);
!
! /* If it's an identifier, and the next token is not a "<", then
! we can avoid the template-id case. This is an optimization
! for this common case. */
! if (token->type == CPP_NAME
! && cp_lexer_peek_nth_token (parser->lexer, 2)->type != CPP_LESS)
! return cp_parser_identifier (parser);
!
cp_parser_parse_tentatively (parser);
/* Try a template-id. */
id = cp_parser_template_id (parser,
*************** cp_parser_id_expression (cp_parser *pars
*** 3128,3134 ****
if (cp_parser_parse_definitely (parser))
return id;
! /* Peek at the next token. */
token = cp_lexer_peek_token (parser->lexer);
switch (token->type)
--- 3150,3157 ----
if (cp_parser_parse_definitely (parser))
return id;
! /* Peek at the next token. (Changes in the token buffer may
! have invalidated the pointer obtained above.) */
token = cp_lexer_peek_token (parser->lexer);
switch (token->type)
*************** cp_parser_class_name (cp_parser *parser,
*** 11331,11337 ****
tree decl;
tree scope;
bool typename_p;
!
/* PARSER->SCOPE can be cleared when parsing the template-arguments
to a template-id, so we save it here. */
scope = parser->scope;
--- 11354,11369 ----
tree decl;
tree scope;
bool typename_p;
! cp_token *token;
!
! /* All class-names start with an identifier. */
! token = cp_lexer_peek_token (parser->lexer);
! if (token->type != CPP_NAME && token->type != CPP_TEMPLATE_ID)
! {
! cp_parser_error (parser, "expected class-name");
! return error_mark_node;
! }
!
/* PARSER->SCOPE can be cleared when parsing the template-arguments
to a template-id, so we save it here. */
scope = parser->scope;
*************** cp_parser_class_name (cp_parser *parser,
*** 11339,11359 ****
in a qualified name where the enclosing scope is type-dependent. */
typename_p = (typename_keyword_p && scope && TYPE_P (scope)
&& cp_parser_dependent_type_p (scope));
!
! /* We don't know whether what comes next is a template-id or
! not. */
! cp_parser_parse_tentatively (parser);
! /* Try a template-id. */
! decl = cp_parser_template_id (parser, template_keyword_p,
! check_dependency_p);
! if (cp_parser_parse_definitely (parser))
! {
! if (decl == error_mark_node)
! return error_mark_node;
! }
! else
{
- /* If it wasn't a template-id, try a simple identifier. */
tree identifier;
/* Look for the identifier. */
--- 11371,11381 ----
in a qualified name where the enclosing scope is type-dependent. */
typename_p = (typename_keyword_p && scope && TYPE_P (scope)
&& cp_parser_dependent_type_p (scope));
! /* Handle the common case (an identifier, but not a template-id)
! efficiently. */
! if (token->type == CPP_NAME
! && cp_lexer_peek_nth_token (parser->lexer, 2)->type != CPP_LESS)
{
tree identifier;
/* Look for the identifier. */
*************** cp_parser_class_name (cp_parser *parser,
*** 11385,11390 ****
--- 11407,11420 ----
check_dependency_p);
}
}
+ else
+ {
+ /* Try a template-id. */
+ decl = cp_parser_template_id (parser, template_keyword_p,
+ check_dependency_p);
+ if (decl == error_mark_node)
+ return error_mark_node;
+ }
decl = cp_parser_maybe_treat_template_as_class (decl, class_head_p);
*************** cp_parser_class_specifier (parser)
*** 11515,11521 ****
parser->default_arg_types;
parser->default_arg_types = TREE_CHAIN (parser->default_arg_types))
cp_parser_late_parsing_default_args
! (parser, TREE_PURPOSE (parser->default_arg_types));
/* Reverse the queue, so that we process it in the order the
functions were declared. */
--- 11545,11551 ----
parser->default_arg_types;
parser->default_arg_types = TREE_CHAIN (parser->default_arg_types))
cp_parser_late_parsing_default_args
! (parser, TREE_PURPOSE (parser->default_arg_types), NULL_TREE);
/* Reverse the queue, so that we process it in the order the
functions were declared. */
*************** cp_parser_lookup_name (parser, name, che
*** 13392,13400 ****
{
/* The error message we have to print is too complicated for
cp_parser_error, so we incorporate its actions directly. */
! cp_parser_simulate_error (parser);
! if (!cp_parser_parsing_tentatively (parser)
! || cp_parser_committed_to_tentative_parse (parser))
{
error ("reference to `%D' is ambiguous", name);
print_candidates (decl);
--- 13422,13428 ----
{
/* The error message we have to print is too complicated for
cp_parser_error, so we incorporate its actions directly. */
! if (!cp_parser_simulate_error (parser))
{
error ("reference to `%D' is ambiguous", name);
print_candidates (decl);
*************** cp_parser_late_parsing_for_member (parse
*** 14216,14226 ****
/* If there are default arguments that have not yet been processed,
take care of them now. */
! if (DECL_FUNCTION_MEMBER_P (member_function))
! push_nested_class (DECL_CONTEXT (member_function), 1);
! cp_parser_late_parsing_default_args (parser, TREE_TYPE (member_function));
! if (DECL_FUNCTION_MEMBER_P (member_function))
! pop_nested_class ();
/* If the body of the function has not yet been parsed, parse it
now. */
--- 14244,14253 ----
/* If there are default arguments that have not yet been processed,
take care of them now. */
! cp_parser_late_parsing_default_args (parser, TREE_TYPE (member_function),
! DECL_FUNCTION_MEMBER_P (member_function)
! ? DECL_CONTEXT (member_function)
! : NULL_TREE);
/* If the body of the function has not yet been parsed, parse it
now. */
*************** cp_parser_late_parsing_for_member (parse
*** 14276,14287 ****
}
/* TYPE is a FUNCTION_TYPE or METHOD_TYPE which contains a parameter
! with an unparsed DEFAULT_ARG. Parse those default args now. */
static void
! cp_parser_late_parsing_default_args (parser, type)
! cp_parser *parser;
! tree type;
{
cp_lexer *saved_lexer;
cp_token_cache *tokens;
--- 14303,14314 ----
}
/* TYPE is a FUNCTION_TYPE or METHOD_TYPE which contains a parameter
! with an unparsed DEFAULT_ARG. If non-NULL, SCOPE is the class in
! whose context name lookups in the default argument should occur.
! Parse the default args now. */
static void
! cp_parser_late_parsing_default_args (cp_parser *parser, tree type, tree scope)
{
cp_lexer *saved_lexer;
cp_token_cache *tokens;
*************** cp_parser_late_parsing_default_args (par
*** 14312,14318 ****
--- 14339,14349 ----
saved_local_variables_forbidden_p = parser->local_variables_forbidden_p;
parser->local_variables_forbidden_p = true;
/* Parse the assignment-expression. */
+ if (scope)
+ push_nested_class (scope, 1);
TREE_PURPOSE (parameters) = cp_parser_assignment_expression (parser);
+ if (scope)
+ pop_nested_class ();
/* Restore saved state. */
parser->lexer = saved_lexer;
*************** cp_parser_require (parser, type, token_d
*** 14450,14463 ****
return cp_lexer_consume_token (parser->lexer);
else
{
! dyn_string_t error_msg;
!
! /* Format the error message. */
! error_msg = dyn_string_new (0);
! dyn_string_append_cstr (error_msg, "expected ");
! dyn_string_append_cstr (error_msg, token_desc);
! cp_parser_error (parser, error_msg->s);
! dyn_string_delete (error_msg);
return NULL;
}
}
--- 14481,14489 ----
return cp_lexer_consume_token (parser->lexer);
else
{
! /* Output the MESSAGE -- unless we're parsing tentatively. */
! if (!cp_parser_simulate_error (parser))
! error ("expected %s", token_desc);
return NULL;
}
}
*************** cp_parser_parse_definitely (parser)
*** 14759,14773 ****
parser->context->deferred_access_checks
= chainon (parser->context->deferred_access_checks,
context->deferred_access_checks);
- return true;
}
/* Otherwise, if errors occurred, roll back our state so that things
are just as they were before we began the tentative parse. */
else
! {
! cp_lexer_rollback_tokens (parser->lexer);
! return false;
! }
}
/* Returns non-zero if we are parsing tentatively. */
--- 14785,14800 ----
parser->context->deferred_access_checks
= chainon (parser->context->deferred_access_checks,
context->deferred_access_checks);
}
/* Otherwise, if errors occurred, roll back our state so that things
are just as they were before we began the tentative parse. */
else
! cp_lexer_rollback_tokens (parser->lexer);
! /* Add the context to the front of the free list. */
! context->next = cp_parser_context_free_list;
! cp_parser_context_free_list = context;
!
! return !error_occurred;
}
/* Returns non-zero if we are parsing tentatively. */
More information about the Gcc-patches
mailing list