zrthxn updated this revision to Diff 418937.
zrthxn marked 12 inline comments as done.
zrthxn added a comment.

Introduced TscRange for quicker operation


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D122603

Files:
  lldb/source/Plugins/Trace/intel-pt/DecodedThread.cpp
  lldb/source/Plugins/Trace/intel-pt/DecodedThread.h
  lldb/source/Plugins/Trace/intel-pt/TraceCursorIntelPT.cpp
  lldb/source/Plugins/Trace/intel-pt/TraceCursorIntelPT.h

Index: lldb/source/Plugins/Trace/intel-pt/TraceCursorIntelPT.h
===================================================================
--- lldb/source/Plugins/Trace/intel-pt/TraceCursorIntelPT.h
+++ lldb/source/Plugins/Trace/intel-pt/TraceCursorIntelPT.h
@@ -42,6 +42,8 @@
   DecodedThreadSP m_decoded_thread_sp;
   /// Internal instruction index currently pointing at.
   size_t m_pos;
+  /// Current instruction timestamp.
+  llvm::Optional<DecodedThread::TscRange> m_current_tsc;
 };
 
 } // namespace trace_intel_pt
Index: lldb/source/Plugins/Trace/intel-pt/TraceCursorIntelPT.cpp
===================================================================
--- lldb/source/Plugins/Trace/intel-pt/TraceCursorIntelPT.cpp
+++ lldb/source/Plugins/Trace/intel-pt/TraceCursorIntelPT.cpp
@@ -23,6 +23,7 @@
   assert(!m_decoded_thread_sp->GetInstructions().empty() &&
          "a trace should have at least one instruction or error");
   m_pos = m_decoded_thread_sp->GetInstructions().size() - 1;
