Index: runtime/vm/object.cc |
=================================================================== |
--- runtime/vm/object.cc (revision 40420) |
+++ runtime/vm/object.cc (working copy) |
@@ -8745,19 +8745,46 @@ |
} |
+// Traits for looking up Libraries by url in a hash set. |
+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 uword Hash(const Object& key) { |
+ return Library::Cast(key).UrlHash(); |
+ } |
+}; |
+ |
+ |
+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 +9968,26 @@ |
RawInstance* LibraryPrefix::LoadError() const { |
- Library& lib = Library::Handle(); |
- Instance& error = Instance::Handle(); |
+ Isolate* isolate = Isolate::Current(); |
+ ObjectStore* object_store = isolate->object_store(); |
+ GrowableObjectArray& libs = |
+ GrowableObjectArray::Handle(isolate, object_store->libraries()); |
+ ASSERT(!libs.IsNull()); |
+ LibraryLoadErrorSet set(HashTables::New<LibraryLoadErrorSet>(libs.Length())); |
+ 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()); |
+ HANDLESCOPE(isolate); |
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(); |
} |