free on application exit on debug builds

This commit is contained in:
nakst 2021-09-04 13:25:24 +01:00
parent 6bdb99a79b
commit c4789093ac
9 changed files with 115 additions and 24 deletions

View File

@ -541,6 +541,39 @@ void _start() {
Instance *instance = message->instanceDestroy.instance;
InstanceDestroy(instance);
instances.FindAndDeleteSwap(instance, true);
} else if (message->type == ES_MSG_APPLICATION_EXIT) {
#ifdef DEBUG_BUILD
for (uintptr_t i = 0; i < drives.Length(); i++) {
EsHeapFree(drives[i].prefix);
}
for (uintptr_t i = 0; i < bookmarks.Length(); i++) {
StringDestroy(&bookmarks[i]);
}
for (uintptr_t i = 0; i < thumbnailCache.Count(); i++) {
EsHeapFree(thumbnailCache[i].bits);
}
for (uintptr_t i = 0; i < loadedFolders.Length(); i++) {
FolderDestroy(loadedFolders[i]);
}
EsAssert(!instances.Length());
EsHandleClose(nonBlockingTaskWorkAvailable);
EsHeapFree(fileTypesBuffer.out);
bookmarks.Free();
drives.Free();
folderViewSettings.Free();
foldersWithNoAttachedInstances.Free();
instances.Free();
knownFileTypes.Free();
knownFileTypesByExtension.Free();
loadedFolders.Free();
nonBlockingTasks.Free();
thumbnailCache.Free();
#endif
} else if (message->type == ES_MSG_REGISTER_FILE_SYSTEM) {
DriveAdd(message->registerFileSystem.mountPoint->prefix, message->registerFileSystem.mountPoint->prefixBytes);
} else if (message->type == ES_MSG_UNREGISTER_FILE_SYSTEM) {

View File

@ -12,6 +12,7 @@ struct FileType {
Array<FileType> knownFileTypes;
HashStore<char, uintptr_t /* index into knownFileTypes */> knownFileTypesByExtension;
EsBuffer fileTypesBuffer;
void AddKnownFileTypes() {
#define ADD_FILE_TYPE(_extension, _name, _iconID) \
@ -22,9 +23,7 @@ void AddKnownFileTypes() {
type.extension = (char *) _extension; \
type.extensionBytes = EsCStringLength(_extension); \
type.iconID = _iconID; \
uintptr_t index = knownFileTypes.Length(); \
knownFileTypes.Add(type); \
*knownFileTypesByExtension.Put(_extension, EsCStringLength(_extension)) = index; \
}
#define KNOWN_FILE_TYPE_DIRECTORY (0)
@ -42,9 +41,9 @@ void AddKnownFileTypes() {
#define KNOWN_FILE_TYPE_DRIVES_PAGE (6)
ADD_FILE_TYPE("", interfaceString_FileManagerDrivesPage, ES_ICON_COMPUTER_LAPTOP);
EsBuffer buffer = { .canGrow = true };
EsSystemConfigurationReadFileTypes(&buffer);
EsINIState s = { .buffer = (char *) buffer.out, .bytes = buffer.bytes };
fileTypesBuffer = { .canGrow = true };
EsSystemConfigurationReadFileTypes(&fileTypesBuffer);
EsINIState s = { .buffer = (char *) fileTypesBuffer.out, .bytes = fileTypesBuffer.bytes };
FileType type = {};
while (EsINIParse(&s)) {

View File

@ -688,6 +688,8 @@ APIInstance *InstanceSetup(EsInstance *instance) {
}
EsInstance *_EsInstanceCreate(size_t bytes, EsMessage *message, const char *applicationName, ptrdiff_t applicationNameBytes) {
if (!api.startupInformation->isDesktop) HeapPrintAllocatedRegions(&heap);
if (applicationNameBytes == -1) {
applicationNameBytes = EsCStringLength(applicationName);
}
@ -803,14 +805,19 @@ EsMessage *EsMessageReceive() {
FileStoreCloseHandle(message.message.instanceSave.file);
} else if (message.message.type == ES_MSG_APPLICATION_EXIT) {
#ifdef DEBUG_BUILD
GlyphCacheFree();
FreeUnusedStyles();
FontDatabaseFree();
FreeUnusedStyles(true /* include permanent styles */);
theming.loadedStyles.Free();
SystemConfigurationUnload();
api.mountPoints.Free();
api.postBox.Free();
api.timers.Free();
EsPrint("ES_MSG_APPLICATION_EXIT - Heap allocation count: %d.\n", heap.allocationsCount);
gui.animatingElements.Free();
gui.accessKeys.entries.Free();
gui.allWindows.Free();
calculator.Free();
HashTableFree(&gui.keyboardShortcutNames, false);
EsPrint("ES_MSG_APPLICATION_EXIT - Heap allocation count: %d (%d from malloc).\n", heap.allocationsCount, mallocCount);
#endif
EsProcessTerminateCurrent();
} else if (message.message.type == ES_MSG_INSTANCE_DESTROY) {
@ -843,6 +850,8 @@ EsMessage *EsMessageReceive() {
if (instance->fileStore) FileStoreCloseHandle(instance->fileStore);
EsHeapFree(instance);
EsHeapFree(message.message.instanceDestroy.instance);
if (!api.startupInformation->isDesktop) HeapPrintAllocatedRegions(&heap);
} else if (message.message.type == ES_MSG_UNREGISTER_FILE_SYSTEM) {
for (uintptr_t i = 0; i < api.mountPoints.Length(); i++) {
if (api.mountPoints[i].information.id == message.message.unregisterFileSystem.id) {

View File

@ -6822,7 +6822,7 @@ void UIProcessWindowManagerMessage(EsWindow *window, EsMessage *message, Process
// Free any unused styles.
FreeUnusedStyles();
FreeUnusedStyles(false);
// Finish update.

View File

@ -129,15 +129,6 @@ GlyphCacheEntry *LookupGlyphCacheEntry(GlyphCacheKey key) {
}
}
void GlyphCacheFree() {
while (fontManagement.glyphCacheLRU.count) {
GlyphCacheFreeEntry();
}
EsAssert(fontManagement.glyphCache.Count() == 0);
fontManagement.glyphCache.Free();
}
// --------------------------------- Font renderer.
bool FontLoad(Font *font, const void *data, size_t dataBytes) {
@ -754,6 +745,50 @@ Font FontGet(EsFont key) {
return font;
}
void FontDatabaseFree() {
while (fontManagement.glyphCacheLRU.count) {
GlyphCacheFreeEntry();
}
for (uintptr_t i = 0; i < fontManagement.loaded.Count(); i++) {
// TODO Unmap file store data.
Font font = fontManagement.loaded[i];
#ifdef USE_HARFBUZZ
hb_font_destroy(font.hb);
#endif
#ifdef USE_FREETYPE
FT_Done_Face(font.ft);
#endif
}
for (uintptr_t i = 0; i < fontManagement.database.Length(); i++) {
FontDatabaseEntry *entry = &fontManagement.database[i];
for (uintptr_t j = 0; j < sizeof(entry->files) / sizeof(entry->files[0]); j++) {
if (entry->files[j]) {
FileStoreCloseHandle(entry->files[j]);
}
}
}
EsAssert(fontManagement.glyphCache.Count() == 0);
EsAssert(fontManagement.glyphCacheBytes == 0);
EsHeapFree(fontManagement.sansName);
EsHeapFree(fontManagement.serifName);
EsHeapFree(fontManagement.monospacedName);
EsHeapFree(fontManagement.fallbackName);
fontManagement.glyphCache.Free();
fontManagement.substitutions.Free();
fontManagement.database.Free();
fontManagement.loaded.Free();
#ifdef USE_FREETYPE
FT_Done_FreeType(fontManagement.freetypeLibrary);
#endif
}
// --------------------------------- Blitting rendered glyphs.
inline static void DrawStringPixel(int oX, int oY, void *bitmap, size_t stride, uint32_t textColor,

View File

@ -1932,10 +1932,11 @@ UIStyleKey MakeStyleKey(const EsStyle *style, uint16_t stateFlags) {
return { .part = (uintptr_t) style, .stateFlags = stateFlags };
}
void FreeUnusedStyles() {
void FreeUnusedStyles(bool includePermanentStyles) {
for (uintptr_t i = 0; i < theming.loadedStyles.Count(); i++) {
if (theming.loadedStyles[i]->referenceCount == 0) {
UIStyle *style = theming.loadedStyles[i];
UIStyle *style = theming.loadedStyles[i];
if (style->referenceCount == 0 || (style->referenceCount == -1 && includePermanentStyles)) {
UIStyleKey key = theming.loadedStyles.KeyAtIndex(i);
theming.loadedStyles.Delete(&key);
EsHeapFree(style);

View File

@ -1887,21 +1887,30 @@ int EsCRTabs(int n) {
}
#ifndef KERNEL
volatile static size_t mallocCount;
void *EsCRTmalloc(size_t size) {
void *x = EsHeapAllocate(size, false);
if (x) __sync_fetch_and_add(&mallocCount, 1);
return x;
}
void *EsCRTcalloc(size_t num, size_t size) {
return EsHeapAllocate(num * size, true);
void *x = EsHeapAllocate(num * size, true);
if (x) __sync_fetch_and_add(&mallocCount, 1);
return x;
}
void EsCRTfree(void *ptr) {
if (ptr) __sync_fetch_and_sub(&mallocCount, 1);
EsHeapFree(ptr);
}
void *EsCRTrealloc(void *ptr, size_t size) {
return EsHeapReallocate(ptr, size, false);
// EsHeapReallocate handles this logic, but do it ourselves to keep mallocCount correct.
if (!ptr) return EsCRTmalloc(size);
else if (!size) return EsCRTfree(ptr), nullptr;
else return EsHeapReallocate(ptr, size, false);
}
#else
void *EsHeapAllocate(size_t size, bool zeroMemory, EsHeap *heap);

View File

@ -1,6 +1,6 @@
// TODO Rewrite. Make faster!
// TODO EsHeapAllocateNearby.
// TODO Larger heap blocks. Due to alignment, we can shift offset values a few bits right.
// TODO Larger heap blocks.
#ifdef DEBUG_BUILD
#define MAYBE_VALIDATE_HEAP() HeapValidate(&heap)

View File

@ -1815,6 +1815,11 @@ namespace Calculator {
#undef FUNCTION1
#undef FUNCTION2
}
void Free() {
FreeAll();
builtins.Free();
}
};
};