| 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/object.h" | 5 #include "vm/object.h" |
| 6 | 6 |
| 7 #include "include/dart_api.h" | 7 #include "include/dart_api.h" |
| 8 #include "platform/assert.h" | 8 #include "platform/assert.h" |
| 9 #include "vm/assembler.h" | 9 #include "vm/assembler.h" |
| 10 #include "vm/become.h" | 10 #include "vm/become.h" |
| (...skipping 10075 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10086 } | 10086 } |
| 10087 static uword Hash(const Object& obj) { return String::Cast(obj).Hash(); } | 10087 static uword Hash(const Object& obj) { return String::Cast(obj).Hash(); } |
| 10088 }; | 10088 }; |
| 10089 typedef UnorderedHashMap<StringEqualsTraits> ResolvedNamesMap; | 10089 typedef UnorderedHashMap<StringEqualsTraits> ResolvedNamesMap; |
| 10090 | 10090 |
| 10091 | 10091 |
| 10092 // Returns true if the name is found in the cache, false no cache hit. | 10092 // Returns true if the name is found in the cache, false no cache hit. |
| 10093 // obj is set to the cached entry. It may be null, indicating that the | 10093 // obj is set to the cached entry. It may be null, indicating that the |
| 10094 // name does not resolve to anything in this library. | 10094 // name does not resolve to anything in this library. |
| 10095 bool Library::LookupResolvedNamesCache(const String& name, Object* obj) const { | 10095 bool Library::LookupResolvedNamesCache(const String& name, Object* obj) const { |
| 10096 if (resolved_names() == Array::null()) { |
| 10097 return false; |
| 10098 } |
| 10096 ResolvedNamesMap cache(resolved_names()); | 10099 ResolvedNamesMap cache(resolved_names()); |
| 10097 bool present = false; | 10100 bool present = false; |
| 10098 *obj = cache.GetOrNull(name, &present); | 10101 *obj = cache.GetOrNull(name, &present); |
| 10099 // Mutator compiler thread may add entries and therefore | 10102 // Mutator compiler thread may add entries and therefore |
| 10100 // change 'resolved_names()' while running a background compilation; | 10103 // change 'resolved_names()' while running a background compilation; |
| 10101 // ASSERT that 'resolved_names()' has not changed only in mutator. | 10104 // ASSERT that 'resolved_names()' has not changed only in mutator. |
| 10102 #if defined(DEBUG) | 10105 #if defined(DEBUG) |
| 10103 if (Thread::Current()->IsMutatorThread()) { | 10106 if (Thread::Current()->IsMutatorThread()) { |
| 10104 ASSERT(cache.Release().raw() == resolved_names()); | 10107 ASSERT(cache.Release().raw() == resolved_names()); |
| 10105 } else { | 10108 } else { |
| 10106 // Release must be called in debug mode. | 10109 // Release must be called in debug mode. |
| 10107 cache.Release(); | 10110 cache.Release(); |
| 10108 } | 10111 } |
| 10109 #endif | 10112 #endif |
| 10110 return present; | 10113 return present; |
| 10111 } | 10114 } |
| 10112 | 10115 |
| 10113 | 10116 |
| 10114 // Add a name to the resolved name cache. This name resolves to the | 10117 // Add a name to the resolved name cache. This name resolves to the |
| 10115 // given object in this library scope. obj may be null, which means | 10118 // given object in this library scope. obj may be null, which means |
| 10116 // the name does not resolve to anything in this library scope. | 10119 // the name does not resolve to anything in this library scope. |
| 10117 void Library::AddToResolvedNamesCache(const String& name, | 10120 void Library::AddToResolvedNamesCache(const String& name, |
| 10118 const Object& obj) const { | 10121 const Object& obj) const { |
| 10119 if (!FLAG_use_lib_cache || Compiler::IsBackgroundCompilation()) { | 10122 if (!FLAG_use_lib_cache || Compiler::IsBackgroundCompilation()) { |
| 10120 return; | 10123 return; |
| 10121 } | 10124 } |
| 10125 if (resolved_names() == Array::null()) { |
| 10126 InitResolvedNamesCache(); |
| 10127 } |
| 10122 ResolvedNamesMap cache(resolved_names()); | 10128 ResolvedNamesMap cache(resolved_names()); |
| 10123 cache.UpdateOrInsert(name, obj); | 10129 cache.UpdateOrInsert(name, obj); |
| 10124 StorePointer(&raw_ptr()->resolved_names_, cache.Release().raw()); | 10130 StorePointer(&raw_ptr()->resolved_names_, cache.Release().raw()); |
| 10125 } | 10131 } |
| 10126 | 10132 |
| 10127 | 10133 |
| 10128 bool Library::LookupExportedNamesCache(const String& name, Object* obj) const { | 10134 bool Library::LookupExportedNamesCache(const String& name, Object* obj) const { |
| 10129 ASSERT(FLAG_use_exp_cache); | 10135 ASSERT(FLAG_use_exp_cache); |
| 10130 if (exported_names() == Array::null()) { | 10136 if (exported_names() == Array::null()) { |
| 10131 return false; | 10137 return false; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 10146 #endif | 10152 #endif |
| 10147 return present; | 10153 return present; |
| 10148 } | 10154 } |
| 10149 | 10155 |
| 10150 void Library::AddToExportedNamesCache(const String& name, | 10156 void Library::AddToExportedNamesCache(const String& name, |
| 10151 const Object& obj) const { | 10157 const Object& obj) const { |
| 10152 if (!FLAG_use_exp_cache || Compiler::IsBackgroundCompilation()) { | 10158 if (!FLAG_use_exp_cache || Compiler::IsBackgroundCompilation()) { |
| 10153 return; | 10159 return; |
| 10154 } | 10160 } |
| 10155 if (exported_names() == Array::null()) { | 10161 if (exported_names() == Array::null()) { |
| 10156 AllocateExportedNamesCache(); | 10162 InitExportedNamesCache(); |
| 10157 } | 10163 } |
| 10158 ResolvedNamesMap cache(exported_names()); | 10164 ResolvedNamesMap cache(exported_names()); |
| 10159 cache.UpdateOrInsert(name, obj); | 10165 cache.UpdateOrInsert(name, obj); |
| 10160 StorePointer(&raw_ptr()->exported_names_, cache.Release().raw()); | 10166 StorePointer(&raw_ptr()->exported_names_, cache.Release().raw()); |
| 10161 } | 10167 } |
| 10162 | 10168 |
| 10163 | 10169 |
| 10164 void Library::InvalidateResolvedName(const String& name) const { | 10170 void Library::InvalidateResolvedName(const String& name) const { |
| 10165 Thread* thread = Thread::Current(); | 10171 Thread* thread = Thread::Current(); |
| 10166 Zone* zone = thread->zone(); | 10172 Zone* zone = thread->zone(); |
| 10167 Object& entry = Object::Handle(zone); | 10173 Object& entry = Object::Handle(zone); |
| 10168 if (LookupResolvedNamesCache(name, &entry)) { | 10174 if (LookupResolvedNamesCache(name, &entry)) { |
| 10169 // TODO(koda): Support deleted sentinel in snapshots and remove only 'name'. | 10175 // TODO(koda): Support deleted sentinel in snapshots and remove only 'name'. |
| 10170 InvalidateResolvedNamesCache(); | 10176 ClearResolvedNamesCache(); |
| 10171 } | 10177 } |
| 10172 // When a new name is added to a library, we need to invalidate all | 10178 // When a new name is added to a library, we need to invalidate all |
| 10173 // caches that contain an entry for this name. If the name was previously | 10179 // caches that contain an entry for this name. If the name was previously |
| 10174 // looked up but could not be resolved, the cache contains a null entry. | 10180 // looked up but could not be resolved, the cache contains a null entry. |
| 10175 GrowableObjectArray& libs = GrowableObjectArray::Handle( | 10181 GrowableObjectArray& libs = GrowableObjectArray::Handle( |
| 10176 zone, thread->isolate()->object_store()->libraries()); | 10182 zone, thread->isolate()->object_store()->libraries()); |
| 10177 Library& lib = Library::Handle(zone); | 10183 Library& lib = Library::Handle(zone); |
| 10178 intptr_t num_libs = libs.Length(); | 10184 intptr_t num_libs = libs.Length(); |
| 10179 for (intptr_t i = 0; i < num_libs; i++) { | 10185 for (intptr_t i = 0; i < num_libs; i++) { |
| 10180 lib ^= libs.At(i); | 10186 lib ^= libs.At(i); |
| 10181 if (lib.LookupExportedNamesCache(name, &entry)) { | 10187 if (lib.LookupExportedNamesCache(name, &entry)) { |
| 10182 lib.InitExportedNamesCache(); | 10188 lib.ClearExportedNamesCache(); |
| 10183 } | 10189 } |
| 10184 } | 10190 } |
| 10185 } | 10191 } |
| 10186 | 10192 |
| 10187 | 10193 |
| 10188 void Library::InvalidateResolvedNamesCache() const { | |
| 10189 const intptr_t kInvalidatedCacheSize = 16; | |
| 10190 InitResolvedNamesCache(kInvalidatedCacheSize); | |
| 10191 } | |
| 10192 | |
| 10193 | |
| 10194 // Invalidate all exported names caches in the isolate. | 10194 // Invalidate all exported names caches in the isolate. |
| 10195 void Library::InvalidateExportedNamesCaches() { | 10195 void Library::InvalidateExportedNamesCaches() { |
| 10196 GrowableObjectArray& libs = GrowableObjectArray::Handle( | 10196 GrowableObjectArray& libs = GrowableObjectArray::Handle( |
| 10197 Isolate::Current()->object_store()->libraries()); | 10197 Isolate::Current()->object_store()->libraries()); |
| 10198 Library& lib = Library::Handle(); | 10198 Library& lib = Library::Handle(); |
| 10199 intptr_t num_libs = libs.Length(); | 10199 intptr_t num_libs = libs.Length(); |
| 10200 for (intptr_t i = 0; i < num_libs; i++) { | 10200 for (intptr_t i = 0; i < num_libs; i++) { |
| 10201 lib ^= libs.At(i); | 10201 lib ^= libs.At(i); |
| 10202 lib.InitExportedNamesCache(); | 10202 lib.ClearExportedNamesCache(); |
| 10203 } | 10203 } |
| 10204 } | 10204 } |
| 10205 | 10205 |
| 10206 | 10206 |
| 10207 void Library::GrowDictionary(const Array& dict, intptr_t dict_size) const { | 10207 void Library::GrowDictionary(const Array& dict, intptr_t dict_size) const { |
| 10208 // TODO(iposva): Avoid exponential growth. | 10208 // TODO(iposva): Avoid exponential growth. |
| 10209 intptr_t new_dict_size = dict_size * 2; | 10209 intptr_t new_dict_size = dict_size * 2; |
| 10210 const Array& new_dict = | 10210 const Array& new_dict = |
| 10211 Array::Handle(Array::New(new_dict_size + 1, Heap::kOld)); | 10211 Array::Handle(Array::New(new_dict_size + 1, Heap::kOld)); |
| 10212 // Rehash all elements from the original dictionary | 10212 // Rehash all elements from the original dictionary |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10391 ASSERT(dict.At(new_index) == Object::null()); | 10391 ASSERT(dict.At(new_index) == Object::null()); |
| 10392 dict.SetAt(new_index, entry); | 10392 dict.SetAt(new_index, entry); |
| 10393 dict.SetAt(index, Object::null_object()); | 10393 dict.SetAt(index, Object::null_object()); |
| 10394 } | 10394 } |
| 10395 } | 10395 } |
| 10396 | 10396 |
| 10397 // Update used count. | 10397 // Update used count. |
| 10398 intptr_t used_elements = Smi::Value(Smi::RawCast(dict.At(dict_size))) - 1; | 10398 intptr_t used_elements = Smi::Value(Smi::RawCast(dict.At(dict_size))) - 1; |
| 10399 dict.SetAt(dict_size, Smi::Handle(zone, Smi::New(used_elements))); | 10399 dict.SetAt(dict_size, Smi::Handle(zone, Smi::New(used_elements))); |
| 10400 | 10400 |
| 10401 InvalidateResolvedNamesCache(); | 10401 ClearResolvedNamesCache(); |
| 10402 InvalidateExportedNamesCaches(); | 10402 InvalidateExportedNamesCaches(); |
| 10403 | 10403 |
| 10404 return true; | 10404 return true; |
| 10405 } | 10405 } |
| 10406 | 10406 |
| 10407 | 10407 |
| 10408 void Library::AddClass(const Class& cls) const { | 10408 void Library::AddClass(const Class& cls) const { |
| 10409 ASSERT(!Compiler::IsBackgroundCompilation()); | 10409 ASSERT(!Compiler::IsBackgroundCompilation()); |
| 10410 const String& class_name = String::Handle(cls.Name()); | 10410 const String& class_name = String::Handle(cls.Name()); |
| 10411 AddObject(cls, class_name); | 10411 AddObject(cls, class_name); |
| (...skipping 392 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10804 | 10804 |
| 10805 | 10805 |
| 10806 static RawArray* NewDictionary(intptr_t initial_size) { | 10806 static RawArray* NewDictionary(intptr_t initial_size) { |
| 10807 const Array& dict = Array::Handle(Array::New(initial_size + 1, Heap::kOld)); | 10807 const Array& dict = Array::Handle(Array::New(initial_size + 1, Heap::kOld)); |
| 10808 // The last element of the dictionary specifies the number of in use slots. | 10808 // The last element of the dictionary specifies the number of in use slots. |
| 10809 dict.SetAt(initial_size, Smi::Handle(Smi::New(0))); | 10809 dict.SetAt(initial_size, Smi::Handle(Smi::New(0))); |
| 10810 return dict.raw(); | 10810 return dict.raw(); |
| 10811 } | 10811 } |
| 10812 | 10812 |
| 10813 | 10813 |
| 10814 void Library::InitResolvedNamesCache(intptr_t size) const { | 10814 void Library::InitResolvedNamesCache() const { |
| 10815 ASSERT(Thread::Current()->IsMutatorThread()); | 10815 ASSERT(Thread::Current()->IsMutatorThread()); |
| 10816 StorePointer(&raw_ptr()->resolved_names_, | 10816 StorePointer(&raw_ptr()->resolved_names_, |
| 10817 HashTables::New<ResolvedNamesMap>(size)); | 10817 HashTables::New<ResolvedNamesMap>(64)); |
| 10818 } | 10818 } |
| 10819 | 10819 |
| 10820 | 10820 |
| 10821 void Library::AllocateExportedNamesCache() const { | 10821 void Library::ClearResolvedNamesCache() const { |
| 10822 ASSERT(Thread::Current()->IsMutatorThread()); |
| 10823 StorePointer(&raw_ptr()->resolved_names_, Array::null()); |
| 10824 } |
| 10825 |
| 10826 |
| 10827 void Library::InitExportedNamesCache() const { |
| 10822 StorePointer(&raw_ptr()->exported_names_, | 10828 StorePointer(&raw_ptr()->exported_names_, |
| 10823 HashTables::New<ResolvedNamesMap>(16)); | 10829 HashTables::New<ResolvedNamesMap>(16)); |
| 10824 } | 10830 } |
| 10825 | 10831 |
| 10826 | 10832 |
| 10827 void Library::InitExportedNamesCache() const { | 10833 void Library::ClearExportedNamesCache() const { |
| 10828 if (exported_names() != Array::null()) { | 10834 StorePointer(&raw_ptr()->exported_names_, Array::null()); |
| 10829 StorePointer(&raw_ptr()->exported_names_, | |
| 10830 HashTables::New<ResolvedNamesMap>(16)); | |
| 10831 } | |
| 10832 } | 10835 } |
| 10833 | 10836 |
| 10834 | 10837 |
| 10835 void Library::InitClassDictionary() const { | 10838 void Library::InitClassDictionary() const { |
| 10836 // TODO(iposva): Find reasonable initial size. | 10839 // TODO(iposva): Find reasonable initial size. |
| 10837 const int kInitialElementCount = 16; | 10840 const int kInitialElementCount = 16; |
| 10838 StorePointer(&raw_ptr()->dictionary_, NewDictionary(kInitialElementCount)); | 10841 StorePointer(&raw_ptr()->dictionary_, NewDictionary(kInitialElementCount)); |
| 10839 } | 10842 } |
| 10840 | 10843 |
| 10841 | 10844 |
| (...skipping 18 matching lines...) Expand all Loading... |
| 10860 Zone* zone = thread->zone(); | 10863 Zone* zone = thread->zone(); |
| 10861 ASSERT(thread->IsMutatorThread()); | 10864 ASSERT(thread->IsMutatorThread()); |
| 10862 // Force the url to have a hash code. | 10865 // Force the url to have a hash code. |
| 10863 url.Hash(); | 10866 url.Hash(); |
| 10864 const bool dart_scheme = url.StartsWith(Symbols::DartScheme()); | 10867 const bool dart_scheme = url.StartsWith(Symbols::DartScheme()); |
| 10865 const bool dart_private_scheme = | 10868 const bool dart_private_scheme = |
| 10866 dart_scheme && url.StartsWith(Symbols::DartSchemePrivate()); | 10869 dart_scheme && url.StartsWith(Symbols::DartSchemePrivate()); |
| 10867 const Library& result = Library::Handle(zone, Library::New()); | 10870 const Library& result = Library::Handle(zone, Library::New()); |
| 10868 result.StorePointer(&result.raw_ptr()->name_, Symbols::Empty().raw()); | 10871 result.StorePointer(&result.raw_ptr()->name_, Symbols::Empty().raw()); |
| 10869 result.StorePointer(&result.raw_ptr()->url_, url.raw()); | 10872 result.StorePointer(&result.raw_ptr()->url_, url.raw()); |
| 10870 result.StorePointer(&result.raw_ptr()->resolved_names_, | 10873 result.StorePointer(&result.raw_ptr()->resolved_names_, Array::null()); |
| 10871 Object::empty_array().raw()); | |
| 10872 result.StorePointer(&result.raw_ptr()->exported_names_, Array::null()); | 10874 result.StorePointer(&result.raw_ptr()->exported_names_, Array::null()); |
| 10873 result.StorePointer(&result.raw_ptr()->dictionary_, | 10875 result.StorePointer(&result.raw_ptr()->dictionary_, |
| 10874 Object::empty_array().raw()); | 10876 Object::empty_array().raw()); |
| 10875 result.StorePointer(&result.raw_ptr()->metadata_, | 10877 result.StorePointer(&result.raw_ptr()->metadata_, |
| 10876 GrowableObjectArray::New(4, Heap::kOld)); | 10878 GrowableObjectArray::New(4, Heap::kOld)); |
| 10877 result.StorePointer(&result.raw_ptr()->toplevel_class_, Class::null()); | 10879 result.StorePointer(&result.raw_ptr()->toplevel_class_, Class::null()); |
| 10878 result.StorePointer( | 10880 result.StorePointer( |
| 10879 &result.raw_ptr()->patch_classes_, | 10881 &result.raw_ptr()->patch_classes_, |
| 10880 GrowableObjectArray::New(Object::empty_array(), Heap::kOld)); | 10882 GrowableObjectArray::New(Object::empty_array(), Heap::kOld)); |
| 10881 result.StorePointer(&result.raw_ptr()->imports_, Object::empty_array().raw()); | 10883 result.StorePointer(&result.raw_ptr()->imports_, Object::empty_array().raw()); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 10894 // frames. | 10896 // frames. |
| 10895 result.set_debuggable(FLAG_show_invisible_frames); | 10897 result.set_debuggable(FLAG_show_invisible_frames); |
| 10896 } else { | 10898 } else { |
| 10897 // Default to debuggable for all other libraries. | 10899 // Default to debuggable for all other libraries. |
| 10898 result.set_debuggable(true); | 10900 result.set_debuggable(true); |
| 10899 } | 10901 } |
| 10900 result.set_is_dart_scheme(dart_scheme); | 10902 result.set_is_dart_scheme(dart_scheme); |
| 10901 result.StoreNonPointer(&result.raw_ptr()->load_state_, | 10903 result.StoreNonPointer(&result.raw_ptr()->load_state_, |
| 10902 RawLibrary::kAllocated); | 10904 RawLibrary::kAllocated); |
| 10903 result.StoreNonPointer(&result.raw_ptr()->index_, -1); | 10905 result.StoreNonPointer(&result.raw_ptr()->index_, -1); |
| 10904 const intptr_t kInitialNameCacheSize = 64; | |
| 10905 result.InitResolvedNamesCache(kInitialNameCacheSize); | |
| 10906 result.InitClassDictionary(); | 10906 result.InitClassDictionary(); |
| 10907 result.InitImportList(); | 10907 result.InitImportList(); |
| 10908 result.AllocatePrivateKey(); | 10908 result.AllocatePrivateKey(); |
| 10909 if (import_core_lib) { | 10909 if (import_core_lib) { |
| 10910 const Library& core_lib = Library::Handle(zone, Library::CoreLibrary()); | 10910 const Library& core_lib = Library::Handle(zone, Library::CoreLibrary()); |
| 10911 ASSERT(!core_lib.IsNull()); | 10911 ASSERT(!core_lib.IsNull()); |
| 10912 const Namespace& ns = Namespace::Handle( | 10912 const Namespace& ns = Namespace::Handle( |
| 10913 zone, | 10913 zone, |
| 10914 Namespace::New(core_lib, Object::null_array(), Object::null_array())); | 10914 Namespace::New(core_lib, Object::null_array(), Object::null_array())); |
| 10915 result.AddImport(ns); | 10915 result.AddImport(ns); |
| (...skipping 12231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 23147 return UserTag::null(); | 23147 return UserTag::null(); |
| 23148 } | 23148 } |
| 23149 | 23149 |
| 23150 | 23150 |
| 23151 const char* UserTag::ToCString() const { | 23151 const char* UserTag::ToCString() const { |
| 23152 const String& tag_label = String::Handle(label()); | 23152 const String& tag_label = String::Handle(label()); |
| 23153 return tag_label.ToCString(); | 23153 return tag_label.ToCString(); |
| 23154 } | 23154 } |
| 23155 | 23155 |
| 23156 } // namespace dart | 23156 } // namespace dart |
| OLD | NEW |