232 lines
5.8 KiB
C
232 lines
5.8 KiB
C
|
//
|
||
|
// 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
|
||
|
|
||
|
//---------------------------------------------------------------------------------------------------------------------------------
|
||
|
|
||
|
|