static gboolean do_mono_metadata_type_equal (MonoType *t1, MonoType *t2, gboolean signature_only);
static gboolean mono_metadata_class_equal (MonoClass *c1, MonoClass *c2, gboolean signature_only);
+static gboolean mono_metadata_fnptr_equal (MonoMethodSignature *s1, MonoMethodSignature *s2, gboolean signature_only);
static gboolean _mono_metadata_generic_class_equal (const MonoGenericClass *g1, const MonoGenericClass *g2,
gboolean signature_only);
MONO_MT_TABLE_IDX, /* "EventType" }, TypeDef or TypeRef */
MONO_MT_END,
-#define EXPORTED_TYPE_SCHEMA_OFFSET EVENT_SCHEMA_OFFSET + 4
+#define EVENT_POINTER_SCHEMA_OFFSET EVENT_SCHEMA_OFFSET + 4
+ MONO_MT_TABLE_IDX, /* "Event" }, */
+ MONO_MT_END,
+
+#define EXPORTED_TYPE_SCHEMA_OFFSET EVENT_POINTER_SCHEMA_OFFSET + 2
MONO_MT_UINT32, /* "Flags" }, */
MONO_MT_TABLE_IDX, /* "TypeDefId" }, */
MONO_MT_STRING_IDX, /* "TypeName" }, */
MONO_MT_TABLE_IDX, /* "Field:Field" }, */
MONO_MT_END,
-#define FILE_SCHEMA_OFFSET FIELD_RVA_SCHEMA_OFFSET + 3
+#define FIELD_POINTER_SCHEMA_OFFSET FIELD_RVA_SCHEMA_OFFSET + 3
+ MONO_MT_TABLE_IDX, /* "Field" }, */
+ MONO_MT_END,
+
+#define FILE_SCHEMA_OFFSET FIELD_POINTER_SCHEMA_OFFSET + 2
MONO_MT_UINT32, /* "Flags" }, */
MONO_MT_STRING_IDX, /* "Name" }, */
MONO_MT_BLOB_IDX, /* "Value" }, */
MONO_MT_HS_IDX, /* "Association" }, */
MONO_MT_END,
-#define MODULE_SCHEMA_OFFSET METHOD_SEMA_SCHEMA_OFFSET + 4
+#define METHOD_POINTER_SCHEMA_OFFSET METHOD_SEMA_SCHEMA_OFFSET + 4
+ MONO_MT_TABLE_IDX, /* "Method" }, */
+ MONO_MT_END,
+
+#define MODULE_SCHEMA_OFFSET METHOD_POINTER_SCHEMA_OFFSET + 2
MONO_MT_UINT16, /* "Generation" }, */
MONO_MT_STRING_IDX, /* "Name" }, */
MONO_MT_GUID_IDX, /* "MVID" }, */
MONO_MT_STRING_IDX, /* "Name" }, */
MONO_MT_END,
-#define PROPERTY_SCHEMA_OFFSET PARAM_SCHEMA_OFFSET + 4
+#define PARAM_POINTER_SCHEMA_OFFSET PARAM_SCHEMA_OFFSET + 4
+ MONO_MT_TABLE_IDX, /* "Param" }, */
+ MONO_MT_END,
+
+#define PROPERTY_SCHEMA_OFFSET PARAM_POINTER_SCHEMA_OFFSET + 2
MONO_MT_UINT16, /* "Flags" }, */
MONO_MT_STRING_IDX, /* "Name" }, */
MONO_MT_BLOB_IDX, /* "Type" }, */
MONO_MT_END,
-#define PROPERTY_MAP_SCHEMA_OFFSET PROPERTY_SCHEMA_OFFSET + 4
+#define PROPERTY_POINTER_SCHEMA_OFFSET PROPERTY_SCHEMA_OFFSET + 4
+ MONO_MT_TABLE_IDX, /* "Property" }, */
+ MONO_MT_END,
+
+#define PROPERTY_MAP_SCHEMA_OFFSET PROPERTY_POINTER_SCHEMA_OFFSET + 2
MONO_MT_TABLE_IDX, /* "Parent:TypeDef" }, */
MONO_MT_TABLE_IDX, /* "PropertyList:Property" }, */
MONO_MT_END,
MODULE_SCHEMA_OFFSET,
TYPEREF_SCHEMA_OFFSET,
TYPEDEF_SCHEMA_OFFSET,
- NULL_SCHEMA_OFFSET,
+ FIELD_POINTER_SCHEMA_OFFSET,
FIELD_SCHEMA_OFFSET,
- NULL_SCHEMA_OFFSET,
+ METHOD_POINTER_SCHEMA_OFFSET,
METHOD_SCHEMA_OFFSET,
- NULL_SCHEMA_OFFSET,
+ PARAM_POINTER_SCHEMA_OFFSET,
PARAM_SCHEMA_OFFSET,
IFACEMAP_SCHEMA_OFFSET,
MEMBERREF_SCHEMA_OFFSET, /* 0xa */
FIELD_LAYOUT_SCHEMA_OFFSET, /* 0x10 */
STDALON_SIG_SCHEMA_OFFSET,
EVENTMAP_SCHEMA_OFFSET,
- NULL_SCHEMA_OFFSET,
+ EVENT_POINTER_SCHEMA_OFFSET,
EVENT_SCHEMA_OFFSET,
PROPERTY_MAP_SCHEMA_OFFSET,
- NULL_SCHEMA_OFFSET,
+ PROPERTY_POINTER_SCHEMA_OFFSET,
PROPERTY_SCHEMA_OFFSET,
METHOD_SEMA_SCHEMA_OFFSET,
METHOD_IMPL_SCHEMA_OFFSET,
field_size = MAX (idx_size (MONO_TABLE_TYPEDEF), idx_size(MONO_TABLE_TYPEREF));
field_size = MAX (field_size, idx_size(MONO_TABLE_TYPESPEC));
break;
+ case MONO_TABLE_EVENT_POINTER:
+ g_assert (i == 0);
+ field_size = idx_size (MONO_TABLE_EVENT); break;
case MONO_TABLE_EXPORTEDTYPE:
g_assert (i == 1);
/* the index is in another metadata file, so it must be 4 */
case MONO_TABLE_FIELDRVA:
g_assert (i == 1);
field_size = idx_size (MONO_TABLE_FIELD); break;
+ case MONO_TABLE_FIELD_POINTER:
+ g_assert (i == 0);
+ field_size = idx_size (MONO_TABLE_FIELD); break;
case MONO_TABLE_IMPLMAP:
g_assert (i == 3);
field_size = idx_size (MONO_TABLE_MODULEREF); break;
case MONO_TABLE_METHODSEMANTICS:
g_assert (i == 1);
field_size = idx_size (MONO_TABLE_METHOD); break;
+ case MONO_TABLE_METHOD_POINTER:
+ g_assert (i == 0);
+ field_size = idx_size (MONO_TABLE_METHOD); break;
case MONO_TABLE_NESTEDCLASS:
g_assert (i == 0 || i == 1);
field_size = idx_size (MONO_TABLE_TYPEDEF); break;
+ case MONO_TABLE_PARAM_POINTER:
+ g_assert (i == 0);
+ field_size = idx_size (MONO_TABLE_PARAM); break;
case MONO_TABLE_PROPERTYMAP:
g_assert (i == 0 || i == 1);
field_size = i ? idx_size (MONO_TABLE_PROPERTY):
idx_size(MONO_TABLE_TYPEDEF);
break;
+ case MONO_TABLE_PROPERTY_POINTER:
+ g_assert (i == 0);
+ field_size = idx_size (MONO_TABLE_PROPERTY); break;
case MONO_TABLE_TYPEDEF:
g_assert (i == 4 || i == 5);
field_size = i == 4 ? idx_size (MONO_TABLE_FIELD):
}
return 0;
}
+
/**
* mono_metadata_decode_blob_size:
* @ptr: pointer to a blob object
return ival - 0x20000000;
}
+/*
+ * Translates the given 1-based index into the Method, Field, Event, or Param tables
+ * using the *Ptr tables in uncompressed metadata, if they are available.
+ *
+ * FIXME: The caller is not forced to call this function, which is error-prone, since
+ * forgetting to call it would only show up as a bug on uncompressed metadata.
+ */
+guint32
+mono_metadata_translate_token_index (MonoImage *image, int table, guint32 idx)
+{
+ if (!image->uncompressed_metadata)
+ return idx;
+
+ switch (table) {
+ case MONO_TABLE_METHOD:
+ if (image->tables [MONO_TABLE_METHOD_POINTER].rows)
+ return mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD_POINTER], idx - 1, MONO_METHOD_POINTER_METHOD);
+ else
+ return idx;
+ case MONO_TABLE_FIELD:
+ if (image->tables [MONO_TABLE_FIELD_POINTER].rows)
+ return mono_metadata_decode_row_col (&image->tables [MONO_TABLE_FIELD_POINTER], idx - 1, MONO_FIELD_POINTER_FIELD);
+ else
+ return idx;
+ case MONO_TABLE_EVENT:
+ if (image->tables [MONO_TABLE_EVENT_POINTER].rows)
+ return mono_metadata_decode_row_col (&image->tables [MONO_TABLE_EVENT_POINTER], idx - 1, MONO_EVENT_POINTER_EVENT);
+ else
+ return idx;
+ case MONO_TABLE_PROPERTY:
+ if (image->tables [MONO_TABLE_PROPERTY_POINTER].rows)
+ return mono_metadata_decode_row_col (&image->tables [MONO_TABLE_PROPERTY_POINTER], idx - 1, MONO_PROPERTY_POINTER_PROPERTY);
+ else
+ return idx;
+ case MONO_TABLE_PARAM:
+ if (image->tables [MONO_TABLE_PARAM_POINTER].rows)
+ return mono_metadata_decode_row_col (&image->tables [MONO_TABLE_PARAM_POINTER], idx - 1, MONO_PARAM_POINTER_PARAM);
+ else
+ return idx;
+ default:
+ return idx;
+ }
+}
+
+/**
+ * mono_metadata_decode_table_row:
+ *
+ * Same as mono_metadata_decode_row, but takes an IMAGE+TABLE ID pair, and takes
+ * uncompressed metadata into account, so it should be used to access the
+ * Method, Field, Param and Event tables when the access is made from metadata, i.e.
+ * IDX is retrieved from a metadata table, like MONO_TYPEDEF_FIELD_LIST.
+ */
+void
+mono_metadata_decode_table_row (MonoImage *image, int table, int idx, guint32 *res, int res_size)
+{
+ if (image->uncompressed_metadata)
+ idx = mono_metadata_translate_token_index (image, table, idx + 1) - 1;
+
+ mono_metadata_decode_row (&image->tables [table], idx, res, res_size);
+}
+
+/**
+ * mono_metadata_decode_table_row_col:
+ *
+ * Same as mono_metadata_decode_row_col, but takes an IMAGE+TABLE ID pair, and takes
+ * uncompressed metadata into account, so it should be used to access the
+ * Method, Field, Param and Event tables.
+ */
+guint32 mono_metadata_decode_table_row_col (MonoImage *image, int table, int idx, guint col)
+{
+ if (image->uncompressed_metadata)
+ idx = mono_metadata_translate_token_index (image, table, idx + 1) - 1;
+
+ return mono_metadata_decode_row_col (&image->tables [table], idx, col);
+}
+
/*
* mono_metadata_parse_typedef_or_ref:
* @m: a metadata context.
g_hash_table_insert (type_cache, (gpointer) &builtin_types [i], (gpointer) &builtin_types [i]);
}
+/**
+ * mono_metadata_cleanup:
+ *
+ * Free all resources used by this module.
+ * This is a Mono runtime internal function.
+ */
+void
+mono_metadata_cleanup (void)
+{
+ g_hash_table_destroy (type_cache);
+ g_hash_table_destroy (generic_inst_cache);
+ g_hash_table_destroy (generic_class_cache);
+}
+
/**
* mono_metadata_parse_type:
* @m: metadata context
* this MonoGenericContainer.
* This is a Mono runtime internal function.
*
+ * LOCKING: Assumes the loader lock is held.
+ *
* Returns: a #MonoType structure representing the decoded type.
*/
MonoType*
}
if (count) {
- type = g_malloc0 (sizeof (MonoType) + ((gint32)count - MONO_ZERO_LEN_ARRAY) * sizeof (MonoCustomMod));
+ type = mono_mempool_alloc0 (m->mempool, sizeof (MonoType) + ((gint32)count - MONO_ZERO_LEN_ARRAY) * sizeof (MonoCustomMod));
type->num_mods = count;
if (count > 64)
g_warning ("got more than 64 modifiers in type");
if (rptr)
*rptr = ptr;
-
- /* FIXME: remove the != MONO_PARSE_PARAM condition, this accounts for
- * almost 10k (about 2/3rds) of all MonoType's we create.
- */
- if (mode != MONO_PARSE_PARAM && !type->num_mods) {
+ if (!type->num_mods) {
/* no need to free type here, because it is on the stack */
if ((type->type == MONO_TYPE_CLASS || type->type == MONO_TYPE_VALUETYPE) && !type->pinned && !type->attrs) {
MonoType *ret = type->byref ? &type->data.klass->this_arg : &type->data.klass->byval_arg;
return cached;
}
- /*printf ("%x%c %s\n", type->attrs, type->pinned ? 'p' : ' ', mono_type_full_name (type));*/
+ /* printf ("%x %x %c %s\n", type->attrs, type->num_mods, type->pinned ? 'p' : ' ', mono_type_full_name (type)); */
- if (type == &stype)
- type = g_memdup (&stype, sizeof (MonoType));
+ if (type == &stype) {
+ type = mono_mempool_alloc (m->mempool, sizeof (MonoType));
+ memcpy (type, &stype, sizeof (MonoType));
+ }
return type;
}
+/*
+ * LOCKING: Assumes the loader lock is held.
+ */
MonoType*
mono_metadata_parse_type (MonoImage *m, MonoParseTypeMode mode, short opt_attrs,
const char *ptr, const char **rptr)
return mono_metadata_parse_type_full (m, NULL, mode, opt_attrs, ptr, rptr);
}
+/*
+ * mono_metadata_get_param_attrs:
+ *
+ * Return the parameter attributes for the method whose MethodDef index is DEF. The
+ * returned memory needs to be freed by the caller. If all the param attributes are
+ * 0, then NULL is returned.
+ */
+int*
+mono_metadata_get_param_attrs (MonoImage *m, int def)
+{
+ MonoTableInfo *paramt = &m->tables [MONO_TABLE_PARAM];
+ MonoTableInfo *methodt = &m->tables [MONO_TABLE_METHOD];
+ guint32 cols [MONO_PARAM_SIZE];
+ guint lastp, i, param_index = mono_metadata_decode_row_col (&m->tables [MONO_TABLE_METHOD], def - 1, MONO_METHOD_PARAMLIST);
+ int *pattrs = NULL;
+
+ if (def < methodt->rows)
+ lastp = mono_metadata_decode_row_col (&m->tables [MONO_TABLE_METHOD], def, MONO_METHOD_PARAMLIST);
+ else
+ lastp = paramt->rows + 1;
+
+ for (i = param_index; i < lastp; ++i) {
+ mono_metadata_decode_row (&m->tables [MONO_TABLE_PARAM], i - 1, cols, MONO_PARAM_SIZE);
+ if (cols [MONO_PARAM_FLAGS]) {
+ if (!pattrs)
+ pattrs = g_new0 (int, 1 + (lastp - param_index));
+ pattrs [cols [MONO_PARAM_SEQUENCE]] = cols [MONO_PARAM_FLAGS];
+ }
+ }
+
+ return pattrs;
+}
+
/*
* mono_metadata_parse_signature_full:
* @image: metadata context
*
* Decode a method signature stored in the STANDALONESIG table
*
+ * LOCKING: Assumes the loader lock is held.
+ *
* Returns: a MonoMethodSignature describing the signature.
*/
MonoMethodSignature*
ptr = mono_metadata_blob_heap (image, sig);
mono_metadata_decode_blob_size (ptr, &ptr);
- return mono_metadata_parse_method_signature_full (image, generic_container, FALSE, ptr, NULL);
+ return mono_metadata_parse_method_signature_full (image, generic_container, 0, ptr, NULL);
}
/*
* The return type and the params types need to be filled later.
* This is a Mono runtime internal function.
*
+ * LOCKING: Assumes the loader lock is held.
+ *
* Returns: the new MonoMethodSignature structure.
*/
MonoMethodSignature*
{
MonoMethodSignature *sig;
- /* later we want to allocate signatures with mempools */
- sig = g_malloc0 (sizeof (MonoMethodSignature) + ((gint32)nparams - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
+ sig = mono_mempool_alloc0 (m->mempool, sizeof (MonoMethodSignature) + ((gint32)nparams - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
sig->param_count = nparams;
sig->sentinelpos = -1;
* Decode a method signature stored at @ptr.
* This is a Mono runtime internal function.
*
+ * LOCKING: Assumes the loader lock is held.
+ *
* Returns: a MonoMethodSignature describing the signature.
*/
MonoMethodSignature *
gen_param_count = mono_metadata_decode_value (ptr, &ptr);
param_count = mono_metadata_decode_value (ptr, &ptr);
- if (def) {
- MonoTableInfo *paramt = &m->tables [MONO_TABLE_PARAM];
- MonoTableInfo *methodt = &m->tables [MONO_TABLE_METHOD];
- guint32 cols [MONO_PARAM_SIZE];
- guint lastp, param_index = mono_metadata_decode_row_col (methodt, def - 1, MONO_METHOD_PARAMLIST);
-
- if (def < methodt->rows)
- lastp = mono_metadata_decode_row_col (methodt, def, MONO_METHOD_PARAMLIST);
- else
- lastp = paramt->rows + 1;
-
- pattrs = g_new0 (int, 1 + param_count);
- for (i = param_index; i < lastp; ++i) {
- mono_metadata_decode_row (paramt, i - 1, cols, MONO_PARAM_SIZE);
- pattrs [cols [MONO_PARAM_SEQUENCE]] = cols [MONO_PARAM_FLAGS];
- }
- }
+ if (def)
+ pattrs = mono_metadata_get_param_attrs (m, def);
method = mono_metadata_signature_alloc (m, param_count);
method->hasthis = hasthis;
method->explicit_this = explicit_this;
if (*ptr == MONO_TYPE_SENTINEL) {
if (method->call_convention != MONO_CALL_VARARG || def)
g_error ("found sentinel for methoddef or no vararg method");
+ if (method->sentinelpos >= 0)
+ g_error ("found sentinel twice in the same signature");
method->sentinelpos = i;
ptr++;
}
is_open = mono_class_is_open_constructed_type (method->params [i]);
}
+ /* The sentinel could be missing if the caller does not pass any additional arguments */
+ if (!def && method->call_convention == MONO_CALL_VARARG && method->sentinelpos < 0)
+ method->sentinelpos = method->param_count;
+
method->has_type_parameters = is_open;
if (def && (method->call_convention == MONO_CALL_VARARG))
* Decode a method signature stored at @ptr.
* This is a Mono runtime internal function.
*
+ * LOCKING: Assumes the loader lock is held.
+ *
* Returns: a MonoMethodSignature describing the signature.
*/
MonoMethodSignature *
if (sig->params [i])
mono_metadata_free_type (sig->params [i]);
}
-
- g_free (sig);
}
/*
return mono_metadata_lookup_generic_inst (ginst);
}
-static void
+static gboolean
do_mono_metadata_parse_generic_class (MonoType *type, MonoImage *m, MonoGenericContainer *container,
const char *ptr, const char **rptr)
{
igclass->klass = g_new0 (MonoClass, 1);
gtype = mono_metadata_parse_type (m, MONO_PARSE_TYPE, 0, ptr, &ptr);
+ if (gtype == NULL)
+ return FALSE;
gclass->container_class = gklass = mono_class_from_mono_type (gtype);
g_assert (gklass->generic_container);
if (rptr)
*rptr = ptr;
+ /* If we failed to parse, return, the error has been flagged. */
+ if (gclass->inst == NULL)
+ return FALSE;
+
/*
* We may be called multiple times on different metadata to create the same
* instantiated type. This happens for instance if we're part of a method or
g_free (gclass);
type->data.generic_class = cached;
- return;
+ return TRUE;
} else {
g_hash_table_insert (generic_class_cache, gclass, gclass);
sizeof (MonoGenericContext) +
gclass->inst->type_argc * sizeof (MonoType);
}
+ return TRUE;
}
/*
g_assert (is_var || type == MONO_TYPE_MVAR);
- if (is_var && gc->parent)
- /*
- * The current MonoGenericContainer is a generic method -> its `parent'
- * points to the containing class'es container.
- */
- gc = gc->parent;
-
- /*
- * Ensure that we have the correct type of GenericContainer.
- */
- g_assert (is_var == !gc->is_method);
+ if (is_var) {
+ if (gc->is_method || gc->parent)
+ /*
+ * The current MonoGenericContainer is a generic method -> its `parent'
+ * points to the containing class'es container.
+ */
+ return gc->parent;
+ }
return gc;
}
do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContainer *container,
const char *ptr, const char **rptr)
{
+ gboolean ok = TRUE;
type->type = mono_metadata_decode_value (ptr, &ptr);
switch (type->type){
type->data.generic_param = mono_metadata_parse_generic_param (m, container, type->type, ptr, &ptr);
break;
case MONO_TYPE_GENERICINST:
- do_mono_metadata_parse_generic_class (type, m, container, ptr, &ptr);
+ ok = do_mono_metadata_parse_generic_class (type, m, container, ptr, &ptr);
break;
default:
g_error ("type 0x%02x not handled in do_mono_metadata_parse_type", type->type);
if (rptr)
*rptr = ptr;
- return TRUE;
+ return ok;
}
/*
* mono_metadata_free_type:
* @type: type to free
*
- * Free the memory allocated for type @type.
+ * Free the memory allocated for type @type which is assumed to be created by
+ * mono_metadata_parse_type ().
*/
void
mono_metadata_free_type (MonoType *type)
mono_metadata_free_array (type->data.array);
break;
}
- g_free (type);
+
+ /* Allocated from a mempool, no need to free it */
}
#if 0
int i;
mh->num_clauses = is_fat ? sect_data_len / 24: sect_data_len / 12;
/* we could just store a pointer if we don't need to byteswap */
- mh->clauses = g_new0 (MonoExceptionClause, mh->num_clauses);
+ mh->clauses = mono_mempool_alloc0 (m->mempool, sizeof (MonoExceptionClause) * mh->num_clauses);
for (i = 0; i < mh->num_clauses; ++i) {
MonoExceptionClause *ec = &mh->clauses [i];
guint32 tof_value;
* info about local variables and optional exception tables.
* This is a Mono runtime internal function.
*
- * Returns: a MonoMethodHeader.
+ * LOCKING: Assumes the loader lock is held.
+ *
+ * Returns: a MonoMethodHeader allocated from the image mempool.
*/
MonoMethodHeader *
mono_metadata_parse_mh_full (MonoImage *m, MonoGenericContainer *container, const char *ptr)
switch (format) {
case METHOD_HEADER_TINY_FORMAT:
- mh = g_new0 (MonoMethodHeader, 1);
+ mh = mono_mempool_alloc0 (m->mempool, sizeof (MonoMethodHeader));
ptr++;
mh->max_stack = 8;
local_var_sig_tok = 0;
mh->code = ptr;
return mh;
case METHOD_HEADER_TINY_FORMAT1:
- mh = g_new0 (MonoMethodHeader, 1);
+ mh = mono_mempool_alloc0 (m->mempool, sizeof (MonoMethodHeader));
ptr++;
mh->max_stack = 8;
local_var_sig_tok = 0;
g_warning ("wrong signature for locals blob");
locals_ptr++;
len = mono_metadata_decode_value (locals_ptr, &locals_ptr);
- mh = g_malloc0 (sizeof (MonoMethodHeader) + (len - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
+ mh = mono_mempool_alloc0 (m->mempool, sizeof (MonoMethodHeader) + (len - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
mh->num_locals = len;
for (i = 0; i < len; ++i) {
mh->locals [i] = mono_metadata_parse_type_full (
m, container, MONO_PARSE_LOCAL, 0, locals_ptr, &locals_ptr);
if (!mh->locals [i]) {
- g_free (mh);
return NULL;
}
}
} else {
- mh = g_new0 (MonoMethodHeader, 1);
+ mh = mono_mempool_alloc0 (m->mempool, sizeof (MonoMethodHeader));
}
mh->code = code;
mh->code_size = code_size;
MonoMethodHeader *
mono_metadata_parse_mh (MonoImage *m, const char *ptr)
{
- return mono_metadata_parse_mh_full (m, NULL, ptr);
+ MonoMethodHeader *res;
+
+ mono_loader_lock ();
+
+ res = mono_metadata_parse_mh_full (m, NULL, ptr);
+
+ mono_loader_unlock ();
+
+ return res;
}
/*
void
mono_metadata_free_mh (MonoMethodHeader *mh)
{
- int i;
- for (i = 0; i < mh->num_locals; ++i)
- mono_metadata_free_type (mh->locals[i]);
- g_free (mh->clauses);
- g_free (mh);
+ /* Allocated from the mempool */
}
/*
return 1;
}
+/**
+ * search_ptr_table:
+ *
+ * Return the 1-based row index in TABLE, which must be one of the *Ptr tables,
+ * which contains IDX.
+ */
+static guint32
+search_ptr_table (MonoImage *image, int table, int idx)
+{
+ MonoTableInfo *ptrdef = &image->tables [table];
+ int i;
+
+ /* Use a linear search to find our index in the table */
+ for (i = 0; i < ptrdef->rows; i ++)
+ /* All the Ptr tables have the same structure */
+ if (mono_metadata_decode_row_col (ptrdef, i, 0) == idx)
+ break;
+
+ if (i < ptrdef->rows)
+ return i + 1;
+ else
+ return idx;
+}
+
/**
* mono_metadata_typedef_from_field:
* @meta: metadata context
loc.col_idx = MONO_TYPEDEF_FIELD_LIST;
loc.t = tdef;
+ if (meta->uncompressed_metadata)
+ loc.idx = search_ptr_table (meta, MONO_TABLE_FIELD_POINTER, loc.idx);
+
if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, typedef_locator))
g_assert_not_reached ();
loc.col_idx = MONO_TYPEDEF_METHOD_LIST;
loc.t = tdef;
+ if (meta->uncompressed_metadata)
+ loc.idx = search_ptr_table (meta, MONO_TABLE_METHOD_POINTER, loc.idx);
+
if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, typedef_locator))
g_assert_not_reached ();
* The array of interfaces that the @index typedef token implements is returned in
* @interfaces. The number of elemnts in the array is returned in @count.
*
+ * LOCKING: Assumes the loader lock is held.
+ *
* Returns: TRUE on success, FALSE on failure.
*/
gboolean
{
MonoTableInfo *tdef = &meta->tables [MONO_TABLE_INTERFACEIMPL];
locator_t loc;
- guint32 start, i;
+ guint32 start, pos;
guint32 cols [MONO_INTERFACEIMPL_SIZE];
MonoClass **result;
else
break;
}
- result = NULL;
- i = 0;
- while (start < tdef->rows) {
- mono_metadata_decode_row (tdef, start, cols, MONO_INTERFACEIMPL_SIZE);
+ pos = start;
+ while (pos < tdef->rows) {
+ mono_metadata_decode_row (tdef, pos, cols, MONO_INTERFACEIMPL_SIZE);
+ if (cols [MONO_INTERFACEIMPL_CLASS] != loc.idx)
+ break;
+ ++pos;
+ }
+
+ result = mono_mempool_alloc0 (meta->mempool, sizeof (MonoClass*) * (pos - start));
+
+ pos = start;
+ while (pos < tdef->rows) {
+ MonoClass *iface;
+
+ mono_metadata_decode_row (tdef, pos, cols, MONO_INTERFACEIMPL_SIZE);
if (cols [MONO_INTERFACEIMPL_CLASS] != loc.idx)
break;
- result = g_renew (MonoClass*, result, i + 1);
- result [i] = mono_class_get_full (
+ iface = mono_class_get_full (
meta, mono_metadata_token_from_dor (cols [MONO_INTERFACEIMPL_INTERFACE]), context);
- *count = ++i;
- ++start;
+ if (iface == NULL)
+ return FALSE;
+ result [pos - start] = iface;
+ ++pos;
}
+ *count = pos - start;
*interfaces = result;
return TRUE;
}
MonoClass **interfaces;
gboolean rv;
+ mono_loader_lock ();
rv = mono_metadata_interfaces_from_typedef_full (meta, index, &interfaces, count, NULL);
+ mono_loader_unlock ();
if (rv)
return interfaces;
else
loc.col_idx = MONO_CUSTOM_ATTR_PARENT;
loc.t = tdef;
+ /* FIXME: Index translation */
+
if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
return 0;
* type in memory
*/
int
-mono_type_size (MonoType *t, gint *align)
+mono_type_size (MonoType *t, int *align)
{
if (!t) {
*align = 1;
MonoClass *container_class;
gclass = mono_get_inflated_generic_class (t->data.generic_class);
- g_assert (!gclass->generic_class.inst->is_open);
- g_assert (!gclass->klass->generic_container);
+ // g_assert (!gclass->generic_class.inst->is_open);
+ // g_assert (!gclass->klass->generic_container);
container_class = gclass->generic_class.container_class;
* type on the runtime stack
*/
int
-mono_type_stack_size (MonoType *t, gint *align)
+mono_type_stack_size (MonoType *t, int *align)
{
- int tmp;
+ guint32 tmp;
g_assert (t != NULL);
return FALSE;
}
+static gboolean
+mono_metadata_fnptr_equal (MonoMethodSignature *s1, MonoMethodSignature *s2, gboolean signature_only)
+{
+ gpointer iter1 = 0, iter2 = 0;
+
+ if (s1 == s2)
+ return TRUE;
+ if (s1->call_convention != s2->call_convention)
+ return FALSE;
+ if (s1->sentinelpos != s2->sentinelpos)
+ return FALSE;
+ if (s1->hasthis != s2->hasthis)
+ return FALSE;
+ if (s1->explicit_this != s2->explicit_this)
+ return FALSE;
+ if (! do_mono_metadata_type_equal (s1->ret, s2->ret, signature_only))
+ return FALSE;
+ if (s1->param_count != s2->param_count)
+ return FALSE;
+
+ while (TRUE) {
+ MonoType *t1 = mono_signature_get_params (s1, &iter1);
+ MonoType *t2 = mono_signature_get_params (s2, &iter2);
+
+ if (t1 == NULL || t2 == NULL)
+ return (t1 == t2);
+ if (! do_mono_metadata_type_equal (t1, t2, signature_only))
+ return FALSE;
+ }
+}
+
/*
* mono_metadata_type_equal:
* @t1: a type
case MONO_TYPE_MVAR:
return mono_metadata_generic_param_equal (
t1->data.generic_param, t2->data.generic_param, signature_only);
+ case MONO_TYPE_FNPTR:
+ return mono_metadata_fnptr_equal (t1->data.method, t2->data.method, signature_only);
default:
g_error ("implement type compare for %0x!", t1->type);
return FALSE;
return TRUE;
}
+/**
+ * mono_metadata_type_dup_mp:
+ * @image: image type is defined in
+ * @original: type to duplicate
+ *
+ * Returns: copy of type allocated from mempool.
+ */
+MonoType *
+mono_metadata_type_dup_mp (MonoImage *image, const MonoType *original)
+{
+ MonoType *r = NULL;
+ mono_loader_lock ();
+ r = mono_mempool_alloc0 (image->mempool, sizeof(MonoType));
+ mono_loader_unlock ();
+ *r = *original;
+ /* FIXME: we don't handle these yet because they need to duplicate memory
+ * but the current routines used are not using the mempools
+ */
+ if (original->type == MONO_TYPE_PTR ||
+ original->type == MONO_TYPE_ARRAY ||
+ original->type == MONO_TYPE_FNPTR)
+ g_assert_not_reached ();
+ return r;
+}
+
guint
mono_signature_hash (MonoMethodSignature *sig)
{
locator_t loc;
loc.idx = index + 1;
+ if (meta->uncompressed_metadata)
+ loc.idx = search_ptr_table (meta, MONO_TABLE_FIELD_POINTER, loc.idx);
+
if (offset) {
tdef = &meta->tables [MONO_TABLE_FIELDLAYOUT];
loc.col_idx = MONO_CONSTANT_PARENT;
loc.t = tdef;
+ /* FIXME: Index translation */
+
if ((hint > 0) && (hint < tdef->rows) && (mono_metadata_decode_row_col (tdef, hint - 1, MONO_CONSTANT_PARENT) == index))
return hint;
if (!msemt->base)
return 0;
+ if (meta->uncompressed_metadata)
+ index = search_ptr_table (meta, MONO_TABLE_EVENT_POINTER, index + 1) - 1;
+
loc.t = msemt;
loc.col_idx = MONO_METHOD_SEMA_ASSOCIATION;
loc.idx = ((index + 1) << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT; /* Method association coded index */
if (!msemt->base)
return 0;
+ if (meta->uncompressed_metadata)
+ index = search_ptr_table (meta, MONO_TABLE_PROPERTY_POINTER, index + 1) - 1;
+
loc.t = msemt;
loc.col_idx = MONO_METHOD_SEMA_ASSOCIATION;
loc.idx = ((index + 1) << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY; /* Method association coded index */
if (!tdef->base)
return 0;
+ /* No index translation seems to be needed */
+
loc.t = tdef;
loc.col_idx = MONO_IMPLMAP_MEMBER;
loc.idx = ((method_idx + 1) << MONO_MEMBERFORWD_BITS) | MONO_MEMBERFORWD_METHODDEF;
if (mspec) {
switch (mspec->native) {
case MONO_NATIVE_BYVALARRAY:
- *conv = MONO_MARSHAL_CONV_ARRAY_BYVALARRAY;
+ if ((type->data.klass->element_class == mono_defaults.char_class) && !unicode)
+ *conv = MONO_MARSHAL_CONV_ARRAY_BYVALCHARARRAY;
+ else
+ *conv = MONO_MARSHAL_CONV_ARRAY_BYVALARRAY;
return MONO_NATIVE_BYVALARRAY;
case MONO_NATIVE_SAFEARRAY:
*conv = MONO_MARSHAL_CONV_ARRAY_SAVEARRAY;
loc.col_idx = MONO_FIELD_MARSHAL_PARENT;
loc.idx = ((idx + 1) << MONO_HAS_FIELD_MARSHAL_BITS) | (is_field? MONO_HAS_FIELD_MARSHAL_FIELDSREF: MONO_HAS_FIELD_MARSHAL_PARAMDEF);
+ /* FIXME: Index translation */
+
if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
return NULL;
method_from_method_def_or_ref (MonoImage *m, guint32 tok, MonoGenericContext *context)
{
guint32 idx = tok >> MONO_METHODDEFORREF_BITS;
+
switch (tok & MONO_METHODDEFORREF_MASK) {
case MONO_METHODDEFORREF_METHODDEF:
return mono_get_method_full (m, MONO_TOKEN_METHOD_DEF | idx, NULL, context);
gint32 i, num;
guint32 cols [MONO_METHODIMPL_SIZE];
MonoMethod **result;
-
+ gint32 ok = TRUE;
+
*overrides = NULL;
if (num_overrides)
*num_overrides = 0;
num = end - start;
result = g_new (MonoMethod*, num * 2);
for (i = 0; i < num; ++i) {
+ MonoMethod *method;
+
mono_metadata_decode_row (tdef, start + i, cols, MONO_METHODIMPL_SIZE);
- result [i * 2] = method_from_method_def_or_ref (
+ method = method_from_method_def_or_ref (
image, cols [MONO_METHODIMPL_DECLARATION], generic_context);
- result [i * 2 + 1] = method_from_method_def_or_ref (
+ if (method == NULL)
+ ok = FALSE;
+ result [i * 2] = method;
+ method = method_from_method_def_or_ref (
image, cols [MONO_METHODIMPL_BODY], generic_context);
+ if (method == NULL)
+ ok = FALSE;
+ result [i * 2 + 1] = method;
}
*overrides = result;
if (num_overrides)
*num_overrides = num;
- return TRUE;
+ return ok;
}
/**
return type->data.array;
}
+/* For MONO_TYPE_PTR */
+MonoType*
+mono_type_get_ptr_type (MonoType *type)
+{
+ return type->data.type;
+}
+
MonoClass*
mono_type_get_modifiers (MonoType *type, gboolean *is_required, gpointer *iter)
{