+  m_current_tsc = m_decoded_thread_sp->GetTSCRange(m_pos);
 }
 
 size_t TraceCursorIntelPT::GetInternalInstructionSize() {
@@ -40,6 +41,12 @@
 
   while (canMoveOne()) {
     m_pos += IsForwards() ? 1 : -1;
+
+    if (m_pos > m_current_tsc->end_index)
+      m_current_tsc = m_decoded_thread_sp->GetNextTSCRange(*m_current_tsc);
+    if (m_pos < m_current_tsc->start_index)
+      m_current_tsc = m_decoded_thread_sp->GetPrevTSCRange(*m_current_tsc);
+    
     if (!m_ignore_errors && IsError())
       return true;
     if (GetInstructionControlFlowType() & m_granularity)
@@ -61,20 +68,24 @@
   switch (origin) {
   case TraceCursor::SeekType::Set:
     m_pos = fitPosToBounds(offset);
+    m_current_tsc = m_decoded_thread_sp->GetTSCRange(m_pos);
     return m_pos;
   case TraceCursor::SeekType::End:
     m_pos = fitPosToBounds(offset + last_index);
+    // not sure if this should be last_index - m_pos or just m_pos
+    m_current_tsc = m_decoded_thread_sp->GetTSCRange(last_index - m_pos);
     return last_index - m_pos;
   case TraceCursor::SeekType::Current:
     int64_t new_pos = fitPosToBounds(offset + m_pos);
     int64_t dist = m_pos - new_pos;
     m_pos = new_pos;
+    m_current_tsc = m_decoded_thread_sp->GetTSCRange(m_pos);
     return std::abs(dist);
   }
 }
 
 bool TraceCursorIntelPT::IsError() {
-  return m_decoded_thread_sp->GetInstructions()[m_pos].IsError();
+  return m_decoded_thread_sp->IsInstructionAnError(m_pos);
 }
 
 const char *TraceCursorIntelPT::GetError() {
@@ -88,7 +99,7 @@
 Optional<uint64_t> TraceCursorIntelPT::GetCounter(lldb::TraceCounter counter_type) {
   switch (counter_type) {
     case lldb::eTraceCounterTSC:
-      return m_decoded_thread_sp->GetInstructions()[m_pos].GetTimestampCounter();
+      return m_current_tsc->tsc;
   }
 }
 
Index: lldb/source/Plugins/Trace/intel-pt/DecodedThread.h
===================================================================
--- lldb/source/Plugins/Trace/intel-pt/DecodedThread.h
+++ lldb/source/Plugins/Trace/intel-pt/DecodedThread.h
@@ -62,9 +62,6 @@
 /// As mentioned, any gap is represented as an error in this class.
 class IntelPTInstruction {
 public:
-  IntelPTInstruction(const pt_insn &pt_insn, uint64_t timestamp)
-      : m_pt_insn(pt_insn), m_timestamp(timestamp), m_is_error(false) {}
-
   IntelPTInstruction(const pt_insn &pt_insn)
       : m_pt_insn(pt_insn), m_is_error(false) {}
 
@@ -85,13 +82,6 @@
   /// Get the size in bytes of an instance of this class
   static size_t GetMemoryUsage();
 
-  /// Get the timestamp associated with the current instruction. The timestamp
-  /// is similar to what a rdtsc instruction would return.
-  ///
-  /// \return
-  ///     The timestamp or \b llvm::None if not available.
-  llvm::Optional<uint64_t> GetTimestampCounter() const;
-
   /// Get the \a lldb::TraceInstructionControlFlowType categories of the
   /// instruction.
   ///
@@ -113,7 +103,6 @@
   // When adding new members to this class, make sure to update
   // IntelPTInstruction::GetNonErrorMemoryUsage() if needed.
   pt_insn m_pt_insn;
-  llvm::Optional<uint64_t> m_timestamp;
   bool m_is_error;
 };
 
@@ -131,6 +120,15 @@
   /// Utility constructor that initializes the trace with a provided error.
   DecodedThread(lldb::ThreadSP thread_sp, llvm::Error &&err);
 
+  /// Append a successfully decoded instruction.
+  void AppendInstruction(const pt_insn& instruction);
+
+  /// Append a timestamp at the index of the last instruction.
+  void AppendInstruction(const pt_insn& instruction, uint64_t timestamp);
+
+  /// Append a decoding error (i.e. an instruction that failed to be decoded).
+  void AppendError(llvm::Error &&error);
+
   /// Get the instructions from the decoded trace. Some of them might indicate
   /// errors (i.e. gaps) in the trace. For an instruction error, you can access
   /// its underlying error message with the \a GetErrorByInstructionIndex()
@@ -140,20 +138,39 @@
   ///   The instructions of the trace.
   llvm::ArrayRef<IntelPTInstruction> GetInstructions() const;
 
+  /// Get iterator of timestamp of an instruction by its index.
+  llvm::Optional<std::map<size_t, uint64_t>::const_iterator> GetTSCIterator(size_t index) const;
+
+  // Range of timestamp iterators for a given index
+  struct TscRange {
+    uint64_t tsc;
+    size_t start_index;
+    size_t end_index;
+    std::map<size_t, uint64_t>::const_iterator next;
+    std::map<size_t, uint64_t>::const_iterator prev;
+
+    // Construct TscRange respecting bounds of timestamp map in thread
+    TscRange(std::map<size_t, uint64_t>::const_iterator it, const DecodedThread& ref);
+  };
+
+  /// Get timestamp of an instruction by its index.
+  llvm::Optional<struct TscRange> GetTSCRange(size_t insn_index) const;
+
+  /// Get timestamp of an instruction by its index.
+  llvm::Optional<struct TscRange> GetNextTSCRange(const TscRange& range) const;
+  
+  /// Get timestamp of an instruction by its index.
+  llvm::Optional<struct TscRange> GetPrevTSCRange(const TscRange& range) const;
+
+  /// Check if an instruction given by its index is an error.
+  bool IsInstructionAnError(size_t insn_idx) const;
+
   /// Get the error associated with a given instruction index.
   ///
   /// \return
   ///   The error message of \b nullptr if the given index
   ///   points to a valid instruction.
-  const char *GetErrorByInstructionIndex(uint64_t ins_idx);
-
-  /// Append a successfully decoded instruction.
-  template <typename... Ts> void AppendInstruction(Ts... instruction_args) {
-    m_instructions.emplace_back(instruction_args...);
-  }
-
-  /// Append a decoding error (i.e. an instruction that failed to be decoded).
-  void AppendError(llvm::Error &&error);
+  const char *GetErrorByInstructionIndex(size_t ins_idx);
 
   /// Get a new cursor for the decoded thread.
   lldb::TraceCursorUP GetCursor();
@@ -178,8 +195,11 @@
   /// to update \a CalculateApproximateMemoryUsage() accordingly.
   lldb::ThreadSP m_thread_sp;
   std::vector<IntelPTInstruction> m_instructions;
+  std::map<size_t, uint64_t> m_instruction_timestamps;
   llvm::DenseMap<uint64_t, std::string> m_errors;
   llvm::Optional<size_t> m_raw_trace_size;
+
+  uint64_t __last_tsc;
 };
 
 using DecodedThreadSP = std::shared_ptr<DecodedThread>;
Index: lldb/source/Plugins/Trace/intel-pt/DecodedThread.cpp
===================================================================
--- lldb/source/Plugins/Trace/intel-pt/DecodedThread.cpp
+++ lldb/source/Plugins/Trace/intel-pt/DecodedThread.cpp
@@ -49,10 +49,6 @@
   return sizeof(IntelPTInstruction);
 }
 
