Merge pull request #28884 from vnen/yield-resume-stack

Keep GDScript functions in stack while yielding
This commit is contained in:
Rémi Verschelde 2019-07-01 16:35:26 +02:00 committed by GitHub
commit 4d99408d12
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 42 additions and 10 deletions

View file

@ -626,8 +626,7 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da
d["frame"] = i;
s->set_metadata(0, d);
//String line = itos(i)+" - "+String(d["file"])+":"+itos(d["line"])+" - at func: "+d["function"];
String line = itos(i) + " - " + String(d["file"]) + ":" + itos(d["line"]);
String line = itos(i) + " - " + String(d["file"]) + ":" + itos(d["line"]) + " - at function: " + d["function"];
s->set_text(0, line);
if (i == 0)

View file

@ -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;