forked from OSchip/llvm-project
Performance optimizations to ClangUserExpression,
mostly related to management of the stack frame for the interpreter. - First, if the expression can be interpreted, allocate the stack frame in the target process (to make sure pointers are valid) but only read/write to the copy in the host's memory. - Second, keep the memory allocations for the stack frame and the materialized struct as member variables of ClangUserExpression. This avoids memory allocations and deallocations each time the expression runs. <rdar://problem/13043685> llvm-svn: 180664
This commit is contained in:
parent
956dca9288
commit
df56540a58
|
@ -200,7 +200,8 @@ public:
|
|||
FinalizeJITExecution (Stream &error_stream,
|
||||
ExecutionContext &exe_ctx,
|
||||
lldb::ClangExpressionVariableSP &result,
|
||||
lldb::addr_t function_stack_pointer = LLDB_INVALID_ADDRESS);
|
||||
lldb::addr_t function_stack_bottom = LLDB_INVALID_ADDRESS,
|
||||
lldb::addr_t function_stack_top = LLDB_INVALID_ADDRESS);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Return the string that the parser should parse. Must be a full
|
||||
|
@ -397,6 +398,8 @@ private:
|
|||
|
||||
lldb::ProcessWP m_process_wp; ///< The process used as the context for the expression.
|
||||
Address m_address; ///< The address the process is stopped in.
|
||||
lldb::addr_t m_stack_frame_bottom; ///< The bottom of the allocated stack frame.
|
||||
lldb::addr_t m_stack_frame_top; ///< The top of the allocated stack frame.
|
||||
|
||||
std::string m_expr_text; ///< The text of the expression, as typed by the user
|
||||
std::string m_expr_prefix; ///< The text of the translation-level definitions, as provided by the user
|
||||
|
|
|
@ -51,8 +51,10 @@ public:
|
|||
llvm::Function &function,
|
||||
llvm::ArrayRef<lldb::addr_t> args,
|
||||
lldb_private::IRMemoryMap &memory_map,
|
||||
lldb_private::Error &error);
|
||||
|
||||
lldb_private::Error &error,
|
||||
lldb::addr_t stack_frame_bottom,
|
||||
lldb::addr_t stack_frame_top);
|
||||
|
||||
private:
|
||||
static bool
|
||||
supportsFunction (llvm::Function &llvm_function,
|
||||
|
|
|
@ -56,6 +56,8 @@ ClangUserExpression::ClangUserExpression (const char *expr,
|
|||
lldb::LanguageType language,
|
||||
ResultType desired_type) :
|
||||
ClangExpression (),
|
||||
m_stack_frame_bottom (LLDB_INVALID_ADDRESS),
|
||||
m_stack_frame_top (LLDB_INVALID_ADDRESS),
|
||||
m_expr_text (expr),
|
||||
m_expr_prefix (expr_prefix ? expr_prefix : ""),
|
||||
m_language (language),
|
||||
|
@ -68,7 +70,8 @@ ClangUserExpression::ClangUserExpression (const char *expr,
|
|||
m_needs_object_ptr (false),
|
||||
m_const_object (false),
|
||||
m_target (NULL),
|
||||
m_can_interpret (false)
|
||||
m_can_interpret (false),
|
||||
m_materialized_address (LLDB_INVALID_ADDRESS)
|
||||
{
|
||||
switch (m_language)
|
||||
{
|
||||
|
@ -641,22 +644,48 @@ ClangUserExpression::PrepareToExecuteJITExpression (Stream &error_stream,
|
|||
}
|
||||
}
|
||||
|
||||
Error alloc_error;
|
||||
|
||||
struct_address = m_execution_unit_ap->Malloc(m_materializer_ap->GetStructByteSize(),
|
||||
m_materializer_ap->GetStructAlignment(),
|
||||
lldb::ePermissionsReadable | lldb::ePermissionsWritable,
|
||||
IRMemoryMap::eAllocationPolicyMirror,
|
||||
alloc_error);
|
||||
|
||||
if (!alloc_error.Success())
|
||||
if (m_materialized_address == LLDB_INVALID_ADDRESS)
|
||||
{
|
||||
error_stream.Printf("Couldn't allocate space for materialized struct: %s\n", alloc_error.AsCString());
|
||||
return false;
|
||||
Error alloc_error;
|
||||
|
||||
IRMemoryMap::AllocationPolicy policy = m_can_interpret ? IRMemoryMap::eAllocationPolicyHostOnly : IRMemoryMap::eAllocationPolicyMirror;
|
||||
|
||||
m_materialized_address = m_execution_unit_ap->Malloc(m_materializer_ap->GetStructByteSize(),
|
||||
m_materializer_ap->GetStructAlignment(),
|
||||
lldb::ePermissionsReadable | lldb::ePermissionsWritable,
|
||||
policy,
|
||||
alloc_error);
|
||||
|
||||
if (!alloc_error.Success())
|
||||
{
|
||||
error_stream.Printf("Couldn't allocate space for materialized struct: %s\n", alloc_error.AsCString());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
m_materialized_address = struct_address;
|
||||
struct_address = m_materialized_address;
|
||||
|
||||
if (m_can_interpret && m_stack_frame_bottom == LLDB_INVALID_ADDRESS)
|
||||
{
|
||||
Error alloc_error;
|
||||
|
||||
const size_t stack_frame_size = 512 * 1024;
|
||||
|
||||
m_stack_frame_bottom = m_execution_unit_ap->Malloc(stack_frame_size,
|
||||
8,
|
||||
lldb::ePermissionsReadable | lldb::ePermissionsWritable,
|
||||
IRMemoryMap::eAllocationPolicyHostOnly,
|
||||
alloc_error);
|
||||
|
||||
m_stack_frame_top = m_stack_frame_bottom + stack_frame_size;
|
||||
|
||||
if (!alloc_error.Success())
|
||||
{
|
||||
error_stream.Printf("Couldn't allocate space for the stack frame: %s\n", alloc_error.AsCString());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Error materialize_error;
|
||||
|
||||
m_dematerializer_sp = m_materializer_ap->Materialize(frame, *m_execution_unit_ap, struct_address, materialize_error);
|
||||
|
@ -703,7 +732,8 @@ bool
|
|||
ClangUserExpression::FinalizeJITExecution (Stream &error_stream,
|
||||
ExecutionContext &exe_ctx,
|
||||
lldb::ClangExpressionVariableSP &result,
|
||||
lldb::addr_t function_stack_pointer)
|
||||
lldb::addr_t function_stack_bottom,
|
||||
lldb::addr_t function_stack_top)
|
||||
{
|
||||
Error expr_error;
|
||||
|
||||
|
@ -711,9 +741,7 @@ ClangUserExpression::FinalizeJITExecution (Stream &error_stream,
|
|||
|
||||
if (log)
|
||||
log->Printf("-- [ClangUserExpression::FinalizeJITExecution] Dematerializing after execution --");
|
||||
|
||||
lldb::addr_t function_stack_bottom = function_stack_pointer - Host::GetPageSize();
|
||||
|
||||
|
||||
if (!m_dematerializer_sp)
|
||||
{
|
||||
error_stream.Printf ("Couldn't dematerialize struct : no dematerializer is present");
|
||||
|
@ -722,7 +750,7 @@ ClangUserExpression::FinalizeJITExecution (Stream &error_stream,
|
|||
|
||||
Error dematerialize_error;
|
||||
|
||||
m_dematerializer_sp->Dematerialize(dematerialize_error, result, function_stack_pointer, function_stack_bottom);
|
||||
m_dematerializer_sp->Dematerialize(dematerialize_error, result, function_stack_bottom, function_stack_top);
|
||||
|
||||
if (!dematerialize_error.Success())
|
||||
{
|
||||
|
@ -765,7 +793,8 @@ ClangUserExpression::Execute (Stream &error_stream,
|
|||
return eExecutionSetupError;
|
||||
}
|
||||
|
||||
lldb::addr_t function_stack_pointer = 0;
|
||||
lldb::addr_t function_stack_bottom = LLDB_INVALID_ADDRESS;
|
||||
lldb::addr_t function_stack_top = LLDB_INVALID_ADDRESS;
|
||||
|
||||
if (m_can_interpret)
|
||||
{
|
||||
|
@ -792,11 +821,16 @@ ClangUserExpression::Execute (Stream &error_stream,
|
|||
|
||||
args.push_back(struct_address);
|
||||
|
||||
function_stack_bottom = m_stack_frame_bottom;
|
||||
function_stack_top = m_stack_frame_top;
|
||||
|
||||
IRInterpreter::Interpret (*module,
|
||||
*function,
|
||||
args,
|
||||
*m_execution_unit_ap.get(),
|
||||
interpreter_error);
|
||||
interpreter_error,
|
||||
function_stack_bottom,
|
||||
function_stack_top);
|
||||
|
||||
if (!interpreter_error.Success())
|
||||
{
|
||||
|
@ -823,8 +857,11 @@ ClangUserExpression::Execute (Stream &error_stream,
|
|||
if (!call_plan_sp || !call_plan_sp->ValidatePlan (&error_stream))
|
||||
return eExecutionSetupError;
|
||||
|
||||
function_stack_pointer = static_cast<ThreadPlanCallFunction *>(call_plan_sp.get())->GetFunctionStackPointer();
|
||||
lldb::addr_t function_stack_pointer = static_cast<ThreadPlanCallFunction *>(call_plan_sp.get())->GetFunctionStackPointer();
|
||||
|
||||
function_stack_bottom = function_stack_pointer - Host::GetPageSize();
|
||||
function_stack_top = function_stack_pointer;
|
||||
|
||||
if (log)
|
||||
log->Printf("-- [ClangUserExpression::Execute] Execution of expression begins --");
|
||||
|
||||
|
@ -876,8 +913,10 @@ ClangUserExpression::Execute (Stream &error_stream,
|
|||
}
|
||||
}
|
||||
|
||||
if (FinalizeJITExecution (error_stream, exe_ctx, result, function_stack_pointer))
|
||||
if (FinalizeJITExecution (error_stream, exe_ctx, result, function_stack_bottom, function_stack_top))
|
||||
{
|
||||
return eExecutionCompleted;
|
||||
}
|
||||
else
|
||||
{
|
||||
error_stream.Printf("Errored out in %s: Couldn't FinalizeJITExpression", __FUNCTION__);
|
||||
|
|
|
@ -77,42 +77,22 @@ public:
|
|||
size_t m_addr_byte_size;
|
||||
|
||||
InterpreterStackFrame (DataLayout &target_data,
|
||||
lldb_private::IRMemoryMap &memory_map) :
|
||||
lldb_private::IRMemoryMap &memory_map,
|
||||
lldb::addr_t stack_frame_bottom,
|
||||
lldb::addr_t stack_frame_top) :
|
||||
m_target_data (target_data),
|
||||
m_memory_map (memory_map)
|
||||
{
|
||||
m_byte_order = (target_data.isLittleEndian() ? lldb::eByteOrderLittle : lldb::eByteOrderBig);
|
||||
m_addr_byte_size = (target_data.getPointerSize(0));
|
||||
|
||||
m_frame_size = 512 * 1024;
|
||||
|
||||
lldb_private::Error alloc_error;
|
||||
|
||||
m_frame_process_address = memory_map.Malloc(m_frame_size,
|
||||
m_addr_byte_size,
|
||||
lldb::ePermissionsReadable | lldb::ePermissionsWritable,
|
||||
lldb_private::IRMemoryMap::eAllocationPolicyMirror,
|
||||
alloc_error);
|
||||
|
||||
if (alloc_error.Success())
|
||||
{
|
||||
m_stack_pointer = m_frame_process_address + m_frame_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_frame_process_address = LLDB_INVALID_ADDRESS;
|
||||
m_stack_pointer = LLDB_INVALID_ADDRESS;
|
||||
}
|
||||
|
||||
m_frame_process_address = stack_frame_bottom;
|
||||
m_frame_size = stack_frame_top - stack_frame_bottom;
|
||||
m_stack_pointer = stack_frame_top;
|
||||
}
|
||||
|
||||
~InterpreterStackFrame ()
|
||||
{
|
||||
if (m_frame_process_address != LLDB_INVALID_ADDRESS)
|
||||
{
|
||||
lldb_private::Error free_error;
|
||||
m_memory_map.Free(m_frame_process_address, free_error);
|
||||
m_frame_process_address = LLDB_INVALID_ADDRESS;
|
||||
}
|
||||
}
|
||||
|
||||
void Jump (const BasicBlock *bb)
|
||||
|
@ -535,7 +515,9 @@ IRInterpreter::Interpret (llvm::Module &module,
|
|||
llvm::Function &function,
|
||||
llvm::ArrayRef<lldb::addr_t> args,
|
||||
lldb_private::IRMemoryMap &memory_map,
|
||||
lldb_private::Error &error)
|
||||
lldb_private::Error &error,
|
||||
lldb::addr_t stack_frame_bottom,
|
||||
lldb::addr_t stack_frame_top)
|
||||
{
|
||||
lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
|
||||
|
||||
|
@ -553,7 +535,7 @@ IRInterpreter::Interpret (llvm::Module &module,
|
|||
|
||||
DataLayout data_layout(&module);
|
||||
|
||||
InterpreterStackFrame frame(data_layout, memory_map);
|
||||
InterpreterStackFrame frame(data_layout, memory_map, stack_frame_bottom, stack_frame_top);
|
||||
|
||||
if (frame.m_frame_process_address == LLDB_INVALID_ADDRESS)
|
||||
{
|
||||
|
|
|
@ -34,7 +34,8 @@ IRMemoryMap::~IRMemoryMap ()
|
|||
for (AllocationMap::value_type &allocation : m_allocations)
|
||||
{
|
||||
if (allocation.second.m_policy == eAllocationPolicyMirror ||
|
||||
allocation.second.m_policy == eAllocationPolicyHostOnly)
|
||||
allocation.second.m_policy == eAllocationPolicyProcessOnly ||
|
||||
(allocation.second.m_policy == eAllocationPolicyHostOnly && process_sp->CanJIT()))
|
||||
process_sp->DeallocateMemory(allocation.second.m_process_alloc);
|
||||
|
||||
if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
|
||||
|
@ -55,6 +56,18 @@ IRMemoryMap::FindSpace (size_t size)
|
|||
|
||||
lldb::addr_t ret = LLDB_INVALID_ADDRESS;
|
||||
|
||||
if (process_sp && process_sp->CanJIT())
|
||||
{
|
||||
Error alloc_error;
|
||||
|
||||
ret = process_sp->AllocateMemory(size, lldb::ePermissionsReadable | lldb::ePermissionsWritable, alloc_error);
|
||||
|
||||
if (!alloc_error.Success())
|
||||
return LLDB_INVALID_ADDRESS;
|
||||
else
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (int iterations = 0; iterations < 16; ++iterations)
|
||||
{
|
||||
lldb::addr_t candidate;
|
||||
|
@ -367,12 +380,20 @@ IRMemoryMap::Free (lldb::addr_t process_address, Error &error)
|
|||
{
|
||||
default:
|
||||
case eAllocationPolicyHostOnly:
|
||||
break;
|
||||
{
|
||||
lldb::ProcessSP process_sp = m_process_wp.lock();
|
||||
if (process_sp && process_sp->CanJIT())
|
||||
process_sp->DeallocateMemory(allocation.m_process_alloc); // FindSpace allocated this for real
|
||||
|
||||
break;
|
||||
}
|
||||
case eAllocationPolicyMirror:
|
||||
case eAllocationPolicyProcessOnly:
|
||||
lldb::ProcessSP process_sp = m_process_wp.lock();
|
||||
if (process_sp)
|
||||
process_sp->DeallocateMemory(allocation.m_process_alloc);
|
||||
{
|
||||
lldb::ProcessSP process_sp = m_process_wp.lock();
|
||||
if (process_sp)
|
||||
process_sp->DeallocateMemory(allocation.m_process_alloc);
|
||||
}
|
||||
}
|
||||
|
||||
if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
|
||||
|
|
|
@ -822,7 +822,7 @@ public:
|
|||
|
||||
lldb::ProcessSP process_sp = map.GetBestExecutionContextScope()->CalculateProcess();
|
||||
|
||||
bool can_persist = (process_sp && process_sp->CanJIT());
|
||||
bool can_persist = (m_is_program_reference && process_sp && process_sp->CanJIT() && !(address >= frame_bottom && address < frame_top));
|
||||
|
||||
if (can_persist && m_keep_in_memory)
|
||||
{
|
||||
|
@ -1316,7 +1316,7 @@ Materializer::Materialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb:
|
|||
}
|
||||
|
||||
void
|
||||
Materializer::Dematerializer::Dematerialize (Error &error, lldb::ClangExpressionVariableSP &result_sp, lldb::addr_t frame_top, lldb::addr_t frame_bottom)
|
||||
Materializer::Dematerializer::Dematerialize (Error &error, lldb::ClangExpressionVariableSP &result_sp, lldb::addr_t frame_bottom, lldb::addr_t frame_top)
|
||||
{
|
||||
lldb::StackFrameSP frame_sp = m_frame_wp.lock();
|
||||
|
||||
|
|
Loading…
Reference in New Issue