Support threads in the script debugger

* This implementation adds threads on the side of the client (script debugger).
* Some functions of the debugger are optimized.
* The profile is also now thread safe using atomics.
* The editor can switch between multiple threads when debugging.

This PR adds threaded support for the script language debugger. Every thread has its own thread local data and it will connect to the debugger using multiple thread IDs.
This means that, now, the editor can receive multiple threads entering debug mode at the same time.
This commit is contained in:
Juan Linietsky 2023-04-29 17:20:38 +02:00
parent 202e4b2c1e
commit 5e512b705e
17 changed files with 409 additions and 223 deletions

View file

@ -663,8 +663,8 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
if (GDScriptLanguage::get_singleton()->profiling) {
function_start_time = OS::get_singleton()->get_ticks_usec();
function_call_time = 0;
profile.call_count++;
profile.frame_call_count++;
profile.call_count.increment();
profile.frame_call_count.increment();
}
bool exit_ok = false;
bool awaited = false;
@ -3550,7 +3550,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
// line
bool do_break = false;
if (EngineDebugger::get_script_debugger()->get_lines_left() > 0) {
if (unlikely(EngineDebugger::get_script_debugger()->get_lines_left() > 0)) {
if (EngineDebugger::get_script_debugger()->get_depth() <= 0) {
EngineDebugger::get_script_debugger()->set_lines_left(EngineDebugger::get_script_debugger()->get_lines_left() - 1);
}
@ -3563,7 +3563,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
do_break = true;
}
if (do_break) {
if (unlikely(do_break)) {
GDScriptLanguage::get_singleton()->debug_break("Breakpoint", true);
}
@ -3630,11 +3630,13 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
#ifdef DEBUG_ENABLED
if (GDScriptLanguage::get_singleton()->profiling) {
uint64_t time_taken = OS::get_singleton()->get_ticks_usec() - function_start_time;
profile.total_time += time_taken;
profile.self_time += time_taken - function_call_time;
profile.frame_total_time += time_taken;
profile.frame_self_time += time_taken - function_call_time;
GDScriptLanguage::get_singleton()->script_frame_time += time_taken - function_call_time;
profile.total_time.add(time_taken);
profile.self_time.add(time_taken - function_call_time);
profile.frame_total_time.add(time_taken);
profile.frame_self_time.add(time_taken - function_call_time);
if (Thread::get_caller_id() == Thread::get_main_id()) {
GDScriptLanguage::get_singleton()->script_frame_time += time_taken - function_call_time;
}
}
// Check if this is not the last time it was interrupted by `await` or if it's the first time executing.