Example #1
0
static inline void
dynamic_image_lock (MonoDynamicImage *image)
{
	MONO_ENTER_GC_SAFE;
	mono_image_lock ((MonoImage*)image);
	MONO_EXIT_GC_SAFE;
}
Example #2
0
static MonoMethod *
create_method_ilgen (MonoMethodBuilder *mb, MonoMethodSignature *signature, int max_stack)
{
	MonoMethodHeader *header;
	MonoMethodWrapper *mw;
	MonoImage *image;
	MonoMethod *method;
	GList *l;
	int i;

	g_assert (mb != NULL);

	image = m_class_get_image (mb->method->klass);

	if (mb->dynamic) {
		method = mb->method;
		mw = (MonoMethodWrapper*)method;

		method->name = mb->name;
		method->dynamic = TRUE;

		mw->header = header = (MonoMethodHeader *) 
			g_malloc0 (MONO_SIZEOF_METHOD_HEADER + mb->locals * sizeof (MonoType *));

		header->code = mb->code;

		for (i = 0, l = mb->locals_list; l; l = l->next, i++) {
			header->locals [i] = (MonoType*)l->data;
		}
	} else
	{
		/* Realloc the method info into a mempool */

		method = (MonoMethod *)mono_image_alloc0 (image, sizeof (MonoMethodWrapper));
		memcpy (method, mb->method, sizeof (MonoMethodWrapper));
		mw = (MonoMethodWrapper*) method;

		if (mb->no_dup_name)
			method->name = mb->name;
		else
			method->name = mono_image_strdup (image, mb->name);

		mw->header = header = (MonoMethodHeader *) 
			mono_image_alloc0 (image, MONO_SIZEOF_METHOD_HEADER + mb->locals * sizeof (MonoType *));

		header->code = (const unsigned char *)mono_image_alloc (image, mb->pos);
		memcpy ((char*)header->code, mb->code, mb->pos);

		for (i = 0, l = mb->locals_list; l; l = l->next, i++) {
			header->locals [i] = (MonoType*)l->data;
		}
	}

	/* Free the locals list so mono_mb_free () doesn't free the types twice */
	g_list_free (mb->locals_list);
	mb->locals_list = NULL;

	method->signature = signature;
	if (!signature->hasthis)
		method->flags |= METHOD_ATTRIBUTE_STATIC;

	if (max_stack < 8)
		max_stack = 8;

	header->max_stack = max_stack;

	header->code_size = mb->pos;
	header->num_locals = mb->locals;
	header->init_locals = mb->init_locals;
	header->volatile_args = mb->volatile_args;
	header->volatile_locals = mb->volatile_locals;
	mb->volatile_args = NULL;
	mb->volatile_locals = NULL;

	header->num_clauses = mb->num_clauses;
	header->clauses = mb->clauses;

	method->skip_visibility = mb->skip_visibility;

	i = g_list_length ((GList *)mw->method_data);
	if (i) {
		GList *tmp;
		void **data;
		l = g_list_reverse ((GList *)mw->method_data);
		if (method_is_dynamic (method))
			data = (void **)g_malloc (sizeof (gpointer) * (i + 1));
		else
			data = (void **)mono_image_alloc (image, sizeof (gpointer) * (i + 1));
		/* store the size in the first element */
		data [0] = GUINT_TO_POINTER (i);
		i = 1;
		for (tmp = l; tmp; tmp = tmp->next) {
			data [i++] = tmp->data;
		}
		g_list_free (l);

		mw->method_data = data;
	}

	/*{
		static int total_code = 0;
		static int total_alloc = 0;
		total_code += mb->pos;
		total_alloc += mb->code_size;
		g_print ("code size: %d of %d (allocated: %d)\n", mb->pos, total_code, total_alloc);
	}*/

#ifdef DEBUG_RUNTIME_CODE
	printf ("RUNTIME CODE FOR %s\n", mono_method_full_name (method, TRUE));
	printf ("%s\n", mono_disasm_code (&marshal_dh, method, mb->code, mb->code + mb->pos));
#endif

	if (mb->param_names) {
		char **param_names = (char **)mono_image_alloc0 (image, signature->param_count * sizeof (gpointer));
		for (i = 0; i < signature->param_count; ++i)
			param_names [i] = mono_image_strdup (image, mb->param_names [i]);

		mono_image_lock (image);
		if (!image->wrapper_param_names)
			image->wrapper_param_names = g_hash_table_new (NULL, NULL);
		g_hash_table_insert (image->wrapper_param_names, method, param_names);
		mono_image_unlock (image);
	}

	return method;
}
Example #3
0
static gboolean
check_image_may_reference_image(MonoImage *from, MonoImage *to)
{
	if (to == from) // Shortcut
		return TRUE;

	// Corlib is never unloaded, and all images implicitly reference it.
	// Some images avoid explicitly referencing it as an optimization, so special-case it here.
	if (to == mono_defaults.corlib)
		return TRUE;

	// Non-dynamic images may NEVER reference dynamic images
	if (to->dynamic && !from->dynamic)
		return FALSE;

	// FIXME: We currently give a dynamic images a pass on the reference rules.
	// Dynamic images may ALWAYS reference non-dynamic images.
	// We allow this because the dynamic image code is known "messy", and in theory it is already
	// protected because dynamic images can only reference classes their assembly has retained.
	// However, long term, we should make this rigorous.
	if (from->dynamic && !to->dynamic)
		return TRUE;

	gboolean success = FALSE;

	// Images to inspect on this pass, images to inspect on the next pass
	GPtrArray *current = g_ptr_array_sized_new (1), *next = g_ptr_array_new ();

	// Because in practice the image graph contains cycles, we must track which images we've visited
	GHashTable *visited = g_hash_table_new (NULL, NULL);

	#define CHECK_IMAGE_VISIT(i) check_image_search (visited, next, (i), to, &success)

	CHECK_IMAGE_VISIT (from); // Initially "next" contains only from node

	// For each pass exhaust the "to check" queue while filling up the "check next" queue
	while (!success && next->len > 0) // Halt on success or when out of nodes to process
	{
		// Swap "current" and "next" and clear next
		GPtrArray *temp = current;
		current = next;
		next = temp;
		g_ptr_array_set_size (next, 0);

		int current_idx;
		for(current_idx = 0; current_idx < current->len; current_idx++)
		{
			MonoImage *checking = g_ptr_array_index (current, current_idx); // CAST?

			mono_image_lock (checking);

			// For each queued image visit all directly referenced images
			int inner_idx;

			for (inner_idx = 0; !success && inner_idx < checking->module_count; inner_idx++)
			{
				CHECK_IMAGE_VISIT (checking->modules[inner_idx]);
			}

			for (inner_idx = 0; !success && inner_idx < checking->nreferences; inner_idx++)
			{
				// References are lazy-loaded and thus allowed to be NULL.
				// If they are NULL, we don't care about them for this search, because they haven't impacted ref_count yet.
				if (checking->references[inner_idx])
				{
					CHECK_IMAGE_VISIT (checking->references[inner_idx]->image);
				}
			}

			mono_image_unlock (checking);
		}
	}

	g_ptr_array_free (current, TRUE); g_ptr_array_free (next, TRUE); g_hash_table_destroy (visited);

	return success;
}