예제 #1
0
static void*
dyn_array_ptr_pop (DynPtrArray *da)
{
	int size = da->array.size;
	void *p;
	g_assert (size > 0);
	if (da->array.capacity == 1) {
		p = dyn_array_ptr_get (da, 0);
		dyn_array_init (&da->array);
	} else {
		g_assert (da->array.capacity > 1);
		dyn_array_ensure_independent (&da->array, sizeof (void*));
		p = dyn_array_ptr_get (da, size - 1);
		--da->array.size;
	}
	return p;
}
예제 #2
0
static gboolean
dyn_array_ptr_contains (DynPtrArray *da, void *x)
{
	int i;
	for (i = 0; i < dyn_array_ptr_size (da); ++i)
		if (dyn_array_ptr_get (da, i) == x)
			return TRUE;
	return FALSE;
}
예제 #3
0
static void*
dyn_array_ptr_pop (DynPtrArray *da)
{
	void *p;
	int size = da->array.size;
	g_assert (size > 0);
	p = dyn_array_ptr_get (da, size - 1);
	--da->array.size;
	return p;
}
예제 #4
0
static void*
dyn_array_ptr_pop (DynPtrArray *da)
{
	int size = da->array.size;
	void *p;
	g_assert (size > 0);
#ifdef OPTIMIZATION_SINGLETON_DYN_ARRAY
	if (da->array.capacity == 1) {
		p = dyn_array_ptr_get (da, 0);
		dyn_array_init (&da->array);
	} else
#endif
	{
		g_assert (da->array.capacity > 1);
		dyn_array_ensure_independent (&da->array, sizeof (void*));
		p = dyn_array_ptr_get (da, size - 1);
		--da->array.size;
	}
	return p;
}
예제 #5
0
static gboolean
match_colors (DynPtrArray *a, DynPtrArray *b)
{
	int i;
	if (dyn_array_ptr_size (a) != dyn_array_ptr_size (b))
		return FALSE;

	for (i = 0; i < dyn_array_ptr_size (a); ++i) {
		if (!dyn_array_ptr_contains (b, dyn_array_ptr_get (a, i)))
			return FALSE;
	}
	return TRUE;
}
예제 #6
0
static void
reset_xrefs (ColorData *color)
{
	int i;
	for (i = 0; i < dyn_array_ptr_size (&color->other_colors); ++i) {
		ColorData *src = dyn_array_ptr_get (&color->other_colors, i);
		if (!src->visited)
			continue;
		src->visited = FALSE;
		if (!dyn_array_ptr_size (&src->bridges))
			reset_xrefs (src);
	}
}
예제 #7
0
static void
gather_xrefs (ColorData *color)
{
	int i;
	for (i = 0; i < dyn_array_ptr_size (&color->other_colors); ++i) {
		ColorData *src = dyn_array_ptr_get (&color->other_colors, i);
		if (src->visited)
			continue;
		src->visited = TRUE;
		if (dyn_array_ptr_size (&src->bridges))
			dyn_array_ptr_add (&color_merge_array, src);
		else
			gather_xrefs (src);
	}
}
예제 #8
0
static ColorData*
reduce_color (void)
{
	ColorData *color = NULL;
	int size = dyn_array_ptr_size (&color_merge_array);

	if (size == 0)
		color = NULL;
	else if (size == 1) {
		color = dyn_array_ptr_get (&color_merge_array, 0);
	} else
		color = new_color (FALSE);

	return color;
}
예제 #9
0
static void
describe_pointer (GCObject *obj)
{
	// HashEntry *entry;
	int i;

	for (i = 0; i < dyn_array_ptr_size (&registered_bridges); ++i) {
		if (obj == dyn_array_ptr_get (&registered_bridges, i)) {
			printf ("Pointer is a registered bridge object.\n");
			break;
		}
	}

	// entry = sgen_hash_table_lookup (&hash_table, obj);
	// if (!entry)
	// 	return;
	//
	// printf ("Bridge hash table entry %p:\n", entry);
	// printf ("  is bridge: %d\n", (int)entry->is_bridge);
	// printf ("  is visited: %d\n", (int)entry->is_visited);
}
예제 #10
0
static ColorData*
find_in_cache (int *insert_index)
{
	HashEntry *bucket;
	int i, hash, size, index;

	size = dyn_array_ptr_size (&color_merge_array);
	/* Cache checking is very ineficient with a lot of elements*/
	if (size > 3)
		return NULL;

	hash = 0;
	for (i = 0 ; i < size; ++i)
		hash += mix_hash ((size_t)dyn_array_ptr_get (&color_merge_array, i));
	if (!hash)
		hash = 1;

	index = hash & (COLOR_CACHE_SIZE - 1);
	bucket = merge_cache [index];
	for (i = 0; i < ELEMENTS_PER_BUCKET; ++i) {
		if (bucket [i].hash != hash)
			continue;
		if (match_colors (&bucket [i].color->other_colors, &color_merge_array)) {
			++cache_hits;
			return bucket [i].color;
		}
	}

	//move elements to the back
	for (i = ELEMENTS_PER_BUCKET - 1; i > 0; --i)
		bucket [i] = bucket [i - 1];
	++cache_misses;
	*insert_index = index;
	bucket [0].hash = hash;
	return NULL;
}
예제 #11
0
static void
create_scc (ScanData *data)
{
	int i;
	gboolean found = FALSE;
	gboolean found_bridge = FALSE;
	ColorData *color_data = NULL;

	for (i = dyn_array_ptr_size (&loop_stack) - 1; i >= 0; --i) {
		ScanData *other = dyn_array_ptr_get (&loop_stack, i);
		found_bridge |= other->is_bridge;
		if (found_bridge || other == data)
			break;
	}

#if DUMP_GRAPH
	printf ("|SCC rooted in %s (%p) has bridge %d\n", safe_name_bridge (data->obj), data->obj, found_bridge);
	printf ("\tpoints-to-colors: ");
	for (i = 0; i < dyn_array_ptr_size (&color_merge_array); ++i)
		printf ("%p ", dyn_array_ptr_get (&color_merge_array, i));
	printf ("\n");

	printf ("loop stack: ");
	for (i = 0; i < dyn_array_ptr_size (&loop_stack); ++i) {
		ScanData *other = dyn_array_ptr_get (&loop_stack, i);
		printf ("(%d/%d)", other->index, other->low_index);
	}
	printf ("\n");
#endif

	if (found_bridge) {
		color_data = new_color (TRUE);
		++num_colors_with_bridges;
	} else {
		color_data = reduce_color ();
	}

	while (dyn_array_ptr_size (&loop_stack) > 0) {
		ScanData *other = dyn_array_ptr_pop (&loop_stack);

#if DUMP_GRAPH
		printf ("\tmember %s (%p) index %d low-index %d color %p state %d\n", safe_name_bridge (other->obj), other->obj, other->index, other->low_index, other->color, other->state);
#endif

		other->color = color_data;
		switch (other->state) {
		case FINISHED_ON_STACK:
			other->state = FINISHED_OFF_STACK;
			break;
		case FINISHED_OFF_STACK:
			break;
		default:
			g_error ("Invalid state when building SCC %d", other->state);
		}

		if (other->is_bridge)
			dyn_array_ptr_add (&color_data->bridges, other->obj);

		if (other == data) {
			found = TRUE;
			break;
		}
	}
	g_assert (found);

	for (i = 0; i < dyn_array_ptr_size (&color_merge_array); ++i) {
		ColorData *cd  = dyn_array_ptr_get (&color_merge_array, i);
		g_assert (cd->visited);
		cd->visited = FALSE;
	}
	dyn_array_ptr_set_size (&color_merge_array, 0);
	found_bridge = FALSE;
}
예제 #12
0
static void
processing_build_callback_data (int generation)
{
	int j, api_index;
	MonoGCBridgeSCC **api_sccs;
	MonoGCBridgeXRef *api_xrefs;
	gint64 curtime;
	ColorBucket *cur;

	g_assert (bridge_processor->num_sccs == 0 && bridge_processor->num_xrefs == 0);
	g_assert (!bridge_processor->api_sccs && !bridge_processor->api_xrefs);

	if (!dyn_array_ptr_size (&registered_bridges))
		return;

	SGEN_TV_GETTIME (curtime);

	/*create API objects */

#if defined (DUMP_GRAPH)
	printf ("***** API *****\n");
	printf ("number of SCCs %d\n", num_colors_with_bridges);
#endif

	/* This is a straightforward translation from colors to the bridge callback format. */
	api_sccs = sgen_alloc_internal_dynamic (sizeof (MonoGCBridgeSCC*) * num_colors_with_bridges, INTERNAL_MEM_BRIDGE_DATA, TRUE);
	api_index = xref_count = 0;

	for (cur = root_color_bucket; cur; cur = cur->next) {
		ColorData *cd;
		for (cd = &cur->data [0]; cd < cur->next_data; ++cd) {
			int bridges = dyn_array_ptr_size (&cd->bridges);
			if (!bridges)
				continue;

			api_sccs [api_index] = sgen_alloc_internal_dynamic (sizeof (MonoGCBridgeSCC) + sizeof (MonoObject*) * bridges, INTERNAL_MEM_BRIDGE_DATA, TRUE);
			api_sccs [api_index]->is_alive = FALSE;
			api_sccs [api_index]->num_objs = bridges;

			cd->api_index = api_index;

			for (j = 0; j < bridges; ++j)
				api_sccs [api_index]->objs [j] = dyn_array_ptr_get (&cd->bridges, j);
			api_index++;
		}
	}

	scc_setup_time = step_timer (&curtime);

	for (cur = root_color_bucket; cur; cur = cur->next) {
		ColorData *cd;
		for (cd = &cur->data [0]; cd < cur->next_data; ++cd) {
			int bridges = dyn_array_ptr_size (&cd->bridges);
			if (!bridges)
				continue;

			dyn_array_ptr_set_size (&color_merge_array, 0);
			gather_xrefs (cd);
			reset_xrefs (cd);
			dyn_array_ptr_set_all (&cd->other_colors, &color_merge_array);
			xref_count += dyn_array_ptr_size (&cd->other_colors);
		}
	}

	gather_xref_time = step_timer (&curtime);

#if defined (DUMP_GRAPH)
	printf ("TOTAL XREFS %d\n", xref_count);
	dump_color_table (" after xref pass", TRUE);
#endif

	api_xrefs = sgen_alloc_internal_dynamic (sizeof (MonoGCBridgeXRef) * xref_count, INTERNAL_MEM_BRIDGE_DATA, TRUE);
	api_index = 0;
	for (cur = root_color_bucket; cur; cur = cur->next) {
		ColorData *src;
		for (src = &cur->data [0]; src < cur->next_data; ++src) {
			int bridges = dyn_array_ptr_size (&src->bridges);
			if (!bridges)
				continue;

			for (j = 0; j < dyn_array_ptr_size (&src->other_colors); ++j) {
				ColorData *dest = dyn_array_ptr_get (&src->other_colors, j);
				g_assert (dyn_array_ptr_size (&dest->bridges)); /* We flattened the color graph, so this must never happen. */

				api_xrefs [api_index].src_scc_index = src->api_index;
				api_xrefs [api_index].dst_scc_index = dest->api_index;
				++api_index;
			}
		}
	}

	g_assert (xref_count == api_index);
	xref_setup_time = step_timer (&curtime);

#if defined (DUMP_GRAPH)
	printf ("---xrefs:\n");
	for (i = 0; i < xref_count; ++i)
		printf ("\t%d -> %d\n", api_xrefs [i].src_scc_index, api_xrefs [i].dst_scc_index);
#endif

	//FIXME move half of the cleanup to before the bridge callback?
	bridge_processor->num_sccs = num_colors_with_bridges;
	bridge_processor->api_sccs = api_sccs;
	bridge_processor->num_xrefs = xref_count;
	bridge_processor->api_xrefs = api_xrefs;
}