GDScript: Add faster instruction for validated constructor
Only for built-in types.
This commit is contained in:
parent
e0dca3c6b6
commit
5518e2a68e
|
@ -244,7 +244,7 @@ GDScriptFunction *GDScriptByteCodeGenerator::write_end() {
|
||||||
|
|
||||||
if (builtin_method_map.size()) {
|
if (builtin_method_map.size()) {
|
||||||
function->builtin_methods.resize(builtin_method_map.size());
|
function->builtin_methods.resize(builtin_method_map.size());
|
||||||
function->_builtin_methods_ptr = function->builtin_methods.ptrw();
|
function->_builtin_methods_ptr = function->builtin_methods.ptr();
|
||||||
function->_builtin_methods_count = builtin_method_map.size();
|
function->_builtin_methods_count = builtin_method_map.size();
|
||||||
for (const Map<Variant::ValidatedBuiltInMethod, int>::Element *E = builtin_method_map.front(); E; E = E->next()) {
|
for (const Map<Variant::ValidatedBuiltInMethod, int>::Element *E = builtin_method_map.front(); E; E = E->next()) {
|
||||||
function->builtin_methods.write[E->get()] = E->key();
|
function->builtin_methods.write[E->get()] = E->key();
|
||||||
|
@ -254,6 +254,18 @@ GDScriptFunction *GDScriptByteCodeGenerator::write_end() {
|
||||||
function->_builtin_methods_count = 0;
|
function->_builtin_methods_count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (constructors_map.size()) {
|
||||||
|
function->constructors.resize(constructors_map.size());
|
||||||
|
function->_constructors_ptr = function->constructors.ptr();
|
||||||
|
function->_constructors_count = constructors_map.size();
|
||||||
|
for (const Map<Variant::ValidatedConstructor, int>::Element *E = constructors_map.front(); E; E = E->next()) {
|
||||||
|
function->constructors.write[E->get()] = E->key();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
function->_constructors_ptr = nullptr;
|
||||||
|
function->_constructors_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (method_bind_map.size()) {
|
if (method_bind_map.size()) {
|
||||||
function->methods.resize(method_bind_map.size());
|
function->methods.resize(method_bind_map.size());
|
||||||
function->_methods_ptr = function->methods.ptrw();
|
function->_methods_ptr = function->methods.ptrw();
|
||||||
|
@ -797,6 +809,46 @@ void GDScriptByteCodeGenerator::write_call_script_function(const Address &p_targ
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
||||||
|
// Try to find an appropriate constructor.
|
||||||
|
bool all_have_type = true;
|
||||||
|
Vector<Variant::Type> arg_types;
|
||||||
|
for (int i = 0; i < p_arguments.size(); i++) {
|
||||||
|
if (!HAS_BUILTIN_TYPE(p_arguments[i])) {
|
||||||
|
all_have_type = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
arg_types.push_back(p_arguments[i].type.builtin_type);
|
||||||
|
}
|
||||||
|
if (all_have_type) {
|
||||||
|
int valid_constructor = -1;
|
||||||
|
for (int i = 0; i < Variant::get_constructor_count(p_type); i++) {
|
||||||
|
if (Variant::get_constructor_argument_count(p_type, i) != p_arguments.size()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int types_correct = true;
|
||||||
|
for (int j = 0; j < arg_types.size(); j++) {
|
||||||
|
if (arg_types[j] != Variant::get_constructor_argument_type(p_type, i, j)) {
|
||||||
|
types_correct = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (types_correct) {
|
||||||
|
valid_constructor = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (valid_constructor >= 0) {
|
||||||
|
append(GDScriptFunction::OPCODE_CONSTRUCT_VALIDATED, 1 + p_arguments.size());
|
||||||
|
for (int i = 0; i < p_arguments.size(); i++) {
|
||||||
|
append(p_arguments[i]);
|
||||||
|
}
|
||||||
|
append(p_target);
|
||||||
|
append(p_arguments.size());
|
||||||
|
append(Variant::get_validated_constructor(p_type, valid_constructor));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
append(GDScriptFunction::OPCODE_CONSTRUCT, 1 + 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]);
|
||||||
|
|
|
@ -69,6 +69,7 @@ class GDScriptByteCodeGenerator : public GDScriptCodeGenerator {
|
||||||
Map<Variant::ValidatedIndexedSetter, int> indexed_setters_map;
|
Map<Variant::ValidatedIndexedSetter, int> indexed_setters_map;
|
||||||
Map<Variant::ValidatedIndexedGetter, int> indexed_getters_map;
|
Map<Variant::ValidatedIndexedGetter, int> indexed_getters_map;
|
||||||
Map<Variant::ValidatedBuiltInMethod, int> builtin_method_map;
|
Map<Variant::ValidatedBuiltInMethod, int> builtin_method_map;
|
||||||
|
Map<Variant::ValidatedConstructor, int> constructors_map;
|
||||||
Map<MethodBind *, int> method_bind_map;
|
Map<MethodBind *, int> method_bind_map;
|
||||||
|
|
||||||
List<int> if_jmp_addrs; // List since this can be nested.
|
List<int> if_jmp_addrs; // List since this can be nested.
|
||||||
|
@ -211,6 +212,15 @@ class GDScriptByteCodeGenerator : public GDScriptCodeGenerator {
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int get_constructor_pos(const Variant::ValidatedConstructor p_constructor) {
|
||||||
|
if (constructors_map.has(p_constructor)) {
|
||||||
|
return constructors_map[p_constructor];
|
||||||
|
}
|
||||||
|
int pos = constructors_map.size();
|
||||||
|
constructors_map[p_constructor] = pos;
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
int get_method_bind_pos(MethodBind *p_method) {
|
int get_method_bind_pos(MethodBind *p_method) {
|
||||||
if (method_bind_map.has(p_method)) {
|
if (method_bind_map.has(p_method)) {
|
||||||
return method_bind_map[p_method];
|
return method_bind_map[p_method];
|
||||||
|
@ -312,6 +322,10 @@ class GDScriptByteCodeGenerator : public GDScriptCodeGenerator {
|
||||||
opcodes.push_back(get_builtin_method_pos(p_method));
|
opcodes.push_back(get_builtin_method_pos(p_method));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void append(const Variant::ValidatedConstructor p_constructor) {
|
||||||
|
opcodes.push_back(get_constructor_pos(p_constructor));
|
||||||
|
}
|
||||||
|
|
||||||
void append(MethodBind *p_method) {
|
void append(MethodBind *p_method) {
|
||||||
opcodes.push_back(get_method_bind_pos(p_method));
|
opcodes.push_back(get_method_bind_pos(p_method));
|
||||||
}
|
}
|
||||||
|
|
|
@ -384,7 +384,7 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const {
|
||||||
} break;
|
} break;
|
||||||
case OPCODE_CONSTRUCT: {
|
case OPCODE_CONSTRUCT: {
|
||||||
Variant::Type t = Variant::Type(_code_ptr[ip + 3 + instr_var_args]);
|
Variant::Type t = Variant::Type(_code_ptr[ip + 3 + instr_var_args]);
|
||||||
int argc = _code_ptr[ip + 2 + instr_var_args];
|
int argc = _code_ptr[ip + 1 + instr_var_args];
|
||||||
|
|
||||||
text += "construct ";
|
text += "construct ";
|
||||||
text += DADDR(1 + argc);
|
text += DADDR(1 + argc);
|
||||||
|
@ -400,6 +400,23 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const {
|
||||||
|
|
||||||
incr = 3 + instr_var_args;
|
incr = 3 + instr_var_args;
|
||||||
} break;
|
} break;
|
||||||
|
case OPCODE_CONSTRUCT_VALIDATED: {
|
||||||
|
int argc = _code_ptr[ip + 1 + instr_var_args];
|
||||||
|
|
||||||
|
text += "construct validated ";
|
||||||
|
text += DADDR(1 + argc);
|
||||||
|
text += " = ";
|
||||||
|
|
||||||
|
text += "<unkown type>(";
|
||||||
|
for (int i = 0; i < argc; i++) {
|
||||||
|
if (i > 0)
|
||||||
|
text += ", ";
|
||||||
|
text += DADDR(i + 1);
|
||||||
|
}
|
||||||
|
text += ")";
|
||||||
|
|
||||||
|
incr = 3 + instr_var_args;
|
||||||
|
} break;
|
||||||
case OPCODE_CONSTRUCT_ARRAY: {
|
case OPCODE_CONSTRUCT_ARRAY: {
|
||||||
int argc = _code_ptr[ip + 1 + instr_var_args];
|
int argc = _code_ptr[ip + 1 + instr_var_args];
|
||||||
text += " make_array ";
|
text += " make_array ";
|
||||||
|
|
|
@ -183,7 +183,8 @@ public:
|
||||||
OPCODE_CAST_TO_BUILTIN,
|
OPCODE_CAST_TO_BUILTIN,
|
||||||
OPCODE_CAST_TO_NATIVE,
|
OPCODE_CAST_TO_NATIVE,
|
||||||
OPCODE_CAST_TO_SCRIPT,
|
OPCODE_CAST_TO_SCRIPT,
|
||||||
OPCODE_CONSTRUCT, //only for basic types!!
|
OPCODE_CONSTRUCT, // Only for basic types!
|
||||||
|
OPCODE_CONSTRUCT_VALIDATED, // Only for basic types!
|
||||||
OPCODE_CONSTRUCT_ARRAY,
|
OPCODE_CONSTRUCT_ARRAY,
|
||||||
OPCODE_CONSTRUCT_DICTIONARY,
|
OPCODE_CONSTRUCT_DICTIONARY,
|
||||||
OPCODE_CALL,
|
OPCODE_CALL,
|
||||||
|
@ -341,6 +342,8 @@ private:
|
||||||
const Variant::ValidatedIndexedGetter *_indexed_getters_ptr = nullptr;
|
const Variant::ValidatedIndexedGetter *_indexed_getters_ptr = nullptr;
|
||||||
int _builtin_methods_count = 0;
|
int _builtin_methods_count = 0;
|
||||||
const Variant::ValidatedBuiltInMethod *_builtin_methods_ptr = nullptr;
|
const Variant::ValidatedBuiltInMethod *_builtin_methods_ptr = nullptr;
|
||||||
|
int _constructors_count = 0;
|
||||||
|
const Variant::ValidatedConstructor *_constructors_ptr = nullptr;
|
||||||
int _methods_count = 0;
|
int _methods_count = 0;
|
||||||
MethodBind **_methods_ptr = nullptr;
|
MethodBind **_methods_ptr = nullptr;
|
||||||
const int *_code_ptr = nullptr;
|
const int *_code_ptr = nullptr;
|
||||||
|
@ -368,6 +371,7 @@ private:
|
||||||
Vector<Variant::ValidatedIndexedSetter> indexed_setters;
|
Vector<Variant::ValidatedIndexedSetter> indexed_setters;
|
||||||
Vector<Variant::ValidatedIndexedGetter> indexed_getters;
|
Vector<Variant::ValidatedIndexedGetter> indexed_getters;
|
||||||
Vector<Variant::ValidatedBuiltInMethod> builtin_methods;
|
Vector<Variant::ValidatedBuiltInMethod> builtin_methods;
|
||||||
|
Vector<Variant::ValidatedConstructor> constructors;
|
||||||
Vector<MethodBind *> methods;
|
Vector<MethodBind *> methods;
|
||||||
Vector<int> code;
|
Vector<int> code;
|
||||||
Vector<GDScriptDataType> argument_types;
|
Vector<GDScriptDataType> argument_types;
|
||||||
|
|
|
@ -214,6 +214,7 @@ String GDScriptFunction::_get_call_error(const Callable::CallError &p_err, const
|
||||||
&&OPCODE_CAST_TO_NATIVE, \
|
&&OPCODE_CAST_TO_NATIVE, \
|
||||||
&&OPCODE_CAST_TO_SCRIPT, \
|
&&OPCODE_CAST_TO_SCRIPT, \
|
||||||
&&OPCODE_CONSTRUCT, \
|
&&OPCODE_CONSTRUCT, \
|
||||||
|
&&OPCODE_CONSTRUCT_VALIDATED, \
|
||||||
&&OPCODE_CONSTRUCT_ARRAY, \
|
&&OPCODE_CONSTRUCT_ARRAY, \
|
||||||
&&OPCODE_CONSTRUCT_DICTIONARY, \
|
&&OPCODE_CONSTRUCT_DICTIONARY, \
|
||||||
&&OPCODE_CALL, \
|
&&OPCODE_CALL, \
|
||||||
|
@ -1276,6 +1277,27 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
|
||||||
}
|
}
|
||||||
DISPATCH_OPCODE;
|
DISPATCH_OPCODE;
|
||||||
|
|
||||||
|
OPCODE(OPCODE_CONSTRUCT_VALIDATED) {
|
||||||
|
CHECK_SPACE(2 + instr_arg_count);
|
||||||
|
|
||||||
|
ip += instr_arg_count;
|
||||||
|
|
||||||
|
int argc = _code_ptr[ip + 1];
|
||||||
|
|
||||||
|
int constructor_idx = _code_ptr[ip + 2];
|
||||||
|
GD_ERR_BREAK(constructor_idx < 0 || constructor_idx >= _constructors_count);
|
||||||
|
Variant::ValidatedConstructor constructor = _constructors_ptr[constructor_idx];
|
||||||
|
|
||||||
|
Variant **argptrs = instruction_args;
|
||||||
|
|
||||||
|
GET_INSTRUCTION_ARG(dst, argc);
|
||||||
|
|
||||||
|
constructor(*dst, (const Variant **)argptrs);
|
||||||
|
|
||||||
|
ip += 3;
|
||||||
|
}
|
||||||
|
DISPATCH_OPCODE;
|
||||||
|
|
||||||
OPCODE(OPCODE_CONSTRUCT_ARRAY) {
|
OPCODE(OPCODE_CONSTRUCT_ARRAY) {
|
||||||
CHECK_SPACE(1 + instr_arg_count);
|
CHECK_SPACE(1 + instr_arg_count);
|
||||||
ip += instr_arg_count;
|
ip += instr_arg_count;
|
||||||
|
|
Loading…
Reference in New Issue