Rename Target::GetSharedModule to Target::GetOrCreateModule.

Add a flag to control whether the ModulesDidLoad notification is
called when a module is added.  If the notifications are disabled,
the caller must call ModulesDidLoad after adding all the new modules,
but postponing this notification until they're all batched up can
allow for better efficiency than notifying one-by-one.

Change the name of the ModuleList notifier functions that a subclass
can implement to start with 'Notify' to make it clear what they are.
Add a NotifyModulesRemoved.

Add header documentation for the changed/updated methods.

Added defaulted-value 'notify' argument to ModuleList Append,
AppendIfNeeded, and Remove because callers working with a local
ModuleList don't have an obvious idea of what notify means in this
context.  When the ModuleList is a part of the Target class, the
notify behavior matters.

DynamicLoaderDarwin has been updated so that libraries being
added/removed are correctly batched up before notifications are
sent.  Added the TestModuleLoadedNotifys.py test to run on 
Darwin to test this.

<rdar://problem/48293064> 

Differential Revision: https://reviews.llvm.org/D60172

llvm-svn: 357955
diff --git a/lldb/source/API/SBTarget.cpp b/lldb/source/API/SBTarget.cpp
index e17355f..fefc70a 100644
--- a/lldb/source/API/SBTarget.cpp
+++ b/lldb/source/API/SBTarget.cpp
@@ -1591,7 +1591,7 @@
     if (symfile)
       module_spec.GetSymbolFileSpec().SetFile(symfile, FileSpec::Style::native);
 
-    sb_module.SetSP(target_sp->GetSharedModule(module_spec));
+    sb_module.SetSP(target_sp->GetOrCreateModule(module_spec, true /* notify */));
   }
   return LLDB_RECORD_RESULT(sb_module);
 }
@@ -1603,7 +1603,8 @@
   lldb::SBModule sb_module;
   TargetSP target_sp(GetSP());
   if (target_sp)
-    sb_module.SetSP(target_sp->GetSharedModule(*module_spec.m_opaque_up));
+    sb_module.SetSP(target_sp->GetOrCreateModule(*module_spec.m_opaque_up, 
+                                                 true /* notify */));
   return LLDB_RECORD_RESULT(sb_module);
 }
 
diff --git a/lldb/source/Commands/CommandObjectTarget.cpp b/lldb/source/Commands/CommandObjectTarget.cpp
index 6051b6c..a76fb9b 100644
--- a/lldb/source/Commands/CommandObjectTarget.cpp
+++ b/lldb/source/Commands/CommandObjectTarget.cpp
@@ -395,7 +395,8 @@
         debugger.GetTargetList().SetSelectedTarget(target_sp.get());
         if (must_set_platform_path) {
           ModuleSpec main_module_spec(file_spec);
-          ModuleSP module_sp = target_sp->GetSharedModule(main_module_spec);
+          ModuleSP module_sp = target_sp->GetOrCreateModule(main_module_spec,
+                                                          true /* notify */);
           if (module_sp)
             module_sp->SetPlatformFileSpec(remote_file);
         }
