From c707d6fe717c43fecafa0aca53182f214268ec16 Mon Sep 17 00:00:00 2001 From: George Marques Date: Fri, 13 Nov 2020 10:31:14 -0300 Subject: GDScript: Gather instructions arguments beforehand Almost all instructions need variant arguments. With this change they are loaded in an array before each instruction call. This makes the addressing code be localized to less places, improving compilation overhead and binary size by a small margin. This should not affect performance. --- modules/gdscript/gdscript_byte_codegen.h | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'modules/gdscript/gdscript_byte_codegen.h') diff --git a/modules/gdscript/gdscript_byte_codegen.h b/modules/gdscript/gdscript_byte_codegen.h index 62438b6dd2..e8d7de21c2 100644 --- a/modules/gdscript/gdscript_byte_codegen.h +++ b/modules/gdscript/gdscript_byte_codegen.h @@ -33,6 +33,8 @@ #include "gdscript_codegen.h" +#include "gdscript_function.h" + class GDScriptByteCodeGenerator : public GDScriptCodeGenerator { bool ended = false; GDScriptFunction *function = nullptr; @@ -57,7 +59,7 @@ class GDScriptByteCodeGenerator : public GDScriptCodeGenerator { #endif int current_line = 0; int stack_max = 0; - int call_max = 0; + int instr_args_max = 0; List if_jmp_addrs; // List since this can be nested. List for_jmp_addrs; @@ -139,11 +141,6 @@ class GDScriptByteCodeGenerator : public GDScriptCodeGenerator { stack_max = p_level + 1; } - void alloc_call(int p_params) { - if (p_params >= call_max) - call_max = p_params; - } - int increase_stack() { int top = current_stack_size++; alloc_stack(current_stack_size); @@ -177,8 +174,13 @@ class GDScriptByteCodeGenerator : public GDScriptCodeGenerator { return -1; // Unreachable. } - void append(int code) { - opcodes.push_back(code); + void append(GDScriptFunction::Opcode p_code, int p_argument_count) { + opcodes.push_back((p_code & GDScriptFunction::INSTR_MASK) | (p_argument_count << GDScriptFunction::INSTR_BITS)); + instr_args_max = MAX(instr_args_max, p_argument_count); + } + + void append(int p_code) { + opcodes.push_back(p_code); } void append(const Address &p_address) { -- cgit v1.2.3 From 1ad5c926dc4d7a182b8621f360b7ce4697dffb25 Mon Sep 17 00:00:00 2001 From: George Marques Date: Fri, 13 Nov 2020 16:47:45 -0300 Subject: GDScript: Add faster operator for known types It now uses the direct operator function pointer, which increases performance in evaluation. --- modules/gdscript/gdscript_byte_codegen.h | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) (limited to 'modules/gdscript/gdscript_byte_codegen.h') diff --git a/modules/gdscript/gdscript_byte_codegen.h b/modules/gdscript/gdscript_byte_codegen.h index e8d7de21c2..cce17793f4 100644 --- a/modules/gdscript/gdscript_byte_codegen.h +++ b/modules/gdscript/gdscript_byte_codegen.h @@ -51,15 +51,16 @@ class GDScriptByteCodeGenerator : public GDScriptCodeGenerator { int current_stack_size = 0; int current_temporaries = 0; + int current_line = 0; + int stack_max = 0; + int instr_args_max = 0; HashMap constant_map; Map name_map; #ifdef TOOLS_ENABLED Vector named_globals; #endif - int current_line = 0; - int stack_max = 0; - int instr_args_max = 0; + Map operator_func_map; List if_jmp_addrs; // List since this can be nested. List for_jmp_addrs; @@ -136,6 +137,14 @@ class GDScriptByteCodeGenerator : public GDScriptCodeGenerator { return pos; } + int get_operation_pos(const Variant::ValidatedOperatorEvaluator p_operation) { + if (operator_func_map.has(p_operation)) + return operator_func_map[p_operation]; + int pos = operator_func_map.size(); + operator_func_map[p_operation] = pos; + return pos; + } + void alloc_stack(int p_level) { if (p_level >= stack_max) stack_max = p_level + 1; @@ -191,6 +200,10 @@ class GDScriptByteCodeGenerator : public GDScriptCodeGenerator { opcodes.push_back(get_name_map_pos(p_name)); } + void append(const Variant::ValidatedOperatorEvaluator p_operation) { + opcodes.push_back(get_operation_pos(p_operation)); + } + void patch_jump(int p_address) { opcodes.write[p_address] = opcodes.size(); } -- cgit v1.2.3 From 5aeb390cd72d0068c4176ad49c4ccdb8ef127d1e Mon Sep 17 00:00:00 2001 From: George Marques Date: Mon, 16 Nov 2020 12:59:53 -0300 Subject: GDScript: Add speficic set/get instructions When the base type is known at compile-time, we can get a direct function pointer that is faster than the regular set/get paths. --- modules/gdscript/gdscript_byte_codegen.h | 78 ++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) (limited to 'modules/gdscript/gdscript_byte_codegen.h') diff --git a/modules/gdscript/gdscript_byte_codegen.h b/modules/gdscript/gdscript_byte_codegen.h index cce17793f4..afb568fd6b 100644 --- a/modules/gdscript/gdscript_byte_codegen.h +++ b/modules/gdscript/gdscript_byte_codegen.h @@ -61,6 +61,12 @@ class GDScriptByteCodeGenerator : public GDScriptCodeGenerator { Vector named_globals; #endif Map operator_func_map; + Map setters_map; + Map getters_map; + Map keyed_setters_map; + Map keyed_getters_map; + Map indexed_setters_map; + Map indexed_getters_map; List if_jmp_addrs; // List since this can be nested. List for_jmp_addrs; @@ -145,6 +151,54 @@ class GDScriptByteCodeGenerator : public GDScriptCodeGenerator { return pos; } + int get_setter_pos(const Variant::ValidatedSetter p_setter) { + if (setters_map.has(p_setter)) + return setters_map[p_setter]; + int pos = setters_map.size(); + setters_map[p_setter] = pos; + return pos; + } + + int get_getter_pos(const Variant::ValidatedGetter p_getter) { + if (getters_map.has(p_getter)) + return getters_map[p_getter]; + int pos = getters_map.size(); + getters_map[p_getter] = pos; + return pos; + } + + int get_keyed_setter_pos(const Variant::ValidatedKeyedSetter p_keyed_setter) { + if (keyed_setters_map.has(p_keyed_setter)) + return keyed_setters_map[p_keyed_setter]; + int pos = keyed_setters_map.size(); + keyed_setters_map[p_keyed_setter] = pos; + return pos; + } + + int get_keyed_getter_pos(const Variant::ValidatedKeyedGetter p_keyed_getter) { + if (keyed_getters_map.has(p_keyed_getter)) + return keyed_getters_map[p_keyed_getter]; + int pos = keyed_getters_map.size(); + keyed_getters_map[p_keyed_getter] = pos; + return pos; + } + + int get_indexed_setter_pos(const Variant::ValidatedIndexedSetter p_indexed_setter) { + if (indexed_setters_map.has(p_indexed_setter)) + return indexed_setters_map[p_indexed_setter]; + int pos = indexed_setters_map.size(); + indexed_setters_map[p_indexed_setter] = pos; + return pos; + } + + int get_indexed_getter_pos(const Variant::ValidatedIndexedGetter p_indexed_getter) { + if (indexed_getters_map.has(p_indexed_getter)) + return indexed_getters_map[p_indexed_getter]; + int pos = indexed_getters_map.size(); + indexed_getters_map[p_indexed_getter] = pos; + return pos; + } + void alloc_stack(int p_level) { if (p_level >= stack_max) stack_max = p_level + 1; @@ -204,6 +258,30 @@ class GDScriptByteCodeGenerator : public GDScriptCodeGenerator { opcodes.push_back(get_operation_pos(p_operation)); } + void append(const Variant::ValidatedSetter p_setter) { + opcodes.push_back(get_setter_pos(p_setter)); + } + + void append(const Variant::ValidatedGetter p_getter) { + opcodes.push_back(get_getter_pos(p_getter)); + } + + void append(const Variant::ValidatedKeyedSetter p_keyed_setter) { + opcodes.push_back(get_keyed_setter_pos(p_keyed_setter)); + } + + void append(const Variant::ValidatedKeyedGetter p_keyed_getter) { + opcodes.push_back(get_keyed_getter_pos(p_keyed_getter)); + } + + void append(const Variant::ValidatedIndexedSetter p_indexed_setter) { + opcodes.push_back(get_indexed_setter_pos(p_indexed_setter)); + } + + void append(const Variant::ValidatedIndexedGetter p_indexed_getter) { + opcodes.push_back(get_indexed_getter_pos(p_indexed_getter)); + } + void patch_jump(int p_address) { opcodes.write[p_address] = opcodes.size(); } -- cgit v1.2.3 From d8b22097f24685cd87a78a5a4fe37a3e8a21ed71 Mon Sep 17 00:00:00 2001 From: George Marques Date: Tue, 17 Nov 2020 10:44:52 -0300 Subject: GDScript: Add faster call instructions for native methods --- modules/gdscript/gdscript_byte_codegen.h | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) (limited to 'modules/gdscript/gdscript_byte_codegen.h') diff --git a/modules/gdscript/gdscript_byte_codegen.h b/modules/gdscript/gdscript_byte_codegen.h index afb568fd6b..9b43adcd73 100644 --- a/modules/gdscript/gdscript_byte_codegen.h +++ b/modules/gdscript/gdscript_byte_codegen.h @@ -54,6 +54,7 @@ class GDScriptByteCodeGenerator : public GDScriptCodeGenerator { int current_line = 0; int stack_max = 0; int instr_args_max = 0; + int ptrcall_max = 0; HashMap constant_map; Map name_map; @@ -67,6 +68,7 @@ class GDScriptByteCodeGenerator : public GDScriptCodeGenerator { Map keyed_getters_map; Map indexed_setters_map; Map indexed_getters_map; + Map method_bind_map; List if_jmp_addrs; // List since this can be nested. List for_jmp_addrs; @@ -199,6 +201,15 @@ class GDScriptByteCodeGenerator : public GDScriptCodeGenerator { return pos; } + int get_method_bind_pos(MethodBind *p_method) { + if (method_bind_map.has(p_method)) { + return method_bind_map[p_method]; + } + int pos = method_bind_map.size(); + method_bind_map[p_method] = pos; + return pos; + } + void alloc_stack(int p_level) { if (p_level >= stack_max) stack_max = p_level + 1; @@ -210,6 +221,11 @@ class GDScriptByteCodeGenerator : public GDScriptCodeGenerator { return top; } + void alloc_ptrcall(int p_params) { + if (p_params >= ptrcall_max) + ptrcall_max = p_params; + } + int address_of(const Address &p_address) { switch (p_address.mode) { case Address::SELF: @@ -282,6 +298,10 @@ class GDScriptByteCodeGenerator : public GDScriptCodeGenerator { opcodes.push_back(get_indexed_getter_pos(p_indexed_getter)); } + void append(MethodBind *p_method) { + opcodes.push_back(get_method_bind_pos(p_method)); + } + void patch_jump(int p_address) { opcodes.write[p_address] = opcodes.size(); } @@ -337,8 +357,8 @@ public: virtual void write_super_call(const Address &p_target, const StringName &p_function_name, const Vector
&p_arguments) override; virtual void write_call_async(const Address &p_target, const Address &p_base, const StringName &p_function_name, const Vector
&p_arguments) override; virtual void write_call_builtin(const Address &p_target, GDScriptFunctions::Function p_function, const Vector
&p_arguments) override; - virtual void write_call_method_bind(const Address &p_target, const Address &p_base, const MethodBind *p_method, const Vector
&p_arguments) override; - virtual void write_call_ptrcall(const Address &p_target, const Address &p_base, const MethodBind *p_method, const Vector
&p_arguments) override; + virtual void write_call_method_bind(const Address &p_target, const Address &p_base, MethodBind *p_method, const Vector
&p_arguments) override; + virtual void write_call_ptrcall(const Address &p_target, const Address &p_base, MethodBind *p_method, const Vector
&p_arguments) override; virtual void write_call_self(const Address &p_target, const StringName &p_function_name, const Vector
&p_arguments) override; virtual void write_call_script_function(const Address &p_target, const Address &p_base, const StringName &p_function_name, const Vector
&p_arguments) override; virtual void write_construct(const Address &p_target, Variant::Type p_type, const Vector
&p_arguments) override; -- cgit v1.2.3 From 52ab64db691e1359ae64ef0d61a8359a2c2a38be Mon Sep 17 00:00:00 2001 From: George Marques Date: Wed, 18 Nov 2020 10:32:28 -0300 Subject: GDScript: Add faster call instructions for builtin methods Methods from builtin types can be called by using the function pointer when the argument and base types are known at compile time. --- modules/gdscript/gdscript_byte_codegen.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'modules/gdscript/gdscript_byte_codegen.h') diff --git a/modules/gdscript/gdscript_byte_codegen.h b/modules/gdscript/gdscript_byte_codegen.h index 9b43adcd73..cced0ecabe 100644 --- a/modules/gdscript/gdscript_byte_codegen.h +++ b/modules/gdscript/gdscript_byte_codegen.h @@ -68,6 +68,7 @@ class GDScriptByteCodeGenerator : public GDScriptCodeGenerator { Map keyed_getters_map; Map indexed_setters_map; Map indexed_getters_map; + Map builtin_method_map; Map method_bind_map; List if_jmp_addrs; // List since this can be nested. @@ -201,6 +202,15 @@ class GDScriptByteCodeGenerator : public GDScriptCodeGenerator { return pos; } + int get_builtin_method_pos(const Variant::ValidatedBuiltInMethod p_method) { + if (builtin_method_map.has(p_method)) { + return builtin_method_map[p_method]; + } + int pos = builtin_method_map.size(); + builtin_method_map[p_method] = pos; + return pos; + } + int get_method_bind_pos(MethodBind *p_method) { if (method_bind_map.has(p_method)) { return method_bind_map[p_method]; @@ -298,6 +308,10 @@ class GDScriptByteCodeGenerator : public GDScriptCodeGenerator { opcodes.push_back(get_indexed_getter_pos(p_indexed_getter)); } + void append(const Variant::ValidatedBuiltInMethod p_method) { + opcodes.push_back(get_builtin_method_pos(p_method)); + } + void append(MethodBind *p_method) { opcodes.push_back(get_method_bind_pos(p_method)); } @@ -357,6 +371,7 @@ public: virtual void write_super_call(const Address &p_target, const StringName &p_function_name, const Vector
&p_arguments) override; virtual void write_call_async(const Address &p_target, const Address &p_base, const StringName &p_function_name, const Vector
&p_arguments) override; virtual void write_call_builtin(const Address &p_target, GDScriptFunctions::Function p_function, const Vector
&p_arguments) override; + virtual void write_call_builtin_type(const Address &p_target, const Address &p_base, Variant::Type p_type, const StringName &p_method, const Vector
&p_arguments) override; virtual void write_call_method_bind(const Address &p_target, const Address &p_base, MethodBind *p_method, const Vector
&p_arguments) override; virtual void write_call_ptrcall(const Address &p_target, const Address &p_base, MethodBind *p_method, const Vector
&p_arguments) override; virtual void write_call_self(const Address &p_target, const StringName &p_function_name, const Vector
&p_arguments) override; -- cgit v1.2.3 From 5518e2a68e36fe8a9dcf1531228a7b3cc4411263 Mon Sep 17 00:00:00 2001 From: George Marques Date: Wed, 18 Nov 2020 11:37:08 -0300 Subject: GDScript: Add faster instruction for validated constructor Only for built-in types. --- modules/gdscript/gdscript_byte_codegen.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'modules/gdscript/gdscript_byte_codegen.h') 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 indexed_setters_map; Map indexed_getters_map; Map builtin_method_map; + Map constructors_map; Map method_bind_map; List 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)); } -- cgit v1.2.3