少年修仙传客户端基础资源
hch
2024-04-01 d01413b00ef631ac20347716b23818b0b811f65f
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;
}