Ver Fonte

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.
George Marques há 4 anos atrás
pai
commit
c707d6fe71

+ 111 - 115
modules/gdscript/gdscript_byte_codegen.cpp

@@ -111,7 +111,7 @@ void GDScriptByteCodeGenerator::write_start(GDScript *p_script, const StringName
 }
 }
 
 
 GDScriptFunction *GDScriptByteCodeGenerator::write_end() {
 GDScriptFunction *GDScriptByteCodeGenerator::write_end() {
-	append(GDScriptFunction::OPCODE_END);
+	append(GDScriptFunction::OPCODE_END, 0);
 
 
 	if (constant_map.size()) {
 	if (constant_map.size()) {
 		function->_constant_count = constant_map.size();
 		function->_constant_count = constant_map.size();
@@ -162,7 +162,7 @@ GDScriptFunction *GDScriptByteCodeGenerator::write_end() {
 		function->stack_debug = stack_debug;
 		function->stack_debug = stack_debug;
 	}
 	}
 	function->_stack_size = stack_max;
 	function->_stack_size = stack_max;
-	function->_call_size = call_max;
+	function->_instruction_args_size = instr_args_max;
 
 
 	ended = true;
 	ended = true;
 	return function;
 	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) {
 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_left_operand);
 	append(p_right_operand);
 	append(p_right_operand);
 	append(p_target);
 	append(p_target);
+	append(p_operator);
 }
 }
 
 
 void GDScriptByteCodeGenerator::write_type_test(const Address &p_target, const Address &p_source, const Address &p_type) {
 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_source);
 	append(p_type);
 	append(p_type);
 	append(p_target);
 	append(p_target);
 }
 }
 
 
 void GDScriptByteCodeGenerator::write_type_test_builtin(const Address &p_target, const Address &p_source, Variant::Type p_type) {
 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_source);
-	append(p_type);
 	append(p_target);
 	append(p_target);
+	append(p_type);
 }
 }
 
 
 void GDScriptByteCodeGenerator::write_and_left_operand(const Address &p_left_operand) {
 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);
 	append(p_left_operand);
 	logic_op_jump_pos1.push_back(opcodes.size());
 	logic_op_jump_pos1.push_back(opcodes.size());
 	append(0); // Jump target, will be patched.
 	append(0); // Jump target, will be patched.
 }
 }
 
 
 void GDScriptByteCodeGenerator::write_and_right_operand(const Address &p_right_operand) {
 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);
 	append(p_right_operand);
 	logic_op_jump_pos2.push_back(opcodes.size());
 	logic_op_jump_pos2.push_back(opcodes.size());
 	append(0); // Jump target, will be patched.
 	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) {
 void GDScriptByteCodeGenerator::write_end_and(const Address &p_target) {
 	// If here means both operands are true.
 	// If here means both operands are true.
-	append(GDScriptFunction::OPCODE_ASSIGN_TRUE);
+	append(GDScriptFunction::OPCODE_ASSIGN_TRUE, 1);
 	append(p_target);
 	append(p_target);
 	// Jump away from the fail condition.
 	// Jump away from the fail condition.
-	append(GDScriptFunction::OPCODE_JUMP);
+	append(GDScriptFunction::OPCODE_JUMP, 0);
 	append(opcodes.size() + 3);
 	append(opcodes.size() + 3);
 	// Here it means one of operands is false.
 	// Here it means one of operands is false.
 	patch_jump(logic_op_jump_pos1.back()->get());
 	patch_jump(logic_op_jump_pos1.back()->get());
 	patch_jump(logic_op_jump_pos2.back()->get());
 	patch_jump(logic_op_jump_pos2.back()->get());
 	logic_op_jump_pos1.pop_back();
 	logic_op_jump_pos1.pop_back();
 	logic_op_jump_pos2.pop_back();
 	logic_op_jump_pos2.pop_back();
-	append(GDScriptFunction::OPCODE_ASSIGN_FALSE);
+	append(GDScriptFunction::OPCODE_ASSIGN_FALSE, 0);
 	append(p_target);
 	append(p_target);
 }
 }
 
 
 void GDScriptByteCodeGenerator::write_or_left_operand(const Address &p_left_operand) {
 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);
 	append(p_left_operand);
 	logic_op_jump_pos1.push_back(opcodes.size());
 	logic_op_jump_pos1.push_back(opcodes.size());
 	append(0); // Jump target, will be patched.
 	append(0); // Jump target, will be patched.
 }
 }
 
 
 void GDScriptByteCodeGenerator::write_or_right_operand(const Address &p_right_operand) {
 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);
 	append(p_right_operand);
 	logic_op_jump_pos2.push_back(opcodes.size());
 	logic_op_jump_pos2.push_back(opcodes.size());
 	append(0); // Jump target, will be patched.
 	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) {
 void GDScriptByteCodeGenerator::write_end_or(const Address &p_target) {
 	// If here means both operands are false.
 	// If here means both operands are false.
-	append(GDScriptFunction::OPCODE_ASSIGN_FALSE);
+	append(GDScriptFunction::OPCODE_ASSIGN_FALSE, 1);
 	append(p_target);
 	append(p_target);
 	// Jump away from the success condition.
 	// Jump away from the success condition.
-	append(GDScriptFunction::OPCODE_JUMP);
+	append(GDScriptFunction::OPCODE_JUMP, 0);
 	append(opcodes.size() + 3);
 	append(opcodes.size() + 3);
 	// Here it means one of operands is false.
 	// Here it means one of operands is false.
 	patch_jump(logic_op_jump_pos1.back()->get());
 	patch_jump(logic_op_jump_pos1.back()->get());
 	patch_jump(logic_op_jump_pos2.back()->get());
 	patch_jump(logic_op_jump_pos2.back()->get());
 	logic_op_jump_pos1.pop_back();
 	logic_op_jump_pos1.pop_back();
 	logic_op_jump_pos2.pop_back();
 	logic_op_jump_pos2.pop_back();
-	append(GDScriptFunction::OPCODE_ASSIGN_TRUE);
+	append(GDScriptFunction::OPCODE_ASSIGN_TRUE, 1);
 	append(p_target);
 	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) {
 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);
 	append(p_condition);
 	ternary_jump_fail_pos.push_back(opcodes.size());
 	ternary_jump_fail_pos.push_back(opcodes.size());
 	append(0); // Jump target, will be patched.
 	append(0); // Jump target, will be patched.
 }
 }
 
 
 void GDScriptByteCodeGenerator::write_ternary_true_expr(const Address &p_expr) {
 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(ternary_result.back()->get());
 	append(p_expr);
 	append(p_expr);
 	// Jump away from the false path.
 	// Jump away from the false path.
-	append(GDScriptFunction::OPCODE_JUMP);
+	append(GDScriptFunction::OPCODE_JUMP, 0);
 	ternary_jump_skip_pos.push_back(opcodes.size());
 	ternary_jump_skip_pos.push_back(opcodes.size());
 	append(0);
 	append(0);
 	// Fail must jump here.
 	// 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) {
 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(ternary_result.back()->get());
 	append(p_expr);
 	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) {
 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_target);
 	append(p_index);
 	append(p_index);
 	append(p_source);
 	append(p_source);
 }
 }
 
 
 void GDScriptByteCodeGenerator::write_get(const Address &p_target, const Address &p_index, const Address &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_source);
 	append(p_index);
 	append(p_index);
 	append(p_target);
 	append(p_target);
 }
 }
 
 
 void GDScriptByteCodeGenerator::write_set_named(const Address &p_target, const StringName &p_name, const Address &p_source) {
 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_target);
