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; Instance *instance = message->instanceDestroy.instance;
InstanceDestroy(instance); InstanceDestroy(instance);
instances.FindAndDeleteSwap(instance, true); 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) { } else if (message->type == ES_MSG_REGISTER_FILE_SYSTEM) {
DriveAdd(message->registerFileSystem.mountPoint->prefix, message->registerFileSystem.mountPoint->prefixBytes); DriveAdd(message->registerFileSystem.mountPoint->prefix, message->registerFileSystem.mountPoint->prefixBytes);
} else if (message->type == ES_MSG_UNREGISTER_FILE_SYSTEM) { } else if (message->type == ES_MSG_UNREGISTER_FILE_SYSTEM) {

View File

@ -12,6 +12,7 @@ struct FileType {
Array<FileType> knownFileTypes; Array<FileType> knownFileTypes;
HashStore<char, uintptr_t /* index into knownFileTypes */> knownFileTypesByExtension; HashStore<char, uintptr_t /* index into knownFileTypes */> knownFileTypesByExtension;
EsBuffer fileTypesBuffer;
void AddKnownFileTypes() { void AddKnownFileTypes() {
#define ADD_FILE_TYPE(_extension, _name, _iconID) \ #define ADD_FILE_TYPE(_extension, _name, _iconID) \
@ -22,9 +23,7 @@ void AddKnownFileTypes() {
type.extension = (char *) _extension; \ type.extension = (char *) _extension; \
type.extensionBytes = EsCStringLength(_extension); \ type.extensionBytes = EsCStringLength(_extension); \
type.iconID = _iconID; \ type.iconID = _iconID; \
uintptr_t index = knownFileTypes.Length(); \
knownFileTypes.Add(type); \ knownFileTypes.Add(type); \
*knownFileTypesByExtension.Put(_extension, EsCStringLength(_extension)) = index; \
} }
#define KNOWN_FILE_TYPE_DIRECTORY (0) #define KNOWN_FILE_TYPE_DIRECTORY (0)
@ -42,9 +41,9 @@ void AddKnownFileTypes() {
#define KNOWN_FILE_TYPE_DRIVES_PAGE (6) #define KNOWN_FILE_TYPE_DRIVES_PAGE (6)
ADD_FILE_TYPE("", interfaceString_FileManagerDrivesPage, ES_ICON_COMPUTER_LAPTOP); ADD_FILE_TYPE("", interfaceString_FileManagerDrivesPage, ES_ICON_COMPUTER_LAPTOP);
EsBuffer buffer = { .canGrow = true }; fileTypesBuffer = { .canGrow = true };
EsSystemConfigurationReadFileTypes(&buffer); EsSystemConfigurationReadFileTypes(&fileTypesBuffer);
EsINIState s = { .buffer = (char *) buffer.out, .bytes = buffer.bytes }; EsINIState s = { .buffer = (char *) fileTypesBuffer.out, .bytes = fileTypesBuffer.bytes };
FileType type = {}; FileType type = {};
while (EsINIParse(&s)) { 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) { EsInstance *_EsInstanceCreate(size_t bytes, EsMessage *message, const char *applicationName, ptrdiff_t applicationNameBytes) {
if (!api.startupInformation->isDesktop) HeapPrintAllocatedRegions(&heap);
if (applicationNameBytes == -1) { if (applicationNameBytes == -1) {
applicationNameBytes = EsCStringLength(applicationName); applicationNameBytes = EsCStringLength(applicationName);
} }
@ -803,14 +805,19 @@ EsMessage *EsMessageReceive() {
FileStoreCloseHandle(message.message.instanceSave.file); FileStoreCloseHandle(message.message.instanceSave.file);
} else if (message.message.type == ES_MSG_APPLICATION_EXIT) { } else if (message.message.type == ES_MSG_APPLICATION_EXIT) {
#ifdef DEBUG_BUILD #ifdef DEBUG_BUILD
GlyphCacheFree(); FontDatabaseFree();
FreeUnusedStyles(); FreeUnusedStyles(true /* include permanent styles */);
theming.loadedStyles.Free(); theming.loadedStyles.Free();
SystemConfigurationUnload(); SystemConfigurationUnload();
api.mountPoints.Free(); api.mountPoints.Free();
api.postBox.Free(); api.postBox.Free();
api.timers.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 #endif
EsProcessTerminateCurrent(); EsProcessTerminateCurrent();
} else if (message.message.type == ES_MSG_INSTANCE_DESTROY) { } else if (message.message.type == ES_MSG_INSTANCE_DESTROY) {
@ -843,6 +850,8 @@ EsMessage *EsMessageReceive() {
if (instance->fileStore) FileStoreCloseHandle(instance->fileStore); if (instance->fileStore) FileStoreCloseHandle(instance->fileStore);
EsHeapFree(instance); EsHeapFree(instance);
EsHeapFree(message.message.instanceDestroy.instance); EsHeapFree(message.message.instanceDestroy.instance);
if (!api.startupInformation->isDesktop) HeapPrintAllocatedRegions(&heap);
} else if (message.message.type == ES_MSG_UNREGISTER_FILE_SYSTEM) { } else if (message.message.type == ES_MSG_UNREGISTER_FILE_SYSTEM) {
for (uintptr_t i = 0; i < api.mountPoints.Length(); i++) { for (uintptr_t i = 0; i < api.mountPoints.Length(); i++) {
if (api.mountPoints[i].information.id == message.message.unregisterFileSystem.id) { 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. // Free any unused styles.
FreeUnusedStyles(); FreeUnusedStyles(false);
// Finish update. // 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. // --------------------------------- Font renderer.
bool FontLoad(Font *font, const void *data, size_t dataBytes) { bool FontLoad(Font *font, const void *data, size_t dataBytes) {
@ -754,6 +745,50 @@ Font FontGet(EsFont key) {
return font; 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. // --------------------------------- Blitting rendered glyphs.
inline static void DrawStringPixel(int oX, int oY, void *bitmap, size_t stride, uint32_t textColor, 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 }; return { .part = (uintptr_t) style, .stateFlags = stateFlags };
} }
void FreeUnusedStyles() { void FreeUnusedStyles(bool includePermanentStyles) {
for (uintptr_t i = 0; i < theming.loadedStyles.Count(); i++) { 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); UIStyleKey key = theming.loadedStyles.KeyAtIndex(i);
theming.loadedStyles.Delete(&key); theming.loadedStyles.Delete(&key);
EsHeapFree(style); EsHeapFree(style);

View File

@ -1887,21 +1887,30 @@ int EsCRTabs(int n) {
} }
#ifndef KERNEL #ifndef KERNEL
volatile static size_t mallocCount;
void *EsCRTmalloc(size_t size) { void *EsCRTmalloc(size_t size) {
void *x = EsHeapAllocate(size, false); void *x = EsHeapAllocate(size, false);
if (x) __sync_fetch_and_add(&mallocCount, 1);
return x; return x;
} }
void *EsCRTcalloc(size_t num, size_t size) { 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) { void EsCRTfree(void *ptr) {
if (ptr) __sync_fetch_and_sub(&mallocCount, 1);
EsHeapFree(ptr); EsHeapFree(ptr);
} }
void *EsCRTrealloc(void *ptr, size_t size) { 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 #else
void *EsHeapAllocate(size_t size, bool zeroMemory, EsHeap *heap); void *EsHeapAllocate(size_t size, bool zeroMemory, EsHeap *heap);

View File

@ -1,6 +1,6 @@
// TODO Rewrite. Make faster! // TODO Rewrite. Make faster!
// TODO EsHeapAllocateNearby. // 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 #ifdef DEBUG_BUILD
#define MAYBE_VALIDATE_HEAP() HeapValidate(&heap) #define MAYBE_VALIDATE_HEAP() HeapValidate(&heap)

View File

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