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