summaryrefslogtreecommitdiff
path: root/modules/gdscript/gdscript_function.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'modules/gdscript/gdscript_function.cpp')
-rw-r--r--modules/gdscript/gdscript_function.cpp262
1 files changed, 106 insertions, 156 deletions
diff --git a/modules/gdscript/gdscript_function.cpp b/modules/gdscript/gdscript_function.cpp
index ca4d6f6de9..1aab71d161 100644
--- a/modules/gdscript/gdscript_function.cpp
+++ b/modules/gdscript/gdscript_function.cpp
@@ -35,12 +35,10 @@
#include "gdscript_functions.h"
Variant *GDScriptFunction::_get_variant(int p_address, GDScriptInstance *p_instance, GDScript *p_script, Variant &self, Variant &static_ref, Variant *p_stack, String &r_error) const {
-
int address = p_address & ADDR_MASK;
//sequential table (jump table generated by compiler)
switch ((p_address & ADDR_TYPE_MASK) >> ADDR_BITS) {
-
case ADDR_TYPE_SELF: {
#ifdef DEBUG_ENABLED
if (unlikely(!p_instance)) {
@@ -51,7 +49,6 @@ Variant *GDScriptFunction::_get_variant(int p_address, GDScriptInstance *p_insta
return &self;
} break;
case ADDR_TYPE_CLASS: {
-
return &static_ref;
} break;
case ADDR_TYPE_MEMBER: {
@@ -65,7 +62,6 @@ Variant *GDScriptFunction::_get_variant(int p_address, GDScriptInstance *p_insta
return &p_instance->members.write[address];
} break;
case ADDR_TYPE_CLASS_CONSTANT: {
-
//todo change to index!
GDScript *s = p_script;
#ifdef DEBUG_ENABLED
@@ -76,7 +72,6 @@ Variant *GDScriptFunction::_get_variant(int p_address, GDScriptInstance *p_insta
while (s) {
GDScript *o = s;
while (o) {
-
Map<StringName, Variant>::Element *E = o->constants.find(*sn);
if (E) {
return &E->get();
@@ -133,7 +128,6 @@ Variant *GDScriptFunction::_get_variant(int p_address, GDScriptInstance *p_insta
#ifdef DEBUG_ENABLED
static String _get_var_type(const Variant *p_var) {
-
String basestr;
if (p_var->get_type() == Variant::OBJECT) {
@@ -146,10 +140,11 @@ static String _get_var_type(const Variant *p_var) {
basestr = "previously freed";
}
} else {
- if (bobj->get_script_instance())
+ if (bobj->get_script_instance()) {
basestr = bobj->get_class() + " (" + bobj->get_script_instance()->get_script()->get_path().get_file() + ")";
- else
+ } else {
basestr = bobj->get_class();
+ }
}
} else {
@@ -161,7 +156,6 @@ static String _get_var_type(const Variant *p_var) {
#endif // DEBUG_ENABLED
String GDScriptFunction::_get_call_error(const Callable::CallError &p_err, const String &p_where, const Variant **argptrs) const {
-
String err_text;
if (p_err.error == Callable::CallError::CALL_ERROR_INVALID_ARGUMENT) {
@@ -259,11 +253,9 @@ String GDScriptFunction::_get_call_error(const Callable::CallError &p_err, const
#endif
Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_args, int p_argcount, Callable::CallError &r_err, CallState *p_state) {
-
OPCODES_TABLE;
if (!_code_ptr) {
-
return Variant();
}
@@ -294,29 +286,23 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
line = p_state->line;
ip = p_state->ip;
alloca_size = p_state->stack.size();
- script = p_state->script.ptr();
+ script = p_state->script;
p_instance = p_state->instance;
defarg = p_state->defarg;
self = p_state->self;
- //stack[p_state->result_pos]=p_state->result; //assign stack with result
} else {
-
if (p_argcount != _argument_count) {
-
if (p_argcount > _argument_count) {
-
r_err.error = Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS;
r_err.argument = _argument_count;
return Variant();
} else if (p_argcount < _argument_count - _default_arg_count) {
-
r_err.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
r_err.argument = _argument_count - _default_arg_count;
return Variant();
} else {
-
defarg = _argument_count - p_argcount;
}
}
@@ -324,11 +310,9 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
alloca_size = sizeof(Variant *) * _call_size + sizeof(Variant) * _stack_size;
if (alloca_size) {
-
uint8_t *aptr = (uint8_t *)alloca(alloca_size);
if (_stack_size) {
-
stack = (Variant *)aptr;
for (int i = 0; i < p_argcount; i++) {
if (!argument_types[i].has_type) {
@@ -337,15 +321,10 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
}
if (!argument_types[i].is_type(*p_args[i], true)) {
- if (argument_types[i].is_type(Variant(), true)) {
- memnew_placement(&stack[i], Variant);
- continue;
- } else {
- r_err.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
- r_err.argument = i;
- r_err.expected = argument_types[i].kind == GDScriptDataType::BUILTIN ? argument_types[i].builtin_type : Variant::OBJECT;
- return Variant();
- }
+ r_err.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_err.argument = i;
+ r_err.expected = argument_types[i].kind == GDScriptDataType::BUILTIN ? argument_types[i].builtin_type : Variant::OBJECT;
+ return Variant();
}
if (argument_types[i].kind == GDScriptDataType::BUILTIN) {
Variant arg = Variant::construct(argument_types[i].builtin_type, &p_args[i], 1, r_err);
@@ -362,10 +341,8 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
}
if (_call_size) {
-
call_args = (Variant **)&aptr[sizeof(Variant) * _stack_size];
} else {
-
call_args = nullptr;
}
@@ -376,7 +353,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
if (p_instance) {
if (p_instance->base_ref && static_cast<Reference *>(p_instance->owner)->is_referenced()) {
-
self = REF(static_cast<Reference *>(p_instance->owner));
} else {
self = p_instance->owner;
@@ -387,12 +363,15 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
}
}
+ static_ref = script;
+
String err_text;
#ifdef DEBUG_ENABLED
- if (EngineDebugger::is_active())
+ if (EngineDebugger::is_active()) {
GDScriptLanguage::get_singleton()->enter_function(p_instance, this, stack, &ip, &line);
+ }
#define GD_ERR_BREAK(m_cond) \
{ \
@@ -443,9 +422,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
#endif
OPCODE_SWITCH(_code_ptr[ip]) {
-
OPCODE(OPCODE_OPERATOR) {
-
CHECK_SPACE(5);
bool valid;
@@ -465,7 +442,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
#endif
#ifdef DEBUG_ENABLED
if (!valid) {
-
if (ret.get_type() == Variant::STRING) {
//return a string when invalid with the error
err_text = ret;
@@ -482,7 +458,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
DISPATCH_OPCODE;
OPCODE(OPCODE_EXTENDS_TEST) {
-
CHECK_SPACE(4);
GET_VARIANT_PTR(a, 1);
@@ -491,7 +466,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
#ifdef DEBUG_ENABLED
if (b->get_type() != Variant::OBJECT || b->operator Object *() == nullptr) {
-
err_text = "Right operand of 'is' is not a class.";
OPCODE_BREAK;
}
@@ -499,7 +473,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
bool extends_ok = false;
if (a->get_type() == Variant::OBJECT && a->operator Object *() != nullptr) {
-
#ifdef DEBUG_ENABLED
bool was_freed;
Object *obj_A = a->get_validated_object_with_check(was_freed);
@@ -528,11 +501,9 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
//in other situation, this shoul return false.
if (obj_A->get_script_instance() && obj_A->get_script_instance()->get_language() == GDScriptLanguage::get_singleton()) {
-
GDScript *cmp = static_cast<GDScript *>(obj_A->get_script_instance()->get_script().ptr());
//bool found=false;
while (cmp) {
-
if (cmp == scr_B) {
//inherits from script, all ok
extends_ok = true;
@@ -544,12 +515,10 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
}
} else {
-
GDScriptNativeClass *nc = Object::cast_to<GDScriptNativeClass>(obj_B);
#ifdef DEBUG_ENABLED
if (!nc) {
-
err_text = "Right operand of 'is' is not a class (type: '" + obj_B->get_class() + "').";
OPCODE_BREAK;
}
@@ -564,7 +533,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
DISPATCH_OPCODE;
OPCODE(OPCODE_IS_BUILTIN) {
-
CHECK_SPACE(4);
GET_VARIANT_PTR(value, 1);
@@ -579,7 +547,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
DISPATCH_OPCODE;
OPCODE(OPCODE_SET) {
-
CHECK_SPACE(3);
GET_VARIANT_PTR(dst, 1);
@@ -606,7 +573,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
DISPATCH_OPCODE;
OPCODE(OPCODE_GET) {
-
CHECK_SPACE(3);
GET_VARIANT_PTR(src, 1);
@@ -639,7 +605,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
DISPATCH_OPCODE;
OPCODE(OPCODE_SET_NAMED) {
-
CHECK_SPACE(3);
GET_VARIANT_PTR(dst, 1);
@@ -665,7 +630,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
DISPATCH_OPCODE;
OPCODE(OPCODE_GET_NAMED) {
-
CHECK_SPACE(4);
GET_VARIANT_PTR(src, 1);
@@ -700,7 +664,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
DISPATCH_OPCODE;
OPCODE(OPCODE_SET_MEMBER) {
-
CHECK_SPACE(3);
int indexname = _code_ptr[ip + 1];
GD_ERR_BREAK(indexname < 0 || indexname >= _global_names_count);
@@ -725,7 +688,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
DISPATCH_OPCODE;
OPCODE(OPCODE_GET_MEMBER) {
-
CHECK_SPACE(3);
int indexname = _code_ptr[ip + 1];
GD_ERR_BREAK(indexname < 0 || indexname >= _global_names_count);
@@ -746,7 +708,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
DISPATCH_OPCODE;
OPCODE(OPCODE_ASSIGN) {
-
CHECK_SPACE(3);
GET_VARIANT_PTR(dst, 1);
GET_VARIANT_PTR(src, 2);
@@ -758,7 +719,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
DISPATCH_OPCODE;
OPCODE(OPCODE_ASSIGN_TRUE) {
-
CHECK_SPACE(2);
GET_VARIANT_PTR(dst, 1);
@@ -769,7 +729,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
DISPATCH_OPCODE;
OPCODE(OPCODE_ASSIGN_FALSE) {
-
CHECK_SPACE(2);
GET_VARIANT_PTR(dst, 1);
@@ -780,7 +739,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
DISPATCH_OPCODE;
OPCODE(OPCODE_ASSIGN_TYPED_BUILTIN) {
-
CHECK_SPACE(4);
GET_VARIANT_PTR(dst, 2);
GET_VARIANT_PTR(src, 3);
@@ -810,7 +768,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
DISPATCH_OPCODE;
OPCODE(OPCODE_ASSIGN_TYPED_NATIVE) {
-
CHECK_SPACE(4);
GET_VARIANT_PTR(dst, 2);
GET_VARIANT_PTR(src, 3);
@@ -839,7 +796,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
DISPATCH_OPCODE;
OPCODE(OPCODE_ASSIGN_TYPED_SCRIPT) {
-
CHECK_SPACE(4);
GET_VARIANT_PTR(dst, 2);
GET_VARIANT_PTR(src, 3);
@@ -856,7 +812,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
}
if (src->get_type() != Variant::NIL && src->operator Object *() != nullptr) {
-
ScriptInstance *scr_inst = src->operator Object *()->get_script_instance();
if (!scr_inst) {
err_text = "Trying to assign value of type '" + src->operator Object *()->get_class_name() +
@@ -890,7 +845,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
DISPATCH_OPCODE;
OPCODE(OPCODE_CAST_TO_BUILTIN) {
-
CHECK_SPACE(4);
Variant::Type to_type = (Variant::Type)_code_ptr[ip + 1];
GET_VARIANT_PTR(src, 2);
@@ -913,7 +867,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
DISPATCH_OPCODE;
OPCODE(OPCODE_CAST_TO_NATIVE) {
-
CHECK_SPACE(4);
GET_VARIANT_PTR(to_type, 1);
GET_VARIANT_PTR(src, 2);
@@ -941,7 +894,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
DISPATCH_OPCODE;
OPCODE(OPCODE_CAST_TO_SCRIPT) {
-
CHECK_SPACE(4);
GET_VARIANT_PTR(to_type, 1);
GET_VARIANT_PTR(src, 2);
@@ -961,11 +913,9 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
bool valid = false;
if (src->get_type() != Variant::NIL && src->operator Object *() != nullptr) {
-
ScriptInstance *scr_inst = src->operator Object *()->get_script_instance();
if (scr_inst) {
-
Script *src_type = src->operator Object *()->get_script_instance()->get_script().ptr();
while (src_type) {
@@ -989,7 +939,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
DISPATCH_OPCODE;
OPCODE(OPCODE_CONSTRUCT) {
-
CHECK_SPACE(2);
Variant::Type t = Variant::Type(_code_ptr[ip + 1]);
int argc = _code_ptr[ip + 2];
@@ -1006,7 +955,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
#ifdef DEBUG_ENABLED
if (err.error != Callable::CallError::CALL_OK) {
-
err_text = _get_call_error(err, "'" + Variant::get_type_name(t) + "' constructor", (const Variant **)argptrs);
OPCODE_BREAK;
}
@@ -1018,7 +966,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
DISPATCH_OPCODE;
OPCODE(OPCODE_CONSTRUCT_ARRAY) {
-
CHECK_SPACE(1);
int argc = _code_ptr[ip + 1];
Array array; //arrays are always shared
@@ -1039,7 +986,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
DISPATCH_OPCODE;
OPCODE(OPCODE_CONSTRUCT_DICTIONARY) {
-
CHECK_SPACE(1);
int argc = _code_ptr[ip + 1];
Dictionary dict; //arrays are always shared
@@ -1047,7 +993,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
CHECK_SPACE(argc * 2 + 2);
for (int i = 0; i < argc; i++) {
-
GET_VARIANT_PTR(k, 2 + i * 2 + 0);
GET_VARIANT_PTR(v, 2 + i * 2 + 1);
dict[*k] = *v;
@@ -1063,7 +1008,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
OPCODE(OPCODE_CALL_RETURN)
OPCODE(OPCODE_CALL) {
-
CHECK_SPACE(4);
bool call_ret = _code_ptr[ip] == OPCODE_CALL_RETURN;
@@ -1094,11 +1038,9 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
#endif
Callable::CallError err;
if (call_ret) {
-
GET_VARIANT_PTR(ret, argc);
base->call_ptr(*methodname, (const Variant **)argptrs, argc, ret, err);
} else {
-
base->call_ptr(*methodname, (const Variant **)argptrs, argc, nullptr, err);
}
#ifdef DEBUG_ENABLED
@@ -1107,7 +1049,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
}
if (err.error != Callable::CallError::CALL_OK) {
-
String methodstr = *methodname;
String basestr = _get_var_type(base);
@@ -1119,14 +1060,11 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
}
}
} else if (methodstr == "free") {
-
if (err.error == Callable::CallError::CALL_ERROR_INVALID_METHOD) {
-
if (base->is_ref()) {
err_text = "Attempted to free a reference.";
OPCODE_BREAK;
} else if (base->get_type() == Variant::OBJECT) {
-
err_text = "Attempted to free a locked object (calling or emitting).";
OPCODE_BREAK;
}
@@ -1143,7 +1081,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
DISPATCH_OPCODE;
OPCODE(OPCODE_CALL_BUILT_IN) {
-
CHECK_SPACE(4);
GDScriptFunctions::Function func = GDScriptFunctions::Function(_code_ptr[ip + 1]);
@@ -1167,7 +1104,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
#ifdef DEBUG_ENABLED
if (err.error != Callable::CallError::CALL_OK) {
-
String methodstr = GDScriptFunctions::get_func_name(func);
if (dst->get_type() == Variant::STRING) {
//call provided error string
@@ -1183,18 +1119,15 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
DISPATCH_OPCODE;
OPCODE(OPCODE_CALL_SELF) {
-
OPCODE_BREAK;
}
OPCODE(OPCODE_CALL_SELF_BASE) {
-
CHECK_SPACE(2);
int self_fun = _code_ptr[ip + 1];
#ifdef DEBUG_ENABLED
if (self_fun < 0 || self_fun >= _global_names_count) {
-
err_text = "compiler bug, function name not found";
OPCODE_BREAK;
}
@@ -1220,19 +1153,17 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
while (gds->base.ptr()) {
gds = gds->base.ptr();
E = gds->member_functions.find(*methodname);
- if (E)
+ if (E) {
break;
+ }
}
Callable::CallError err;
if (E) {
-
*dst = E->get()->call(p_instance, (const Variant **)argptrs, argc, err);
} else if (gds->native.ptr()) {
-
if (*methodname != GDScriptLanguage::get_singleton()->strings._init) {
-
MethodBind *mb = ClassDB::get_method(gds->native->get_name(), *methodname);
if (!mb) {
err.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
@@ -1243,7 +1174,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
err.error = Callable::CallError::CALL_OK;
}
} else {
-
if (*methodname != GDScriptLanguage::get_singleton()->strings._init) {
err.error = Callable::CallError::CALL_ERROR_INVALID_METHOD;
} else {
@@ -1252,7 +1182,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
}
if (err.error != Callable::CallError::CALL_OK) {
-
String methodstr = *methodname;
err_text = _get_call_error(err, "function '" + methodstr + "'", (const Variant **)argptrs);
@@ -1265,7 +1194,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
OPCODE(OPCODE_YIELD)
OPCODE(OPCODE_YIELD_SIGNAL) {
-
int ipofs = 1;
if (_code_ptr[ip] == OPCODE_YIELD_SIGNAL) {
CHECK_SPACE(4);
@@ -1285,13 +1213,24 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
gdfs->state.stack_size = _stack_size;
gdfs->state.self = self;
gdfs->state.alloca_size = alloca_size;
- gdfs->state.script = Ref<GDScript>(_script);
gdfs->state.ip = ip + ipofs;
gdfs->state.line = line;
- gdfs->state.instance_id = (p_instance && p_instance->get_owner()) ? p_instance->get_owner()->get_instance_id() : ObjectID();
- //gdfs->state.result_pos=ip+ipofs-1;
+ gdfs->state.script = _script;
+ {
+ MutexLock lock(GDScriptLanguage::get_singleton()->lock);
+ _script->pending_func_states.add(&gdfs->scripts_list);
+ if (p_instance) {
+ gdfs->state.instance = p_instance;
+ p_instance->pending_func_states.add(&gdfs->instances_list);
+ } else {
+ gdfs->state.instance = nullptr;
+ }
+ }
+#ifdef DEBUG_ENABLED
+ gdfs->state.function_name = name;
+ gdfs->state.script_path = _script->get_path();
+#endif
gdfs->state.defarg = defarg;
- gdfs->state.instance = p_instance;
gdfs->function = this;
retvalue = gdfs;
@@ -1327,7 +1266,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
OPCODE_BREAK;
}
if (signal.length() == 0) {
-
err_text = "Second argument of yield() is an empty string (for signal name).";
OPCODE_BREAK;
}
@@ -1353,7 +1291,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
}
OPCODE(OPCODE_YIELD_RESUME) {
-
CHECK_SPACE(2);
#ifdef DEBUG_ENABLED
if (!p_state) {
@@ -1368,7 +1305,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
DISPATCH_OPCODE;
OPCODE(OPCODE_JUMP) {
-
CHECK_SPACE(2);
int to = _code_ptr[ip + 1];
@@ -1378,7 +1314,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
DISPATCH_OPCODE;
OPCODE(OPCODE_JUMP_IF) {
-
CHECK_SPACE(3);
GET_VARIANT_PTR(test, 1);
@@ -1396,7 +1331,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
DISPATCH_OPCODE;
OPCODE(OPCODE_JUMP_IF_NOT) {
-
CHECK_SPACE(3);
GET_VARIANT_PTR(test, 1);
@@ -1414,14 +1348,12 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
DISPATCH_OPCODE;
OPCODE(OPCODE_JUMP_TO_DEF_ARGUMENT) {
-
CHECK_SPACE(2);
ip = _default_arg_ptr[defarg];
}
DISPATCH_OPCODE;
OPCODE(OPCODE_RETURN) {
-
CHECK_SPACE(2);
GET_VARIANT_PTR(r, 1);
retvalue = *r;
@@ -1432,7 +1364,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
}
OPCODE(OPCODE_ITERATE_BEGIN) {
-
CHECK_SPACE(8); //space for this a regular iterate
GET_VARIANT_PTR(counter, 1);
@@ -1465,7 +1396,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
DISPATCH_OPCODE;
OPCODE(OPCODE_ITERATE) {
-
CHECK_SPACE(4);
GET_VARIANT_PTR(counter, 1);
@@ -1502,11 +1432,14 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
#ifdef DEBUG_ENABLED
GET_VARIANT_PTR(test, 1);
- GET_VARIANT_PTR(message, 2);
bool result = test->booleanize();
if (!result) {
- const String &message_str = *message;
+ String message_str;
+ if (_code_ptr[ip + 2] != 0) {
+ GET_VARIANT_PTR(message, 2);
+ message_str = *message;
+ }
if (message_str.empty()) {
err_text = "Assertion failed.";
} else {
@@ -1541,15 +1474,17 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
bool do_break = false;
if (EngineDebugger::get_script_debugger()->get_lines_left() > 0) {
-
- if (EngineDebugger::get_script_debugger()->get_depth() <= 0)
+ if (EngineDebugger::get_script_debugger()->get_depth() <= 0) {
EngineDebugger::get_script_debugger()->set_lines_left(EngineDebugger::get_script_debugger()->get_lines_left() - 1);
- if (EngineDebugger::get_script_debugger()->get_lines_left() <= 0)
+ }
+ if (EngineDebugger::get_script_debugger()->get_lines_left() <= 0) {
do_break = true;
+ }
}
- if (EngineDebugger::get_script_debugger()->is_breakpoint(line, source))
+ if (EngineDebugger::get_script_debugger()->is_breakpoint(line, source)) {
do_break = true;
+ }
if (do_break) {
GDScriptLanguage::get_singleton()->debug_break("Breakpoint", true);
@@ -1577,20 +1512,24 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
OPCODES_END
#ifdef DEBUG_ENABLED
- if (exit_ok)
+ if (exit_ok) {
OPCODE_OUT;
+ }
//error
// function, file, line, error, explanation
String err_file;
- if (p_instance && ObjectDB::get_instance(p_instance->owner_id) != nullptr && p_instance->script->is_valid() && p_instance->script->path != "")
+ if (p_instance && ObjectDB::get_instance(p_instance->owner_id) != nullptr && p_instance->script->is_valid() && p_instance->script->path != "") {
err_file = p_instance->script->path;
- else if (script)
+ } else if (script) {
err_file = script->path;
- if (err_file == "")
+ }
+ if (err_file == "") {
err_file = "<built-in>";
+ }
String err_func = name;
- if (p_instance && ObjectDB::get_instance(p_instance->owner_id) != nullptr && p_instance->script->is_valid() && p_instance->script->name != "")
+ if (p_instance && ObjectDB::get_instance(p_instance->owner_id) != nullptr && p_instance->script->is_valid() && p_instance->script->name != "") {
err_func = p_instance->script->name + "." + err_func;
+ }
int err_line = line;
if (err_text == "") {
err_text = "Internal Script Error! - opcode #" + itos(last_opcode) + " (report please).";
@@ -1622,14 +1561,16 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
// 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 (EngineDebugger::is_active())
+ if (EngineDebugger::is_active()) {
GDScriptLanguage::get_singleton()->exit_function();
+ }
#endif
if (_stack_size) {
//free stack
- for (int i = 0; i < _stack_size; i++)
+ for (int i = 0; i < _stack_size; i++) {
stack[i].~Variant();
+ }
}
#ifdef DEBUG_ENABLED
@@ -1640,32 +1581,28 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
}
const int *GDScriptFunction::get_code() const {
-
return _code_ptr;
}
-int GDScriptFunction::get_code_size() const {
+int GDScriptFunction::get_code_size() const {
return _code_size;
}
Variant GDScriptFunction::get_constant(int p_idx) const {
-
ERR_FAIL_INDEX_V(p_idx, constants.size(), "<errconst>");
return constants[p_idx];
}
StringName GDScriptFunction::get_global_name(int p_idx) const {
-
ERR_FAIL_INDEX_V(p_idx, global_names.size(), "<errgname>");
return global_names[p_idx];
}
int GDScriptFunction::get_default_argument_count() const {
-
return _default_arg_count;
}
-int GDScriptFunction::get_default_argument_addr(int p_idx) const {
+int GDScriptFunction::get_default_argument_addr(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx, default_arguments.size(), -1);
return default_arguments[p_idx];
}
@@ -1680,45 +1617,38 @@ GDScriptDataType GDScriptFunction::get_argument_type(int p_idx) const {
}
StringName GDScriptFunction::get_name() const {
-
return name;
}
int GDScriptFunction::get_max_stack_size() const {
-
return _stack_size;
}
struct _GDFKC {
-
int order;
List<int> pos;
};
struct _GDFKCS {
-
int order;
StringName id;
int pos;
bool operator<(const _GDFKCS &p_r) const {
-
return order < p_r.order;
}
};
void GDScriptFunction::debug_get_stack_member_state(int p_line, List<Pair<StringName, int>> *r_stackvars) const {
-
int oc = 0;
Map<StringName, _GDFKC> sdmap;
for (const List<StackDebug>::Element *E = stack_debug.front(); E; E = E->next()) {
-
const StackDebug &sd = E->get();
- if (sd.line > p_line)
+ if (sd.line > p_line) {
break;
+ }
if (sd.added) {
-
if (!sdmap.has(sd.identifier)) {
_GDFKC d;
d.order = oc++;
@@ -1729,18 +1659,17 @@ void GDScriptFunction::debug_get_stack_member_state(int p_line, List<Pair<String
sdmap[sd.identifier].pos.push_back(sd.pos);
}
} else {
-
ERR_CONTINUE(!sdmap.has(sd.identifier));
sdmap[sd.identifier].pos.pop_back();
- if (sdmap[sd.identifier].pos.empty())
+ if (sdmap[sd.identifier].pos.empty()) {
sdmap.erase(sd.identifier);
+ }
}
}
List<_GDFKCS> stackpositions;
for (Map<StringName, _GDFKC>::Element *E = sdmap.front(); E; E = E->next()) {
-
_GDFKCS spp;
spp.id = E->key();
spp.order = E->get().order;
@@ -1751,7 +1680,6 @@ void GDScriptFunction::debug_get_stack_member_state(int p_line, List<Pair<String
stackpositions.sort();
for (List<_GDFKCS>::Element *E = stackpositions.front(); E; E = E->next()) {
-
Pair<StringName, int> p;
p.first = E->get().id;
p.second = E->get().pos;
@@ -1761,7 +1689,6 @@ void GDScriptFunction::debug_get_stack_member_state(int p_line, List<Pair<String
GDScriptFunction::GDScriptFunction() :
function_list(this) {
-
_stack_size = 0;
_call_size = 0;
rpc_mode = MultiplayerAPI::RPC_MODE_DISABLED;
@@ -1800,7 +1727,6 @@ GDScriptFunction::~GDScriptFunction() {
/////////////////////
Variant GDScriptFunctionState::_signal_callback(const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
-
Variant arg;
r_error.error = Callable::CallError::CALL_OK;
@@ -1833,28 +1759,48 @@ Variant GDScriptFunctionState::_signal_callback(const Variant **p_args, int p_ar
}
bool GDScriptFunctionState::is_valid(bool p_extended_check) const {
-
- if (function == nullptr)
+ if (function == nullptr) {
return false;
+ }
if (p_extended_check) {
- //class instance gone?
- if (state.instance_id.is_valid() && !ObjectDB::get_instance(state.instance_id))
+ MutexLock lock(GDScriptLanguage::get_singleton()->lock);
+
+ // Script gone?
+ if (!scripts_list.in_list()) {
return false;
+ }
+ // Class instance gone? (if not static function)
+ if (state.instance && !instances_list.in_list()) {
+ return false;
+ }
}
return true;
}
Variant GDScriptFunctionState::resume(const Variant &p_arg) {
-
ERR_FAIL_COND_V(!function, Variant());
- if (state.instance_id.is_valid() && !ObjectDB::get_instance(state.instance_id)) {
+ {
+ MutexLock lock(GDScriptLanguage::singleton->lock);
+
+ if (!scripts_list.in_list()) {
#ifdef DEBUG_ENABLED
- ERR_FAIL_V_MSG(Variant(), "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_MSG(Variant(), "Resumed function '" + state.function_name + "()' after yield, but script is gone. At script: " + state.script_path + ":" + itos(state.line));
#else
- return Variant();
+ return Variant();
+#endif
+ }
+ if (state.instance && !instances_list.in_list()) {
+#ifdef DEBUG_ENABLED
+ ERR_FAIL_V_MSG(Variant(), "Resumed function '" + state.function_name + "()' after yield, but class instance is gone. At script: " + state.script_path + ":" + itos(state.line));
+#else
+ return Variant();
#endif
+ }
+ // Do these now to avoid locking again after the call
+ scripts_list.remove_from_list();
+ instances_list.remove_from_list();
}
state.result = p_arg;
@@ -1884,13 +1830,8 @@ Variant GDScriptFunctionState::resume(const Variant &p_arg) {
}
#ifdef DEBUG_ENABLED
- if (EngineDebugger::is_active())
+ if (EngineDebugger::is_active()) {
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
}
@@ -1898,8 +1839,17 @@ Variant GDScriptFunctionState::resume(const Variant &p_arg) {
return ret;
}
-void GDScriptFunctionState::_bind_methods() {
+void GDScriptFunctionState::_clear_stack() {
+ if (state.stack_size) {
+ Variant *stack = (Variant *)state.stack.ptr();
+ for (int i = 0; i < state.stack_size; i++) {
+ stack[i].~Variant();
+ }
+ state.stack_size = 0;
+ }
+}
+void GDScriptFunctionState::_bind_methods() {
ClassDB::bind_method(D_METHOD("resume", "arg"), &GDScriptFunctionState::resume, DEFVAL(Variant()));
ClassDB::bind_method(D_METHOD("is_valid", "extended_check"), &GDScriptFunctionState::is_valid, DEFVAL(false));
ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "_signal_callback", &GDScriptFunctionState::_signal_callback, MethodInfo("_signal_callback"));
@@ -1907,18 +1857,18 @@ void GDScriptFunctionState::_bind_methods() {
ADD_SIGNAL(MethodInfo("completed", PropertyInfo(Variant::NIL, "result", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NIL_IS_VARIANT)));
}
-GDScriptFunctionState::GDScriptFunctionState() {
-
+GDScriptFunctionState::GDScriptFunctionState() :
+ scripts_list(this),
+ instances_list(this) {
function = nullptr;
}
GDScriptFunctionState::~GDScriptFunctionState() {
+ _clear_stack();
- if (function != nullptr) {
- //never called, deinitialize stack
- for (int i = 0; i < state.stack_size; i++) {
- Variant *v = (Variant *)&state.stack[sizeof(Variant) * i];
- v->~Variant();
- }
+ {
+ MutexLock lock(GDScriptLanguage::singleton->lock);
+ scripts_list.remove_from_list();
+ instances_list.remove_from_list();
}
}