1 /* Statistics about heap space usage. */
2
3 /* -------------------------- Specification ---------------------------- */
4
5 /* Returns the size of the memory occupied by static (gcinvariant) heap
6 objects. */
7 global uintM static_space (void);
8
9 /* Returns the size of the memory occupied by (dynamically) allocated heap
10 objects. */
11 global uintM used_space (void);
12
13 /* Returns the size of memory available until the next GC occurs. */
14 global uintM free_space (void);
15
16 #ifdef SPVW_PAGES
17 /* Recomputes mem.used_space and mem.total_space.
18 > bool check: if true, mem.used_space must remain the same. */
19 local void recalc_space (bool check);
20 #endif
21
22 /* -------------------------- Implementation --------------------------- */
23
24 #if !defined(OLD_GC) && defined(MULTITHREAD) && defined(SPVW_BLOCKS)
25 /* UP: returns sum of sizes of all holes in a heap
26 currently used from spvw_garcol.d and here */
heap_holes_space(Heap * heap)27 local inline uintM heap_holes_space(Heap *heap) {
28 var uintM ret = 0;
29 var aint hl = heap->holes_list;
30 while (hl) {
31 var heap_hole *hh = (heap_hole *)&((Sbvector)hl)->data;
32 ret += hh->hh_size;
33 hl = hh->hh_next;
34 }
35 return ret;
36 }
37 #else
38 /* no holes in single thread builds & MT+SPVW_PAGES */
39 #define heap_holes_space(heap) (uintM)0
40 #endif
41
42
static_space(void)43 global uintM static_space (void) {
44 var uintM sum = 0;
45 /* space of symbol_tab: cf. macro for_all_constsyms */
46 sum += symbol_count * sizeof(symbol_);
47 /* space of subr_tab: cf. macro for_all_subrs */
48 #ifdef MAP_MEMORY_TABLES
49 sum += total_subr_count * sizeof(subr_t);
50 #else
51 {
52 var module_t* module; /* traverse modules */
53 for_modules(all_modules, {
54 if (module->initialized)
55 sum += *module->stab_size * sizeof(subr_t);
56 });
57 }
58 #endif
59 return sum;
60 }
61
62 global uintM used_space (void);
63 #ifdef SPVW_BLOCKS
64 #ifdef SPVW_MIXED_BLOCKS_OPPOSITE
used_space()65 global uintM used_space() {
66 #if !defined(GENERATIONAL_GC)
67 #define Heap_used_space(h) ((uintM)((h).pages.end - (h).pages.start))
68 return Heap_used_space(mem.varobjects) /* space for objects of variable length */
69 - heap_holes_space(&mem.varobjects) /* subtract heap holes */
70 + Heap_used_space(mem.conses); /* space for conses */
71 #else /* defined(GENERATIONAL_GC) */
72 return
73 (uintM)(mem.varobjects.heap_gen0_end - mem.varobjects.heap_gen0_start)
74 + (uintM)(mem.varobjects.heap_end - mem.varobjects.heap_gen1_start)
75 - heap_holes_space(&mem.varobjects)
76 + (uintM)(mem.conses.heap_gen1_end - mem.conses.heap_start)
77 + (uintM)(mem.conses.heap_gen0_end - mem.conses.heap_gen0_start);
78 #endif
79 }
80 #else
used_space()81 global uintM used_space() {
82 var uintM sum = 0;
83 #if !defined(GENERATIONAL_GC)
84 for_each_heap(heap, {
85 sum += heap->heap_end - heap->heap_start - heap_holes_space(heap);
86 });
87 #else /* defined(GENERATIONAL_GC) */
88 for_each_heap(heap, {
89 sum += (heap->heap_gen0_end - heap->heap_gen0_start)
90 + (heap->heap_end - heap->heap_gen1_start)
91 - heap_holes_space(heap);
92 });
93 #endif
94 return sum;
95 }
96 #endif
97 #endif
98 #ifdef SPVW_PAGES
99 #if 0
100 global uintM used_space() {
101 var uintM sum = 0;
102 for_each_page(page, { sum += page->page_end - page->page_start; });
103 return sum;
104 }
105 #else
106 /* the calculation of used_space() accesses each page once, which
107 can cause lots of paging, so the result is saved in mem.used_space. */
used_space()108 global uintM used_space() { return mem.used_space; }
109 #endif
110 #endif
111
112 global uintM free_space (void);
113 #ifdef SPVW_BLOCKS
114 #if defined(SPVW_MIXED_BLOCKS_OPPOSITE) && !defined(TRIVIALMAP_MEMORY) && !defined(GENERATIONAL_GC)
free_space()115 global uintM free_space() { /* space in the big gap */
116 return (mem.conses.heap_start-mem.varobjects.heap_end);
117 }
118 #else
free_space()119 global uintM free_space() {
120 return mem.total_room; /* space, that may be consumed until the next GC */
121 }
122 #endif
123 #endif
124 #ifdef SPVW_PAGES
125 #if 0
126 global uintM free_space() {
127 var uintM sum = 0;
128 for_each_page(page, { sum += page->page_room; });
129 return sum;
130 }
131 #else
132 /* the calculation of free_space() accesses each page once, which
133 can cause lots of paging, so the result is calculated with
134 help of mem.used_space. */
free_space()135 global uintM free_space() { return mem.total_space - mem.used_space; }
136 #endif
137 #endif
138
139 #ifdef SPVW_PAGES
recalc_space(bool check)140 local void recalc_space (bool check) {
141 var uintM sum_used = 0;
142 var uintM sum_free = 0;
143 for_each_page(page, {
144 sum_used += page->page_end - page->page_start;
145 sum_free += page->page_room;
146 });
147 if (check) {
148 if (!(mem.used_space == sum_used))
149 abort();
150 } else {
151 mem.used_space = sum_used;
152 }
153 mem.total_space = sum_used + sum_free;
154 }
155 #endif
156