-
Notifications
You must be signed in to change notification settings - Fork 15.3k
[lldb] Introduce SBFrameList for lazy frame iteration #166651
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
@llvm/pr-subscribers-lldb Author: Med Ismail Bennani (medismailben) ChangesThis patch introduces The new The implementation uses This is particularly useful for ScriptedFrameProviders, where user scripts will be to iterate, filter, and replace frames lazily without materializing the entire stack upfront. Patch is 21.67 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/166651.diff 18 Files Affected:
diff --git a/lldb/bindings/interface/SBFrameListDocstrings.i b/lldb/bindings/interface/SBFrameListDocstrings.i
new file mode 100644
index 0000000000000..2ca10b3b4c72b
--- /dev/null
+++ b/lldb/bindings/interface/SBFrameListDocstrings.i
@@ -0,0 +1,13 @@
+%feature("docstring",
+"Represents a list of :py:class:`SBFrame` objects."
+) lldb::SBFrameList;
+
+%feature("autodoc", "GetSize(SBFrameList self) -> uint32_t") lldb::SBFrameList::GetSize;
+%feature("docstring", "
+ Returns the number of frames in the list."
+) lldb::SBFrameList::GetSize;
+
+%feature("autodoc", "GetFrameAtIndex(SBFrameList self, uint32_t idx) -> SBFrame") lldb::SBFrameList::GetFrameAtIndex;
+%feature("docstring", "
+ Returns the frame at the given index."
+) lldb::SBFrameList::GetFrameAtIndex;
\ No newline at end of file
diff --git a/lldb/bindings/interface/SBFrameListExtensions.i b/lldb/bindings/interface/SBFrameListExtensions.i
new file mode 100644
index 0000000000000..61f05add9c9a5
--- /dev/null
+++ b/lldb/bindings/interface/SBFrameListExtensions.i
@@ -0,0 +1,41 @@
+%extend lldb::SBFrameList {
+
+#ifdef SWIGPYTHON
+ %nothreadallow;
+#endif
+ std::string lldb::SBFrameList::__str__ (){
+ lldb::SBStream description;
+ if (!$self->GetDescription(description))
+ return std::string("<empty> lldb.SBFrameList()");
+ const char *desc = description.GetData();
+ size_t desc_len = description.GetSize();
+ if (desc_len > 0 && (desc[desc_len-1] == '\n' || desc[desc_len-1] == '\r'))
+ --desc_len;
+ return std::string(desc, desc_len);
+ }
+#ifdef SWIGPYTHON
+ %clearnothreadallow;
+#endif
+
+#ifdef SWIGPYTHON
+ %pythoncode %{
+ def __iter__(self):
+ '''Iterate over all frames in a lldb.SBFrameList object.'''
+ return lldb_iter(self, 'GetSize', 'GetFrameAtIndex')
+
+ def __len__(self):
+ return int(self.GetSize())
+
+ def __getitem__(self, key):
+ if type(key) is not int:
+ return None
+ if key < 0:
+ count = len(self)
+ if -count <= key < count:
+ key %= count
+
+ frame = self.GetFrameAtIndex(key)
+ return frame if frame.IsValid() else None
+ %}
+#endif
+}
\ No newline at end of file
diff --git a/lldb/bindings/interface/SBThreadExtensions.i b/lldb/bindings/interface/SBThreadExtensions.i
index 4ec9f10b1a256..c9ae4103d7b60 100644
--- a/lldb/bindings/interface/SBThreadExtensions.i
+++ b/lldb/bindings/interface/SBThreadExtensions.i
@@ -41,7 +41,8 @@ STRING_EXTENSION_OUTSIDE(SBThread)
def get_thread_frames(self):
'''An accessor function that returns a list() that contains all frames in a lldb.SBThread object.'''
frames = []
- for frame in self:
+ frame_list = self.GetFrames()
+ for frame in frame_list:
frames.append(frame)
return frames
diff --git a/lldb/bindings/interfaces.swig b/lldb/bindings/interfaces.swig
index b3d44979c916c..5fe058e33e619 100644
--- a/lldb/bindings/interfaces.swig
+++ b/lldb/bindings/interfaces.swig
@@ -39,6 +39,7 @@
%include "./interface/SBFileSpecListDocstrings.i"
%include "./interface/SBFormatDocstrings.i"
%include "./interface/SBFrameDocstrings.i"
+%include "./interface/SBFrameListDocstrings.i"
%include "./interface/SBFunctionDocstrings.i"
%include "./interface/SBHostOSDocstrings.i"
%include "./interface/SBInstructionDocstrings.i"
@@ -119,6 +120,7 @@
%include "lldb/API/SBFileSpecList.h"
%include "lldb/API/SBFormat.h"
%include "lldb/API/SBFrame.h"
+%include "lldb/API/SBFrameList.h"
%include "lldb/API/SBFunction.h"
%include "lldb/API/SBHostOS.h"
%include "lldb/API/SBInstruction.h"
@@ -193,6 +195,7 @@
%include "./interface/SBFileSpecExtensions.i"
%include "./interface/SBFileSpecListExtensions.i"
%include "./interface/SBFrameExtensions.i"
+%include "./interface/SBFrameListExtensions.i"
%include "./interface/SBFunctionExtensions.i"
%include "./interface/SBInstructionExtensions.i"
%include "./interface/SBInstructionListExtensions.i"
diff --git a/lldb/include/lldb/API/LLDB.h b/lldb/include/lldb/API/LLDB.h
index 6485f35302a1c..6ac35bb4a364b 100644
--- a/lldb/include/lldb/API/LLDB.h
+++ b/lldb/include/lldb/API/LLDB.h
@@ -37,6 +37,7 @@
#include "lldb/API/SBFileSpecList.h"
#include "lldb/API/SBFormat.h"
#include "lldb/API/SBFrame.h"
+#include "lldb/API/SBFrameList.h"
#include "lldb/API/SBFunction.h"
#include "lldb/API/SBHostOS.h"
#include "lldb/API/SBInstruction.h"
diff --git a/lldb/include/lldb/API/SBDefines.h b/lldb/include/lldb/API/SBDefines.h
index 85f6bbeea5bf9..5fcc685050c0b 100644
--- a/lldb/include/lldb/API/SBDefines.h
+++ b/lldb/include/lldb/API/SBDefines.h
@@ -76,6 +76,7 @@ class LLDB_API SBFileSpec;
class LLDB_API SBFileSpecList;
class LLDB_API SBFormat;
class LLDB_API SBFrame;
+class LLDB_API SBFrameList;
class LLDB_API SBFunction;
class LLDB_API SBHostOS;
class LLDB_API SBInstruction;
diff --git a/lldb/include/lldb/API/SBFrame.h b/lldb/include/lldb/API/SBFrame.h
index 92917e57fc125..5283cdfe53faa 100644
--- a/lldb/include/lldb/API/SBFrame.h
+++ b/lldb/include/lldb/API/SBFrame.h
@@ -222,6 +222,7 @@ class LLDB_API SBFrame {
protected:
friend class SBBlock;
friend class SBExecutionContext;
+ friend class SBFrameList;
friend class SBInstruction;
friend class SBThread;
friend class SBValue;
diff --git a/lldb/include/lldb/API/SBFrameList.h b/lldb/include/lldb/API/SBFrameList.h
new file mode 100644
index 0000000000000..4b875f848829e
--- /dev/null
+++ b/lldb/include/lldb/API/SBFrameList.h
@@ -0,0 +1,57 @@
+//===------------------------------------------------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_API_SBFRAMELIST_H
+#define LLDB_API_SBFRAMELIST_H
+
+#include "lldb/API/SBDefines.h"
+
+namespace lldb {
+
+class LLDB_API SBFrameList {
+public:
+ SBFrameList();
+
+ SBFrameList(const lldb::SBFrameList &rhs);
+
+ ~SBFrameList();
+
+ const lldb::SBFrameList &operator=(const lldb::SBFrameList &rhs);
+
+ explicit operator bool() const;
+
+ bool IsValid() const;
+
+ uint32_t GetSize() const;
+
+ lldb::SBFrame GetFrameAtIndex(uint32_t idx) const;
+
+ lldb::SBThread GetThread() const;
+
+ void Clear();
+
+ void Append(const lldb::SBFrame &frame);
+
+ void Append(const lldb::SBFrameList &frame_list);
+
+ bool GetDescription(lldb::SBStream &description) const;
+
+protected:
+ friend class SBThread;
+
+private:
+ SBFrameList(const lldb::StackFrameListSP &frame_list_sp);
+
+ void SetFrameList(const lldb::StackFrameListSP &frame_list_sp);
+
+ lldb::StackFrameListSP m_opaque_sp;
+};
+
+} // namespace lldb
+
+#endif // LLDB_API_SBFRAMELIST_H
diff --git a/lldb/include/lldb/API/SBStream.h b/lldb/include/lldb/API/SBStream.h
index d230da6123fb3..21f9d21e0e717 100644
--- a/lldb/include/lldb/API/SBStream.h
+++ b/lldb/include/lldb/API/SBStream.h
@@ -81,6 +81,7 @@ class LLDB_API SBStream {
friend class SBFileSpec;
friend class SBFileSpecList;
friend class SBFrame;
+ friend class SBFrameList;
friend class SBFunction;
friend class SBInstruction;
friend class SBInstructionList;
diff --git a/lldb/include/lldb/API/SBThread.h b/lldb/include/lldb/API/SBThread.h
index e9fe5858d125e..3a78026c6687b 100644
--- a/lldb/include/lldb/API/SBThread.h
+++ b/lldb/include/lldb/API/SBThread.h
@@ -178,6 +178,8 @@ class LLDB_API SBThread {
lldb::SBFrame GetFrameAtIndex(uint32_t idx);
+ lldb::SBFrameList GetFrames();
+
lldb::SBFrame GetSelectedFrame();
lldb::SBFrame SetSelectedFrame(uint32_t frame_idx);
@@ -236,6 +238,7 @@ class LLDB_API SBThread {
friend class SBSaveCoreOptions;
friend class SBExecutionContext;
friend class SBFrame;
+ friend class SBFrameList;
friend class SBProcess;
friend class SBDebugger;
friend class SBValue;
diff --git a/lldb/include/lldb/Target/StackFrameList.h b/lldb/include/lldb/Target/StackFrameList.h
index ea9aab86b8ea1..5b0df0ddb3e29 100644
--- a/lldb/include/lldb/Target/StackFrameList.h
+++ b/lldb/include/lldb/Target/StackFrameList.h
@@ -101,6 +101,9 @@ class StackFrameList {
/// Returns whether we have currently fetched all the frames of a stack.
bool WereAllFramesFetched() const;
+ /// Get the thread associated with this frame list.
+ Thread &GetThread() const { return m_thread; }
+
protected:
friend class Thread;
friend class ScriptedThread;
diff --git a/lldb/include/lldb/Target/Thread.h b/lldb/include/lldb/Target/Thread.h
index 688c056da2633..841f80cd1b1eb 100644
--- a/lldb/include/lldb/Target/Thread.h
+++ b/lldb/include/lldb/Target/Thread.h
@@ -1295,6 +1295,8 @@ class Thread : public std::enable_shared_from_this<Thread>,
/// an empty std::optional is returned in that case.
std::optional<lldb::addr_t> GetPreviousFrameZeroPC();
+ lldb::StackFrameListSP GetStackFrameList();
+
protected:
friend class ThreadPlan;
friend class ThreadList;
@@ -1336,8 +1338,6 @@ class Thread : public std::enable_shared_from_this<Thread>,
return StructuredData::ObjectSP();
}
- lldb::StackFrameListSP GetStackFrameList();
-
void SetTemporaryResumeState(lldb::StateType new_state) {
m_temporary_resume_state = new_state;
}
diff --git a/lldb/source/API/CMakeLists.txt b/lldb/source/API/CMakeLists.txt
index ce59ee505cd3d..ac47580d60840 100644
--- a/lldb/source/API/CMakeLists.txt
+++ b/lldb/source/API/CMakeLists.txt
@@ -69,6 +69,7 @@ add_lldb_library(liblldb SHARED ${option_framework}
SBFileSpecList.cpp
SBFormat.cpp
SBFrame.cpp
+ SBFrameList.cpp
SBFunction.cpp
SBHostOS.cpp
SBInstruction.cpp
diff --git a/lldb/source/API/SBFrameList.cpp b/lldb/source/API/SBFrameList.cpp
new file mode 100644
index 0000000000000..77f58e3ffc080
--- /dev/null
+++ b/lldb/source/API/SBFrameList.cpp
@@ -0,0 +1,111 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 "lldb/API/SBFrameList.h"
+#include "lldb/API/SBFrame.h"
+#include "lldb/API/SBStream.h"
+#include "lldb/API/SBThread.h"
+#include "lldb/Target/StackFrameList.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Utility/Instrumentation.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+SBFrameList::SBFrameList() : m_opaque_sp() { LLDB_INSTRUMENT_VA(this); }
+
+SBFrameList::SBFrameList(const SBFrameList &rhs)
+ : m_opaque_sp(rhs.m_opaque_sp) {
+ LLDB_INSTRUMENT_VA(this, rhs);
+}
+
+SBFrameList::~SBFrameList() = default;
+
+const SBFrameList &SBFrameList::operator=(const SBFrameList &rhs) {
+ LLDB_INSTRUMENT_VA(this, rhs);
+
+ if (this != &rhs)
+ m_opaque_sp = rhs.m_opaque_sp;
+ return *this;
+}
+
+SBFrameList::SBFrameList(const lldb::StackFrameListSP &frame_list_sp)
+ : m_opaque_sp(frame_list_sp) {}
+
+void SBFrameList::SetFrameList(const lldb::StackFrameListSP &frame_list_sp) {
+ m_opaque_sp = frame_list_sp;
+}
+
+SBFrameList::operator bool() const {
+ LLDB_INSTRUMENT_VA(this);
+
+ return m_opaque_sp.get() != nullptr;
+}
+
+bool SBFrameList::IsValid() const {
+ LLDB_INSTRUMENT_VA(this);
+ return this->operator bool();
+}
+
+uint32_t SBFrameList::GetSize() const {
+ LLDB_INSTRUMENT_VA(this);
+
+ if (m_opaque_sp)
+ return m_opaque_sp->GetNumFrames();
+ return 0;
+}
+
+SBFrame SBFrameList::GetFrameAtIndex(uint32_t idx) const {
+ LLDB_INSTRUMENT_VA(this, idx);
+
+ SBFrame sb_frame;
+ if (m_opaque_sp)
+ sb_frame.SetFrameSP(m_opaque_sp->GetFrameAtIndex(idx));
+ return sb_frame;
+}
+
+SBThread SBFrameList::GetThread() const {
+ LLDB_INSTRUMENT_VA(this);
+
+ SBThread sb_thread;
+ if (m_opaque_sp)
+ sb_thread.SetThread(m_opaque_sp->GetThread().shared_from_this());
+ return sb_thread;
+}
+
+void SBFrameList::Clear() {
+ LLDB_INSTRUMENT_VA(this);
+
+ if (m_opaque_sp)
+ m_opaque_sp->Clear();
+}
+
+void SBFrameList::Append(const SBFrame &frame) {
+ LLDB_INSTRUMENT_VA(this, frame);
+
+ // Note: StackFrameList doesn't have an Append method, so this is a no-op
+ // This method is kept for API consistency with other SB*List classes
+}
+
+void SBFrameList::Append(const SBFrameList &frame_list) {
+ LLDB_INSTRUMENT_VA(this, frame_list);
+
+ // Note: StackFrameList doesn't have an Append method, so this is a no-op
+ // This method is kept for API consistency with other SB*List classes
+}
+
+bool SBFrameList::GetDescription(SBStream &description) const {
+ LLDB_INSTRUMENT_VA(this, description);
+
+ Stream &strm = description.ref();
+ if (m_opaque_sp) {
+ m_opaque_sp->Dump(&strm);
+ return true;
+ }
+ return false;
+}
diff --git a/lldb/source/API/SBThread.cpp b/lldb/source/API/SBThread.cpp
index 4e4aa48bc9a2e..2351d787c74e9 100644
--- a/lldb/source/API/SBThread.cpp
+++ b/lldb/source/API/SBThread.cpp
@@ -14,6 +14,7 @@
#include "lldb/API/SBFileSpec.h"
#include "lldb/API/SBFormat.h"
#include "lldb/API/SBFrame.h"
+#include "lldb/API/SBFrameList.h"
#include "lldb/API/SBProcess.h"
#include "lldb/API/SBStream.h"
#include "lldb/API/SBStructuredData.h"
@@ -1079,6 +1080,26 @@ SBFrame SBThread::GetFrameAtIndex(uint32_t idx) {
return sb_frame;
}
+lldb::SBFrameList SBThread::GetFrames() {
+ LLDB_INSTRUMENT_VA(this);
+
+ SBFrameList sb_frame_list;
+ llvm::Expected<StoppedExecutionContext> exe_ctx =
+ GetStoppedExecutionContext(m_opaque_sp);
+ if (!exe_ctx) {
+ LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
+ return SBFrameList();
+ }
+
+ if (exe_ctx->HasThreadScope()) {
+ StackFrameListSP frame_list_sp =
+ exe_ctx->GetThreadPtr()->GetStackFrameList();
+ sb_frame_list.SetFrameList(frame_list_sp);
+ }
+
+ return sb_frame_list;
+}
+
lldb::SBFrame SBThread::GetSelectedFrame() {
LLDB_INSTRUMENT_VA(this);
diff --git a/lldb/test/API/python_api/frame_list/Makefile b/lldb/test/API/python_api/frame_list/Makefile
new file mode 100644
index 0000000000000..2bb9ce046a907
--- /dev/null
+++ b/lldb/test/API/python_api/frame_list/Makefile
@@ -0,0 +1,3 @@
+CXX_SOURCES := main.cpp
+
+include Makefile.rules
\ No newline at end of file
diff --git a/lldb/test/API/python_api/frame_list/TestSBFrameList.py b/lldb/test/API/python_api/frame_list/TestSBFrameList.py
new file mode 100644
index 0000000000000..f348ce492e547
--- /dev/null
+++ b/lldb/test/API/python_api/frame_list/TestSBFrameList.py
@@ -0,0 +1,194 @@
+"""
+Test SBFrameList API.
+"""
+
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class FrameListAPITestCase(TestBase):
+ def test_frame_list_api(self):
+ """Test SBThread.GetFrames() returns a valid SBFrameList."""
+ self.build()
+ self.frame_list_api()
+
+ def test_frame_list_iterator(self):
+ """Test SBFrameList iterator functionality."""
+ self.build()
+ self.frame_list_iterator()
+
+ def test_frame_list_indexing(self):
+ """Test SBFrameList indexing and length."""
+ self.build()
+ self.frame_list_indexing()
+
+ def test_frame_list_get_thread(self):
+ """Test SBFrameList.GetThread() returns correct thread."""
+ self.build()
+ self.frame_list_get_thread()
+
+ def setUp(self):
+ TestBase.setUp(self)
+ self.main_source = "main.cpp"
+
+ def frame_list_api(self):
+ """Test SBThread.GetFrames() returns a valid SBFrameList."""
+ exe = self.getBuildArtifact("a.out")
+
+ target, process, thread, bkpt = lldbutil.run_to_source_breakpoint(
+ self, "Set break point at this line", lldb.SBFileSpec(self.main_source)
+ )
+
+ self.assertTrue(
+ thread.IsValid(), "There should be a thread stopped due to breakpoint"
+ )
+
+ # Test GetFrames() returns a valid SBFrameList
+ frame_list = thread.GetFrames()
+ self.assertTrue(frame_list.IsValid(), "Frame list should be valid")
+ self.assertGreater(
+ frame_list.GetSize(), 0, "Frame list should have at least one frame"
+ )
+
+ # Verify frame list size matches thread frame count
+ self.assertEqual(
+ frame_list.GetSize(),
+ thread.GetNumFrames(),
+ "Frame list size should match thread frame count",
+ )
+
+ # Verify frames are the same
+ for i in range(frame_list.GetSize()):
+ frame_from_list = frame_list.GetFrameAtIndex(i)
+ frame_from_thread = thread.GetFrameAtIndex(i)
+ self.assertTrue(
+ frame_from_list.IsValid(), f"Frame {i} from list should be valid"
+ )
+ self.assertEqual(
+ frame_from_list.GetPC(),
+ frame_from_thread.GetPC(),
+ f"Frame {i} PC should match",
+ )
+
+ def frame_list_iterator(self):
+ """Test SBFrameList iterator functionality."""
+ exe = self.getBuildArtifact("a.out")
+
+ target, process, thread, bkpt = lldbutil.run_to_source_breakpoint(
+ self, "Set break point at this line", lldb.SBFileSpec(self.main_source)
+ )
+
+ self.assertTrue(
+ thread.IsValid(), "There should be a thread stopped due to breakpoint"
+ )
+
+ frame_list = thread.GetFrames()
+
+ # Test iteration
+ frame_count = 0
+ for frame in frame_list:
+ self.assertTrue(frame.IsValid(), "Each frame should be valid")
+ frame_count += 1
+
+ self.assertEqual(
+ frame_count,
+ frame_list.GetSize(),
+ "Iterator should visit all frames",
+ )
+
+ # Test that we can iterate multiple times
+ second_count = 0
+ for frame in frame_list:
+ second_count += 1
+
+ self.assertEqual(
+ frame_count, second_count, "Should be able to iterate multiple times"
+ )
+
+ def frame_list_indexing(self):
+ """Test SBFrameList indexing and length."""
+ exe = self.getBuildArtifact("a.out")
+
+ target, process, thread, bkpt = lldbutil.run_to_source_breakpoint(
+ self, "Set break point at this line", lldb.SBFileSpec(self.main_source)
+ )
+
+ self.assertTrue(
+ thread.IsValid(), "There should be a thread stopped due to breakpoint"
+ )
+
+ frame_list = thread.GetFrames()
+
+ # Test len()
+ self.assertEqual(
+ len(frame_list), frame_list.GetSize(), "len() should return frame count"
+ )
+
+ # Test positive indexing
+ first_frame = frame_list[0]
+ self.assertTrue(first_frame.IsValid(), "First frame should be valid")
+ self.assertEqual(
+ first_frame.GetPC(),
+ thread.GetFrameAtIndex(0).GetPC(),
+ "Indexed frame should match",
+ )
+
+ # Test negative indexing
+ if len(frame_list) > 0:
+ last_frame = frame_list[-1]
+ self.assertTrue(last_frame.IsValid(), "Last frame should be valid")
+ self.assertEqual(
+ last_frame.GetPC(),
+ thread.GetFrameAtIndex(len(frame_list) - 1).GetPC(),
+ "Negative indexing should work",
+ )
+
+ # Test out of bounds returns None
+ out_of_bounds = frame_list[10000]
+ self.assertIsNone(out_of_bounds, "Out of bounds index should return None")
+
+ # Test bool conversion
+ self.assertTrue(bool(frame_list), "Non-empty frame list should be truthy")
+
+ # Test Clear()
+ frame_list.Clear()
+ # Note: Clear() clears the underlying StackFrameList cache,
+ # but the frame list object itself should still be valid
+ self.assertTrue(
+ frame_list.IsValid(), "Frame list should still be valid after Clear()"
+ )
+
+ def frame_list_get_thread(self):
+ """Test SBFrameList.GetThread() returns correct thr...
[truncated]
|
aa9c49a to
244ae1a
Compare
JDevlieghere
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM modulo missing newlines.
244ae1a to
53a6cf7
Compare
This patch introduces `SBFrameList`, a new SBAPI class that allows iterating over stack frames lazily without calling `SBThread::GetFrameAtIndex` in a loop. The new `SBThread::GetFrames()` method returns an `SBFrameList` that supports Python iteration (`for frame in frame_list:`), indexing (`frame_list[0]`, `frame_list[-1]`), and length queries (`len()`). The implementation uses `StackFrameListSP` as the opaque pointer, sharing the thread's underlying frame list to ensure frames are materialized on-demand. This is particularly useful for ScriptedFrameProviders, where user scripts can now iterate, filter, and replace frames lazily without materializing the entire stack upfront. Signed-off-by: Med Ismail Bennani <[email protected]>
ea90698 to
c8b43aa
Compare
This patch introduces `SBFrameList`, a new SBAPI class that allows iterating over stack frames lazily without calling `SBThread::GetFrameAtIndex` in a loop. The new `SBThread::GetFrames()` method returns an `SBFrameList` that supports Python iteration (`for frame in frame_list:`), indexing (`frame_list[0]`, `frame_list[-1]`), and length queries (`len()`). The implementation uses `StackFrameListSP` as the opaque pointer, sharing the thread's underlying frame list to ensure frames are materialized on-demand. This is particularly useful for ScriptedFrameProviders, where user scripts will be to iterate, filter, and replace frames lazily without materializing the entire stack upfront. Signed-off-by: Med Ismail Bennani <[email protected]> (cherry picked from commit d584d00)
This patch introduces `SBFrameList`, a new SBAPI class that allows iterating over stack frames lazily without calling `SBThread::GetFrameAtIndex` in a loop. The new `SBThread::GetFrames()` method returns an `SBFrameList` that supports Python iteration (`for frame in frame_list:`), indexing (`frame_list[0]`, `frame_list[-1]`), and length queries (`len()`). The implementation uses `StackFrameListSP` as the opaque pointer, sharing the thread's underlying frame list to ensure frames are materialized on-demand. This is particularly useful for ScriptedFrameProviders, where user scripts will be to iterate, filter, and replace frames lazily without materializing the entire stack upfront. Signed-off-by: Med Ismail Bennani <[email protected]> (cherry picked from commit d584d00)
This patch introduces
SBFrameList, a new SBAPI class that allows iterating over stack frames lazily without callingSBThread::GetFrameAtIndexin a loop.The new
SBThread::GetFrames()method returns anSBFrameListthat supports Python iteration (for frame in frame_list:), indexing (frame_list[0],frame_list[-1]), and length queries (len()).The implementation uses
StackFrameListSPas the opaque pointer, sharing the thread's underlying frame list to ensure frames are materialized on-demand.This is particularly useful for ScriptedFrameProviders, where user scripts will be to iterate, filter, and replace frames lazily without materializing the entire stack upfront.