| 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 |