mirror of
				https://github.com/godotengine/godot.git
				synced 2025-10-31 21:51:22 +00:00 
			
		
		
		
	GDScript: Add speficic set/get instructions
When the base type is known at compile-time, we can get a direct function pointer that is faster than the regular set/get paths.
This commit is contained in:
		
							parent
							
								
									1ad5c926dc
								
							
						
					
					
						commit
						5aeb390cd7
					
				
					 5 changed files with 476 additions and 13 deletions
				
			
		|  | @ -170,6 +170,78 @@ GDScriptFunction *GDScriptByteCodeGenerator::write_end() { | |||
| 		function->_operator_funcs_ptr = nullptr; | ||||
| 	} | ||||
| 
 | ||||
| 	if (setters_map.size()) { | ||||
| 		function->setters.resize(setters_map.size()); | ||||
| 		function->_setters_count = function->setters.size(); | ||||
| 		function->_setters_ptr = function->setters.ptr(); | ||||
| 		for (const Map<Variant::ValidatedSetter, int>::Element *E = setters_map.front(); E; E = E->next()) { | ||||
| 			function->setters.write[E->get()] = E->key(); | ||||
| 		} | ||||
| 	} else { | ||||
| 		function->_setters_count = 0; | ||||
| 		function->_setters_ptr = nullptr; | ||||
| 	} | ||||
| 
 | ||||
| 	if (getters_map.size()) { | ||||
| 		function->getters.resize(getters_map.size()); | ||||
| 		function->_getters_count = function->getters.size(); | ||||
| 		function->_getters_ptr = function->getters.ptr(); | ||||
| 		for (const Map<Variant::ValidatedGetter, int>::Element *E = getters_map.front(); E; E = E->next()) { | ||||
| 			function->getters.write[E->get()] = E->key(); | ||||
| 		} | ||||
| 	} else { | ||||
| 		function->_getters_count = 0; | ||||
| 		function->_getters_ptr = nullptr; | ||||
| 	} | ||||
| 
 | ||||
| 	if (keyed_setters_map.size()) { | ||||
| 		function->keyed_setters.resize(keyed_setters_map.size()); | ||||
| 		function->_keyed_setters_count = function->keyed_setters.size(); | ||||
| 		function->_keyed_setters_ptr = function->keyed_setters.ptr(); | ||||
| 		for (const Map<Variant::ValidatedKeyedSetter, int>::Element *E = keyed_setters_map.front(); E; E = E->next()) { | ||||
| 			function->keyed_setters.write[E->get()] = E->key(); | ||||
| 		} | ||||
| 	} else { | ||||
| 		function->_keyed_setters_count = 0; | ||||
| 		function->_keyed_setters_ptr = nullptr; | ||||
| 	} | ||||
| 
 | ||||
| 	if (keyed_getters_map.size()) { | ||||
| 		function->keyed_getters.resize(keyed_getters_map.size()); | ||||
| 		function->_keyed_getters_count = function->keyed_getters.size(); | ||||
| 		function->_keyed_getters_ptr = function->keyed_getters.ptr(); | ||||
| 		for (const Map<Variant::ValidatedKeyedGetter, int>::Element *E = keyed_getters_map.front(); E; E = E->next()) { | ||||
| 			function->keyed_getters.write[E->get()] = E->key(); | ||||
| 		} | ||||
| 	} else { | ||||
| 		function->_keyed_getters_count = 0; | ||||
| 		function->_keyed_getters_ptr = nullptr; | ||||
| 	} | ||||
| 
 | ||||
| 	if (indexed_setters_map.size()) { | ||||
| 		function->indexed_setters.resize(indexed_setters_map.size()); | ||||
| 		function->_indexed_setters_count = function->indexed_setters.size(); | ||||
| 		function->_indexed_setters_ptr = function->indexed_setters.ptr(); | ||||
| 		for (const Map<Variant::ValidatedIndexedSetter, int>::Element *E = indexed_setters_map.front(); E; E = E->next()) { | ||||
| 			function->indexed_setters.write[E->get()] = E->key(); | ||||
| 		} | ||||
| 	} else { | ||||
| 		function->_indexed_setters_count = 0; | ||||
| 		function->_indexed_setters_ptr = nullptr; | ||||
| 	} | ||||
| 
 | ||||
| 	if (indexed_getters_map.size()) { | ||||
| 		function->indexed_getters.resize(indexed_getters_map.size()); | ||||
| 		function->_indexed_getters_count = function->indexed_getters.size(); | ||||
| 		function->_indexed_getters_ptr = function->indexed_getters.ptr(); | ||||
| 		for (const Map<Variant::ValidatedIndexedGetter, int>::Element *E = indexed_getters_map.front(); E; E = E->next()) { | ||||
| 			function->indexed_getters.write[E->get()] = E->key(); | ||||
| 		} | ||||
| 	} else { | ||||
| 		function->_indexed_getters_count = 0; | ||||
| 		function->_indexed_getters_ptr = nullptr; | ||||
| 	} | ||||
| 
 | ||||