@@ -2598,7 +2599,8 @@
             module_spec.GetSymbolFileSpec() =
                 m_symbol_file.GetOptionValue().GetCurrentValue();
           if (Symbols::DownloadObjectAndSymbolFile(module_spec)) {
-            ModuleSP module_sp(target->GetSharedModule(module_spec));
+            ModuleSP module_sp(target->GetOrCreateModule(module_spec,
+                                                 true /* notify */));
             if (module_sp) {
               result.SetStatus(eReturnStatusSuccessFinishResult);
               return true;
@@ -2660,7 +2662,8 @@
             if (!module_spec.GetArchitecture().IsValid())
               module_spec.GetArchitecture() = target->GetArchitecture();
             Status error;
-            ModuleSP module_sp(target->GetSharedModule(module_spec, &error));
+            ModuleSP module_sp(target->GetOrCreateModule(module_spec, 
+                                            true /* notify */, &error));
             if (!module_sp) {
               const char *error_cstr = error.AsCString();
               if (error_cstr)
diff --git a/lldb/source/Core/DynamicLoader.cpp b/lldb/source/Core/DynamicLoader.cpp
index a580539..c773caa 100644
--- a/lldb/source/Core/DynamicLoader.cpp
+++ b/lldb/source/Core/DynamicLoader.cpp
@@ -96,7 +96,7 @@
       }
 
       if (!executable) {
-        executable = target.GetSharedModule(module_spec);
+        executable = target.GetOrCreateModule(module_spec, true /* notify */);
         if (executable.get() != target.GetExecutableModulePointer()) {
           // Don't load dependent images since we are in dyld where we will
           // know and find out about all images that are loaded
@@ -166,7 +166,8 @@
     return module_sp;
   }
 
-  if ((module_sp = target.GetSharedModule(module_spec))) {
+  if ((module_sp = target.GetOrCreateModule(module_spec, 
+                                            true /* notify */))) {
     UpdateLoadedSections(module_sp, link_map_addr, base_addr,
                          base_addr_is_offset);
     return module_sp;
@@ -202,7 +203,8 @@
         return module_sp;
       }
 
-      if ((module_sp = target.GetSharedModule(new_module_spec))) {
+      if ((module_sp = target.GetOrCreateModule(new_module_spec, 
+                                                true /* notify */))) {
         UpdateLoadedSections(module_sp, link_map_addr, base_addr, false);
         return module_sp;
       }
diff --git a/lldb/source/Core/ModuleList.cpp b/lldb/source/Core/ModuleList.cpp
index d59e429..e02c6e5 100644
--- a/lldb/source/Core/ModuleList.cpp
+++ b/lldb/source/Core/ModuleList.cpp
@@ -147,11 +147,13 @@
     std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
     m_modules.push_back(module_sp);
     if (use_notifier && m_notifier)
-      m_notifier->ModuleAdded(*this, module_sp);
+      m_notifier->NotifyModuleAdded(*this, module_sp);
   }
 }
 
-void ModuleList::Append(const ModuleSP &module_sp) { AppendImpl(module_sp); }
+void ModuleList::Append(const ModuleSP &module_sp, bool notify) { 
+  AppendImpl(module_sp, notify); 
+}
 
 void ModuleList::ReplaceEquivalent(const ModuleSP &module_sp) {
   if (module_sp) {
@@ -177,7 +179,7 @@
   }
 }
 
-bool ModuleList::AppendIfNeeded(const ModuleSP &module_sp) {
+bool ModuleList::AppendIfNeeded(const ModuleSP &module_sp, bool notify) {
   if (module_sp) {
     std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
     collection::iterator pos, end = m_modules.end();
@@ -186,7 +188,7 @@
         return false; // Already in the list
     }
     // Only push module_sp on the list if it wasn't already in there.
-    Append(module_sp);
+    Append(module_sp, notify);
     return true;
   }
   return false;
@@ -214,7 +216,7 @@
       if (pos->get() == module_sp.get()) {
         m_modules.erase(pos);
         if (use_notifier && m_notifier)
-          m_notifier->ModuleRemoved(*this, module_sp);
+          m_notifier->NotifyModuleRemoved(*this, module_sp);
         return true;
       }
     }
@@ -228,12 +230,12 @@
   ModuleSP module_sp(*pos);
   collection::iterator retval = m_modules.erase(pos);
   if (use_notifier && m_notifier)
-    m_notifier->ModuleRemoved(*this, module_sp);
+    m_notifier->NotifyModuleRemoved(*this, module_sp);
   return retval;
 }
 
-bool ModuleList::Remove(const ModuleSP &module_sp) {
-  return RemoveImpl(module_sp);
+bool ModuleList::Remove(const ModuleSP &module_sp, bool notify) {
+  return RemoveImpl(module_sp, notify);
 }
 
 bool ModuleList::ReplaceModule(const lldb::ModuleSP &old_module_sp,
@@ -242,7 +244,7 @@
     return false;
   AppendImpl(new_module_sp, false);
   if (m_notifier)
-    m_notifier->ModuleUpdated(*this, old_module_sp, new_module_sp);
+    m_notifier->NotifyModuleUpdated(*this, old_module_sp, new_module_sp);
   return true;
 }
 
@@ -291,9 +293,11 @@
   size_t num_removed = 0;
   collection::iterator pos, end = module_list.m_modules.end();
   for (pos = module_list.m_modules.begin(); pos != end; ++pos) {
-    if (Remove(*pos))
+    if (Remove(*pos, false /* notify */))
       ++num_removed;
   }
+  if (m_notifier)
+    m_notifier->NotifyModulesRemoved(module_list);
   return num_removed;
 }
 
@@ -304,7 +308,7 @@
 void ModuleList::ClearImpl(bool use_notifier) {
   std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
   if (use_notifier && m_notifier)
-    m_notifier->WillClearList(*this);
+    m_notifier->NotifyWillClearList(*this);
   m_modules.clear();
 }
 
diff --git a/lldb/source/Expression/FunctionCaller.cpp b/lldb/source/Expression/FunctionCaller.cpp
index 52c86ff..fa156dc 100644
--- a/lldb/source/Expression/FunctionCaller.cpp
+++ b/lldb/source/Expression/FunctionCaller.cpp
@@ -103,7 +103,8 @@
       jit_file.GetFilename() = const_func_name;
       jit_module_sp->SetFileSpecAndObjectName(jit_file, ConstString());
       m_jit_module_wp = jit_module_sp;
-      process->GetTarget().GetImages().Append(jit_module_sp);
+      process->GetTarget().GetImages().Append(jit_module_sp, 
+                                              true /* notify */);
     }
   }
   if (process && m_jit_start_addr)
