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