Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,9 @@ public static JSTypeInfo CreateJSTypeInfoForTypeSymbol(ITypeSymbol type)
}
return new JSFunctionTypeInfo(false, signatureTypes);
default:
// JS Interop generator does not support the marshalling of structs
// In case structs were to be allowed for marshalling in the future,
// disallow marshalling of structs with the InlineArrayAttribute
return new JSInvalidTypeInfo();
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/mono/mono/metadata/assembly.c
Original file line number Diff line number Diff line change
Expand Up @@ -1785,7 +1785,7 @@ struct HasReferenceAssemblyAttributeIterData {
};

static gboolean
has_reference_assembly_attribute_iterator (MonoImage *image, guint32 typeref_scope_token, const char *nspace, const char *name, guint32 method_token, gpointer user_data)
has_reference_assembly_attribute_iterator (MonoImage *image, guint32 typeref_scope_token, const char *nspace, const char *name, guint32 method_token, guint32 *cols, gpointer user_data)
{
gboolean stop_scanning = FALSE;
struct HasReferenceAssemblyAttributeIterData *iter_data = (struct HasReferenceAssemblyAttributeIterData*)user_data;
Expand Down
2 changes: 2 additions & 0 deletions src/mono/mono/metadata/class-getters.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ MONO_CLASS_GETTER(m_class_is_unicode, gboolean, , MonoClass, unicode)
MONO_CLASS_GETTER(m_class_was_typebuilder, gboolean, , MonoClass, wastypebuilder)
MONO_CLASS_GETTER(m_class_is_array_special_interface, gboolean, , MonoClass, is_array_special_interface)
MONO_CLASS_GETTER(m_class_is_byreflike, gboolean, , MonoClass, is_byreflike)
MONO_CLASS_GETTER(m_class_is_inlinearray, gboolean, , MonoClass, is_inlinearray)
MONO_CLASS_GETTER(m_class_inlinearray_value, gint32, , MonoClass, inlinearray_value)
MONO_CLASS_GETTER(m_class_get_min_align, guint8, , MonoClass, min_align)
MONO_CLASS_GETTER(m_class_get_packing_size, guint, , MonoClass, packing_size)
MONO_CLASS_GETTER(m_class_is_ghcimpl, gboolean, , MonoClass, ghcimpl)
Expand Down
145 changes: 106 additions & 39 deletions src/mono/mono/metadata/class-init.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,27 @@ static gint32 inflated_classes_size;
gint32 mono_inflated_methods_size;
static gint32 class_def_count, class_gtd_count, class_ginst_count, class_gparam_count, class_array_count, class_pointer_count;

typedef struct {
/* inputs */
const char *nspace;
const char *name;
gboolean in_corlib;
gboolean has_value;
MonoHasValueCallback has_value_callback;
/* output */
gboolean has_attr;
gpointer value;
} FoundAttrUD;

/* Low level lock which protects data structures in this module */
static mono_mutex_t classes_mutex;

static gboolean class_kind_may_contain_generic_instances (MonoTypeKind kind);
static void mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd);
static int generic_array_methods (MonoClass *klass);
static void setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos, GHashTable *cache);
static gboolean class_has_isbyreflike_attribute (MonoClass *klass);
static FoundAttrUD class_has_isbyreflike_attribute (MonoClass *klass);
static FoundAttrUD class_has_inlinearray_attribute (MonoClass *klass);

static
GENERATE_TRY_GET_CLASS_WITH_CACHE(icollection, "System.Collections.Generic", "ICollection`1");
Expand Down Expand Up @@ -291,6 +304,9 @@ mono_class_setup_fields (MonoClass *klass)
instance_size = MONO_ABI_SIZEOF (MonoObject);
}

if (m_class_is_inlinearray (klass) && m_class_inlinearray_value (klass) <= 0)
mono_class_set_type_load_failure (klass, "Inline array length property must be positive.");

