You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-04 12:00:25 +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:
@@ -170,6 +170,78 @@ GDScriptFunction *GDScriptByteCodeGenerator::write_end() {
|
|||||||
function->_operator_funcs_ptr = nullptr;
|
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) {
|
if (debug_stack) {
|
||||||
function->stack_debug = stack_debug;
|
function->stack_debug = stack_debug;
|
||||||
}
|
}
|
||||||
@@ -193,6 +265,9 @@ void GDScriptByteCodeGenerator::set_initial_line(int p_line) {
|
|||||||
#define HAS_BUILTIN_TYPE(m_var) \
|
#define HAS_BUILTIN_TYPE(m_var) \
|
||||||
(m_var.type.has_type && m_var.type.kind == GDScriptDataType::BUILTIN)
|
(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) {
|
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)) {
|
if (HAS_BUILTIN_TYPE(p_left_operand) && HAS_BUILTIN_TYPE(p_right_operand)) {
|
||||||
// Gather specific operator.
|
// 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) {
|
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_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, 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_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) {
|
||||||
|
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(GDScriptFunction::OPCODE_SET_NAMED, 2);
|
||||||
append(p_target);
|
append(p_target);
|
||||||
append(p_source);
|
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) {
|
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(GDScriptFunction::OPCODE_GET_NAMED, 2);
|
||||||
append(p_source);
|
append(p_source);
|
||||||
append(p_target);
|
append(p_target);
|
||||||
|
|||||||
@@ -61,6 +61,12 @@ class GDScriptByteCodeGenerator : public GDScriptCodeGenerator {
|
|||||||
Vector<StringName> named_globals;
|
Vector<StringName> named_globals;
|
||||||
#endif
|
#endif
|
||||||
Map<Variant::ValidatedOperatorEvaluator, int> operator_func_map;
|
Map<Variant::ValidatedOperatorEvaluator, int> operator_func_map;
|
||||||
|
Map<Variant::ValidatedSetter, int> setters_map;
|
||||||
|
Map<Variant::ValidatedGetter, int> getters_map;
|
||||||
|
Map<Variant::ValidatedKeyedSetter, int> keyed_setters_map;
|
||||||
|
Map<Variant::ValidatedKeyedGetter, int> keyed_getters_map;
|
||||||
|
Map<Variant::ValidatedIndexedSetter, int> indexed_setters_map;
|
||||||
|
Map<Variant::ValidatedIndexedGetter, int> indexed_getters_map;
|
||||||
|
|
||||||
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;
|
||||||
@@ -145,6 +151,54 @@ class GDScriptByteCodeGenerator : public GDScriptCodeGenerator {
|
|||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int get_setter_pos(const Variant::ValidatedSetter p_setter) {
|
||||||
|
if (setters_map.has(p_setter))
|
||||||
|
return setters_map[p_setter];
|
||||||
|
int pos = setters_map.size();
|
||||||
|
setters_map[p_setter] = pos;
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_getter_pos(const Variant::ValidatedGetter p_getter) {
|
||||||
|
if (getters_map.has(p_getter))
|
||||||
|
return getters_map[p_getter];
|
||||||
|
int pos = getters_map.size();
|
||||||
|
getters_map[p_getter] = pos;
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_keyed_setter_pos(const Variant::ValidatedKeyedSetter p_keyed_setter) {
|
||||||
|
if (keyed_setters_map.has(p_keyed_setter))
|
||||||
|
return keyed_setters_map[p_keyed_setter];
|
||||||
|
int pos = keyed_setters_map.size();
|
||||||
|
keyed_setters_map[p_keyed_setter] = pos;
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_keyed_getter_pos(const Variant::ValidatedKeyedGetter p_keyed_getter) {
|
||||||
|
if (keyed_getters_map.has(p_keyed_getter))
|
||||||
|
return keyed_getters_map[p_keyed_getter];
|
||||||
|
int pos = keyed_getters_map.size();
|
||||||
|
keyed_getters_map[p_keyed_getter] = pos;
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_indexed_setter_pos(const Variant::ValidatedIndexedSetter p_indexed_setter) {
|
||||||
|
if (indexed_setters_map.has(p_indexed_setter))
|
||||||
|
return indexed_setters_map[p_indexed_setter];
|
||||||
|
int pos = indexed_setters_map.size();
|
||||||
|
indexed_setters_map[p_indexed_setter] = pos;
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_indexed_getter_pos(const Variant::ValidatedIndexedGetter p_indexed_getter) {
|
||||||
|
if (indexed_getters_map.has(p_indexed_getter))
|
||||||
|
return indexed_getters_map[p_indexed_getter];
|
||||||
|
int pos = indexed_getters_map.size();
|
||||||
|
indexed_getters_map[p_indexed_getter] = pos;
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
void alloc_stack(int p_level) {
|
void alloc_stack(int p_level) {
|
||||||
if (p_level >= stack_max)
|
if (p_level >= stack_max)
|
||||||
stack_max = p_level + 1;
|
stack_max = p_level + 1;
|
||||||
@@ -204,6 +258,30 @@ class GDScriptByteCodeGenerator : public GDScriptCodeGenerator {
|
|||||||
opcodes.push_back(get_operation_pos(p_operation));
|
opcodes.push_back(get_operation_pos(p_operation));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void append(const Variant::ValidatedSetter p_setter) {
|
||||||
|
opcodes.push_back(get_setter_pos(p_setter));
|
||||||
|
}
|
||||||
|
|
||||||
|
void append(const Variant::ValidatedGetter p_getter) {
|
||||||
|
opcodes.push_back(get_getter_pos(p_getter));
|
||||||
|
}
|
||||||
|
|
||||||
|
void append(const Variant::ValidatedKeyedSetter p_keyed_setter) {
|
||||||
|
opcodes.push_back(get_keyed_setter_pos(p_keyed_setter));
|
||||||
|
}
|
||||||
|
|
||||||
|
void append(const Variant::ValidatedKeyedGetter p_keyed_getter) {
|
||||||
|
opcodes.push_back(get_keyed_getter_pos(p_keyed_getter));
|
||||||
|
}
|
||||||
|
|
||||||
|
void append(const Variant::ValidatedIndexedSetter p_indexed_setter) {
|
||||||
|
opcodes.push_back(get_indexed_setter_pos(p_indexed_setter));
|
||||||
|
}
|
||||||
|
|
||||||
|
void append(const Variant::ValidatedIndexedGetter p_indexed_getter) {
|
||||||
|
opcodes.push_back(get_indexed_getter_pos(p_indexed_getter));
|
||||||
|
}
|
||||||
|
|
||||||
void patch_jump(int p_address) {
|
void patch_jump(int p_address) {
|
||||||
opcodes.write[p_address] = opcodes.size();
|
opcodes.write[p_address] = opcodes.size();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -167,8 +167,8 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const {
|
|||||||
|
|
||||||
incr += 4;
|
incr += 4;
|
||||||
} break;
|
} break;
|
||||||
case OPCODE_SET: {
|
case OPCODE_SET_KEYED: {
|
||||||
text += "set ";
|
text += "set keyed ";
|
||||||
text += DADDR(1);
|
text += DADDR(1);
|
||||||
text += "[";
|
text += "[";
|
||||||
text += DADDR(2);
|
text += DADDR(2);
|
||||||
@@ -177,8 +177,28 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const {
|
|||||||
|
|
||||||
incr += 4;
|
incr += 4;
|
||||||
} break;
|
} break;
|
||||||
case OPCODE_GET: {
|
case OPCODE_SET_KEYED_VALIDATED: {
|
||||||
text += "get ";
|
text += "set keyed validated ";
|
||||||
|
text += DADDR(1);
|
||||||
|
text += "[";
|
||||||
|
text += DADDR(2);
|
||||||
|
text += "] = ";
|
||||||
|
text += DADDR(3);
|
||||||
|
|
||||||
|
incr += 5;
|
||||||
|
} break;
|
||||||
|
case OPCODE_SET_INDEXED_VALIDATED: {
|
||||||
|
text += "set indexed validated ";
|
||||||
|
text += DADDR(1);
|
||||||
|
text += "[";
|
||||||
|
text += DADDR(2);
|
||||||
|
text += "] = ";
|
||||||
|
text += DADDR(3);
|
||||||
|
|
||||||
|
incr += 5;
|
||||||
|
} break;
|
||||||
|
case OPCODE_GET_KEYED: {
|
||||||
|
text += "get keyed ";
|
||||||
text += DADDR(3);
|
text += DADDR(3);
|
||||||
text += " = ";
|
text += " = ";
|
||||||
text += DADDR(1);
|
text += DADDR(1);
|
||||||
@@ -188,6 +208,28 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const {
|
|||||||
|
|
||||||
incr += 4;
|
incr += 4;
|
||||||
} break;
|
} break;
|
||||||
|
case OPCODE_GET_KEYED_VALIDATED: {
|
||||||
|
text += "get keyed validated ";
|
||||||
|
text += DADDR(3);
|
||||||
|
text += " = ";
|
||||||
|
text += DADDR(1);
|
||||||
|
text += "[";
|
||||||
|
text += DADDR(2);
|
||||||
|
text += "]";
|
||||||
|
|
||||||
|
incr += 5;
|
||||||
|
} break;
|
||||||
|
case OPCODE_GET_INDEXED_VALIDATED: {
|
||||||
|
text += "get indexed validated ";
|
||||||
|
text += DADDR(3);
|
||||||
|
text += " = ";
|
||||||
|
text += DADDR(1);
|
||||||
|
text += "[";
|
||||||
|
text += DADDR(2);
|
||||||
|
text += "]";
|
||||||
|
|
||||||
|
incr += 5;
|
||||||
|
} break;
|
||||||
case OPCODE_SET_NAMED: {
|
case OPCODE_SET_NAMED: {
|
||||||
text += "set_named ";
|
text += "set_named ";
|
||||||
text += DADDR(1);
|
text += DADDR(1);
|
||||||
@@ -198,6 +240,16 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const {
|
|||||||
|
|
||||||
incr += 4;
|
incr += 4;
|
||||||
} break;
|
} break;
|
||||||
|
case OPCODE_SET_NAMED_VALIDATED: {
|
||||||
|
text += "set_named validated ";
|
||||||
|
text += DADDR(1);
|
||||||
|
text += "[\"";
|
||||||
|
text += "<unknown name>";
|
||||||
|
text += "\"] = ";
|
||||||
|
text += DADDR(2);
|
||||||
|
|
||||||
|
incr += 4;
|
||||||
|
} break;
|
||||||
case OPCODE_GET_NAMED: {
|
case OPCODE_GET_NAMED: {
|
||||||
text += "get_named ";
|
text += "get_named ";
|
||||||
text += DADDR(2);
|
text += DADDR(2);
|
||||||
@@ -209,6 +261,17 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const {
|
|||||||
|
|
||||||
incr += 4;
|
incr += 4;
|
||||||
} break;
|
} break;
|
||||||
|
case OPCODE_GET_NAMED_VALIDATED: {
|
||||||
|
text += "get_named validated ";
|
||||||
|
text += DADDR(2);
|
||||||
|
text += " = ";
|
||||||
|
text += DADDR(1);
|
||||||
|
text += "[\"";
|
||||||
|
text += "<unknown name>";
|
||||||
|
text += "\"]";
|
||||||
|
|
||||||
|
incr += 4;
|
||||||
|
} break;
|
||||||
case OPCODE_SET_MEMBER: {
|
case OPCODE_SET_MEMBER: {
|
||||||
text += "set_member ";
|
text += "set_member ";
|
||||||
text += "[\"";
|
text += "[\"";
|
||||||
|
|||||||
@@ -162,10 +162,16 @@ public:
|
|||||||
OPCODE_OPERATOR_VALIDATED,
|
OPCODE_OPERATOR_VALIDATED,
|
||||||
OPCODE_EXTENDS_TEST,
|
OPCODE_EXTENDS_TEST,
|
||||||
OPCODE_IS_BUILTIN,
|
OPCODE_IS_BUILTIN,
|
||||||
OPCODE_SET,
|
OPCODE_SET_KEYED,
|
||||||
OPCODE_GET,
|
OPCODE_SET_KEYED_VALIDATED,
|
||||||
|
OPCODE_SET_INDEXED_VALIDATED,
|
||||||
|
OPCODE_GET_KEYED,
|
||||||
|
OPCODE_GET_KEYED_VALIDATED,
|
||||||
|
OPCODE_GET_INDEXED_VALIDATED,
|
||||||
OPCODE_SET_NAMED,
|
OPCODE_SET_NAMED,
|
||||||
|
OPCODE_SET_NAMED_VALIDATED,
|
||||||
OPCODE_GET_NAMED,
|
OPCODE_GET_NAMED,
|
||||||
|
OPCODE_GET_NAMED_VALIDATED,
|
||||||
OPCODE_SET_MEMBER,
|
OPCODE_SET_MEMBER,
|
||||||
OPCODE_GET_MEMBER,
|
OPCODE_GET_MEMBER,
|
||||||
OPCODE_ASSIGN,
|
OPCODE_ASSIGN,
|
||||||
@@ -244,6 +250,18 @@ private:
|
|||||||
int _default_arg_count = 0;
|
int _default_arg_count = 0;
|
||||||
int _operator_funcs_count = 0;
|
int _operator_funcs_count = 0;
|
||||||
const Variant::ValidatedOperatorEvaluator *_operator_funcs_ptr = nullptr;
|
const Variant::ValidatedOperatorEvaluator *_operator_funcs_ptr = nullptr;
|
||||||
|
int _setters_count = 0;
|
||||||
|
const Variant::ValidatedSetter *_setters_ptr = nullptr;
|
||||||
|
int _getters_count = 0;
|
||||||
|
const Variant::ValidatedGetter *_getters_ptr = nullptr;
|
||||||
|
int _keyed_setters_count = 0;
|
||||||
|
const Variant::ValidatedKeyedSetter *_keyed_setters_ptr = nullptr;
|
||||||
|
int _keyed_getters_count = 0;
|
||||||
|
const Variant::ValidatedKeyedGetter *_keyed_getters_ptr = nullptr;
|
||||||
|
int _indexed_setters_count = 0;
|
||||||
|
const Variant::ValidatedIndexedSetter *_indexed_setters_ptr = nullptr;
|
||||||
|
int _indexed_getters_count = 0;
|
||||||
|
const Variant::ValidatedIndexedGetter *_indexed_getters_ptr = nullptr;
|
||||||
const int *_code_ptr = nullptr;
|
const int *_code_ptr = nullptr;
|
||||||
int _code_size = 0;
|
int _code_size = 0;
|
||||||
int _argument_count = 0;
|
int _argument_count = 0;
|
||||||
@@ -260,6 +278,12 @@ private:
|
|||||||
Vector<StringName> global_names;
|
Vector<StringName> global_names;
|
||||||
Vector<int> default_arguments;
|
Vector<int> default_arguments;
|
||||||
Vector<Variant::ValidatedOperatorEvaluator> operator_funcs;
|
Vector<Variant::ValidatedOperatorEvaluator> operator_funcs;
|
||||||
|
Vector<Variant::ValidatedSetter> setters;
|
||||||
|
Vector<Variant::ValidatedGetter> getters;
|
||||||
|
Vector<Variant::ValidatedKeyedSetter> keyed_setters;
|
||||||
|
Vector<Variant::ValidatedKeyedGetter> keyed_getters;
|
||||||
|
Vector<Variant::ValidatedIndexedSetter> indexed_setters;
|
||||||
|
Vector<Variant::ValidatedIndexedGetter> indexed_getters;
|
||||||
Vector<int> code;
|
Vector<int> code;
|
||||||
Vector<GDScriptDataType> argument_types;
|
Vector<GDScriptDataType> argument_types;
|
||||||
GDScriptDataType return_type;
|
GDScriptDataType return_type;
|
||||||
|
|||||||
@@ -191,10 +191,16 @@ String GDScriptFunction::_get_call_error(const Callable::CallError &p_err, const
|
|||||||
&&OPCODE_OPERATOR_VALIDATED, \
|
&&OPCODE_OPERATOR_VALIDATED, \
|
||||||
&&OPCODE_EXTENDS_TEST, \
|
&&OPCODE_EXTENDS_TEST, \
|
||||||
&&OPCODE_IS_BUILTIN, \
|
&&OPCODE_IS_BUILTIN, \
|
||||||
&&OPCODE_SET, \
|
&&OPCODE_SET_KEYED, \
|
||||||
&&OPCODE_GET, \
|
&&OPCODE_SET_KEYED_VALIDATED, \
|
||||||
|
&&OPCODE_SET_INDEXED_VALIDATED, \
|
||||||
|
&&OPCODE_GET_KEYED, \
|
||||||
|
&&OPCODE_GET_KEYED_VALIDATED, \
|
||||||
|
&&OPCODE_GET_INDEXED_VALIDATED, \
|
||||||
&&OPCODE_SET_NAMED, \
|
&&OPCODE_SET_NAMED, \
|
||||||
|
&&OPCODE_SET_NAMED_VALIDATED, \
|
||||||
&&OPCODE_GET_NAMED, \
|
&&OPCODE_GET_NAMED, \
|
||||||
|
&&OPCODE_GET_NAMED_VALIDATED, \
|
||||||
&&OPCODE_SET_MEMBER, \
|
&&OPCODE_SET_MEMBER, \
|
||||||
&&OPCODE_GET_MEMBER, \
|
&&OPCODE_GET_MEMBER, \
|
||||||
&&OPCODE_ASSIGN, \
|
&&OPCODE_ASSIGN, \
|
||||||
@@ -575,7 +581,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
|
|||||||
}
|
}
|
||||||
DISPATCH_OPCODE;
|
DISPATCH_OPCODE;
|
||||||
|
|
||||||
OPCODE(OPCODE_SET) {
|
OPCODE(OPCODE_SET_KEYED) {
|
||||||
CHECK_SPACE(3);
|
CHECK_SPACE(3);
|
||||||
|
|
||||||
GET_INSTRUCTION_ARG(dst, 0);
|
GET_INSTRUCTION_ARG(dst, 0);
|
||||||
@@ -601,7 +607,69 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
|
|||||||
}
|
}
|
||||||
DISPATCH_OPCODE;
|
DISPATCH_OPCODE;
|
||||||
|
|
||||||
OPCODE(OPCODE_GET) {
|
OPCODE(OPCODE_SET_KEYED_VALIDATED) {
|
||||||
|
CHECK_SPACE(4);
|
||||||
|
|
||||||
|
GET_INSTRUCTION_ARG(dst, 0);
|
||||||
|
GET_INSTRUCTION_ARG(index, 1);
|
||||||
|
GET_INSTRUCTION_ARG(value, 2);
|
||||||
|
|
||||||
|
int index_setter = _code_ptr[ip + 4];
|
||||||
|
GD_ERR_BREAK(index_setter < 0 || index_setter >= _keyed_setters_count);
|
||||||
|
const Variant::ValidatedKeyedSetter setter = _keyed_setters_ptr[index_setter];
|
||||||
|
|
||||||
|
bool valid;
|
||||||
|
setter(dst, index, value, valid);
|
||||||
|
|
||||||
|
#ifdef DEBUG_ENABLED
|
||||||
|
if (!valid) {
|
||||||
|
String v = index->operator String();
|
||||||
|
if (v != "") {
|
||||||
|
v = "'" + v + "'";
|
||||||
|
} else {
|
||||||
|
v = "of type '" + _get_var_type(index) + "'";
|
||||||
|
}
|
||||||
|
err_text = "Invalid set index " + v + " (on base: '" + _get_var_type(dst) + "') with value of type '" + _get_var_type(value) + "'";
|
||||||
|
OPCODE_BREAK;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
ip += 5;
|
||||||
|
}
|
||||||
|
DISPATCH_OPCODE;
|
||||||
|
|
||||||
|
OPCODE(OPCODE_SET_INDEXED_VALIDATED) {
|
||||||
|
CHECK_SPACE(4);
|
||||||
|
|
||||||
|
GET_INSTRUCTION_ARG(dst, 0);
|
||||||
|
GET_INSTRUCTION_ARG(index, 1);
|
||||||
|
GET_INSTRUCTION_ARG(value, 2);
|
||||||
|
|
||||||
|
int index_setter = _code_ptr[ip + 4];
|
||||||
|
GD_ERR_BREAK(index_setter < 0 || index_setter >= _indexed_setters_count);
|
||||||
|
const Variant::ValidatedIndexedSetter setter = _indexed_setters_ptr[index_setter];
|
||||||
|
|
||||||
|
int64_t int_index = *VariantInternal::get_int(index);
|
||||||
|
|
||||||
|
bool oob;
|
||||||
|
setter(dst, int_index, value, oob);
|
||||||
|
|
||||||
|
#ifdef DEBUG_ENABLED
|
||||||
|
if (oob) {
|
||||||
|
String v = index->operator String();
|
||||||
|
if (v != "") {
|
||||||
|
v = "'" + v + "'";
|
||||||
|
} else {
|
||||||
|
v = "of type '" + _get_var_type(index) + "'";
|
||||||
|
}
|
||||||
|
err_text = "Out of bounds set index " + v + " (on base: '" + _get_var_type(dst) + "')";
|
||||||
|
OPCODE_BREAK;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
ip += 5;
|
||||||
|
}
|
||||||
|
DISPATCH_OPCODE;
|
||||||
|
|
||||||
|
OPCODE(OPCODE_GET_KEYED) {
|
||||||
CHECK_SPACE(3);
|
CHECK_SPACE(3);
|
||||||
|
|
||||||
GET_INSTRUCTION_ARG(src, 0);
|
GET_INSTRUCTION_ARG(src, 0);
|
||||||
@@ -610,7 +678,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
|
|||||||
|
|
||||||
bool valid;
|
bool valid;
|
||||||
#ifdef DEBUG_ENABLED
|
#ifdef DEBUG_ENABLED
|
||||||
//allow better error message in cases where src and dst are the same stack position
|
// Allow better error message in cases where src and dst are the same stack position.
|
||||||
Variant ret = src->get(*index, &valid);
|
Variant ret = src->get(*index, &valid);
|
||||||
#else
|
#else
|
||||||
*dst = src->get(*index, &valid);
|
*dst = src->get(*index, &valid);
|
||||||
@@ -633,6 +701,74 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
|
|||||||
}
|
}
|
||||||
DISPATCH_OPCODE;
|
DISPATCH_OPCODE;
|
||||||
|
|
||||||
|
OPCODE(OPCODE_GET_KEYED_VALIDATED) {
|
||||||
|
CHECK_SPACE(4);
|
||||||
|
|
||||||
|
GET_INSTRUCTION_ARG(src, 0);
|
||||||
|
GET_INSTRUCTION_ARG(key, 1);
|
||||||
|
GET_INSTRUCTION_ARG(dst, 2);
|
||||||
|
|
||||||
|
int index_getter = _code_ptr[ip + 4];
|
||||||
|
GD_ERR_BREAK(index_getter < 0 || index_getter >= _keyed_getters_count);
|
||||||
|
const Variant::ValidatedKeyedGetter getter = _keyed_getters_ptr[index_getter];
|
||||||
|
|
||||||
|
bool valid;
|
||||||
|
#ifdef DEBUG_ENABLED
|
||||||
|
// Allow better error message in cases where src and dst are the same stack position.
|
||||||
|
Variant ret;
|
||||||
|
getter(src, key, &ret, valid);
|
||||||
|
#else
|
||||||
|
getter(src, key, dst, valid);
|
||||||
|
#endif
|
||||||
|
#ifdef DEBUG_ENABLED
|
||||||
|
if (!valid) {
|
||||||
|
String v = key->operator String();
|
||||||
|
if (v != "") {
|
||||||
|
v = "'" + v + "'";
|
||||||
|
} else {
|
||||||
|
v = "of type '" + _get_var_type(key) + "'";
|
||||||
|
}
|
||||||
|
err_text = "Invalid get index " + v + " (on base: '" + _get_var_type(src) + "').";
|
||||||
|
OPCODE_BREAK;
|
||||||
|
}
|
||||||
|
*dst = ret;
|
||||||
|
#endif
|
||||||
|
ip += 5;
|
||||||
|
}
|
||||||
|
DISPATCH_OPCODE;
|
||||||
|
|
||||||
|
OPCODE(OPCODE_GET_INDEXED_VALIDATED) {
|
||||||
|
CHECK_SPACE(4);
|
||||||
|
|
||||||
|
GET_INSTRUCTION_ARG(src, 0);
|
||||||
|
GET_INSTRUCTION_ARG(index, 1);
|
||||||
|
GET_INSTRUCTION_ARG(dst, 2);
|
||||||
|
|
||||||
|
int index_getter = _code_ptr[ip + 4];
|
||||||
|
GD_ERR_BREAK(index_getter < 0 || index_getter >= _indexed_getters_count);
|
||||||
|
const Variant::ValidatedIndexedGetter getter = _indexed_getters_ptr[index_getter];
|
||||||
|
|
||||||
|
int64_t int_index = *VariantInternal::get_int(index);
|
||||||
|
|
||||||
|
bool oob;
|
||||||
|
getter(src, int_index, dst, oob);
|
||||||
|
|
||||||
|
#ifdef DEBUG_ENABLED
|
||||||
|
if (oob) {
|
||||||
|
String v = index->operator String();
|
||||||
|
if (v != "") {
|
||||||
|
v = "'" + v + "'";
|
||||||
|
} else {
|
||||||
|
v = "of type '" + _get_var_type(index) + "'";
|
||||||
|
}
|
||||||
|
err_text = "Out of bounds get index " + v + " (on base: '" + _get_var_type(src) + "')";
|
||||||
|
OPCODE_BREAK;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
ip += 5;
|
||||||
|
}
|
||||||
|
DISPATCH_OPCODE;
|
||||||
|
|
||||||
OPCODE(OPCODE_SET_NAMED) {
|
OPCODE(OPCODE_SET_NAMED) {
|
||||||
CHECK_SPACE(3);
|
CHECK_SPACE(3);
|
||||||
|
|
||||||
@@ -658,6 +794,21 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
|
|||||||
}
|
}
|
||||||
DISPATCH_OPCODE;
|
DISPATCH_OPCODE;
|
||||||
|
|
||||||
|
OPCODE(OPCODE_SET_NAMED_VALIDATED) {
|
||||||
|
CHECK_SPACE(3);
|
||||||
|
|
||||||
|
GET_INSTRUCTION_ARG(dst, 0);
|
||||||
|
GET_INSTRUCTION_ARG(value, 1);
|
||||||
|
|
||||||
|
int index_setter = _code_ptr[ip + 3];
|
||||||
|
GD_ERR_BREAK(index_setter < 0 || index_setter >= _setters_count);
|
||||||
|
const Variant::ValidatedSetter setter = _setters_ptr[index_setter];
|
||||||
|
|
||||||
|
setter(dst, value);
|
||||||
|
ip += 4;
|
||||||
|
}
|
||||||
|
DISPATCH_OPCODE;
|
||||||
|
|
||||||
OPCODE(OPCODE_GET_NAMED) {
|
OPCODE(OPCODE_GET_NAMED) {
|
||||||
CHECK_SPACE(4);
|
CHECK_SPACE(4);
|
||||||
|
|
||||||
@@ -692,6 +843,21 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
|
|||||||
}
|
}
|
||||||
DISPATCH_OPCODE;
|
DISPATCH_OPCODE;
|
||||||
|
|
||||||
|
OPCODE(OPCODE_GET_NAMED_VALIDATED) {
|
||||||
|
CHECK_SPACE(3);
|
||||||
|
|
||||||
|
GET_INSTRUCTION_ARG(src, 0);
|
||||||
|
GET_INSTRUCTION_ARG(dst, 1);
|
||||||
|
|
||||||
|
int index_getter = _code_ptr[ip + 3];
|
||||||
|
GD_ERR_BREAK(index_getter < 0 || index_getter >= _getters_count);
|
||||||
|
const Variant::ValidatedGetter getter = _getters_ptr[index_getter];
|
||||||
|
|
||||||
|
getter(src, dst);
|
||||||
|
ip += 4;
|
||||||
|
}
|
||||||
|
DISPATCH_OPCODE;
|
||||||
|
|
||||||
OPCODE(OPCODE_SET_MEMBER) {
|
OPCODE(OPCODE_SET_MEMBER) {
|
||||||
CHECK_SPACE(3);
|
CHECK_SPACE(3);
|
||||||
GET_INSTRUCTION_ARG(src, 0);
|
GET_INSTRUCTION_ARG(src, 0);
|
||||||
|
|||||||
Reference in New Issue
Block a user