-	append(p_name);
 	append(p_source);
 	append(p_source);
+	append(p_name);
 }
 }
 
 
 void GDScriptByteCodeGenerator::write_get_named(const Address &p_target, const StringName &p_name, const Address &p_source) {
 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_source);
-	append(p_name);
 	append(p_target);
 	append(p_target);
+	append(p_name);
 }
 }
 
 
 void GDScriptByteCodeGenerator::write_set_member(const Address &p_value, const StringName &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_value);
+	append(p_name);
 }
 }
 
 
 void GDScriptByteCodeGenerator::write_get_member(const Address &p_target, const StringName &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_target);
+	append(p_name);
 }
 }
 
 
 void GDScriptByteCodeGenerator::write_assign(const Address &p_target, const Address &p_source) {
 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.
 		// Typed assignment.
 		switch (p_target.type.kind) {
 		switch (p_target.type.kind) {
 			case GDScriptDataType::BUILTIN: {
 			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_target);
 				append(p_source);
 				append(p_source);
+				append(p_target.type.builtin_type);
 			} break;
 			} break;
 			case GDScriptDataType::NATIVE: {
 			case GDScriptDataType::NATIVE: {
 				int class_idx = GDScriptLanguage::get_singleton()->get_global_map()[p_target.type.native_type];
 				int class_idx = GDScriptLanguage::get_singleton()->get_global_map()[p_target.type.native_type];
 				class_idx |= (GDScriptFunction::ADDR_TYPE_GLOBAL << GDScriptFunction::ADDR_BITS);
 				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_target);
 				append(p_source);
 				append(p_source);
+				append(class_idx);
 			} break;
 			} break;
 			case GDScriptDataType::SCRIPT:
 			case GDScriptDataType::SCRIPT:
 			case GDScriptDataType::GDSCRIPT: {
 			case GDScriptDataType::GDSCRIPT: {
 				Variant script = p_target.type.script_type;
 				Variant script = p_target.type.script_type;
 				int idx = get_constant_pos(script);
 				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_target);
 				append(p_source);
 				append(p_source);
+				append(idx);
 			} break;
 			} break;
 			default: {
 			default: {
 				ERR_PRINT("Compiler bug: unresolved assign.");
 				ERR_PRINT("Compiler bug: unresolved assign.");
 
 
 				// Shouldn't get here, but fail-safe to a regular assignment
 				// 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_target);
 				append(p_source);
 				append(p_source);
 			}
 			}
@@ -375,13 +376,13 @@ void GDScriptByteCodeGenerator::write_assign(const Address &p_target, const Addr
 	} else {
 	} else {
 		if (p_target.type.kind == GDScriptDataType::BUILTIN && p_source.type.kind == GDScriptDataType::BUILTIN && p_target.type.builtin_type != p_source.type.builtin_type) {
 		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..
 			// 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_target);
 			append(p_source);
 			append(p_source);
+			append(p_target.type.builtin_type);
 		} else {
 		} else {
 			// Either untyped assignment or already type-checked by the parser
 			// Either untyped assignment or already type-checked by the parser
-			append(GDScriptFunction::OPCODE_ASSIGN);
+			append(GDScriptFunction::OPCODE_ASSIGN, 2);
 			append(p_target);
 			append(p_target);
 			append(p_source);
 			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) {
 void GDScriptByteCodeGenerator::write_assign_true(const Address &p_target) {
-	append(GDScriptFunction::OPCODE_ASSIGN_TRUE);
+	append(GDScriptFunction::OPCODE_ASSIGN_TRUE, 1);
 	append(p_target);
 	append(p_target);
 }
 }
 
 
 void GDScriptByteCodeGenerator::write_assign_false(const Address &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);
 	append(p_target);
 }
 }
 
 
 void GDScriptByteCodeGenerator::write_cast(const Address &p_target, const Address &p_source, const GDScriptDataType &p_type) {
 void GDScriptByteCodeGenerator::write_cast(const Address &p_target, const Address &p_source, const GDScriptDataType &p_type) {
+	int index = 0;
+
 	switch (p_type.kind) {
 	switch (p_type.kind) {
 		case GDScriptDataType::BUILTIN: {
 		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;
 		} break;
 		case GDScriptDataType::NATIVE: {
 		case GDScriptDataType::NATIVE: {
 			int class_idx = GDScriptLanguage::get_singleton()->get_global_map()[p_type.native_type];
 			int class_idx = GDScriptLanguage::get_singleton()->get_global_map()[p_type.native_type];
 			class_idx |= (GDScriptFunction::ADDR_TYPE_GLOBAL << GDScriptFunction::ADDR_BITS);
 			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;
 		} break;
 		case GDScriptDataType::SCRIPT:
 		case GDScriptDataType::SCRIPT:
 		case GDScriptDataType::GDSCRIPT: {
 		case GDScriptDataType::GDSCRIPT: {
 			Variant script = p_type.script_type;
 			Variant script = p_type.script_type;
 			int idx = get_constant_pos(script);
 			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;
 		} break;
 		default: {
 		default: {
 			return;
 			return;
@@ -425,147 +429,139 @@ void GDScriptByteCodeGenerator::write_cast(const Address &p_target, const Addres
 
 
 	append(p_source);
 	append(p_source);
 	append(p_target);
 	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) {
 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++) {
 	for (int i = 0; i < p_arguments.size(); i++) {
 		append(p_arguments[i]);
 		append(p_arguments[i]);
 	}
 	}
+	append(p_base);
 	append(p_target);
 	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) {
 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++) {
 	for (int i = 0; i < p_arguments.size(); i++) {
 		append(p_arguments[i]);
 		append(p_arguments[i]);
 	}
 	}
 	append(p_target);
 	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) {
 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++) {
 	for (int i = 0; i < p_arguments.size(); i++) {
 		append(p_arguments[i]);
 		append(p_arguments[i]);
 	}
 	}
+	append(p_base);
 	append(p_target);
 	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) {
 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++) {
 	for (int i = 0; i < p_arguments.size(); i++) {
 		append(p_arguments[i]);
 		append(p_arguments[i]);
 	}
 	}
 	append(p_target);
 	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) {
 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++) {
 	for (int i = 0; i < p_arguments.size(); i++) {
 		append(p_arguments[i]);
 		append(p_arguments[i]);
 	}
 	}
+	append(p_base);
 	append(p_target);
 	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) {
 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++) {
 	for (int i = 0; i < p_arguments.size(); i++) {
 		append(p_arguments[i]);
 		append(p_arguments[i]);
 	}
 	}
+	append(p_base);
 	append(p_target);
 	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) {
 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++) {
 	for (int i = 0; i < p_arguments.size(); i++) {
 		append(p_arguments[i]);
 		append(p_arguments[i]);
 	}
 	}
+	append(GDScriptFunction::ADDR_TYPE_SELF << GDScriptFunction::ADDR_BITS);
 	append(p_target);
 	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) {
 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++) {
 	for (int i = 0; i < p_arguments.size(); i++) {
 		append(p_arguments[i]);
 		append(p_arguments[i]);
 	}
 	}
+	append(p_base);
 	append(p_target);
 	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) {
 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++) {
 	for (int i = 0; i < p_arguments.size(); i++) {
 		append(p_arguments[i]);
 		append(p_arguments[i]);
 	}
 	}
 	append(p_target);
 	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) {
 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++) {
 	for (int i = 0; i < p_arguments.size(); i++) {
 		append(p_arguments[i]);
 		append(p_arguments[i]);
 	}
 	}
 	append(p_target);
 	append(p_target);