| 	if (debug_stack) { | ||||
| 		function->stack_debug = stack_debug; | ||||
| 	} | ||||
|  | @ -193,6 +265,9 @@ void GDScriptByteCodeGenerator::set_initial_line(int p_line) { | |||
| #define HAS_BUILTIN_TYPE(m_var) \ | ||||
| 	(m_var.type.has_type && m_var.type.kind == GDScriptDataType::BUILTIN) | ||||
| 
 | ||||
| #define IS_BUILTIN_TYPE(m_var, m_type) \ | ||||
| 	(m_var.type.has_type && m_var.type.kind == GDScriptDataType::BUILTIN && m_var.type.builtin_type == m_type) | ||||
| 
 | ||||
| void GDScriptByteCodeGenerator::write_operator(const Address &p_target, Variant::Operator p_operator, const Address &p_left_operand, const Address &p_right_operand) { | ||||
| 	if (HAS_BUILTIN_TYPE(p_left_operand) && HAS_BUILTIN_TYPE(p_right_operand)) { | ||||
| 		// Gather specific operator.
 | ||||
|  | @ -324,20 +399,69 @@ void GDScriptByteCodeGenerator::write_end_ternary() { | |||
| } | ||||
| 
 | ||||
| void GDScriptByteCodeGenerator::write_set(const Address &p_target, const Address &p_index, const Address &p_source) { | ||||
| 	append(GDScriptFunction::OPCODE_SET, 3); | ||||
| 	if (HAS_BUILTIN_TYPE(p_target)) { | ||||
| 		if (IS_BUILTIN_TYPE(p_index, Variant::INT) && Variant::get_member_validated_indexed_setter(p_target.type.builtin_type)) { | ||||
| 			// Use indexed setter instead.
 | ||||
| 			Variant::ValidatedIndexedSetter setter = Variant::get_member_validated_indexed_setter(p_target.type.builtin_type); | ||||
| 			append(GDScriptFunction::OPCODE_SET_INDEXED_VALIDATED, 3); | ||||
| 			append(p_target); | ||||
| 			append(p_index); | ||||
| 			append(p_source); | ||||
| 			append(setter); | ||||
| 			return; | ||||
| 		} else if (Variant::get_member_validated_keyed_setter(p_target.type.builtin_type)) { | ||||
| 			Variant::ValidatedKeyedSetter setter = Variant::get_member_validated_keyed_setter(p_target.type.builtin_type); | ||||
| 			append(GDScriptFunction::OPCODE_SET_KEYED_VALIDATED, 3); | ||||
| 			append(p_target); | ||||
| 			append(p_index); | ||||
| 			append(p_source); | ||||
| 			append(setter); | ||||
| 			return; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	append(GDScriptFunction::OPCODE_SET_KEYED, 3); | ||||
| 	append(p_target); | ||||
| 	append(p_index); | ||||
| 	append(p_source); | ||||
| } | ||||
| 
 | ||||
| void GDScriptByteCodeGenerator::write_get(const Address &p_target, const Address &p_index, const Address &p_source) { | ||||
| 	append(GDScriptFunction::OPCODE_GET, 3); | ||||
| 	if (HAS_BUILTIN_TYPE(p_source)) { | ||||
| 		if (IS_BUILTIN_TYPE(p_index, Variant::INT) && Variant::get_member_validated_indexed_getter(p_source.type.builtin_type)) { | ||||
| 			// Use indexed getter instead.
 | ||||
| 			Variant::ValidatedIndexedGetter getter = Variant::get_member_validated_indexed_getter(p_source.type.builtin_type); | ||||
| 			append(GDScriptFunction::OPCODE_GET_INDEXED_VALIDATED, 3); | ||||
| 			append(p_source); | ||||
| 			append(p_index); | ||||
| 			append(p_target); | ||||
| 			append(getter); | ||||
| 			return; | ||||
| 		} else if (Variant::get_member_validated_keyed_getter(p_source.type.builtin_type)) { | ||||
| 			Variant::ValidatedKeyedGetter getter = Variant::get_member_validated_keyed_getter(p_source.type.builtin_type); | ||||
| 			append(GDScriptFunction::OPCODE_GET_KEYED_VALIDATED, 3); | ||||
| 			append(p_source); | ||||
| 			append(p_index); | ||||
| 			append(p_target); | ||||
| 			append(getter); | ||||
| 			return; | ||||
| 		} | ||||
| 	} | ||||
| 	append(GDScriptFunction::OPCODE_GET_KEYED, 3); | ||||
| 	append(p_source); | ||||
| 	append(p_index); | ||||
| 	append(p_target); | ||||
| } | ||||
| 
 | ||||
| void GDScriptByteCodeGenerator::write_set_named(const Address &p_target, const StringName &p_name, const Address &p_source) { | ||||
| 	if (HAS_BUILTIN_TYPE(p_target) && Variant::get_member_validated_setter(p_target.type.builtin_type, p_name)) { | ||||
| 		Variant::ValidatedSetter setter = Variant::get_member_validated_setter(p_target.type.builtin_type, p_name); | ||||
| 		append(GDScriptFunction::OPCODE_SET_NAMED_VALIDATED, 2); | ||||
| 		append(p_target); | ||||
| 		append(p_source); | ||||
| 		append(setter); | ||||
| 		return; | ||||
| 	} | ||||
| 	append(GDScriptFunction::OPCODE_SET_NAMED, 2); | ||||
| 	append(p_target); | ||||
| 	append(p_source); | ||||
|  | @ -345,6 +469,14 @@ void GDScriptByteCodeGenerator::write_set_named(const Address &p_target, const S | |||
| } | ||||
| 
 | ||||
| void GDScriptByteCodeGenerator::write_get_named(const Address &p_target, const StringName &p_name, const Address &p_source) { | ||||
| 	if (HAS_BUILTIN_TYPE(p_source) && Variant::get_member_validated_getter(p_source.type.builtin_type, p_name)) { | ||||
| 		Variant::ValidatedGetter getter = Variant::get_member_validated_getter(p_source.type.builtin_type, p_name); | ||||
| 		append(GDScriptFunction::OPCODE_GET_NAMED_VALIDATED, 2); | ||||
| 		append(p_source); | ||||
| 		append(p_target); | ||||
| 		append(getter); | ||||
| 		return; | ||||
| 	} | ||||
| 	append(GDScriptFunction::OPCODE_GET_NAMED, 2); | ||||
| 	append(p_source); | ||||
| 	append(p_target); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 George Marques
						George Marques