OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/parser.h" | 5 #include "vm/parser.h" |
6 | 6 |
7 #include "lib/invocation_mirror.h" | 7 #include "lib/invocation_mirror.h" |
8 #include "platform/utils.h" | 8 #include "platform/utils.h" |
9 #include "vm/ast_transformer.h" | 9 #include "vm/ast_transformer.h" |
10 #include "vm/bootstrap.h" | 10 #include "vm/bootstrap.h" |
(...skipping 448 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
459 void Parser::ComputeCurrentToken() { | 459 void Parser::ComputeCurrentToken() { |
460 ASSERT(token_kind_ == Token::kILLEGAL); | 460 ASSERT(token_kind_ == Token::kILLEGAL); |
461 token_kind_ = tokens_iterator_.CurrentTokenKind(); | 461 token_kind_ = tokens_iterator_.CurrentTokenKind(); |
462 if (token_kind_ == Token::kERROR) { | 462 if (token_kind_ == Token::kERROR) { |
463 ReportError(TokenPos(), "%s", CurrentLiteral()->ToCString()); | 463 ReportError(TokenPos(), "%s", CurrentLiteral()->ToCString()); |
464 } | 464 } |
465 } | 465 } |
466 | 466 |
467 | 467 |
468 Token::Kind Parser::LookaheadToken(int num_tokens) { | 468 Token::Kind Parser::LookaheadToken(int num_tokens) { |
469 INC_STAT(I, num_tokens_lookahead, 1); | |
470 INC_STAT(I, num_token_checks, 1); | |
471 return tokens_iterator_.LookaheadTokenKind(num_tokens); | 469 return tokens_iterator_.LookaheadTokenKind(num_tokens); |
472 } | 470 } |
473 | 471 |
474 | 472 |
475 String* Parser::CurrentLiteral() const { | 473 String* Parser::CurrentLiteral() const { |
476 String& result = | 474 String& result = |
477 String::ZoneHandle(Z, tokens_iterator_.CurrentLiteral()); | 475 String::ZoneHandle(Z, tokens_iterator_.CurrentLiteral()); |
478 return &result; | 476 return &result; |
479 } | 477 } |
480 | 478 |
(...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
797 } | 795 } |
798 | 796 |
799 private: | 797 private: |
800 Zone* zone_; | 798 Zone* zone_; |
801 GrowableArray<const Field*> fields_; | 799 GrowableArray<const Field*> fields_; |
802 GrowableArray<const Function*> functions_; | 800 GrowableArray<const Function*> functions_; |
803 }; | 801 }; |
804 | 802 |
805 | 803 |
806 void Parser::ParseClass(const Class& cls) { | 804 void Parser::ParseClass(const Class& cls) { |
| 805 Thread* thread = Thread::Current(); |
| 806 Zone* zone = thread->zone(); |
| 807 const int64_t num_tokes_before = STAT_VALUE(thread, num_tokens_consumed); |
807 if (!cls.is_synthesized_class()) { | 808 if (!cls.is_synthesized_class()) { |
808 Thread* thread = Thread::Current(); | 809 ASSERT(thread->long_jump_base()->IsSafeToJump()); |
809 Zone* zone = thread->zone(); | |
810 CSTAT_TIMER_SCOPE(thread, parser_timer); | 810 CSTAT_TIMER_SCOPE(thread, parser_timer); |
811 ASSERT(thread->long_jump_base()->IsSafeToJump()); | |
812 const Script& script = Script::Handle(zone, cls.script()); | 811 const Script& script = Script::Handle(zone, cls.script()); |
813 const Library& lib = Library::Handle(zone, cls.library()); | 812 const Library& lib = Library::Handle(zone, cls.library()); |
814 Parser parser(script, lib, cls.token_pos()); | 813 Parser parser(script, lib, cls.token_pos()); |
815 parser.ParseClassDefinition(cls); | 814 parser.ParseClassDefinition(cls); |
816 } else if (cls.is_enum_class()) { | 815 } else if (cls.is_enum_class()) { |
817 Thread* thread = Thread::Current(); | 816 ASSERT(thread->long_jump_base()->IsSafeToJump()); |
818 Zone* zone = thread->zone(); | |
819 CSTAT_TIMER_SCOPE(thread, parser_timer); | 817 CSTAT_TIMER_SCOPE(thread, parser_timer); |
820 ASSERT(thread->long_jump_base()->IsSafeToJump()); | |
821 const Script& script = Script::Handle(zone, cls.script()); | 818 const Script& script = Script::Handle(zone, cls.script()); |
822 const Library& lib = Library::Handle(zone, cls.library()); | 819 const Library& lib = Library::Handle(zone, cls.library()); |
823 Parser parser(script, lib, cls.token_pos()); | 820 Parser parser(script, lib, cls.token_pos()); |
824 parser.ParseEnumDefinition(cls); | 821 parser.ParseEnumDefinition(cls); |
825 } | 822 } |
| 823 const int64_t num_tokes_after = STAT_VALUE(thread, num_tokens_consumed); |
| 824 INC_STAT(thread, num_class_tokens, num_tokes_after - num_tokes_before); |
826 } | 825 } |
827 | 826 |
828 | 827 |
829 RawObject* Parser::ParseFunctionParameters(const Function& func) { | 828 RawObject* Parser::ParseFunctionParameters(const Function& func) { |
830 ASSERT(!func.IsNull()); | 829 ASSERT(!func.IsNull()); |
831 Thread* thread = Thread::Current(); | 830 Thread* thread = Thread::Current(); |
832 Isolate* isolate = thread->isolate(); | 831 Isolate* isolate = thread->isolate(); |
833 StackZone stack_zone(thread); | 832 StackZone stack_zone(thread); |
834 Zone* zone = stack_zone.GetZone(); | 833 Zone* zone = stack_zone.GetZone(); |
835 LongJumpScope jump; | 834 LongJumpScope jump; |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
902 return false; | 901 return false; |
903 } | 902 } |
904 UNREACHABLE(); | 903 UNREACHABLE(); |
905 return false; | 904 return false; |
906 } | 905 } |
907 | 906 |
908 | 907 |
909 void Parser::ParseFunction(ParsedFunction* parsed_function) { | 908 void Parser::ParseFunction(ParsedFunction* parsed_function) { |
910 Thread* thread = parsed_function->thread(); | 909 Thread* thread = parsed_function->thread(); |
911 ASSERT(thread == Thread::Current()); | 910 ASSERT(thread == Thread::Current()); |
912 Isolate* isolate = thread->isolate(); | |
913 Zone* zone = thread->zone(); | 911 Zone* zone = thread->zone(); |
914 CSTAT_TIMER_SCOPE(thread, parser_timer); | 912 CSTAT_TIMER_SCOPE(thread, parser_timer); |
915 INC_STAT(isolate, num_functions_compiled, 1); | 913 INC_STAT(thread, num_functions_parsed, 1); |
916 VMTagScope tagScope(thread, VMTag::kCompileParseFunctionTagId, | 914 VMTagScope tagScope(thread, VMTag::kCompileParseFunctionTagId, |
917 FLAG_profile_vm); | 915 FLAG_profile_vm); |
918 | 916 |
919 ASSERT(thread->long_jump_base()->IsSafeToJump()); | 917 ASSERT(thread->long_jump_base()->IsSafeToJump()); |
920 ASSERT(parsed_function != NULL); | 918 ASSERT(parsed_function != NULL); |
921 const Function& func = parsed_function->function(); | 919 const Function& func = parsed_function->function(); |
922 const Script& script = Script::Handle(zone, func.script()); | 920 const Script& script = Script::Handle(zone, func.script()); |
923 Parser parser(script, parsed_function, func.token_pos()); | 921 Parser parser(script, parsed_function, func.token_pos()); |
924 SequenceNode* node_sequence = NULL; | 922 SequenceNode* node_sequence = NULL; |
925 switch (func.kind()) { | 923 switch (func.kind()) { |
(...skipping 23 matching lines...) Expand all Loading... |
949 case RawFunction::kImplicitGetter: | 947 case RawFunction::kImplicitGetter: |
950 ASSERT(!func.is_static()); | 948 ASSERT(!func.is_static()); |
951 node_sequence = parser.ParseInstanceGetter(func); | 949 node_sequence = parser.ParseInstanceGetter(func); |
952 break; | 950 break; |
953 case RawFunction::kImplicitSetter: | 951 case RawFunction::kImplicitSetter: |
954 ASSERT(!func.is_static()); | 952 ASSERT(!func.is_static()); |
955 node_sequence = parser.ParseInstanceSetter(func); | 953 node_sequence = parser.ParseInstanceSetter(func); |
956 break; | 954 break; |
957 case RawFunction::kImplicitStaticFinalGetter: | 955 case RawFunction::kImplicitStaticFinalGetter: |
958 node_sequence = parser.ParseStaticFinalGetter(func); | 956 node_sequence = parser.ParseStaticFinalGetter(func); |
959 INC_STAT(isolate, num_implicit_final_getters, 1); | 957 INC_STAT(thread, num_implicit_final_getters, 1); |
960 break; | 958 break; |
961 case RawFunction::kMethodExtractor: | 959 case RawFunction::kMethodExtractor: |
962 node_sequence = parser.ParseMethodExtractor(func); | 960 node_sequence = parser.ParseMethodExtractor(func); |
| 961 INC_STAT(thread, num_method_extractors, 1); |
963 break; | 962 break; |
964 case RawFunction::kNoSuchMethodDispatcher: | 963 case RawFunction::kNoSuchMethodDispatcher: |
965 node_sequence = | 964 node_sequence = |
966 parser.ParseNoSuchMethodDispatcher(func); | 965 parser.ParseNoSuchMethodDispatcher(func); |
967 break; | 966 break; |
968 case RawFunction::kInvokeFieldDispatcher: | 967 case RawFunction::kInvokeFieldDispatcher: |
969 node_sequence = | 968 node_sequence = |
970 parser.ParseInvokeFieldDispatcher(func); | 969 parser.ParseInvokeFieldDispatcher(func); |
971 break; | 970 break; |
972 case RawFunction::kIrregexpFunction: | 971 case RawFunction::kIrregexpFunction: |
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1191 if (parsed_function->has_finally_return_temp_var()) { | 1190 if (parsed_function->has_finally_return_temp_var()) { |
1192 body->scope()->AddVariable(parsed_function->finally_return_temp_var()); | 1191 body->scope()->AddVariable(parsed_function->finally_return_temp_var()); |
1193 } | 1192 } |
1194 // The instantiator is not required in a static expression. | 1193 // The instantiator is not required in a static expression. |
1195 ASSERT(!parser.IsInstantiatorRequired()); | 1194 ASSERT(!parser.IsInstantiatorRequired()); |
1196 | 1195 |
1197 return parsed_function; | 1196 return parsed_function; |
1198 } | 1197 } |
1199 | 1198 |
1200 | 1199 |
1201 RawObject* Parser::ParseFunctionFromSource(const Class& owning_class, | |
1202 const String& source) { | |
1203 Thread* thread = Thread::Current(); | |
1204 Isolate* isolate = thread->isolate(); | |
1205 StackZone stack_zone(thread); | |
1206 LongJumpScope jump; | |
1207 if (setjmp(*jump.Set()) == 0) { | |
1208 const String& uri = String::Handle(Symbols::New("dynamically-added")); | |
1209 const Script& script = Script::Handle( | |
1210 Script::New(uri, source, RawScript::kSourceTag)); | |
1211 const Library& owning_library = Library::Handle(owning_class.library()); | |
1212 const String& private_key = String::Handle(owning_library.private_key()); | |
1213 script.Tokenize(private_key); | |
1214 const intptr_t token_pos = 0; | |
1215 Parser parser(script, owning_library, token_pos); | |
1216 parser.is_top_level_ = true; | |
1217 parser.set_current_class(owning_class); | |
1218 const String& class_name = String::Handle(owning_class.Name()); | |
1219 ClassDesc members(stack_zone.GetZone(), | |
1220 owning_class, | |
1221 class_name, | |
1222 false, /* is_interface */ | |
1223 token_pos); | |
1224 const intptr_t metadata_pos = parser.SkipMetadata(); | |
1225 parser.ParseClassMemberDefinition(&members, metadata_pos); | |
1226 ASSERT(members.functions().length() == 1); | |
1227 const Function& func = *members.functions().At(0); | |
1228 func.set_eval_script(script); | |
1229 ParsedFunction* parsed_function = new ParsedFunction(thread, func); | |
1230 Parser::ParseFunction(parsed_function); | |
1231 return func.raw(); | |
1232 } else { | |
1233 const Error& error = Error::Handle(isolate->object_store()->sticky_error()); | |
1234 isolate->object_store()->clear_sticky_error(); | |
1235 return error.raw(); | |
1236 } | |
1237 UNREACHABLE(); | |
1238 return Object::null(); | |
1239 } | |
1240 | |
1241 | |
1242 SequenceNode* Parser::ParseStaticFinalGetter(const Function& func) { | 1200 SequenceNode* Parser::ParseStaticFinalGetter(const Function& func) { |
1243 TRACE_PARSER("ParseStaticFinalGetter"); | 1201 TRACE_PARSER("ParseStaticFinalGetter"); |
1244 ParamList params; | 1202 ParamList params; |
1245 ASSERT(func.num_fixed_parameters() == 0); // static. | 1203 ASSERT(func.num_fixed_parameters() == 0); // static. |
1246 ASSERT(!func.HasOptionalParameters()); | 1204 ASSERT(!func.HasOptionalParameters()); |
1247 ASSERT(AbstractType::Handle(Z, func.result_type()).IsResolved()); | 1205 ASSERT(AbstractType::Handle(Z, func.result_type()).IsResolved()); |
1248 | 1206 |
1249 // Build local scope for function and populate with the formal parameters. | 1207 // Build local scope for function and populate with the formal parameters. |
1250 OpenFunctionBlock(func); | 1208 OpenFunctionBlock(func); |
1251 AddFormalParamsToScope(¶ms, current_block_->scope); | 1209 AddFormalParamsToScope(¶ms, current_block_->scope); |
(...skipping 3391 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4643 } else { | 4601 } else { |
4644 CheckToken(Token::kLBRACE); | 4602 CheckToken(Token::kLBRACE); |
4645 SkipBlock(); | 4603 SkipBlock(); |
4646 ExpectToken(Token::kRBRACE); | 4604 ExpectToken(Token::kRBRACE); |
4647 } | 4605 } |
4648 } | 4606 } |
4649 | 4607 |
4650 | 4608 |
4651 void Parser::ParseClassDefinition(const Class& cls) { | 4609 void Parser::ParseClassDefinition(const Class& cls) { |
4652 TRACE_PARSER("ParseClassDefinition"); | 4610 TRACE_PARSER("ParseClassDefinition"); |
4653 INC_STAT(I, num_classes_compiled, 1); | 4611 INC_STAT(thread(), num_classes_parsed, 1); |
4654 set_current_class(cls); | 4612 set_current_class(cls); |
4655 is_top_level_ = true; | 4613 is_top_level_ = true; |
4656 String& class_name = String::Handle(Z, cls.Name()); | 4614 String& class_name = String::Handle(Z, cls.Name()); |
4657 SkipMetadata(); | 4615 SkipMetadata(); |
4658 if (is_patch_source() && | 4616 if (is_patch_source() && |
4659 (CurrentToken() == Token::kIDENT) && | 4617 (CurrentToken() == Token::kIDENT) && |
4660 CurrentLiteral()->Equals("patch")) { | 4618 CurrentLiteral()->Equals("patch")) { |
4661 ConsumeToken(); | 4619 ConsumeToken(); |
4662 } else if (CurrentToken() == Token::kABSTRACT) { | 4620 } else if (CurrentToken() == Token::kABSTRACT) { |
4663 ConsumeToken(); | 4621 ConsumeToken(); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4703 Error& error = Error::Handle(Z); | 4661 Error& error = Error::Handle(Z); |
4704 if (!orig_class.ApplyPatch(cls, &error)) { | 4662 if (!orig_class.ApplyPatch(cls, &error)) { |
4705 Report::LongJumpF(error, script_, class_pos, "applying patch failed"); | 4663 Report::LongJumpF(error, script_, class_pos, "applying patch failed"); |
4706 } | 4664 } |
4707 } | 4665 } |
4708 } | 4666 } |
4709 | 4667 |
4710 | 4668 |
4711 void Parser::ParseEnumDefinition(const Class& cls) { | 4669 void Parser::ParseEnumDefinition(const Class& cls) { |
4712 TRACE_PARSER("ParseEnumDefinition"); | 4670 TRACE_PARSER("ParseEnumDefinition"); |
4713 INC_STAT(I, num_classes_compiled, 1); | 4671 INC_STAT(thread(), num_classes_parsed, 1); |
4714 | 4672 |
4715 SkipMetadata(); | 4673 SkipMetadata(); |
4716 ExpectToken(Token::kENUM); | 4674 ExpectToken(Token::kENUM); |
4717 | 4675 |
4718 const String& enum_name = String::Handle(Z, cls.Name()); | 4676 const String& enum_name = String::Handle(Z, cls.Name()); |
4719 ClassDesc enum_members(Z, cls, enum_name, false, cls.token_pos()); | 4677 ClassDesc enum_members(Z, cls, enum_name, false, cls.token_pos()); |
4720 | 4678 |
4721 // Add instance field 'final int index'. | 4679 // Add instance field 'final int index'. |
4722 Field& index_field = Field::ZoneHandle(Z); | 4680 Field& index_field = Field::ZoneHandle(Z); |
4723 const Type& int_type = Type::Handle(Z, Type::IntType()); | 4681 const Type& int_type = Type::Handle(Z, Type::IntType()); |
(...skipping 2957 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7681 ASSERT(existing_var != NULL); | 7639 ASSERT(existing_var != NULL); |
7682 // Use before define cases have already been detected and reported above. | 7640 // Use before define cases have already been detected and reported above. |
7683 ASSERT(existing_var->owner() == current_block_->scope); | 7641 ASSERT(existing_var->owner() == current_block_->scope); |
7684 ReportError(function_pos, "identifier '%s' already defined", | 7642 ReportError(function_pos, "identifier '%s' already defined", |
7685 function_variable->name().ToCString()); | 7643 function_variable->name().ToCString()); |
7686 } | 7644 } |
7687 } | 7645 } |
7688 | 7646 |
7689 // Parse the local function. | 7647 // Parse the local function. |
7690 SequenceNode* statements = Parser::ParseFunc(function); | 7648 SequenceNode* statements = Parser::ParseFunc(function); |
| 7649 INC_STAT(thread(), num_functions_parsed, 1); |
7691 | 7650 |
7692 // Now that the local function has formal parameters, lookup the signature | 7651 // Now that the local function has formal parameters, lookup the signature |
7693 // class in the current library (but not in its imports) and only create a new | 7652 // class in the current library (but not in its imports) and only create a new |
7694 // canonical signature class if it does not exist yet. | 7653 // canonical signature class if it does not exist yet. |
7695 const String& signature = String::Handle(Z, function.Signature()); | 7654 const String& signature = String::Handle(Z, function.Signature()); |
7696 Class& signature_class = Class::ZoneHandle(Z); | 7655 Class& signature_class = Class::ZoneHandle(Z); |
7697 if (!is_new_closure) { | 7656 if (!is_new_closure) { |
7698 signature_class = function.signature_class(); | 7657 signature_class = function.signature_class(); |
7699 } | 7658 } |
7700 if (signature_class.IsNull()) { | 7659 if (signature_class.IsNull()) { |
(...skipping 6587 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
14288 void Parser::SkipQualIdent() { | 14247 void Parser::SkipQualIdent() { |
14289 ASSERT(IsIdentifier()); | 14248 ASSERT(IsIdentifier()); |
14290 ConsumeToken(); | 14249 ConsumeToken(); |
14291 if (CurrentToken() == Token::kPERIOD) { | 14250 if (CurrentToken() == Token::kPERIOD) { |
14292 ConsumeToken(); // Consume the kPERIOD token. | 14251 ConsumeToken(); // Consume the kPERIOD token. |
14293 ExpectIdentifier("identifier expected after '.'"); | 14252 ExpectIdentifier("identifier expected after '.'"); |
14294 } | 14253 } |
14295 } | 14254 } |
14296 | 14255 |
14297 } // namespace dart | 14256 } // namespace dart |
OLD | NEW |