+	append(p_arguments.size());
 }
 }
 
 
 void GDScriptByteCodeGenerator::write_construct_dictionary(const Address &p_target, const Vector<Address> &p_arguments) {
 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++) {
 	for (int i = 0; i < p_arguments.size(); i++) {
 		append(p_arguments[i]);
 		append(p_arguments[i]);
 	}
 	}
 	append(p_target);
 	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) {
 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(p_operand);
-	append(GDScriptFunction::OPCODE_AWAIT_RESUME);
+	append(GDScriptFunction::OPCODE_AWAIT_RESUME, 1);
 	append(p_target);
 	append(p_target);
 }
 }
 
 
 void GDScriptByteCodeGenerator::write_if(const Address &p_condition) {
 void GDScriptByteCodeGenerator::write_if(const Address &p_condition) {
-	append(GDScriptFunction::OPCODE_JUMP_IF_NOT);
+	append(GDScriptFunction::OPCODE_JUMP_IF_NOT, 1);
 	append(p_condition);
 	append(p_condition);
 	if_jmp_addrs.push_back(opcodes.size());
 	if_jmp_addrs.push_back(opcodes.size());
 	append(0); // Jump destination, will be patched.
 	append(0); // Jump destination, will be patched.
 }
 }
 
 
 void GDScriptByteCodeGenerator::write_else() {
 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();
 	int else_jmp_addr = opcodes.size();
 	append(0); // Jump destination, will be patched.
 	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>());
 	current_breaks_to_patch.push_back(List<int>());
 
 
 	// Assign container.
 	// Assign container.
-	append(GDScriptFunction::OPCODE_ASSIGN);
+	append(GDScriptFunction::OPCODE_ASSIGN, 2);
 	append(container_pos);
 	append(container_pos);
 	append(p_list);
 	append(p_list);
 
 
 	// Begin loop.
 	// Begin loop.
-	append(GDScriptFunction::OPCODE_ITERATE_BEGIN);
+	append(GDScriptFunction::OPCODE_ITERATE_BEGIN, 3);
 	append(counter_pos);
 	append(counter_pos);
 	append(container_pos);
 	append(container_pos);
+	append(p_variable);
 	for_jmp_addrs.push_back(opcodes.size());
 	for_jmp_addrs.push_back(opcodes.size());
 	append(0); // End of loop address, will be patched.
 	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.
 	append(opcodes.size() + 6); // Skip over 'continue' code.
 
 
 	// Next iteration.
 	// Next iteration.
 	int continue_addr = opcodes.size();
 	int continue_addr = opcodes.size();
 	continue_addrs.push_back(continue_addr);
 	continue_addrs.push_back(continue_addr);
-	append(GDScriptFunction::OPCODE_ITERATE);
+	append(GDScriptFunction::OPCODE_ITERATE, 3);
 	append(counter_pos);
 	append(counter_pos);
 	append(container_pos);
 	append(container_pos);
+	append(p_variable);
 	for_jmp_addrs.push_back(opcodes.size());
 	for_jmp_addrs.push_back(opcodes.size());
 	append(0); // Jump destination, will be patched.
 	append(0); // Jump destination, will be patched.
