[Lldb-commits] [lldb] [lldb] Consolidate ScriptedThreadPlan state into ScriptedMetadata (PR #199064)

Med Ismail Bennani via lldb-commits lldb-commits at lists.llvm.org
Thu May 21 09:13:14 PDT 2026


https://github.com/medismailben updated https://github.com/llvm/llvm-project/pull/199064

>From f405a2b3e8b6f2e2a4c758cb81fd0579a9b6f9d2 Mon Sep 17 00:00:00 2001
From: Med Ismail Bennani <ismail at bennani.ma>
Date: Thu, 21 May 2026 09:11:17 -0700
Subject: [PATCH] [lldb] Consolidate ScriptedThreadPlan state into
 ScriptedMetadata

This is a follow-up to 1b4a578a9f77.

Replace ScriptedThreadPlan's separate `m_class_name` and `m_args_data`
members with a single `m_scripted_metadata`, and update its constructor,
Thread::QueueThreadPlanForStepScripted and the SB/CLI callers to take a
`const ScriptedMetadata &` directly. Drop the now-redundant `args_sp`
parameter from ScriptedThreadPlanInterface::CreatePluginObject; the
Python override constructs a StructuredDataImpl from the metadata's
args dict for the dispatched call.

ScriptedThreadPlan keeps its own `m_scripted_metadata` member because
the interface's metadata is only set when `DidPush()` calls
`CreatePluginObject`, so the plan needs to hold the metadata between
construction and `DidPush()`.

Signed-off-by: Med Ismail Bennani <ismail at bennani.ma>
---
 .../Interfaces/ScriptedThreadPlanInterface.h  |  3 +-
 lldb/include/lldb/Target/ScriptedThreadPlan.h |  9 ++--
 lldb/include/lldb/Target/Thread.h             |  5 +-
 lldb/source/API/SBThread.cpp                  |  7 ++-
 lldb/source/API/SBThreadPlan.cpp              | 34 ++++++++++----
 lldb/source/Commands/CommandObjectThread.cpp  |  5 +-
 .../ScriptedThreadPlanPythonInterface.cpp     |  3 +-
 .../ScriptedThreadPlanPythonInterface.h       |  3 +-
 lldb/source/Target/ScriptedThreadPlan.cpp     | 47 ++++++++++---------
 lldb/source/Target/Thread.cpp                 |  9 ++--
 10 files changed, 76 insertions(+), 49 deletions(-)

diff --git a/lldb/include/lldb/Interpreter/Interfaces/ScriptedThreadPlanInterface.h b/lldb/include/lldb/Interpreter/Interfaces/ScriptedThreadPlanInterface.h
index c81166c9c6c35..6c9acc1d8691f 100644
--- a/lldb/include/lldb/Interpreter/Interfaces/ScriptedThreadPlanInterface.h
+++ b/lldb/include/lldb/Interpreter/Interfaces/ScriptedThreadPlanInterface.h
@@ -18,8 +18,7 @@ class ScriptedThreadPlanInterface : public ScriptedInterface {
 public:
   virtual llvm::Expected<StructuredData::GenericSP>
   CreatePluginObject(const ScriptedMetadata &scripted_metadata,
-                     lldb::ThreadPlanSP thread_plan_sp,
-                     const StructuredDataImpl &args_sp) = 0;
+                     lldb::ThreadPlanSP thread_plan_sp) = 0;
 
   virtual llvm::Expected<bool> ExplainsStop(Event *event) { return true; }
 
diff --git a/lldb/include/lldb/Target/ScriptedThreadPlan.h b/lldb/include/lldb/Target/ScriptedThreadPlan.h
index 7532b6b0a41c5..99f0c3f7d41ba 100644
--- a/lldb/include/lldb/Target/ScriptedThreadPlan.h
+++ b/lldb/include/lldb/Target/ScriptedThreadPlan.h
@@ -19,6 +19,7 @@
 #include "lldb/Target/Thread.h"
 #include "lldb/Target/ThreadPlan.h"
 #include "lldb/Target/ThreadPlanTracer.h"
+#include "lldb/Utility/ScriptedMetadata.h"
 #include "lldb/Utility/StructuredData.h"
 #include "lldb/Utility/UserID.h"
 #include "lldb/lldb-forward.h"
@@ -28,8 +29,7 @@ namespace lldb_private {
 
 class ScriptedThreadPlan : public ThreadPlan {
 public:
-  ScriptedThreadPlan(Thread &thread, const char *class_name,
-                     const StructuredDataImpl &args_data);
+  ScriptedThreadPlan(Thread &thread, const ScriptedMetadata &scripted_metadata);
 
   void GetDescription(Stream *s, lldb::DescriptionLevel level) override;
 
@@ -58,9 +58,10 @@ class ScriptedThreadPlan : public ThreadPlan {
 
   ScriptInterpreter *GetScriptInterpreter();
 
+  llvm::StringRef GetScriptClassName() const;
+
 private:
-  std::string m_class_name;
-  StructuredDataImpl m_args_data;
+  ScriptedMetadata m_scripted_metadata;
   std::string m_error_str;
   StructuredData::ObjectSP m_implementation_sp;
   StreamString m_stop_description; // Cache the stop description here
diff --git a/lldb/include/lldb/Target/Thread.h b/lldb/include/lldb/Target/Thread.h
index 58bd6960a803d..8664c2148b463 100644
--- a/lldb/include/lldb/Target/Thread.h
+++ b/lldb/include/lldb/Target/Thread.h
@@ -24,6 +24,7 @@
 #include "lldb/Utility/Broadcaster.h"
 #include "lldb/Utility/CompletionRequest.h"
 #include "lldb/Utility/Event.h"
+#include "lldb/Utility/ScriptedMetadata.h"
 #include "lldb/Utility/StructuredData.h"
 #include "lldb/Utility/UnimplementedError.h"
 #include "lldb/Utility/UserID.h"
@@ -1009,8 +1010,8 @@ class Thread : public std::enable_shared_from_this<Thread>,
       bool stop_others, uint32_t frame_idx, Status &status);
 
   virtual lldb::ThreadPlanSP
-  QueueThreadPlanForStepScripted(bool abort_other_plans, const char *class_name,
-                                 StructuredData::ObjectSP extra_args_sp,
+  QueueThreadPlanForStepScripted(bool abort_other_plans,
+                                 const ScriptedMetadata &scripted_metadata,
                                  bool stop_other_threads, Status &status);
 
   // Thread Plan accessors:
diff --git a/lldb/source/API/SBThread.cpp b/lldb/source/API/SBThread.cpp
index 8f672ae539780..fafb533771e56 100644
--- a/lldb/source/API/SBThread.cpp
+++ b/lldb/source/API/SBThread.cpp
@@ -897,8 +897,13 @@ SBError SBThread::StepUsingScriptedThreadPlan(const char *script_class_name,
   Status new_plan_status;
   StructuredData::ObjectSP obj_sp = args_data.m_impl_up->GetObjectSP();
 
+  StructuredData::DictionarySP args_dict_sp;
+  if (obj_sp && obj_sp->GetType() == lldb::eStructuredDataTypeDictionary)
+    args_dict_sp = std::static_pointer_cast<StructuredData::Dictionary>(obj_sp);
+
+  ScriptedMetadata scripted_metadata(script_class_name, args_dict_sp);
   ThreadPlanSP new_plan_sp = thread->QueueThreadPlanForStepScripted(
-      false, script_class_name, obj_sp, false, new_plan_status);
+      false, scripted_metadata, false, new_plan_status);
 
   if (new_plan_status.Fail()) {
     error = Status::FromErrorString(new_plan_status.AsCString());
diff --git a/lldb/source/API/SBThreadPlan.cpp b/lldb/source/API/SBThreadPlan.cpp
index c8ca6c81a3efb..88cf87c9dbe60 100644
--- a/lldb/source/API/SBThreadPlan.cpp
+++ b/lldb/source/API/SBThreadPlan.cpp
@@ -65,9 +65,11 @@ SBThreadPlan::SBThreadPlan(lldb::SBThread &sb_thread, const char *class_name) {
   LLDB_INSTRUMENT_VA(this, sb_thread, class_name);
 
   Thread *thread = sb_thread.get();
-  if (thread)
-    m_opaque_wp = std::make_shared<ScriptedThreadPlan>(*thread, class_name,
-                                                       StructuredDataImpl());
+  if (thread) {
+    ScriptedMetadata scripted_metadata(class_name, {});
+    m_opaque_wp =
+        std::make_shared<ScriptedThreadPlan>(*thread, scripted_metadata);
+  }
 }
 
 SBThreadPlan::SBThreadPlan(lldb::SBThread &sb_thread, const char *class_name,
@@ -75,9 +77,17 @@ SBThreadPlan::SBThreadPlan(lldb::SBThread &sb_thread, const char *class_name,
   LLDB_INSTRUMENT_VA(this, sb_thread, class_name, args_data);
 
   Thread *thread = sb_thread.get();
-  if (thread)
-    m_opaque_wp = std::make_shared<ScriptedThreadPlan>(*thread, class_name,
-                                                       *args_data.m_impl_up);
+  if (thread) {
+    StructuredData::ObjectSP args_obj = args_data.m_impl_up->GetObjectSP();
+    StructuredData::DictionarySP args_dict_sp;
+    if (args_obj &&
+        args_obj->GetType() == lldb::eStructuredDataTypeDictionary)
+      args_dict_sp =
+          std::static_pointer_cast<StructuredData::Dictionary>(args_obj);
+    ScriptedMetadata scripted_metadata(class_name, args_dict_sp);
+    m_opaque_wp =
+        std::make_shared<ScriptedThreadPlan>(*thread, scripted_metadata);
+  }
 }
 
 // Assignment operator
@@ -397,10 +407,10 @@ SBThreadPlan::QueueThreadPlanForStepScripted(const char *script_class_name,
   ThreadPlanSP thread_plan_sp(GetSP());
   if (thread_plan_sp) {
     Status plan_status;
-    StructuredData::ObjectSP empty_args;
+    ScriptedMetadata scripted_metadata(script_class_name, {});
     SBThreadPlan plan =
         SBThreadPlan(thread_plan_sp->GetThread().QueueThreadPlanForStepScripted(
-            false, script_class_name, empty_args, false, plan_status));
+            false, scripted_metadata, false, plan_status));
 
     if (plan_status.Fail())
       error.SetErrorString(plan_status.AsCString());
@@ -422,9 +432,15 @@ SBThreadPlan::QueueThreadPlanForStepScripted(const char *script_class_name,
   if (thread_plan_sp) {
     Status plan_status;
     StructuredData::ObjectSP args_obj = args_data.m_impl_up->GetObjectSP();
+    StructuredData::DictionarySP args_dict_sp;
+    if (args_obj &&
+        args_obj->GetType() == lldb::eStructuredDataTypeDictionary)
+      args_dict_sp =
+          std::static_pointer_cast<StructuredData::Dictionary>(args_obj);
+    ScriptedMetadata scripted_metadata(script_class_name, args_dict_sp);
     SBThreadPlan plan =
         SBThreadPlan(thread_plan_sp->GetThread().QueueThreadPlanForStepScripted(
-            false, script_class_name, args_obj, false, plan_status));
+            false, scripted_metadata, false, plan_status));
 
     if (plan_status.Fail())
       error.SetErrorString(plan_status.AsCString());
diff --git a/lldb/source/Commands/CommandObjectThread.cpp b/lldb/source/Commands/CommandObjectThread.cpp
index 229e29fcb26c4..1cf9cefd87193 100644
--- a/lldb/source/Commands/CommandObjectThread.cpp
+++ b/lldb/source/Commands/CommandObjectThread.cpp
@@ -745,9 +745,10 @@ class CommandObjectThreadStepWithTypeAndScope : public CommandObjectParsed {
           thread->GetSelectedFrameIndex(DoNoSelectMostRelevantFrame),
           new_plan_status, m_options.m_step_out_avoid_no_debug);
     } else if (m_step_type == eStepTypeScripted) {
+      ScriptedMetadata scripted_metadata(m_class_options.GetName(),
+                                         m_class_options.GetStructuredData());
       new_plan_sp = thread->QueueThreadPlanForStepScripted(
-          abort_other_plans, m_class_options.GetName().c_str(),
-          m_class_options.GetStructuredData(), bool_stop_other_threads,
+          abort_other_plans, scripted_metadata, bool_stop_other_threads,
           new_plan_status);
     } else {
       result.AppendError("step type is not supported");
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPlanPythonInterface.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPlanPythonInterface.cpp
index cce342c4b3eb8..007765daef818 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPlanPythonInterface.cpp
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPlanPythonInterface.cpp
@@ -28,7 +28,8 @@ ScriptedThreadPlanPythonInterface::ScriptedThreadPlanPythonInterface(
 llvm::Expected<StructuredData::GenericSP>
 ScriptedThreadPlanPythonInterface::CreatePluginObject(
     const ScriptedMetadata &scripted_metadata,
-    lldb::ThreadPlanSP thread_plan_sp, const StructuredDataImpl &args_sp) {
+    lldb::ThreadPlanSP thread_plan_sp) {
+  StructuredDataImpl args_sp(scripted_metadata.GetArgsSP());
   return ScriptedPythonInterface::CreatePluginObject(scripted_metadata, nullptr,
                                                      thread_plan_sp, args_sp);
 }
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPlanPythonInterface.h b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPlanPythonInterface.h
index 7efd894d9d53a..efb3225b36df7 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPlanPythonInterface.h
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedThreadPlanPythonInterface.h
@@ -24,8 +24,7 @@ class ScriptedThreadPlanPythonInterface : public ScriptedThreadPlanInterface,
 
   llvm::Expected<StructuredData::GenericSP>
   CreatePluginObject(const ScriptedMetadata &scripted_metadata,
-                     lldb::ThreadPlanSP thread_plan_sp,
-                     const StructuredDataImpl &args_sp) override;
+                     lldb::ThreadPlanSP thread_plan_sp) override;
 
   llvm::SmallVector<AbstractMethodRequirement>
   GetAbstractMethodRequirements() const override {
diff --git a/lldb/source/Target/ScriptedThreadPlan.cpp b/lldb/source/Target/ScriptedThreadPlan.cpp
index 757417ac649c7..e218299f0909d 100644
--- a/lldb/source/Target/ScriptedThreadPlan.cpp
+++ b/lldb/source/Target/ScriptedThreadPlan.cpp
@@ -24,11 +24,11 @@
 using namespace lldb;
 using namespace lldb_private;
 
-ScriptedThreadPlan::ScriptedThreadPlan(Thread &thread, const char *class_name,
-                                       const StructuredDataImpl &args_data)
+ScriptedThreadPlan::ScriptedThreadPlan(
+    Thread &thread, const ScriptedMetadata &scripted_metadata)
     : ThreadPlan(ThreadPlan::eKindPython, "Script based Thread Plan", thread,
                  eVoteNoOpinion, eVoteNoOpinion),
-      m_class_name(class_name), m_args_data(args_data), m_did_push(false),
+      m_scripted_metadata(scripted_metadata), m_did_push(false),
       m_stop_others(false) {
   ScriptInterpreter *interpreter = GetScriptInterpreter();
   if (!interpreter) {
@@ -74,14 +74,19 @@ ScriptInterpreter *ScriptedThreadPlan::GetScriptInterpreter() {
   return m_process.GetTarget().GetDebugger().GetScriptInterpreter();
 }
 
+llvm::StringRef ScriptedThreadPlan::GetScriptClassName() const {
+  if (m_interface && m_interface->GetScriptedMetadata())
+    return m_interface->GetScriptedMetadata()->GetClassName();
+  return "<unknown>";
+}
+
 void ScriptedThreadPlan::DidPush() {
   // We set up the script side in DidPush, so that it can push other plans in
   // the constructor, and doesn't have to care about the details of DidPush.
   m_did_push = true;
   if (m_interface) {
-    ScriptedMetadata scripted_metadata(m_class_name, {});
     auto obj_or_err = m_interface->CreatePluginObject(
-        scripted_metadata, this->shared_from_this(), m_args_data);
+        m_scripted_metadata, this->shared_from_this());
     if (!obj_or_err) {
       m_error_str = llvm::toString(obj_or_err.takeError());
       SetPlanComplete(false);
@@ -92,8 +97,8 @@ void ScriptedThreadPlan::DidPush() {
 
 bool ScriptedThreadPlan::ShouldStop(Event *event_ptr) {
   Log *log = GetLog(LLDBLog::Thread);
-  LLDB_LOGF(log, "%s called on Scripted Thread Plan: %s )",
-            LLVM_PRETTY_FUNCTION, m_class_name.c_str());
+  LLDB_LOG(log, "{0} called on Scripted Thread Plan: {1} )",
+            LLVM_PRETTY_FUNCTION, GetScriptClassName());
 
   bool should_stop = true;
   if (m_implementation_sp) {
@@ -110,8 +115,8 @@ bool ScriptedThreadPlan::ShouldStop(Event *event_ptr) {
 
 bool ScriptedThreadPlan::IsPlanStale() {
   Log *log = GetLog(LLDBLog::Thread);
-  LLDB_LOGF(log, "%s called on Scripted Thread Plan: %s )",
-            LLVM_PRETTY_FUNCTION, m_class_name.c_str());
+  LLDB_LOG(log, "{0} called on Scripted Thread Plan: {1} )",
+            LLVM_PRETTY_FUNCTION, GetScriptClassName());
 
   bool is_stale = true;
   if (m_implementation_sp) {
@@ -128,8 +133,8 @@ bool ScriptedThreadPlan::IsPlanStale() {
 
 bool ScriptedThreadPlan::DoPlanExplainsStop(Event *event_ptr) {
   Log *log = GetLog(LLDBLog::Thread);
-  LLDB_LOGF(log, "%s called on Scripted Thread Plan: %s )",
-            LLVM_PRETTY_FUNCTION, m_class_name.c_str());
+  LLDB_LOG(log, "{0} called on Scripted Thread Plan: {1} )",
+            LLVM_PRETTY_FUNCTION, GetScriptClassName());
 
   bool explains_stop = true;
   if (m_implementation_sp) {
@@ -147,8 +152,8 @@ bool ScriptedThreadPlan::DoPlanExplainsStop(Event *event_ptr) {
 
 bool ScriptedThreadPlan::MischiefManaged() {
   Log *log = GetLog(LLDBLog::Thread);
-  LLDB_LOGF(log, "%s called on Scripted Thread Plan: %s )",
-            LLVM_PRETTY_FUNCTION, m_class_name.c_str());
+  LLDB_LOG(log, "{0} called on Scripted Thread Plan: {1} )",
+            LLVM_PRETTY_FUNCTION, GetScriptClassName());
   bool mischief_managed = true;
   if (m_implementation_sp) {
     // I don't really need mischief_managed, since it's simpler to just call
@@ -165,8 +170,8 @@ bool ScriptedThreadPlan::MischiefManaged() {
 
 lldb::StateType ScriptedThreadPlan::GetPlanRunState() {
   Log *log = GetLog(LLDBLog::Thread);
-  LLDB_LOGF(log, "%s called on Scripted Thread Plan: %s )",
-            LLVM_PRETTY_FUNCTION, m_class_name.c_str());
+  LLDB_LOG(log, "{0} called on Scripted Thread Plan: {1} )",
+            LLVM_PRETTY_FUNCTION, GetScriptClassName());
   lldb::StateType run_state = eStateRunning;
   if (m_implementation_sp)
     run_state = m_interface->GetRunState();
@@ -176,8 +181,8 @@ lldb::StateType ScriptedThreadPlan::GetPlanRunState() {
 void ScriptedThreadPlan::GetDescription(Stream *s,
                                         lldb::DescriptionLevel level) {
   Log *log = GetLog(LLDBLog::Thread);
-  LLDB_LOGF(log, "%s called on Scripted Thread Plan: %s )",
-            LLVM_PRETTY_FUNCTION, m_class_name.c_str());
+  LLDB_LOG(log, "{0} called on Scripted Thread Plan: {1} )",
+            LLVM_PRETTY_FUNCTION, GetScriptClassName());
   if (m_implementation_sp) {
     ScriptInterpreter *script_interp = GetScriptInterpreter();
     if (script_interp) {
@@ -188,7 +193,7 @@ void ScriptedThreadPlan::GetDescription(Stream *s,
             GetLog(LLDBLog::Thread), std::move(err),
             "Can't call ScriptedThreadPlan::GetStopDescription: {0}");
         s->Printf("Scripted thread plan implemented by class %s.",
-                  m_class_name.c_str());
+                  GetScriptClassName().data());
       } else
         s->PutCString(
             reinterpret_cast<StreamString *>(stream.get())->GetData());
@@ -199,15 +204,15 @@ void ScriptedThreadPlan::GetDescription(Stream *s,
   // add something.
   if (m_stop_description.Empty())
     s->Printf("Scripted thread plan implemented by class %s.",
-              m_class_name.c_str());
+              GetScriptClassName().data());
   s->PutCString(m_stop_description.GetData());
 }
 
 // The ones below are not currently exported to Python.
 bool ScriptedThreadPlan::WillStop() {
   Log *log = GetLog(LLDBLog::Thread);
-  LLDB_LOGF(log, "%s called on Scripted Thread Plan: %s )",
-            LLVM_PRETTY_FUNCTION, m_class_name.c_str());
+  LLDB_LOG(log, "{0} called on Scripted Thread Plan: {1} )",
+            LLVM_PRETTY_FUNCTION, GetScriptClassName());
   return true;
 }
 
diff --git a/lldb/source/Target/Thread.cpp b/lldb/source/Target/Thread.cpp
index 9199721be9627..feaa5ba387324 100644
--- a/lldb/source/Target/Thread.cpp
+++ b/lldb/source/Target/Thread.cpp
@@ -1435,12 +1435,11 @@ ThreadPlanSP Thread::QueueThreadPlanForStepUntil(
 }
 
 lldb::ThreadPlanSP Thread::QueueThreadPlanForStepScripted(
-    bool abort_other_plans, const char *class_name,
-    StructuredData::ObjectSP extra_args_sp, bool stop_other_threads,
-    Status &status) {
+    bool abort_other_plans, const ScriptedMetadata &scripted_metadata,
+    bool stop_other_threads, Status &status) {
 
-  ThreadPlanSP thread_plan_sp(new ScriptedThreadPlan(
-      *this, class_name, StructuredDataImpl(extra_args_sp)));
+  ThreadPlanSP thread_plan_sp(
+      new ScriptedThreadPlan(*this, scripted_metadata));
   thread_plan_sp->SetStopOthers(stop_other_threads);
   status = QueueThreadPlan(thread_plan_sp, abort_other_plans);
   return thread_plan_sp;



More information about the lldb-commits mailing list