Reduce number of addressing modes in GDScript VM
There's now only 3 addressing modes: stack, constant, and member. Self, class, and nil are now present respectively in the first 3 stack slots. Global and class constants are moved to local constants when compiling. Named globals is only present on editor to use on tool singletons, so its use now emits a new instruction to copy the global to the stack. This allow us to further optimize the VM later by embedding the addressing modes in the instructions themselves, which is better done with less permutations.
This commit is contained in:
parent
084b882c0a
commit
cf4079cb5f
|
@ -59,12 +59,7 @@ uint32_t GDScriptByteCodeGenerator::add_local_constant(const StringName &p_name,
|
|||
}
|
||||
|
||||
uint32_t GDScriptByteCodeGenerator::add_or_get_constant(const Variant &p_constant) {
|
||||
if (constant_map.has(p_constant)) {
|
||||
return constant_map[p_constant];
|
||||
}
|
||||
int index = constant_map.size();
|
||||
constant_map[p_constant] = index;
|
||||
return index;
|
||||
return get_constant_pos(p_constant);
|
||||
}
|
||||
|
||||
uint32_t GDScriptByteCodeGenerator::add_or_get_name(const StringName &p_name) {
|
||||
|
@ -612,7 +607,8 @@ void GDScriptByteCodeGenerator::write_assign(const Address &p_target, const Addr
|
|||
} break;
|
||||
case GDScriptDataType::NATIVE: {
|
||||
int class_idx = GDScriptLanguage::get_singleton()->get_global_map()[p_target.type.native_type];
|
||||
class_idx |= (GDScriptFunction::ADDR_TYPE_GLOBAL << GDScriptFunction::ADDR_BITS);
|
||||
Variant nc = GDScriptLanguage::get_singleton()->get_global_array()[class_idx];
|
||||
class_idx = get_constant_pos(nc) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS);
|
||||
append(GDScriptFunction::OPCODE_ASSIGN_TYPED_NATIVE, 3);
|
||||
append(p_target);
|
||||
append(p_source);
|
||||
|
@ -621,8 +617,7 @@ void GDScriptByteCodeGenerator::write_assign(const Address &p_target, const Addr
|
|||
case GDScriptDataType::SCRIPT:
|
||||
case GDScriptDataType::GDSCRIPT: {
|
||||
Variant script = p_target.type.script_type;
|
||||
int idx = get_constant_pos(script);
|
||||
idx |= (GDScriptFunction::ADDR_TYPE_LOCAL_CONSTANT << GDScriptFunction::ADDR_BITS);
|
||||
int idx = get_constant_pos(script) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS);
|
||||
|
||||
append(GDScriptFunction::OPCODE_ASSIGN_TYPED_SCRIPT, 3);
|
||||
append(p_target);
|
||||
|
@ -673,6 +668,12 @@ void GDScriptByteCodeGenerator::write_assign_default_parameter(const Address &p_
|
|||
function->default_arguments.push_back(opcodes.size());
|
||||
}
|
||||
|
||||
void GDScriptByteCodeGenerator::write_store_named_global(const Address &p_dst, const StringName &p_global) {
|
||||
append(GDScriptFunction::OPCODE_STORE_NAMED_GLOBAL, 1);
|
||||
append(p_dst);
|
||||
append(p_global);
|
||||
}
|
||||
|
||||
void GDScriptByteCodeGenerator::write_cast(const Address &p_target, const Address &p_source, const GDScriptDataType &p_type) {
|
||||
int index = 0;
|
||||
|
||||
|
@ -683,16 +684,14 @@ void GDScriptByteCodeGenerator::write_cast(const Address &p_target, const Addres
|
|||
} break;
|
||||
case GDScriptDataType::NATIVE: {
|
||||
int class_idx = GDScriptLanguage::get_singleton()->get_global_map()[p_type.native_type];
|
||||
class_idx |= (GDScriptFunction::ADDR_TYPE_GLOBAL << GDScriptFunction::ADDR_BITS);
|
||||
Variant nc = GDScriptLanguage::get_singleton()->get_global_array()[class_idx];
|
||||
append(GDScriptFunction::OPCODE_CAST_TO_NATIVE, 3);
|
||||
index = class_idx;
|
||||
index = get_constant_pos(nc) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS);
|
||||
} break;
|
||||
case GDScriptDataType::SCRIPT:
|
||||
case GDScriptDataType::GDSCRIPT: {
|
||||
Variant script = p_type.script_type;
|
||||
int idx = get_constant_pos(script);
|
||||
idx |= (GDScriptFunction::ADDR_TYPE_LOCAL_CONSTANT << GDScriptFunction::ADDR_BITS);
|
||||
|
||||
int idx = get_constant_pos(script) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS);
|
||||
append(GDScriptFunction::OPCODE_CAST_TO_SCRIPT, 3);
|
||||
index = idx;
|
||||
} break;
|
||||
|
@ -903,7 +902,7 @@ void GDScriptByteCodeGenerator::write_call_self(const Address &p_target, const S
|
|||
for (int i = 0; i < p_arguments.size(); i++) {
|
||||
append(p_arguments[i]);
|
||||
}
|
||||
append(GDScriptFunction::ADDR_TYPE_SELF << GDScriptFunction::ADDR_BITS);
|
||||
append(GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS);
|
||||
append(p_target);
|
||||
append(p_arguments.size());
|
||||
append(p_function_name);
|
||||
|
@ -914,7 +913,7 @@ void GDScriptByteCodeGenerator::write_call_self_async(const Address &p_target, c
|
|||
for (int i = 0; i < p_arguments.size(); i++) {
|
||||
append(p_arguments[i]);
|
||||
}
|
||||
append(GDScriptFunction::ADDR_TYPE_SELF << GDScriptFunction::ADDR_BITS);
|
||||
append(GDScriptFunction::ADDR_SELF);
|
||||
append(p_target);
|
||||
append(p_arguments.size());
|
||||
append(p_function_name);
|
||||
|
@ -999,7 +998,7 @@ void GDScriptByteCodeGenerator::write_construct_typed_array(const Address &p_tar
|
|||
if (p_element_type.script_type) {
|
||||
Variant script_type = Ref<Script>(p_element_type.script_type);
|
||||
int addr = get_constant_pos(script_type);
|
||||
addr |= GDScriptFunction::ADDR_TYPE_LOCAL_CONSTANT << GDScriptFunction::ADDR_BITS;
|
||||
addr |= GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS;
|
||||
append(addr);
|
||||
} else {
|
||||
append(Address()); // null.
|
||||
|
@ -1296,8 +1295,7 @@ void GDScriptByteCodeGenerator::write_return(const Address &p_return_value) {
|
|||
const GDScriptDataType &element_type = function->return_type.get_container_element_type();
|
||||
|
||||
Variant script = function->return_type.script_type;
|
||||
int script_idx = get_constant_pos(script);
|
||||
script_idx |= (GDScriptFunction::ADDR_TYPE_LOCAL_CONSTANT << GDScriptFunction::ADDR_BITS);
|
||||
int script_idx = get_constant_pos(script) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS);
|
||||
|
||||
append(GDScriptFunction::OPCODE_RETURN_TYPED_ARRAY, 2);
|
||||
append(p_return_value);
|
||||
|
@ -1326,7 +1324,7 @@ void GDScriptByteCodeGenerator::write_return(const Address &p_return_value) {
|
|||
|
||||
Variant script = function->return_type.script_type;
|
||||
int script_idx = get_constant_pos(script);
|
||||
script_idx |= (GDScriptFunction::ADDR_TYPE_LOCAL_CONSTANT << GDScriptFunction::ADDR_BITS);
|
||||
script_idx |= (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS);
|
||||
|
||||
append(GDScriptFunction::OPCODE_RETURN_TYPED_ARRAY, 2);
|
||||
append(p_return_value);
|
||||
|
@ -1343,14 +1341,14 @@ void GDScriptByteCodeGenerator::write_return(const Address &p_return_value) {
|
|||
append(GDScriptFunction::OPCODE_RETURN_TYPED_NATIVE, 2);
|
||||
append(p_return_value);
|
||||
int class_idx = GDScriptLanguage::get_singleton()->get_global_map()[function->return_type.native_type];
|
||||
class_idx |= (GDScriptFunction::ADDR_TYPE_GLOBAL << GDScriptFunction::ADDR_BITS);
|
||||
Variant nc = GDScriptLanguage::get_singleton()->get_global_array()[class_idx];
|
||||
class_idx = get_constant_pos(nc) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS);
|
||||
append(class_idx);
|
||||
} break;
|
||||
case GDScriptDataType::GDSCRIPT:
|
||||
case GDScriptDataType::SCRIPT: {
|
||||
Variant script = function->return_type.script_type;
|
||||
int script_idx = get_constant_pos(script);
|
||||
script_idx |= (GDScriptFunction::ADDR_TYPE_LOCAL_CONSTANT << GDScriptFunction::ADDR_BITS);
|
||||
int script_idx = get_constant_pos(script) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS);
|
||||
|
||||
append(GDScriptFunction::OPCODE_RETURN_TYPED_SCRIPT, 2);
|
||||
append(p_return_value);
|
||||
|
|
|
@ -51,11 +51,11 @@ class GDScriptByteCodeGenerator : public GDScriptCodeGenerator {
|
|||
List<Map<StringName, int>> block_identifier_stack;
|
||||
Map<StringName, int> block_identifiers;
|
||||
|
||||
int current_stack_size = 0;
|
||||
int current_stack_size = 3; // First 3 spots are reserved for self, class, and nil.
|
||||
int current_temporaries = 0;
|
||||
int current_locals = 0;
|
||||
int current_line = 0;
|
||||
int stack_max = 0;
|
||||
int stack_max = 3;
|
||||
int instr_args_max = 0;
|
||||
int ptrcall_max = 0;
|
||||
|
||||
|
@ -135,7 +135,7 @@ class GDScriptByteCodeGenerator : public GDScriptCodeGenerator {
|
|||
ERR_PRINT("Leaving block with non-zero temporary variables: " + itos(current_temporaries));
|
||||
}
|
||||
#endif
|
||||
current_stack_size = current_locals;
|
||||
current_stack_size = current_locals + 3; // Keep the 3 reserved slots for self, class, and nil.
|
||||
|
||||
if (debug_stack) {
|
||||
for (Map<StringName, int>::Element *E = block_identifiers.front(); E; E = E->next()) {
|
||||
|
@ -300,26 +300,19 @@ class GDScriptByteCodeGenerator : public GDScriptCodeGenerator {
|
|||
int address_of(const Address &p_address) {
|
||||
switch (p_address.mode) {
|
||||
case Address::SELF:
|
||||
return GDScriptFunction::ADDR_TYPE_SELF << GDScriptFunction::ADDR_BITS;
|
||||
return GDScriptFunction::ADDR_SELF;
|
||||
case Address::CLASS:
|
||||
return GDScriptFunction::ADDR_TYPE_CLASS << GDScriptFunction::ADDR_BITS;
|
||||
return GDScriptFunction::ADDR_CLASS;
|
||||
case Address::MEMBER:
|
||||
return p_address.address | (GDScriptFunction::ADDR_TYPE_MEMBER << GDScriptFunction::ADDR_BITS);
|
||||
case Address::CLASS_CONSTANT:
|
||||
return p_address.address | (GDScriptFunction::ADDR_TYPE_CLASS_CONSTANT << GDScriptFunction::ADDR_BITS);
|
||||
case Address::LOCAL_CONSTANT:
|
||||
case Address::CONSTANT:
|
||||
return p_address.address | (GDScriptFunction::ADDR_TYPE_LOCAL_CONSTANT << GDScriptFunction::ADDR_BITS);
|
||||
return p_address.address | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS);
|
||||
case Address::LOCAL_VARIABLE:
|
||||
case Address::TEMPORARY:
|
||||
case Address::FUNCTION_PARAMETER:
|
||||
return p_address.address | (GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS);
|
||||
case Address::GLOBAL:
|
||||
return p_address.address | (GDScriptFunction::ADDR_TYPE_GLOBAL << GDScriptFunction::ADDR_BITS);
|
||||
case Address::NAMED_GLOBAL:
|
||||
return p_address.address | (GDScriptFunction::ADDR_TYPE_NAMED_GLOBAL << GDScriptFunction::ADDR_BITS);
|
||||
case Address::NIL:
|
||||
return GDScriptFunction::ADDR_TYPE_NIL << GDScriptFunction::ADDR_BITS;
|
||||
return GDScriptFunction::ADDR_NIL;
|
||||
}
|
||||
return -1; // Unreachable.
|
||||
}
|
||||
|
@ -441,6 +434,7 @@ public:
|
|||
virtual void write_assign_true(const Address &p_target) override;
|
||||
virtual void write_assign_false(const Address &p_target) override;
|
||||
virtual void write_assign_default_parameter(const Address &p_dst, const Address &p_src) override;
|
||||
virtual void write_store_named_global(const Address &p_dst, const StringName &p_global) override;
|
||||
virtual void write_cast(const Address &p_target, const Address &p_source, const GDScriptDataType &p_type) override;
|
||||
virtual void write_call(const Address &p_target, const Address &p_base, const StringName &p_function_name, const Vector<Address> &p_arguments) override;
|
||||
virtual void write_super_call(const Address &p_target, const StringName &p_function_name, const Vector<Address> &p_arguments) override;
|
||||
|
|
|
@ -45,13 +45,9 @@ public:
|
|||
CLASS,
|
||||
MEMBER,
|
||||
CONSTANT,
|
||||
CLASS_CONSTANT,
|
||||
LOCAL_CONSTANT,
|
||||
LOCAL_VARIABLE,
|
||||
FUNCTION_PARAMETER,
|
||||
TEMPORARY,
|
||||
GLOBAL,
|
||||
NAMED_GLOBAL,
|
||||
NIL,
|
||||
};
|
||||
AddressMode mode = NIL;
|
||||
|
@ -123,6 +119,7 @@ public:
|
|||
virtual void write_assign_true(const Address &p_target) = 0;
|
||||
virtual void write_assign_false(const Address &p_target) = 0;
|
||||
virtual void write_assign_default_parameter(const Address &dst, const Address &src) = 0;
|
||||
virtual void write_store_named_global(const Address &p_dst, const StringName &p_global) = 0;
|
||||
virtual void write_cast(const Address &p_target, const Address &p_source, const GDScriptDataType &p_type) = 0;
|
||||
virtual void write_call(const Address &p_target, const Address &p_base, const StringName &p_function_name, const Vector<Address> &p_arguments) = 0;
|
||||
virtual void write_super_call(const Address &p_target, const StringName &p_function_name, const Vector<Address> &p_arguments) = 0;
|
||||
|
|
|
@ -262,7 +262,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
|
|||
GDScriptNativeClass *nc = nullptr;
|
||||
while (scr) {
|
||||
if (scr->constants.has(identifier)) {
|
||||
return GDScriptCodeGenerator::Address(GDScriptCodeGenerator::Address::CLASS_CONSTANT, gen->add_or_get_name(identifier)); // TODO: Get type here.
|
||||
return codegen.add_constant(scr->constants[identifier]); // TODO: Get type here.
|
||||
}
|
||||
if (scr->native.is_valid()) {
|
||||
nc = scr->native.ptr();
|
||||
|
@ -319,7 +319,8 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
|
|||
|
||||
if (GDScriptLanguage::get_singleton()->get_global_map().has(identifier)) {
|
||||
int idx = GDScriptLanguage::get_singleton()->get_global_map()[identifier];
|
||||
return GDScriptCodeGenerator::Address(GDScriptCodeGenerator::Address::GLOBAL, idx); // TODO: Get type.
|
||||
Variant global = GDScriptLanguage::get_singleton()->get_global_array()[idx];
|
||||
return codegen.add_constant(global); // TODO: Get type.
|
||||
}
|
||||
|
||||
// Try global classes.
|
||||
|
@ -347,7 +348,9 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
|
|||
|
||||
#ifdef TOOLS_ENABLED
|
||||
if (GDScriptLanguage::get_singleton()->get_named_globals_map().has(identifier)) {
|
||||
return GDScriptCodeGenerator::Address(GDScriptCodeGenerator::Address::NAMED_GLOBAL, gen->add_or_get_name(identifier)); // TODO: Get type.
|
||||
GDScriptCodeGenerator::Address global = codegen.add_temporary(); // TODO: Get type.
|
||||
gen->write_store_named_global(global, identifier);
|
||||
return global;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -61,7 +61,7 @@ class GDScriptCompiler {
|
|||
|
||||
GDScriptCodeGenerator::Address add_local_constant(const StringName &p_name, const Variant &p_value) {
|
||||
uint32_t addr = generator->add_local_constant(p_name, p_value);
|
||||
locals[p_name] = GDScriptCodeGenerator::Address(GDScriptCodeGenerator::Address::LOCAL_CONSTANT, addr);
|
||||
locals[p_name] = GDScriptCodeGenerator::Address(GDScriptCodeGenerator::Address::CONSTANT, addr);
|
||||
return locals[p_name];
|
||||
}
|
||||
|
||||
|
|
|
@ -69,35 +69,23 @@ static String _disassemble_address(const GDScript *p_script, const GDScriptFunct
|
|||
int addr = p_address & GDScriptFunction::ADDR_MASK;
|
||||
|
||||
switch (p_address >> GDScriptFunction::ADDR_BITS) {
|
||||
case GDScriptFunction::ADDR_TYPE_SELF: {
|
||||
return "self";
|
||||
} break;
|
||||
case GDScriptFunction::ADDR_TYPE_CLASS: {
|
||||
return "class";
|
||||
} break;
|
||||
case GDScriptFunction::ADDR_TYPE_MEMBER: {
|
||||
return "member(" + p_script->debug_get_member_by_index(addr) + ")";
|
||||
} break;
|
||||
case GDScriptFunction::ADDR_TYPE_CLASS_CONSTANT: {
|
||||
return "class_const(" + p_function.get_global_name(addr) + ")";
|
||||
} break;
|
||||
case GDScriptFunction::ADDR_TYPE_LOCAL_CONSTANT: {
|
||||
case GDScriptFunction::ADDR_TYPE_CONSTANT: {
|
||||
return "const(" + _get_variant_string(p_function.get_constant(addr)) + ")";
|
||||
} break;
|
||||
case GDScriptFunction::ADDR_TYPE_STACK: {
|
||||
return "stack(" + itos(addr) + ")";
|
||||
} break;
|
||||
case GDScriptFunction::ADDR_TYPE_STACK_VARIABLE: {
|
||||
return "var_stack(" + itos(addr) + ")";
|
||||
} break;
|
||||
case GDScriptFunction::ADDR_TYPE_GLOBAL: {
|
||||
return "global(" + _get_variant_string(GDScriptLanguage::get_singleton()->get_global_array()[addr]) + ")";
|
||||
} break;
|
||||
case GDScriptFunction::ADDR_TYPE_NAMED_GLOBAL: {
|
||||
return "named_global(" + p_function.get_global_name(addr) + ")";
|
||||
} break;
|
||||
case GDScriptFunction::ADDR_TYPE_NIL: {
|
||||
return "nil";
|
||||
switch (addr) {
|
||||
case GDScriptFunction::ADDR_STACK_SELF:
|
||||
return "self";
|
||||
case GDScriptFunction::ADDR_STACK_CLASS:
|
||||
return "class";
|
||||
case GDScriptFunction::ADDR_STACK_NIL:
|
||||
return "nil";
|
||||
default:
|
||||
return "stack(" + itos(addr) + ")";
|
||||
}
|
||||
} break;
|
||||
}
|
||||
|
||||
|
@ -885,6 +873,14 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const {
|
|||
incr += 5;
|
||||
} break;
|
||||
DISASSEMBLE_ITERATE_TYPES(DISASSEMBLE_ITERATE);
|
||||
case OPCODE_STORE_NAMED_GLOBAL: {
|
||||
text += "store named global ";
|
||||
text += DADDR(1);
|
||||
text += " = ";
|
||||
text += String(_global_names_ptr[_code_ptr[ip + 2]]);
|
||||
|
||||
incr += 3;
|
||||
} break;
|
||||
case OPCODE_LINE: {
|
||||
int line = _code_ptr[ip + 1] - 1;
|
||||
if (line >= 0 && line < p_code_lines.size()) {
|
||||
|
|
|
@ -350,6 +350,7 @@ public:
|
|||
OPCODE_ITERATE_PACKED_VECTOR3_ARRAY,
|
||||
OPCODE_ITERATE_PACKED_COLOR_ARRAY,
|
||||
OPCODE_ITERATE_OBJECT,
|
||||
OPCODE_STORE_NAMED_GLOBAL,
|
||||
OPCODE_ASSERT,
|
||||
OPCODE_BREAKPOINT,
|
||||
OPCODE_LINE,
|
||||
|
@ -360,16 +361,18 @@ public:
|
|||
ADDR_BITS = 24,
|
||||
ADDR_MASK = ((1 << ADDR_BITS) - 1),
|
||||
ADDR_TYPE_MASK = ~ADDR_MASK,
|
||||
ADDR_TYPE_SELF = 0,
|
||||
ADDR_TYPE_CLASS = 1,
|
||||
ADDR_TYPE_STACK = 0,
|
||||
ADDR_TYPE_CONSTANT = 1,
|
||||
ADDR_TYPE_MEMBER = 2,
|
||||
ADDR_TYPE_CLASS_CONSTANT = 3,
|
||||
ADDR_TYPE_LOCAL_CONSTANT = 4,
|
||||
ADDR_TYPE_STACK = 5,
|
||||
ADDR_TYPE_STACK_VARIABLE = 6,
|
||||
ADDR_TYPE_GLOBAL = 7,
|
||||
ADDR_TYPE_NAMED_GLOBAL = 8,
|
||||
ADDR_TYPE_NIL = 9
|
||||
};
|
||||
|
||||
enum FixedAddresses {
|
||||
ADDR_STACK_SELF = 0,
|
||||
ADDR_STACK_CLASS = 1,
|
||||
ADDR_STACK_NIL = 2,
|
||||
ADDR_SELF = ADDR_STACK_SELF | (ADDR_TYPE_STACK << ADDR_BITS),
|
||||
ADDR_CLASS = ADDR_STACK_CLASS | (ADDR_TYPE_STACK << ADDR_BITS),
|
||||
ADDR_NIL = ADDR_STACK_NIL | (ADDR_TYPE_STACK << ADDR_BITS),
|
||||
};
|
||||
|
||||
enum Instruction {
|
||||
|
@ -462,7 +465,7 @@ private:
|
|||
|
||||
List<StackDebug> stack_debug;
|
||||
|
||||
_FORCE_INLINE_ Variant *_get_variant(int p_address, GDScriptInstance *p_instance, GDScript *p_script, Variant &self, Variant &static_ref, Variant *p_stack, String &r_error) const;
|
||||
_FORCE_INLINE_ Variant *_get_variant(int p_address, GDScriptInstance *p_instance, Variant *p_stack, String &r_error) const;
|
||||
_FORCE_INLINE_ String _get_call_error(const Callable::CallError &p_err, const String &p_where, const Variant **argptrs) const;
|
||||
|
||||
friend class GDScriptLanguage;
|
||||
|
@ -497,7 +500,6 @@ public:
|
|||
#endif
|
||||
Vector<uint8_t> stack;
|
||||
int stack_size = 0;
|
||||
Variant self;
|
||||
uint32_t alloca_size = 0;
|
||||
int ip = 0;
|
||||
int line = 0;
|
||||
|
|
|
@ -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;
|
||||
// Add 3 here for self, class, and nil.
|
||||
alloca_size = sizeof(Variant *) * 3 + sizeof(Variant *) * _instruction_args_size + sizeof(Variant) * _stack_size;
|
||||
|
||||
if (alloca_size) {
|
||||
uint8_t *aptr = (uint8_t *)alloca(alloca_size);
|
||||
uint8_t *aptr = (uint8_t *)alloca(alloca_size);
|
||||
stack = (Variant *)aptr;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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];
|
||||
} else {
|
||||
instruction_args = nullptr;
|
||||
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 {
|
||||
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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue