summaryrefslogtreecommitdiffstats
path: root/lldb/source/Breakpoint/BreakpointLocation.cpp
diff options
context:
space:
mode:
authorSean Callanan <scallanan@apple.com>2013-04-19 07:09:15 +0000
committerSean Callanan <scallanan@apple.com>2013-04-19 07:09:15 +0000
commit3dbf346ef358004c213774c7bb83e47687ced102 (patch)
treed9054f8c56042c3c843cd3d8557154b167e166d2 /lldb/source/Breakpoint/BreakpointLocation.cpp
parentcf5e5bade1638d5f2e2f8c1f808a5150f4208ba2 (diff)
downloadbcm5719-llvm-3dbf346ef358004c213774c7bb83e47687ced102.tar.gz
bcm5719-llvm-3dbf346ef358004c213774c7bb83e47687ced102.zip
Optimized the way breakpoint conditions are evaluated.
Previously, the options for a breakopint or its locations stored only the text of the breakpoint condition (ironically, they used ClangUserExpression as a glorified std::string) and, each time the condition had to be evaluated in the StopInfo code, the expression parser would be invoked via a static method to parse and then execute the expression. I made several changes here: - Each breakpoint location now has its own ClangUserExpressionSP containing a version of the breakpoint expression compiled for that exact location. - Whenever the breakpoint is hit, the breakpoint condition expression is simply re-run to determine whether to stop. - If the process changes (e.g., it's re-run) or the source code of the expression changes (we use a hash so as to avoid doing string comparisons) the ClangUserExpressionSP is re-generated. This should improve performance of breakpoint conditions significantly, and takes advantage of the recent expression re-use work. llvm-svn: 179838
Diffstat (limited to 'lldb/source/Breakpoint/BreakpointLocation.cpp')
-rw-r--r--lldb/source/Breakpoint/BreakpointLocation.cpp104
1 files changed, 102 insertions, 2 deletions
diff --git a/lldb/source/Breakpoint/BreakpointLocation.cpp b/lldb/source/Breakpoint/BreakpointLocation.cpp
index 71e8eb7c868..04142b268e4 100644
--- a/lldb/source/Breakpoint/BreakpointLocation.cpp
+++ b/lldb/source/Breakpoint/BreakpointLocation.cpp
@@ -240,9 +240,109 @@ BreakpointLocation::SetCondition (const char *condition)
}
const char *
-BreakpointLocation::GetConditionText () const
+BreakpointLocation::GetConditionText (size_t *hash) const
{
- return GetOptionsNoCreate()->GetConditionText();
+ return GetOptionsNoCreate()->GetConditionText(hash);
+}
+
+bool
+BreakpointLocation::ConditionSaysStop (ExecutionContext &exe_ctx, Error &error)
+{
+ Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
+
+ size_t condition_hash;
+ const char *condition_text = GetConditionText(&condition_hash);
+
+ if (!condition_text)
+ return false;
+
+ if (condition_hash != m_condition_hash ||
+ !m_user_expression_sp ||
+ !m_user_expression_sp->MatchesContext(exe_ctx))
+ {
+ m_user_expression_sp.reset(new ClangUserExpression(condition_text,
+ NULL,
+ lldb::eLanguageTypeUnknown,
+ ClangUserExpression::eResultTypeAny));
+
+ StreamString errors;
+
+ if (!m_user_expression_sp->Parse(errors,
+ exe_ctx,
+ eExecutionPolicyOnlyWhenNeeded,
+ true))
+ {
+ error.SetErrorStringWithFormat("Couldn't parse conditional expression:\n%s",
+ errors.GetData());
+ m_user_expression_sp.reset();
+ return false;
+ }
+
+ m_condition_hash = condition_hash;
+ }
+
+ // We need to make sure the user sees any parse errors in their condition, so we'll hook the
+ // constructor errors up to the debugger's Async I/O.
+
+ ValueObjectSP result_value_sp;
+ const bool unwind_on_error = true;
+ const bool ignore_breakpoints = true;
+ const bool try_all_threads = true;
+
+ Error expr_error;
+
+ StreamString execution_errors;
+
+ ClangExpressionVariableSP result_variable_sp;
+
+ ExecutionResults result_code =
+ m_user_expression_sp->Execute(execution_errors,
+ exe_ctx,
+ unwind_on_error,
+ ignore_breakpoints,
+ m_user_expression_sp,
+ result_variable_sp,
+ try_all_threads,
+ ClangUserExpression::kDefaultTimeout);
+
+ bool ret;
+
+ if (result_code == eExecutionCompleted)
+ {
+ result_value_sp = result_variable_sp->GetValueObject();
+
+ if (result_value_sp)
+ {
+ Scalar scalar_value;
+ if (result_value_sp->ResolveValue (scalar_value))
+ {
+ if (scalar_value.ULongLong(1) == 0)
+ ret = false;
+ else
+ ret = true;
+ if (log)
+ log->Printf("Condition successfully evaluated, result is %s.\n",
+ ret ? "true" : "false");
+ }
+ else
+ {
+ ret = false;
+ error.SetErrorString("Failed to get an integer result from the expression");
+ }
+ }
+ else
+ {
+ ret = false;
+ error.SetErrorString("Failed to get any result from the expression");
+ }
+ }
+ else
+ {
+ ret = false;
+ error.SetErrorStringWithFormat("Couldn't execute expression:\n%s", execution_errors.GetData());
+ }
+
+ return ret;
}
uint32_t
OpenPOWER on IntegriCloud