diff options
author | RĂ©mi Verschelde <rverschelde@gmail.com> | 2019-07-01 16:35:26 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-07-01 16:35:26 +0200 |
commit | 4d99408d123e4eea5773c8d1e35b59385b0aefa1 (patch) | |
tree | 6a3725357efcc0c2c2a841cf49f10612ad48e435 /modules | |
parent | f5d9454a4b88cff363513fb4b34ab74f29eba1c7 (diff) | |
parent | 9df1a2442b480f9ed8a8d4ec8992ea5046b98719 (diff) |
Merge pull request #28884 from vnen/yield-resume-stack
Keep GDScript functions in stack while yielding
Diffstat (limited to 'modules')
-rw-r--r-- | modules/gdscript/gdscript_function.cpp | 49 |
1 files changed, 41 insertions, 8 deletions
diff --git a/modules/gdscript/gdscript_function.cpp b/modules/gdscript/gdscript_function.cpp index ad48aa1d28..d5e74c07c9 100644 --- a/modules/gdscript/gdscript_function.cpp +++ b/modules/gdscript/gdscript_function.cpp @@ -1591,15 +1591,26 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a GDScriptLanguage::get_singleton()->script_frame_time += time_taken - function_call_time; } - if (ScriptDebugger::get_singleton()) - GDScriptLanguage::get_singleton()->exit_function(); + bool yielded = retvalue.is_ref() && Object::cast_to<GDScriptFunctionState>(retvalue); + + // Check if this is the last time the function is resuming from yield + // Will be true if never yielded as well + // When it's the last resume it will postpone the exit from stack, + // so the debugger knows which function triggered the resume of the next function (if any) + if (!p_state || yielded) { + if (ScriptDebugger::get_singleton()) + GDScriptLanguage::get_singleton()->exit_function(); #endif - if (_stack_size) { - //free stack - for (int i = 0; i < _stack_size; i++) - stack[i].~Variant(); + if (_stack_size) { + //free stack + for (int i = 0; i < _stack_size; i++) + stack[i].~Variant(); + } + +#ifdef DEBUG_ENABLED } +#endif return retvalue; } @@ -1775,7 +1786,7 @@ Variant GDScriptFunctionState::_signal_callback(const Variant **p_args, int p_ar if (state.instance_id && !ObjectDB::get_instance(state.instance_id)) { #ifdef DEBUG_ENABLED - ERR_EXPLAIN("Resumed after yield, but class instance is gone"); + ERR_EXPLAIN("Resumed function '" + String(function->get_name()) + "()' after yield, but class instance is gone. At script: " + state.script->get_path() + ":" + itos(state.line)); ERR_FAIL_V(Variant()); #else return Variant(); @@ -1838,6 +1849,17 @@ Variant GDScriptFunctionState::_signal_callback(const Variant **p_args, int p_ar } } +#ifdef DEBUG_ENABLED + if (ScriptDebugger::get_singleton()) + GDScriptLanguage::get_singleton()->exit_function(); + if (state.stack_size) { + //free stack + Variant *stack = (Variant *)state.stack.ptr(); + for (int i = 0; i < state.stack_size; i++) + stack[i].~Variant(); + } +#endif + return ret; } @@ -1860,7 +1882,7 @@ Variant GDScriptFunctionState::resume(const Variant &p_arg) { ERR_FAIL_COND_V(!function, Variant()); if (state.instance_id && !ObjectDB::get_instance(state.instance_id)) { #ifdef DEBUG_ENABLED - ERR_EXPLAIN("Resumed after yield, but class instance is gone"); + ERR_EXPLAIN("Resumed function '" + String(function->get_name()) + "()' after yield, but class instance is gone. At script: " + state.script->get_path() + ":" + itos(state.line)); ERR_FAIL_V(Variant()); #else return Variant(); @@ -1892,6 +1914,17 @@ Variant GDScriptFunctionState::resume(const Variant &p_arg) { } else { emit_signal("completed", ret); } + +#ifdef DEBUG_ENABLED + if (ScriptDebugger::get_singleton()) + GDScriptLanguage::get_singleton()->exit_function(); + if (state.stack_size) { + //free stack + Variant *stack = (Variant *)state.stack.ptr(); + for (int i = 0; i < state.stack_size; i++) + stack[i].~Variant(); + } +#endif } return ret; |