diff options
Diffstat (limited to 'modules/gdscript/gdscript_vm.cpp')
-rw-r--r-- | modules/gdscript/gdscript_vm.cpp | 49 |
1 files changed, 33 insertions, 16 deletions
diff --git a/modules/gdscript/gdscript_vm.cpp b/modules/gdscript/gdscript_vm.cpp index 8f85d8159b..e0beed367a 100644 --- a/modules/gdscript/gdscript_vm.cpp +++ b/modules/gdscript/gdscript_vm.cpp @@ -177,6 +177,8 @@ String GDScriptFunction::_get_call_error(const Callable::CallError &p_err, const err_text = "Invalid call. Nonexistent " + p_where + "."; } else if (p_err.error == Callable::CallError::CALL_ERROR_INSTANCE_IS_NULL) { err_text = "Attempt to call " + p_where + " on a null instance."; + } else if (p_err.error == Callable::CallError::CALL_ERROR_METHOD_NOT_CONST) { + err_text = "Attempt to call " + p_where + " on a const instance."; } else { err_text = "Bug, call error: #" + itos(p_err.error); } @@ -311,6 +313,7 @@ void (*type_init_function_table[])(Variant *) = { &&OPCODE_JUMP_IF, \ &&OPCODE_JUMP_IF_NOT, \ &&OPCODE_JUMP_TO_DEF_ARGUMENT, \ + &&OPCODE_JUMP_IF_SHARED, \ &&OPCODE_RETURN, \ &&OPCODE_RETURN_TYPED_BUILTIN, \ &&OPCODE_RETURN_TYPED_ARRAY, \ @@ -1029,11 +1032,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a #endif #ifdef DEBUG_ENABLED if (!valid) { - if (src->has_method(*index)) { - err_text = "Invalid get index '" + index->operator String() + "' (on base: '" + _get_var_type(src) + "'). Did you mean '." + index->operator String() + "()' or funcref(obj, \"" + index->operator String() + "\") ?"; - } else { - err_text = "Invalid get index '" + index->operator String() + "' (on base: '" + _get_var_type(src) + "')."; - } + err_text = "Invalid get index '" + index->operator String() + "' (on base: '" + _get_var_type(src) + "')."; OPCODE_BREAK; } *dst = ret; @@ -1894,7 +1893,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a VariantInternal::initialize(ret, Variant::OBJECT); Object **ret_opaque = VariantInternal::get_object(ret); method->ptrcall(base_obj, argptrs, ret_opaque); - VariantInternal::object_assign(ret, *ret_opaque); // Set so ID is correct too. + VariantInternal::update_object_id(ret); #ifdef DEBUG_ENABLED if (GDScriptLanguage::get_singleton()->profiling) { @@ -2361,6 +2360,21 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a } DISPATCH_OPCODE; + OPCODE(OPCODE_JUMP_IF_SHARED) { + CHECK_SPACE(3); + + GET_INSTRUCTION_ARG(val, 0); + + if (val->is_shared()) { + int to = _code_ptr[ip + 2]; + GD_ERR_BREAK(to < 0 || to > _code_size); + ip = to; + } else { + ip += 3; + } + } + DISPATCH_OPCODE; + OPCODE(OPCODE_RETURN) { CHECK_SPACE(2); GET_INSTRUCTION_ARG(r, 0); @@ -3432,9 +3446,9 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a _err_print_error(err_func.utf8().get_data(), err_file.utf8().get_data(), err_line, err_text.utf8().get_data(), false, ERR_HANDLER_SCRIPT); } -#endif // Get a default return type in case of failure retvalue = _get_default_variant_for_data_type(return_type); +#endif OPCODE_OUT; } @@ -3450,23 +3464,26 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a GDScriptLanguage::get_singleton()->script_frame_time += time_taken - function_call_time; } - // Check if this function has been interrupted by `await`. - // If that is the case we want to keep it in the debugger until it actually exits. + // Check if this is not the last time it was interrupted by `await` or if it's the first time executing. + // If that is the case then we exit the function as normal. Otherwise we postpone it until the last `await` is completed. // This ensures the call stack can be properly shown when using `await`, showing what resumed the function. - if (!awaited) { + if (!p_state || awaited) { if (EngineDebugger::is_active()) { GDScriptLanguage::get_singleton()->exit_function(); } - } #endif - // Clear the stack even if there was an `await`. - // The stack saved in the state is a copy, so this needs to be destructed to avoid leaks. - if (_stack_size) { - // Free stack. - for (int i = 0; i < _stack_size; i++) { + // Free stack, except reserved addresses. + for (int i = 3; i < _stack_size; i++) { stack[i].~Variant(); } +#ifdef DEBUG_ENABLED + } +#endif + + // Always free reserved addresses, since they are never copied. + for (int i = 0; i < 3; i++) { + stack[i].~Variant(); } return retvalue; |