Fixed issues with the unwinding code where the collection of FuncUnwinders
was being searched and sorted using a shared pointer as the value which means
the pointer value was what was being searched for. This means that anytime
you did a stack backtrace, the collection of FuncUnwinders doubled and then
the array or shared pointer got sorted (by pointer value), so you had an ever
increasing collection of shared pointer where a match was never found. This
means we had a ton of duplicates in this table and would cause issues after
one had been debugging for a long time.



git-svn-id: https://llvm.org/svn/llvm-project/llvdb/trunk@123045 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Symbol/FuncUnwinders.cpp b/source/Symbol/FuncUnwinders.cpp
index 265ba7c..126ddd2 100644
--- a/source/Symbol/FuncUnwinders.cpp
+++ b/source/Symbol/FuncUnwinders.cpp
@@ -24,109 +24,101 @@
 using namespace lldb_private;
 
 
-FuncUnwinders::FuncUnwinders (UnwindTable& unwind_table, UnwindAssemblyProfiler *assembly_profiler, AddressRange range) : 
-        m_unwind_table(unwind_table), 
-        m_assembly_profiler(assembly_profiler), 
-        m_range(range), 
-        m_unwind_at_call_site(NULL), 
-        m_unwind_at_non_call_site(NULL), 
-        m_fast_unwind(NULL), 
-        m_arch_default_unwind(NULL), 
-        m_first_non_prologue_insn() { }
+FuncUnwinders::FuncUnwinders
+(
+    UnwindTable& unwind_table, 
+    UnwindAssemblyProfiler *assembly_profiler, 
+    AddressRange range
+) : 
+    m_unwind_table(unwind_table), 
+    m_assembly_profiler(assembly_profiler), 
+    m_range(range), 
+    m_unwind_at_call_site_ap (), 
+    m_unwind_at_non_call_site_ap (), 
+    m_fast_unwind_ap (), 
+    m_arch_default_unwind (NULL), 
+    m_tried_unwind_at_call_site (false),
+    m_tried_unwind_at_non_call_site (false),
+    m_tried_fast_unwind (false),
+    m_tried_arch_default_unwind (false),
+    m_first_non_prologue_insn() 
+{
+}
 
 FuncUnwinders::~FuncUnwinders () 
 { 
-  if (m_unwind_at_call_site)
-      delete m_unwind_at_call_site;
-  if (m_unwind_at_non_call_site)
-      delete m_unwind_at_non_call_site;
-  if (m_fast_unwind)
-      delete m_fast_unwind;
-  if (m_arch_default_unwind)
-      delete m_arch_default_unwind;
 }
 
 UnwindPlan*
 FuncUnwinders::GetUnwindPlanAtCallSite (int current_offset)
 {
-    if (m_unwind_at_call_site != NULL)
-        return m_unwind_at_call_site;
-    if (!m_range.GetBaseAddress().IsValid())
-        return NULL;
-
-    // We have cases (e.g. with _sigtramp on Mac OS X) where the hand-written eh_frame unwind info for a
-    // function does not cover the entire range of the function and so the FDE only lists a subset of the
-    // address range.  If we try to look up the unwind info by the starting address of the function 
-    // (i.e. m_range.GetBaseAddress()) we may not find the eh_frame FDE.  We need to use the actual byte offset
-    // into the function when looking it up.
-
-    Address current_pc (m_range.GetBaseAddress ());
-    if (current_offset != -1)
-        current_pc.SetOffset (current_pc.GetOffset() + current_offset);
-
-    DWARFCallFrameInfo *eh_frame = m_unwind_table.GetEHFrameInfo();
-    UnwindPlan *up = NULL;
-    if (eh_frame)
+    if (m_tried_unwind_at_call_site == false && m_unwind_at_call_site_ap.get() == NULL)
     {
-        up = new UnwindPlan;
-        if (!eh_frame->GetUnwindPlan (current_pc, *up))
+        m_tried_unwind_at_call_site = true;
+        // We have cases (e.g. with _sigtramp on Mac OS X) where the hand-written eh_frame unwind info for a
+        // function does not cover the entire range of the function and so the FDE only lists a subset of the
+        // address range.  If we try to look up the unwind info by the starting address of the function 
+        // (i.e. m_range.GetBaseAddress()) we may not find the eh_frame FDE.  We need to use the actual byte offset
+        // into the function when looking it up.
+
+        if (m_range.GetBaseAddress().IsValid())
         {
-            delete up;
-            return NULL;
+            Address current_pc (m_range.GetBaseAddress ());
+            if (current_offset != -1)
+                current_pc.SetOffset (current_pc.GetOffset() + current_offset);
+
+            DWARFCallFrameInfo *eh_frame = m_unwind_table.GetEHFrameInfo();
+            if (eh_frame)
+            {
+                m_unwind_at_call_site_ap.reset (new UnwindPlan);
+                if (!eh_frame->GetUnwindPlan (current_pc, *m_unwind_at_call_site_ap))
+                    m_unwind_at_call_site_ap.reset();
+            }
         }
     }
-    if (!up)
-        return NULL;
-
-    m_unwind_at_call_site = up;
-    return m_unwind_at_call_site;
+    return m_unwind_at_call_site_ap.get();
 }
 
 UnwindPlan*
 FuncUnwinders::GetUnwindPlanAtNonCallSite (Thread& thread)
 {
-    if (m_unwind_at_non_call_site != NULL)
-        return m_unwind_at_non_call_site;
-    UnwindPlan *up = new UnwindPlan;
-    if (!m_assembly_profiler->GetNonCallSiteUnwindPlanFromAssembly (m_range, thread, *up))
+    if (m_tried_unwind_at_non_call_site == false && m_unwind_at_non_call_site_ap.get() == NULL)
     {
-        delete up;
-        return NULL;
+        m_tried_unwind_at_non_call_site = true;
+        m_unwind_at_non_call_site_ap.reset (new UnwindPlan);
+        if (!m_assembly_profiler->GetNonCallSiteUnwindPlanFromAssembly (m_range, thread, *m_unwind_at_non_call_site_ap))
+            m_unwind_at_non_call_site_ap.reset();
     }
-    m_unwind_at_non_call_site = up;
-    return m_unwind_at_non_call_site;
+    return m_unwind_at_non_call_site_ap.get();
 }
 
 UnwindPlan*
 FuncUnwinders::GetUnwindPlanFastUnwind (Thread& thread)
 {
-    if (m_fast_unwind != NULL)
-        return m_fast_unwind;
-    UnwindPlan *up = new UnwindPlan;
-    if (!m_assembly_profiler->GetFastUnwindPlan (m_range, thread, *up))
+    if (m_tried_fast_unwind == false && m_fast_unwind_ap.get() == NULL)
     {
-        delete up;
-        return NULL;
+        m_tried_fast_unwind = true;
+        m_fast_unwind_ap.reset (new UnwindPlan);
+        if (!m_assembly_profiler->GetFastUnwindPlan (m_range, thread, *m_fast_unwind_ap))
+            m_fast_unwind_ap.reset();
     }
-    m_fast_unwind = up;
-    return m_fast_unwind;
+    return m_fast_unwind_ap.get();
 }
 
 UnwindPlan*
 FuncUnwinders::GetUnwindPlanArchitectureDefault (Thread& thread)
 {
-    if (m_arch_default_unwind != NULL)
-        return m_arch_default_unwind;
-
-    Address current_pc;
-    Target *target = thread.CalculateTarget();
-    if (target)
+    if (m_tried_arch_default_unwind == false && m_arch_default_unwind == NULL)
     {
-        ArchSpec arch = target->GetArchitecture ();
-        ArchDefaultUnwindPlan *arch_default = ArchDefaultUnwindPlan::FindPlugin (arch);
-        if (arch_default)
+        m_tried_arch_default_unwind = true;
+        Address current_pc;
+        Target *target = thread.CalculateTarget();
+        if (target)
         {
-            m_arch_default_unwind = arch_default->GetArchDefaultUnwindPlan (thread, current_pc);
+            ArchSpec arch = target->GetArchitecture ();
+            ArchDefaultUnwindPlan *arch_default = ArchDefaultUnwindPlan::FindPlugin (arch);
+            if (arch_default)
+                m_arch_default_unwind = arch_default->GetArchDefaultUnwindPlan (thread, current_pc);
         }
     }