/* Get the real size */
explicit_size = mono_metadata_packing_from_typedef (klass->image, klass->type_token, &packing_size, &real_size);
if (explicit_size)
Expand Down Expand Up @@ -359,6 +375,10 @@ mono_class_setup_fields (MonoClass *klass)
mono_class_set_type_load_failure (klass, "Generic class cannot have explicit layout.");
break;
}
if (m_class_is_inlinearray (klass)) {
mono_class_set_type_load_failure (klass, "Inline array struct must not have explicit layout.");
break;
}
}
if (mono_type_has_exceptions (field->type)) {
char *class_name = mono_type_get_full_name (klass);
Expand Down Expand Up @@ -699,9 +719,17 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError
mono_get_runtime_callbacks ()->init_class (klass);

// compute is_byreflike
if (m_class_is_valuetype (klass))
if (class_has_isbyreflike_attribute (klass))
if (m_class_is_valuetype (klass)) {
FoundAttrUD attr;
attr = class_has_isbyreflike_attribute (klass);
if (attr.has_attr)
klass->is_byreflike = 1;
attr = class_has_inlinearray_attribute (klass);
if (attr.has_attr) {
klass->is_inlinearray = 1;
klass->inlinearray_value = GPOINTER_TO_INT32 (attr.value);
}
}

mono_loader_unlock ();

Expand Down Expand Up @@ -746,65 +774,87 @@ mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
mono_loader_unlock ();
}

struct FoundAttrUD {
/* inputs */
const char *nspace;
const char *name;
gboolean in_corlib;
/* output */
gboolean has_attr;
};

