Don't box params on Native->C# calls with Variant params

Godot uses Variant parameters for calls to script methods.
Up until now we were boxing such parameters when marshalling
them for invokation, even if they were value types.

Now Godot allocates the marshalled parameters on the stack,
reducing the GC allocations resulted from boxing.
This commit is contained in:
Ignacio Etcheverry 2020-12-05 00:19:15 +01:00
parent 04bef80b42
commit a946f84e3d
11 changed files with 757 additions and 683 deletions

View File

@ -290,7 +290,7 @@ bool GDMonoClass::has_public_parameterless_ctor() {
return ctor && ctor->get_visibility() == IMonoClassMember::PUBLIC;
}
GDMonoMethod *GDMonoClass::get_method(const StringName &p_name, int p_params_count) {
GDMonoMethod *GDMonoClass::get_method(const StringName &p_name, uint16_t p_params_count) {
MethodKey key = MethodKey(p_name, p_params_count);
GDMonoMethod **match = methods.getptr(key);
@ -330,7 +330,7 @@ GDMonoMethod *GDMonoClass::get_method(MonoMethod *p_raw_method, const StringName
return get_method(p_raw_method, p_name, params_count);
}
GDMonoMethod *GDMonoClass::get_method(MonoMethod *p_raw_method, const StringName &p_name, int p_params_count) {
GDMonoMethod *GDMonoClass::get_method(MonoMethod *p_raw_method, const StringName &p_name, uint16_t p_params_count) {
ERR_FAIL_NULL_V(p_raw_method, nullptr);
MethodKey key = MethodKey(p_name, p_params_count);

View File

@ -59,13 +59,12 @@ class GDMonoClass {
MethodKey() {}
MethodKey(const StringName &p_name, int p_params_count) {
name = p_name;
params_count = p_params_count;
MethodKey(const StringName &p_name, uint16_t p_params_count) :
name(p_name), params_count(p_params_count) {
}
StringName name;
int params_count;
uint16_t params_count = 0;
};
StringName namespace_name;
@ -139,10 +138,10 @@ public:
bool implements_interface(GDMonoClass *p_interface);
bool has_public_parameterless_ctor();
GDMonoMethod *get_method(const StringName &p_name, int p_params_count = 0);
GDMonoMethod *get_method(const StringName &p_name, uint16_t p_params_count = 0);
GDMonoMethod *get_method(MonoMethod *p_raw_method);
GDMonoMethod *get_method(MonoMethod *p_raw_method, const StringName &p_name);
GDMonoMethod *get_method(MonoMethod *p_raw_method, const StringName &p_name, int p_params_count);
GDMonoMethod *get_method(MonoMethod *p_raw_method, const StringName &p_name, uint16_t p_params_count);
GDMonoMethod *get_method_with_desc(const String &p_description, bool p_include_namespace);
GDMonoField *get_field(const StringName &p_name);

View File

@ -46,29 +46,15 @@ void GDMonoField::set_value_raw(MonoObject *p_object, void *p_ptr) {
}
void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_value) {
#define SET_FROM_STRUCT(m_type) \
{ \
GDMonoMarshal::M_##m_type from = MARSHALLED_OUT(m_type, p_value.operator ::m_type()); \
mono_field_set_value(p_object, mono_field, &from); \
}
#define SET_FROM_ARRAY(m_type) \
{ \
MonoArray *managed = GDMonoMarshal::m_type##_to_mono_array(p_value.operator ::m_type()); \
mono_field_set_value(p_object, mono_field, managed); \
}
switch (type.type_encoding) {
case MONO_TYPE_BOOLEAN: {
MonoBoolean val = p_value.operator bool();
mono_field_set_value(p_object, mono_field, &val);
} break;
case MONO_TYPE_CHAR: {
int16_t val = p_value.operator unsigned short();
mono_field_set_value(p_object, mono_field, &val);
} break;
case MONO_TYPE_I1: {
int8_t val = p_value.operator signed char();
mono_field_set_value(p_object, mono_field, &val);
@ -85,7 +71,6 @@ void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_
int64_t val = p_value.operator int64_t();
mono_field_set_value(p_object, mono_field, &val);
} break;
case MONO_TYPE_U1: {
uint8_t val = p_value.operator unsigned char();
mono_field_set_value(p_object, mono_field, &val);
@ -102,93 +87,92 @@ void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_
uint64_t val = p_value.operator uint64_t();
mono_field_set_value(p_object, mono_field, &val);
} break;
case MONO_TYPE_R4: {
float val = p_value.operator float();
mono_field_set_value(p_object, mono_field, &val);
} break;
case MONO_TYPE_R8: {
double val = p_value.operator double();
mono_field_set_value(p_object, mono_field, &val);
} break;
case MONO_TYPE_STRING: {
if (p_value.get_type() == Variant::NIL) {
// Otherwise, Variant -> String would return the string "Null"
MonoString *mono_string = nullptr;
mono_field_set_value(p_object, mono_field, mono_string);
} else {
MonoString *mono_string = GDMonoMarshal::mono_string_from_godot(p_value);
mono_field_set_value(p_object, mono_field, mono_string);
}
} break;
case MONO_TYPE_VALUETYPE: {
GDMonoClass *tclass = type.type_class;
if (tclass == CACHED_CLASS(Vector2)) {
SET_FROM_STRUCT(Vector2);
GDMonoMarshal::M_Vector2 from = MARSHALLED_OUT(Vector2, p_value.operator ::Vector2());
mono_field_set_value(p_object, mono_field, &from);
break;
}
if (tclass == CACHED_CLASS(Vector2i)) {
SET_FROM_STRUCT(Vector2i);
GDMonoMarshal::M_Vector2i from = MARSHALLED_OUT(Vector2i, p_value.operator ::Vector2i());
mono_field_set_value(p_object, mono_field, &from);
break;
}
if (tclass == CACHED_CLASS(Rect2)) {
SET_FROM_STRUCT(Rect2);
GDMonoMarshal::M_Rect2 from = MARSHALLED_OUT(Rect2, p_value.operator ::Rect2());
mono_field_set_value(p_object, mono_field, &from);
break;
}
if (tclass == CACHED_CLASS(Rect2i)) {
SET_FROM_STRUCT(Rect2i);
GDMonoMarshal::M_Rect2i from = MARSHALLED_OUT(Rect2i, p_value.operator ::Rect2i());
mono_field_set_value(p_object, mono_field, &from);
break;
}
if (tclass == CACHED_CLASS(Transform2D)) {
SET_FROM_STRUCT(Transform2D);
GDMonoMarshal::M_Transform2D from = MARSHALLED_OUT(Transform2D, p_value.operator ::Transform2D());
mono_field_set_value(p_object, mono_field, &from);
break;
}
if (tclass == CACHED_CLASS(Vector3)) {
SET_FROM_STRUCT(Vector3);
GDMonoMarshal::M_Vector3 from = MARSHALLED_OUT(Vector3, p_value.operator ::Vector3());
mono_field_set_value(p_object, mono_field, &from);
break;
}
if (tclass == CACHED_CLASS(Vector3i)) {
SET_FROM_STRUCT(Vector3i);
GDMonoMarshal::M_Vector3i from = MARSHALLED_OUT(Vector3i, p_value.operator ::Vector3i());
mono_field_set_value(p_object, mono_field, &from);
break;
}
if (tclass == CACHED_CLASS(Basis)) {
SET_FROM_STRUCT(Basis);
GDMonoMarshal::M_Basis from = MARSHALLED_OUT(Basis, p_value.operator ::Basis());
mono_field_set_value(p_object, mono_field, &from);
break;
}
if (tclass == CACHED_CLASS(Quat)) {
SET_FROM_STRUCT(Quat);
GDMonoMarshal::M_Quat from = MARSHALLED_OUT(Quat, p_value.operator ::Quat());
mono_field_set_value(p_object, mono_field, &from);
break;
}
if (tclass == CACHED_CLASS(Transform)) {
SET_FROM_STRUCT(Transform);
GDMonoMarshal::M_Transform from = MARSHALLED_OUT(Transform, p_value.operator ::Transform());
mono_field_set_value(p_object, mono_field, &from);
break;
}
if (tclass == CACHED_CLASS(AABB)) {
SET_FROM_STRUCT(AABB);
GDMonoMarshal::M_AABB from = MARSHALLED_OUT(AABB, p_value.operator ::AABB());
mono_field_set_value(p_object, mono_field, &from);
break;
}
if (tclass == CACHED_CLASS(Color)) {
SET_FROM_STRUCT(Color);
GDMonoMarshal::M_Color from = MARSHALLED_OUT(Color, p_value.operator ::Color());
mono_field_set_value(p_object, mono_field, &from);
break;
}
if (tclass == CACHED_CLASS(Plane)) {
SET_FROM_STRUCT(Plane);
GDMonoMarshal::M_Plane from = MARSHALLED_OUT(Plane, p_value.operator ::Plane());
mono_field_set_value(p_object, mono_field, &from);
break;
}
@ -267,118 +251,35 @@ void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_
ERR_FAIL_MSG("Attempted to set the value of a field of unmarshallable type: '" + tclass->get_name() + "'.");
} break;
case MONO_TYPE_STRING: {
if (p_value.get_type() == Variant::NIL) {
// Otherwise, Variant -> String would return the string "Null"
MonoString *mono_string = nullptr;
mono_field_set_value(p_object, mono_field, mono_string);
} else {
MonoString *mono_string = GDMonoMarshal::mono_string_from_godot(p_value);
mono_field_set_value(p_object, mono_field, mono_string);
}
} break;
case MONO_TYPE_ARRAY:
case MONO_TYPE_SZARRAY: {
MonoArrayType *array_type = mono_type_get_array_type(type.type_class->get_mono_type());
if (array_type->eklass == CACHED_CLASS_RAW(MonoObject)) {
SET_FROM_ARRAY(Array);
break;
}
if (array_type->eklass == CACHED_CLASS_RAW(uint8_t)) {
SET_FROM_ARRAY(PackedByteArray);
break;
}
if (array_type->eklass == CACHED_CLASS_RAW(int32_t)) {
SET_FROM_ARRAY(PackedInt32Array);
break;
}
if (array_type->eklass == CACHED_CLASS_RAW(int64_t)) {
SET_FROM_ARRAY(PackedInt64Array);
break;
}
if (array_type->eklass == CACHED_CLASS_RAW(float)) {
SET_FROM_ARRAY(PackedFloat32Array);
break;
}
if (array_type->eklass == CACHED_CLASS_RAW(double)) {
SET_FROM_ARRAY(PackedFloat64Array);
break;
}
if (array_type->eklass == CACHED_CLASS_RAW(String)) {
SET_FROM_ARRAY(PackedStringArray);
break;
}
if (array_type->eklass == CACHED_CLASS_RAW(Vector2)) {
SET_FROM_ARRAY(PackedVector2Array);
break;
}
if (array_type->eklass == CACHED_CLASS_RAW(Vector3)) {
SET_FROM_ARRAY(PackedVector3Array);
break;
}
if (array_type->eklass == CACHED_CLASS_RAW(Color)) {
SET_FROM_ARRAY(PackedColorArray);
break;
}
GDMonoClass *array_type_class = GDMono::get_singleton()->get_class(array_type->eklass);
if (CACHED_CLASS(GodotObject)->is_assignable_from(array_type_class)) {
MonoArray *managed = GDMonoMarshal::Array_to_mono_array(p_value.operator ::Array(), array_type_class);
MonoArray *managed = GDMonoMarshal::variant_to_mono_array(p_value, type.type_class);
if (likely(managed != nullptr)) {
mono_field_set_value(p_object, mono_field, managed);
break;
}
ERR_FAIL_MSG("Attempted to convert Variant to a managed array of unmarshallable element type.");
} break;
case MONO_TYPE_CLASS: {
GDMonoClass *type_class = type.type_class;
// GodotObject
if (CACHED_CLASS(GodotObject)->is_assignable_from(type_class)) {
MonoObject *managed = GDMonoUtils::unmanaged_get_managed(p_value.operator Object *());
MonoObject *managed = GDMonoMarshal::variant_to_mono_object_of_class(p_value, type.type_class);
if (likely(managed != nullptr)) {
mono_field_set_value(p_object, mono_field, managed);
}
} break;
case MONO_TYPE_GENERICINST: {
MonoObject *managed = GDMonoMarshal::variant_to_mono_object_of_genericinst(p_value, type.type_class);
if (likely(managed != nullptr)) {
mono_field_set_value(p_object, mono_field, managed);
break;
}
if (CACHED_CLASS(StringName) == type_class) {
MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator StringName());
mono_field_set_value(p_object, mono_field, managed);
break;
}
if (CACHED_CLASS(NodePath) == type_class) {
MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator NodePath());
mono_field_set_value(p_object, mono_field, managed);
break;
}
if (CACHED_CLASS(RID) == type_class) {
MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator ::RID());
mono_field_set_value(p_object, mono_field, managed);
break;
}
// Godot.Collections.Dictionary or IDictionary
if (CACHED_CLASS(Dictionary) == type_class || type_class == CACHED_CLASS(System_Collections_IDictionary)) {
MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator Dictionary(), CACHED_CLASS(Dictionary));
mono_field_set_value(p_object, mono_field, managed);
break;
}
// Godot.Collections.Array or ICollection or IEnumerable
if (CACHED_CLASS(Array) == type_class ||
type_class == CACHED_CLASS(System_Collections_ICollection) ||
type_class == CACHED_CLASS(System_Collections_IEnumerable)) {
MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator Array(), CACHED_CLASS(Array));
mono_field_set_value(p_object, mono_field, managed);
break;
}
ERR_FAIL_MSG("Attempted to set the value of a field of unmarshallable type: '" + type_class->get_name() + "'.");
} break;
case MONO_TYPE_OBJECT: {
// Variant
switch (p_value.get_type()) {
@ -404,43 +305,56 @@ void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_
mono_field_set_value(p_object, mono_field, mono_string);
} break;
case Variant::VECTOR2: {
SET_FROM_STRUCT(Vector2);
GDMonoMarshal::M_Vector2 from = MARSHALLED_OUT(Vector2, p_value.operator ::Vector2());
mono_field_set_value(p_object, mono_field, &from);
} break;
case Variant::VECTOR2I: {
SET_FROM_STRUCT(Vector2i);
GDMonoMarshal::M_Vector2i from = MARSHALLED_OUT(Vector2i, p_value.operator ::Vector2i());
mono_field_set_value(p_object, mono_field, &from);
} break;
case Variant::RECT2: {
SET_FROM_STRUCT(Rect2);
GDMonoMarshal::M_Rect2 from = MARSHALLED_OUT(Rect2, p_value.operator ::Rect2());
mono_field_set_value(p_object, mono_field, &from);
} break;
case Variant::RECT2I: {
SET_FROM_STRUCT(Rect2i);
GDMonoMarshal::M_Rect2i from = MARSHALLED_OUT(Rect2i, p_value.operator ::Rect2i());
mono_field_set_value(p_object, mono_field, &from);
} break;
case Variant::VECTOR3: {
SET_FROM_STRUCT(Vector3);
GDMonoMarshal::M_Vector3 from = MARSHALLED_OUT(Vector3, p_value.operator ::Vector3());
mono_field_set_value(p_object, mono_field, &from);
} break;
case Variant::VECTOR3I: {
SET_FROM_STRUCT(Vector3i);
GDMonoMarshal::M_Vector3i from = MARSHALLED_OUT(Vector3i, p_value.operator ::Vector3i());
mono_field_set_value(p_object, mono_field, &from);
} break;
case Variant::TRANSFORM2D: {
SET_FROM_STRUCT(Transform2D);
GDMonoMarshal::M_Transform2D from = MARSHALLED_OUT(Transform2D, p_value.operator ::Transform2D());
mono_field_set_value(p_object, mono_field, &from);
} break;
case Variant::PLANE: {
SET_FROM_STRUCT(Plane);
GDMonoMarshal::M_Plane from = MARSHALLED_OUT(Plane, p_value.operator ::Plane());
mono_field_set_value(p_object, mono_field, &from);
} break;
case Variant::QUAT: {
SET_FROM_STRUCT(Quat);
GDMonoMarshal::M_Quat from = MARSHALLED_OUT(Quat, p_value.operator ::Quat());
mono_field_set_value(p_object, mono_field, &from);
} break;
case Variant::AABB: {
SET_FROM_STRUCT(AABB);
GDMonoMarshal::M_AABB from = MARSHALLED_OUT(AABB, p_value.operator ::AABB());
mono_field_set_value(p_object, mono_field, &from);
} break;
case Variant::BASIS: {
SET_FROM_STRUCT(Basis);
GDMonoMarshal::M_Basis from = MARSHALLED_OUT(Basis, p_value.operator ::Basis());
mono_field_set_value(p_object, mono_field, &from);
} break;
case Variant::TRANSFORM: {
SET_FROM_STRUCT(Transform);
GDMonoMarshal::M_Transform from = MARSHALLED_OUT(Transform, p_value.operator ::Transform());
mono_field_set_value(p_object, mono_field, &from);
} break;
case Variant::COLOR: {
SET_FROM_STRUCT(Color);
GDMonoMarshal::M_Color from = MARSHALLED_OUT(Color, p_value.operator ::Color());
mono_field_set_value(p_object, mono_field, &from);
} break;
case Variant::STRING_NAME: {
MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator StringName());
@ -475,106 +389,49 @@ void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_
mono_field_set_value(p_object, mono_field, managed);
} break;
case Variant::PACKED_BYTE_ARRAY: {
SET_FROM_ARRAY(PackedByteArray);
MonoArray *managed = GDMonoMarshal::PackedByteArray_to_mono_array(p_value.operator ::PackedByteArray());
mono_field_set_value(p_object, mono_field, managed);
} break;
case Variant::PACKED_INT32_ARRAY: {
SET_FROM_ARRAY(PackedInt32Array);
MonoArray *managed = GDMonoMarshal::PackedInt32Array_to_mono_array(p_value.operator ::PackedInt32Array());
mono_field_set_value(p_object, mono_field, managed);
} break;
case Variant::PACKED_INT64_ARRAY: {
SET_FROM_ARRAY(PackedInt64Array);
MonoArray *managed = GDMonoMarshal::PackedInt64Array_to_mono_array(p_value.operator ::PackedInt64Array());
mono_field_set_value(p_object, mono_field, managed);
} break;
case Variant::PACKED_FLOAT32_ARRAY: {
SET_FROM_ARRAY(PackedFloat32Array);
MonoArray *managed = GDMonoMarshal::PackedFloat32Array_to_mono_array(p_value.operator ::PackedFloat32Array());
mono_field_set_value(p_object, mono_field, managed);
} break;
case Variant::PACKED_FLOAT64_ARRAY: {
SET_FROM_ARRAY(PackedFloat64Array);
MonoArray *managed = GDMonoMarshal::PackedFloat64Array_to_mono_array(p_value.operator ::PackedFloat64Array());
mono_field_set_value(p_object, mono_field, managed);
} break;
case Variant::PACKED_STRING_ARRAY: {
SET_FROM_ARRAY(PackedStringArray);
MonoArray *managed = GDMonoMarshal::PackedStringArray_to_mono_array(p_value.operator ::PackedStringArray());
mono_field_set_value(p_object, mono_field, managed);
} break;
case Variant::PACKED_VECTOR2_ARRAY: {
SET_FROM_ARRAY(PackedVector2Array);
MonoArray *managed = GDMonoMarshal::PackedVector2Array_to_mono_array(p_value.operator ::PackedVector2Array());
mono_field_set_value(p_object, mono_field, managed);
} break;
case Variant::PACKED_VECTOR3_ARRAY: {
SET_FROM_ARRAY(PackedVector3Array);
MonoArray *managed = GDMonoMarshal::PackedVector3Array_to_mono_array(p_value.operator ::PackedVector3Array());
mono_field_set_value(p_object, mono_field, managed);
} break;
case Variant::PACKED_COLOR_ARRAY: {
SET_FROM_ARRAY(PackedColorArray);
MonoArray *managed = GDMonoMarshal::PackedColorArray_to_mono_array(p_value.operator ::PackedColorArray());
mono_field_set_value(p_object, mono_field, managed);
} break;
default:
break;
}
} break;
case MONO_TYPE_GENERICINST: {
MonoReflectionType *reftype = mono_type_get_object(mono_domain_get(), type.type_class->get_mono_type());
// Godot.Collections.Dictionary<TKey, TValue>
if (GDMonoUtils::Marshal::type_is_generic_dictionary(reftype)) {
MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator Dictionary(), type.type_class);
mono_field_set_value(p_object, mono_field, managed);
break;
}
// Godot.Collections.Array<T>
if (GDMonoUtils::Marshal::type_is_generic_array(reftype)) {
MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator Array(), type.type_class);
mono_field_set_value(p_object, mono_field, managed);
break;
}
// System.Collections.Generic.Dictionary<TKey, TValue>
if (GDMonoUtils::Marshal::type_is_system_generic_dictionary(reftype)) {
MonoReflectionType *key_reftype = nullptr;
MonoReflectionType *value_reftype = nullptr;
GDMonoUtils::Marshal::dictionary_get_key_value_types(reftype, &key_reftype, &value_reftype);
MonoObject *managed = GDMonoMarshal::Dictionary_to_system_generic_dict(p_value.operator Dictionary(),
type.type_class, key_reftype, value_reftype);
mono_field_set_value(p_object, mono_field, managed);
break;
}
// System.Collections.Generic.List<T>
if (GDMonoUtils::Marshal::type_is_system_generic_list(reftype)) {
MonoReflectionType *elem_reftype = nullptr;
GDMonoUtils::Marshal::array_get_element_type(reftype, &elem_reftype);
MonoObject *managed = GDMonoMarshal::Array_to_system_generic_list(p_value.operator Array(),
type.type_class, elem_reftype);
mono_field_set_value(p_object, mono_field, managed);
break;
}
// IDictionary<TKey, TValue>
if (GDMonoUtils::Marshal::type_is_generic_idictionary(reftype)) {
MonoReflectionType *key_reftype;
MonoReflectionType *value_reftype;
GDMonoUtils::Marshal::dictionary_get_key_value_types(reftype, &key_reftype, &value_reftype);
GDMonoClass *godot_dict_class = GDMonoUtils::Marshal::make_generic_dictionary_type(key_reftype, value_reftype);
MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator Dictionary(), godot_dict_class);
mono_field_set_value(p_object, mono_field, managed);
break;
}
// ICollection<T> or IEnumerable<T>
if (GDMonoUtils::Marshal::type_is_generic_icollection(reftype) || GDMonoUtils::Marshal::type_is_generic_ienumerable(reftype)) {
MonoReflectionType *elem_reftype;
GDMonoUtils::Marshal::array_get_element_type(reftype, &elem_reftype);
GDMonoClass *godot_array_class = GDMonoUtils::Marshal::make_generic_array_type(elem_reftype);
MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator Array(), godot_array_class);
mono_field_set_value(p_object, mono_field, managed);
break;
}
} break;
default: {
ERR_PRINT("Attempted to set the value of a field of unexpected type encoding: " + itos(type.type_encoding) + ".");
} break;
}
#undef SET_FROM_ARRAY_AND_BREAK
#undef SET_FROM_STRUCT_AND_BREAK
}
MonoObject *GDMonoField::get_value(MonoObject *p_object) {

File diff suppressed because it is too large Load Diff

View File

@ -90,15 +90,40 @@ _FORCE_INLINE_ MonoString *mono_string_from_godot(const String &p_string) {
// Variant
MonoObject *variant_to_mono_object(const Variant *p_var, const ManagedType &p_type);
MonoObject *variant_to_mono_object(const Variant *p_var);
size_t variant_get_managed_unboxed_size(const ManagedType &p_type);
void *variant_to_managed_unboxed(const Variant &p_var, const ManagedType &p_type, void *r_buffer, unsigned int &r_offset);
MonoObject *variant_to_mono_object(const Variant &p_var, const ManagedType &p_type);
_FORCE_INLINE_ MonoObject *variant_to_mono_object(const Variant &p_var) {
return variant_to_mono_object(&p_var);
MonoObject *variant_to_mono_object(const Variant &p_var);
MonoArray *variant_to_mono_array(const Variant &p_var, GDMonoClass *p_type_class);
MonoObject *variant_to_mono_object_of_class(const Variant &p_var, GDMonoClass *p_type_class);
MonoObject *variant_to_mono_object_of_genericinst(const Variant &p_var, GDMonoClass *p_type_class);
MonoString *variant_to_mono_string(const Variant &p_var);
// These overloads were added to avoid passing a `const Variant *` to the `const Variant &`
// parameter. That would result in the `Variant(bool)` copy constructor being called as
// pointers are implicitly converted to bool. Implicit conversions are f-ing evil.
_FORCE_INLINE_ void *variant_to_managed_unboxed(const Variant *p_var, const ManagedType &p_type, void *r_buffer, unsigned int &r_offset) {
return variant_to_managed_unboxed(*p_var, p_type, r_buffer, r_offset);
}
_FORCE_INLINE_ MonoObject *variant_to_mono_object(const Variant &p_var, const ManagedType &p_type) {
return variant_to_mono_object(&p_var, p_type);
_FORCE_INLINE_ MonoObject *variant_to_mono_object(const Variant *p_var, const ManagedType &p_type) {
return variant_to_mono_object(*p_var, p_type);
}
_FORCE_INLINE_ MonoObject *variant_to_mono_object(const Variant *p_var) {
return variant_to_mono_object(*p_var);
}
_FORCE_INLINE_ MonoArray *variant_to_mono_array(const Variant *p_var, GDMonoClass *p_type_class) {
return variant_to_mono_array(*p_var, p_type_class);
}
_FORCE_INLINE_ MonoObject *variant_to_mono_object_of_class(const Variant *p_var, GDMonoClass *p_type_class) {
return variant_to_mono_object_of_class(*p_var, p_type_class);
}
_FORCE_INLINE_ MonoObject *variant_to_mono_object_of_genericinst(const Variant *p_var, GDMonoClass *p_type_class) {
return variant_to_mono_object_of_genericinst(*p_var, p_type_class);
}
_FORCE_INLINE_ MonoString *variant_to_mono_string(const Variant *p_var) {
return variant_to_mono_string(*p_var);
}
Variant mono_object_to_variant(MonoObject *p_obj);
@ -120,7 +145,7 @@ Array system_generic_list_to_Array(MonoObject *p_obj, GDMonoClass *p_class, Mono
// Array
MonoArray *Array_to_mono_array(const Array &p_array);
MonoArray *Array_to_mono_array(const Array &p_array, GDMonoClass *p_array_type_class);
MonoArray *Array_to_mono_array(const Array &p_array, MonoClass *p_array_type_class);
Array mono_array_to_Array(MonoArray *p_array);
// PackedInt32Array

View File

@ -75,6 +75,10 @@ void GDMonoMethod::_update_signature(MonoMethodSignature *p_method_sig) {
// clear the cache
method_info_fetched = false;
method_info = MethodInfo();
for (int i = 0; i < params_count; i++) {
params_buffer_size += GDMonoMarshal::variant_get_managed_unboxed_size(param_types[i]);
}
}
GDMonoClass *GDMonoMethod::get_enclosing_class() const {
@ -107,14 +111,15 @@ MonoObject *GDMonoMethod::invoke(MonoObject *p_object, const Variant **p_params,
MonoObject *ret;
if (params_count > 0) {
MonoArray *params = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(MonoObject), params_count);
void **params = (void **)alloca(params_count * sizeof(void *));
uint8_t *buffer = (uint8_t *)alloca(params_buffer_size);
unsigned int offset = 0;
for (int i = 0; i < params_count; i++) {
MonoObject *boxed_param = GDMonoMarshal::variant_to_mono_object(p_params[i], param_types[i]);
mono_array_setref(params, i, boxed_param);
params[i] = GDMonoMarshal::variant_to_managed_unboxed(p_params[i], param_types[i], buffer + offset, offset);
}
ret = GDMonoUtils::runtime_invoke_array(mono_method, p_object, params, &exc);
ret = GDMonoUtils::runtime_invoke(mono_method, p_object, params, &exc);
} else {
ret = GDMonoUtils::runtime_invoke(mono_method, p_object, nullptr, &exc);
}
@ -279,16 +284,8 @@ const MethodInfo &GDMonoMethod::get_method_info() {
return method_info;
}
GDMonoMethod::GDMonoMethod(StringName p_name, MonoMethod *p_method) {
name = p_name;
mono_method = p_method;
method_info_fetched = false;
attrs_fetched = false;
attributes = nullptr;
GDMonoMethod::GDMonoMethod(StringName p_name, MonoMethod *p_method) :
name(p_name), mono_method(p_method) {
_update_signature();
}

View File

@ -38,15 +38,16 @@
class GDMonoMethod : public IMonoClassMember {
StringName name;
int params_count;
uint16_t params_count;
unsigned int params_buffer_size = 0;
ManagedType return_type;
Vector<ManagedType> param_types;
bool method_info_fetched;
bool method_info_fetched = false;
MethodInfo method_info;
bool attrs_fetched;
MonoCustomAttrInfo *attributes;
bool attrs_fetched = false;
MonoCustomAttrInfo *attributes = nullptr;
void _update_signature();
void _update_signature(MonoMethodSignature *p_method_sig);
@ -72,7 +73,7 @@ public:
_FORCE_INLINE_ MonoMethod *get_mono_ptr() const { return mono_method; }
_FORCE_INLINE_ int get_parameters_count() const { return params_count; }
_FORCE_INLINE_ uint16_t get_parameters_count() const { return params_count; }
_FORCE_INLINE_ ManagedType get_return_type() const { return return_type; }
MonoObject *invoke(MonoObject *p_object, const Variant **p_params, MonoException **r_exc = nullptr) const;

View File

@ -149,10 +149,9 @@ bool GDMonoProperty::has_setter() {
void GDMonoProperty::set_value(MonoObject *p_object, MonoObject *p_value, MonoException **r_exc) {
MonoMethod *prop_method = mono_property_get_set_method(mono_property);
MonoArray *params = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(MonoObject), 1);
mono_array_setref(params, 0, p_value);
void *params[1] = { p_value };
MonoException *exc = nullptr;
GDMonoUtils::runtime_invoke_array(prop_method, p_object, params, &exc);
GDMonoUtils::runtime_invoke(prop_method, p_object, params, &exc);
if (exc) {
if (r_exc) {
*r_exc = exc;

View File

@ -498,13 +498,6 @@ MonoObject *runtime_invoke(MonoMethod *p_method, void *p_obj, void **p_params, M
return ret;
}
MonoObject *runtime_invoke_array(MonoMethod *p_method, void *p_obj, MonoArray *p_params, MonoException **r_exc) {
GD_MONO_BEGIN_RUNTIME_INVOKE;
MonoObject *ret = mono_runtime_invoke_array(p_method, p_obj, p_params, (MonoObject **)r_exc);
GD_MONO_END_RUNTIME_INVOKE;
return ret;
}
MonoString *object_to_string(MonoObject *p_obj, MonoException **r_exc) {
GD_MONO_BEGIN_RUNTIME_INVOKE;
MonoString *ret = mono_object_to_string(p_obj, (MonoObject **)r_exc);

View File

@ -135,7 +135,6 @@ _FORCE_INLINE_ int &get_runtime_invoke_count_ref() {
}
MonoObject *runtime_invoke(MonoMethod *p_method, void *p_obj, void **p_params, MonoException **r_exc);
MonoObject *runtime_invoke_array(MonoMethod *p_method, void *p_obj, MonoArray *p_params, MonoException **r_exc);
MonoString *object_to_string(MonoObject *p_obj, MonoException **r_exc);

View File

@ -109,11 +109,15 @@ void SignalAwaiterCallable::call(const Variant **p_arguments, int p_argcount, Va
"Resumed after await, but class instance is gone.");
#endif
MonoArray *signal_args = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(MonoObject), p_argcount);
MonoArray *signal_args = nullptr;
for (int i = 0; i < p_argcount; i++) {
MonoObject *boxed = GDMonoMarshal::variant_to_mono_object(*p_arguments[i]);
mono_array_setref(signal_args, i, boxed);
if (p_argcount > 0) {
signal_args = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(MonoObject), p_argcount);
for (int i = 0; i < p_argcount; i++) {
MonoObject *boxed = GDMonoMarshal::variant_to_mono_object(*p_arguments[i]);
mono_array_setref(signal_args, i, boxed);
}
}
MonoObject *awaiter = awaiter_handle.get_target();