diff options
author | George Marques <george@gmarqu.es> | 2020-11-18 11:37:08 -0300 |
---|---|---|
committer | George Marques <george@gmarqu.es> | 2020-11-21 13:30:17 -0300 |
commit | 5518e2a68e36fe8a9dcf1531228a7b3cc4411263 (patch) | |
tree | d0790c288e54056f5a480d43fe88819535c1fa39 | |
parent | e0dca3c6b6f0a4dc0126c45873ff4c8c30e2d8a0 (diff) |
GDScript: Add faster instruction for validated constructor
Only for built-in types.
-rw-r--r-- | modules/gdscript/gdscript_byte_codegen.cpp | 54 | ||||
-rw-r--r-- | modules/gdscript/gdscript_byte_codegen.h | 14 | ||||
-rw-r--r-- | modules/gdscript/gdscript_disassembler.cpp | 19 | ||||
-rw-r--r-- | modules/gdscript/gdscript_function.h | 6 | ||||
-rw-r--r-- | modules/gdscript/gdscript_vm.cpp | 22 |
5 files changed, 112 insertions, 3 deletions
diff --git a/modules/gdscript/gdscript_byte_codegen.cpp b/modules/gdscript/gdscript_byte_codegen.cpp index 5772f8bce3..5f1c738207 100644 --- a/modules/gdscript/gdscript_byte_codegen.cpp +++ b/modules/gdscript/gdscript_byte_codegen.cpp @@ -244,7 +244,7 @@ GDScriptFunction *GDScriptByteCodeGenerator::write_end() { if (builtin_method_map.size()) { function->builtin_methods.resize(builtin_method_map.size()); - function->_builtin_methods_ptr = function->builtin_methods.ptrw(); + function->_builtin_methods_ptr = function->builtin_methods.ptr(); function->_builtin_methods_count = builtin_method_map.size(); for (const Map<Variant::ValidatedBuiltInMethod, int>::Element *E = builtin_method_map.front(); E; E = E->next()) { function->builtin_methods.write[E->get()] = E->key(); @@ -254,6 +254,18 @@ GDScriptFunction *GDScriptByteCodeGenerator::write_end() { function->_builtin_methods_count = 0; } + if (constructors_map.size()) { + function->constructors.resize(constructors_map.size()); + function->_constructors_ptr = function->constructors.ptr(); + function->_constructors_count = constructors_map.size(); + for (const Map<Variant::ValidatedConstructor, int>::Element *E = constructors_map.front(); E; E = E->next()) { + function->constructors.write[E->get()] = E->key(); + } + } else { + function->_constructors_ptr = nullptr; + function->_constructors_count = 0; + } + if (method_bind_map.size()) { function->methods.resize(method_bind_map.size()); function->_methods_ptr = function->methods.ptrw(); @@ -797,6 +809,46 @@ void GDScriptByteCodeGenerator::write_call_script_function(const Address &p_targ } void GDScriptByteCodeGenerator::write_construct(const Address &p_target, Variant::Type p_type, const Vector<Address> &p_arguments) { + // Try to find an appropriate constructor. + bool all_have_type = true; + Vector<Variant::Type> arg_types; + for (int i = 0; i < p_arguments.size(); i++) { + if (!HAS_BUILTIN_TYPE(p_arguments[i])) { + all_have_type = false; + break; + } + arg_types.push_back(p_arguments[i].type.builtin_type); + } + if (all_have_type) { + int valid_constructor = -1; + for (int i = 0; i < Variant::get_constructor_count(p_type); i++) { + if (Variant::get_constructor_argument_count(p_type, i) != p_arguments.size()) { + continue; + } + int types_correct = true; + for (int j = 0; j < arg_types.size(); j++) { + if (arg_types[j] != Variant::get_constructor_argument_type(p_type, i, j)) { + types_correct = false; + break; + } + } + if (types_correct) { + valid_constructor = i; + break; + } + } + if (valid_constructor >= 0) { + append(GDScriptFunction::OPCODE_CONSTRUCT_VALIDATED, 1 + p_arguments.size()); + for (int i = 0; i < p_arguments.size(); i++) { + append(p_arguments[i]); + } + append(p_target); + append(p_arguments.size()); + append(Variant::get_validated_constructor(p_type, valid_constructor)); + return; + } + } + append(GDScriptFunction::OPCODE_CONSTRUCT, 1 + p_arguments.size()); for (int i = 0; i < p_arguments.size(); i++) { append(p_arguments[i]); diff --git a/modules/gdscript/gdscript_byte_codegen.h b/modules/gdscript/gdscript_byte_codegen.h index cced0ecabe..a546920fb2 100644 --- a/modules/gdscript/gdscript_byte_codegen.h +++ b/modules/gdscript/gdscript_byte_codegen.h @@ -69,6 +69,7 @@ class GDScriptByteCodeGenerator : public GDScriptCodeGenerator { Map<Variant::ValidatedIndexedSetter, int> indexed_setters_map; Map<Variant::ValidatedIndexedGetter, int> indexed_getters_map; Map<Variant::ValidatedBuiltInMethod, int> builtin_method_map; + Map<Variant::ValidatedConstructor, int> constructors_map; Map<MethodBind *, int> method_bind_map; List<int> if_jmp_addrs; // List since this can be nested. @@ -211,6 +212,15 @@ class GDScriptByteCodeGenerator : public GDScriptCodeGenerator { return pos; } + int get_constructor_pos(const Variant::ValidatedConstructor p_constructor) { + if (constructors_map.has(p_constructor)) { + return constructors_map[p_constructor]; + } + int pos = constructors_map.size(); + constructors_map[p_constructor] = pos; + return pos; + } + int get_method_bind_pos(MethodBind *p_method) { if (method_bind_map.has(p_method)) { return method_bind_map[p_method]; @@ -312,6 +322,10 @@ class GDScriptByteCodeGenerator : public GDScriptCodeGenerator { opcodes.push_back(get_builtin_method_pos(p_method)); } + void append(const Variant::ValidatedConstructor p_constructor) { + opcodes.push_back(get_constructor_pos(p_constructor)); + } + void append(MethodBind *p_method) { opcodes.push_back(get_method_bind_pos(p_method)); } diff --git a/modules/gdscript/gdscript_disassembler.cpp b/modules/gdscript/gdscript_disassembler.cpp index 9f224108a7..c918251772 100644 --- a/modules/gdscript/gdscript_disassembler.cpp +++ b/modules/gdscript/gdscript_disassembler.cpp @@ -384,7 +384,7 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const { } break; case OPCODE_CONSTRUCT: { Variant::Type t = Variant::Type(_code_ptr[ip + 3 + instr_var_args]); - int argc = _code_ptr[ip + 2 + instr_var_args]; + int argc = _code_ptr[ip + 1 + instr_var_args]; text += "construct "; text += DADDR(1 + argc); @@ -400,6 +400,23 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const { incr = 3 + instr_var_args; } break; + case OPCODE_CONSTRUCT_VALIDATED: { + int argc = _code_ptr[ip + 1 + instr_var_args]; + + text += "construct validated "; + text += DADDR(1 + argc); + text += " = "; + + text += "<unkown type>("; + for (int i = 0; i < argc; i++) { + if (i > 0) + text += ", "; + text += DADDR(i + 1); + } + text += ")"; + + incr = 3 + instr_var_args; + } break; case OPCODE_CONSTRUCT_ARRAY: { int argc = _code_ptr[ip + 1 + instr_var_args]; text += " make_array "; diff --git a/modules/gdscript/gdscript_function.h b/modules/gdscript/gdscript_function.h index 3fb63f1297..bb5cc1284d 100644 --- a/modules/gdscript/gdscript_function.h +++ b/modules/gdscript/gdscript_function.h @@ -183,7 +183,8 @@ public: OPCODE_CAST_TO_BUILTIN, OPCODE_CAST_TO_NATIVE, OPCODE_CAST_TO_SCRIPT, - OPCODE_CONSTRUCT, //only for basic types!! + OPCODE_CONSTRUCT, // Only for basic types! + OPCODE_CONSTRUCT_VALIDATED, // Only for basic types! OPCODE_CONSTRUCT_ARRAY, OPCODE_CONSTRUCT_DICTIONARY, OPCODE_CALL, @@ -341,6 +342,8 @@ private: const Variant::ValidatedIndexedGetter *_indexed_getters_ptr = nullptr; int _builtin_methods_count = 0; const Variant::ValidatedBuiltInMethod *_builtin_methods_ptr = nullptr; + int _constructors_count = 0; + const Variant::ValidatedConstructor *_constructors_ptr = nullptr; int _methods_count = 0; MethodBind **_methods_ptr = nullptr; const int *_code_ptr = nullptr; @@ -368,6 +371,7 @@ private: Vector<Variant::ValidatedIndexedSetter> indexed_setters; Vector<Variant::ValidatedIndexedGetter> indexed_getters; Vector<Variant::ValidatedBuiltInMethod> builtin_methods; + Vector<Variant::ValidatedConstructor> constructors; Vector<MethodBind *> methods; Vector<int> code; Vector<GDScriptDataType> argument_types; diff --git a/modules/gdscript/gdscript_vm.cpp b/modules/gdscript/gdscript_vm.cpp index 04cd41ed6b..7c8bfcd944 100644 --- a/modules/gdscript/gdscript_vm.cpp +++ b/modules/gdscript/gdscript_vm.cpp @@ -214,6 +214,7 @@ String GDScriptFunction::_get_call_error(const Callable::CallError &p_err, const &&OPCODE_CAST_TO_NATIVE, \ &&OPCODE_CAST_TO_SCRIPT, \ &&OPCODE_CONSTRUCT, \ + &&OPCODE_CONSTRUCT_VALIDATED, \ &&OPCODE_CONSTRUCT_ARRAY, \ &&OPCODE_CONSTRUCT_DICTIONARY, \ &&OPCODE_CALL, \ @@ -1276,6 +1277,27 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a } DISPATCH_OPCODE; + OPCODE(OPCODE_CONSTRUCT_VALIDATED) { + CHECK_SPACE(2 + instr_arg_count); + + ip += instr_arg_count; + + int argc = _code_ptr[ip + 1]; + + int constructor_idx = _code_ptr[ip + 2]; + GD_ERR_BREAK(constructor_idx < 0 || constructor_idx >= _constructors_count); + Variant::ValidatedConstructor constructor = _constructors_ptr[constructor_idx]; + + Variant **argptrs = instruction_args; + + GET_INSTRUCTION_ARG(dst, argc); + + constructor(*dst, (const Variant **)argptrs); + + ip += 3; + } + DISPATCH_OPCODE; + OPCODE(OPCODE_CONSTRUCT_ARRAY) { CHECK_SPACE(1 + instr_arg_count); ip += instr_arg_count; |