2
0
Эх сурвалжийг харах

Reduce number of addressing modes in GDScript VM

There's now only 3 addressing modes: stack, constant, and member.

Self, class, and nil are now present respectively in the first 3 stack
slots. Global and class constants are moved to local constants when
compiling. Named globals is only present on editor to use on tool
singletons, so its use now emits a new instruction to copy the global to
the stack.

This allow us to further optimize the VM later by embedding the
addressing modes in the instructions themselves, which is better done
with less permutations.
George Marques 4 жил өмнө
parent
commit
cf4079cb5f

+ 21 - 23
modules/gdscript/gdscript_byte_codegen.cpp

@@ -59,12 +59,7 @@ uint32_t GDScriptByteCodeGenerator::add_local_constant(const StringName &p_name,
 }
 }
 
 
 uint32_t GDScriptByteCodeGenerator::add_or_get_constant(const Variant &p_constant) {
 uint32_t GDScriptByteCodeGenerator::add_or_get_constant(const Variant &p_constant) {
-	if (constant_map.has(p_constant)) {
-		return constant_map[p_constant];
-	}
-	int index = constant_map.size();
-	constant_map[p_constant] = index;
-	return index;
+	return get_constant_pos(p_constant);
 }
 }
 
 
 uint32_t GDScriptByteCodeGenerator::add_or_get_name(const StringName &p_name) {
 uint32_t GDScriptByteCodeGenerator::add_or_get_name(const StringName &p_name) {
@@ -612,7 +607,8 @@ void GDScriptByteCodeGenerator::write_assign(const Address &p_target, const Addr
 			} 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);
+				Variant nc = GDScriptLanguage::get_singleton()->get_global_array()[class_idx];
+				class_idx = get_constant_pos(nc) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS);
 				append(GDScriptFunction::OPCODE_ASSIGN_TYPED_NATIVE, 3);
 				append(GDScriptFunction::OPCODE_ASSIGN_TYPED_NATIVE, 3);
 				append(p_target);
 				append(p_target);
 				append(p_source);
 				append(p_source);
@@ -621,8 +617,7 @@ void GDScriptByteCodeGenerator::write_assign(const Address &p_target, const Addr
 			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);
-				idx |= (GDScriptFunction::ADDR_TYPE_LOCAL_CONSTANT << GDScriptFunction::ADDR_BITS);
+				int idx = get_constant_pos(script) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS);
 
 
 				append(GDScriptFunction::OPCODE_ASSIGN_TYPED_SCRIPT, 3);
 				append(GDScriptFunction::OPCODE_ASSIGN_TYPED_SCRIPT, 3);
 				append(p_target);
 				append(p_target);
@@ -673,6 +668,12 @@ void GDScriptByteCodeGenerator::write_assign_default_parameter(const Address &p_
 	function->default_arguments.push_back(opcodes.size());
 	function->default_arguments.push_back(opcodes.size());
 }
 }
 
 
+void GDScriptByteCodeGenerator::write_store_named_global(const Address &p_dst, const StringName &p_global) {
+	append(GDScriptFunction::OPCODE_STORE_NAMED_GLOBAL, 1);
+	append(p_dst);
+	append(p_global);
+}
+
 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;
 	int index = 0;
 
 
@@ -683,16 +684,14 @@ void GDScriptByteCodeGenerator::write_cast(const Address &p_target, const Addres
 		} 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);
+			Variant nc = GDScriptLanguage::get_singleton()->get_global_array()[class_idx];
 			append(GDScriptFunction::OPCODE_CAST_TO_NATIVE, 3);
 			append(GDScriptFunction::OPCODE_CAST_TO_NATIVE, 3);
-			index = class_idx;
+			index = get_constant_pos(nc) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS);
 		} 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);
-			idx |= (GDScriptFunction::ADDR_TYPE_LOCAL_CONSTANT << GDScriptFunction::ADDR_BITS);
-
+			int idx = get_constant_pos(script) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS);
 			append(GDScriptFunction::OPCODE_CAST_TO_SCRIPT, 3);
 			append(GDScriptFunction::OPCODE_CAST_TO_SCRIPT, 3);
 			index = idx;
 			index = idx;
 		} break;
 		} break;
