1 //
2 // m3_code.c
3 //
4 // Created by Steven Massey on 4/19/19.
5 // Copyright © 2019 Steven Massey. All rights reserved.
6 //
7
8 #include "m3_code.h"
9
10
11 //---------------------------------------------------------------------------------------------------------------------------------
12
13
NewCodePage(u32 i_minNumLines)14 IM3CodePage NewCodePage (u32 i_minNumLines)
15 {
16 static u32 s_sequence = 0;
17
18 IM3CodePage page;
19
20 u32 pageSize = sizeof (M3CodePageHeader) + sizeof (code_t) * i_minNumLines;
21
22 pageSize = (pageSize + (d_m3CodePageAlignSize-1)) & ~(d_m3CodePageAlignSize-1); // align
23 page = (IM3CodePage)m3_Malloc (pageSize);
24
25 if (page)
26 {
27 page->info.sequence = ++s_sequence;
28 page->info.numLines = (pageSize - sizeof (M3CodePageHeader)) / sizeof (code_t);
29
30 #if d_m3RecordBacktraces
31 u32 pageSizeBt = sizeof (M3CodeMappingPage) + sizeof (M3CodeMapEntry) * page->info.numLines;
32 page->info.mapping = (M3CodeMappingPage *)m3_Malloc (pageSizeBt);
33
34 if (page->info.mapping)
35 {
36 page->info.mapping->size = 0;
37 page->info.mapping->capacity = page->info.numLines;
38 }
39 else
40 {
41 m3_Free (page);
42 return NULL;
43 }
44 page->info.mapping->basePC = GetPageStartPC(page);
45 #endif // d_m3RecordBacktraces
46
47 m3log (runtime, "new page: %p; seq: %d; bytes: %d; lines: %d", GetPagePC (page), page->info.sequence, pageSize, page->info.numLines);
48 }
49
50 return page;
51 }
52
53
FreeCodePages(IM3CodePage * io_list)54 void FreeCodePages (IM3CodePage * io_list)
55 {
56 IM3CodePage page = * io_list;
57
58 while (page)
59 {
60 m3log (code, "free page: %d; %p; util: %3.1f%%", page->info.sequence, page, 100. * page->info.lineIndex / page->info.numLines);
61
62 IM3CodePage next = page->info.next;
63 #if d_m3RecordBacktraces
64 m3_Free (page->info.mapping);
65 #endif // d_m3RecordBacktraces
66 m3_Free (page);
67 page = next;
68 }
69
70 * io_list = NULL;
71 }
72
73
NumFreeLines(IM3CodePage i_page)74 u32 NumFreeLines (IM3CodePage i_page)
75 {
76 d_m3Assert (i_page->info.lineIndex <= i_page->info.numLines);
77
78 return i_page->info.numLines - i_page->info.lineIndex;
79 }
80
81
EmitWord_impl(IM3CodePage i_page,void * i_word)82 void EmitWord_impl (IM3CodePage i_page, void * i_word)
83 { d_m3Assert (i_page->info.lineIndex+1 <= i_page->info.numLines);
84 i_page->code [i_page->info.lineIndex++] = i_word;
85 }
86
EmitWord32(IM3CodePage i_page,const u32 i_word)87 void EmitWord32 (IM3CodePage i_page, const u32 i_word)
88 { d_m3Assert (i_page->info.lineIndex+1 <= i_page->info.numLines);
89 * ((u32 *) & i_page->code [i_page->info.lineIndex++]) = i_word;
90 }
91
EmitWord64(IM3CodePage i_page,const u64 i_word)92 void EmitWord64 (IM3CodePage i_page, const u64 i_word)
93 {
94 #if M3_SIZEOF_PTR == 4
95 d_m3Assert (i_page->info.lineIndex+2 <= i_page->info.numLines);
96 * ((u64 *) & i_page->code [i_page->info.lineIndex]) = i_word;
97 i_page->info.lineIndex += 2;
98 #else
99 d_m3Assert (i_page->info.lineIndex+1 <= i_page->info.numLines);
100 * ((u64 *) & i_page->code [i_page->info.lineIndex]) = i_word;
101 i_page->info.lineIndex += 1;
102 #endif
103 }
104
105
106 #if d_m3RecordBacktraces
EmitMappingEntry(IM3CodePage i_page,u32 i_moduleOffset)107 void EmitMappingEntry (IM3CodePage i_page, u32 i_moduleOffset)
108 {
109 M3CodeMappingPage * page = i_page->info.mapping;
110 d_m3Assert (page->size < page->capacity);
111
112 M3CodeMapEntry * entry = & page->entries[page->size++];
113 pc_t pc = GetPagePC (i_page);
114
115 entry->pcOffset = pc - page->basePC;
116 entry->moduleOffset = i_moduleOffset;
117 }
118 #endif // d_m3RecordBacktraces
119
GetPageStartPC(IM3CodePage i_page)120 pc_t GetPageStartPC (IM3CodePage i_page)
121 {
122 return & i_page->code [0];
123 }
124
125
GetPagePC(IM3CodePage i_page)126 pc_t GetPagePC (IM3CodePage i_page)
127 {
128 if (i_page)
129 return & i_page->code [i_page->info.lineIndex];
130 else
131 return NULL;
132 }
133
134
PushCodePage(IM3CodePage * i_list,IM3CodePage i_codePage)135 void PushCodePage (IM3CodePage * i_list, IM3CodePage i_codePage)
136 {
137 IM3CodePage next = * i_list;
138 i_codePage->info.next = next;
139 * i_list = i_codePage;
140 }
141
142
PopCodePage(IM3CodePage * i_list)143 IM3CodePage PopCodePage (IM3CodePage * i_list)
144 {
145 IM3CodePage page = * i_list;
146 * i_list = page->info.next;
147 page->info.next = NULL;
148
149 return page;
150 }
151
152
153
FindCodePageEnd(IM3CodePage i_list,IM3CodePage * o_end)154 u32 FindCodePageEnd (IM3CodePage i_list, IM3CodePage * o_end)
155 {
156 u32 numPages = 0;
157 * o_end = NULL;
158
159 while (i_list)
160 {
161 * o_end = i_list;
162 ++numPages;
163 i_list = i_list->info.next;
164 }
165
166 return numPages;
167 }
168
169
CountCodePages(IM3CodePage i_list)170 u32 CountCodePages (IM3CodePage i_list)
171 {
172 IM3CodePage unused;
173 return FindCodePageEnd (i_list, & unused);
174 }
175
176
GetEndCodePage(IM3CodePage i_list)177 IM3CodePage GetEndCodePage (IM3CodePage i_list)
178 {
179 IM3CodePage end;
180 FindCodePageEnd (i_list, & end);
181
182 return end;
183 }
184
185 #if d_m3RecordBacktraces
ContainsPC(IM3CodePage i_page,pc_t i_pc)186 bool ContainsPC (IM3CodePage i_page, pc_t i_pc)
187 {
188 return GetPageStartPC (i_page) <= i_pc && i_pc < GetPagePC (i_page);
189 }
190
191
MapPCToOffset(IM3CodePage i_page,pc_t i_pc,u32 * o_moduleOffset)192 bool MapPCToOffset (IM3CodePage i_page, pc_t i_pc, u32 * o_moduleOffset)
193 {
194 M3CodeMappingPage * mapping = i_page->info.mapping;
195
196 u32 pcOffset = i_pc - mapping->basePC;
197
198 u32 left = 0;
199 u32 right = mapping->size;
200
201 while (left < right)
202 {
203 u32 mid = left + (right - left) / 2;
204
205 if (mapping->entries[mid].pcOffset < pcOffset)
206 {
207 left = mid + 1;
208 }
209 else if (mapping->entries[mid].pcOffset > pcOffset)
210 {
211 right = mid;
212 }
213 else
214 {
215 *o_moduleOffset = mapping->entries[mid].moduleOffset;
216 return true;
217 }
218 }
219
220 // Getting here means left is now one more than the element we want.
221 if (left > 0)
222 {
223 left--;
224 *o_moduleOffset = mapping->entries[left].moduleOffset;
225 return true;
226 }
227 else return false;
228 }
229 #endif // d_m3RecordBacktraces
230
231 //---------------------------------------------------------------------------------------------------------------------------------
232
233
234