Chromium Code Reviews| Index: runtime/vm/object.cc |
| =================================================================== |
| --- runtime/vm/object.cc (revision 40392) |
| +++ runtime/vm/object.cc (working copy) |
| @@ -8745,19 +8745,71 @@ |
| } |
| +// Traits for looking up Libraries by url in a hash set. |
| +class LibraryUrl { |
|
Ivan Posva
2014/09/18 00:58:05
Not needed.
siva
2014/09/18 01:07:37
Done.
|
| + public: |
| + LibraryUrl(const String& url, String* tmp_string) |
| + : url_(url), tmp_string_(tmp_string) {} |
| + bool Matches(const Library& library) const { |
| + if (url_.IsSymbol()) { |
| + return url_.raw() == library.url(); |
| + } else { |
| + *tmp_string_ = library.url(); |
| + return url_.Equals(*tmp_string_); |
| + } |
| + } |
| + intptr_t Hash() const { return url_.Hash(); } |
| + private: |
| + const String& url_; |
| + String* tmp_string_; |
| +}; |
| + |
| + |
| +class LibraryUrlTraits { |
| + public: |
| + // Called when growing the table. |
| + static bool IsMatch(const Object& a, const Object& b) { |
| + ASSERT(a.IsLibrary() && b.IsLibrary()); |
| + // Library objects are always canonical. |
| + return a.raw() == b.raw(); |
| + } |
| + static bool IsMatch(const LibraryUrl& url, const Object& obj) { |
| + return url.Matches(Library::Cast(obj)); |
|
Ivan Posva
2014/09/18 00:58:05
ditto.
siva
2014/09/18 01:07:37
Done.
|
| + } |
| + static uword Hash(const Object& key) { |
| + return Library::Cast(key).UrlHash(); |
| + } |
| + static uword Hash(const LibraryUrl& url) { |
|
Ivan Posva
2014/09/18 00:58:05
ditto.
siva
2014/09/18 01:07:37
Done.
|
| + return url.Hash(); |
| + } |
| +}; |
| + |
| + |
| +typedef UnorderedHashSet<LibraryUrlTraits> LibraryLoadErrorSet; |
| + |
| + |
| RawInstance* Library::TransitiveLoadError() const { |
| if (LoadError() != Instance::null()) { |
| return LoadError(); |
| } |
| + Isolate* isolate = Isolate::Current(); |
| + ObjectStore* object_store = isolate->object_store(); |
| + LibraryLoadErrorSet set(object_store->library_load_error_table()); |
| + bool present = false; |
| + if (set.GetOrNull(*this, &present) != Object::null()) { |
| + object_store->set_library_load_error_table(set.Release()); |
| + return Instance::null(); |
| + } |
| + // Ensure we don't repeatedly visit the same library again. |
| + set.Insert(*this); |
| + object_store->set_library_load_error_table(set.Release()); |
| intptr_t num_imp = num_imports(); |
| - Library& lib = Library::Handle(); |
| - Instance& error = Instance::Handle(); |
| + Library& lib = Library::Handle(isolate); |
| + Instance& error = Instance::Handle(isolate); |
| for (intptr_t i = 0; i < num_imp; i++) { |
| + HANDLESCOPE(isolate); |
| lib = ImportLibraryAt(i); |
| - // Break potential import cycles while recursing through imports. |
| - set_num_imports(0); |
| error = lib.TransitiveLoadError(); |
| - set_num_imports(num_imp); |
| if (!error.IsNull()) { |
| break; |
| } |
| @@ -9941,17 +9993,23 @@ |
| RawInstance* LibraryPrefix::LoadError() const { |
| - Library& lib = Library::Handle(); |
| - Instance& error = Instance::Handle(); |
| + const intptr_t kNumLibs = 25; |
|
Ivan Posva
2014/09/18 00:58:04
Please use the already known number of loaded libr
siva
2014/09/18 01:07:37
Done.
|
| + Isolate* isolate = Isolate::Current(); |
| + ObjectStore* object_store = isolate->object_store(); |
| + LibraryLoadErrorSet set(HashTables::New<LibraryLoadErrorSet>(kNumLibs)); |
| + object_store->set_library_load_error_table(set.Release()); |
| + Library& lib = Library::Handle(isolate); |
| + Instance& error = Instance::Handle(isolate); |
| for (int32_t i = 0; i < num_imports(); i++) { |
| lib = GetLibrary(i); |
| ASSERT(!lib.IsNull()); |
| error = lib.TransitiveLoadError(); |
| if (!error.IsNull()) { |
| - return error.raw(); |
| + break; |
| } |
| } |
| - return Instance::null(); |
| + object_store->set_library_load_error_table(Object::empty_array()); |
| + return error.raw(); |
| } |