@@ -903,7 +902,7 @@ void GDScriptByteCodeGenerator::write_call_self(const Address &p_target, const S
 	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(GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS);
 	append(p_target);
 	append(p_target);
 	append(p_arguments.size());
 	append(p_arguments.size());
 	append(p_function_name);
 	append(p_function_name);
@@ -914,7 +913,7 @@ void GDScriptByteCodeGenerator::write_call_self_async(const Address &p_target, c
 	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(GDScriptFunction::ADDR_SELF);
 	append(p_target);
 	append(p_target);
 	append(p_arguments.size());
 	append(p_arguments.size());
 	append(p_function_name);
 	append(p_function_name);
@@ -999,7 +998,7 @@ void GDScriptByteCodeGenerator::write_construct_typed_array(const Address &p_tar
 	if (p_element_type.script_type) {
 	if (p_element_type.script_type) {
 		Variant script_type = Ref<Script>(p_element_type.script_type);
 		Variant script_type = Ref<Script>(p_element_type.script_type);
 		int addr = get_constant_pos(script_type);
 		int addr = get_constant_pos(script_type);
-		addr |= GDScriptFunction::ADDR_TYPE_LOCAL_CONSTANT << GDScriptFunction::ADDR_BITS;
+		addr |= GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS;
 		append(addr);
 		append(addr);
 	} else {
 	} else {
 		append(Address()); // null.
 		append(Address()); // null.
@@ -1296,8 +1295,7 @@ void GDScriptByteCodeGenerator::write_return(const Address &p_return_value) {
 				const GDScriptDataType &element_type = function->return_type.get_container_element_type();
 				const GDScriptDataType &element_type = function->return_type.get_container_element_type();
 
 
 				Variant script = function->return_type.script_type;
 				Variant script = function->return_type.script_type;
-				int script_idx = get_constant_pos(script);
-				script_idx |= (GDScriptFunction::ADDR_TYPE_LOCAL_CONSTANT << GDScriptFunction::ADDR_BITS);
+				int script_idx = get_constant_pos(script) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS);
 
 
 				append(GDScriptFunction::OPCODE_RETURN_TYPED_ARRAY, 2);
 				append(GDScriptFunction::OPCODE_RETURN_TYPED_ARRAY, 2);
 				append(p_return_value);
 				append(p_return_value);
@@ -1326,7 +1324,7 @@ void GDScriptByteCodeGenerator::write_return(const Address &p_return_value) {
 
 
 					Variant script = function->return_type.script_type;
 					Variant script = function->return_type.script_type;
 					int script_idx = get_constant_pos(script);
 					int script_idx = get_constant_pos(script);
-					script_idx |= (GDScriptFunction::ADDR_TYPE_LOCAL_CONSTANT << GDScriptFunction::ADDR_BITS);
+					script_idx |= (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS);
 
 
 					append(GDScriptFunction::OPCODE_RETURN_TYPED_ARRAY, 2);
 					append(GDScriptFunction::OPCODE_RETURN_TYPED_ARRAY, 2);
 					append(p_return_value);
 					append(p_return_value);
@@ -1343,14 +1341,14 @@ void GDScriptByteCodeGenerator::write_return(const Address &p_return_value) {
 				append(GDScriptFunction::OPCODE_RETURN_TYPED_NATIVE, 2);
 				append(GDScriptFunction::OPCODE_RETURN_TYPED_NATIVE, 2);
 				append(p_return_value);
 				append(p_return_value);
 				int class_idx = GDScriptLanguage::get_singleton()->get_global_map()[function->return_type.native_type];
 				int class_idx = GDScriptLanguage::get_singleton()->get_global_map()[function->return_type.native_type];
-				class_idx |= (GDScriptFunction::ADDR_TYPE_GLOBAL << GDScriptFunction::ADDR_BITS);
+				Variant nc = GDScriptLanguage::get_singleton()->get_global_array()[class_idx];
+				class_idx = get_constant_pos(nc) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS);
 				append(class_idx);
 				append(class_idx);
 			} break;
 			} break;
 			case GDScriptDataType::GDSCRIPT:
 			case GDScriptDataType::GDSCRIPT:
 			case GDScriptDataType::SCRIPT: {
 			case GDScriptDataType::SCRIPT: {
 				Variant script = function->return_type.script_type;
 				Variant script = function->return_type.script_type;
-				int script_idx = get_constant_pos(script);
-				script_idx |= (GDScriptFunction::ADDR_TYPE_LOCAL_CONSTANT << GDScriptFunction::ADDR_BITS);
+				int script_idx = get_constant_pos(script) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS);
 
 
 				append(GDScriptFunction::OPCODE_RETURN_TYPED_SCRIPT, 2);
 				append(GDScriptFunction::OPCODE_RETURN_TYPED_SCRIPT, 2);
 				append(p_return_value);
 				append(p_return_value);

+ 8 - 14
modules/gdscript/gdscript_byte_codegen.h

@@ -51,11 +51,11 @@ class GDScriptByteCodeGenerator : public GDScriptCodeGenerator {
 	List<Map<StringName, int>> block_identifier_stack;
 	List<Map<StringName, int>> block_identifier_stack;
 	Map<StringName, int> block_identifiers;
 	Map<StringName, int> block_identifiers;
 
 
-	int current_stack_size = 0;
+	int current_stack_size = 3; // First 3 spots are reserved for self, class, and nil.
 	int current_temporaries = 0;
 	int current_temporaries = 0;
 	int current_locals = 0;
 	int current_locals = 0;
 	int current_line = 0;
 	int current_line = 0;
-	int stack_max = 0;
+	int stack_max = 3;
 	int instr_args_max = 0;
 	int instr_args_max = 0;
 	int ptrcall_max = 0;
 	int ptrcall_max = 0;
 
 
@@ -135,7 +135,7 @@ class GDScriptByteCodeGenerator : public GDScriptCodeGenerator {
 			ERR_PRINT("Leaving block with non-zero temporary variables: " + itos(current_temporaries));
 			ERR_PRINT("Leaving block with non-zero temporary variables: " + itos(current_temporaries));
 		}
 		}
 #endif
 #endif
-		current_stack_size = current_locals;
+		current_stack_size = current_locals + 3; // Keep the 3 reserved slots for self, class, and nil.
 
 
 		if (debug_stack) {
 		if (debug_stack) {
 			for (Map<StringName, int>::Element *E = block_identifiers.front(); E; E = E->next()) {
 			for (Map<StringName, int>::Element *E = block_identifiers.front(); E; E = E->next()) {
@@ -300,26 +300,19 @@ class GDScriptByteCodeGenerator : public GDScriptCodeGenerator {
 	int address_of(const Address &p_address) {
 	int address_of(const Address &p_address) {
 		switch (p_address.mode) {
 		switch (p_address.mode) {
 			case Address::SELF:
 			case Address::SELF:
-				return GDScriptFunction::ADDR_TYPE_SELF << GDScriptFunction::ADDR_BITS;
+				return GDScriptFunction::ADDR_SELF;
 			case Address::CLASS:
 			case Address::CLASS:
-				return GDScriptFunction::ADDR_TYPE_CLASS << GDScriptFunction::ADDR_BITS;
+				return GDScriptFunction::ADDR_CLASS;
 			case Address::MEMBER:
 			case Address::MEMBER:
 				return p_address.address | (GDScriptFunction::ADDR_TYPE_MEMBER << GDScriptFunction::ADDR_BITS);
 				return p_address.address | (GDScriptFunction::ADDR_TYPE_MEMBER << GDScriptFunction::ADDR_BITS);
-			case Address::CLASS_CONSTANT:
-				return p_address.address | (GDScriptFunction::ADDR_TYPE_CLASS_CONSTANT << GDScriptFunction::ADDR_BITS);
-			case Address::LOCAL_CONSTANT:
 			case Address::CONSTANT:
 			case Address::CONSTANT:
-				return p_address.address | (GDScriptFunction::ADDR_TYPE_LOCAL_CONSTANT << GDScriptFunction::ADDR_BITS);
+				return p_address.address | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS);
 			case Address::LOCAL_VARIABLE:
 			case Address::LOCAL_VARIABLE:
 			case Address::TEMPORARY:
 			case Address::TEMPORARY:
 			case Address::FUNCTION_PARAMETER:
 			case Address::FUNCTION_PARAMETER:
 				return p_address.address | (GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS);
 				return p_address.address | (GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS);
-			case Address::GLOBAL:
-				return p_address.address | (GDScriptFunction::ADDR_TYPE_GLOBAL << GDScriptFunction::ADDR_BITS);
-			case Address::NAMED_GLOBAL:
-				return p_address.address | (GDScriptFunction::ADDR_TYPE_NAMED_GLOBAL << GDScriptFunction::ADDR_BITS);
 			case Address::NIL:
 			case Address::NIL:
-				return GDScriptFunction::ADDR_TYPE_NIL << GDScriptFunction::ADDR_BITS;
+				return GDScriptFunction::ADDR_NIL;
 		}
 		}
 		return -1; // Unreachable.
 		return -1; // Unreachable.
 	}
 	}
@@ -441,6 +434,7 @@ public:
 	virtual void write_assign_true(const Address &p_target) override;
 	virtual void write_assign_true(const Address &p_target) override;
 	virtual void write_assign_false(const Address &p_target) override;
 	virtual void write_assign_false(const Address &p_target) override;
 	virtual void write_assign_default_parameter(const Address &p_dst, const Address &p_src) override;
 	virtual void write_assign_default_parameter(const Address &p_dst, const Address &p_src) override;
+	virtual void write_store_named_global(const Address &p_dst, const StringName &p_global) override;
 	virtual void write_cast(const Address &p_target, const Address &p_source, const GDScriptDataType &p_type) override;
 	virtual void write_cast(const Address &p_target, const Address &p_source, const GDScriptDataType &p_type) override;
 	virtual void write_call(const Address &p_target, const Address &p_base, const StringName &p_function_name, const Vector<Address> &p_arguments) override;
 	virtual void write_call(const Address &p_target, const Address &p_base, const StringName &p_function_name, const Vector<Address> &p_arguments) override;
 	virtual void write_super_call(const Address &p_target, const StringName &p_function_name, const Vector<Address> &p_arguments) override;
 	virtual void write_super_call(const Address &p_target, const StringName &p_function_name, const Vector<Address> &p_arguments) override;

+ 1 - 4
modules/gdscript/gdscript_codegen.h

@@ -45,13 +45,9 @@ public:
 			CLASS,
 			CLASS,
 			MEMBER,
 			MEMBER,
 			CONSTANT,
 			CONSTANT,
-			CLASS_CONSTANT,
-			LOCAL_CONSTANT,
 			LOCAL_VARIABLE,
 			LOCAL_VARIABLE,
 			FUNCTION_PARAMETER,
 			FUNCTION_PARAMETER,
 			TEMPORARY,
 			TEMPORARY,
-			GLOBAL,
-			NAMED_GLOBAL,
 			NIL,
 			NIL,
 		};
 		};
 		AddressMode mode = NIL;
 		AddressMode mode = NIL;
@@ -123,6 +119,7 @@ public:
 	virtual void write_assign_true(const Address &p_target) = 0;
 	virtual void write_assign_true(const Address &p_target) = 0;
 	virtual void write_assign_false(const Address &p_target) = 0;
 	virtual void write_assign_false(const Address &p_target) = 0;
 	virtual void write_assign_default_parameter(const Address &dst, const Address &src) = 0;
 	virtual void write_assign_default_parameter(const Address &dst, const Address &src) = 0;
+	virtual void write_store_named_global(const Address &p_dst, const StringName &p_global) = 0;
 	virtual void write_cast(const Address &p_target, const Address &p_source, const GDScriptDataType &p_type) = 0;
 	virtual void write_cast(const Address &p_target, const Address &p_source, const GDScriptDataType &p_type) = 0;
 	virtual void write_call(const Address &p_target, const Address &p_base, const StringName &p_function_name, const Vector<Address> &p_arguments) = 0;
 	virtual void write_call(const Address &p_target, const Address &p_base, const StringName &p_function_name, const Vector<Address> &p_arguments) = 0;
 	virtual void write_super_call(const Address &p_target, const StringName &p_function_name, const Vector<Address> &p_arguments) = 0;
 	virtual void write_super_call(const Address &p_target, const StringName &p_function_name, const Vector<Address> &p_arguments) = 0;

+ 6 - 3
modules/gdscript/gdscript_compiler.cpp

@@ -262,7 +262,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
 					GDScriptNativeClass *nc = nullptr;
 					GDScriptNativeClass *nc = nullptr;
 					while (scr) {
 					while (scr) {
 						if (scr->constants.has(identifier)) {
 						if (scr->constants.has(identifier)) {
-							return GDScriptCodeGenerator::Address(GDScriptCodeGenerator::Address::CLASS_CONSTANT, gen->add_or_get_name(identifier)); // TODO: Get type here.
+							return codegen.add_constant(scr->constants[identifier]); // TODO: Get type here.
 						}
 						}
 						if (scr->native.is_valid()) {
 						if (scr->native.is_valid()) {
 							nc = scr->native.ptr();
 							nc = scr->native.ptr();
@@ -319,7 +319,8 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
 
 
 			if (GDScriptLanguage::get_singleton()->get_global_map().has(identifier)) {
 			if (GDScriptLanguage::get_singleton()->get_global_map().has(identifier)) {
 				int idx = GDScriptLanguage::get_singleton()->get_global_map()[identifier];
 				int idx = GDScriptLanguage::get_singleton()->get_global_map()[identifier];
-				return GDScriptCodeGenerator::Address(GDScriptCodeGenerator::Address::GLOBAL, idx); // TODO: Get type.
+				Variant global = GDScriptLanguage::get_singleton()->get_global_array()[idx];
+				return codegen.add_constant(global); // TODO: Get type.
 			}
 			}
 
 
 			// Try global classes.
 			// Try global classes.
@@ -347,7 +348,9 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
 
 
 #ifdef TOOLS_ENABLED
 #ifdef TOOLS_ENABLED
 			if (GDScriptLanguage::get_singleton()->get_named_globals_map().has(identifier)) {
 			if (GDScriptLanguage::get_singleton()->get_named_globals_map().has(identifier)) {
-				return GDScriptCodeGenerator::Address(GDScriptCodeGenerator::Address::NAMED_GLOBAL, gen->add_or_get_name(identifier)); // TODO: Get type.
+				GDScriptCodeGenerator::Address global = codegen.add_temporary(); // TODO: Get type.
+				gen->write_store_named_global(global, identifier);
+				return global;
 			}
 			}
 #endif
 #endif
 
 

+ 1 - 1
modules/gdscript/gdscript_compiler.h

@@ -61,7 +61,7 @@ class GDScriptCompiler {
 
 
 		GDScriptCodeGenerator::Address add_local_constant(const StringName &p_name, const Variant &p_value) {
 		GDScriptCodeGenerator::Address add_local_constant(const StringName &p_name, const Variant &p_value) {
 			uint32_t addr = generator->add_local_constant(p_name, p_value);
 			uint32_t addr = generator->add_local_constant(p_name, p_value);
-			locals[p_name] = GDScriptCodeGenerator::Address(GDScriptCodeGenerator::Address::LOCAL_CONSTANT, addr);
+			locals[p_name] = GDScriptCodeGenerator::Address(GDScriptCodeGenerator::Address::CONSTANT, addr);
 			return locals[p_name];
 			return locals[p_name];
 		}
 		}
 
 

+ 19 - 23
modules/gdscript/gdscript_disassembler.cpp

@@ -69,35 +69,23 @@ static String _disassemble_address(const GDScript *p_script, const GDScriptFunct
 	int addr = p_address & GDScriptFunction::ADDR_MASK;
 	int addr = p_address & GDScriptFunction::ADDR_MASK;
 
 
 	switch (p_address >> GDScriptFunction::ADDR_BITS) {
 	switch (p_address >> GDScriptFunction::ADDR_BITS) {
-		case GDScriptFunction::ADDR_TYPE_SELF: {
-			return "self";
-		} break;
-		case GDScriptFunction::ADDR_TYPE_CLASS: {
-			return "class";
-		} break;
 		case GDScriptFunction::ADDR_TYPE_MEMBER: {
 		case GDScriptFunction::ADDR_TYPE_MEMBER: {
 			return "member(" + p_script->debug_get_member_by_index(addr) + ")";
 			return "member(" + p_script->debug_get_member_by_index(addr) + ")";
 		} break;
 		} break;
-		case GDScriptFunction::ADDR_TYPE_CLASS_CONSTANT: {
-			return "class_const(" + p_function.get_global_name(addr) + ")";
-		} break;
-		case GDScriptFunction::ADDR_TYPE_LOCAL_CONSTANT: {
+		case GDScriptFunction::ADDR_TYPE_CONSTANT: {
 			return "const(" + _get_variant_string(p_function.get_constant(addr)) + ")";
 			return "const(" + _get_variant_string(p_function.get_constant(addr)) + ")";
 		} break;
 		} break;
 		case GDScriptFunction::ADDR_TYPE_STACK: {
 		case GDScriptFunction::ADDR_TYPE_STACK: {
-			return "stack(" + itos(addr) + ")";
-		} break;
-		case GDScriptFunction::ADDR_TYPE_STACK_VARIABLE: {
-			return "var_stack(" + itos(addr) + ")";
-		} break;
-		case GDScriptFunction::ADDR_TYPE_GLOBAL: {
-			return "global(" + _get_variant_string(GDScriptLanguage::get_singleton()->get_global_array()[addr]) + ")";
-		} break;
-		case GDScriptFunction::ADDR_TYPE_NAMED_GLOBAL: {
-			return "named_global(" + p_function.get_global_name(addr) + ")";
-		} break;
-		case GDScriptFunction::ADDR_TYPE_NIL: {
-			return "nil";
+			switch (addr) {
+				case GDScriptFunction::ADDR_STACK_SELF:
+					return "self";
+				case GDScriptFunction::ADDR_STACK_CLASS:
+					return "class";
+				case GDScriptFunction::ADDR_STACK_NIL:
+					return "nil";
+				default:
+					return "stack(" + itos(addr) + ")";
+			}
 		} break;
 		} break;
 	}
 	}
 
 
@@ -885,6 +873,14 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const {
 				incr += 5;
 				incr += 5;
 			} break;
 			} break;
 				DISASSEMBLE_ITERATE_TYPES(DISASSEMBLE_ITERATE);
 				DISASSEMBLE_ITERATE_TYPES(DISASSEMBLE_ITERATE);
+			case OPCODE_STORE_NAMED_GLOBAL: {
+				text += "store named global ";
+				text += DADDR(1);
+				text += " = ";
+				text += String(_global_names_ptr[_code_ptr[ip + 2]]);
+
+				incr += 3;
+			} break;
 			case OPCODE_LINE: {
 			case OPCODE_LINE: {
 				int line = _code_ptr[ip + 1] - 1;
 				int line = _code_ptr[ip + 1] - 1;
 				if (line >= 0 && line < p_code_lines.size()) {
 				if (line >= 0 && line < p_code_lines.size()) {

+ 13 - 11
modules/gdscript/gdscript_function.h

@@ -350,6 +350,7 @@ public:
 		OPCODE_ITERATE_PACKED_VECTOR3_ARRAY,
 		OPCODE_ITERATE_PACKED_VECTOR3_ARRAY,
 		OPCODE_ITERATE_PACKED_COLOR_ARRAY,
 		OPCODE_ITERATE_PACKED_COLOR_ARRAY,
 		OPCODE_ITERATE_OBJECT,
 		OPCODE_ITERATE_OBJECT,
+		OPCODE_STORE_NAMED_GLOBAL,
 		OPCODE_ASSERT,
 		OPCODE_ASSERT,
 		OPCODE_BREAKPOINT,
 		OPCODE_BREAKPOINT,
 		OPCODE_LINE,
 		OPCODE_LINE,
@@ -360,16 +361,18 @@ public:
 		ADDR_BITS = 24,
 		ADDR_BITS = 24,
 		ADDR_MASK = ((1 << ADDR_BITS) - 1),
 		ADDR_MASK = ((1 << ADDR_BITS) - 1),
 		ADDR_TYPE_MASK = ~ADDR_MASK,
 		ADDR_TYPE_MASK = ~ADDR_MASK,
-		ADDR_TYPE_SELF = 0,
-		ADDR_TYPE_CLASS = 1,
+		ADDR_TYPE_STACK = 0,
+		ADDR_TYPE_CONSTANT = 1,
 		ADDR_TYPE_MEMBER = 2,
 		ADDR_TYPE_MEMBER = 2,
-		ADDR_TYPE_CLASS_CONSTANT = 3,
-		ADDR_TYPE_LOCAL_CONSTANT = 4,
-		ADDR_TYPE_STACK = 5,
-		ADDR_TYPE_STACK_VARIABLE = 6,
-		ADDR_TYPE_GLOBAL = 7,
-		ADDR_TYPE_NAMED_GLOBAL = 8,
-		ADDR_TYPE_NIL = 9
+	};
+
+	enum FixedAddresses {
+		ADDR_STACK_SELF = 0,
+		ADDR_STACK_CLASS = 1,
+		ADDR_STACK_NIL = 2,
+		ADDR_SELF = ADDR_STACK_SELF | (ADDR_TYPE_STACK << ADDR_BITS),
+		ADDR_CLASS = ADDR_STACK_CLASS | (ADDR_TYPE_STACK << ADDR_BITS),
+		ADDR_NIL = ADDR_STACK_NIL | (ADDR_TYPE_STACK << ADDR_BITS),
 	};
 	};
 
 
 	enum Instruction {
 	enum Instruction {
@@ -462,7 +465,7 @@ private:
 
 
 	List<StackDebug> stack_debug;
 	List<StackDebug> stack_debug;
 
 
-	_FORCE_INLINE_ Variant *_get_variant(int p_address, GDScriptInstance *p_instance, GDScript *p_script, Variant &self, Variant &static_ref, Variant *p_stack, String &r_error) const;
+	_FORCE_INLINE_ Variant *_get_variant(int p_address, GDScriptInstance *p_instance, Variant *p_stack, String &r_error) const;
 	_FORCE_INLINE_ String _get_call_error(const Callable::CallError &p_err, const String &p_where, const Variant **argptrs) const;
 	_FORCE_INLINE_ String _get_call_error(const Callable::CallError &p_err, const String &p_where, const Variant **argptrs) const;
 
 
 	friend class GDScriptLanguage;
 	friend class GDScriptLanguage;
@@ -497,7 +500,6 @@ public:
 #endif
 #endif
 		Vector<uint8_t> stack;
 		Vector<uint8_t> stack;
 		int stack_size = 0;
 		int stack_size = 0;
-		Variant self;
 		uint32_t alloca_size = 0;
 		uint32_t alloca_size = 0;
 		int ip = 0;
 		int ip = 0;
 		int line = 0;
 		int line = 0;

+ 59 - 114
modules/gdscript/gdscript_vm.cpp

@@ -34,22 +34,22 @@
 #include "core/os/os.h"
 #include "core/os/os.h"
 #include "gdscript.h"
 #include "gdscript.h"
 
 
-Variant *GDScriptFunction::_get_variant(int p_address, GDScriptInstance *p_instance, GDScript *p_script, Variant &self, Variant &static_ref, Variant *p_stack, String &r_error) const {
+Variant *GDScriptFunction::_get_variant(int p_address, GDScriptInstance *p_instance, Variant *p_stack, String &r_error) const {
 	int address = p_address & ADDR_MASK;
 	int address = p_address & ADDR_MASK;
 
 
 	//sequential table (jump table generated by compiler)
 	//sequential table (jump table generated by compiler)
 	switch ((p_address & ADDR_TYPE_MASK) >> ADDR_BITS) {
 	switch ((p_address & ADDR_TYPE_MASK) >> ADDR_BITS) {
-		case ADDR_TYPE_SELF: {
+		case ADDR_TYPE_STACK: {
 #ifdef DEBUG_ENABLED
 #ifdef DEBUG_ENABLED
-			if (unlikely(!p_instance)) {
-				r_error = "Cannot access self without instance.";
-				return nullptr;
-			}
+			ERR_FAIL_INDEX_V(address, _stack_size, nullptr);
 #endif
 #endif
-			return &self;
+			return &p_stack[address];
 		} break;
 		} break;
-		case ADDR_TYPE_CLASS: {
-			return &static_ref;
+		case ADDR_TYPE_CONSTANT: {
+#ifdef DEBUG_ENABLED
+			ERR_FAIL_INDEX_V(address, _constant_count, nullptr);
+#endif
+			return &_constants_ptr[address];
 		} break;
 		} break;
 		case ADDR_TYPE_MEMBER: {
 		case ADDR_TYPE_MEMBER: {
 #ifdef DEBUG_ENABLED
 #ifdef DEBUG_ENABLED
@@ -61,65 +61,6 @@ Variant *GDScriptFunction::_get_variant(int p_address, GDScriptInstance *p_insta
 			//member indexing is O(1)
 			//member indexing is O(1)
 			return &p_instance->members.write[address];
 			return &p_instance->members.write[address];
 		} break;
 		} break;
-		case ADDR_TYPE_CLASS_CONSTANT: {
-			//todo change to index!
-			GDScript *s = p_script;
-#ifdef DEBUG_ENABLED
-			ERR_FAIL_INDEX_V(address, _global_names_count, nullptr);
-#endif
-			const StringName *sn = &_global_names_ptr[address];
-
-			while (s) {
-				GDScript *o = s;
-				while (o) {
-					Map<StringName, Variant>::Element *E = o->constants.find(*sn);
-					if (E) {
-						return &E->get();
-					}
-					o = o->_owner;
-				}
-				s = s->_base;
-			}
-
-			ERR_FAIL_V_MSG(nullptr, "GDScriptCompiler bug.");
-		} break;
-		case ADDR_TYPE_LOCAL_CONSTANT: {
-#ifdef DEBUG_ENABLED
-			ERR_FAIL_INDEX_V(address, _constant_count, nullptr);
-#endif
-			return &_constants_ptr[address];
-		} break;
-		case ADDR_TYPE_STACK:
-		case ADDR_TYPE_STACK_VARIABLE: {
-#ifdef DEBUG_ENABLED
-			ERR_FAIL_INDEX_V(address, _stack_size, nullptr);
-#endif
-			return &p_stack[address];
-		} break;
-		case ADDR_TYPE_GLOBAL: {
-#ifdef DEBUG_ENABLED
-			ERR_FAIL_INDEX_V(address, GDScriptLanguage::get_singleton()->get_global_array_size(), nullptr);
-#endif
-			return &GDScriptLanguage::get_singleton()->get_global_array()[address];
-		} break;
-#ifdef TOOLS_ENABLED
-		case ADDR_TYPE_NAMED_GLOBAL: {
-#ifdef DEBUG_ENABLED
-			ERR_FAIL_INDEX_V(address, _global_names_count, nullptr);
-#endif
-			StringName id = _global_names_ptr[address];
-
-			if (GDScriptLanguage::get_singleton()->get_named_globals_map().has(id)) {
-				return (Variant *)&GDScriptLanguage::get_singleton()->get_named_globals_map()[id];
-			} else {
-				r_error = "Autoload singleton '" + String(id) + "' has been removed.";
-				return nullptr;
-			}
-		} break;
-#endif
-		case ADDR_TYPE_NIL: {
-			return &nil;
-		} break;
 	}
 	}
 
 
 	ERR_FAIL_V_MSG(nullptr, "Bad code! (unknown addressing mode).");
 	ERR_FAIL_V_MSG(nullptr, "Bad code! (unknown addressing mode).");
@@ -340,6 +281,7 @@ String GDScriptFunction::_get_call_error(const Callable::CallError &p_err, const
 		&&OPCODE_ITERATE_PACKED_VECTOR3_ARRAY,       \
 		&&OPCODE_ITERATE_PACKED_VECTOR3_ARRAY,       \
 		&&OPCODE_ITERATE_PACKED_COLOR_ARRAY,         \
 		&&OPCODE_ITERATE_PACKED_COLOR_ARRAY,         \
 		&&OPCODE_ITERATE_OBJECT,                     \
 		&&OPCODE_ITERATE_OBJECT,                     \
+		&&OPCODE_STORE_NAMED_GLOBAL,                 \
 		&&OPCODE_ASSERT,                             \
 		&&OPCODE_ASSERT,                             \
 		&&OPCODE_BREAKPOINT,                         \
 		&&OPCODE_BREAKPOINT,                         \
 		&&OPCODE_LINE,                               \
 		&&OPCODE_LINE,                               \
@@ -415,11 +357,9 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
 
 
 	r_err.error = Callable::CallError::CALL_OK;
 	r_err.error = Callable::CallError::CALL_OK;
 
 
-	Variant self;
-	Variant static_ref;
 	Variant retvalue;
 	Variant retvalue;
 	Variant *stack = nullptr;
 	Variant *stack = nullptr;
-	Variant **instruction_args;
+	Variant **instruction_args = nullptr;
 	const void **call_args_ptr = nullptr;
 	const void **call_args_ptr = nullptr;
 	int defarg = 0;
 	int defarg = 0;
 
 
@@ -444,7 +384,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
 		script = p_state->script;
 		script = p_state->script;
 		p_instance = p_state->instance;
 		p_instance = p_state->instance;
 		defarg = p_state->defarg;
 		defarg = p_state->defarg;
-		self = p_state->self;
 
 
 	} else {
 	} else {
 		if (p_argcount != _argument_count) {
 		if (p_argcount != _argument_count) {
@@ -462,55 +401,49 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
 			}
 			}
 		}
 		}
 
 
-		alloca_size = sizeof(Variant *) * _instruction_args_size + sizeof(Variant) * _stack_size;
-
-		if (alloca_size) {
-			uint8_t *aptr = (uint8_t *)alloca(alloca_size);
+		// Add 3 here for self, class, and nil.
+		alloca_size = sizeof(Variant *) * 3 + sizeof(Variant *) * _instruction_args_size + sizeof(Variant) * _stack_size;
 
 
-			if (_stack_size) {
-				stack = (Variant *)aptr;
-				for (int i = 0; i < p_argcount; i++) {
-					if (!argument_types[i].has_type) {
-						memnew_placement(&stack[i], Variant(*p_args[i]));
-						continue;
-					}
+		uint8_t *aptr = (uint8_t *)alloca(alloca_size);
+		stack = (Variant *)aptr;
 
 
-					if (!argument_types[i].is_type(*p_args[i], true)) {
-						r_err.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
-						r_err.argument = i;
-						r_err.expected = argument_types[i].kind == GDScriptDataType::BUILTIN ? argument_types[i].builtin_type : Variant::OBJECT;
-						return Variant();
-					}
-					if (argument_types[i].kind == GDScriptDataType::BUILTIN) {
-						Variant arg;
-						Variant::construct(argument_types[i].builtin_type, arg, &p_args[i], 1, r_err);
-						memnew_placement(&stack[i], Variant(arg));
-					} else {
-						memnew_placement(&stack[i], Variant(*p_args[i]));
-					}
-				}
-				for (int i = p_argcount; i < _stack_size; i++) {
-					memnew_placement(&stack[i], Variant);
-				}
-			} else {
-				stack = nullptr;
+		for (int i = 0; i < p_argcount; i++) {
+			if (!argument_types[i].has_type) {
+				memnew_placement(&stack[i + 3], Variant(*p_args[i]));
+				continue;
 			}
 			}
 
 
-			if (_instruction_args_size) {
-				instruction_args = (Variant **)&aptr[sizeof(Variant) * _stack_size];
+			if (!argument_types[i].is_type(*p_args[i], true)) {
+				r_err.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT;
+				r_err.argument = i;
+				r_err.expected = argument_types[i].kind == GDScriptDataType::BUILTIN ? argument_types[i].builtin_type : Variant::OBJECT;
+				return Variant();
+			}
+			if (argument_types[i].kind == GDScriptDataType::BUILTIN) {
+				Variant arg;
+				Variant::construct(argument_types[i].builtin_type, arg, &p_args[i], 1, r_err);
+				memnew_placement(&stack[i + 3], Variant(arg));
 			} else {
 			} else {
-				instruction_args = nullptr;
+				memnew_placement(&stack[i + 3], Variant(*p_args[i]));
 			}
 			}
+		}
+		for (int i = p_argcount + 3; i < _stack_size; i++) {
+			memnew_placement(&stack[i], Variant);
+		}
 
 
+		memnew_placement(&stack[ADDR_STACK_NIL], Variant);
+
+		if (_instruction_args_size) {
+			instruction_args = (Variant **)&aptr[sizeof(Variant) * _stack_size];
 		} else {
 		} else {
-			stack = nullptr;
 			instruction_args = nullptr;
 			instruction_args = nullptr;
 		}
 		}
 
 
 		if (p_instance) {
 		if (p_instance) {
-			self = p_instance->owner;
+			memnew_placement(&stack[ADDR_STACK_SELF], Variant(p_instance->owner));
 			script = p_instance->script.ptr();
 			script = p_instance->script.ptr();
 		} else {
 		} else {
+			memnew_placement(&stack[ADDR_STACK_SELF], Variant);
 			script = _script;
 			script = _script;
 		}
 		}
 	}
 	}
@@ -520,7 +453,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
 		call_args_ptr = nullptr;
 		call_args_ptr = nullptr;
 	}
 	}
 
 
-	static_ref = script;
+	memnew_placement(&stack[ADDR_STACK_CLASS], Variant(script));
 
 
 	String err_text;
 	String err_text;
 
 
@@ -541,10 +474,10 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
 #define CHECK_SPACE(m_space) \
 #define CHECK_SPACE(m_space) \
 	GD_ERR_BREAK((ip + m_space) > _code_size)
 	GD_ERR_BREAK((ip + m_space) > _code_size)
 
 
-#define GET_VARIANT_PTR(m_v, m_code_ofs)                                                                   \
-	Variant *m_v;                                                                                          \
-	m_v = _get_variant(_code_ptr[ip + m_code_ofs], p_instance, script, self, static_ref, stack, err_text); \
-	if (unlikely(!m_v))                                                                                    \
+#define GET_VARIANT_PTR(m_v, m_code_ofs)                                         \
+	Variant *m_v;                                                                \
+	m_v = _get_variant(_code_ptr[ip + m_code_ofs], p_instance, stack, err_text); \
+	if (unlikely(!m_v))                                                          \
 		OPCODE_BREAK;
 		OPCODE_BREAK;
 
 
 #else
 #else
@@ -552,7 +485,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
 #define CHECK_SPACE(m_space)
 #define CHECK_SPACE(m_space)
 #define GET_VARIANT_PTR(m_v, m_code_ofs) \
 #define GET_VARIANT_PTR(m_v, m_code_ofs) \
 	Variant *m_v;                        \
 	Variant *m_v;                        \
-	m_v = _get_variant(_code_ptr[ip + m_code_ofs], p_instance, script, self, static_ref, stack, err_text);
+	m_v = _get_variant(_code_ptr[ip + m_code_ofs], p_instance, stack, err_text);
 
 
 #endif
 #endif
 
 
@@ -2038,7 +1971,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
 						memnew_placement(&gdfs->state.stack.write[sizeof(Variant) * i], Variant(stack[i]));
 						memnew_placement(&gdfs->state.stack.write[sizeof(Variant) * i], Variant(stack[i]));
 					}
 					}
 					gdfs->state.stack_size = _stack_size;
 					gdfs->state.stack_size = _stack_size;
-					gdfs->state.self = self;
 					gdfs->state.alloca_size = alloca_size;
 					gdfs->state.alloca_size = alloca_size;
 					gdfs->state.ip = ip + 2;
 					gdfs->state.ip = ip + 2;
 					gdfs->state.line = line;
 					gdfs->state.line = line;
@@ -3028,6 +2960,19 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
 			}
 			}
 			DISPATCH_OPCODE;
 			DISPATCH_OPCODE;
 
 
+			OPCODE(OPCODE_STORE_NAMED_GLOBAL) {
+				CHECK_SPACE(3);
+				int globalname_idx = _code_ptr[ip + 2];
+				GD_ERR_BREAK(globalname_idx < 0 || globalname_idx >= _global_names_count);
+				const StringName *globalname = &_global_names_ptr[globalname_idx];
+
+				GET_INSTRUCTION_ARG(dst, 0);
+				*dst = GDScriptLanguage::get_singleton()->get_named_globals_map()[*globalname];
+
+				ip += 3;
+			}
+			DISPATCH_OPCODE;
+
 			OPCODE(OPCODE_ASSERT) {
 			OPCODE(OPCODE_ASSERT) {
 				CHECK_SPACE(3);
 				CHECK_SPACE(3);