-
Notifications
You must be signed in to change notification settings - Fork 1
/
visualizer.h
executable file
·160 lines (137 loc) · 5.23 KB
/
visualizer.h
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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
#ifndef VISUALIZER_HEADER_GUARD
#define VISUALIZER_HEADER_GUARD
#include <stdlib.h>
#include <stdio.h>
#include <string.h> // for memset
#include "memlib.h"
#include "alloc_types.h"
// Heap Visualizer - visually display the state of the heap, as encoded
// in the heap metadata. This cannot help you if the metadata are wrong,
// and this should be used in conjunction with the heap checker.
// ** State enumerations ** //
// States of a cell in a small run
// We will represent filled with 'O', unfilled with '.', and never with '-'
#define FILLED 0
#define UNFILLED 1
#define NEVER 2
// ** Prototypes ** //
void visualize_large_run(arena_chunk_hdr* this_chunk, size_t this_page);
void visualize_small_run(arena_chunk_hdr* this_chunk, size_t this_page);
void visualize_chunk(arena_chunk_hdr* this_chunk);
inline size_t small_address_to_cell(small_run_hdr* this_hdr, size_t* this_cell, size_t object_size);
/*************
* Functions *
*************/
void visualize_arena(arena_hdr* this_arena) {
// Visualizes only the first chunk, because I said so.
// TODO: Visualize more chunks.
//visualize_chunk((arena_chunk_hdr*)(this_arena->deepest));
visualize_chunk((arena_chunk_hdr*)((byte*)this_arena + ARENA_HDR_SIZE));
}
void visualize_chunk(arena_chunk_hdr* this_chunk) {
printf("\n\n** Visualizing chunk at heap point %p **\n", this_chunk);
// To compute position in heap, we get our delta to the true heap bottom, and divide
// by the size of chunks.
printf("This is %zu chunk(s) up from the bottom of the heap.\n",
(long)((byte*)this_chunk - (byte*)mem_heap_lo())/ FINAL_CHUNK_SIZE);
printf("It also has %zu free pages.\n", this_chunk->num_pages_available);
printf("Page map:\n");
// Iterate over the page map, doing work
size_t ii;
for (ii=0 ; ii < this_chunk->num_pages_allocated ; ii++) {
// Print page number
printf(" % 4zu : ", ii);
switch (this_chunk->page_map[ii]) {
// Print trivial cases
case HEADER:
printf("Arena chunk metadata.\n");
break;
case FREE:
printf("Unallocated page.\n");
break;
case SMALL_RUN_FRAGMENT:
printf("... small run continues ...\n");
break;
case LARGE_RUN_FRAGMENT:
printf("... large run continues ...\n");
break;
// Nontrivial case - header of a large run.
case LARGE_RUN_HEADER:
visualize_large_run(this_chunk, ii);
break;
// Very nontrivial case - header of a small run
case SMALL_RUN_HEADER:
visualize_small_run(this_chunk, ii);
break;
default:
printf("This value does not make sense: %d.\n", this_chunk->page_map[ii]);
break;
}
}
printf("\n");
}
void visualize_large_run(arena_chunk_hdr* this_chunk, size_t this_page) {
// Extract run location, convert to run header, analyze
large_run_hdr* this_hdr = (large_run_hdr *) (this_chunk->get_page_location((size_t)this_page));
printf("Large run begins, spanning %zu pages.\n",
(this_hdr->num_pages));
}
void visualize_small_run(arena_chunk_hdr* this_chunk, size_t this_page) {
// Extract location etc.
small_run_hdr* this_hdr = (small_run_hdr *) (this_chunk->get_page_location((size_t)this_page));
size_t num_cells = this_hdr->parent->available_registrations;
size_t object_size = this_hdr->parent->object_size;
printf("Small run begins, containing %zu slots of size %zu bytes.\n",
(num_cells),
(object_size));
printf(" In total, this run spans %zu bytes.\n",
(this_hdr->parent->run_length));
printf(" Cells are mapped as follows:");
// Now to visualize the run. Start by assigning every cell FILLED.
uint8_t cells[num_cells];
int ii;
memset(&cells, FILLED, num_cells * sizeof(uint8_t));
// Then mark everything at or after the NEXT pointer NEVER
if (this_hdr->next != NULL) {
size_t trailing_free_cell_start = small_address_to_cell(this_hdr, this_hdr->next, object_size);
for (ii = trailing_free_cell_start ; ii < num_cells ; ii++)
cells[ii] = NEVER;
}
// Then follow the free list, marking those cells UNFILLED
size_t* follow_free = this_hdr->free_list;
size_t follow_free_cell;
while (follow_free != NULL) {
follow_free_cell = small_address_to_cell(this_hdr, follow_free, object_size);
cells[follow_free_cell] = UNFILLED;
// Since we're following the free list, we know the contents of a cell is
// a pointer to the next free cell or to NULL, and can follow it down
follow_free = (size_t*)(*follow_free);
}
// Print the visualization, up to 50 cells per line, using a single
// symbol to represent the state of each cell
for (ii = 0 ; ii < num_cells ; ii++) {
// Linebreak every 64 chars
if (ii%64 == 0) {
printf("\n ");
}
switch (cells[ii]) {
case FILLED:
printf("O");
break;
case UNFILLED:
printf(".");
break;
case NEVER:
printf("-");
break;
}
}
printf("\n");
}
inline size_t small_address_to_cell(small_run_hdr* this_hdr, size_t* this_cell, size_t object_size) {
// Given an address in a header, determine what cell number that is in the cell map
// Direct address subtraction is fun!
size_t delta = (size_t)((byte*)this_cell - (byte*)this_hdr) - SMALL_RUN_HDR_SIZE;
return (size_t)(delta / object_size);
}
#endif /* VISUALIZER_HEADER_GUARD */