-	append(p_variable);
 }
 }
 
 
 void GDScriptByteCodeGenerator::write_endfor() {
 void GDScriptByteCodeGenerator::write_endfor() {
 	// Jump back to loop check.
 	// Jump back to loop check.
-	append(GDScriptFunction::OPCODE_JUMP);
+	append(GDScriptFunction::OPCODE_JUMP, 0);
 	append(continue_addrs.back()->get());
 	append(continue_addrs.back()->get());
 	continue_addrs.pop_back();
 	continue_addrs.pop_back();
 
 
@@ -641,7 +637,7 @@ void GDScriptByteCodeGenerator::start_while_condition() {
 
 
 void GDScriptByteCodeGenerator::write_while(const Address &p_condition) {
 void GDScriptByteCodeGenerator::write_while(const Address &p_condition) {
 	// Condition check.
 	// Condition check.
-	append(GDScriptFunction::OPCODE_JUMP_IF_NOT);
+	append(GDScriptFunction::OPCODE_JUMP_IF_NOT, 1);
 	append(p_condition);
 	append(p_condition);
 	while_jmp_addrs.push_back(opcodes.size());
 	while_jmp_addrs.push_back(opcodes.size());
 	append(0); // End of loop address, will be patched.
 	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() {
 void GDScriptByteCodeGenerator::write_endwhile() {
 	// Jump back to loop check.
 	// Jump back to loop check.
-	append(GDScriptFunction::OPCODE_JUMP);
+	append(GDScriptFunction::OPCODE_JUMP, 0);
 	append(continue_addrs.back()->get());
 	append(continue_addrs.back()->get());
 	continue_addrs.pop_back();
 	continue_addrs.pop_back();
 
 
@@ -687,39 +683,39 @@ void GDScriptByteCodeGenerator::end_match() {
 }
 }
 
 
 void GDScriptByteCodeGenerator::write_break() {
 void GDScriptByteCodeGenerator::write_break() {
-	append(GDScriptFunction::OPCODE_JUMP);
+	append(GDScriptFunction::OPCODE_JUMP, 0);
 	current_breaks_to_patch.back()->get().push_back(opcodes.size());
 	current_breaks_to_patch.back()->get().push_back(opcodes.size());
 	append(0);
 	append(0);
 }
 }
 
 
 void GDScriptByteCodeGenerator::write_continue() {
 void GDScriptByteCodeGenerator::write_continue() {
-	append(GDScriptFunction::OPCODE_JUMP);
+	append(GDScriptFunction::OPCODE_JUMP, 0);
 	append(continue_addrs.back()->get());
 	append(continue_addrs.back()->get());
 }
 }
 
 
 void GDScriptByteCodeGenerator::write_continue_match() {
 void GDScriptByteCodeGenerator::write_continue_match() {
-	append(GDScriptFunction::OPCODE_JUMP);
+	append(GDScriptFunction::OPCODE_JUMP, 0);
 	match_continues_to_patch.back()->get().push_back(opcodes.size());
 	match_continues_to_patch.back()->get().push_back(opcodes.size());
 	append(0);
 	append(0);
 }
 }
 
 
 void GDScriptByteCodeGenerator::write_breakpoint() {
 void GDScriptByteCodeGenerator::write_breakpoint() {
-	append(GDScriptFunction::OPCODE_BREAKPOINT);
+	append(GDScriptFunction::OPCODE_BREAKPOINT, 0);
 }
 }
 
 
 void GDScriptByteCodeGenerator::write_newline(int p_line) {
 void GDScriptByteCodeGenerator::write_newline(int p_line) {
-	append(GDScriptFunction::OPCODE_LINE);
+	append(GDScriptFunction::OPCODE_LINE, 0);
 	append(p_line);
 	append(p_line);
 	current_line = p_line;
 	current_line = p_line;
 }
 }
 
 
 void GDScriptByteCodeGenerator::write_return(const Address &p_return_value) {
 void GDScriptByteCodeGenerator::write_return(const Address &p_return_value) {
-	append(GDScriptFunction::OPCODE_RETURN);
+	append(GDScriptFunction::OPCODE_RETURN, 1);
 	append(p_return_value);
 	append(p_return_value);
 }
 }
 
 
 void GDScriptByteCodeGenerator::write_assert(const Address &p_test, const Address &p_message) {
 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_test);
 	append(p_message);
 	append(p_message);
 }
 }

+ 10 - 8
modules/gdscript/gdscript_byte_codegen.h

@@ -33,6 +33,8 @@
 
 
 #include "gdscript_codegen.h"
 #include "gdscript_codegen.h"
 
 
+#include "gdscript_function.h"
+
 class GDScriptByteCodeGenerator : public GDScriptCodeGenerator {
 class GDScriptByteCodeGenerator : public GDScriptCodeGenerator {
 	bool ended = false;
 	bool ended = false;
 	GDScriptFunction *function = nullptr;
 	GDScriptFunction *function = nullptr;
@@ -57,7 +59,7 @@ class GDScriptByteCodeGenerator : public GDScriptCodeGenerator {
 #endif
 #endif
 	int current_line = 0;
 	int current_line = 0;
 	int stack_max = 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> if_jmp_addrs; // List since this can be nested.
 	List<int> for_jmp_addrs;
 	List<int> for_jmp_addrs;
@@ -139,11 +141,6 @@ class GDScriptByteCodeGenerator : public GDScriptCodeGenerator {
 			stack_max = p_level + 1;
 			stack_max = p_level + 1;
 	}
 	}
 
 
-	void alloc_call(int p_params) {
-		if (p_params >= call_max)
-			call_max = p_params;
-	}
-
 	int increase_stack() {
 	int increase_stack() {
 		int top = current_stack_size++;
 		int top = current_stack_size++;
 		alloc_stack(current_stack_size);
 		alloc_stack(current_stack_size);
@@ -177,8 +174,13 @@ class GDScriptByteCodeGenerator : public GDScriptCodeGenerator {
 		return -1; // Unreachable.
 		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) {
 	void append(const Address &p_address) {

+ 63 - 62
modules/gdscript/gdscript_disassembler.cpp

@@ -117,21 +117,22 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const {
 		text += ": ";
 		text += ": ";
 
 
 		// This makes the compiler complain if some opcode is unchecked in the switch.
 		// 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) {
 		switch (code) {
 			case OPCODE_OPERATOR: {
 			case OPCODE_OPERATOR: {
-				int operation = _code_ptr[ip + 1];
+				int operation = _code_ptr[ip + 4];
 
 
 				text += "operator ";
 				text += "operator ";
 
 
-				text += DADDR(4);
+				text += DADDR(3);
 				text += " = ";
 				text += " = ";
-				text += DADDR(2);
+				text += DADDR(1);
 				text += " ";
 				text += " ";
 				text += Variant::get_operator_name(Variant::Operator(operation));
 				text += Variant::get_operator_name(Variant::Operator(operation));
 				text += " ";
 				text += " ";
-				text += DADDR(3);
+				text += DADDR(2);
 
 
 				incr += 5;
 				incr += 5;
 			} break;
 			} break;
@@ -147,11 +148,11 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const {
 			} break;
 			} break;
 			case OPCODE_IS_BUILTIN: {
 			case OPCODE_IS_BUILTIN: {
 				text += "is builtin ";
 				text += "is builtin ";
-				text += DADDR(3);
+				text += DADDR(2);
 				text += " = ";
 				text += " = ";
 				text += DADDR(1);
 				text += DADDR(1);
 				text += " is ";
 				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;
 				incr += 4;
 			} break;
 			} break;
@@ -180,19 +181,19 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const {
 				text += "set_named ";
 				text += "set_named ";
 				text += DADDR(1);
 				text += DADDR(1);
 				text += "[\"";
 				text += "[\"";
-				text += _global_names_ptr[_code_ptr[ip + 2]];
+				text += _global_names_ptr[_code_ptr[ip + 3]];
 				text += "\"] = ";
 				text += "\"] = ";
-				text += DADDR(3);
+				text += DADDR(2);
 
 
 				incr += 4;
 				incr += 4;
 			} break;
 			} break;
 			case OPCODE_GET_NAMED: {
 			case OPCODE_GET_NAMED: {
 				text += "get_named ";
 				text += "get_named ";
-				text += DADDR(3);
+				text += DADDR(2);
 				text += " = ";
 				text += " = ";
 				text += DADDR(1);
 				text += DADDR(1);
 				text += "[\"";
 				text += "[\"";
-				text += _global_names_ptr[_code_ptr[ip + 2]];
+				text += _global_names_ptr[_code_ptr[ip + 3]];
 				text += "\"]";
 				text += "\"]";
 
 
 				incr += 4;
 				incr += 4;
@@ -200,18 +201,18 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const {
 			case OPCODE_SET_MEMBER: {
 			case OPCODE_SET_MEMBER: {
 				text += "set_member ";
 				text += "set_member ";
 				text += "[\"";
 				text += "[\"";
-				text += _global_names_ptr[_code_ptr[ip + 1]];
+				text += _global_names_ptr[_code_ptr[ip + 2]];
 				text += "\"] = ";
 				text += "\"] = ";
-				text += DADDR(2);
+				text += DADDR(1);
 
 
 				incr += 3;
 				incr += 3;
 			} break;
 			} break;
 			case OPCODE_GET_MEMBER: {
 			case OPCODE_GET_MEMBER: {
 				text += "get_member ";
 				text += "get_member ";
-				text += DADDR(2);
+				text += DADDR(1);
 				text += " = ";
 				text += " = ";
 				text += "[\"";
 				text += "[\"";
-				text += _global_names_ptr[_code_ptr[ip + 1]];
+				text += _global_names_ptr[_code_ptr[ip + 2]];
 				text += "\"]";
 				text += "\"]";
 
 
 				incr += 3;
 				incr += 3;
@@ -240,45 +241,45 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const {
 			} break;
 			} break;
 			case OPCODE_ASSIGN_TYPED_BUILTIN: {
 			case OPCODE_ASSIGN_TYPED_BUILTIN: {
 				text += "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 += ") ";
-				text += DADDR(2);
+				text += DADDR(1);
 				text += " = ";
 				text += " = ";
-				text += DADDR(3);
+				text += DADDR(2);
 
 
 				incr += 4;
 				incr += 4;
 			} break;
 			} break;
 			case OPCODE_ASSIGN_TYPED_NATIVE: {
 			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 *());
 				GDScriptNativeClass *nc = Object::cast_to<GDScriptNativeClass>(class_name.operator Object *());
 
 
 				text += "assign typed native (";
 				text += "assign typed native (";
 				text += nc->get_name().operator String();
 				text += nc->get_name().operator String();
 				text += ") ";
 				text += ") ";
-				text += DADDR(2);
+				text += DADDR(1);
 				text += " = ";
 				text += " = ";
-				text += DADDR(3);
+				text += DADDR(2);
 
 
 				incr += 4;
 				incr += 4;
 			} break;
 			} break;
 			case OPCODE_ASSIGN_TYPED_SCRIPT: {
 			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 *());
 				Script *sc = Object::cast_to<Script>(script.operator Object *());
 
 
 				text += "assign typed script (";
 				text += "assign typed script (";
 				text += sc->get_path();
 				text += sc->get_path();
 				text += ") ";
 				text += ") ";
-				text += DADDR(2);
+				text += DADDR(1);
 				text += " = ";
 				text += " = ";
-				text += DADDR(3);
+				text += DADDR(2);
 
 
 				incr += 4;
 				incr += 4;
 			} break;
 			} break;
 			case OPCODE_CAST_TO_BUILTIN: {
 			case OPCODE_CAST_TO_BUILTIN: {
 				text += "cast builtin ";
 				text += "cast builtin ";
-				text += DADDR(3);
-				text += " = ";
 				text += DADDR(2);
 				text += DADDR(2);
+				text += " = ";
+				text += DADDR(1);
 				text += " as ";
 				text += " as ";
 				text += Variant::get_type_name(Variant::Type(_code_ptr[ip + 1]));
 				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 *());
 				GDScriptNativeClass *nc = Object::cast_to<GDScriptNativeClass>(class_name.operator Object *());
 
 
 				text += "cast native ";
 				text += "cast native ";
-				text += DADDR(3);
-				text += " = ";
 				text += DADDR(2);
 				text += DADDR(2);
+				text += " = ";
+				text += DADDR(1);
 				text += " as ";
 				text += " as ";
 				text += nc->get_name();
 				text += nc->get_name();
 
 
@@ -299,42 +300,42 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const {
 			} break;
 			} break;
 			case OPCODE_CAST_TO_SCRIPT: {
 			case OPCODE_CAST_TO_SCRIPT: {
 				text += "cast ";
 				text += "cast ";
-				text += DADDR(3);
-				text += " = ";
 				text += DADDR(2);
 				text += DADDR(2);
-				text += " as ";
+				text += " = ";
 				text += DADDR(1);
 				text += DADDR(1);
+				text += " as ";
+				text += DADDR(3);
 
 
 				incr += 4;
 				incr += 4;
 			} break;
 			} break;
 			case OPCODE_CONSTRUCT: {
 			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 += "construct ";
-				text += DADDR(3 + argc);
+				text += DADDR(1 + argc);
 				text += " = ";
 				text += " = ";
 
 
 				text += Variant::get_type_name(t) + "(";
 				text += Variant::get_type_name(t) + "(";
 				for (int i = 0; i < argc; i++) {
 				for (int i = 0; i < argc; i++) {
 					if (i > 0)
 					if (i > 0)
 						text += ", ";
 						text += ", ";
-					text += DADDR(i + 3);
+					text += DADDR(i + 1);
 				}
 				}
 				text += ")";
 				text += ")";
 
 
-				incr = 4 + argc;
+				incr = 3 + instr_var_args;
 			} break;
 			} break;
 			case OPCODE_CONSTRUCT_ARRAY: {
 			case OPCODE_CONSTRUCT_ARRAY: {
-				int argc = _code_ptr[ip + 1];
+				int argc = _code_ptr[ip + 1 + instr_var_args];
 				text += " make_array ";
 				text += " make_array ";
-				text += DADDR(2 + argc);
+				text += DADDR(1 + argc);
 				text += " = [";
 				text += " = [";
 
 
 				for (int i = 0; i < argc; i++) {
 				for (int i = 0; i < argc; i++) {
 					if (i > 0)
 					if (i > 0)
 						text += ", ";
 						text += ", ";
-					text += DADDR(2 + i);
+					text += DADDR(1 + i);
 				}
 				}
 
 
 				text += "]";
 				text += "]";
@@ -342,17 +343,17 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const {
 				incr += 3 + argc;
 				incr += 3 + argc;
 			} break;
 			} break;
 			case OPCODE_CONSTRUCT_DICTIONARY: {
 			case OPCODE_CONSTRUCT_DICTIONARY: {
-				int argc = _code_ptr[ip + 1];
+				int argc = _code_ptr[ip + 1 + instr_var_args];
 				text += "make_dict ";
 				text += "make_dict ";
-				text += DADDR(2 + argc * 2);
+				text += DADDR(1 + argc * 2);
 				text += " = {";
 				text += " = {";
 
 
 				for (int i = 0; i < argc; i++) {
 				for (int i = 0; i < argc; i++) {
 					if (i > 0)
 					if (i > 0)
 						text += ", ";
 						text += ", ";
-					text += DADDR(2 + i * 2 + 0);
+					text += DADDR(1 + i * 2 + 0);
 					text += ": ";
 					text += ": ";
-					text += DADDR(2 + i * 2 + 1);
+					text += DADDR(1 + i * 2 + 1);
 				}
 				}
 
 
 				text += "}";
 				text += "}";
@@ -362,8 +363,8 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const {
 			case OPCODE_CALL:
 			case OPCODE_CALL:
 			case OPCODE_CALL_RETURN:
 			case OPCODE_CALL_RETURN:
 			case OPCODE_CALL_ASYNC: {
 			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) {
 				if (ret) {
 					text += "call-ret ";
 					text += "call-ret ";
@@ -373,19 +374,19 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const {
 					text += "call ";
 					text += "call ";
 				}
 				}
 
 
-				int argc = _code_ptr[ip + 1];
+				int argc = _code_ptr[ip + 1 + instr_var_args];
 				if (ret || async) {
 				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 += "(";
 				text += "(";
 
 
 				for (int i = 0; i < argc; i++) {
 				for (int i = 0; i < argc; i++) {
 					if (i > 0)
 					if (i > 0)
 						text += ", ";
 						text += ", ";
-					text += DADDR(4 + i);
+					text += DADDR(1 + i);
 				}
 				}
 				text += ")";
 				text += ")";
 
 
@@ -394,16 +395,16 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const {
 			case OPCODE_CALL_BUILT_IN: {
 			case OPCODE_CALL_BUILT_IN: {
 				text += "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 += "(";
 				text += "(";
 
 
 				for (int i = 0; i < argc; i++) {
 				for (int i = 0; i < argc; i++) {
 					if (i > 0)
 					if (i > 0)
 						text += ", ";
 						text += ", ";
-					text += DADDR(3 + i);
+					text += DADDR(1 + i);
 				}
 				}
 				text += ")";
 				text += ")";
 
 
@@ -412,16 +413,16 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const {
 			case OPCODE_CALL_SELF_BASE: {
 			case OPCODE_CALL_SELF_BASE: {
 				text += "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 += "(";
 				text += "(";
 
 
 				for (int i = 0; i < argc; i++) {
 				for (int i = 0; i < argc; i++) {
 					if (i > 0)
 					if (i > 0)
 						text += ", ";
 						text += ", ";
-					text += DADDR(3 + i);
+					text += DADDR(1 + i);
 				}
 				}
 				text += ")";
 				text += ")";
 
 
@@ -474,25 +475,25 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const {
 			} break;
 			} break;
 			case OPCODE_ITERATE_BEGIN: {
 			case OPCODE_ITERATE_BEGIN: {
 				text += "for-init ";
 				text += "for-init ";
-				text += DADDR(4);
+				text += DADDR(3);
 				text += " in ";
 				text += " in ";
 				text += DADDR(2);
 				text += DADDR(2);
 				text += " counter ";
 				text += " counter ";
 				text += DADDR(1);
 				text += DADDR(1);
 				text += " end ";
 				text += " end ";
-				text += itos(_code_ptr[ip + 3]);
+				text += itos(_code_ptr[ip + 4]);
 
 
 				incr += 5;
 				incr += 5;
 			} break;
 			} break;
 			case OPCODE_ITERATE: {
 			case OPCODE_ITERATE: {
 				text += "for-loop ";
 				text += "for-loop ";
-				text += DADDR(4);
+				text += DADDR(2);
 				text += " in ";
 				text += " in ";
 				text += DADDR(2);
 				text += DADDR(2);
 				text += " counter ";
 				text += " counter ";
 				text += DADDR(1);
 				text += DADDR(1);
 				text += " end ";
 				text += " end ";
-				text += itos(_code_ptr[ip + 3]);
+				text += itos(_code_ptr[ip + 4]);
 
 
 				incr += 5;
 				incr += 5;
 			} break;
 			} break;

+ 1 - 19
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>";
 	name = "<anonymous>";
 #ifdef DEBUG_ENABLED
 #ifdef DEBUG_ENABLED
-	_func_cname = nullptr;
-
 	{
 	{
 		MutexLock lock(GDScriptLanguage::get_singleton()->lock);
 		MutexLock lock(GDScriptLanguage::get_singleton()->lock);
-
 		GDScriptLanguage::get_singleton()->function_list.add(&function_list);
 		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
 #endif
 }
 }
 
 

+ 33 - 27
modules/gdscript/gdscript_function.h

@@ -215,6 +215,12 @@ public:
 		ADDR_TYPE_NIL = 9
 		ADDR_TYPE_NIL = 9
 	};
 	};
 
 
+	enum Instruction {
+		INSTR_BITS = 20,
+		INSTR_MASK = ((1 << INSTR_BITS) - 1),
+		INSTR_ARGS_MASK = ~INSTR_MASK,
+	};
+
 	struct StackDebug {
 	struct StackDebug {
 		int line;
 		int line;
 		int pos;
 		int pos;
@@ -229,22 +235,22 @@ private:
 	StringName source;
 	StringName source;
 
 
 	mutable Variant nil;
 	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;
 	StringName name;
 	Vector<Variant> constants;
 	Vector<Variant> constants;
@@ -265,22 +271,22 @@ private:
 
 
 	friend class GDScriptLanguage;
 	friend class GDScriptLanguage;
 
 
-	SelfList<GDScriptFunction> function_list;
+	SelfList<GDScriptFunction> function_list{ this };
 #ifdef DEBUG_ENABLED
 #ifdef DEBUG_ENABLED
 	CharString func_cname;
 	CharString func_cname;
-	const char *_func_cname;
+	const char *_func_cname = nullptr;
 
 
 	struct Profile {
 	struct Profile {
 		StringName signature;
 		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;
 	} profile;
 
 
 #endif
 #endif

+ 143 - 150
modules/gdscript/gdscript_vm.cpp

@@ -231,13 +231,14 @@ String GDScriptFunction::_get_call_error(const Callable::CallError &p_err, const
 
 
 #define OPCODE(m_op) \
 #define OPCODE(m_op) \
 	m_op:
 	m_op:
-#define OPCODE_WHILE(m_test)
+#define OPCODE_WHILE(m_test) \
+	OPSWHILE:
 #define OPCODES_END \
 #define OPCODES_END \
 	OPSEXIT:
 	OPSEXIT:
 #define OPCODES_OUT \
 #define OPCODES_OUT \
 	OPSOUT:
 	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_BREAK goto OPSEXIT
 #define OPCODE_OUT goto OPSOUT
 #define OPCODE_OUT goto OPSOUT
 #else
 #else
@@ -265,7 +266,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
 	Variant static_ref;
 	Variant static_ref;
 	Variant retvalue;
 	Variant retvalue;
 	Variant *stack = nullptr;
 	Variant *stack = nullptr;
-	Variant **call_args;
+	Variant **instruction_args;
 	int defarg = 0;
 	int defarg = 0;
 
 
 #ifdef DEBUG_ENABLED
 #ifdef DEBUG_ENABLED
@@ -282,7 +283,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
 	if (p_state) {
 	if (p_state) {
 		//use existing (supplied) state (awaited)
 		//use existing (supplied) state (awaited)
 		stack = (Variant *)p_state->stack.ptr();
 		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;
 		line = p_state->line;
 		ip = p_state->ip;
 		ip = p_state->ip;
 		alloca_size = p_state->stack.size();
 		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) {
 		if (alloca_size) {
 			uint8_t *aptr = (uint8_t *)alloca(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;
 				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 {
 			} else {
-				call_args = nullptr;
+				instruction_args = nullptr;
 			}
 			}
 
 
 		} else {
 		} else {
 			stack = nullptr;
 			stack = nullptr;
-			call_args = nullptr;
+			instruction_args = nullptr;
 		}
 		}
 
 
 		if (p_instance) {
 		if (p_instance) {
@@ -400,6 +401,9 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
 
 
 #endif
 #endif
 
 
+#define GET_INSTRUCTION_ARG(m_v, m_idx) \
+	Variant *m_v = instruction_args[m_idx]
+
 #ifdef DEBUG_ENABLED
 #ifdef DEBUG_ENABLED
 
 
 	uint64_t function_start_time = 0;
 	uint64_t function_start_time = 0;
@@ -421,18 +425,24 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
 #else
 #else
 	OPCODE_WHILE(true) {
 	OPCODE_WHILE(true) {
 #endif
 #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) {
 			OPCODE(OPCODE_OPERATOR) {
 				CHECK_SPACE(5);
 				CHECK_SPACE(5);
 
 
 				bool valid;
 				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);
 				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
 #ifdef DEBUG_ENABLED
 
 
@@ -461,9 +471,9 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
 			OPCODE(OPCODE_EXTENDS_TEST) {
 			OPCODE(OPCODE_EXTENDS_TEST) {
 				CHECK_SPACE(4);
 				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
 #ifdef DEBUG_ENABLED
 				if (b->get_type() != Variant::OBJECT || b->operator Object *() == nullptr) {
 				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) {
 			OPCODE(OPCODE_IS_BUILTIN) {
 				CHECK_SPACE(4);
 				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);
 				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) {
 			OPCODE(OPCODE_SET) {
 				CHECK_SPACE(3);
 				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;
 				bool valid;
 				dst->set(*index, *value, &valid);
 				dst->set(*index, *value, &valid);
@@ -576,9 +586,9 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
 			OPCODE(OPCODE_GET) {
 			OPCODE(OPCODE_GET) {
 				CHECK_SPACE(3);
 				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;
 				bool valid;
 #ifdef DEBUG_ENABLED
 #ifdef DEBUG_ENABLED
@@ -608,10 +618,10 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
 			OPCODE(OPCODE_SET_NAMED) {
 			OPCODE(OPCODE_SET_NAMED) {
 				CHECK_SPACE(3);
 				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);
 				GD_ERR_BREAK(indexname < 0 || indexname >= _global_names_count);
 				const StringName *index = &_global_names_ptr[indexname];
 				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) {
 			OPCODE(OPCODE_GET_NAMED) {
 				CHECK_SPACE(4);
 				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);
 				GD_ERR_BREAK(indexname < 0 || indexname >= _global_names_count);
 				const StringName *index = &_global_names_ptr[indexname];
 				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) {
 			OPCODE(OPCODE_SET_MEMBER) {
 				CHECK_SPACE(3);
 				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);
 				GD_ERR_BREAK(indexname < 0 || indexname >= _global_names_count);
 				const StringName *index = &_global_names_ptr[indexname];
 				const StringName *index = &_global_names_ptr[indexname];
-				GET_VARIANT_PTR(src, 2);
 
 
 				bool valid;
 				bool valid;
 #ifndef DEBUG_ENABLED
 #ifndef DEBUG_ENABLED
@@ -690,11 +700,10 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
 
 
 			OPCODE(OPCODE_GET_MEMBER) {
 			OPCODE(OPCODE_GET_MEMBER) {
 				CHECK_SPACE(3);
 				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);
 				GD_ERR_BREAK(indexname < 0 || indexname >= _global_names_count);
 				const StringName *index = &_global_names_ptr[indexname];
 				const StringName *index = &_global_names_ptr[indexname];
-				GET_VARIANT_PTR(dst, 2);
-
 #ifndef DEBUG_ENABLED
 #ifndef DEBUG_ENABLED
 				ClassDB::get_property(p_instance->owner, *index, *dst);
 				ClassDB::get_property(p_instance->owner, *index, *dst);
 #else
 #else
@@ -710,8 +719,8 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
 
 
 			OPCODE(OPCODE_ASSIGN) {
 			OPCODE(OPCODE_ASSIGN) {
 				CHECK_SPACE(3);
 				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;
 				*dst = *src;
 
 
@@ -721,7 +730,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
 
 
 			OPCODE(OPCODE_ASSIGN_TRUE) {
 			OPCODE(OPCODE_ASSIGN_TRUE) {
 				CHECK_SPACE(2);
 				CHECK_SPACE(2);
-				GET_VARIANT_PTR(dst, 1);
+				GET_INSTRUCTION_ARG(dst, 0);
 
 
 				*dst = true;
 				*dst = true;
 
 
@@ -731,7 +740,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
 
 
 			OPCODE(OPCODE_ASSIGN_FALSE) {
 			OPCODE(OPCODE_ASSIGN_FALSE) {
 				CHECK_SPACE(2);
 				CHECK_SPACE(2);
-				GET_VARIANT_PTR(dst, 1);
+				GET_INSTRUCTION_ARG(dst, 0);
 
 
 				*dst = false;
 				*dst = false;
 
 
@@ -741,10 +750,10 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
 
 
 			OPCODE(OPCODE_ASSIGN_TYPED_BUILTIN) {
 			OPCODE(OPCODE_ASSIGN_TYPED_BUILTIN) {
 				CHECK_SPACE(4);
 				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);
 				GD_ERR_BREAK(var_type < 0 || var_type >= Variant::VARIANT_MAX);
 
 
 				if (src->get_type() != var_type) {
 				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) {
 			OPCODE(OPCODE_ASSIGN_TYPED_NATIVE) {
 				CHECK_SPACE(4);
 				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
 #ifdef DEBUG_ENABLED
-				GET_VARIANT_PTR(type, 1);
+				GET_INSTRUCTION_ARG(type, 2);
 				GDScriptNativeClass *nc = Object::cast_to<GDScriptNativeClass>(type->operator Object *());
 				GDScriptNativeClass *nc = Object::cast_to<GDScriptNativeClass>(type->operator Object *());
 				GD_ERR_BREAK(!nc);
 				GD_ERR_BREAK(!nc);
 				if (src->get_type() != Variant::OBJECT && src->get_type() != Variant::NIL) {
 				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) {
 			OPCODE(OPCODE_ASSIGN_TYPED_SCRIPT) {
 				CHECK_SPACE(4);
 				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
 #ifdef DEBUG_ENABLED
-				GET_VARIANT_PTR(type, 1);
+				GET_INSTRUCTION_ARG(type, 2);
 				Script *base_type = Object::cast_to<Script>(type->operator Object *());
 				Script *base_type = Object::cast_to<Script>(type->operator Object *());
 
 
 				GD_ERR_BREAK(!base_type);
 				GD_ERR_BREAK(!base_type);
@@ -847,9 +856,9 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
 
 
 			OPCODE(OPCODE_CAST_TO_BUILTIN) {
 			OPCODE(OPCODE_CAST_TO_BUILTIN) {
 				CHECK_SPACE(4);
 				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);
 				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) {
 			OPCODE(OPCODE_CAST_TO_NATIVE) {
 				CHECK_SPACE(4);
 				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 *());
 				GDScriptNativeClass *nc = Object::cast_to<GDScriptNativeClass>(to_type->operator Object *());
 				GD_ERR_BREAK(!nc);
 				GD_ERR_BREAK(!nc);
@@ -896,9 +905,9 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
 
 
 			OPCODE(OPCODE_CAST_TO_SCRIPT) {
 			OPCODE(OPCODE_CAST_TO_SCRIPT) {
 				CHECK_SPACE(4);
 				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 *());
 				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;
 			DISPATCH_OPCODE;
 
 
 			OPCODE(OPCODE_CONSTRUCT) {
 			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;
 				Callable::CallError err;
 				Variant::construct(t, *dst, (const Variant **)argptrs, argc, 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
 #endif
 
 
-				ip += 4 + argc;
-				//construct a basic type
+				ip += 3;
 			}
 			}
 			DISPATCH_OPCODE;
 			DISPATCH_OPCODE;
 
 
 			OPCODE(OPCODE_CONSTRUCT_ARRAY) {
 			OPCODE(OPCODE_CONSTRUCT_ARRAY) {
-				CHECK_SPACE(1);
+				CHECK_SPACE(1 + instr_arg_count);
+				ip += instr_arg_count;
+
 				int argc = _code_ptr[ip + 1];
 				int argc = _code_ptr[ip + 1];
-				Array array; //arrays are always shared
+				Array array;
 				array.resize(argc);
 				array.resize(argc);
-				CHECK_SPACE(argc + 2);
 
 
 				for (int i = 0; i < argc; i++) {
 				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;
 				*dst = array;
 
 
-				ip += 3 + argc;
+				ip += 2;
 			}
 			}
 			DISPATCH_OPCODE;
 			DISPATCH_OPCODE;
 
 
 			OPCODE(OPCODE_CONSTRUCT_DICTIONARY) {
 			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++) {
 				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;
 					dict[*k] = *v;
 				}
 				}
 
 
-				GET_VARIANT_PTR(dst, 2 + argc * 2);
+				GET_INSTRUCTION_ARG(dst, argc * 2);
 
 
 				*dst = dict;
 				*dst = dict;
 
 
-				ip += 3 + argc * 2;
+				ip += 2;
 			}
 			}
 			DISPATCH_OPCODE;
 			DISPATCH_OPCODE;
 
 
 			OPCODE(OPCODE_CALL_ASYNC)
 			OPCODE(OPCODE_CALL_ASYNC)
 			OPCODE(OPCODE_CALL_RETURN)
 			OPCODE(OPCODE_CALL_RETURN)
 			OPCODE(OPCODE_CALL) {
 			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
 #ifdef DEBUG_ENABLED
-				bool call_async = _code_ptr[ip] == OPCODE_CALL_ASYNC;
+				bool call_async = (_code_ptr[ip] & INSTR_MASK) == OPCODE_CALL_ASYNC;
 #endif
 #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);
 				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
 #ifdef DEBUG_ENABLED
 				uint64_t call_time = 0;
 				uint64_t call_time = 0;
@@ -1043,7 +1047,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
 #endif
 #endif
 				Callable::CallError err;
 				Callable::CallError err;
 				if (call_ret) {
 				if (call_ret) {
-					GET_VARIANT_PTR(ret, argc);
+					GET_INSTRUCTION_ARG(ret, argc + 1);
 					base->call(*methodname, (const Variant **)argptrs, argc, *ret, err);
 					base->call(*methodname, (const Variant **)argptrs, argc, *ret, err);
 #ifdef DEBUG_ENABLED
 #ifdef DEBUG_ENABLED
 					if (!call_async && ret->get_type() == Variant::OBJECT) {
 					if (!call_async && ret->get_type() == Variant::OBJECT) {
@@ -1104,31 +1108,24 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
 				}
 				}
 #endif
 #endif
 
 
-				//_call_func(nullptr,base,*methodname,ip,argc,p_instance,stack);
-				ip += argc + 1;
+				ip += 3;
 			}
 			}
 			DISPATCH_OPCODE;
 			DISPATCH_OPCODE;
 
 
 			OPCODE(OPCODE_CALL_BUILT_IN) {
 			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;
 				Callable::CallError err;
-
 				GDScriptFunctions::call(func, (const Variant **)argptrs, argc, *dst, err);
 				GDScriptFunctions::call(func, (const Variant **)argptrs, argc, *dst, err);
 
 
 #ifdef DEBUG_ENABLED
 #ifdef DEBUG_ENABLED
@@ -1143,14 +1140,16 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
 					OPCODE_BREAK;
 					OPCODE_BREAK;
 				}
 				}
 #endif
 #endif
-				ip += argc + 1;
+				ip += 3;
 			}
 			}
 			DISPATCH_OPCODE;
 			DISPATCH_OPCODE;
 
 
 			OPCODE(OPCODE_CALL_SELF_BASE) {
 			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
 #ifdef DEBUG_ENABLED
 				if (self_fun < 0 || self_fun >= _global_names_count) {
 				if (self_fun < 0 || self_fun >= _global_names_count) {
 					err_text = "compiler bug, function name not found";
 					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];
 				const StringName *methodname = &_global_names_ptr[self_fun];
 
 
 				int argc = _code_ptr[ip + 2];
 				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;
 				const GDScript *gds = _script;
 
 
@@ -1213,15 +1206,15 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
 					OPCODE_BREAK;
 					OPCODE_BREAK;
 				}
 				}
 
 
-				ip += 4 + argc;
+				ip += 3;
 			}
 			}
 			DISPATCH_OPCODE;
 			DISPATCH_OPCODE;
 
 
 			OPCODE(OPCODE_AWAIT) {
 			OPCODE(OPCODE_AWAIT) {
 				CHECK_SPACE(2);
 				CHECK_SPACE(2);
 
 
-				//do the oneshot connect
-				GET_VARIANT_PTR(argobj, 1);
+				// Do the oneshot connect.
+				GET_INSTRUCTION_ARG(argobj, 0);
 
 
 				Signal sig;
 				Signal sig;
 				bool is_signal = true;
 				bool is_signal = true;
@@ -1313,7 +1306,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
 					OPCODE_BREAK;
 					OPCODE_BREAK;
 				}
 				}
 #endif
 #endif
-				GET_VARIANT_PTR(result, 1);
+				GET_INSTRUCTION_ARG(result, 0);
 				*result = p_state->result;
 				*result = p_state->result;
 				ip += 2;
 				ip += 2;
 			}
 			}
@@ -1331,7 +1324,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
 			OPCODE(OPCODE_JUMP_IF) {
 			OPCODE(OPCODE_JUMP_IF) {
 				CHECK_SPACE(3);
 				CHECK_SPACE(3);
 
 
-				GET_VARIANT_PTR(test, 1);
+				GET_INSTRUCTION_ARG(test, 0);
 
 
 				bool result = test->booleanize();
 				bool result = test->booleanize();
 
 
@@ -1348,7 +1341,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
 			OPCODE(OPCODE_JUMP_IF_NOT) {
 			OPCODE(OPCODE_JUMP_IF_NOT) {
 				CHECK_SPACE(3);
 				CHECK_SPACE(3);
 
 
-				GET_VARIANT_PTR(test, 1);
+				GET_INSTRUCTION_ARG(test, 0);
 
 
 				bool result = test->booleanize();
 				bool result = test->booleanize();
 
 
@@ -1370,7 +1363,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
 
 
 			OPCODE(OPCODE_RETURN) {
 			OPCODE(OPCODE_RETURN) {
 				CHECK_SPACE(2);
 				CHECK_SPACE(2);
-				GET_VARIANT_PTR(r, 1);
+				GET_INSTRUCTION_ARG(r, 0);
 				retvalue = *r;
 				retvalue = *r;
 #ifdef DEBUG_ENABLED
 #ifdef DEBUG_ENABLED
 				exit_ok = true;
 				exit_ok = true;
@@ -1379,10 +1372,10 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
 			}
 			}
 
 
 			OPCODE(OPCODE_ITERATE_BEGIN) {
 			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;
 				bool valid;
 				if (!container->iter_init(*counter, valid)) {
 				if (!container->iter_init(*counter, valid)) {
@@ -1392,11 +1385,11 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
 						OPCODE_BREAK;
 						OPCODE_BREAK;
 					}
 					}
 #endif
 #endif
-					int jumpto = _code_ptr[ip + 3];
+					int jumpto = _code_ptr[ip + 4];
 					GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
 					GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
 					ip = jumpto;
 					ip = jumpto;
 				} else {
 				} else {
-					GET_VARIANT_PTR(iterator, 4);
+					GET_INSTRUCTION_ARG(iterator, 2);
 
 
 					*iterator = container->iter_get(*counter, valid);
 					*iterator = container->iter_get(*counter, valid);
 #ifdef DEBUG_ENABLED
 #ifdef DEBUG_ENABLED
@@ -1405,7 +1398,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
 						OPCODE_BREAK;
 						OPCODE_BREAK;
 					}
 					}
 #endif
 #endif
-					ip += 5; //skip regular iterate which is always next
+					ip += 5; // Skip regular iterate which is always next.
 				}
 				}
 			}
 			}
 			DISPATCH_OPCODE;
 			DISPATCH_OPCODE;
@@ -1413,8 +1406,8 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
 			OPCODE(OPCODE_ITERATE) {
 			OPCODE(OPCODE_ITERATE) {
 				CHECK_SPACE(4);
 				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;
 				bool valid;
 				if (!container->iter_next(*counter, valid)) {
 				if (!container->iter_next(*counter, valid)) {
@@ -1424,11 +1417,11 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
 						OPCODE_BREAK;
 						OPCODE_BREAK;
 					}
 					}
 #endif
 #endif
-					int jumpto = _code_ptr[ip + 3];
+					int jumpto = _code_ptr[ip + 4];
 					GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
 					GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
 					ip = jumpto;
 					ip = jumpto;
 				} else {
 				} else {
-					GET_VARIANT_PTR(iterator, 4);
+					GET_INSTRUCTION_ARG(iterator, 2);
 
 
 					*iterator = container->iter_get(*counter, valid);
 					*iterator = container->iter_get(*counter, valid);
 #ifdef DEBUG_ENABLED
 #ifdef DEBUG_ENABLED
@@ -1446,13 +1439,13 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
 				CHECK_SPACE(3);
 				CHECK_SPACE(3);
 
 
 #ifdef DEBUG_ENABLED
 #ifdef DEBUG_ENABLED
-				GET_VARIANT_PTR(test, 1);
+				GET_INSTRUCTION_ARG(test, 0);
 				bool result = test->booleanize();
 				bool result = test->booleanize();
 
 
 				if (!result) {
 				if (!result) {
 					String message_str;
 					String message_str;
 					if (_code_ptr[ip + 2] != 0) {
 					if (_code_ptr[ip + 2] != 0) {
-						GET_VARIANT_PTR(message, 2);
+						GET_INSTRUCTION_ARG(message, 1);
 						message_str = *message;
 						message_str = *message;
 					}
 					}
 					if (message_str.empty()) {
 					if (message_str.empty()) {