@@ -447,11 +447,41 @@ static bool HasReflectionInfo(ObjectFile *obj_file) {
447
447
return hasReflectionSection;
448
448
}
449
449
450
- SwiftLanguageRuntimeImpl::ReflectionContextInterface *
450
+ SwiftLanguageRuntimeImpl::ThreadSafeReflectionContext
451
451
SwiftLanguageRuntimeImpl::GetReflectionContext () {
452
- if (!m_initialized_reflection_ctx)
453
- SetupReflection ();
454
- return m_reflection_ctx.get ();
452
+ m_reflection_ctx_mutex.lock ();
453
+ SetupReflection ();
454
+ // SetupReflection can potentially fail.
455
+ if (m_initialized_reflection_ctx)
456
+ ProcessModulesToAdd ();
457
+ return {m_reflection_ctx.get (), m_reflection_ctx_mutex};
458
+ }
459
+
460
+ void SwiftLanguageRuntimeImpl::ProcessModulesToAdd () {
461
+ // A snapshot of the modules to be processed. This is necessary because
462
+ // AddModuleToReflectionContext may recursively call into this function again.
463
+ ModuleList modules_to_add_snapshot;
464
+ modules_to_add_snapshot.Swap (m_modules_to_add);
465
+
466
+ if (modules_to_add_snapshot.IsEmpty ())
467
+ return ;
468
+
469
+ auto &target = m_process.GetTarget ();
470
+ auto exe_module = target.GetExecutableModule ();
471
+ Progress progress (
472
+ llvm::formatv (" Setting up Swift reflection for '{0}'" ,
473
+ exe_module->GetFileSpec ().GetFilename ().AsCString ()),
474
+ modules_to_add_snapshot.GetSize ());
475
+
476
+ size_t completion = 0 ;
477
+
478
+ // Add all defered modules to reflection context that were added to
479
+ // the target since this SwiftLanguageRuntime was created.
480
+ modules_to_add_snapshot.ForEach ([&](const ModuleSP &module_sp) -> bool {
481
+ AddModuleToReflectionContext (module_sp);
482
+ progress.Increment (++completion);
483
+ return true ;
484
+ });
455
485
}
456
486
457
487
SwiftMetadataCache *
@@ -463,79 +493,53 @@ SwiftLanguageRuntimeImpl::GetSwiftMetadataCache() {
463
493
464
494
void SwiftLanguageRuntimeImpl::SetupReflection () {
465
495
LLDB_SCOPED_TIMER ();
466
-
467
- // SetupABIBit() iterates of the Target's images and thus needs to
468
- // acquire that ModuleList's lock. We need to acquire this before
469
- // locking m_add_module_mutex, since ModulesDidLoad can also be
470
- // called from a place where that lock is already held:
471
- // + lldb_private::DynamicLoaderDarwin::AddModulesUsingImageInfos()
472
- // + lldb_private::ModuleList::AppendIfNeeded()
473
- // + lldb_private::Target::NotifyModuleAdded()
474
- // + lldb_private::Target::ModulesDidLoad()
475
496
497
+
498
+ std::lock_guard<std::recursive_mutex> lock (m_reflection_ctx_mutex);
499
+ if (m_initialized_reflection_ctx)
500
+ return ;
501
+
476
502
// The global ABI bit is read by the Swift runtime library.
477
503
SetupABIBit ();
478
504
479
- // A copy of the modules that should be added, to prevent mutating the list
480
- // while iterating over it.
481
- ModuleList modules_snapshot;
482
-
483
505
auto &target = m_process.GetTarget ();
484
506
auto exe_module = target.GetExecutableModule ();
485
- {
486
- std::lock_guard<std::recursive_mutex> lock (m_add_module_mutex);
487
- if (m_initialized_reflection_ctx)
488
- return ;
489
-
490
- if (!exe_module) {
491
- LLDB_LOGF (GetLog (LLDBLog::Types), " %s: Failed to get executable module" ,
492
- LLVM_PRETTY_FUNCTION);
493
- m_initialized_reflection_ctx = false ;
494
- return ;
495
- }
496
507
497
- bool objc_interop = (bool )findRuntime (m_process, RuntimeKind::ObjC);
498
- const char *objc_interop_msg =
499
- objc_interop ? " with Objective-C interopability" : " Swift only" ;
500
-
501
- auto &triple = exe_module->GetArchitecture ().GetTriple ();
502
- if (triple.isArch64Bit ()) {
503
- LLDB_LOGF (GetLog (LLDBLog::Types),
504
- " Initializing a 64-bit reflection context (%s) for \" %s\" " ,
505
- triple.str ().c_str (), objc_interop_msg);
506
- m_reflection_ctx = ReflectionContextInterface::CreateReflectionContext64 (
507
- this ->GetMemoryReader (), objc_interop, GetSwiftMetadataCache ());
508
- } else if (triple.isArch32Bit ()) {
509
- LLDB_LOGF (GetLog (LLDBLog::Types),
510
- " Initializing a 32-bit reflection context (%s) for \" %s\" " ,
511
- triple.str ().c_str (), objc_interop_msg);
512
- m_reflection_ctx = ReflectionContextInterface::CreateReflectionContext32 (
513
- this ->GetMemoryReader (), objc_interop, GetSwiftMetadataCache ());
514
- } else {
515
- LLDB_LOGF (GetLog (LLDBLog::Types),
516
- " Could not initialize reflection context for \" %s\" " ,
517
- triple.str ().c_str ());
518
- }
519
-
520
- modules_snapshot = std::move (m_modules_to_add);
521
- m_modules_to_add.Clear ();
522
- m_initialized_reflection_ctx = true ;
508
+ auto *log = GetLog (LLDBLog::Types);
509
+ if (!exe_module) {
510
+ LLDB_LOGF (log, " %s: Failed to get executable module" ,
511
+ LLVM_PRETTY_FUNCTION);
512
+ m_initialized_reflection_ctx = false ;
513
+ return ;
523
514
}
524
515
525
- Progress progress (
526
- llvm::formatv (" Setting up Swift reflection for '{0}'" ,
527
- exe_module->GetFileSpec ().GetFilename ().AsCString ()),
528
- modules_snapshot.GetSize ());
529
-
530
- size_t completion = 0 ;
531
-
532
- // Add all defered modules to reflection context that were added to
533
- // the target since this SwiftLanguageRuntime was created.
534
- modules_snapshot.ForEach ([&](const ModuleSP &module_sp) -> bool {
535
- AddModuleToReflectionContext (module_sp);
536
- progress.Increment (++completion);
537
- return true ;
538
- });
516
+ bool objc_interop = (bool )findRuntime (m_process, RuntimeKind::ObjC);
517
+ const char *objc_interop_msg =
518
+ objc_interop ? " with Objective-C interopability" : " Swift only" ;
519
+
520
+ auto &triple = exe_module->GetArchitecture ().GetTriple ();
521
+ if (triple.isArch64Bit ()) {
522
+ LLDB_LOGF (log, " Initializing a 64-bit reflection context (%s) for \" %s\" " ,
523
+ triple.str ().c_str (), objc_interop_msg);
524
+ m_reflection_ctx = ReflectionContextInterface::CreateReflectionContext64 (
525
+ this ->GetMemoryReader (), objc_interop, GetSwiftMetadataCache ());
526
+ } else if (triple.isArch32Bit ()) {
527
+ LLDB_LOGF (log,
528
+ " Initializing a 32-bit reflection context (%s) for \" %s\" " ,
529
+ triple.str ().c_str (), objc_interop_msg);
530
+ m_reflection_ctx = ReflectionContextInterface::CreateReflectionContext32 (
531
+ this ->GetMemoryReader (), objc_interop, GetSwiftMetadataCache ());
532
+ } else {
533
+ LLDB_LOGF (log,
534
+ " Could not initialize reflection context for \" %s\" " ,
535
+ triple.str ().c_str ());
536
+ }
537
+ // We set m_initialized_reflection_ctx to true here because
538
+ // AddModuleToReflectionContext can potentially call into SetupReflection
539
+ // again (which will early exit). This is safe to do since every other thread
540
+ // using reflection context will have to wait until all the modules are added,
541
+ // since the thread performing the initialization locked the mutex.
542
+ m_initialized_reflection_ctx = true ;
539
543
}
540
544
541
545
bool SwiftLanguageRuntimeImpl::IsABIStable () {
@@ -922,17 +926,9 @@ bool SwiftLanguageRuntimeImpl::AddModuleToReflectionContext(
922
926
}
923
927
924
928
void SwiftLanguageRuntimeImpl::ModulesDidLoad (const ModuleList &module_list) {
925
- // If the reflection context hasn't been initialized, add them to
926
- // the list of deferred modules so they are added in
927
- // SetupReflection(), otherwise add them directly.
928
- std::lock_guard<std::recursive_mutex> lock (m_add_module_mutex);
929
- if (!m_initialized_reflection_ctx)
930
- m_modules_to_add.AppendIfNeeded (module_list);
931
- else
932
- module_list.ForEach ([&](const ModuleSP &module_sp) -> bool {
933
- AddModuleToReflectionContext (module_sp);
934
- return true ;
935
- });
929
+ // The modules will be lazily processed on the next call to
930
+ // GetReflectionContext.
931
+ m_modules_to_add.AppendIfNeeded (module_list);
936
932
}
937
933
938
934
std::string
0 commit comments