summaryrefslogtreecommitdiffstats
path: root/modules/gdscript/gdscript_vm.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'modules/gdscript/gdscript_vm.cpp')
-rw-r--r--modules/gdscript/gdscript_vm.cpp49
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;