diff options
Diffstat (limited to 'modules')
-rw-r--r-- | modules/gdscript/gdscript_byte_codegen.cpp | 226 | ||||
-rw-r--r-- | modules/gdscript/gdscript_byte_codegen.h | 18 | ||||
-rw-r--r-- | modules/gdscript/gdscript_disassembler.cpp | 125 | ||||
-rw-r--r-- | modules/gdscript/gdscript_function.cpp | 20 | ||||
-rw-r--r-- | modules/gdscript/gdscript_function.h | 60 | ||||
-rw-r--r-- | modules/gdscript/gdscript_vm.cpp | 293 |
6 files changed, 361 insertions, 381 deletions
diff --git a/modules/gdscript/gdscript_byte_codegen.cpp b/modules/gdscript/gdscript_byte_codegen.cpp index cc9e87b882..33e3909e90 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<Address> &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<Address> &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<Address> &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<Address> &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<Address> &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<Address> &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<Address> &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<Address> &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<Address> &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<Address> &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<Address> &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<int>()); // 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 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<int> if_jmp_addrs; // List since this can be nested. List<int> 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 4c3f5d3e75..d5de126d2e 100644 --- a/modules/gdscript/gdscript_disassembler.cpp +++ b/modules/gdscript/gdscript_disassembler.cpp @@ -117,21 +117,22 @@ void GDScriptFunction::disassemble(const Vector<String> &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<String> &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<String> &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<String> &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<String> &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<GDScriptNativeClass>(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<Script>(script.operator Object *()); text += "assign typed script ("; text += sc->get_path(); text += ") "; - text += DADDR(2); + text += DADDR(1); text += " = "; - text += DADDR(3); + text += DADDR(2); incr += 4; } break; case OPCODE_CAST_TO_BUILTIN: { text += "cast builtin "; - text += DADDR(3); - text += " = "; text += DADDR(2); + text += " = "; + text += DADDR(1); text += " as "; text += Variant::get_type_name(Variant::Type(_code_ptr[ip + 1])); @@ -289,9 +290,9 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const { GDScriptNativeClass *nc = Object::cast_to<GDScriptNativeClass>(class_name.operator Object *()); text += "cast native "; - text += DADDR(3); - text += " = "; text += DADDR(2); + text += " = "; + text += DADDR(1); text += " as "; text += nc->get_name(); @@ -299,42 +300,42 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const { } break; case OPCODE_CAST_TO_SCRIPT: { text += "cast "; - text += DADDR(3); - text += " = "; text += DADDR(2); - text += " as "; + text += " = "; text += DADDR(1); + text += " as "; + text += DADDR(3); incr += 4; } break; case OPCODE_CONSTRUCT: { - Variant::Type t = Variant::Type(_code_ptr[ip + 1]); - int argc = _code_ptr[ip + 2]; + Variant::Type t = Variant::Type(_code_ptr[ip + 3 + instr_var_args]); + int argc = _code_ptr[ip + 2 + instr_var_args]; text += "construct "; - text += DADDR(3 + argc); + text += DADDR(1 + argc); text += " = "; text += Variant::get_type_name(t) + "("; for (int i = 0; i < argc; i++) { if (i > 0) text += ", "; - text += DADDR(i + 3); + text += DADDR(i + 1); } text += ")"; - incr = 4 + argc; + incr = 3 + instr_var_args; } break; case OPCODE_CONSTRUCT_ARRAY: { - int argc = _code_ptr[ip + 1]; + int argc = _code_ptr[ip + 1 + instr_var_args]; text += " make_array "; - text += DADDR(2 + argc); + text += DADDR(1 + argc); text += " = ["; for (int i = 0; i < argc; i++) { if (i > 0) text += ", "; - text += DADDR(2 + i); + text += DADDR(1 + i); } text += "]"; @@ -342,17 +343,17 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const { incr += 3 + argc; } break; case OPCODE_CONSTRUCT_DICTIONARY: { - int argc = _code_ptr[ip + 1]; + int argc = _code_ptr[ip + 1 + instr_var_args]; text += "make_dict "; - text += DADDR(2 + argc * 2); + text += DADDR(1 + argc * 2); text += " = {"; for (int i = 0; i < argc; i++) { if (i > 0) text += ", "; - text += DADDR(2 + i * 2 + 0); + text += DADDR(1 + i * 2 + 0); text += ": "; - text += DADDR(2 + i * 2 + 1); + text += DADDR(1 + i * 2 + 1); } text += "}"; @@ -362,8 +363,8 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const { case OPCODE_CALL: case OPCODE_CALL_RETURN: case OPCODE_CALL_ASYNC: { - bool ret = _code_ptr[ip] == OPCODE_CALL_RETURN; - bool async = _code_ptr[ip] == OPCODE_CALL_ASYNC; + bool ret = (_code_ptr[ip] & INSTR_MASK) == OPCODE_CALL_RETURN; + bool async = (_code_ptr[ip] & INSTR_MASK) == OPCODE_CALL_ASYNC; if (ret) { text += "call-ret "; @@ -373,19 +374,19 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const { text += "call "; } - int argc = _code_ptr[ip + 1]; + int argc = _code_ptr[ip + 1 + instr_var_args]; if (ret || async) { - text += DADDR(4 + argc) + " = "; + text += DADDR(2 + argc) + " = "; } - text += DADDR(2) + "."; - text += String(_global_names_ptr[_code_ptr[ip + 3]]); + text += DADDR(1 + argc) + "."; + text += String(_global_names_ptr[_code_ptr[ip + 2 + instr_var_args]]); text += "("; for (int i = 0; i < argc; i++) { if (i > 0) text += ", "; - text += DADDR(4 + i); + text += DADDR(1 + i); } text += ")"; @@ -394,16 +395,16 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const { case OPCODE_CALL_BUILT_IN: { text += "call-built-in "; - int argc = _code_ptr[ip + 2]; - text += DADDR(3 + argc) + " = "; + int argc = _code_ptr[ip + 1 + instr_var_args]; + text += DADDR(1 + argc) + " = "; - text += GDScriptFunctions::get_func_name(GDScriptFunctions::Function(_code_ptr[ip + 1])); + text += GDScriptFunctions::get_func_name(GDScriptFunctions::Function(_code_ptr[ip + 2 + instr_var_args])); text += "("; for (int i = 0; i < argc; i++) { if (i > 0) text += ", "; - text += DADDR(3 + i); + text += DADDR(1 + i); } text += ")"; @@ -412,16 +413,16 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const { case OPCODE_CALL_SELF_BASE: { text += "call-self-base "; - int argc = _code_ptr[ip + 2]; - text += DADDR(3 + argc) + " = "; + int argc = _code_ptr[ip + 1 + instr_var_args]; + text += DADDR(2 + argc) + " = "; - text += _global_names_ptr[_code_ptr[ip + 1]]; + text += _global_names_ptr[_code_ptr[ip + 2 + instr_var_args]]; text += "("; for (int i = 0; i < argc; i++) { if (i > 0) text += ", "; - text += DADDR(3 + i); + text += DADDR(1 + i); } text += ")"; @@ -474,25 +475,25 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const { } break; case OPCODE_ITERATE_BEGIN: { text += "for-init "; - text += DADDR(4); + text += DADDR(3); text += " in "; text += DADDR(2); text += " counter "; text += DADDR(1); text += " end "; - text += itos(_code_ptr[ip + 3]); + text += itos(_code_ptr[ip + 4]); incr += 5; } break; case OPCODE_ITERATE: { text += "for-loop "; - text += DADDR(4); + text += DADDR(2); text += " in "; text += DADDR(2); text += " counter "; text += DADDR(1); text += " end "; - text += itos(_code_ptr[ip + 3]); + text += itos(_code_ptr[ip + 4]); incr += 5; } break; diff --git a/modules/gdscript/gdscript_function.cpp b/modules/gdscript/gdscript_function.cpp index 397c1f0bf8..32372439c5 100644 --- a/modules/gdscript/gdscript_function.cpp +++ b/modules/gdscript/gdscript_function.cpp @@ -139,31 +139,13 @@ void GDScriptFunction::debug_get_stack_member_state(int p_line, List<Pair<String } } -GDScriptFunction::GDScriptFunction() : - function_list(this) { - _stack_size = 0; - _call_size = 0; - rpc_mode = MultiplayerAPI::RPC_MODE_DISABLED; +GDScriptFunction::GDScriptFunction() { name = "<anonymous>"; #ifdef DEBUG_ENABLED - _func_cname = nullptr; - { MutexLock lock(GDScriptLanguage::get_singleton()->lock); - GDScriptLanguage::get_singleton()->function_list.add(&function_list); } - - profile.call_count = 0; - profile.self_time = 0; - profile.total_time = 0; - profile.frame_call_count = 0; - profile.frame_self_time = 0; - profile.frame_total_time = 0; - profile.last_frame_call_count = 0; - profile.last_frame_self_time = 0; - profile.last_frame_total_time = 0; - #endif } diff --git a/modules/gdscript/gdscript_function.h b/modules/gdscript/gdscript_function.h index 50eadcaf86..ca9dda9b80 100644 --- a/modules/gdscript/gdscript_function.h +++ b/modules/gdscript/gdscript_function.h @@ -215,6 +215,12 @@ public: ADDR_TYPE_NIL = 9 }; + enum Instruction { + INSTR_BITS = 20, + INSTR_MASK = ((1 << INSTR_BITS) - 1), + INSTR_ARGS_MASK = ~INSTR_MASK, + }; + struct StackDebug { int line; int pos; @@ -229,22 +235,22 @@ private: StringName source; mutable Variant nil; - mutable Variant *_constants_ptr; - int _constant_count; - const StringName *_global_names_ptr; - int _global_names_count; - const int *_default_arg_ptr; - int _default_arg_count; - const int *_code_ptr; - int _code_size; - int _argument_count; - int _stack_size; - int _call_size; - int _initial_line; - bool _static; - MultiplayerAPI::RPCMode rpc_mode; - - GDScript *_script; + mutable Variant *_constants_ptr = nullptr; + int _constant_count = 0; + const StringName *_global_names_ptr = nullptr; + int _global_names_count = 0; + const int *_default_arg_ptr = nullptr; + int _default_arg_count = 0; + const int *_code_ptr = nullptr; + int _code_size = 0; + int _argument_count = 0; + int _stack_size = 0; + int _instruction_args_size = 0; + int _initial_line = 0; + bool _static = false; + MultiplayerAPI::RPCMode rpc_mode = MultiplayerAPI::RPC_MODE_DISABLED; + + GDScript *_script = nullptr; StringName name; Vector<Variant> constants; @@ -265,22 +271,22 @@ private: friend class GDScriptLanguage; - SelfList<GDScriptFunction> function_list; + SelfList<GDScriptFunction> function_list{ this }; #ifdef DEBUG_ENABLED CharString func_cname; - const char *_func_cname; + const char *_func_cname = nullptr; struct Profile { StringName signature; - uint64_t call_count; - uint64_t self_time; - uint64_t total_time; - uint64_t frame_call_count; - uint64_t frame_self_time; - uint64_t frame_total_time; - uint64_t last_frame_call_count; - uint64_t last_frame_self_time; - uint64_t last_frame_total_time; + uint64_t call_count = 0; + uint64_t self_time = 0; + uint64_t total_time = 0; + uint64_t frame_call_count = 0; + uint64_t frame_self_time = 0; + uint64_t frame_total_time = 0; + uint64_t last_frame_call_count = 0; + uint64_t last_frame_self_time = 0; + uint64_t last_frame_total_time = 0; } profile; #endif diff --git a/modules/gdscript/gdscript_vm.cpp b/modules/gdscript/gdscript_vm.cpp index 65bea37b94..a10f2a9274 100644 --- a/modules/gdscript/gdscript_vm.cpp +++ b/modules/gdscript/gdscript_vm.cpp @@ -231,13 +231,14 @@ String GDScriptFunction::_get_call_error(const Callable::CallError &p_err, const #define OPCODE(m_op) \ m_op: -#define OPCODE_WHILE(m_test) +#define OPCODE_WHILE(m_test) \ + OPSWHILE: #define OPCODES_END \ OPSEXIT: #define OPCODES_OUT \ OPSOUT: -#define DISPATCH_OPCODE goto *switch_table_ops[_code_ptr[ip]] -#define OPCODE_SWITCH(m_test) DISPATCH_OPCODE; +#define DISPATCH_OPCODE goto OPSWHILE +#define OPCODE_SWITCH(m_test) goto *switch_table_ops[m_test]; #define OPCODE_BREAK goto OPSEXIT #define OPCODE_OUT goto OPSOUT #else @@ -265,7 +266,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a Variant static_ref; Variant retvalue; Variant *stack = nullptr; - Variant **call_args; + Variant **instruction_args; int defarg = 0; #ifdef DEBUG_ENABLED @@ -282,7 +283,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a if (p_state) { //use existing (supplied) state (awaited) stack = (Variant *)p_state->stack.ptr(); - call_args = (Variant **)&p_state->stack.ptr()[sizeof(Variant) * p_state->stack_size]; //ptr() to avoid bounds check + instruction_args = (Variant **)&p_state->stack.ptr()[sizeof(Variant) * p_state->stack_size]; //ptr() to avoid bounds check line = p_state->line; ip = p_state->ip; alloca_size = p_state->stack.size(); @@ -307,7 +308,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a } } - alloca_size = sizeof(Variant *) * _call_size + sizeof(Variant) * _stack_size; + alloca_size = sizeof(Variant *) * _instruction_args_size + sizeof(Variant) * _stack_size; if (alloca_size) { uint8_t *aptr = (uint8_t *)alloca(alloca_size); @@ -341,15 +342,15 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a stack = nullptr; } - if (_call_size) { - call_args = (Variant **)&aptr[sizeof(Variant) * _stack_size]; + if (_instruction_args_size) { + instruction_args = (Variant **)&aptr[sizeof(Variant) * _stack_size]; } else { - call_args = nullptr; + instruction_args = nullptr; } } else { stack = nullptr; - call_args = nullptr; + instruction_args = nullptr; } if (p_instance) { @@ -400,6 +401,9 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a #endif +#define GET_INSTRUCTION_ARG(m_v, m_idx) \ + Variant *m_v = instruction_args[m_idx] + #ifdef DEBUG_ENABLED uint64_t function_start_time = 0; @@ -421,18 +425,24 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a #else OPCODE_WHILE(true) { #endif + // Load arguments for the instruction before each instruction. + int instr_arg_count = ((_code_ptr[ip]) & INSTR_ARGS_MASK) >> INSTR_BITS; + for (int i = 0; i < instr_arg_count; i++) { + GET_VARIANT_PTR(v, i + 1); + instruction_args[i] = v; + } - OPCODE_SWITCH(_code_ptr[ip]) { + OPCODE_SWITCH(_code_ptr[ip] & INSTR_MASK) { OPCODE(OPCODE_OPERATOR) { CHECK_SPACE(5); bool valid; - Variant::Operator op = (Variant::Operator)_code_ptr[ip + 1]; + Variant::Operator op = (Variant::Operator)_code_ptr[ip + 4]; GD_ERR_BREAK(op >= Variant::OP_MAX); - GET_VARIANT_PTR(a, 2); - GET_VARIANT_PTR(b, 3); - GET_VARIANT_PTR(dst, 4); + GET_INSTRUCTION_ARG(a, 0); + GET_INSTRUCTION_ARG(b, 1); + GET_INSTRUCTION_ARG(dst, 2); #ifdef DEBUG_ENABLED @@ -461,9 +471,9 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a OPCODE(OPCODE_EXTENDS_TEST) { CHECK_SPACE(4); - GET_VARIANT_PTR(a, 1); - GET_VARIANT_PTR(b, 2); - GET_VARIANT_PTR(dst, 3); + GET_INSTRUCTION_ARG(a, 0); + GET_INSTRUCTION_ARG(b, 1); + GET_INSTRUCTION_ARG(dst, 2); #ifdef DEBUG_ENABLED if (b->get_type() != Variant::OBJECT || b->operator Object *() == nullptr) { @@ -536,9 +546,9 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a OPCODE(OPCODE_IS_BUILTIN) { CHECK_SPACE(4); - GET_VARIANT_PTR(value, 1); - Variant::Type var_type = (Variant::Type)_code_ptr[ip + 2]; - GET_VARIANT_PTR(dst, 3); + GET_INSTRUCTION_ARG(value, 0); + GET_INSTRUCTION_ARG(dst, 1); + Variant::Type var_type = (Variant::Type)_code_ptr[ip + 3]; GD_ERR_BREAK(var_type < 0 || var_type >= Variant::VARIANT_MAX); @@ -550,9 +560,9 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a OPCODE(OPCODE_SET) { CHECK_SPACE(3); - GET_VARIANT_PTR(dst, 1); - GET_VARIANT_PTR(index, 2); - GET_VARIANT_PTR(value, 3); + GET_INSTRUCTION_ARG(dst, 0); + GET_INSTRUCTION_ARG(index, 1); + GET_INSTRUCTION_ARG(value, 2); bool valid; dst->set(*index, *value, &valid); @@ -576,9 +586,9 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a OPCODE(OPCODE_GET) { CHECK_SPACE(3); - GET_VARIANT_PTR(src, 1); - GET_VARIANT_PTR(index, 2); - GET_VARIANT_PTR(dst, 3); + GET_INSTRUCTION_ARG(src, 0); + GET_INSTRUCTION_ARG(index, 1); + GET_INSTRUCTION_ARG(dst, 2); bool valid; #ifdef DEBUG_ENABLED @@ -608,10 +618,10 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a OPCODE(OPCODE_SET_NAMED) { CHECK_SPACE(3); - GET_VARIANT_PTR(dst, 1); - GET_VARIANT_PTR(value, 3); + GET_INSTRUCTION_ARG(dst, 0); + GET_INSTRUCTION_ARG(value, 1); - int indexname = _code_ptr[ip + 2]; + int indexname = _code_ptr[ip + 3]; GD_ERR_BREAK(indexname < 0 || indexname >= _global_names_count); const StringName *index = &_global_names_ptr[indexname]; @@ -633,10 +643,10 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a OPCODE(OPCODE_GET_NAMED) { CHECK_SPACE(4); - GET_VARIANT_PTR(src, 1); - GET_VARIANT_PTR(dst, 3); + GET_INSTRUCTION_ARG(src, 0); + GET_INSTRUCTION_ARG(dst, 1); - int indexname = _code_ptr[ip + 2]; + int indexname = _code_ptr[ip + 3]; GD_ERR_BREAK(indexname < 0 || indexname >= _global_names_count); const StringName *index = &_global_names_ptr[indexname]; @@ -666,10 +676,10 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a OPCODE(OPCODE_SET_MEMBER) { CHECK_SPACE(3); - int indexname = _code_ptr[ip + 1]; + GET_INSTRUCTION_ARG(src, 0); + int indexname = _code_ptr[ip + 2]; GD_ERR_BREAK(indexname < 0 || indexname >= _global_names_count); const StringName *index = &_global_names_ptr[indexname]; - GET_VARIANT_PTR(src, 2); bool valid; #ifndef DEBUG_ENABLED @@ -690,11 +700,10 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a OPCODE(OPCODE_GET_MEMBER) { CHECK_SPACE(3); - int indexname = _code_ptr[ip + 1]; + GET_INSTRUCTION_ARG(dst, 0); + int indexname = _code_ptr[ip + 2]; GD_ERR_BREAK(indexname < 0 || indexname >= _global_names_count); const StringName *index = &_global_names_ptr[indexname]; - GET_VARIANT_PTR(dst, 2); - #ifndef DEBUG_ENABLED ClassDB::get_property(p_instance->owner, *index, *dst); #else @@ -710,8 +719,8 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a OPCODE(OPCODE_ASSIGN) { CHECK_SPACE(3); - GET_VARIANT_PTR(dst, 1); - GET_VARIANT_PTR(src, 2); + GET_INSTRUCTION_ARG(dst, 0); + GET_INSTRUCTION_ARG(src, 1); *dst = *src; @@ -721,7 +730,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a OPCODE(OPCODE_ASSIGN_TRUE) { CHECK_SPACE(2); - GET_VARIANT_PTR(dst, 1); + GET_INSTRUCTION_ARG(dst, 0); *dst = true; @@ -731,7 +740,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a OPCODE(OPCODE_ASSIGN_FALSE) { CHECK_SPACE(2); - GET_VARIANT_PTR(dst, 1); + GET_INSTRUCTION_ARG(dst, 0); *dst = false; @@ -741,10 +750,10 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a OPCODE(OPCODE_ASSIGN_TYPED_BUILTIN) { CHECK_SPACE(4); - GET_VARIANT_PTR(dst, 2); - GET_VARIANT_PTR(src, 3); + GET_INSTRUCTION_ARG(dst, 0); + GET_INSTRUCTION_ARG(src, 1); - Variant::Type var_type = (Variant::Type)_code_ptr[ip + 1]; + Variant::Type var_type = (Variant::Type)_code_ptr[ip + 3]; GD_ERR_BREAK(var_type < 0 || var_type >= Variant::VARIANT_MAX); if (src->get_type() != var_type) { @@ -770,11 +779,11 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a OPCODE(OPCODE_ASSIGN_TYPED_NATIVE) { CHECK_SPACE(4); - GET_VARIANT_PTR(dst, 2); - GET_VARIANT_PTR(src, 3); + GET_INSTRUCTION_ARG(dst, 0); + GET_INSTRUCTION_ARG(src, 1); #ifdef DEBUG_ENABLED - GET_VARIANT_PTR(type, 1); + GET_INSTRUCTION_ARG(type, 2); GDScriptNativeClass *nc = Object::cast_to<GDScriptNativeClass>(type->operator Object *()); GD_ERR_BREAK(!nc); if (src->get_type() != Variant::OBJECT && src->get_type() != Variant::NIL) { @@ -798,11 +807,11 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a OPCODE(OPCODE_ASSIGN_TYPED_SCRIPT) { CHECK_SPACE(4); - GET_VARIANT_PTR(dst, 2); - GET_VARIANT_PTR(src, 3); + GET_INSTRUCTION_ARG(dst, 0); + GET_INSTRUCTION_ARG(src, 1); #ifdef DEBUG_ENABLED - GET_VARIANT_PTR(type, 1); + GET_INSTRUCTION_ARG(type, 2); Script *base_type = Object::cast_to<Script>(type->operator Object *()); GD_ERR_BREAK(!base_type); @@ -847,9 +856,9 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a OPCODE(OPCODE_CAST_TO_BUILTIN) { CHECK_SPACE(4); - Variant::Type to_type = (Variant::Type)_code_ptr[ip + 1]; - GET_VARIANT_PTR(src, 2); - GET_VARIANT_PTR(dst, 3); + GET_INSTRUCTION_ARG(src, 0); + GET_INSTRUCTION_ARG(dst, 1); + Variant::Type to_type = (Variant::Type)_code_ptr[ip + 3]; GD_ERR_BREAK(to_type < 0 || to_type >= Variant::VARIANT_MAX); @@ -869,9 +878,9 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a OPCODE(OPCODE_CAST_TO_NATIVE) { CHECK_SPACE(4); - GET_VARIANT_PTR(to_type, 1); - GET_VARIANT_PTR(src, 2); - GET_VARIANT_PTR(dst, 3); + GET_INSTRUCTION_ARG(src, 0); + GET_INSTRUCTION_ARG(dst, 1); + GET_INSTRUCTION_ARG(to_type, 2); GDScriptNativeClass *nc = Object::cast_to<GDScriptNativeClass>(to_type->operator Object *()); GD_ERR_BREAK(!nc); @@ -896,9 +905,9 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a OPCODE(OPCODE_CAST_TO_SCRIPT) { CHECK_SPACE(4); - GET_VARIANT_PTR(to_type, 1); - GET_VARIANT_PTR(src, 2); - GET_VARIANT_PTR(dst, 3); + GET_INSTRUCTION_ARG(src, 0); + GET_INSTRUCTION_ARG(dst, 1); + GET_INSTRUCTION_ARG(to_type, 2); Script *base_type = Object::cast_to<Script>(to_type->operator Object *()); @@ -940,17 +949,17 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a DISPATCH_OPCODE; OPCODE(OPCODE_CONSTRUCT) { - CHECK_SPACE(2); - Variant::Type t = Variant::Type(_code_ptr[ip + 1]); - int argc = _code_ptr[ip + 2]; - CHECK_SPACE(argc + 2); - Variant **argptrs = call_args; - for (int i = 0; i < argc; i++) { - GET_VARIANT_PTR(v, 3 + i); - argptrs[i] = v; - } + CHECK_SPACE(2 + instr_arg_count); + + ip += instr_arg_count; + + int argc = _code_ptr[ip + 1]; + + Variant::Type t = Variant::Type(_code_ptr[ip + 2]); + Variant **argptrs = instruction_args; + + GET_INSTRUCTION_ARG(dst, argc); - GET_VARIANT_PTR(dst, 3 + argc); Callable::CallError err; Variant::construct(t, *dst, (const Variant **)argptrs, argc, err); @@ -961,77 +970,72 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a } #endif - ip += 4 + argc; - //construct a basic type + ip += 3; } DISPATCH_OPCODE; OPCODE(OPCODE_CONSTRUCT_ARRAY) { - CHECK_SPACE(1); + CHECK_SPACE(1 + instr_arg_count); + ip += instr_arg_count; + int argc = _code_ptr[ip + 1]; - Array array; //arrays are always shared + Array array; array.resize(argc); - CHECK_SPACE(argc + 2); for (int i = 0; i < argc; i++) { - GET_VARIANT_PTR(v, 2 + i); - array[i] = *v; + array[i] = *(instruction_args[i]); } - GET_VARIANT_PTR(dst, 2 + argc); + GET_INSTRUCTION_ARG(dst, argc); *dst = array; - ip += 3 + argc; + ip += 2; } DISPATCH_OPCODE; OPCODE(OPCODE_CONSTRUCT_DICTIONARY) { - CHECK_SPACE(1); - int argc = _code_ptr[ip + 1]; - Dictionary dict; //arrays are always shared + CHECK_SPACE(2 + instr_arg_count); - CHECK_SPACE(argc * 2 + 2); + ip += instr_arg_count; + + int argc = _code_ptr[ip + 1]; + Dictionary dict; for (int i = 0; i < argc; i++) { - GET_VARIANT_PTR(k, 2 + i * 2 + 0); - GET_VARIANT_PTR(v, 2 + i * 2 + 1); + GET_INSTRUCTION_ARG(k, i * 2 + 0); + GET_INSTRUCTION_ARG(v, i * 2 + 1); dict[*k] = *v; } - GET_VARIANT_PTR(dst, 2 + argc * 2); + GET_INSTRUCTION_ARG(dst, argc * 2); *dst = dict; - ip += 3 + argc * 2; + ip += 2; } DISPATCH_OPCODE; OPCODE(OPCODE_CALL_ASYNC) OPCODE(OPCODE_CALL_RETURN) OPCODE(OPCODE_CALL) { - CHECK_SPACE(4); - bool call_ret = _code_ptr[ip] != OPCODE_CALL; + CHECK_SPACE(3 + instr_arg_count); + bool call_ret = (_code_ptr[ip] & INSTR_MASK) != OPCODE_CALL; #ifdef DEBUG_ENABLED - bool call_async = _code_ptr[ip] == OPCODE_CALL_ASYNC; + bool call_async = (_code_ptr[ip] & INSTR_MASK) == OPCODE_CALL_ASYNC; #endif - int argc = _code_ptr[ip + 1]; - GET_VARIANT_PTR(base, 2); - int nameg = _code_ptr[ip + 3]; - - GD_ERR_BREAK(nameg < 0 || nameg >= _global_names_count); - const StringName *methodname = &_global_names_ptr[nameg]; + ip += instr_arg_count; + int argc = _code_ptr[ip + 1]; GD_ERR_BREAK(argc < 0); - ip += 4; - CHECK_SPACE(argc + 1); - Variant **argptrs = call_args; - for (int i = 0; i < argc; i++) { - GET_VARIANT_PTR(v, i); - argptrs[i] = v; - } + int methodname_idx = _code_ptr[ip + 2]; + GD_ERR_BREAK(methodname_idx < 0 || methodname_idx >= _global_names_count); + const StringName *methodname = &_global_names_ptr[methodname_idx]; + + GET_INSTRUCTION_ARG(base, argc); + Variant **argptrs = instruction_args; #ifdef DEBUG_ENABLED uint64_t call_time = 0; @@ -1043,7 +1047,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a #endif Callable::CallError err; if (call_ret) { - GET_VARIANT_PTR(ret, argc); + GET_INSTRUCTION_ARG(ret, argc + 1); base->call(*methodname, (const Variant **)argptrs, argc, *ret, err); #ifdef DEBUG_ENABLED if (!call_async && ret->get_type() == Variant::OBJECT) { @@ -1104,31 +1108,24 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a } #endif - //_call_func(nullptr,base,*methodname,ip,argc,p_instance,stack); - ip += argc + 1; + ip += 3; } DISPATCH_OPCODE; OPCODE(OPCODE_CALL_BUILT_IN) { - CHECK_SPACE(4); + CHECK_SPACE(3 + instr_arg_count); - GDScriptFunctions::Function func = GDScriptFunctions::Function(_code_ptr[ip + 1]); - int argc = _code_ptr[ip + 2]; - GD_ERR_BREAK(argc < 0); + ip += instr_arg_count; - ip += 3; - CHECK_SPACE(argc + 1); - Variant **argptrs = call_args; + int argc = _code_ptr[ip + 1]; + GD_ERR_BREAK(argc < 0); - for (int i = 0; i < argc; i++) { - GET_VARIANT_PTR(v, i); - argptrs[i] = v; - } + GDScriptFunctions::Function func = GDScriptFunctions::Function(_code_ptr[ip + 2]); + Variant **argptrs = instruction_args; - GET_VARIANT_PTR(dst, argc); + GET_INSTRUCTION_ARG(dst, argc); Callable::CallError err; - GDScriptFunctions::call(func, (const Variant **)argptrs, argc, *dst, err); #ifdef DEBUG_ENABLED @@ -1143,14 +1140,16 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a OPCODE_BREAK; } #endif - ip += argc + 1; + ip += 3; } DISPATCH_OPCODE; OPCODE(OPCODE_CALL_SELF_BASE) { - CHECK_SPACE(2); - int self_fun = _code_ptr[ip + 1]; + CHECK_SPACE(3 + instr_arg_count); + + ip += instr_arg_count; + int self_fun = _code_ptr[ip + 1]; #ifdef DEBUG_ENABLED if (self_fun < 0 || self_fun >= _global_names_count) { err_text = "compiler bug, function name not found"; @@ -1160,17 +1159,11 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a const StringName *methodname = &_global_names_ptr[self_fun]; int argc = _code_ptr[ip + 2]; + GD_ERR_BREAK(argc < 0); - CHECK_SPACE(2 + argc + 1); - - Variant **argptrs = call_args; - - for (int i = 0; i < argc; i++) { - GET_VARIANT_PTR(v, i + 3); - argptrs[i] = v; - } + Variant **argptrs = instruction_args; - GET_VARIANT_PTR(dst, argc + 3); + GET_INSTRUCTION_ARG(dst, argc); const GDScript *gds = _script; @@ -1213,15 +1206,15 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a OPCODE_BREAK; } - ip += 4 + argc; + ip += 3; } DISPATCH_OPCODE; OPCODE(OPCODE_AWAIT) { CHECK_SPACE(2); - //do the oneshot connect - GET_VARIANT_PTR(argobj, 1); + // Do the oneshot connect. + GET_INSTRUCTION_ARG(argobj, 0); Signal sig; bool is_signal = true; @@ -1313,7 +1306,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a OPCODE_BREAK; } #endif - GET_VARIANT_PTR(result, 1); + GET_INSTRUCTION_ARG(result, 0); *result = p_state->result; ip += 2; } @@ -1331,7 +1324,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a OPCODE(OPCODE_JUMP_IF) { CHECK_SPACE(3); - GET_VARIANT_PTR(test, 1); + GET_INSTRUCTION_ARG(test, 0); bool result = test->booleanize(); @@ -1348,7 +1341,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a OPCODE(OPCODE_JUMP_IF_NOT) { CHECK_SPACE(3); - GET_VARIANT_PTR(test, 1); + GET_INSTRUCTION_ARG(test, 0); bool result = test->booleanize(); @@ -1370,7 +1363,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a OPCODE(OPCODE_RETURN) { CHECK_SPACE(2); - GET_VARIANT_PTR(r, 1); + GET_INSTRUCTION_ARG(r, 0); retvalue = *r; #ifdef DEBUG_ENABLED exit_ok = true; @@ -1379,10 +1372,10 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a } OPCODE(OPCODE_ITERATE_BEGIN) { - CHECK_SPACE(8); //space for this a regular iterate + CHECK_SPACE(8); // Space for this and a regular iterate. - GET_VARIANT_PTR(counter, 1); - GET_VARIANT_PTR(container, 2); + GET_INSTRUCTION_ARG(counter, 0); + GET_INSTRUCTION_ARG(container, 1); bool valid; if (!container->iter_init(*counter, valid)) { @@ -1392,11 +1385,11 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a OPCODE_BREAK; } #endif - int jumpto = _code_ptr[ip + 3]; + int jumpto = _code_ptr[ip + 4]; GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size); ip = jumpto; } else { - GET_VARIANT_PTR(iterator, 4); + GET_INSTRUCTION_ARG(iterator, 2); *iterator = container->iter_get(*counter, valid); #ifdef DEBUG_ENABLED @@ -1405,7 +1398,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a OPCODE_BREAK; } #endif - ip += 5; //skip regular iterate which is always next + ip += 5; // Skip regular iterate which is always next. } } DISPATCH_OPCODE; @@ -1413,8 +1406,8 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a OPCODE(OPCODE_ITERATE) { CHECK_SPACE(4); - GET_VARIANT_PTR(counter, 1); - GET_VARIANT_PTR(container, 2); + GET_INSTRUCTION_ARG(counter, 0); + GET_INSTRUCTION_ARG(container, 1); bool valid; if (!container->iter_next(*counter, valid)) { @@ -1424,11 +1417,11 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a OPCODE_BREAK; } #endif - int jumpto = _code_ptr[ip + 3]; + int jumpto = _code_ptr[ip + 4]; GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size); ip = jumpto; } else { - GET_VARIANT_PTR(iterator, 4); + GET_INSTRUCTION_ARG(iterator, 2); *iterator = container->iter_get(*counter, valid); #ifdef DEBUG_ENABLED @@ -1446,13 +1439,13 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a CHECK_SPACE(3); #ifdef DEBUG_ENABLED - GET_VARIANT_PTR(test, 1); + GET_INSTRUCTION_ARG(test, 0); bool result = test->booleanize(); if (!result) { String message_str; if (_code_ptr[ip + 2] != 0) { - GET_VARIANT_PTR(message, 2); + GET_INSTRUCTION_ARG(message, 1); message_str = *message; } if (message_str.empty()) { |