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 #include "vm/flags.h" | 6 #include "vm/flags.h" |
7 | 7 |
8 #ifndef DART_PRECOMPILED_RUNTIME | 8 #ifndef DART_PRECOMPILED_RUNTIME |
9 | 9 |
10 #include "lib/invocation_mirror.h" | 10 #include "lib/invocation_mirror.h" |
(...skipping 4372 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4383 ReportError(", or } expected"); | 4383 ReportError(", or } expected"); |
4384 } | 4384 } |
4385 } | 4385 } |
4386 ExpectToken(Token::kRBRACE); | 4386 ExpectToken(Token::kRBRACE); |
4387 | 4387 |
4388 Object& obj = Object::Handle(Z, library_.LookupLocalObject(*enum_name)); | 4388 Object& obj = Object::Handle(Z, library_.LookupLocalObject(*enum_name)); |
4389 if (!obj.IsNull()) { | 4389 if (!obj.IsNull()) { |
4390 ReportError(name_pos, "'%s' is already defined", enum_name->ToCString()); | 4390 ReportError(name_pos, "'%s' is already defined", enum_name->ToCString()); |
4391 } | 4391 } |
4392 Class& cls = Class::Handle(Z); | 4392 Class& cls = Class::Handle(Z); |
4393 cls = Class::New(*enum_name, script_, declaration_pos); | 4393 cls = Class::New(library_, *enum_name, script_, declaration_pos); |
4394 cls.set_library(library_); | |
4395 library_.AddClass(cls); | 4394 library_.AddClass(cls); |
4396 cls.set_is_synthesized_class(); | 4395 cls.set_is_synthesized_class(); |
4397 cls.set_is_enum_class(); | 4396 cls.set_is_enum_class(); |
4398 if (FLAG_enable_mirrors && (metadata_pos.IsReal())) { | 4397 if (FLAG_enable_mirrors && (metadata_pos.IsReal())) { |
4399 library_.AddClassMetadata(cls, tl_owner, metadata_pos); | 4398 library_.AddClassMetadata(cls, tl_owner, metadata_pos); |
4400 } | 4399 } |
4401 cls.set_super_type(Type::Handle(Z, Type::ObjectType())); | 4400 cls.set_super_type(Type::Handle(Z, Type::ObjectType())); |
4402 pending_classes.Add(cls, Heap::kOld); | 4401 pending_classes.Add(cls, Heap::kOld); |
4403 } | 4402 } |
4404 | 4403 |
(...skipping 22 matching lines...) Expand all Loading... |
4427 OS::Print("TopLevel parsing class '%s'\n", class_name.ToCString()); | 4426 OS::Print("TopLevel parsing class '%s'\n", class_name.ToCString()); |
4428 } | 4427 } |
4429 Class& cls = Class::Handle(Z); | 4428 Class& cls = Class::Handle(Z); |
4430 TypeArguments& orig_type_parameters = TypeArguments::Handle(Z); | 4429 TypeArguments& orig_type_parameters = TypeArguments::Handle(Z); |
4431 Object& obj = Object::Handle(Z, library_.LookupLocalObject(class_name)); | 4430 Object& obj = Object::Handle(Z, library_.LookupLocalObject(class_name)); |
4432 if (obj.IsNull()) { | 4431 if (obj.IsNull()) { |
4433 if (is_patch) { | 4432 if (is_patch) { |
4434 ReportError(classname_pos, "missing class '%s' cannot be patched", | 4433 ReportError(classname_pos, "missing class '%s' cannot be patched", |
4435 class_name.ToCString()); | 4434 class_name.ToCString()); |
4436 } | 4435 } |
4437 cls = Class::New(class_name, script_, declaration_pos); | 4436 cls = Class::New(library_, class_name, script_, declaration_pos); |
4438 library_.AddClass(cls); | 4437 library_.AddClass(cls); |
4439 } else { | 4438 } else { |
4440 if (!obj.IsClass()) { | 4439 if (!obj.IsClass()) { |
4441 ReportError(classname_pos, "'%s' is already defined", | 4440 ReportError(classname_pos, "'%s' is already defined", |
4442 class_name.ToCString()); | 4441 class_name.ToCString()); |
4443 } | 4442 } |
4444 cls ^= obj.raw(); | 4443 cls ^= obj.raw(); |
4445 if (is_patch) { | 4444 if (is_patch) { |
4446 // Preserve and reuse the original type parameters and bounds since the | 4445 // Preserve and reuse the original type parameters and bounds since the |
4447 // ones defined in the patch class will not be finalized. | 4446 // ones defined in the patch class will not be finalized. |
4448 orig_type_parameters = cls.type_parameters(); | 4447 orig_type_parameters = cls.type_parameters(); |
4449 cls = Class::New(class_name, script_, declaration_pos); | 4448 cls = Class::New(library_, class_name, script_, declaration_pos); |
4450 cls.set_library(library_); | |
4451 } else { | 4449 } else { |
4452 // Not patching a class, but it has been found. This must be one of the | 4450 // Not patching a class, but it has been found. This must be one of the |
4453 // pre-registered classes from object.cc or a duplicate definition. | 4451 // pre-registered classes from object.cc or a duplicate definition. |
4454 if (!(cls.is_prefinalized() || | 4452 if (!(cls.is_prefinalized() || |
4455 RawObject::IsImplicitFieldClassId(cls.id()))) { | 4453 RawObject::IsImplicitFieldClassId(cls.id()))) { |
4456 ReportError(classname_pos, "class '%s' is already defined", | 4454 ReportError(classname_pos, "class '%s' is already defined", |
4457 class_name.ToCString()); | 4455 class_name.ToCString()); |
4458 } | 4456 } |
4459 // Pre-registered classes need their scripts connected at this time. | 4457 // Pre-registered classes need their scripts connected at this time. |
4460 cls.set_script(script_); | 4458 cls.set_script(script_); |
(...skipping 449 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4910 if (FLAG_trace_parser) { | 4908 if (FLAG_trace_parser) { |
4911 OS::Print("toplevel parsing mixin application alias class '%s'\n", | 4909 OS::Print("toplevel parsing mixin application alias class '%s'\n", |
4912 class_name.ToCString()); | 4910 class_name.ToCString()); |
4913 } | 4911 } |
4914 const Object& obj = Object::Handle(Z, library_.LookupLocalObject(class_name)); | 4912 const Object& obj = Object::Handle(Z, library_.LookupLocalObject(class_name)); |
4915 if (!obj.IsNull()) { | 4913 if (!obj.IsNull()) { |
4916 ReportError(classname_pos, "'%s' is already defined", | 4914 ReportError(classname_pos, "'%s' is already defined", |
4917 class_name.ToCString()); | 4915 class_name.ToCString()); |
4918 } | 4916 } |
4919 const Class& mixin_application = | 4917 const Class& mixin_application = |
4920 Class::Handle(Z, Class::New(class_name, script_, classname_pos)); | 4918 Class::Handle(Z, Class::New(library_, class_name, |
| 4919 script_, classname_pos)); |
4921 mixin_application.set_is_mixin_app_alias(); | 4920 mixin_application.set_is_mixin_app_alias(); |
4922 library_.AddClass(mixin_application); | 4921 library_.AddClass(mixin_application); |
4923 set_current_class(mixin_application); | 4922 set_current_class(mixin_application); |
4924 ParseTypeParameters(mixin_application); | 4923 ParseTypeParameters(mixin_application); |
4925 | 4924 |
4926 ExpectToken(Token::kASSIGN); | 4925 ExpectToken(Token::kASSIGN); |
4927 | 4926 |
4928 if (CurrentToken() == Token::kABSTRACT) { | 4927 if (CurrentToken() == Token::kABSTRACT) { |
4929 mixin_application.set_is_abstract(); | 4928 mixin_application.set_is_abstract(); |
4930 ConsumeToken(); | 4929 ConsumeToken(); |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5038 Object::Handle(Z, library_.LookupLocalObject(*alias_name)); | 5037 Object::Handle(Z, library_.LookupLocalObject(*alias_name)); |
5039 if (!obj.IsNull()) { | 5038 if (!obj.IsNull()) { |
5040 ReportError(alias_name_pos, | 5039 ReportError(alias_name_pos, |
5041 "'%s' is already defined", alias_name->ToCString()); | 5040 "'%s' is already defined", alias_name->ToCString()); |
5042 } | 5041 } |
5043 | 5042 |
5044 // Create the function type alias scope class. It will be linked to its | 5043 // Create the function type alias scope class. It will be linked to its |
5045 // signature function after it has been parsed. The type parameters, in order | 5044 // signature function after it has been parsed. The type parameters, in order |
5046 // to be properly finalized, need to be associated to this scope class as | 5045 // to be properly finalized, need to be associated to this scope class as |
5047 // they are parsed. | 5046 // they are parsed. |
5048 const Class& function_type_alias = Class::Handle(Z, | 5047 const Class& function_type_alias = |
5049 Class::New(*alias_name, script_, declaration_pos)); | 5048 Class::Handle(Z, Class::New( |
| 5049 library_, *alias_name, script_, declaration_pos)); |
5050 function_type_alias.set_is_synthesized_class(); | 5050 function_type_alias.set_is_synthesized_class(); |
5051 function_type_alias.set_is_abstract(); | 5051 function_type_alias.set_is_abstract(); |
5052 function_type_alias.set_is_prefinalized(); | 5052 function_type_alias.set_is_prefinalized(); |
5053 library_.AddClass(function_type_alias); | 5053 library_.AddClass(function_type_alias); |
5054 set_current_class(function_type_alias); | 5054 set_current_class(function_type_alias); |
5055 // Parse the type parameters of the function type. | 5055 // Parse the type parameters of the function type. |
5056 ParseTypeParameters(function_type_alias); | 5056 ParseTypeParameters(function_type_alias); |
5057 // At this point, the type parameters have been parsed, so we can resolve the | 5057 // At this point, the type parameters have been parsed, so we can resolve the |
5058 // result type. | 5058 // result type. |
5059 if (!result_type.IsNull()) { | 5059 if (!result_type.IsNull()) { |
(...skipping 1029 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6089 ObjectStore* object_store = I->object_store(); | 6089 ObjectStore* object_store = I->object_store(); |
6090 const GrowableObjectArray& pending_classes = | 6090 const GrowableObjectArray& pending_classes = |
6091 GrowableObjectArray::Handle(Z, object_store->pending_classes()); | 6091 GrowableObjectArray::Handle(Z, object_store->pending_classes()); |
6092 SetPosition(TokenPosition::kMinSource); | 6092 SetPosition(TokenPosition::kMinSource); |
6093 is_top_level_ = true; | 6093 is_top_level_ = true; |
6094 TopLevel top_level(Z); | 6094 TopLevel top_level(Z); |
6095 | 6095 |
6096 Object& tl_owner = Object::Handle(Z); | 6096 Object& tl_owner = Object::Handle(Z); |
6097 Class& toplevel_class = Class::Handle(Z, library_.toplevel_class()); | 6097 Class& toplevel_class = Class::Handle(Z, library_.toplevel_class()); |
6098 if (toplevel_class.IsNull()) { | 6098 if (toplevel_class.IsNull()) { |
6099 toplevel_class = Class::New(Symbols::TopLevel(), script_, TokenPos()); | 6099 toplevel_class = |
| 6100 Class::New(library_, Symbols::TopLevel(), script_, TokenPos()); |
6100 toplevel_class.set_library(library_); | 6101 toplevel_class.set_library(library_); |
6101 library_.set_toplevel_class(toplevel_class); | 6102 library_.set_toplevel_class(toplevel_class); |
6102 tl_owner = toplevel_class.raw(); | 6103 tl_owner = toplevel_class.raw(); |
6103 } else { | 6104 } else { |
6104 tl_owner = PatchClass::New(toplevel_class, script_); | 6105 tl_owner = PatchClass::New(toplevel_class, script_); |
6105 } | 6106 } |
6106 | 6107 |
6107 if (is_library_source() || is_patch_source()) { | 6108 if (is_library_source() || is_patch_source()) { |
6108 set_current_class(toplevel_class); | 6109 set_current_class(toplevel_class); |
6109 ParseLibraryDefinition(tl_owner); | 6110 ParseLibraryDefinition(tl_owner); |
(...skipping 5894 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12004 | 12005 |
12005 bool Parser::IsInstantiatorRequired() const { | 12006 bool Parser::IsInstantiatorRequired() const { |
12006 ASSERT(!current_function().IsNull()); | 12007 ASSERT(!current_function().IsNull()); |
12007 if (current_function().is_static() && | 12008 if (current_function().is_static() && |
12008 !current_function().IsInFactoryScope()) { | 12009 !current_function().IsInFactoryScope()) { |
12009 return false; | 12010 return false; |
12010 } | 12011 } |
12011 return current_class().IsGeneric(); | 12012 return current_class().IsGeneric(); |
12012 } | 12013 } |
12013 | 12014 |
12014 // We cache computed compile-time constants in a map so we can look them | |
12015 // up when the same code gets compiled again. The map key is a pair | |
12016 // (script url, token position) which is encoded in an array with 2 | |
12017 // elements: | |
12018 // - key[0] contains the canonicalized url of the script. | |
12019 // - key[1] contains the token position of the constant in the script. | |
12020 | 12015 |
12021 // ConstantPosKey allows us to look up a constant in the map without | 12016 void Parser::InsertCachedConstantValue(const String& url, |
12022 // allocating a key pair (array). | 12017 TokenPosition token_pos, |
12023 struct ConstantPosKey : ValueObject { | 12018 const Instance& value) { |
12024 ConstantPosKey(const String& url, TokenPosition pos) | 12019 Isolate* isolate = Isolate::Current(); |
12025 : script_url(url), token_pos(pos) { } | 12020 ConstantPosKey key(url, token_pos); |
12026 const String& script_url; | 12021 if (isolate->object_store()->compile_time_constants() == Array::null()) { |
12027 TokenPosition token_pos; | 12022 const intptr_t kInitialConstMapSize = 16; |
12028 }; | 12023 isolate->object_store()->set_compile_time_constants( |
12029 | 12024 Array::Handle(HashTables::New<ConstantsMap>(kInitialConstMapSize, |
12030 | 12025 Heap::kNew))); |
12031 class ConstMapKeyEqualsTraits { | |
12032 public: | |
12033 static const char* Name() { return "ConstMapKeyEqualsTraits"; } | |
12034 static bool ReportStats() { return false; } | |
12035 | |
12036 static bool IsMatch(const Object& a, const Object& b) { | |
12037 const Array& key1 = Array::Cast(a); | |
12038 const Array& key2 = Array::Cast(b); | |
12039 // Compare raw strings of script url symbol and raw smi of token positon. | |
12040 return (key1.At(0) == key2.At(0)) && (key1.At(1) == key2.At(1)); | |
12041 } | 12026 } |
12042 static bool IsMatch(const ConstantPosKey& key1, const Object& b) { | 12027 ConstantsMap constants(isolate->object_store()->compile_time_constants()); |
12043 const Array& key2 = Array::Cast(b); | 12028 constants.InsertNewOrGetValue(key, value); |
12044 // Compare raw strings of script url symbol and token positon. | 12029 isolate->object_store()->set_compile_time_constants(constants.Release()); |
12045 return (key1.script_url.raw() == key2.At(0)) | 12030 } |
12046 && (key1.token_pos.value() == Smi::Value(Smi::RawCast(key2.At(1)))); | |
12047 } | |
12048 static uword Hash(const Object& obj) { | |
12049 const Array& key = Array::Cast(obj); | |
12050 intptr_t url_hash = String::HashRawSymbol(String::RawCast(key.At(0))); | |
12051 intptr_t pos = Smi::Value(Smi::RawCast(key.At(1))); | |
12052 return HashValue(url_hash, pos); | |
12053 } | |
12054 static uword Hash(const ConstantPosKey& key) { | |
12055 return HashValue(String::HashRawSymbol(key.script_url.raw()), | |
12056 key.token_pos.value()); | |
12057 } | |
12058 // Used by CacheConstantValue if a new constant is added to the map. | |
12059 static RawObject* NewKey(const ConstantPosKey& key) { | |
12060 const Array& key_obj = Array::Handle(Array::New(2)); | |
12061 key_obj.SetAt(0, key.script_url); | |
12062 key_obj.SetAt(1, Smi::Handle(Smi::New(key.token_pos.value()))); | |
12063 return key_obj.raw();; | |
12064 } | |
12065 | |
12066 private: | |
12067 static uword HashValue(intptr_t url_hash, intptr_t pos) { | |
12068 return url_hash * pos % (Smi::kMaxValue - 13); | |
12069 } | |
12070 }; | |
12071 typedef UnorderedHashMap<ConstMapKeyEqualsTraits> ConstantsMap; | |
12072 | 12031 |
12073 | 12032 |
12074 void Parser::CacheConstantValue(TokenPosition token_pos, | 12033 void Parser::CacheConstantValue(TokenPosition token_pos, |
12075 const Instance& value) { | 12034 const Instance& value) { |
12076 if (current_function().kind() == RawFunction::kImplicitStaticFinalGetter) { | 12035 if (current_function().kind() == RawFunction::kImplicitStaticFinalGetter) { |
12077 // Don't cache constants in initializer expressions. They get | 12036 // Don't cache constants in initializer expressions. They get |
12078 // evaluated only once. | 12037 // evaluated only once. |
12079 return; | 12038 return; |
12080 } | 12039 } |
12081 ConstantPosKey key(String::Handle(Z, script_.url()), token_pos); | 12040 const String& url = String::Handle(Z, script_.url()); |
12082 if (isolate()->object_store()->compile_time_constants() == Array::null()) { | 12041 InsertCachedConstantValue(url, token_pos, value); |
12083 const intptr_t kInitialConstMapSize = 16; | 12042 if (FLAG_compiler_stats) { |
12084 isolate()->object_store()->set_compile_time_constants( | 12043 ConstantsMap constants(isolate()->object_store()->compile_time_constants()); |
12085 Array::Handle(Z, HashTables::New<ConstantsMap>(kInitialConstMapSize, | 12044 thread_->compiler_stats()->num_cached_consts = constants.NumOccupied(); |
12086 Heap::kNew))); | 12045 constants.Release(); |
12087 } | 12046 } |
12088 ConstantsMap constants(isolate()->object_store()->compile_time_constants()); | |
12089 constants.InsertNewOrGetValue(key, value); | |
12090 if (FLAG_compiler_stats) { | |
12091 thread_->compiler_stats()->num_cached_consts = constants.NumOccupied(); | |
12092 } | |
12093 isolate()->object_store()->set_compile_time_constants(constants.Release()); | |
12094 } | 12047 } |
12095 | 12048 |
12096 | 12049 |
12097 bool Parser::GetCachedConstant(TokenPosition token_pos, Instance* value) { | 12050 bool Parser::GetCachedConstant(TokenPosition token_pos, Instance* value) { |
12098 if (isolate()->object_store()->compile_time_constants() == Array::null()) { | 12051 if (isolate()->object_store()->compile_time_constants() == Array::null()) { |
12099 return false; | 12052 return false; |
12100 } | 12053 } |
12101 ConstantPosKey key(String::Handle(Z, script_.url()), token_pos); | 12054 ConstantPosKey key(String::Handle(Z, script_.url()), token_pos); |
12102 ConstantsMap constants(isolate()->object_store()->compile_time_constants()); | 12055 ConstantsMap constants(isolate()->object_store()->compile_time_constants()); |
12103 bool is_present = false; | 12056 bool is_present = false; |
(...skipping 2423 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
14527 return Object::null(); | 14480 return Object::null(); |
14528 } | 14481 } |
14529 | 14482 |
14530 | 14483 |
14531 ParsedFunction* Parser::ParseStaticFieldInitializer(const Field& field) { | 14484 ParsedFunction* Parser::ParseStaticFieldInitializer(const Field& field) { |
14532 UNREACHABLE(); | 14485 UNREACHABLE(); |
14533 return NULL; | 14486 return NULL; |
14534 } | 14487 } |
14535 | 14488 |
14536 | 14489 |
| 14490 void Parser::InsertCachedConstantValue(const String& url, |
| 14491 TokenPosition token_pos, |
| 14492 const Instance& value) { |
| 14493 UNREACHABLE(); |
| 14494 } |
| 14495 |
| 14496 |
14537 ArgumentListNode* Parser::BuildNoSuchMethodArguments( | 14497 ArgumentListNode* Parser::BuildNoSuchMethodArguments( |
14538 TokenPosition call_pos, | 14498 TokenPosition call_pos, |
14539 const String& function_name, | 14499 const String& function_name, |
14540 const ArgumentListNode& function_args, | 14500 const ArgumentListNode& function_args, |
14541 const LocalVariable* temp_for_last_arg, | 14501 const LocalVariable* temp_for_last_arg, |
14542 bool is_super_invocation) { | 14502 bool is_super_invocation) { |
14543 UNREACHABLE(); | 14503 UNREACHABLE(); |
14544 return NULL; | 14504 return NULL; |
14545 } | 14505 } |
14546 | 14506 |
14547 } // namespace dart | 14507 } // namespace dart |
14548 | 14508 |
14549 #endif // DART_PRECOMPILED_RUNTIME | 14509 #endif // DART_PRECOMPILED_RUNTIME |
OLD | NEW |