From c707d6fe717c43fecafa0aca53182f214268ec16 Mon Sep 17 00:00:00 2001 From: George Marques Date: Fri, 13 Nov 2020 10:31:14 -0300 Subject: [PATCH] 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.cpp | 226 ++++++++-------- modules/gdscript/gdscript_byte_codegen.h | 18 +- modules/gdscript/gdscript_disassembler.cpp | 125 ++++----- modules/gdscript/gdscript_function.cpp | 20 +- modules/gdscript/gdscript_function.h | 58 ++-- modules/gdscript/gdscript_vm.cpp | 293 ++++++++++----------- 6 files changed, 360 insertions(+), 380 deletions(-) diff --git a/modules/gdscript/gdscript_byte_codegen.cpp b/modules/gdscript/gdscript_byte_codegen.cpp index cc9e87b8827..33e3909e90c 100644 --- a/modules/gdscript/gdscript_byte_codegen.cpp +++ b/modules/gdscript/gdscript_byte_codegen.cpp @@ -111,7 +111,7 @@ void GDScriptByteCodeGenerator::write_start(GDScript *p_script, const StringName } GDScriptFunction *GDScriptByteCodeGenerator::write_end() { - append(GDScriptFunction::OPCODE_END); + append(GDScriptFunction::OPCODE_END, 0); if (constant_map.size()) { function->_constant_count = constant_map.size(); @@ -162,7 +162,7 @@ GDScriptFunction *GDScriptByteCodeGenerator::write_end() { function->stack_debug = stack_debug; } function->_stack_size = stack_max; - function->_call_size = call_max; + function->_instruction_args_size = instr_args_max; ended = true; return function; @@ -179,36 +179,36 @@ void GDScriptByteCodeGenerator::set_initial_line(int p_line) { } void GDScriptByteCodeGenerator::write_operator(const Address &p_target, Variant::Operator p_operator, const Address &p_left_operand, const Address &p_right_operand) { - append(GDScriptFunction::OPCODE_OPERATOR); - append(p_operator); + append(GDScriptFunction::OPCODE_OPERATOR, 3); append(p_left_operand); append(p_right_operand); append(p_target); + append(p_operator); } void GDScriptByteCodeGenerator::write_type_test(const Address &p_target, const Address &p_source, const Address &p_type) { - append(GDScriptFunction::OPCODE_EXTENDS_TEST); + append(GDScriptFunction::OPCODE_EXTENDS_TEST, 3); append(p_source); append(p_type); append(p_target); } void GDScriptByteCodeGenerator::write_type_test_builtin(const Address &p_target, const Address &p_source, Variant::Type p_type) { - append(GDScriptFunction::OPCODE_IS_BUILTIN); + append(GDScriptFunction::OPCODE_IS_BUILTIN, 3); append(p_source); - append(p_type); append(p_target); + append(p_type); } void GDScriptByteCodeGenerator::write_and_left_operand(const Address &p_left_operand) { - append(GDScriptFunction::OPCODE_JUMP_IF_NOT); + append(GDScriptFunction::OPCODE_JUMP_IF_NOT, 1); append(p_left_operand); logic_op_jump_pos1.push_back(opcodes.size()); append(0); // Jump target, will be patched. } void GDScriptByteCodeGenerator::write_and_right_operand(const Address &p_right_operand) { - append(GDScriptFunction::OPCODE_JUMP_IF_NOT); + append(GDScriptFunction::OPCODE_JUMP_IF_NOT, 1); append(p_right_operand); logic_op_jump_pos2.push_back(opcodes.size()); append(0); // Jump target, will be patched. @@ -216,29 +216,29 @@ void GDScriptByteCodeGenerator::write_and_right_operand(const Address &p_right_o void GDScriptByteCodeGenerator::write_end_and(const Address &p_target) { // If here means both operands are true. - append(GDScriptFunction::OPCODE_ASSIGN_TRUE); + append(GDScriptFunction::OPCODE_ASSIGN_TRUE, 1); append(p_target); // Jump away from the fail condition. - append(GDScriptFunction::OPCODE_JUMP); + append(GDScriptFunction::OPCODE_JUMP, 0); append(opcodes.size() + 3); // Here it means one of operands is false. patch_jump(logic_op_jump_pos1.back()->get()); patch_jump(logic_op_jump_pos2.back()->get()); logic_op_jump_pos1.pop_back(); logic_op_jump_pos2.pop_back(); - append(GDScriptFunction::OPCODE_ASSIGN_FALSE); + append(GDScriptFunction::OPCODE_ASSIGN_FALSE, 0); append(p_target); } void GDScriptByteCodeGenerator::write_or_left_operand(const Address &p_left_operand) { - append(GDScriptFunction::OPCODE_JUMP_IF); + append(GDScriptFunction::OPCODE_JUMP_IF, 1); append(p_left_operand); logic_op_jump_pos1.push_back(opcodes.size()); append(0); // Jump target, will be patched. } void GDScriptByteCodeGenerator::write_or_right_operand(const Address &p_right_operand) { - append(GDScriptFunction::OPCODE_JUMP_IF); + append(GDScriptFunction::OPCODE_JUMP_IF, 1); append(p_right_operand); logic_op_jump_pos2.push_back(opcodes.size()); append(0); // Jump target, will be patched. @@ -246,17 +246,17 @@ void GDScriptByteCodeGenerator::write_or_right_operand(const Address &p_right_op void GDScriptByteCodeGenerator::write_end_or(const Address &p_target) { // If here means both operands are false. - append(GDScriptFunction::OPCODE_ASSIGN_FALSE); + append(GDScriptFunction::OPCODE_ASSIGN_FALSE, 1); append(p_target); // Jump away from the success condition. - append(GDScriptFunction::OPCODE_JUMP); + append(GDScriptFunction::OPCODE_JUMP, 0); append(opcodes.size() + 3); // Here it means one of operands is false. patch_jump(logic_op_jump_pos1.back()->get()); patch_jump(logic_op_jump_pos2.back()->get()); logic_op_jump_pos1.pop_back(); logic_op_jump_pos2.pop_back(); - append(GDScriptFunction::OPCODE_ASSIGN_TRUE); + append(GDScriptFunction::OPCODE_ASSIGN_TRUE, 1); append(p_target); } @@ -265,18 +265,18 @@ void GDScriptByteCodeGenerator::write_start_ternary(const Address &p_target) { } void GDScriptByteCodeGenerator::write_ternary_condition(const Address &p_condition) { - append(GDScriptFunction::OPCODE_JUMP_IF_NOT); + append(GDScriptFunction::OPCODE_JUMP_IF_NOT, 1); append(p_condition); ternary_jump_fail_pos.push_back(opcodes.size()); append(0); // Jump target, will be patched. } void GDScriptByteCodeGenerator::write_ternary_true_expr(const Address &p_expr) { - append(GDScriptFunction::OPCODE_ASSIGN); + append(GDScriptFunction::OPCODE_ASSIGN, 2); append(ternary_result.back()->get()); append(p_expr); // Jump away from the false path. - append(GDScriptFunction::OPCODE_JUMP); + append(GDScriptFunction::OPCODE_JUMP, 0); ternary_jump_skip_pos.push_back(opcodes.size()); append(0); // Fail must jump here. @@ -285,7 +285,7 @@ void GDScriptByteCodeGenerator::write_ternary_true_expr(const Address &p_expr) { } void GDScriptByteCodeGenerator::write_ternary_false_expr(const Address &p_expr) { - append(GDScriptFunction::OPCODE_ASSIGN); + append(GDScriptFunction::OPCODE_ASSIGN, 2); append(ternary_result.back()->get()); append(p_expr); } @@ -296,43 +296,43 @@ void GDScriptByteCodeGenerator::write_end_ternary() { } void GDScriptByteCodeGenerator::write_set(const Address &p_target, const Address &p_index, const Address &p_source) { - append(GDScriptFunction::OPCODE_SET); + append(GDScriptFunction::OPCODE_SET, 3); append(p_target); append(p_index); append(p_source); } void GDScriptByteCodeGenerator::write_get(const Address &p_target, const Address &p_index, const Address &p_source) { - append(GDScriptFunction::OPCODE_GET); + append(GDScriptFunction::OPCODE_GET, 3); append(p_source); append(p_index); append(p_target); } void GDScriptByteCodeGenerator::write_set_named(const Address &p_target, const StringName &p_name, const Address &p_source) { - append(GDScriptFunction::OPCODE_SET_NAMED); + append(GDScriptFunction::OPCODE_SET_NAMED, 2); append(p_target); - append(p_name); append(p_source); + append(p_name); } void GDScriptByteCodeGenerator::write_get_named(const Address &p_target, const StringName &p_name, const Address &p_source) { - append(GDScriptFunction::OPCODE_GET_NAMED); + append(GDScriptFunction::OPCODE_GET_NAMED, 2); append(p_source); - append(p_name); append(p_target); + append(p_name); } void GDScriptByteCodeGenerator::write_set_member(const Address &p_value, const StringName &p_name) { - append(GDScriptFunction::OPCODE_SET_MEMBER); - append(p_name); + append(GDScriptFunction::OPCODE_SET_MEMBER, 1); append(p_value); + append(p_name); } void GDScriptByteCodeGenerator::write_get_member(const Address &p_target, const StringName &p_name) { - append(GDScriptFunction::OPCODE_GET_MEMBER); - append(p_name); + append(GDScriptFunction::OPCODE_GET_MEMBER, 1); append(p_target); + append(p_name); } void GDScriptByteCodeGenerator::write_assign(const Address &p_target, const Address &p_source) { @@ -340,34 +340,35 @@ void GDScriptByteCodeGenerator::write_assign(const Address &p_target, const Addr // Typed assignment. switch (p_target.type.kind) { case GDScriptDataType::BUILTIN: { - append(GDScriptFunction::OPCODE_ASSIGN_TYPED_BUILTIN); - append(p_target.type.builtin_type); + append(GDScriptFunction::OPCODE_ASSIGN_TYPED_BUILTIN, 2); append(p_target); append(p_source); + append(p_target.type.builtin_type); } 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); - append(GDScriptFunction::OPCODE_ASSIGN_TYPED_NATIVE); - append(class_idx); + append(GDScriptFunction::OPCODE_ASSIGN_TYPED_NATIVE, 3); append(p_target); append(p_source); + append(class_idx); } break; 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); - append(GDScriptFunction::OPCODE_ASSIGN_TYPED_SCRIPT); - append(idx); + append(GDScriptFunction::OPCODE_ASSIGN_TYPED_SCRIPT, 3); append(p_target); append(p_source); + append(idx); } break; default: { ERR_PRINT("Compiler bug: unresolved assign."); // Shouldn't get here, but fail-safe to a regular assignment - append(GDScriptFunction::OPCODE_ASSIGN); + append(GDScriptFunction::OPCODE_ASSIGN, 2); append(p_target); append(p_source); } @@ -375,13 +376,13 @@ void GDScriptByteCodeGenerator::write_assign(const Address &p_target, const Addr } else { if (p_target.type.kind == GDScriptDataType::BUILTIN && p_source.type.kind == GDScriptDataType::BUILTIN && p_target.type.builtin_type != p_source.type.builtin_type) { // Need conversion.. - append(GDScriptFunction::OPCODE_ASSIGN_TYPED_BUILTIN); - append(p_target.type.builtin_type); + append(GDScriptFunction::OPCODE_ASSIGN_TYPED_BUILTIN, 2); append(p_target); append(p_source); + append(p_target.type.builtin_type); } else { // Either untyped assignment or already type-checked by the parser - append(GDScriptFunction::OPCODE_ASSIGN); + append(GDScriptFunction::OPCODE_ASSIGN, 2); append(p_target); append(p_source); } @@ -389,34 +390,37 @@ void GDScriptByteCodeGenerator::write_assign(const Address &p_target, const Addr } void GDScriptByteCodeGenerator::write_assign_true(const Address &p_target) { - append(GDScriptFunction::OPCODE_ASSIGN_TRUE); + append(GDScriptFunction::OPCODE_ASSIGN_TRUE, 1); append(p_target); } void GDScriptByteCodeGenerator::write_assign_false(const Address &p_target) { - append(GDScriptFunction::OPCODE_ASSIGN_FALSE); + append(GDScriptFunction::OPCODE_ASSIGN_FALSE, 1); append(p_target); } void GDScriptByteCodeGenerator::write_cast(const Address &p_target, const Address &p_source, const GDScriptDataType &p_type) { + int index = 0; + switch (p_type.kind) { case GDScriptDataType::BUILTIN: { - append(GDScriptFunction::OPCODE_CAST_TO_BUILTIN); - append(p_type.builtin_type); + append(GDScriptFunction::OPCODE_CAST_TO_BUILTIN, 2); + index = p_type.builtin_type; } 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); - append(GDScriptFunction::OPCODE_CAST_TO_NATIVE); - append(class_idx); + append(GDScriptFunction::OPCODE_CAST_TO_NATIVE, 3); + index = class_idx; } 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); - append(GDScriptFunction::OPCODE_CAST_TO_SCRIPT); - append(idx); + append(GDScriptFunction::OPCODE_CAST_TO_SCRIPT, 3); + index = idx; } break; default: { return; @@ -425,147 +429,139 @@ void GDScriptByteCodeGenerator::write_cast(const Address &p_target, const Addres append(p_source); append(p_target); + append(index); } void GDScriptByteCodeGenerator::write_call(const Address &p_target, const Address &p_base, const StringName &p_function_name, const Vector
&p_arguments) { - append(p_target.mode == Address::NIL ? GDScriptFunction::OPCODE_CALL : GDScriptFunction::OPCODE_CALL_RETURN); - append(p_arguments.size()); - append(p_base); - append(p_function_name); + append(p_target.mode == Address::NIL ? GDScriptFunction::OPCODE_CALL : GDScriptFunction::OPCODE_CALL_RETURN, 2 + p_arguments.size()); for (int i = 0; i < p_arguments.size(); i++) { append(p_arguments[i]); } + append(p_base); append(p_target); - alloc_call(p_arguments.size()); + append(p_arguments.size()); + append(p_function_name); } void GDScriptByteCodeGenerator::write_super_call(const Address &p_target, const StringName &p_function_name, const Vector
&p_arguments) { - append(GDScriptFunction::OPCODE_CALL_SELF_BASE); - append(p_function_name); - append(p_arguments.size()); + append(GDScriptFunction::OPCODE_CALL_SELF_BASE, 1 + p_arguments.size()); for (int i = 0; i < p_arguments.size(); i++) { append(p_arguments[i]); } append(p_target); - alloc_call(p_arguments.size()); + append(p_arguments.size()); + append(p_function_name); } void GDScriptByteCodeGenerator::write_call_async(const Address &p_target, const Address &p_base, const StringName &p_function_name, const Vector
&p_arguments) { - append(GDScriptFunction::OPCODE_CALL_ASYNC); - append(p_arguments.size()); - append(p_base); - append(p_function_name); + append(GDScriptFunction::OPCODE_CALL_ASYNC, 2 + p_arguments.size()); for (int i = 0; i < p_arguments.size(); i++) { append(p_arguments[i]); } + append(p_base); append(p_target); - alloc_call(p_arguments.size()); + append(p_arguments.size()); + append(p_function_name); } void GDScriptByteCodeGenerator::write_call_builtin(const Address &p_target, GDScriptFunctions::Function p_function, const Vector
&p_arguments) { - append(GDScriptFunction::OPCODE_CALL_BUILT_IN); - append(p_function); - append(p_arguments.size()); + append(GDScriptFunction::OPCODE_CALL_BUILT_IN, 1 + p_arguments.size()); for (int i = 0; i < p_arguments.size(); i++) { append(p_arguments[i]); } append(p_target); - alloc_call(p_arguments.size()); + append(p_arguments.size()); + append(p_function); } void GDScriptByteCodeGenerator::write_call_method_bind(const Address &p_target, const Address &p_base, const MethodBind *p_method, const Vector
&p_arguments) { - append(p_target.mode == Address::NIL ? GDScriptFunction::OPCODE_CALL : GDScriptFunction::OPCODE_CALL_RETURN); - append(p_arguments.size()); - append(p_base); - append(p_method->get_name()); + append(p_target.mode == Address::NIL ? GDScriptFunction::OPCODE_CALL : GDScriptFunction::OPCODE_CALL_RETURN, 2 + p_arguments.size()); for (int i = 0; i < p_arguments.size(); i++) { append(p_arguments[i]); } + append(p_base); append(p_target); - alloc_call(p_arguments.size()); + append(p_arguments.size()); + append(p_method->get_name()); } void GDScriptByteCodeGenerator::write_call_ptrcall(const Address &p_target, const Address &p_base, const MethodBind *p_method, const Vector
&p_arguments) { - append(p_target.mode == Address::NIL ? GDScriptFunction::OPCODE_CALL : GDScriptFunction::OPCODE_CALL_RETURN); - append(p_arguments.size()); - append(p_base); - append(p_method->get_name()); + append(p_target.mode == Address::NIL ? GDScriptFunction::OPCODE_CALL : GDScriptFunction::OPCODE_CALL_RETURN, 2 + p_arguments.size()); for (int i = 0; i < p_arguments.size(); i++) { append(p_arguments[i]); } + append(p_base); append(p_target); - alloc_call(p_arguments.size()); + append(p_arguments.size()); + append(p_method->get_name()); } void GDScriptByteCodeGenerator::write_call_self(const Address &p_target, const StringName &p_function_name, const Vector
&p_arguments) { - append(p_target.mode == Address::NIL ? GDScriptFunction::OPCODE_CALL : GDScriptFunction::OPCODE_CALL_RETURN); - append(p_arguments.size()); - append(GDScriptFunction::ADDR_TYPE_SELF << GDScriptFunction::ADDR_BITS); - append(p_function_name); + append(p_target.mode == Address::NIL ? GDScriptFunction::OPCODE_CALL : GDScriptFunction::OPCODE_CALL_RETURN, 2 + p_arguments.size()); for (int i = 0; i < p_arguments.size(); i++) { append(p_arguments[i]); } + append(GDScriptFunction::ADDR_TYPE_SELF << GDScriptFunction::ADDR_BITS); append(p_target); - alloc_call(p_arguments.size()); + append(p_arguments.size()); + append(p_function_name); } void GDScriptByteCodeGenerator::write_call_script_function(const Address &p_target, const Address &p_base, const StringName &p_function_name, const Vector
&p_arguments) { - append(p_target.mode == Address::NIL ? GDScriptFunction::OPCODE_CALL : GDScriptFunction::OPCODE_CALL_RETURN); - append(p_arguments.size()); - append(p_base); - append(p_function_name); + append(p_target.mode == Address::NIL ? GDScriptFunction::OPCODE_CALL : GDScriptFunction::OPCODE_CALL_RETURN, 2 + p_arguments.size()); for (int i = 0; i < p_arguments.size(); i++) { append(p_arguments[i]); } + append(p_base); append(p_target); - alloc_call(p_arguments.size()); + append(p_arguments.size()); + append(p_function_name); } void GDScriptByteCodeGenerator::write_construct(const Address &p_target, Variant::Type p_type, const Vector
&p_arguments) { - append(GDScriptFunction::OPCODE_CONSTRUCT); - append(p_type); - append(p_arguments.size()); + append(GDScriptFunction::OPCODE_CONSTRUCT, 1 + p_arguments.size()); for (int i = 0; i < p_arguments.size(); i++) { append(p_arguments[i]); } append(p_target); - alloc_call(p_arguments.size()); + append(p_arguments.size()); + append(p_type); } void GDScriptByteCodeGenerator::write_construct_array(const Address &p_target, const Vector
&p_arguments) { - append(GDScriptFunction::OPCODE_CONSTRUCT_ARRAY); - append(p_arguments.size()); + append(GDScriptFunction::OPCODE_CONSTRUCT_ARRAY, 1 + p_arguments.size()); for (int i = 0; i < p_arguments.size(); i++) { append(p_arguments[i]); } append(p_target); + append(p_arguments.size()); } void GDScriptByteCodeGenerator::write_construct_dictionary(const Address &p_target, const Vector
&p_arguments) { - append(GDScriptFunction::OPCODE_CONSTRUCT_DICTIONARY); - append(p_arguments.size() / 2); // This is number of key-value pairs, so only half of actual arguments. + append(GDScriptFunction::OPCODE_CONSTRUCT_DICTIONARY, 1 + p_arguments.size()); for (int i = 0; i < p_arguments.size(); i++) { append(p_arguments[i]); } append(p_target); + append(p_arguments.size() / 2); // This is number of key-value pairs, so only half of actual arguments. } void GDScriptByteCodeGenerator::write_await(const Address &p_target, const Address &p_operand) { - append(GDScriptFunction::OPCODE_AWAIT); + append(GDScriptFunction::OPCODE_AWAIT, 1); append(p_operand); - append(GDScriptFunction::OPCODE_AWAIT_RESUME); + append(GDScriptFunction::OPCODE_AWAIT_RESUME, 1); append(p_target); } void GDScriptByteCodeGenerator::write_if(const Address &p_condition) { - append(GDScriptFunction::OPCODE_JUMP_IF_NOT); + append(GDScriptFunction::OPCODE_JUMP_IF_NOT, 1); append(p_condition); if_jmp_addrs.push_back(opcodes.size()); append(0); // Jump destination, will be patched. } void GDScriptByteCodeGenerator::write_else() { - append(GDScriptFunction::OPCODE_JUMP); // Jump from true if block; + append(GDScriptFunction::OPCODE_JUMP, 0); // Jump from true if block; int else_jmp_addr = opcodes.size(); append(0); // Jump destination, will be patched. @@ -586,34 +582,34 @@ void GDScriptByteCodeGenerator::write_for(const Address &p_variable, const Addre current_breaks_to_patch.push_back(List()); // Assign container. - append(GDScriptFunction::OPCODE_ASSIGN); + append(GDScriptFunction::OPCODE_ASSIGN, 2); append(container_pos); append(p_list); // Begin loop. - append(GDScriptFunction::OPCODE_ITERATE_BEGIN); + append(GDScriptFunction::OPCODE_ITERATE_BEGIN, 3); append(counter_pos); append(container_pos); + append(p_variable); for_jmp_addrs.push_back(opcodes.size()); append(0); // End of loop address, will be patched. - append(p_variable); - append(GDScriptFunction::OPCODE_JUMP); + append(GDScriptFunction::OPCODE_JUMP, 0); append(opcodes.size() + 6); // Skip over 'continue' code. // Next iteration. int continue_addr = opcodes.size(); continue_addrs.push_back(continue_addr); - append(GDScriptFunction::OPCODE_ITERATE); + append(GDScriptFunction::OPCODE_ITERATE, 3); append(counter_pos); append(container_pos); + append(p_variable); for_jmp_addrs.push_back(opcodes.size()); append(0); // Jump destination, will be patched. - append(p_variable); } void GDScriptByteCodeGenerator::write_endfor() { // Jump back to loop check. - append(GDScriptFunction::OPCODE_JUMP); + append(GDScriptFunction::OPCODE_JUMP, 0); append(continue_addrs.back()->get()); continue_addrs.pop_back(); @@ -641,7 +637,7 @@ void GDScriptByteCodeGenerator::start_while_condition() { void GDScriptByteCodeGenerator::write_while(const Address &p_condition) { // Condition check. - append(GDScriptFunction::OPCODE_JUMP_IF_NOT); + append(GDScriptFunction::OPCODE_JUMP_IF_NOT, 1); append(p_condition); while_jmp_addrs.push_back(opcodes.size()); append(0); // End of loop address, will be patched. @@ -649,7 +645,7 @@ void GDScriptByteCodeGenerator::write_while(const Address &p_condition) { void GDScriptByteCodeGenerator::write_endwhile() { // Jump back to loop check. - append(GDScriptFunction::OPCODE_JUMP); + append(GDScriptFunction::OPCODE_JUMP, 0); append(continue_addrs.back()->get()); continue_addrs.pop_back(); @@ -687,39 +683,39 @@ void GDScriptByteCodeGenerator::end_match() { } void GDScriptByteCodeGenerator::write_break() { - append(GDScriptFunction::OPCODE_JUMP); + append(GDScriptFunction::OPCODE_JUMP, 0); current_breaks_to_patch.back()->get().push_back(opcodes.size()); append(0); } void GDScriptByteCodeGenerator::write_continue() { - append(GDScriptFunction::OPCODE_JUMP); + append(GDScriptFunction::OPCODE_JUMP, 0); append(continue_addrs.back()->get()); } void GDScriptByteCodeGenerator::write_continue_match() { - append(GDScriptFunction::OPCODE_JUMP); + append(GDScriptFunction::OPCODE_JUMP, 0); match_continues_to_patch.back()->get().push_back(opcodes.size()); append(0); } void GDScriptByteCodeGenerator::write_breakpoint() { - append(GDScriptFunction::OPCODE_BREAKPOINT); + append(GDScriptFunction::OPCODE_BREAKPOINT, 0); } void GDScriptByteCodeGenerator::write_newline(int p_line) { - append(GDScriptFunction::OPCODE_LINE); + append(GDScriptFunction::OPCODE_LINE, 0); append(p_line); current_line = p_line; } void GDScriptByteCodeGenerator::write_return(const Address &p_return_value) { - append(GDScriptFunction::OPCODE_RETURN); + append(GDScriptFunction::OPCODE_RETURN, 1); append(p_return_value); } void GDScriptByteCodeGenerator::write_assert(const Address &p_test, const Address &p_message) { - append(GDScriptFunction::OPCODE_ASSERT); + append(GDScriptFunction::OPCODE_ASSERT, 2); append(p_test); append(p_message); } diff --git a/modules/gdscript/gdscript_byte_codegen.h b/modules/gdscript/gdscript_byte_codegen.h index 62438b6dd2e..e8d7de21c20 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) { diff --git a/modules/gdscript/gdscript_disassembler.cpp b/modules/gdscript/gdscript_disassembler.cpp index 4c3f5d3e755..d5de126d2e0 100644 --- a/modules/gdscript/gdscript_disassembler.cpp +++ b/modules/gdscript/gdscript_disassembler.cpp @@ -117,21 +117,22 @@ void GDScriptFunction::disassemble(const Vector &p_code_lines) const { text += ": "; // This makes the compiler complain if some opcode is unchecked in the switch. - Opcode code = Opcode(_code_ptr[ip]); + Opcode code = Opcode(_code_ptr[ip] & INSTR_MASK); + int instr_var_args = (_code_ptr[ip] & INSTR_ARGS_MASK) >> INSTR_BITS; switch (code) { case OPCODE_OPERATOR: { - int operation = _code_ptr[ip + 1]; + int operation = _code_ptr[ip + 4]; text += "operator "; - text += DADDR(4); + text += DADDR(3); text += " = "; - text += DADDR(2); + text += DADDR(1); text += " "; text += Variant::get_operator_name(Variant::Operator(operation)); text += " "; - text += DADDR(3); + text += DADDR(2); incr += 5; } break; @@ -147,11 +148,11 @@ void GDScriptFunction::disassemble(const Vector &p_code_lines) const { } break; case OPCODE_IS_BUILTIN: { text += "is builtin "; - text += DADDR(3); + text += DADDR(2); text += " = "; text += DADDR(1); text += " is "; - text += Variant::get_type_name(Variant::Type(_code_ptr[ip + 2])); + text += Variant::get_type_name(Variant::Type(_code_ptr[ip + 3])); incr += 4; } break; @@ -180,19 +181,19 @@ void GDScriptFunction::disassemble(const Vector &p_code_lines) const { text += "set_named "; text += DADDR(1); text += "[\""; - text += _global_names_ptr[_code_ptr[ip + 2]]; + text += _global_names_ptr[_code_ptr[ip + 3]]; text += "\"] = "; - text += DADDR(3); + text += DADDR(2); incr += 4; } break; case OPCODE_GET_NAMED: { text += "get_named "; - text += DADDR(3); + text += DADDR(2); text += " = "; text += DADDR(1); text += "[\""; - text += _global_names_ptr[_code_ptr[ip + 2]]; + text += _global_names_ptr[_code_ptr[ip + 3]]; text += "\"]"; incr += 4; @@ -200,18 +201,18 @@ void GDScriptFunction::disassemble(const Vector &p_code_lines) const { case OPCODE_SET_MEMBER: { text += "set_member "; text += "[\""; - text += _global_names_ptr[_code_ptr[ip + 1]]; + text += _global_names_ptr[_code_ptr[ip + 2]]; text += "\"] = "; - text += DADDR(2); + text += DADDR(1); incr += 3; } break; case OPCODE_GET_MEMBER: { text += "get_member "; - text += DADDR(2); + text += DADDR(1); text += " = "; text += "[\""; - text += _global_names_ptr[_code_ptr[ip + 1]]; + text += _global_names_ptr[_code_ptr[ip + 2]]; text += "\"]"; incr += 3; @@ -240,45 +241,45 @@ void GDScriptFunction::disassemble(const Vector &p_code_lines) const { } break; case OPCODE_ASSIGN_TYPED_BUILTIN: { text += "assign typed builtin ("; - text += Variant::get_type_name((Variant::Type)_code_ptr[ip + 1]); + text += Variant::get_type_name((Variant::Type)_code_ptr[ip + 3]); text += ") "; - text += DADDR(2); + text += DADDR(1); text += " = "; - text += DADDR(3); + text += DADDR(2); incr += 4; } break; case OPCODE_ASSIGN_TYPED_NATIVE: { - Variant class_name = _constants_ptr[_code_ptr[ip + 1]]; + Variant class_name = _constants_ptr[_code_ptr[ip + 3]]; GDScriptNativeClass *nc = Object::cast_to(class_name.operator Object *()); text += "assign typed native ("; text += nc->get_name().operator String(); text += ") "; - text += DADDR(2); + text += DADDR(1); text += " = "; - text += DADDR(3); + text += DADDR(2); incr += 4; } break; case OPCODE_ASSIGN_TYPED_SCRIPT: { - Variant script = _constants_ptr[_code_ptr[ip + 1]]; + Variant script = _constants_ptr[_code_ptr[ip + 3]]; Script *sc = Object::cast_to