|
@@ -34,22 +34,22 @@
|
|
|
#include "core/os/os.h"
|
|
|
#include "gdscript.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 {
|
|
|
+Variant *GDScriptFunction::_get_variant(int p_address, GDScriptInstance *p_instance, 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: {
|
|
|
+ case ADDR_TYPE_STACK: {
|
|
|
#ifdef DEBUG_ENABLED
|
|
|
- if (unlikely(!p_instance)) {
|
|
|
- r_error = "Cannot access self without instance.";
|
|
|
- return nullptr;
|
|
|
- }
|
|
|
+ ERR_FAIL_INDEX_V(address, _stack_size, nullptr);
|
|
|
#endif
|
|
|
- return &self;
|
|
|
+ return &p_stack[address];
|
|
|
} break;
|
|
|
- case ADDR_TYPE_CLASS: {
|
|
|
- return &static_ref;
|
|
|
+ case ADDR_TYPE_CONSTANT: {
|
|
|
+#ifdef DEBUG_ENABLED
|
|
|
+ ERR_FAIL_INDEX_V(address, _constant_count, nullptr);
|
|
|
+#endif
|
|
|
+ return &_constants_ptr[address];
|
|
|
} break;
|
|
|
case ADDR_TYPE_MEMBER: {
|
|
|
#ifdef DEBUG_ENABLED
|
|
@@ -61,65 +61,6 @@ Variant *GDScriptFunction::_get_variant(int p_address, GDScriptInstance *p_insta
|
|
|
//member indexing is O(1)
|
|
|
return &p_instance->members.write[address];
|
|
|
} break;
|
|
|
- case ADDR_TYPE_CLASS_CONSTANT: {
|
|
|
- //todo change to index!
|
|
|
- GDScript *s = p_script;
|
|
|
-#ifdef DEBUG_ENABLED
|
|
|
- ERR_FAIL_INDEX_V(address, _global_names_count, nullptr);
|
|
|
-#endif
|
|
|
- const StringName *sn = &_global_names_ptr[address];
|
|
|
-
|
|
|
- while (s) {
|
|
|
- GDScript *o = s;
|
|
|
- while (o) {
|
|
|
- Map<StringName, Variant>::Element *E = o->constants.find(*sn);
|
|
|
- if (E) {
|
|
|
- return &E->get();
|
|
|
- }
|
|
|
- o = o->_owner;
|
|
|
- }
|
|
|
- s = s->_base;
|
|
|
- }
|
|
|
-
|
|
|
- ERR_FAIL_V_MSG(nullptr, "GDScriptCompiler bug.");
|
|
|
- } break;
|
|
|
- case ADDR_TYPE_LOCAL_CONSTANT: {
|
|
|
-#ifdef DEBUG_ENABLED
|
|
|
- ERR_FAIL_INDEX_V(address, _constant_count, nullptr);
|
|
|
-#endif
|
|
|
- return &_constants_ptr[address];
|
|
|
- } break;
|
|
|
- case ADDR_TYPE_STACK:
|
|
|
- case ADDR_TYPE_STACK_VARIABLE: {
|
|
|
-#ifdef DEBUG_ENABLED
|
|
|
- ERR_FAIL_INDEX_V(address, _stack_size, nullptr);
|
|
|
-#endif
|
|
|
- return &p_stack[address];
|
|
|
- } break;
|
|
|
- case ADDR_TYPE_GLOBAL: {
|
|
|
-#ifdef DEBUG_ENABLED
|
|
|
- ERR_FAIL_INDEX_V(address, GDScriptLanguage::get_singleton()->get_global_array_size(), nullptr);
|
|
|
-#endif
|
|
|
- return &GDScriptLanguage::get_singleton()->get_global_array()[address];
|
|
|
- } break;
|
|
|
-#ifdef TOOLS_ENABLED
|
|
|
- case ADDR_TYPE_NAMED_GLOBAL: {
|
|
|
-#ifdef DEBUG_ENABLED
|
|
|
- ERR_FAIL_INDEX_V(address, _global_names_count, nullptr);
|
|
|
-#endif
|
|
|
- StringName id = _global_names_ptr[address];
|
|
|
-
|
|
|
- if (GDScriptLanguage::get_singleton()->get_named_globals_map().has(id)) {
|
|
|
- return (Variant *)&GDScriptLanguage::get_singleton()->get_named_globals_map()[id];
|
|
|
- } else {
|
|
|
- r_error = "Autoload singleton '" + String(id) + "' has been removed.";
|
|
|
- return nullptr;
|
|
|
- }
|
|
|
- } break;
|
|
|
-#endif
|
|
|
- case ADDR_TYPE_NIL: {
|
|
|
- return &nil;
|
|
|
- } break;
|
|
|
}
|
|
|
|
|
|
ERR_FAIL_V_MSG(nullptr, "Bad code! (unknown addressing mode).");
|
|
@@ -340,6 +281,7 @@ String GDScriptFunction::_get_call_error(const Callable::CallError &p_err, const
|
|
|
&&OPCODE_ITERATE_PACKED_VECTOR3_ARRAY, \
|
|
|
&&OPCODE_ITERATE_PACKED_COLOR_ARRAY, \
|
|
|
&&OPCODE_ITERATE_OBJECT, \
|
|
|
+ &&OPCODE_STORE_NAMED_GLOBAL, \
|
|
|
&&OPCODE_ASSERT, \
|
|
|
&&OPCODE_BREAKPOINT, \
|
|
|
&&OPCODE_LINE, \
|
|
@@ -415,11 +357,9 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
|
|
|
|
|
|
r_err.error = Callable::CallError::CALL_OK;
|
|
|
|
|
|
- Variant self;
|
|
|
- Variant static_ref;
|
|
|
Variant retvalue;
|
|
|
Variant *stack = nullptr;
|
|
|
- Variant **instruction_args;
|
|
|
+ Variant **instruction_args = nullptr;
|
|
|
const void **call_args_ptr = nullptr;
|
|
|
int defarg = 0;
|
|
|
|
|
@@ -444,7 +384,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
|
|
|
script = p_state->script;
|
|
|
p_instance = p_state->instance;
|
|
|
defarg = p_state->defarg;
|
|
|
- self = p_state->self;
|
|
|
|
|
|
} else {
|
|
|
if (p_argcount != _argument_count) {
|
|
@@ -462,55 +401,49 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- alloca_size = sizeof(Variant *) * _instruction_args_size + sizeof(Variant) * _stack_size;
|
|
|
-
|
|
|
- if (alloca_size) {
|
|
|
- uint8_t *aptr = (uint8_t *)alloca(alloca_size);
|
|
|
+ // Add 3 here for self, class, and nil.
|
|
|
+ alloca_size = sizeof(Variant *) * 3 + sizeof(Variant *) * _instruction_args_size + sizeof(Variant) * _stack_size;
|
|
|
|
|
|
- if (_stack_size) {
|
|
|
- stack = (Variant *)aptr;
|
|
|
- for (int i = 0; i < p_argcount; i++) {
|
|
|
- if (!argument_types[i].has_type) {
|
|
|
- memnew_placement(&stack[i], Variant(*p_args[i]));
|
|
|
- continue;
|
|
|
- }
|
|
|
+ uint8_t *aptr = (uint8_t *)alloca(alloca_size);
|
|
|
+ stack = (Variant *)aptr;
|
|
|
|
|
|
- if (!argument_types[i].is_type(*p_args[i], true)) {
|
|
|
- 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, arg, &p_args[i], 1, r_err);
|
|
|
- memnew_placement(&stack[i], Variant(arg));
|
|
|
- } else {
|
|
|
- memnew_placement(&stack[i], Variant(*p_args[i]));
|
|
|
- }
|
|
|
- }
|
|
|
- for (int i = p_argcount; i < _stack_size; i++) {
|
|
|
- memnew_placement(&stack[i], Variant);
|
|
|
- }
|
|
|
- } else {
|
|
|
- stack = nullptr;
|
|
|
+ for (int i = 0; i < p_argcount; i++) {
|
|
|
+ if (!argument_types[i].has_type) {
|
|
|
+ memnew_placement(&stack[i + 3], Variant(*p_args[i]));
|
|
|
+ continue;
|
|
|
}
|
|
|
|
|
|
- if (_instruction_args_size) {
|
|
|
- instruction_args = (Variant **)&aptr[sizeof(Variant) * _stack_size];
|
|
|
+ if (!argument_types[i].is_type(*p_args[i], true)) {
|
|
|
+ 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, arg, &p_args[i], 1, r_err);
|
|
|
+ memnew_placement(&stack[i + 3], Variant(arg));
|
|
|
} else {
|
|
|
- instruction_args = nullptr;
|
|
|
+ memnew_placement(&stack[i + 3], Variant(*p_args[i]));
|
|
|
}
|
|
|
+ }
|
|
|
+ for (int i = p_argcount + 3; i < _stack_size; i++) {
|
|
|
+ memnew_placement(&stack[i], Variant);
|
|
|
+ }
|
|
|
|
|
|
+ memnew_placement(&stack[ADDR_STACK_NIL], Variant);
|
|
|
+
|
|
|
+ if (_instruction_args_size) {
|
|
|
+ instruction_args = (Variant **)&aptr[sizeof(Variant) * _stack_size];
|
|
|
} else {
|
|
|
- stack = nullptr;
|
|
|
instruction_args = nullptr;
|
|
|
}
|
|
|
|
|
|
if (p_instance) {
|
|
|
- self = p_instance->owner;
|
|
|
+ memnew_placement(&stack[ADDR_STACK_SELF], Variant(p_instance->owner));
|
|
|
script = p_instance->script.ptr();
|
|
|
} else {
|
|
|
+ memnew_placement(&stack[ADDR_STACK_SELF], Variant);
|
|
|
script = _script;
|
|
|
}
|
|
|
}
|
|
@@ -520,7 +453,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
|
|
|
call_args_ptr = nullptr;
|
|
|
}
|
|
|
|
|
|
- static_ref = script;
|
|
|
+ memnew_placement(&stack[ADDR_STACK_CLASS], Variant(script));
|
|
|
|
|
|
String err_text;
|
|
|
|
|
@@ -541,10 +474,10 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
|
|
|
#define CHECK_SPACE(m_space) \
|
|
|
GD_ERR_BREAK((ip + m_space) > _code_size)
|
|
|
|
|
|
-#define GET_VARIANT_PTR(m_v, m_code_ofs) \
|
|
|
- Variant *m_v; \
|
|
|
- m_v = _get_variant(_code_ptr[ip + m_code_ofs], p_instance, script, self, static_ref, stack, err_text); \
|
|
|
- if (unlikely(!m_v)) \
|
|
|
+#define GET_VARIANT_PTR(m_v, m_code_ofs) \
|
|
|
+ Variant *m_v; \
|
|
|
+ m_v = _get_variant(_code_ptr[ip + m_code_ofs], p_instance, stack, err_text); \
|
|
|
+ if (unlikely(!m_v)) \
|
|
|
OPCODE_BREAK;
|
|
|
|
|
|
#else
|
|
@@ -552,7 +485,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
|
|
|
#define CHECK_SPACE(m_space)
|
|
|
#define GET_VARIANT_PTR(m_v, m_code_ofs) \
|
|
|
Variant *m_v; \
|
|
|
- m_v = _get_variant(_code_ptr[ip + m_code_ofs], p_instance, script, self, static_ref, stack, err_text);
|
|
|
+ m_v = _get_variant(_code_ptr[ip + m_code_ofs], p_instance, stack, err_text);
|
|
|
|
|
|
#endif
|
|
|
|
|
@@ -2038,7 +1971,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
|
|
|
memnew_placement(&gdfs->state.stack.write[sizeof(Variant) * i], Variant(stack[i]));
|
|
|
}
|
|
|
gdfs->state.stack_size = _stack_size;
|
|
|
- gdfs->state.self = self;
|
|
|
gdfs->state.alloca_size = alloca_size;
|
|
|
gdfs->state.ip = ip + 2;
|
|
|
gdfs->state.line = line;
|
|
@@ -3028,6 +2960,19 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
|
|
|
}
|
|
|
DISPATCH_OPCODE;
|
|
|
|
|
|
+ OPCODE(OPCODE_STORE_NAMED_GLOBAL) {
|
|
|
+ CHECK_SPACE(3);
|
|
|
+ int globalname_idx = _code_ptr[ip + 2];
|
|
|
+ GD_ERR_BREAK(globalname_idx < 0 || globalname_idx >= _global_names_count);
|
|
|
+ const StringName *globalname = &_global_names_ptr[globalname_idx];
|
|
|
+
|
|
|
+ GET_INSTRUCTION_ARG(dst, 0);
|
|
|
+ *dst = GDScriptLanguage::get_singleton()->get_named_globals_map()[*globalname];
|
|
|
+
|
|
|
+ ip += 3;
|
|
|
+ }
|
|
|
+ DISPATCH_OPCODE;
|
|
|
+
|
|
|
OPCODE(OPCODE_ASSERT) {
|
|
|
CHECK_SPACE(3);
|
|
|
|