Chromium Code Reviews| Index: runtime/vm/parser.cc |
| diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc |
| index 10601210232485cf707819ca479d47609a9d26ce..fda2748d68ff3f2e5edd0d662b39dc0bec899e68 100644 |
| --- a/runtime/vm/parser.cc |
| +++ b/runtime/vm/parser.cc |
| @@ -526,6 +526,7 @@ struct MemberDesc { |
| Token::Kind operator_token; |
| const AbstractType* type; |
| intptr_t name_pos; |
| + intptr_t decl_begin_pos; |
| String* name; |
| // For constructors: NULL or name of redirected to constructor. |
| String* redirect_name; |
| @@ -764,6 +765,7 @@ void Parser::ParseFunction(ParsedFunction* parsed_function) { |
| case RawFunction::kConstructor: |
| // The call to a redirecting factory is redirected. |
| ASSERT(!func.IsRedirectingFactory()); |
| + parser.SkipFunctionPreamble(func); |
| node_sequence = parser.ParseFunc(func, default_parameter_values); |
| break; |
| case RawFunction::kImplicitGetter: |
| @@ -2835,7 +2837,6 @@ void Parser::ParseQualIdent(QualIdent* qual_ident) { |
| void Parser::ParseMethodOrConstructor(ClassDesc* members, MemberDesc* method) { |
| TRACE_PARSER("ParseMethodOrConstructor"); |
| ASSERT(CurrentToken() == Token::kLPAREN || method->IsGetter()); |
| - intptr_t method_pos = this->TokenPos(); |
| ASSERT(method->type != NULL); |
| ASSERT(method->name_pos > 0); |
| ASSERT(current_member_ == method); |
| @@ -3089,7 +3090,7 @@ void Parser::ParseMethodOrConstructor(ClassDesc* members, MemberDesc* method) { |
| method->has_abstract, |
| method->has_external, |
| current_class(), |
| - method_pos)); |
| + method->decl_begin_pos)); |
| func.set_result_type(*method->type); |
| func.set_end_token_pos(method_end_pos); |
| if (method->metadata_pos > 0) { |
| @@ -3285,6 +3286,7 @@ void Parser::ParseClassMemberDefinition(ClassDesc* members, |
| MemberDesc member; |
| current_member_ = &member; |
| member.metadata_pos = metadata_pos; |
| + member.decl_begin_pos = TokenPos(); |
| if ((CurrentToken() == Token::kEXTERNAL) && |
| (LookaheadToken(1) != Token::kLPAREN)) { |
| ConsumeToken(); |
| @@ -3874,6 +3876,7 @@ bool Parser::IsMixinTypedef() { |
| void Parser::ParseTypedef(const GrowableObjectArray& pending_classes) { |
| TRACE_PARSER("ParseTypedef"); |
| ExpectToken(Token::kTYPEDEF); |
| + const intptr_t decl_begin_pos = TokenPos(); |
| if (IsMixinTypedef()) { |
| ParseMixinTypedef(pending_classes); |
| @@ -3947,7 +3950,7 @@ void Parser::ParseTypedef(const GrowableObjectArray& pending_classes) { |
| /* is_abstract = */ false, |
| /* is_external = */ false, |
| function_type_alias, |
| - alias_name_pos)); |
| + decl_begin_pos)); |
| signature_function.set_result_type(result_type); |
| AddFormalParamsToFunction(&func_params, signature_function); |
| @@ -4337,6 +4340,7 @@ void Parser::ParseTopLevelVariable(TopLevel* top_level, |
| void Parser::ParseTopLevelFunction(TopLevel* top_level, |
| intptr_t metadata_pos) { |
| TRACE_PARSER("ParseTopLevelFunction"); |
| + const intptr_t decl_begin_pos = TokenPos(); |
| AbstractType& result_type = Type::Handle(Type::DynamicType()); |
| const bool is_static = true; |
| bool is_external = false; |
| @@ -4410,7 +4414,7 @@ void Parser::ParseTopLevelFunction(TopLevel* top_level, |
| /* is_abstract = */ false, |
| is_external, |
| current_class(), |
| - function_pos)); |
| + decl_begin_pos)); |
| func.set_result_type(result_type); |
| func.set_end_token_pos(function_end_pos); |
| AddFormalParamsToFunction(¶ms, func); |
| @@ -4429,6 +4433,7 @@ void Parser::ParseTopLevelFunction(TopLevel* top_level, |
| void Parser::ParseTopLevelAccessor(TopLevel* top_level, |
| intptr_t metadata_pos) { |
| TRACE_PARSER("ParseTopLevelAccessor"); |
| + const intptr_t decl_begin_pos = TokenPos(); |
| const bool is_static = true; |
| bool is_external = false; |
| bool is_patch = false; |
| @@ -4535,7 +4540,7 @@ void Parser::ParseTopLevelAccessor(TopLevel* top_level, |
| /* is_abstract = */ false, |
| is_external, |
| current_class(), |
| - accessor_pos)); |
| + decl_begin_pos)); |
| func.set_result_type(result_type); |
| func.set_end_token_pos(accessor_end_pos); |
| AddFormalParamsToFunction(¶ms, func); |
| @@ -10041,6 +10046,32 @@ void Parser::SkipFunctionLiteral() { |
| } |
| +// Skips function/method/constructor/getter/setter preambles until the formal |
| +// parameter list. It is enough to skip the tokens, since we have already |
| +// previously parsed the function. |
| +void Parser::SkipFunctionPreamble(const Function& func) { |
| + if (func.IsImplicitConstructor()) return; |
| + while (true) { |
| + if (CurrentToken() == Token::kLPAREN || |
| + CurrentToken() == Token::kARROW || |
| + CurrentToken() == Token::kSEMICOLON || |
| + CurrentToken() == Token::kLBRACE) { |
| + return; |
| + } |
| + // Case handles "native" keyword, but also return types of form |
| + // native.SomeType where native is the name of a library. |
| + if (CurrentToken() == Token::kIDENT && |
| + LookaheadToken(1) != Token::kPERIOD) { |
| + String* lit = CurrentLiteral(); |
| + if (lit->Equals("native")) { |
|
hausner
2013/08/13 15:40:11
I think you can speed this loop up by declaring a
Michael Lippautz (Google)
2013/08/13 18:07:34
Done.
|
| + return; |
| + } |
| + } |
| + ConsumeToken(); |
| + } |
| +} |
| + |
| + |
| void Parser::SkipListLiteral() { |
| if (CurrentToken() == Token::kINDEX) { |
| // Empty list literal. |