Index: runtime/vm/object.cc |
=================================================================== |
--- runtime/vm/object.cc (revision 40392) |
+++ runtime/vm/object.cc (working copy) |
@@ -8745,23 +8745,75 @@ |
} |
+// Traits for looking up Libraries by url in a hash set. |
+class LibraryUrl { |
+ 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)); |
+ } |
+ static uword Hash(const Object& key) { |
+ return Library::Cast(key).UrlHash(); |
+ } |
+ static uword Hash(const LibraryUrl& url) { |
+ 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(); |
+ } |
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); |
+ // Ensure we don't repeatedly visit the same library again. |
+ set.Insert(lib); |
error = lib.TransitiveLoadError(); |
- set_num_imports(num_imp); |
if (!error.IsNull()) { |
break; |
} |
} |
+ object_store->set_library_load_error_table(set.Release()); |
return error.raw(); |
} |
@@ -9941,17 +9993,23 @@ |
RawInstance* LibraryPrefix::LoadError() const { |
- Library& lib = Library::Handle(); |
- Instance& error = Instance::Handle(); |
+ const intptr_t kNumLibs = 25; |
+ Isolate* isolate = Isolate::Current(); |
+ ObjectStore* object_store = isolate->object_store(); |
+ LibraryLoadErrorSet set(HashTables::New<LibraryLoadErrorSet>(kNumLibs)); |
Ivan Posva
2014/09/18 00:58:04
How about just calling set.Clear() once we are don
siva
2014/09/18 01:07:37
Ignoring this for now.
|
+ 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); |
Ivan Posva
2014/09/18 00:58:04
HANDLESCOPE(isolate);
siva
2014/09/18 01:07:37
Done.
|
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(); |
} |