orca/ext/wasm3/source/m3_code.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
//---------------------------------------------------------------------------------------------------------------------------------