diff --git a/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp b/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp
index d88ce1c..45f6d49 100644
--- a/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp
+++ b/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp
@@ -841,7 +841,7 @@
       // the DebugSymbols framework with the UUID to find the binary via its
       // search methods.
       if (!m_module_sp) {
-        m_module_sp = target.GetSharedModule(module_spec);
+        m_module_sp = target.GetOrCreateModule(module_spec, true /* notify */);
       }
 
       if (IsKernel() && !m_module_sp) {
diff --git a/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp b/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp
index e6deab8..0fb05e9 100644
--- a/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp
+++ b/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp
@@ -199,7 +199,7 @@
     return executable;
 
   // TODO: What case is this code used?
-  executable = target.GetSharedModule(module_spec);
+  executable = target.GetOrCreateModule(module_spec, true /* notify */);
   if (executable.get() != target.GetExecutableModulePointer()) {
     // Don't load dependent images since we are in dyld where we will know and
     // find out about all images that are loaded
diff --git a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp
index 87e43eb..086169d 100644
--- a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp
+++ b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp
@@ -122,7 +122,9 @@
 
   if (!module_sp) {
     if (can_create) {
-      module_sp = target.GetSharedModule(module_spec);
+      // We'll call Target::ModulesDidLoad after all the modules have been
+      // added to the target, don't let it be called for every one.
+      module_sp = target.GetOrCreateModule(module_spec, false /* notify */);
       if (!module_sp || module_sp->GetObjectFile() == NULL)
         module_sp = m_process->ReadModuleFromMemory(image_info.file_spec,
                                                     image_info.address);
@@ -637,7 +639,8 @@
               module_spec.SetObjectOffset(objfile->GetFileOffset() +
                                           commpage_section->GetFileOffset());
               module_spec.SetObjectSize(objfile->GetByteSize());
-              commpage_image_module_sp = target.GetSharedModule(module_spec);
+              commpage_image_module_sp = target.GetOrCreateModule(module_spec, 
+                                                               true /* notify */);
               if (!commpage_image_module_sp ||
                   commpage_image_module_sp->GetObjectFile() == NULL) {
                 commpage_image_module_sp = m_process->ReadModuleFromMemory(
diff --git a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
index 6583a80..31ab9fa 100644
--- a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
+++ b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
@@ -543,7 +543,8 @@
   FileSpec file(info.GetName().GetCString());
   ModuleSpec module_spec(file, target.GetArchitecture());
 
-  if (ModuleSP module_sp = target.GetSharedModule(module_spec)) {
+  if (ModuleSP module_sp = target.GetOrCreateModule(module_spec, 
+                                                    true /* notify */)) {
     UpdateLoadedSections(module_sp, LLDB_INVALID_ADDRESS, m_interpreter_base,
                          false);
     return module_sp;
diff --git a/lldb/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp b/lldb/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp
index a2a17b2..fa3fbe0 100644
--- a/lldb/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp
+++ b/lldb/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp
@@ -68,11 +68,9 @@
 
   // Resolve the module unless we already have one.
   if (!module_sp) {
-    // Confusingly, there is no Target::AddSharedModule.  Instead, calling
-    // GetSharedModule() with a new module will add it to the module list and
-    // return a corresponding ModuleSP.
     Status error;
-    module_sp = m_process->GetTarget().GetSharedModule(module_spec, &error);
+    module_sp = m_process->GetTarget().GetOrCreateModule(module_spec, 
+                                             true /* notify */, &error);
     if (error.Fail())
       return;
   }
diff --git a/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp b/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp
index 2a248f6..e9146b5 100644
--- a/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp
+++ b/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp
@@ -915,7 +915,8 @@
     FileSystem::Instance().Resolve(executable_file);
     ModuleSpec module_spec(executable_file);
     Status error;
-    module = GetTarget().GetSharedModule(module_spec, &error);
+    module = GetTarget().GetOrCreateModule(module_spec, 
+                                           true /* notify */, &error);
     if (!module) {
       return;
     }
diff --git a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
index 1c79705..21c9be5 100644
--- a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
+++ b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
@@ -244,7 +244,8 @@
       exe_module_spec.GetFileSpec().SetFile(
           m_nt_file_entries[0].path.GetCString(), FileSpec::Style::native);
       if (exe_module_spec.GetFileSpec()) {
-        exe_module_sp = GetTarget().GetSharedModule(exe_module_spec);
+        exe_module_sp = GetTarget().GetOrCreateModule(exe_module_spec, 
+                                                      true /* notify */);
         if (exe_module_sp)
           GetTarget().SetExecutableModule(exe_module_sp, eLoadDependentsNo);
       }
diff --git a/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp b/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp
index d6ab58c..3da103b 100644
--- a/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp
+++ b/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp
@@ -388,7 +388,8 @@
     Status error;
     // Try and find a module with a full UUID that matches. This function will
     // add the module to the target if it finds one.
-    lldb::ModuleSP module_sp = GetTarget().GetSharedModule(module_spec, &error);
+    lldb::ModuleSP module_sp = GetTarget().GetOrCreateModule(module_spec, 
+                                                     true /* notify */, &error);
     if (!module_sp) {
       // Try and find a module without specifying the UUID and only looking for
       // the file given a basename. We then will look for a partial UUID match
@@ -400,7 +401,8 @@
       ModuleSpec basename_module_spec(module_spec);
       basename_module_spec.GetUUID().Clear();
       basename_module_spec.GetFileSpec().GetDirectory().Clear();
-      module_sp = GetTarget().GetSharedModule(basename_module_spec, &error);
+      module_sp = GetTarget().GetOrCreateModule(basename_module_spec, 
+                                                     true /* notify */, &error);
       if (module_sp) {
         // We consider the module to be a match if the minidump UUID is a
         // prefix of the actual UUID, or if either of the UUIDs are empty.
@@ -430,7 +432,7 @@
 
       module_sp = Module::CreateModuleFromObjectFile<PlaceholderObjectFile>(
           module_spec, module->base_of_image, module->size_of_image);
-      GetTarget().GetImages().Append(module_sp);
+      GetTarget().GetImages().Append(module_sp, true /* notify */);
     }
 
     bool load_addr_changed = false;
diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp
index a1bf4d9..f382813 100644
--- a/lldb/source/Target/Target.cpp
+++ b/lldb/source/Target/Target.cpp
@@ -1442,7 +1442,8 @@
                        "Target::SetExecutableModule (executable = '%s')",
                        executable_sp->GetFileSpec().GetPath().c_str());
 
-    m_images.Append(executable_sp); // The first image is our executable file
+    const bool notify = true;
+    m_images.Append(executable_sp, notify); // The first image is our executable file
 
     // If we haven't set an architecture yet, reset our architecture based on
     // what we found in the executable module.
@@ -1470,6 +1471,7 @@
     }
 
     if (executable_objfile && load_dependents) {
+      ModuleList added_modules;
       executable_objfile->GetDependentModules(dependent_files);
       for (uint32_t i = 0; i < dependent_files.GetSize(); i++) {
         FileSpec dependent_file_spec(
@@ -1482,13 +1484,16 @@
           platform_dependent_file_spec = dependent_file_spec;
 
         ModuleSpec module_spec(platform_dependent_file_spec, m_arch.GetSpec());
-        ModuleSP image_module_sp(GetSharedModule(module_spec));
+        ModuleSP image_module_sp(GetOrCreateModule(module_spec, 
+                                 false /* notify */));
         if (image_module_sp) {
+          added_modules.AppendIfNeeded (image_module_sp, false);
           ObjectFile *objfile = image_module_sp->GetObjectFile();
           if (objfile)
             objfile->GetDependentModules(dependent_files);
         }
       }
+      ModulesDidLoad(added_modules);
     }
   }
 }
@@ -1606,20 +1611,19 @@
   return false;
 }
 
-void Target::WillClearList(const ModuleList &module_list) {}
+void Target::NotifyWillClearList(const ModuleList &module_list) {}
 
-void Target::ModuleAdded(const ModuleList &module_list,
+void Target::NotifyModuleAdded(const ModuleList &module_list,
                          const ModuleSP &module_sp) {
   // A module is being added to this target for the first time
   if (m_valid) {
     ModuleList my_module_list;
     my_module_list.Append(module_sp);
-    LoadScriptingResourceForModule(module_sp, this);
     ModulesDidLoad(my_module_list);
   }
 }
 
-void Target::ModuleRemoved(const ModuleList &module_list,
+void Target::NotifyModuleRemoved(const ModuleList &module_list,
                            const ModuleSP &module_sp) {
   // A module is being removed from this target.
   if (m_valid) {
@@ -1629,7 +1633,7 @@
   }
 }
 
-void Target::ModuleUpdated(const ModuleList &module_list,
+void Target::NotifyModuleUpdated(const ModuleList &module_list,
                            const ModuleSP &old_module_sp,
                            const ModuleSP &new_module_sp) {
   // A module is replacing an already added module
@@ -1641,8 +1645,20 @@
   }
 }
 
+void Target::NotifyModulesRemoved(lldb_private::ModuleList &module_list) {
+  ModulesDidUnload (module_list, false);
+}
+
+
 void Target::ModulesDidLoad(ModuleList &module_list) {
   if (m_valid && module_list.GetSize()) {
+
+    const ModuleList &modules = GetImages();
+    const size_t num_images = modules.GetSize();
+    for (size_t idx = 0; idx < num_images; ++idx) {
+      ModuleSP module_sp(modules.GetModuleAtIndex(idx));
+      LoadScriptingResourceForModule(module_sp, this);
+    }
     m_breakpoint_list.UpdateBreakpoints(module_list, true, false);
     m_internal_breakpoint_list.UpdateBreakpoints(module_list, true, false);
     if (m_process_sp) {
@@ -1984,8 +2000,8 @@
   return false;
 }
 
-ModuleSP Target::GetSharedModule(const ModuleSpec &module_spec,
-                                 Status *error_ptr) {
+ModuleSP Target::GetOrCreateModule(const ModuleSpec &module_spec, bool notify,
+                                   Status *error_ptr) {
   ModuleSP module_sp;
 
   Status error;
@@ -2118,8 +2134,9 @@
           Module *old_module_ptr = old_module_sp.get();
           old_module_sp.reset();
           ModuleList::RemoveSharedModuleIfOrphaned(old_module_ptr);
-        } else
-          m_images.Append(module_sp);
+        } else {
+          m_images.Append(module_sp, notify);
+        }
       } else
         module_sp.reset();
     }