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