diff --git a/lldb/source/Plugins/Trace/intel-pt/DecodedThread.h b/lldb/source/Plugins/Trace/intel-pt/DecodedThread.h --- a/lldb/source/Plugins/Trace/intel-pt/DecodedThread.h +++ b/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 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 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(pt_insn instruction); + + /// Append a timestamp at the index of the last instruction. + void AppendInstructionTimestamp(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,21 @@ /// The instructions of the trace. llvm::ArrayRef GetInstructions() const; + /// Get timestamp of an instruction by its index. + uint64_t GetInstructionTimestamp(size_t index) const; + + /// Check if the instruction at a given index was an error. + /// -- Reasoning (this will be removed before committing) + /// This is faster and less wasteful of memory than creating an ArrayRef + /// every time that you need to check this, with GetInstructions()[i].IsError() + bool GetInstructionIsError(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 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,6 +177,7 @@ /// to update \a CalculateApproximateMemoryUsage() accordingly. lldb::ThreadSP m_thread_sp; std::vector m_instructions; + std::map m_instruction_timestamps; llvm::DenseMap m_errors; llvm::Optional m_raw_trace_size; }; diff --git a/lldb/source/Plugins/Trace/intel-pt/DecodedThread.cpp b/lldb/source/Plugins/Trace/intel-pt/DecodedThread.cpp --- a/lldb/source/Plugins/Trace/intel-pt/DecodedThread.cpp +++ b/lldb/source/Plugins/Trace/intel-pt/DecodedThread.cpp @@ -49,10 +49,6 @@ return sizeof(IntelPTInstruction); } -Optional IntelPTInstruction::GetTimestampCounter() const { - return m_timestamp; -} - Optional DecodedThread::GetRawTraceSize() const { return m_raw_trace_size; } @@ -90,6 +86,16 @@ ThreadSP DecodedThread::GetThread() { return m_thread_sp; } +void DecodedThread::AppendInstruction(pt_insn insn) { + m_instructions.emplace_back(insn); +} + +void DecodedThread::AppendInstructionTimestamp(uint64_t time) { + auto last_ts = m_instruction_timestamps.find(m_instruction_timestamps.size() - 1); + if (last_ts->second != time) + m_instruction_timestamps.emplace(m_instructions.size() - 1, time); +} + void DecodedThread::AppendError(llvm::Error &&error) { m_errors.try_emplace(m_instructions.size(), toString(std::move(error))); m_instructions.emplace_back(); @@ -99,7 +105,16 @@ return makeArrayRef(m_instructions); } -const char *DecodedThread::GetErrorByInstructionIndex(uint64_t idx) { +uint64_t DecodedThread::GetInstructionTimestamp(size_t index) const { + // m_instruction_timestamps.find(index) + return 0; +} + +bool DecodedThread::GetInstructionIsError(size_t idx) const { + return m_instructions[idx].IsError(); +} + +const char *DecodedThread::GetErrorByInstructionIndex(size_t idx) { auto it = m_errors.find(idx); if (it == m_errors.end()) return nullptr; diff --git a/lldb/source/Plugins/Trace/intel-pt/IntelPTDecoder.cpp b/lldb/source/Plugins/Trace/intel-pt/IntelPTDecoder.cpp --- a/lldb/source/Plugins/Trace/intel-pt/IntelPTDecoder.cpp +++ b/lldb/source/Plugins/Trace/intel-pt/IntelPTDecoder.cpp @@ -150,7 +150,8 @@ // was enabled. decoded_thread_sp->AppendInstruction(insn); } else { - decoded_thread_sp->AppendInstruction(insn, time); + decoded_thread_sp->AppendInstruction(insn); + decoded_thread_sp->AppendInstructionTimestamp(time); } } } diff --git a/lldb/source/Plugins/Trace/intel-pt/TraceCursorIntelPT.h b/lldb/source/Plugins/Trace/intel-pt/TraceCursorIntelPT.h --- a/lldb/source/Plugins/Trace/intel-pt/TraceCursorIntelPT.h +++ b/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. + uint64_t m_currentts; }; } // namespace trace_intel_pt diff --git a/lldb/source/Plugins/Trace/intel-pt/TraceCursorIntelPT.cpp b/lldb/source/Plugins/Trace/intel-pt/TraceCursorIntelPT.cpp --- a/lldb/source/Plugins/Trace/intel-pt/TraceCursorIntelPT.cpp +++ b/lldb/source/Plugins/Trace/intel-pt/TraceCursorIntelPT.cpp @@ -74,7 +74,7 @@ } bool TraceCursorIntelPT::IsError() { - return m_decoded_thread_sp->GetInstructions()[m_pos].IsError(); + return m_decoded_thread_sp->GetInstructionIsError(m_pos); } const char *TraceCursorIntelPT::GetError() { @@ -88,7 +88,8 @@ Optional TraceCursorIntelPT::GetCounter(lldb::TraceCounter counter_type) { switch (counter_type) { case lldb::eTraceCounterTSC: - return m_decoded_thread_sp->GetInstructions()[m_pos].GetTimestampCounter(); + // Hack to satisfy the the type of inherited member function + return Optional(m_decoded_thread_sp->GetInstructionTimestamp(m_pos)); } }