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