Merge pull request #47727 from vnen/gdscript-less-addressing
Reduce number of addressing modes in GDScript VM
This commit is contained in:
commit
3aadbec23a
8 changed files with 129 additions and 194 deletions
|
|
@ -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…
Add table
Add a link
Reference in a new issue