// // m3_code.c // // Created by Steven Massey on 4/19/19. // Copyright © 2019 Steven Massey. All rights reserved. // #include "m3_code.h" #include "m3_env.h" //--------------------------------------------------------------------------------------------------------------------------------- IM3CodePage NewCodePage (IM3Runtime i_runtime, u32 i_minNumLines) { IM3CodePage page; u32 pageSize = sizeof (M3CodePageHeader) + sizeof (code_t) * i_minNumLines; pageSize = (pageSize + (d_m3CodePageAlignSize-1)) & ~(d_m3CodePageAlignSize-1); // align page = (IM3CodePage)m3_Malloc ("M3CodePage", pageSize); if (page) { page->info.sequence = ++i_runtime->newCodePageSequence; page->info.numLines = (pageSize - sizeof (M3CodePageHeader)) / sizeof (code_t); #if d_m3RecordBacktraces u32 pageSizeBt = sizeof (M3CodeMappingPage) + sizeof (M3CodeMapEntry) * page->info.numLines; page->info.mapping = (M3CodeMappingPage *)m3_Malloc ("M3CodeMappingPage", pageSizeBt); if (page->info.mapping) { page->info.mapping->size = 0; page->info.mapping->capacity = page->info.numLines; } else { m3_Free (page); return NULL; } page->info.mapping->basePC = GetPageStartPC(page); #endif // d_m3RecordBacktraces m3log (runtime, "new page: %p; seq: %d; bytes: %d; lines: %d", GetPagePC (page), page->info.sequence, pageSize, page->info.numLines); } return page; } void FreeCodePages (IM3CodePage * io_list) { IM3CodePage page = * io_list; while (page) { m3log (code, "free page: %d; %p; util: %3.1f%%", page->info.sequence, page, 100. * page->info.lineIndex / page->info.numLines); IM3CodePage next = page->info.next; #if d_m3RecordBacktraces m3_Free (page->info.mapping); #endif // d_m3RecordBacktraces m3_Free (page); page = next; } * io_list = NULL; } u32 NumFreeLines (IM3CodePage i_page) { d_m3Assert (i_page->info.lineIndex <= i_page->info.numLines); return i_page->info.numLines - i_page->info.lineIndex; } void EmitWord_impl (IM3CodePage i_page, void * i_word) { d_m3Assert (i_page->info.lineIndex+1 <= i_page->info.numLines); i_page->code [i_page->info.lineIndex++] = i_word; } void EmitWord32 (IM3CodePage i_page, const u32 i_word) { d_m3Assert (i_page->info.lineIndex+1 <= i_page->info.numLines); * ((u32 *) & i_page->code [i_page->info.lineIndex++]) = i_word; } void EmitWord64 (IM3CodePage i_page, const u64 i_word) { #if M3_SIZEOF_PTR == 4 d_m3Assert (i_page->info.lineIndex+2 <= i_page->info.numLines); * ((u64 *) & i_page->code [i_page->info.lineIndex]) = i_word; i_page->info.lineIndex += 2; #else d_m3Assert (i_page->info.lineIndex+1 <= i_page->info.numLines); * ((u64 *) & i_page->code [i_page->info.lineIndex]) = i_word; i_page->info.lineIndex += 1; #endif } #if d_m3RecordBacktraces void EmitMappingEntry (IM3CodePage i_page, u32 i_moduleOffset) { M3CodeMappingPage * page = i_page->info.mapping; d_m3Assert (page->size < page->capacity); M3CodeMapEntry * entry = & page->entries[page->size++]; pc_t pc = GetPagePC (i_page); entry->pcOffset = pc - page->basePC; entry->moduleOffset = i_moduleOffset; } #endif // d_m3RecordBacktraces pc_t GetPageStartPC (IM3CodePage i_page) { return & i_page->code [0]; } pc_t GetPagePC (IM3CodePage i_page) { if (i_page) return & i_page->code [i_page->info.lineIndex]; else return NULL; } void PushCodePage (IM3CodePage * i_list, IM3CodePage i_codePage) { IM3CodePage next = * i_list; i_codePage->info.next = next; * i_list = i_codePage; } IM3CodePage PopCodePage (IM3CodePage * i_list) { IM3CodePage page = * i_list; * i_list = page->info.next; page->info.next = NULL; return page; } u32 FindCodePageEnd (IM3CodePage i_list, IM3CodePage * o_end) { u32 numPages = 0; * o_end = NULL; while (i_list) { * o_end = i_list; ++numPages; i_list = i_list->info.next; } return numPages; } u32 CountCodePages (IM3CodePage i_list) { IM3CodePage unused; return FindCodePageEnd (i_list, & unused); } IM3CodePage GetEndCodePage (IM3CodePage i_list) { IM3CodePage end; FindCodePageEnd (i_list, & end); return end; } #if d_m3RecordBacktraces bool ContainsPC (IM3CodePage i_page, pc_t i_pc) { return GetPageStartPC (i_page) <= i_pc && i_pc < GetPagePC (i_page); } bool MapPCToOffset (IM3CodePage i_page, pc_t i_pc, u32 * o_moduleOffset) { M3CodeMappingPage * mapping = i_page->info.mapping; u32 pcOffset = i_pc - mapping->basePC; u32 left = 0; u32 right = mapping->size; while (left < right) { u32 mid = left + (right - left) / 2; if (mapping->entries[mid].pcOffset < pcOffset) { left = mid + 1; } else if (mapping->entries[mid].pcOffset > pcOffset) { right = mid; } else { *o_moduleOffset = mapping->entries[mid].moduleOffset; return true; } } // Getting here means left is now one more than the element we want. if (left > 0) { left--; *o_moduleOffset = mapping->entries[left].moduleOffset; return true; } else return false; } #endif // d_m3RecordBacktraces //---------------------------------------------------------------------------------------------------------------------------------