[Lldb-commits] [PATCH] D159313: [lldb][NFCI] Remove use of ConstString in StructuredData

2023-09-14 Thread Alex Langford via Phabricator via lldb-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rGa5a2a5a3eca0: [lldb][NFCI] Remove use of ConstString in 
StructuredData (authored by bulbazord).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D159313/new/

https://reviews.llvm.org/D159313

Files:
  lldb/include/lldb/Utility/StructuredData.h
  lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp
  lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
  lldb/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp
  lldb/source/Target/Target.cpp
  lldb/source/Utility/StructuredData.cpp

Index: lldb/source/Utility/StructuredData.cpp
===
--- lldb/source/Utility/StructuredData.cpp
+++ lldb/source/Utility/StructuredData.cpp
@@ -162,8 +162,18 @@
 
 void StructuredData::Dictionary::Serialize(json::OStream &s) const {
   s.objectBegin();
-  for (const auto &pair : m_dict) {
-s.attributeBegin(pair.first.GetStringRef());
+
+  // To ensure the output format is always stable, we sort the dictionary by key
+  // first.
+  using Entry = std::pair;
+  std::vector sorted_entries;
+  for (const auto &pair : m_dict)
+sorted_entries.push_back({pair.first(), pair.second});
+
+  llvm::sort(sorted_entries);
+
+  for (const auto &pair : sorted_entries) {
+s.attributeBegin(pair.first);
 pair.second->Serialize(s);
 s.attributeEnd();
   }
@@ -228,9 +238,20 @@
 
 void StructuredData::Dictionary::GetDescription(lldb_private::Stream &s) const {
   size_t indentation_level = s.GetIndentLevel();
-  for (auto iter = m_dict.begin(); iter != m_dict.end(); iter++) {
+
+  // To ensure the output format is always stable, we sort the dictionary by key
+  // first.
+  using Entry = std::pair;
+  std::vector sorted_entries;
+  for (const auto &pair : m_dict)
+sorted_entries.push_back({pair.first(), pair.second});
+
+  llvm::sort(sorted_entries);
+
+  for (auto iter = sorted_entries.begin(); iter != sorted_entries.end();
+   iter++) {
 // Sanitize.
-if (iter->first.IsNull() || iter->first.IsEmpty() || !iter->second)
+if (iter->first.empty() || !iter->second)
   continue;
 
 // Reset original indentation level.
@@ -238,7 +259,7 @@
 s.Indent();
 
 // Print key.
-s.Printf("%s:", iter->first.AsCString());
+s.Format("{0}:", iter->first);
 
 // Return to new line and increase indentation if value is record type.
 // Otherwise add spacing.
@@ -252,7 +273,7 @@
 
 // Print value and new line if now last pair.
 iter->second->GetDescription(s);
-if (std::next(iter) != m_dict.end())
+if (std::next(iter) != sorted_entries.end())
   s.EOL();
 
 // Reset indentation level if it was incremented previously.
Index: lldb/source/Target/Target.cpp
===
--- lldb/source/Target/Target.cpp
+++ lldb/source/Target/Target.cpp
@@ -3859,11 +3859,10 @@
   s.Indent("Args:\n");
   s.SetIndentLevel(s.GetIndentLevel() + 4);
 
-  auto print_one_element = [&s](ConstString key,
+  auto print_one_element = [&s](llvm::StringRef key,
 StructuredData::Object *object) {
 s.Indent();
-s.Printf("%s : %s\n", key.GetCString(),
-  object->GetStringValue().str().c_str());
+s.Format("{0} : {1}\n", key, object->GetStringValue());
 return true;
   };
 
Index: lldb/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp
===
--- lldb/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp
+++ lldb/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp
@@ -224,7 +224,7 @@
   [&module_sp, new_style_source_remapping_dictionary,
original_DBGSourcePath_value,
do_truncate_remapping_names](
-  ConstString key,
+  llvm::StringRef key,
   StructuredData::Object *object) -> bool {
 if (object && object->GetAsString()) {
 
@@ -237,7 +237,7 @@
 DBGSourcePath = original_DBGSourcePath_value;
   }
   module_sp->GetSourceMappingList().Append(
-  key.GetStringRef(), DBGSourcePath, true);
+  key, DBGSourcePath, true);
   // With version 2 of DBGSourcePathRemapping, we
   // can chop off the last two filename parts
   // from the source remapping and get a more
@@ -245,7 +245,7 @@
   // Add this as another option in addition to
   // the full source path remap.
   if (do_truncate_remapping_names) {
-  

[Lldb-commits] [PATCH] D159313: [lldb][NFCI] Remove use of ConstString in StructuredData

2023-09-14 Thread Felipe de Azevedo Piovezan via Phabricator via lldb-commits
fdeazeve accepted this revision.
fdeazeve added a comment.
This revision is now accepted and ready to land.

LGTM!


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D159313/new/

https://reviews.llvm.org/D159313

___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [PATCH] D159313: [lldb][NFCI] Remove use of ConstString in StructuredData

2023-09-14 Thread Alex Langford via Phabricator via lldb-commits
bulbazord updated this revision to Diff 556798.
bulbazord added a comment.

Remove unneeded lambda


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D159313/new/

https://reviews.llvm.org/D159313

Files:
  lldb/include/lldb/Utility/StructuredData.h
  lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp
  lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
  lldb/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp
  lldb/source/Target/Target.cpp
  lldb/source/Utility/StructuredData.cpp

Index: lldb/source/Utility/StructuredData.cpp
===
--- lldb/source/Utility/StructuredData.cpp
+++ lldb/source/Utility/StructuredData.cpp
@@ -162,8 +162,18 @@
 
 void StructuredData::Dictionary::Serialize(json::OStream &s) const {
   s.objectBegin();
-  for (const auto &pair : m_dict) {
-s.attributeBegin(pair.first.GetStringRef());
+
+  // To ensure the output format is always stable, we sort the dictionary by key
+  // first.
+  using Entry = std::pair;
+  std::vector sorted_entries;
+  for (const auto &pair : m_dict)
+sorted_entries.push_back({pair.first(), pair.second});
+
+  llvm::sort(sorted_entries);
+
+  for (const auto &pair : sorted_entries) {
+s.attributeBegin(pair.first);
 pair.second->Serialize(s);
 s.attributeEnd();
   }
@@ -228,9 +238,20 @@
 
 void StructuredData::Dictionary::GetDescription(lldb_private::Stream &s) const {
   size_t indentation_level = s.GetIndentLevel();
-  for (auto iter = m_dict.begin(); iter != m_dict.end(); iter++) {
+
+  // To ensure the output format is always stable, we sort the dictionary by key
+  // first.
+  using Entry = std::pair;
+  std::vector sorted_entries;
+  for (const auto &pair : m_dict)
+sorted_entries.push_back({pair.first(), pair.second});
+
+  llvm::sort(sorted_entries);
+
+  for (auto iter = sorted_entries.begin(); iter != sorted_entries.end();
+   iter++) {
 // Sanitize.
-if (iter->first.IsNull() || iter->first.IsEmpty() || !iter->second)
+if (iter->first.empty() || !iter->second)
   continue;
 
 // Reset original indentation level.
@@ -238,7 +259,7 @@
 s.Indent();
 
 // Print key.
-s.Printf("%s:", iter->first.AsCString());
+s.Format("{0}:", iter->first);
 
 // Return to new line and increase indentation if value is record type.
 // Otherwise add spacing.
@@ -252,7 +273,7 @@
 
 // Print value and new line if now last pair.
 iter->second->GetDescription(s);
-if (std::next(iter) != m_dict.end())
+if (std::next(iter) != sorted_entries.end())
   s.EOL();
 
 // Reset indentation level if it was incremented previously.
Index: lldb/source/Target/Target.cpp
===
--- lldb/source/Target/Target.cpp
+++ lldb/source/Target/Target.cpp
@@ -3859,11 +3859,10 @@
   s.Indent("Args:\n");
   s.SetIndentLevel(s.GetIndentLevel() + 4);
 
-  auto print_one_element = [&s](ConstString key,
+  auto print_one_element = [&s](llvm::StringRef key,
 StructuredData::Object *object) {
 s.Indent();
-s.Printf("%s : %s\n", key.GetCString(),
-  object->GetStringValue().str().c_str());
+s.Format("{0} : {1}\n", key, object->GetStringValue());
 return true;
   };
 
Index: lldb/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp
===
--- lldb/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp
+++ lldb/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp
@@ -224,7 +224,7 @@
   [&module_sp, new_style_source_remapping_dictionary,
original_DBGSourcePath_value,
do_truncate_remapping_names](
-  ConstString key,
+  llvm::StringRef key,
   StructuredData::Object *object) -> bool {
 if (object && object->GetAsString()) {
 
@@ -237,7 +237,7 @@
 DBGSourcePath = original_DBGSourcePath_value;
   }
   module_sp->GetSourceMappingList().Append(
-  key.GetStringRef(), DBGSourcePath, true);
+  key, DBGSourcePath, true);
   // With version 2 of DBGSourcePathRemapping, we
   // can chop off the last two filename parts
   // from the source remapping and get a more
@@ -245,7 +245,7 @@
   // Add this as another option in addition to
   // the full source path remap.
   if (do_truncate_remapping_names) {
-FileSpec build_path(key.AsCString());
+FileSpec 

[Lldb-commits] [PATCH] D159313: [lldb][NFCI] Remove use of ConstString in StructuredData

2023-09-14 Thread Alex Langford via Phabricator via lldb-commits
bulbazord added inline comments.



Comment at: lldb/source/Utility/StructuredData.cpp:249-251
+  llvm::sort(sorted_entries, [&](const Entry &lhs, const Entry &rhs) -> bool {
+return lhs.first < rhs.first;
+  });

Oh I can remove this lambda too -- Let me update.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D159313/new/

https://reviews.llvm.org/D159313

___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [PATCH] D159313: [lldb][NFCI] Remove use of ConstString in StructuredData

2023-09-11 Thread Alex Langford via Phabricator via lldb-commits
bulbazord added inline comments.



Comment at: lldb/include/lldb/Utility/StructuredData.h:436
   auto array_sp = std::make_shared();
-  collection::const_iterator iter;
-  for (iter = m_dict.begin(); iter != m_dict.end(); ++iter) {
+  for (auto iter = m_dict.begin(); iter != m_dict.end(); ++iter) {
 auto key_object_sp = std::make_shared();

fdeazeve wrote:
> Since we are touching this line anyway, could you replace this with
> 
> ```
> for (StringRef key : llvm::make_first_range(m_dict))
> ```
> 
> This has a bit less cognitive burden IMO
Unfortunately no, `llvm::make_first_range` assumes that you can refer to 
`first` on an iterator, but `first` is actually a method to be called. The 
iterator code will have to stay for now.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D159313/new/

https://reviews.llvm.org/D159313

___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [PATCH] D159313: [lldb][NFCI] Remove use of ConstString in StructuredData

2023-09-11 Thread Alex Langford via Phabricator via lldb-commits
bulbazord updated this revision to Diff 556469.
bulbazord marked 7 inline comments as done.
bulbazord added a comment.

Address feedback from @fdeazeve


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D159313/new/

https://reviews.llvm.org/D159313

Files:
  lldb/include/lldb/Utility/StructuredData.h
  lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp
  lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
  lldb/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp
  lldb/source/Target/Target.cpp
  lldb/source/Utility/StructuredData.cpp

Index: lldb/source/Utility/StructuredData.cpp
===
--- lldb/source/Utility/StructuredData.cpp
+++ lldb/source/Utility/StructuredData.cpp
@@ -162,8 +162,18 @@
 
 void StructuredData::Dictionary::Serialize(json::OStream &s) const {
   s.objectBegin();
-  for (const auto &pair : m_dict) {
-s.attributeBegin(pair.first.GetStringRef());
+
+  // To ensure the output format is always stable, we sort the dictionary by key
+  // first.
+  using Entry = std::pair;
+  std::vector sorted_entries;
+  for (const auto &pair : m_dict)
+sorted_entries.push_back({pair.first(), pair.second});
+
+  llvm::sort(sorted_entries);
+
+  for (const auto &pair : sorted_entries) {
+s.attributeBegin(pair.first);
 pair.second->Serialize(s);
 s.attributeEnd();
   }
@@ -228,9 +238,22 @@
 
 void StructuredData::Dictionary::GetDescription(lldb_private::Stream &s) const {
   size_t indentation_level = s.GetIndentLevel();
-  for (auto iter = m_dict.begin(); iter != m_dict.end(); iter++) {
+
+  // To ensure the output format is always stable, we sort the dictionary by key
+  // first.
+  using Entry = std::pair;
+  std::vector sorted_entries;
+  for (const auto &pair : m_dict)
+sorted_entries.push_back({pair.first(), pair.second});
+
+  llvm::sort(sorted_entries, [&](const Entry &lhs, const Entry &rhs) -> bool {
+return lhs.first < rhs.first;
+  });
+
+  for (auto iter = sorted_entries.begin(); iter != sorted_entries.end();
+   iter++) {
 // Sanitize.
-if (iter->first.IsNull() || iter->first.IsEmpty() || !iter->second)
+if (iter->first.empty() || !iter->second)
   continue;
 
 // Reset original indentation level.
@@ -238,7 +261,7 @@
 s.Indent();
 
 // Print key.
-s.Printf("%s:", iter->first.AsCString());
+s.Format("{0}:", iter->first);
 
 // Return to new line and increase indentation if value is record type.
 // Otherwise add spacing.
@@ -252,7 +275,7 @@
 
 // Print value and new line if now last pair.
 iter->second->GetDescription(s);
-if (std::next(iter) != m_dict.end())
+if (std::next(iter) != sorted_entries.end())
   s.EOL();
 
 // Reset indentation level if it was incremented previously.
Index: lldb/source/Target/Target.cpp
===
--- lldb/source/Target/Target.cpp
+++ lldb/source/Target/Target.cpp
@@ -3859,11 +3859,10 @@
   s.Indent("Args:\n");
   s.SetIndentLevel(s.GetIndentLevel() + 4);
 
-  auto print_one_element = [&s](ConstString key,
+  auto print_one_element = [&s](llvm::StringRef key,
 StructuredData::Object *object) {
 s.Indent();
-s.Printf("%s : %s\n", key.GetCString(),
-  object->GetStringValue().str().c_str());
+s.Format("{0} : {1}\n", key, object->GetStringValue());
 return true;
   };
 
Index: lldb/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp
===
--- lldb/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp
+++ lldb/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp
@@ -224,7 +224,7 @@
   [&module_sp, new_style_source_remapping_dictionary,
original_DBGSourcePath_value,
do_truncate_remapping_names](
-  ConstString key,
+  llvm::StringRef key,
   StructuredData::Object *object) -> bool {
 if (object && object->GetAsString()) {
 
@@ -237,7 +237,7 @@
 DBGSourcePath = original_DBGSourcePath_value;
   }
   module_sp->GetSourceMappingList().Append(
-  key.GetStringRef(), DBGSourcePath, true);
+  key, DBGSourcePath, true);
   // With version 2 of DBGSourcePathRemapping, we
   // can chop off the last two filename parts
   // from the source remapping and get a more
@@ -245,7 +245,7 @@
   // Add this as another option in addition to
   // the full source path remap.
   if (

[Lldb-commits] [PATCH] D159313: [lldb][NFCI] Remove use of ConstString in StructuredData

2023-08-31 Thread Alex Langford via Phabricator via lldb-commits
bulbazord marked an inline comment as done.
bulbazord added inline comments.



Comment at: lldb/include/lldb/Utility/StructuredData.h:448
-  if (!key.empty()) {
-ConstString key_cs(key);
-collection::const_iterator iter = m_dict.find(key_cs);

fdeazeve wrote:
> This line in particular also shows why I think this patch is appropriate: 
> even queries were introducing strings into the pool
Yes, this also was happening in `HasKey` as well. 



Comment at: lldb/include/lldb/Utility/StructuredData.h:537
 void AddItem(llvm::StringRef key, ObjectSP value_sp) {
-  ConstString key_cs(key);
-  m_dict[key_cs] = std::move(value_sp);
+  m_dict.insert({key, std::move(value_sp)});
 }

fdeazeve wrote:
> This is not equivalent to the old code, right? The previous code would 
> overwrite the contents if the key already existed.
Oh, good catch. I think what I want is `insert_or_assign`. Will update.



Comment at: lldb/source/Utility/StructuredData.cpp:173
+
+  llvm::sort(sorted_entries, [&](const Entry &lhs, const Entry &rhs) -> bool {
+return lhs.first < rhs.first;

fdeazeve wrote:
> I thought pairs had `operator <` defined already?
Oh, I didn't even think to check. I'll try it and update if I don't need to 
define this lambda.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D159313/new/

https://reviews.llvm.org/D159313

___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [PATCH] D159313: [lldb][NFCI] Remove use of ConstString in StructuredData

2023-08-31 Thread Felipe de Azevedo Piovezan via Phabricator via lldb-commits
fdeazeve added inline comments.



Comment at: lldb/include/lldb/Utility/StructuredData.h:436
   auto array_sp = std::make_shared();
-  collection::const_iterator iter;
-  for (iter = m_dict.begin(); iter != m_dict.end(); ++iter) {
+  for (auto iter = m_dict.begin(); iter != m_dict.end(); ++iter) {
 auto key_object_sp = std::make_shared();

Since we are touching this line anyway, could you replace this with

```
for (StringRef key : llvm::make_first_range(m_dict))
```

This has a bit less cognitive burden IMO



Comment at: lldb/include/lldb/Utility/StructuredData.h:438
 auto key_object_sp = std::make_shared();
-key_object_sp->SetValue(iter->first.AsCString());
+key_object_sp->SetValue(iter->first());
 array_sp->Push(key_object_sp);

Also since you are touching this line, one could argue for it to be deleted and 
folded into `std::make_shared(Key);`

I don't feel strongly about it though, it could also be more appropriate for a 
separate commit



Comment at: lldb/include/lldb/Utility/StructuredData.h:448
-  if (!key.empty()) {
-ConstString key_cs(key);
-collection::const_iterator iter = m_dict.find(key_cs);

This line in particular also shows why I think this patch is appropriate: even 
queries were introducing strings into the pool



Comment at: lldb/include/lldb/Utility/StructuredData.h:537
 void AddItem(llvm::StringRef key, ObjectSP value_sp) {
-  ConstString key_cs(key);
-  m_dict[key_cs] = std::move(value_sp);
+  m_dict.insert({key, std::move(value_sp)});
 }

This is not equivalent to the old code, right? The previous code would 
overwrite the contents if the key already existed.



Comment at: lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp:2035
   uint32_t reg;
-  if (llvm::to_integer(key.AsCString(), reg))
 expedited_register_map[reg] =

This is another win: the old code was calling `StringRef(const char*)`, which 
has to iterate over the entire string to find the null terminating character.



Comment at: lldb/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp:248
   if (do_truncate_remapping_names) {
-FileSpec build_path(key.AsCString());
 FileSpec source_path(DBGSourcePath.c_str());

same win here



Comment at: lldb/source/Target/Target.cpp:3866
-s.Printf("%s : %s\n", key.GetCString(),
-  object->GetStringValue().str().c_str());
 return true;

we talked about it in private, but I feel like stating this publicly: does 
anyone know if this was legal? `object->GetStringValue().str()` creates a 
temporary std::string. And then we call `c_str()` and pass that to the Printf 
function. Does the temporary std::string have its lifetime extended?



Comment at: lldb/source/Utility/StructuredData.cpp:173
+
+  llvm::sort(sorted_entries, [&](const Entry &lhs, const Entry &rhs) -> bool {
+return lhs.first < rhs.first;

I thought pairs had `operator <` defined already?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D159313/new/

https://reviews.llvm.org/D159313

___
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [PATCH] D159313: [lldb][NFCI] Remove use of ConstString in StructuredData

2023-08-31 Thread Alex Langford via Phabricator via lldb-commits
bulbazord created this revision.
bulbazord added reviewers: JDevlieghere, mib, jingham, fdeazeve.
Herald added a subscriber: mgrang.
Herald added a project: All.
bulbazord requested review of this revision.
Herald added a project: LLDB.
Herald added a subscriber: lldb-commits.

The remaining use of ConstString in StructuredData is the Dictionary
class. Internally it's backed by a `std::map`.
I propose that we replace it with a `llvm::StringMap`.

Many StructuredData::Dictionary objects are ephemeral and only exist for
a short amount of time. Many of these Dictionaries are only produced
once and are never used again. That leaves us with a lot of string data
in the ConstString StringPool that is sitting there never to be used
again. Even if the same string is used many times for keys of different
Dictionary objects, that is something we can measure and adjust for
instead of assuming that every key may be reused at some point in the
future.

Quick comparisons of key data is likely not a concern with Dictionary,
but the use of `llvm::StringMap` means that lookups should be fast with
its hashing strategy.

Switching to a llvm::StringMap meant that the iteration order may be
different. To account for this when serializing/dumping the dictionary,
I added some code to sort the output by key before emitting anything.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D159313

Files:
  lldb/include/lldb/Utility/StructuredData.h
  lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp
  lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
  lldb/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp
  lldb/source/Target/Target.cpp
  lldb/source/Utility/StructuredData.cpp

Index: lldb/source/Utility/StructuredData.cpp
===
--- lldb/source/Utility/StructuredData.cpp
+++ lldb/source/Utility/StructuredData.cpp
@@ -162,8 +162,20 @@
 
 void StructuredData::Dictionary::Serialize(json::OStream &s) const {
   s.objectBegin();
-  for (const auto &pair : m_dict) {
-s.attributeBegin(pair.first.GetStringRef());
+
+  // To ensure the output format is always stable, we sort the dictionary by key
+  // first.
+  using Entry = std::pair;
+  std::vector sorted_entries;
+  for (const auto &pair : m_dict)
+sorted_entries.push_back({pair.first(), pair.second});
+
+  llvm::sort(sorted_entries, [&](const Entry &lhs, const Entry &rhs) -> bool {
+return lhs.first < rhs.first;
+  });
+
+  for (const auto &pair : sorted_entries) {
+s.attributeBegin(pair.first);
 pair.second->Serialize(s);
 s.attributeEnd();
   }
@@ -228,9 +240,22 @@
 
 void StructuredData::Dictionary::GetDescription(lldb_private::Stream &s) const {
   size_t indentation_level = s.GetIndentLevel();
-  for (auto iter = m_dict.begin(); iter != m_dict.end(); iter++) {
+
+  // To ensure the output format is always stable, we sort the dictionary by key
+  // first.
+  using Entry = std::pair;
+  std::vector sorted_entries;
+  for (const auto &pair : m_dict)
+sorted_entries.push_back({pair.first(), pair.second});
+
+  llvm::sort(sorted_entries, [&](const Entry &lhs, const Entry &rhs) -> bool {
+return lhs.first < rhs.first;
+  });
+
+  for (auto iter = sorted_entries.begin(); iter != sorted_entries.end();
+   iter++) {
 // Sanitize.
-if (iter->first.IsNull() || iter->first.IsEmpty() || !iter->second)
+if (iter->first.empty() || !iter->second)
   continue;
 
 // Reset original indentation level.
@@ -238,7 +263,7 @@
 s.Indent();
 
 // Print key.
-s.Printf("%s:", iter->first.AsCString());
+s.Format("{0}:", iter->first);
 
 // Return to new line and increase indentation if value is record type.
 // Otherwise add spacing.
@@ -252,7 +277,7 @@
 
 // Print value and new line if now last pair.
 iter->second->GetDescription(s);
-if (std::next(iter) != m_dict.end())
+if (std::next(iter) != sorted_entries.end())
   s.EOL();
 
 // Reset indentation level if it was incremented previously.
Index: lldb/source/Target/Target.cpp
===
--- lldb/source/Target/Target.cpp
+++ lldb/source/Target/Target.cpp
@@ -3859,11 +3859,10 @@
   s.Indent("Args:\n");
   s.SetIndentLevel(s.GetIndentLevel() + 4);
 
-  auto print_one_element = [&s](ConstString key,
+  auto print_one_element = [&s](llvm::StringRef key,
 StructuredData::Object *object) {
 s.Indent();
-s.Printf("%s : %s\n", key.GetCString(),
-  object->GetStringValue().str().c_str());
+s.Format("{0} : {1}\n", key, object->GetStringValue());
 return true;
   };
 
Index: lldb/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp
===
--- lldb/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp
+++ lldb/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp
@@ -224,7 +224,7 @@