The way it works now, it stores a `const char *` that it does not explicitly own. It's owned by the ConstString StringPool. This is purely to manage its lifetime, we don't really benefit from deduplication (nor should we try to, they are errors). We also don't really benefit from quick comparisons. This may make the size of TraceItemStorage larger, but you have to pay the cost of owning the data somewhere. The ConstString StringPool is an attractive choice but ultimately a poor one. Differential Revision: https://reviews.llvm.org/D152326
147 lines
4.3 KiB
C++
147 lines
4.3 KiB
C++
//===-- TraceCursorIntelPT.cpp --------------------------------------------===//
|
|
//
|
|
// 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 "TraceCursorIntelPT.h"
|
|
#include "DecodedThread.h"
|
|
#include "TraceIntelPT.h"
|
|
#include <cstdlib>
|
|
#include <optional>
|
|
|
|
using namespace lldb;
|
|
using namespace lldb_private;
|
|
using namespace lldb_private::trace_intel_pt;
|
|
using namespace llvm;
|
|
|
|
TraceCursorIntelPT::TraceCursorIntelPT(
|
|
ThreadSP thread_sp, DecodedThreadSP decoded_thread_sp,
|
|
const std::optional<LinuxPerfZeroTscConversion> &tsc_conversion,
|
|
std::optional<uint64_t> beginning_of_time_nanos)
|
|
: TraceCursor(thread_sp), m_decoded_thread_sp(decoded_thread_sp),
|
|
m_tsc_conversion(tsc_conversion),
|
|
m_beginning_of_time_nanos(beginning_of_time_nanos) {
|
|
Seek(0, lldb::eTraceCursorSeekTypeEnd);
|
|
}
|
|
|
|
void TraceCursorIntelPT::Next() {
|
|
m_pos += IsForwards() ? 1 : -1;
|
|
ClearTimingRangesIfInvalid();
|
|
}
|
|
|
|
void TraceCursorIntelPT::ClearTimingRangesIfInvalid() {
|
|
if (m_tsc_range_calculated) {
|
|
if (!m_tsc_range || m_pos < 0 || !m_tsc_range->InRange(m_pos)) {
|
|
m_tsc_range = None;
|
|
m_tsc_range_calculated = false;
|
|
}
|
|
}
|
|
|
|
if (m_nanoseconds_range_calculated) {
|
|
if (!m_nanoseconds_range || m_pos < 0 ||
|
|
!m_nanoseconds_range->InRange(m_pos)) {
|
|
m_nanoseconds_range = None;
|
|
m_nanoseconds_range_calculated = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
const std::optional<DecodedThread::TSCRange> &
|
|
TraceCursorIntelPT::GetTSCRange() const {
|
|
if (!m_tsc_range_calculated) {
|
|
m_tsc_range_calculated = true;
|
|
m_tsc_range = m_decoded_thread_sp->GetTSCRangeByIndex(m_pos);
|
|
}
|
|
return m_tsc_range;
|
|
}
|
|
|
|
const std::optional<DecodedThread::NanosecondsRange> &
|
|
TraceCursorIntelPT::GetNanosecondsRange() const {
|
|
if (!m_nanoseconds_range_calculated) {
|
|
m_nanoseconds_range_calculated = true;
|
|
m_nanoseconds_range =
|
|
m_decoded_thread_sp->GetNanosecondsRangeByIndex(m_pos);
|
|
}
|
|
return m_nanoseconds_range;
|
|
}
|
|
|
|
bool TraceCursorIntelPT::Seek(int64_t offset,
|
|
lldb::TraceCursorSeekType origin) {
|
|
switch (origin) {
|
|
case lldb::eTraceCursorSeekTypeBeginning:
|
|
m_pos = offset;
|
|
break;
|
|
case lldb::eTraceCursorSeekTypeEnd:
|
|
m_pos = m_decoded_thread_sp->GetItemsCount() - 1 + offset;
|
|
break;
|
|
case lldb::eTraceCursorSeekTypeCurrent:
|
|
m_pos += offset;
|
|
}
|
|
|
|
ClearTimingRangesIfInvalid();
|
|
|
|
return HasValue();
|
|
}
|
|
|
|
bool TraceCursorIntelPT::HasValue() const {
|
|
return m_pos >= 0 &&
|
|
static_cast<uint64_t>(m_pos) < m_decoded_thread_sp->GetItemsCount();
|
|
}
|
|
|
|
lldb::TraceItemKind TraceCursorIntelPT::GetItemKind() const {
|
|
return m_decoded_thread_sp->GetItemKindByIndex(m_pos);
|
|
}
|
|
|
|
llvm::StringRef TraceCursorIntelPT::GetError() const {
|
|
return m_decoded_thread_sp->GetErrorByIndex(m_pos);
|
|
}
|
|
|
|
lldb::addr_t TraceCursorIntelPT::GetLoadAddress() const {
|
|
return m_decoded_thread_sp->GetInstructionLoadAddress(m_pos);
|
|
}
|
|
|
|
std::optional<uint64_t> TraceCursorIntelPT::GetHWClock() const {
|
|
if (const std::optional<DecodedThread::TSCRange> &range = GetTSCRange())
|
|
return range->tsc;
|
|
return std::nullopt;
|
|
}
|
|
|
|
std::optional<double> TraceCursorIntelPT::GetWallClockTime() const {
|
|
if (const std::optional<DecodedThread::NanosecondsRange> &range =
|
|
GetNanosecondsRange())
|
|
return range->GetInterpolatedTime(m_pos, *m_beginning_of_time_nanos,
|
|
*m_tsc_conversion);
|
|
return std::nullopt;
|
|
}
|
|
|
|
lldb::cpu_id_t TraceCursorIntelPT::GetCPU() const {
|
|
return m_decoded_thread_sp->GetCPUByIndex(m_pos);
|
|
}
|
|
|
|
lldb::TraceEvent TraceCursorIntelPT::GetEventType() const {
|
|
return m_decoded_thread_sp->GetEventByIndex(m_pos);
|
|
}
|
|
|
|
bool TraceCursorIntelPT::GoToId(user_id_t id) {
|
|
if (!HasId(id))
|
|
return false;
|
|
m_pos = id;
|
|
ClearTimingRangesIfInvalid();
|
|
return true;
|
|
}
|
|
|
|
bool TraceCursorIntelPT::HasId(lldb::user_id_t id) const {
|
|
return id < m_decoded_thread_sp->GetItemsCount();
|
|
}
|
|
|
|
user_id_t TraceCursorIntelPT::GetId() const { return m_pos; }
|
|
|
|
std::optional<std::string> TraceCursorIntelPT::GetSyncPointMetadata() const {
|
|
return formatv("offset = 0x{0:x}",
|
|
m_decoded_thread_sp->GetSyncPointOffsetByIndex(m_pos))
|
|
.str();
|
|
}
|