Welcome to mirror list, hosted at ThFree Co, Russian Federation.

heapsections.c - github.com/Unity-Technologies/bdwgc.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 45bff49a5aea6ef8ec1b2d89bcebd9d5812fbba0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#include "private/gc_priv.h"

static struct hblk* GetNextFreeBlock(ptr_t ptr)
{
	struct hblk* result = NULL;
	unsigned i;

	for (i = 0; i < N_HBLK_FLS + 1; i++)
	{
		struct hblk* freeBlock = GC_hblkfreelist[i];

		for (freeBlock = GC_hblkfreelist[i]; freeBlock != NULL; freeBlock = HDR(freeBlock)->hb_next)
		{
			/* We're only interested in pointers after "ptr" argument */
			if ((ptr_t)freeBlock < ptr)
				continue;

			/* If we haven't had a result before or our previous result is */
			/* ahead of the current freeBlock, mark the current freeBlock as result */
			if (result == NULL || result > freeBlock)
				result = freeBlock;
		}
	}

	return result;
}

static void CallHeapSectionCallback(void* user_data, ptr_t start, ptr_t end, GC_heap_section_proc callback)
{
	hdr *hhdr = HDR(start);

	// Validate that the heap block is valid, then fire our callback.
	if (IS_FORWARDING_ADDR_OR_NIL(hhdr) || HBLK_IS_FREE(hhdr)) {
		return;
	}
	
	callback(user_data, start, end);
}

void GC_foreach_heap_section(void* user_data, GC_heap_section_proc callback)
{
	unsigned i;
	struct hblk* nextFreeBlock = NULL;

	GC_ASSERT(I_HOLD_LOCK());

	if (callback == NULL)
		return;

	for (i = 0; i < GC_n_heap_sects; i++)
	{
		ptr_t sectionStart = GC_heap_sects[i].hs_start;
		ptr_t sectionEnd = sectionStart + GC_heap_sects[i].hs_bytes;
       
		/* Merge in contiguous sections. Copied from GC_dump_regions

		A free block might start in one heap section and extend
		into the next one. Merging the section avoids crashes when
		trying to copy the start of section that is a free block
		continued from the previous section. */
		while (i + 1 < GC_n_heap_sects && GC_heap_sects[i + 1].hs_start == sectionEnd)
		{
			++i;
			sectionEnd = GC_heap_sects[i].hs_start + GC_heap_sects[i].hs_bytes;
        }

		while (sectionStart < sectionEnd)
		{
			nextFreeBlock = GetNextFreeBlock(sectionStart);

			if (nextFreeBlock == NULL || (ptr_t)nextFreeBlock > sectionEnd)
			{
				CallHeapSectionCallback(user_data, sectionStart, sectionEnd, callback);
				break;
			}
			else
			{
				size_t sectionLength = (char*)nextFreeBlock - sectionStart;
				if (sectionLength > 0)
					CallHeapSectionCallback(user_data, sectionStart, sectionStart + sectionLength, callback);
				sectionStart = (char*)nextFreeBlock + HDR(nextFreeBlock)->hb_sz;
			}
		}
	}
}

void HeapSectionCountIncrementer(void* context, GC_PTR start, GC_PTR end)
{
	GC_word* countPtr = (GC_word*)context;
	(*countPtr)++;
}

GC_word GC_get_heap_section_count()
{
	GC_word count = 0;
	GC_foreach_heap_section(&count, HeapSectionCountIncrementer);
	return count;
}