4f1998513da86288ea78ee386f4c6e61233038e2
[mono.git] / mono / metadata / sgen-pinning-stats.c
1 enum {
2         PIN_TYPE_STACK,
3         PIN_TYPE_STATIC_DATA,
4         PIN_TYPE_OTHER,
5         PIN_TYPE_MAX
6 };
7
8 typedef struct _PinStatAddress PinStatAddress;
9 struct _PinStatAddress {
10         char *addr;
11         int pin_types;
12         PinStatAddress *left;
13         PinStatAddress *right;
14 };
15
16 static PinStatAddress *pin_stat_addresses = NULL;
17 static size_t pinned_byte_counts [PIN_TYPE_MAX];
18
19 static void
20 pin_stats_tree_free (PinStatAddress *node)
21 {
22         if (!node)
23                 return;
24         pin_stats_tree_free (node->left);
25         pin_stats_tree_free (node->right);
26         free_internal_mem (node, INTERNAL_MEM_STATISTICS);
27 }
28
29 static void
30 pin_stats_reset (void)
31 {
32         int i;
33         pin_stats_tree_free (pin_stat_addresses);
34         pin_stat_addresses = NULL;
35         for (i = 0; i < PIN_TYPE_MAX; ++i)
36                 pinned_byte_counts [i] = 0;
37 }
38
39 static void
40 pin_stats_register_address (char *addr, int pin_type)
41 {
42         PinStatAddress **node_ptr = &pin_stat_addresses;
43         PinStatAddress *node;
44         int pin_type_bit = 1 << pin_type;
45
46         while (*node_ptr) {
47                 node = *node_ptr;
48                 if (addr == node->addr) {
49                         node->pin_types |= pin_type_bit;
50                         return;
51                 }
52                 if (addr < node->addr)
53                         node_ptr = &node->left;
54                 else
55                         node_ptr = &node->right;
56         }
57
58         node = get_internal_mem (sizeof (PinStatAddress), INTERNAL_MEM_STATISTICS);
59         node->addr = addr;
60         node->pin_types = pin_type_bit;
61         node->left = node->right = NULL;
62
63         *node_ptr = node;
64 }
65
66 static void
67 pin_stats_count_object_from_tree (char *obj, size_t size, PinStatAddress *node, int *pin_types)
68 {
69         if (!node)
70                 return;
71         if (node->addr >= obj && node->addr < obj + size) {
72                 int i;
73                 for (i = 0; i < PIN_TYPE_MAX; ++i) {
74                         int pin_bit = 1 << i;
75                         if (!(*pin_types & pin_bit) && (node->pin_types & pin_bit)) {
76                                 pinned_byte_counts [i] += size;
77                                 *pin_types |= pin_bit;
78                         }
79                 }
80         }
81         if (obj < node->addr)
82                 pin_stats_count_object_from_tree (obj, size, node->left, pin_types);
83         if (obj + size - 1 > node->addr)
84                 pin_stats_count_object_from_tree (obj, size, node->right, pin_types);
85 }
86
87 static void
88 pin_stats_register_object (char *obj, size_t size)
89 {
90         int pin_types = 0;
91         pin_stats_count_object_from_tree (obj, size, pin_stat_addresses, &pin_types);
92 }