ConstString.cpp revision 448bd2fe5693c3ef591743d460b8b830607cfa09
1//===-- ConstString.cpp -----------------------------------------*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9#include "lldb/Core/ConstString.h" 10#include "lldb/Core/Stream.h" 11#include "lldb/Host/Mutex.h" 12#include "llvm/ADT/StringMap.h" 13 14using namespace lldb_private; 15 16 17//---------------------------------------------------------------------- 18// The global string pool is implemented as a hash_map that maps 19// std::string objects to a uint32_t reference count. 20// 21// In debug builds the value that is stored in the ConstString objects is 22// a C string that is owned by one of the std::string objects in the 23// hash map. This was done for visibility purposes when debugging as 24// gcc was often generating insufficient debug info for the 25// iterator objects. 26// 27// In release builds, the value that is stored in the ConstString objects 28// is the iterator into the ConstString::HashMap. This is much faster when 29// it comes to modifying the reference count, and removing strings from 30// the pool. 31//---------------------------------------------------------------------- 32class Pool 33{ 34public: 35 typedef const char * StringPoolValueType; 36 typedef llvm::StringMap<StringPoolValueType, llvm::BumpPtrAllocator> StringPool; 37 typedef llvm::StringMapEntry<StringPoolValueType> StringPoolEntryType; 38 39 //------------------------------------------------------------------ 40 // Default constructor 41 // 42 // Initialize the member variables and create the empty string. 43 //------------------------------------------------------------------ 44 Pool () : 45 m_mutex (Mutex::eMutexTypeRecursive), 46 m_string_map () 47 { 48 } 49 50 //------------------------------------------------------------------ 51 // Destructor 52 //------------------------------------------------------------------ 53 ~Pool () 54 { 55 } 56 57 58 static StringPoolEntryType & 59 GetStringMapEntryFromKeyData (const char *keyData) 60 { 61 char *ptr = const_cast<char*>(keyData) - sizeof (StringPoolEntryType); 62 return *reinterpret_cast<StringPoolEntryType*>(ptr); 63 } 64 65 size_t 66 GetConstCStringLength (const char *ccstr) const 67 { 68 if (ccstr) 69 { 70 const StringPoolEntryType&entry = GetStringMapEntryFromKeyData (ccstr); 71 return entry.getKey().size(); 72 } 73 return 0; 74 } 75 76 StringPoolValueType 77 GetMangledCounterpart (const char *ccstr) const 78 { 79 if (ccstr) 80 return GetStringMapEntryFromKeyData (ccstr).getValue(); 81 return 0; 82 } 83 84 bool 85 SetMangledCounterparts (const char *key_ccstr, const char *value_ccstr) 86 { 87 if (key_ccstr && value_ccstr) 88 { 89 GetStringMapEntryFromKeyData (key_ccstr).setValue(value_ccstr); 90 GetStringMapEntryFromKeyData (value_ccstr).setValue(key_ccstr); 91 return true; 92 } 93 return false; 94 } 95 96 const char * 97 GetConstCString (const char *cstr) 98 { 99 if (cstr) 100 return GetConstCStringWithLength (cstr, strlen (cstr)); 101 return NULL; 102 } 103 104 const char * 105 GetConstCStringWithLength (const char *cstr, int cstr_len) 106 { 107 if (cstr) 108 { 109 Mutex::Locker locker (m_mutex); 110 llvm::StringRef string_ref (cstr, cstr_len); 111 StringPoolEntryType& entry = m_string_map.GetOrCreateValue (string_ref, (StringPoolValueType)NULL); 112 return entry.getKeyData(); 113 } 114 return NULL; 115 } 116 117 const char * 118 GetConstCStringAndSetMangledCounterPart (const char *demangled_cstr, const char *mangled_ccstr) 119 { 120 if (demangled_cstr) 121 { 122 Mutex::Locker locker (m_mutex); 123 // Make string pool entry with the mangled counterpart already set 124 StringPoolEntryType& entry = m_string_map.GetOrCreateValue (llvm::StringRef (demangled_cstr), mangled_ccstr); 125 126 // Extract the const version of the demangled_cstr 127 const char *demangled_ccstr = entry.getKeyData(); 128 // Now assign the demangled const string as the counterpart of the 129 // mangled const string... 130 GetStringMapEntryFromKeyData (mangled_ccstr).setValue(demangled_ccstr); 131 // Return the constant demangled C string 132 return demangled_ccstr; 133 } 134 return NULL; 135 } 136 137 const char * 138 GetConstTrimmedCStringWithLength (const char *cstr, int cstr_len) 139 { 140 if (cstr) 141 { 142 int trimmed_len = std::min<int> (strlen (cstr), cstr_len); 143 return GetConstCStringWithLength (cstr, trimmed_len); 144 } 145 return NULL; 146 } 147 148 //------------------------------------------------------------------ 149 // Return the size in bytes that this object and any items in its 150 // collection of uniqued strings + reference count values takes in 151 // memory. 152 //------------------------------------------------------------------ 153 size_t 154 MemorySize() const 155 { 156 Mutex::Locker locker (m_mutex); 157 size_t mem_size = sizeof(Pool); 158 const_iterator end = m_string_map.end(); 159 for (const_iterator pos = m_string_map.begin(); pos != end; ++pos) 160 { 161 mem_size += sizeof(StringPoolEntryType) + pos->getKey().size(); 162 } 163 return mem_size; 164 } 165 166protected: 167 //------------------------------------------------------------------ 168 // Typedefs 169 //------------------------------------------------------------------ 170 typedef StringPool::iterator iterator; 171 typedef StringPool::const_iterator const_iterator; 172 173 //------------------------------------------------------------------ 174 // Member variables 175 //------------------------------------------------------------------ 176 mutable Mutex m_mutex; 177 StringPool m_string_map; 178}; 179 180//---------------------------------------------------------------------- 181// Frameworks and dylibs aren't supposed to have global C++ 182// initializers so we hide the string pool in a static function so 183// that it will get initialized on the first call to this static 184// function. 185//---------------------------------------------------------------------- 186static Pool & 187StringPool() 188{ 189 static Pool string_pool; 190 return string_pool; 191} 192 193//---------------------------------------------------------------------- 194// Construct with C String value 195// 196// Constructs this object with a C string by looking to see if the 197// C string already exists in the global string pool. If it does 198// exist, it retains an extra reference to the string in the string 199// pool. If it doesn't exist, it is added to the string pool with 200// a reference count of 1. 201//---------------------------------------------------------------------- 202ConstString::ConstString (const char *cstr) : 203 m_string (StringPool().GetConstCString (cstr)) 204{ 205} 206 207//---------------------------------------------------------------------- 208// Construct with C String value with max length 209// 210// Constructs this object with a C string with a length. If 211// the length of the string is greather than "cstr_len", the 212// string length will be truncated. This allows substrings to be 213// created without the need to NULL terminate the string as it 214// is passed into this function. 215// 216// If the C string already exists in the global string pool, it 217// retains an extra reference to the string in the string 218// pool. If it doesn't exist, it is added to the string pool with 219// a reference count of 1. 220//---------------------------------------------------------------------- 221ConstString::ConstString (const char *cstr, size_t cstr_len) : 222 m_string (StringPool().GetConstCStringWithLength (cstr, cstr_len)) 223{ 224} 225 226bool 227ConstString::operator < (const ConstString& rhs) const 228{ 229 if (m_string == rhs.m_string) 230 return false; 231 232 llvm::StringRef lhs_string_ref (m_string, StringPool().GetConstCStringLength (m_string)); 233 llvm::StringRef rhs_string_ref (rhs.m_string, StringPool().GetConstCStringLength (rhs.m_string)); 234 235 // If both have valid C strings, then return the comparison 236 if (lhs_string_ref.data() && rhs_string_ref.data()) 237 return lhs_string_ref < rhs_string_ref; 238 239 // Else one of them was NULL, so if LHS is NULL then it is less than 240 return lhs_string_ref.data() == NULL; 241} 242 243//---------------------------------------------------------------------- 244// Stream the string value "str" to the stream "s" 245//---------------------------------------------------------------------- 246Stream& 247lldb_private::operator << (Stream& s, const ConstString& str) 248{ 249 const char *cstr = str.GetCString(); 250 if (cstr) 251 s << cstr; 252 253 return s; 254} 255 256size_t 257ConstString::GetLength () const 258{ 259 return StringPool().GetConstCStringLength (m_string); 260} 261 262//---------------------------------------------------------------------- 263// Compare two string objects. 264// 265// Returns: 266// -1 if a < b 267// 0 if a == b 268// 1 if a > b 269//---------------------------------------------------------------------- 270int 271ConstString::Compare (const ConstString& lhs, const ConstString& rhs) 272{ 273 // If the iterators are the same, this is the same string 274 register const char *lhs_cstr = lhs.m_string; 275 register const char *rhs_cstr = rhs.m_string; 276 if (lhs_cstr == rhs_cstr) 277 return 0; 278 if (lhs_cstr && rhs_cstr) 279 { 280 llvm::StringRef lhs_string_ref (lhs_cstr, StringPool().GetConstCStringLength (lhs_cstr)); 281 llvm::StringRef rhs_string_ref (rhs_cstr, StringPool().GetConstCStringLength (rhs_cstr)); 282 return lhs_string_ref.compare(rhs_string_ref); 283 } 284 285 if (lhs_cstr) 286 return +1; // LHS isn't NULL but RHS is 287 else 288 return -1; // LHS is NULL but RHS isn't 289} 290 291//---------------------------------------------------------------------- 292// Dump the string value to the stream "s". If the contained string 293// is empty, print "fail_value" to the stream instead. If 294// "fail_value" is NULL, then nothing will be dumped to the 295// stream. 296//---------------------------------------------------------------------- 297void 298ConstString::Dump(Stream *s, const char *fail_value) const 299{ 300 const char *cstr = AsCString (fail_value); 301 if (cstr) 302 s->PutCString (cstr); 303} 304 305//---------------------------------------------------------------------- 306// Dump extra debug information to the stream "s". 307//---------------------------------------------------------------------- 308void 309ConstString::DumpDebug(Stream *s) const 310{ 311 const char *cstr = GetCString (); 312 size_t cstr_len = GetLength(); 313 // Only print the parens if we have a non-NULL string 314 const char *parens = cstr ? "\"" : ""; 315 s->Printf("%*p: ConstString, string = %s%s%s, length = %zu", (int)sizeof(void*) * 2, this, parens, cstr, parens, cstr_len); 316} 317 318//---------------------------------------------------------------------- 319// Set the string value in the object by uniquing the "cstr" string 320// value in our global string pool. 321// 322// If the C string already exists in the global string pool, it 323// retains an extra reference to the string in the string 324// pool. If it doesn't exist, it is added to the string pool with 325// a reference count of 1. 326//---------------------------------------------------------------------- 327void 328ConstString::SetCString (const char *cstr) 329{ 330 m_string = StringPool().GetConstCString (cstr); 331} 332 333void 334ConstString::SetCStringWithMangledCounterpart (const char *demangled, const ConstString &mangled) 335{ 336 m_string = StringPool().GetConstCStringAndSetMangledCounterPart (demangled, mangled.m_string); 337} 338 339bool 340ConstString::GetMangledCounterpart (ConstString &counterpart) const 341{ 342 counterpart.m_string = StringPool().GetMangledCounterpart(m_string); 343 return counterpart; 344} 345 346//---------------------------------------------------------------------- 347// Set the string value in the object by uniquing "cstr_len" bytes 348// starting at the "cstr" string value in our global string pool. 349// If trim is true, then "cstr_len" indicates a maximum length of 350// the CString and if the actual length of the string is less, then 351// it will be trimmed. If trim is false, then this allows strings 352// with NULL characters ('\0') to be added to the string pool. 353// 354// If the C string already exists in the global string pool, it 355// retains an extra reference to the string in the string 356// pool. If it doesn't exist, it is added to the string pool with 357// a reference count of 1. 358//---------------------------------------------------------------------- 359void 360ConstString::SetCStringWithLength (const char *cstr, size_t cstr_len) 361{ 362 m_string = StringPool().GetConstCStringWithLength(cstr, cstr_len); 363} 364 365void 366ConstString::SetTrimmedCStringWithLength (const char *cstr, size_t cstr_len) 367{ 368 m_string = StringPool().GetConstTrimmedCStringWithLength (cstr, cstr_len); 369} 370 371//---------------------------------------------------------------------- 372// Reports the the size in bytes of all shared C string values, 373// containers and reference count values as a byte size for the 374// entire string pool. 375//---------------------------------------------------------------------- 376size_t 377ConstString::StaticMemorySize() 378{ 379 // Get the size of the static string pool 380 return StringPool().MemorySize(); 381} 382