Summary:
When we want to compare a ConstString against a string literal (or any other non-ConstString),
we currently have to explicitly turn the other string into a ConstString. This makes sense as
comparing ConstStrings against each other is only a fast pointer comparison.
However, currently we (rather incorrectly) use in several places in LLDB temporary ConstStrings when
we just want to compare a given ConstString against a hardcoded value, for example like this:
```
if (extension != ConstString(".oat") && extension != ConstString(".odex"))
```
Obviously this kind of defeats the point of ConstStrings. In the comparison above we would
construct two temporary ConstStrings every time we hit the given code. Constructing a
ConstString is relatively expensive: we need to go to the StringPool, take a read and possibly
an exclusive write-lock and then look up our temporary string in the string map of the pool.
So we do a lot of heavy work for essentially just comparing a <6 characters in two strings.
I initially wanted to just fix these issues by turning the temporary ConstString in static variables/
members, but that made the code much less readable. Instead I propose to add a new overload
for the ConstString comparison operator that takes a StringRef. This comparison operator directly
compares the ConstString content against the given StringRef without turning the StringRef into
a ConstString.
This means that the example above can look like this now:
```
if (extension != ".oat" && extension != ".odex")
```
It also no longer has to unlock/lock two locks and call multiple functions in other TUs for constructing
the temporary ConstString instances. Instead this should end up just being a direct string comparison
of the two given strings on most compilers.
This patch also directly updates all uses of temporary and short ConstStrings in LLDB to use this new
comparison operator. It also adds a some unit tests for the new and old comparison operator.
Reviewers: #lldb, JDevlieghere, espindola, amccarth
Reviewed By: JDevlieghere, amccarth
Subscribers: amccarth, clayborg, JDevlieghere, emaste, arichardson, MaskRay, lldb-commits
Tags: #lldb
Differential Revision: https://reviews.llvm.org/D60667
llvm-svn: 359281
170 lines
4.5 KiB
C++
170 lines
4.5 KiB
C++
//===-- LibStdcppUniquePointer.cpp ------------------------------*- C++ -*-===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "LibStdcpp.h"
|
|
|
|
#include "lldb/Core/ValueObject.h"
|
|
#include "lldb/DataFormatters/FormattersHelpers.h"
|
|
#include "lldb/DataFormatters/TypeSynthetic.h"
|
|
#include "lldb/Utility/ConstString.h"
|
|
|
|
#include <memory>
|
|
#include <vector>
|
|
|
|
using namespace lldb;
|
|
using namespace lldb_private;
|
|
using namespace lldb_private::formatters;
|
|
|
|
namespace {
|
|
|
|
class LibStdcppUniquePtrSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
|
|
public:
|
|
explicit LibStdcppUniquePtrSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
|
|
|
|
size_t CalculateNumChildren() override;
|
|
|
|
lldb::ValueObjectSP GetChildAtIndex(size_t idx) override;
|
|
|
|
bool Update() override;
|
|
|
|
bool MightHaveChildren() override;
|
|
|
|
size_t GetIndexOfChildWithName(ConstString name) override;
|
|
|
|
bool GetSummary(Stream &stream, const TypeSummaryOptions &options);
|
|
|
|
private:
|
|
ValueObjectSP m_ptr_obj;
|
|
ValueObjectSP m_obj_obj;
|
|
ValueObjectSP m_del_obj;
|
|
|
|
ValueObjectSP GetTuple();
|
|
};
|
|
|
|
} // end of anonymous namespace
|
|
|
|
LibStdcppUniquePtrSyntheticFrontEnd::LibStdcppUniquePtrSyntheticFrontEnd(
|
|
lldb::ValueObjectSP valobj_sp)
|
|
: SyntheticChildrenFrontEnd(*valobj_sp) {
|
|
Update();
|
|
}
|
|
|
|
ValueObjectSP LibStdcppUniquePtrSyntheticFrontEnd::GetTuple() {
|
|
ValueObjectSP valobj_backend_sp = m_backend.GetSP();
|
|
|
|
if (!valobj_backend_sp)
|
|
return nullptr;
|
|
|
|
ValueObjectSP valobj_sp = valobj_backend_sp->GetNonSyntheticValue();
|
|
if (!valobj_sp)
|
|
return nullptr;
|
|
|
|
ValueObjectSP obj_child_sp =
|
|
valobj_sp->GetChildMemberWithName(ConstString("_M_t"), true);
|
|
if (!obj_child_sp)
|
|
return nullptr;
|
|
|
|
ValueObjectSP obj_subchild_sp =
|
|
obj_child_sp->GetChildMemberWithName(ConstString("_M_t"), true);
|
|
|
|
// if there is a _M_t subchild, the tuple is found in the obj_subchild_sp
|
|
// (for libstdc++ 6.0.23).
|
|
if (obj_subchild_sp) {
|
|
return obj_subchild_sp;
|
|
}
|
|
|
|
return obj_child_sp;
|
|
}
|
|
|
|
bool LibStdcppUniquePtrSyntheticFrontEnd::Update() {
|
|
ValueObjectSP tuple_sp = GetTuple();
|
|
|
|
if (!tuple_sp)
|
|
return false;
|
|
|
|
std::unique_ptr<SyntheticChildrenFrontEnd> tuple_frontend(
|
|
LibStdcppTupleSyntheticFrontEndCreator(nullptr, tuple_sp));
|
|
|
|
ValueObjectSP ptr_obj = tuple_frontend->GetChildAtIndex(0);
|
|
if (ptr_obj)
|
|
m_ptr_obj = ptr_obj->Clone(ConstString("pointer"));
|
|
|
|
ValueObjectSP del_obj = tuple_frontend->GetChildAtIndex(1);
|
|
if (del_obj)
|
|
m_del_obj = del_obj->Clone(ConstString("deleter"));
|
|
|
|
if (m_ptr_obj) {
|
|
Status error;
|
|
ValueObjectSP obj_obj = m_ptr_obj->Dereference(error);
|
|
if (error.Success()) {
|
|
m_obj_obj = obj_obj->Clone(ConstString("object"));
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool LibStdcppUniquePtrSyntheticFrontEnd::MightHaveChildren() { return true; }
|
|
|
|
lldb::ValueObjectSP
|
|
LibStdcppUniquePtrSyntheticFrontEnd::GetChildAtIndex(size_t idx) {
|
|
if (idx == 0)
|
|
return m_ptr_obj;
|
|
if (idx == 1)
|
|
return m_del_obj;
|
|
if (idx == 2)
|
|
return m_obj_obj;
|
|
return lldb::ValueObjectSP();
|
|
}
|
|
|
|
size_t LibStdcppUniquePtrSyntheticFrontEnd::CalculateNumChildren() {
|
|
if (m_del_obj)
|
|
return 2;
|
|
return 1;
|
|
}
|
|
|
|
size_t LibStdcppUniquePtrSyntheticFrontEnd::GetIndexOfChildWithName(
|
|
ConstString name) {
|
|
if (name == "ptr" || name == "pointer")
|
|
return 0;
|
|
if (name == "del" || name == "deleter")
|
|
return 1;
|
|
if (name == "obj" || name == "object" || name == "$$dereference$$")
|
|
return 2;
|
|
return UINT32_MAX;
|
|
}
|
|
|
|
bool LibStdcppUniquePtrSyntheticFrontEnd::GetSummary(
|
|
Stream &stream, const TypeSummaryOptions &options) {
|
|
if (!m_ptr_obj)
|
|
return false;
|
|
|
|
bool success;
|
|
uint64_t ptr_value = m_ptr_obj->GetValueAsUnsigned(0, &success);
|
|
if (!success)
|
|
return false;
|
|
if (ptr_value == 0)
|
|
stream.Printf("nullptr");
|
|
else
|
|
stream.Printf("0x%" PRIx64, ptr_value);
|
|
return true;
|
|
}
|
|
|
|
SyntheticChildrenFrontEnd *
|
|
lldb_private::formatters::LibStdcppUniquePtrSyntheticFrontEndCreator(
|
|
CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
|
|
return (valobj_sp ? new LibStdcppUniquePtrSyntheticFrontEnd(valobj_sp)
|
|
: nullptr);
|
|
}
|
|
|
|
bool lldb_private::formatters::LibStdcppUniquePointerSummaryProvider(
|
|
ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
|
|
LibStdcppUniquePtrSyntheticFrontEnd formatter(valobj.GetSP());
|
|
return formatter.GetSummary(stream, options);
|
|
}
|