-Optional<uint64_t> IntelPTInstruction::GetTimestampCounter() const {
-  return m_timestamp;
-}
-
 Optional<size_t> DecodedThread::GetRawTraceSize() const {
   return m_raw_trace_size;
 }
@@ -90,6 +86,18 @@
 
 ThreadSP DecodedThread::GetThread() { return m_thread_sp; }
 
+void DecodedThread::AppendInstruction(const pt_insn &insn) {
+  m_instructions.emplace_back(insn);
+}
+
+void DecodedThread::AppendInstruction(const pt_insn &insn, uint64_t tsc) {
+  m_instructions.emplace_back(insn);
+  if (__last_tsc != tsc) {
+    m_instruction_timestamps.emplace(m_instructions.size() - 1, tsc);
+    __last_tsc = tsc;
+  }
+}
+
 void DecodedThread::AppendError(llvm::Error &&error) {
   m_errors.try_emplace(m_instructions.size(), toString(std::move(error)));
   m_instructions.emplace_back();
@@ -99,18 +107,84 @@
   return makeArrayRef(m_instructions);
 }
 
-const char *DecodedThread::GetErrorByInstructionIndex(uint64_t idx) {
-  auto it = m_errors.find(idx);
+DecodedThread::TscRange::TscRange(std::map<size_t, uint64_t>::const_iterator it,
+                                  const DecodedThread &ref) {
+  auto begin = ref.m_instruction_timestamps.begin();
+  auto end = ref.m_instruction_timestamps.begin();
+
+  start_index = it->first;
+  tsc = it->second;
+
+  if (it != end)
+    end_index = (++it)->first - 1;
+  else
+    end_index = end->first;
+
+  next = it;
+
+  if (--it != begin)
+    prev = --it;
+  else
+    start_index = begin->first;
+}
+
+Optional<std::map<size_t, uint64_t>::const_iterator>
+DecodedThread::GetTSCIterator(size_t insn_idx) const {
+  if (m_instruction_timestamps.empty())
+    return None;
+
+  auto it = m_instruction_timestamps.upper_bound(insn_idx);
+  if (it == m_instruction_timestamps.begin())
+    return None;
+
+  return --it;
+}
+
+Optional<struct DecodedThread::TscRange>
+DecodedThread::GetTSCRange(size_t insn_index) const {
+  auto it = GetTSCIterator(insn_index);
+  if (!it.hasValue())
+    return None;
+
+  auto start = *it;
+  return TscRange(start, *this);
+}
+
+Optional<struct DecodedThread::TscRange>
+DecodedThread::GetNextTSCRange(const TscRange &range) const {
+  auto next = range.next;
+  if (next == m_instruction_timestamps.end())
+    return None;
+
+  return TscRange(next, *this);
+}
+
+Optional<struct DecodedThread::TscRange>
+DecodedThread::GetPrevTSCRange(const TscRange &range) const {
+  auto prev = range.prev;
+  if (prev == m_instruction_timestamps.begin())
+    return None;
+
+  return TscRange(prev, *this);
+}
+
+bool DecodedThread::IsInstructionAnError(size_t insn_idx) const {
+  return m_instructions[insn_idx].IsError();
+}
+
+const char *DecodedThread::GetErrorByInstructionIndex(size_t insn_idx) {
+  auto it = m_errors.find(insn_idx);
   if (it == m_errors.end())
     return nullptr;
 
   return it->second.c_str();
 }
 
-DecodedThread::DecodedThread(ThreadSP thread_sp) : m_thread_sp(thread_sp) {}
+DecodedThread::DecodedThread(ThreadSP thread_sp)
+    : m_thread_sp(thread_sp), __last_tsc(0) {}
 
 DecodedThread::DecodedThread(ThreadSP thread_sp, Error &&error)
-    : m_thread_sp(thread_sp) {
+    : m_thread_sp(thread_sp), __last_tsc(0) {
   AppendError(std::move(error));
 }
 
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to