static gboolean
has_wellknown_attribute_func (MonoImage *image, guint32 typeref_scope_token, const char *nspace, const char *name, guint32 method_token, gpointer user_data)
has_wellknown_attribute_func (MonoImage *image, guint32 typeref_scope_token, const char *nspace, const char *name, guint32 method_token, guint32 *cols, gpointer user_data)
{
struct FoundAttrUD *has_attr = (struct FoundAttrUD *)user_data;
if (!strcmp (name, has_attr->name) && !strcmp (nspace, has_attr->nspace)) {
has_attr->has_attr = TRUE;
return TRUE;
FoundAttrUD *attr = (FoundAttrUD *)user_data;
if (!strcmp (name, attr->name) && !strcmp (nspace, attr->nspace)) {
if (attr->has_value_callback != NULL) {
attr->has_value_callback (image, method_token, cols, user_data);
}
attr->has_attr = TRUE;
}
/* TODO: use typeref_scope_token to check that attribute comes from
* corlib if in_corlib is TRUE, without triggering an assembly load.
* If we're inside corlib, expect the scope to be
* MONO_RESOLUTION_SCOPE_MODULE I think, if we're outside it'll be an
* MONO_RESOLUTION_SCOPE_ASSEMBLYREF and we'll need to check the
* name.*/
return FALSE;
return attr->has_attr;
}

static gboolean
class_has_wellknown_attribute (MonoClass *klass, const char *nspace, const char *name, gboolean in_corlib)
static void
has_inline_array_attribute_value_func (MonoImage *image, uint32_t method_token, uint32_t *cols, gpointer user_data)
{
struct FoundAttrUD has_attr;
has_attr.nspace = nspace;
has_attr.name = name;
has_attr.in_corlib = in_corlib;
has_attr.has_attr = FALSE;
FoundAttrUD *attr = (FoundAttrUD *)user_data;
MonoError error;
MonoMethod *ctor = mono_get_method_checked (image, method_token, NULL, NULL, &error);
if (ctor) {
const char *data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
uint32_t data_size = mono_metadata_decode_value (data, &data);
MonoDecodeCustomAttr *decoded_attr = mono_reflection_create_custom_attr_data_args_noalloc (image, ctor, (guchar*)data, data_size, &error);
mono_error_assert_ok (&error);
g_assert (decoded_attr->named_args_num == 0 && decoded_attr->typed_args_num == 1);
attr->value = *(gpointer*)decoded_attr->typed_args [0]->value.primitive;
g_free (decoded_attr);
} else {
g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x due to: %s", image->name, method_token, mono_error_get_message (&error));
}
}

mono_class_metadata_foreach_custom_attr (klass, has_wellknown_attribute_func, &has_attr);
static FoundAttrUD
class_has_wellknown_attribute (MonoClass *klass, const char *nspace, const char *name, gboolean in_corlib, gboolean has_value, MonoHasValueCallback callback)
{
FoundAttrUD attr;
attr.nspace = nspace;
attr.name = name;
attr.in_corlib = in_corlib;
attr.has_attr = FALSE;
attr.has_value = has_value;
attr.has_value_callback = callback;

return has_attr.has_attr;
mono_class_metadata_foreach_custom_attr (klass, has_wellknown_attribute_func, &attr);

return attr;
}

static gboolean
method_has_wellknown_attribute (MonoMethod *method, const char *nspace, const char *name, gboolean in_corlib)
static FoundAttrUD
method_has_wellknown_attribute (MonoMethod *method, const char *nspace, const char *name, gboolean in_corlib, gboolean has_value, MonoHasValueCallback callback)
{
struct FoundAttrUD has_attr;
has_attr.nspace = nspace;
has_attr.name = name;
has_attr.in_corlib = in_corlib;
has_attr.has_attr = FALSE;
FoundAttrUD attr;
attr.nspace = nspace;
attr.name = name;
attr.in_corlib = in_corlib;
attr.has_attr = FALSE;
attr.has_value = has_value;
attr.has_value_callback = callback;

mono_method_metadata_foreach_custom_attr (method, has_wellknown_attribute_func, &has_attr);
mono_method_metadata_foreach_custom_attr (method, has_wellknown_attribute_func, &attr);

return has_attr.has_attr;
return attr;
}


static gboolean
static FoundAttrUD
class_has_isbyreflike_attribute (MonoClass *klass)
{
return class_has_wellknown_attribute (klass, "System.Runtime.CompilerServices", "IsByRefLikeAttribute", TRUE);
return class_has_wellknown_attribute (klass, "System.Runtime.CompilerServices", "IsByRefLikeAttribute", TRUE, FALSE, NULL);
}

static FoundAttrUD
class_has_inlinearray_attribute (MonoClass *klass)
{
return class_has_wellknown_attribute (klass, "System.Runtime.CompilerServices", "InlineArrayAttribute", TRUE, TRUE, has_inline_array_attribute_value_func);
}


Expand All @@ -815,7 +865,8 @@ mono_class_setup_method_has_preserve_base_overrides_attribute (MonoMethod *metho
/* FIXME: implement well known attribute check for dynamic images */
if (image_is_dynamic (image))
return FALSE;
return method_has_wellknown_attribute (method, "System.Runtime.CompilerServices", "PreserveBaseOverridesAttribute", TRUE);
FoundAttrUD attr = method_has_wellknown_attribute (method, "System.Runtime.CompilerServices", "PreserveBaseOverridesAttribute", TRUE, FALSE, NULL);
return attr.has_attr;
}

static gboolean
Expand Down Expand Up @@ -868,6 +919,8 @@ mono_class_create_generic_inst (MonoGenericClass *gclass)
klass->this_arg.type = m_class_get_byval_arg (klass)->type;
klass->this_arg.data.generic_class = klass->_byval_arg.data.generic_class = gclass;
klass->this_arg.byref__ = TRUE;
klass->is_inlinearray = gklass->is_inlinearray;
klass->inlinearray_value = gklass->inlinearray_value;
klass->enumtype = gklass->enumtype;
klass->valuetype = gklass->valuetype;

Expand Down Expand Up @@ -2184,6 +2237,7 @@ mono_class_layout_fields (MonoClass *klass, int base_instance_size, int packing_
real_size = MONO_ABI_SIZEOF (MonoObject);
}

guint32 inlined_fields = 0;
for (pass = 0; pass < passes; ++pass) {
for (i = 0; i < top; i++){
gint32 align;
Expand Down Expand Up @@ -2217,6 +2271,17 @@ mono_class_layout_fields (MonoClass *klass, int base_instance_size, int packing_
}

size = mono_type_size (field->type, &align);
if (m_class_is_inlinearray (klass)) {
// Limit the max size of array instance to 1MiB
const guint32 struct_max_size = 1024 * 1024;
// If size overflows, it returns 0
size *= m_class_inlinearray_value (klass);
inlined_fields++;
if(size == 0 || size > struct_max_size) {
mono_class_set_type_load_failure (klass, "Inline array struct size out of bounds, abnormally large.");
break;
}
}

/* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
align = packing_size ? MIN (packing_size, align): align;
Expand Down Expand Up @@ -2244,6 +2309,8 @@ mono_class_layout_fields (MonoClass *klass, int base_instance_size, int packing_
instance_size &= ~(min_align - 1);
}
}
if (m_class_is_inlinearray (klass) && inlined_fields != 1)
mono_class_set_type_load_failure (klass, "Inline array struct must have a single field.");
break;
case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT: {
real_size = 0;
Expand Down
3 changes: 3 additions & 0 deletions src/mono/mono/metadata/class-private-definition.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ struct _MonoClass {
guint wastypebuilder : 1; /* class was created at runtime from a TypeBuilder */
guint is_array_special_interface : 1; /* gtd or ginst of once of the magic interfaces that arrays implement */
guint is_byreflike : 1; /* class is a valuetype and has System.Runtime.CompilerServices.IsByRefLikeAttribute */
guint is_inlinearray : 1; /* class is a valuetype and has System.Runtime.CompilerServices.InlineArrayAttribute */

/* next byte */
guint8 min_align;
Expand Down Expand Up @@ -102,6 +103,8 @@ struct _MonoClass {
guint16 *interface_offsets_packed;
guint8 *interface_bitmap;

gint32 inlinearray_value; /* System.Runtime.CompilerServices.InlineArrayAttribute length value */

MonoClass **interfaces;

union _MonoClassSizes sizes;
Expand Down
4 changes: 3 additions & 1 deletion src/mono/mono/metadata/custom-attrs-internals.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ typedef struct _MonoDecodeCustomAttr {
MonoCustomAttrInfo*
mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs);

typedef gboolean (*MonoAssemblyMetadataCustomAttrIterFunc) (MonoImage *image, guint32 typeref_scope_token, const gchar* nspace, const gchar* name, guint32 method_token, gpointer user_data);
typedef gboolean (*MonoAssemblyMetadataCustomAttrIterFunc) (MonoImage *image, guint32 typeref_scope_token, const gchar* nspace, const gchar* name, guint32 method_token, guint32 *cols, gpointer user_data);

typedef void (*MonoHasValueCallback) (MonoImage *image, uint32_t method_token, uint32_t *cols, gpointer user_data);

void
mono_assembly_metadata_foreach_custom_attr (MonoAssembly *assembly, MonoAssemblyMetadataCustomAttrIterFunc func, gpointer user_data);
Expand Down
2 changes: 1 addition & 1 deletion src/mono/mono/metadata/custom-attrs.c
Original file line number Diff line number Diff line change
Expand Up @@ -2813,7 +2813,7 @@ metadata_foreach_custom_attr_from_index (MonoImage *image, guint32 idx, MonoAsse
if (!custom_attr_class_name_from_method_token (image, mtoken, &assembly_token, &nspace, &name))
continue;

stop_iterating = func (image, assembly_token, nspace, name, mtoken, user_data);
stop_iterating = func (image, assembly_token, nspace, name, mtoken, cols, user_data);
}
}

Expand Down
10 changes: 10 additions & 0 deletions src/mono/mono/metadata/object.c
Original file line number Diff line number Diff line change
Expand Up @@ -878,6 +878,7 @@ compute_class_bitmap (MonoClass *klass, gsize *bitmap, int size, int offset, int
pos += offset;

type = mono_type_get_underlying_type (field->type);

switch (type->type) {
case MONO_TYPE_U:
case MONO_TYPE_I:
Expand Down Expand Up @@ -931,6 +932,15 @@ compute_class_bitmap (MonoClass *klass, gsize *bitmap, int size, int offset, int
g_error ("compute_class_bitmap: Invalid type %x for field %s:%s\n", type->type, mono_type_get_full_name (m_field_get_parent (field)), field->name);
break;
}

// A struct with the inline array attribute is handled in the same way as an array
if (m_class_is_inlinearray (klass)) {
g_assert ((m_field_get_offset (field) % wordsize) == 0);

g_assert (pos < GINT_TO_UINT32(size) || pos <= GINT_TO_UINT32(max_size));
bitmap [pos / BITMAP_EL_SIZE] |= ((gsize)1) << (pos % BITMAP_EL_SIZE);
*max_set = MAX (GINT_TO_UINT32(*max_set), pos);
}
}
if (static_fields)
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
<PropertyGroup>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<OutputType>Exe</OutputType>
<MonoAotIncompatible>true</MonoAotIncompatible>
</PropertyGroup>
<ItemGroup>
<Compile Include="InlineArrayInvalid.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
<PropertyGroup>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<OutputType>Exe</OutputType>
<MonoAotIncompatible>true</MonoAotIncompatible>
</PropertyGroup>
<ItemGroup>
<Compile Include="InlineArrayValid.cs" />
Expand Down
4 changes: 0 additions & 4 deletions src/tests/issues.targets
Original file line number Diff line number Diff line change
Expand Up @@ -1526,10 +1526,6 @@
<Issue>Static virtual methods are not yet implemented in the Mono runtime.</Issue>
</ExcludeList>

<ExcludeList Include="$(XunitTestBinBase)/Loader/classloader/InlineArray/**">
<Issue>https://github.com/dotnet/runtime/issues/80798</Issue>
</ExcludeList>

<ExcludeList Include="$(XunitTestBinBase)/baseservices/exceptions/stackoverflow/stackoverflowtester/**">
<Issue>needs triage</Issue>
</ExcludeList>
Expand Down