diff --git a/lldb/include/lldb/Core/ConstString.h b/lldb/include/lldb/Core/ConstString.h index 763534cae804..72c6b56f3c8c 100644 --- a/lldb/include/lldb/Core/ConstString.h +++ b/lldb/include/lldb/Core/ConstString.h @@ -338,6 +338,12 @@ public: void SetCString (const char *cstr); + void + SetCStringWithMangledCounterpart (const char *demangled, const ConstString &mangled); + + bool + GetMangledCounterpart (ConstString &counterpart) const; + //------------------------------------------------------------------ /// Set the C string value with length. /// diff --git a/lldb/include/lldb/Core/History.h b/lldb/include/lldb/Core/History.h new file mode 100644 index 000000000000..181677392e44 --- /dev/null +++ b/lldb/include/lldb/Core/History.h @@ -0,0 +1,177 @@ +//===-- History.h -----------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef lldb_History_h_ +#define lldb_History_h_ + +// C Includes +#include + +// C++ Includes +#include +#include + +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-public.h" +#include "lldb/Host/Mutex.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class HistorySource History.h "lldb/Core/History.h" +/// @brief A class that defines history events. +//---------------------------------------------------------------------- + +class HistorySource +{ +public: + typedef const void * HistoryEvent; + + HistorySource () : + m_mutex (Mutex::eMutexTypeRecursive), + m_events () + { + } + + virtual + ~HistorySource() + { + } + + // Create a new history event. Subclasses should use any data or members + // in the subclass of this class to produce a history event and push it + // onto the end of the history stack. + + virtual HistoryEvent + CreateHistoryEvent () = 0; + + virtual void + DeleteHistoryEvent (HistoryEvent event) = 0; + + virtual void + DumpHistoryEvent (Stream &strm, HistoryEvent event) = 0; + + virtual size_t + GetHistoryEventCount() = 0; + + virtual HistoryEvent + GetHistoryEventAtIndex (uint32_t idx) = 0; + + virtual HistoryEvent + GetCurrentHistoryEvent () = 0; + + // Return 0 when lhs == rhs, 1 if lhs > rhs, or -1 if lhs < rhs. + virtual int + CompareHistoryEvents (const HistoryEvent lhs, + const HistoryEvent rhs); + + virtual bool + IsCurrentHistoryEvent (const HistoryEvent event); + +private: + typedef std::stack collection; + + Mutex m_mutex; + collection m_events; + + DISALLOW_COPY_AND_ASSIGN (HistorySource); + +}; + +//---------------------------------------------------------------------- +/// @class HistorySourceUInt History.h "lldb/Core/History.h" +/// @brief A class that defines history events that are represented by +/// unsigned integers. +/// +/// Any history event that is defined by a unique monotonically +/// increasing unsigned integer +//---------------------------------------------------------------------- + +class HistorySourceUInt : public HistorySource +{ + HistorySourceUInt (const char *id_name, uintptr_t start_value = 0u) : + HistorySource(), + m_name (id_name), + m_curr_id (start_value) + { + } + + virtual + ~HistorySourceUInt() + { + } + + // Create a new history event. Subclasses should use any data or members + // in the subclass of this class to produce a history event and push it + // onto the end of the history stack. + + virtual HistoryEvent + CreateHistoryEvent () + { + ++m_curr_id; + return (HistoryEvent)m_curr_id; + } + + virtual void + DeleteHistoryEvent (HistoryEvent event) + { + // Nothing to delete, the event contains the integer + } + + virtual void + DumpHistoryEvent (Stream &strm, HistoryEvent event); + + virtual size_t + GetHistoryEventCount() + { + return m_curr_id; + } + + virtual HistoryEvent + GetHistoryEventAtIndex (uint32_t idx) + { + return (HistoryEvent)((uintptr_t)idx); + } + + virtual HistoryEvent + GetCurrentHistoryEvent () + { + return (HistoryEvent)m_curr_id; + } + + // Return 0 when lhs == rhs, 1 if lhs > rhs, or -1 if lhs < rhs. + virtual int + CompareHistoryEvents (const HistoryEvent lhs, + const HistoryEvent rhs) + { + uintptr_t lhs_uint = (uintptr_t)lhs; + uintptr_t rhs_uint = (uintptr_t)rhs; + if (lhs_uint < rhs_uint) + return -1; + if (lhs_uint > rhs_uint) + return +1; + return 0; + } + + virtual bool + IsCurrentHistoryEvent (const HistoryEvent event) + { + return (uintptr_t)event == m_curr_id; + } + +protected: + std::string m_name; // The name of the history unsigned integer + uintptr_t m_curr_id; // The current value of the history unsigned unteger +}; + + +} // namespace lldb_private + +#endif // lldb_History_h_ diff --git a/lldb/lldb.xcodeproj/project.pbxproj b/lldb/lldb.xcodeproj/project.pbxproj index fb7e13addba0..7ff679883f64 100644 --- a/lldb/lldb.xcodeproj/project.pbxproj +++ b/lldb/lldb.xcodeproj/project.pbxproj @@ -393,6 +393,7 @@ 26F5C32D10F3DFDD009D5894 /* libtermcap.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 26F5C32B10F3DFDD009D5894 /* libtermcap.dylib */; }; 26F5C37510F3F61B009D5894 /* libobjc.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 26F5C37410F3F61B009D5894 /* libobjc.dylib */; }; 26F5C39110F3FA26009D5894 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 26F5C39010F3FA26009D5894 /* CoreFoundation.framework */; }; + 26F73062139D8FDB00FD51C7 /* History.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26F73061139D8FDB00FD51C7 /* History.cpp */; }; 49C850771384A02F007DB519 /* ProcessDataAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = 49C850761384A02F007DB519 /* ProcessDataAllocator.h */; }; 49C8507C1384A786007DB519 /* ProcessDataAllocator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49C850781384A0CA007DB519 /* ProcessDataAllocator.cpp */; }; 4C74CB6312288704006A8171 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C74CB6212288704006A8171 /* Carbon.framework */; }; @@ -1054,6 +1055,8 @@ 26F5C32B10F3DFDD009D5894 /* libtermcap.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libtermcap.dylib; path = /usr/lib/libtermcap.dylib; sourceTree = ""; }; 26F5C37410F3F61B009D5894 /* libobjc.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libobjc.dylib; path = /usr/lib/libobjc.dylib; sourceTree = ""; }; 26F5C39010F3FA26009D5894 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = /System/Library/Frameworks/CoreFoundation.framework; sourceTree = ""; }; + 26F7305F139D8FC900FD51C7 /* History.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = History.h; path = include/lldb/Core/History.h; sourceTree = ""; }; + 26F73061139D8FDB00FD51C7 /* History.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = History.cpp; path = source/Core/History.cpp; sourceTree = ""; }; 26F996A7119B79C300412154 /* ARM_DWARF_Registers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ARM_DWARF_Registers.h; path = source/Utility/ARM_DWARF_Registers.h; sourceTree = ""; }; 26F996A8119B79C300412154 /* ARM_GCC_Registers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ARM_GCC_Registers.h; path = source/Utility/ARM_GCC_Registers.h; sourceTree = ""; }; 26FA4315130103F400E71120 /* FileSpec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FileSpec.h; path = include/lldb/Host/FileSpec.h; sourceTree = ""; }; @@ -1896,6 +1899,8 @@ 26BC7D6310F1B77400F91463 /* FileSpecList.h */, 26BC7E7B10F1B85900F91463 /* FileSpecList.cpp */, 26BC7D6410F1B77400F91463 /* Flags.h */, + 26F7305F139D8FC900FD51C7 /* History.h */, + 26F73061139D8FDB00FD51C7 /* History.cpp */, 9AA69DBB118A029E00D753A0 /* InputReader.h */, 9AA69DB5118A027A00D753A0 /* InputReader.cpp */, 9A9E1F0013980943005AC039 /* InputReaderStack.h */, @@ -3215,6 +3220,7 @@ 2690B3711381D5C300ECFBAE /* Memory.cpp in Sources */, 9A9E1EFF1398086D005AC039 /* InputReaderStack.cpp in Sources */, B28058A1139988B0002D96D0 /* InferiorCallPOSIX.cpp in Sources */, + 26F73062139D8FDB00FD51C7 /* History.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/lldb/source/Core/ConstString.cpp b/lldb/source/Core/ConstString.cpp index e3b0623502d1..94dd43da8a08 100644 --- a/lldb/source/Core/ConstString.cpp +++ b/lldb/source/Core/ConstString.cpp @@ -32,6 +32,10 @@ using namespace lldb_private; class Pool { public: + typedef const char * StringPoolValueType; + typedef llvm::StringMap StringPool; + typedef llvm::StringMapEntry StringPoolEntryType; + //------------------------------------------------------------------ // Default constructor // @@ -51,24 +55,44 @@ public: } - static llvm::StringMapEntry & + static StringPoolEntryType & GetStringMapEntryFromKeyData (const char *keyData) { - char *ptr = const_cast(keyData) - sizeof (llvm::StringMapEntry); - return *reinterpret_cast*>(ptr); + char *ptr = const_cast(keyData) - sizeof (StringPoolEntryType); + return *reinterpret_cast(ptr); } size_t - GetConstCStringLength (const char *ccstr) + GetConstCStringLength (const char *ccstr) const { if (ccstr) { - llvm::StringMapEntry&entry = GetStringMapEntryFromKeyData (ccstr); + const StringPoolEntryType&entry = GetStringMapEntryFromKeyData (ccstr); return entry.getKey().size(); } return 0; } + StringPoolValueType + GetMangledCounterpart (const char *ccstr) const + { + if (ccstr) + return GetStringMapEntryFromKeyData (ccstr).getValue(); + return 0; + } + + bool + SetMangledCounterparts (const char *key_ccstr, const char *value_ccstr) + { + if (key_ccstr && value_ccstr) + { + GetStringMapEntryFromKeyData (key_ccstr).setValue(value_ccstr); + GetStringMapEntryFromKeyData (value_ccstr).setValue(key_ccstr); + return true; + } + return false; + } + const char * GetConstCString (const char *cstr) { @@ -84,12 +108,32 @@ public: { Mutex::Locker locker (m_mutex); llvm::StringRef string_ref (cstr, cstr_len); - llvm::StringMapEntry& entry = m_string_map.GetOrCreateValue (string_ref); + StringPoolEntryType& entry = m_string_map.GetOrCreateValue (string_ref); return entry.getKeyData(); } return NULL; } + const char * + GetConstCStringAndSetMangledCounterPart (const char *demangled_cstr, const char *mangled_ccstr) + { + if (demangled_cstr) + { + Mutex::Locker locker (m_mutex); + // Make string pool entry with the mangled counterpart already set + StringPoolEntryType& entry = m_string_map.GetOrCreateValue (llvm::StringRef (demangled_cstr), mangled_ccstr); + + // Extract the const version of the demangled_cstr + const char *demangled_ccstr = entry.getKeyData(); + // Now assign the demangled const string as the counterpart of the + // mangled const string... + GetStringMapEntryFromKeyData (mangled_ccstr).setValue(demangled_ccstr); + // Return the constant demangled C string + return demangled_ccstr; + } + return NULL; + } + const char * GetConstTrimmedCStringWithLength (const char *cstr, int cstr_len) { @@ -114,7 +158,7 @@ public: const_iterator end = m_string_map.end(); for (const_iterator pos = m_string_map.begin(); pos != end; ++pos) { - mem_size += sizeof(llvm::StringMapEntry) + pos->getKey().size(); + mem_size += sizeof(StringPoolEntryType) + pos->getKey().size(); } return mem_size; } @@ -123,7 +167,6 @@ protected: //------------------------------------------------------------------ // Typedefs //------------------------------------------------------------------ - typedef llvm::StringMap StringPool; typedef StringPool::iterator iterator; typedef StringPool::const_iterator const_iterator; @@ -320,6 +363,19 @@ ConstString::SetCString (const char *cstr) m_string = StringPool().GetConstCString (cstr); } +void +ConstString::SetCStringWithMangledCounterpart (const char *demangled, const ConstString &mangled) +{ + m_string = StringPool().GetConstCStringAndSetMangledCounterPart (demangled, mangled.m_string); +} + +bool +ConstString::GetMangledCounterpart (ConstString &counterpart) const +{ + counterpart.m_string = StringPool().GetMangledCounterpart(m_string); + return counterpart; +} + //---------------------------------------------------------------------- // Set the string value in the object by uniquing "cstr_len" bytes // starting at the "cstr" string value in our global string pool. diff --git a/lldb/source/Core/History.cpp b/lldb/source/Core/History.cpp new file mode 100644 index 000000000000..929c85447984 --- /dev/null +++ b/lldb/source/Core/History.cpp @@ -0,0 +1,25 @@ +//===-- History.cpp ---------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Core/History.h" + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Core/Stream.h" + +using namespace lldb; +using namespace lldb_private; + +void +HistorySourceUInt::DumpHistoryEvent (Stream &strm, HistoryEvent event) +{ + strm.Printf ("%s %llu", m_name.c_str(), (uint64_t)((uintptr_t)event)); +} diff --git a/lldb/source/Core/Mangled.cpp b/lldb/source/Core/Mangled.cpp index 110fa6562811..839154d59147 100644 --- a/lldb/source/Core/Mangled.cpp +++ b/lldb/source/Core/Mangled.cpp @@ -152,29 +152,9 @@ Mangled::GetDemangledName () const // lets just make sure it isn't empty... const char * mangled = m_mangled.AsCString(); // Don't bother running anything that doesn't start with _Z through the demangler - if (mangled[0] != '\0' && mangled[0] == '_' && mangled[1] == 'Z') + if (mangled[0] == '_' && mangled[1] == 'Z') { - // Since demangling can be a costly, and since all names that go - // into a ConstString (like our m_mangled and m_demangled members) - // end up being unique "const char *" values, we can use a DenseMap - // to speed up our lookup. We do this because often our symbol table - // and our debug information both have the mangled names which they - // would each need to demangle. Also, with GCC we end up with the one - // definition rule where a lot of STL code produces symbols that are - // in multiple compile units and the mangled names end up being in - // the same binary multiple times. The performance win isn't huge, - // but we showed a 20% improvement on darwin. - typedef llvm::DenseMap MangledToDemangledMap; - static MangledToDemangledMap g_mangled_to_demangled; - - // Check our mangled string pointer to demangled string pointer map first - MangledToDemangledMap::const_iterator pos = g_mangled_to_demangled.find (mangled); - if (pos != g_mangled_to_demangled.end()) - { - // We have already demangled this string, we can just use our saved result! - m_demangled.SetCString(pos->second); - } - else + if (!m_mangled.GetMangledCounterpart(m_demangled)) { // We didn't already mangle this name, demangle it and if all goes well // add it to our map. @@ -182,11 +162,7 @@ Mangled::GetDemangledName () const if (demangled_name) { - m_demangled.SetCString (demangled_name); - // Now that the name has been uniqued, add the uniqued C string - // pointer from m_mangled as the key to the uniqued C string - // pointer in m_demangled. - g_mangled_to_demangled.insert (std::make_pair (mangled, m_demangled.GetCString())); + m_demangled.SetCStringWithMangledCounterpart(demangled_name, m_mangled); free (demangled_name); } }