diff --git a/CMakeLists.txt b/CMakeLists.txt index a6ff8346d..9f897936b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -73,6 +73,13 @@ if (WIN32 OR MINGW) add_definitions(-D_WIN32_WINNT=0x601) endif() +if(MSVC) + # Override memory allocations to use mimalloc + add_definitions(/FI"${CMAKE_SOURCE_DIR}/libraries/mimalloc/include/mimalloc-override.h") + # Use static C runtime, necessary for mimalloc and also means matching C runtiume doesn't need to be on users box + set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$,$>:Debug>") +endif() + if (MSVC) # Disable RTTI diff --git a/cmake/Emscripten.cmake b/cmake/Emscripten.cmake index 7c3790624..ddca97f9a 100644 --- a/cmake/Emscripten.cmake +++ b/cmake/Emscripten.cmake @@ -6,7 +6,7 @@ set(EDGE_SOKOL_GLES3 ON) set(EDGE_EMSC_COMMON_FLAGS "-sUSE_SDL=2") set(EDGE_EMSC_COMPILER_FLAGS "-DEDGE_WEB=1") -set(EDGE_EMSC_LINKER_FLAGS "-sENVIRONMENT=web -sWASM=1 -sALLOW_MEMORY_GROWTH=1 -sINITIAL_MEMORY=512Mb -sERROR_ON_UNDEFINED_SYMBOLS=1 -sMAX_WEBGL_VERSION=2 -sFULL_ES2=1 -sGL_MAX_TEMP_BUFFER_SIZE=16777216 -sLZ4=1 -lidbfs.js -sEXPORT_ES6=1 -sUSE_ES6_IMPORT_META=0 -sMODULARIZE=1 -sEXPORT_NAME=\"createEdgeModule\"") +set(EDGE_EMSC_LINKER_FLAGS "-sMALLOC=mimalloc -sENVIRONMENT=web -sWASM=1 -sALLOW_MEMORY_GROWTH=1 -sINITIAL_MEMORY=512Mb -sERROR_ON_UNDEFINED_SYMBOLS=1 -sMIN_WEBGL_VERSION=2 -sMAX_WEBGL_VERSION=2 -sGL_MAX_TEMP_BUFFER_SIZE=16777216 -sLZ4=1 -lidbfs.js -sEXPORT_ES6=1 -sUSE_ES6_IMPORT_META=0 -sMODULARIZE=1 -sEXPORT_NAME=\"createEdgeModule\"") # Enable sourcemap support set(EDGE_EMSC_LINKER_FLAGS "${EDGE_EMSC_LINKER_FLAGS} -gsource-map --source-map-base=/") diff --git a/libraries/mimalloc/CMakeLists.txt b/libraries/mimalloc/CMakeLists.txt index 8ee98c62c..8d6aa754a 100644 --- a/libraries/mimalloc/CMakeLists.txt +++ b/libraries/mimalloc/CMakeLists.txt @@ -7,7 +7,7 @@ set(CMAKE_CXX_STANDARD 17) option(MI_SECURE "Use full security mitigations (like guard pages, allocation randomization, double-free mitigation, and free-list corruption detection)" OFF) option(MI_DEBUG_FULL "Use full internal heap invariant checking in DEBUG mode (expensive)" OFF) option(MI_PADDING "Enable padding to detect heap block overflow (always on in DEBUG or SECURE mode, or with Valgrind/ASAN)" OFF) -option(MI_OVERRIDE "Override the standard malloc interface (i.e. define entry points for 'malloc', 'free', etc)" OFF) +option(MI_OVERRIDE "Override the standard malloc interface (i.e. define entry points for 'malloc', 'free', etc)" ON) option(MI_XMALLOC "Enable abort() call on memory allocation failure by default" OFF) option(MI_SHOW_ERRORS "Show error and warning messages by default (only enabled by default in DEBUG mode)" OFF) option(MI_TRACK_VALGRIND "Compile with Valgrind support (adds a small overhead)" OFF) @@ -16,8 +16,8 @@ option(MI_TRACK_ETW "Compile with Windows event tracing (ETW) support (a option(MI_USE_CXX "Use the C++ compiler to compile the library (instead of the C compiler)" OFF) option(MI_OPT_ARCH "Only for optimized builds: turn on architecture specific optimizations (for arm64: '-march=armv8.1-a' (2016))" ON) option(MI_SEE_ASM "Generate assembly files" OFF) -option(MI_OSX_INTERPOSE "Use interpose to override standard malloc on macOS" OFF) -option(MI_OSX_ZONE "Use malloc zone to override standard malloc on macOS" OFF) +option(MI_OSX_INTERPOSE "Use interpose to override standard malloc on macOS" ON) +option(MI_OSX_ZONE "Use malloc zone to override standard malloc on macOS" ON) option(MI_WIN_REDIRECT "Use redirection module ('mimalloc-redirect') on Windows if compiling mimalloc as a DLL" ON) option(MI_WIN_USE_FIXED_TLS "Use a fixed TLS slot on Windows to avoid extra tests in the malloc fast path" OFF) option(MI_LOCAL_DYNAMIC_TLS "Use local-dynamic-tls, a slightly slower but dlopen-compatible thread local storage mechanism (Unix)" OFF) @@ -532,7 +532,7 @@ message(STATUS "") # ----------------------------------------------------------------------------- # static library if (MI_BUILD_STATIC) - add_library(mimalloc STATIC ${mi_sources}) + add_library(mimalloc STATIC ${mi_sources} ec-overrides.cc) set_property(TARGET mimalloc PROPERTY POSITION_INDEPENDENT_CODE ON) target_compile_definitions(mimalloc PRIVATE ${mi_defines} MI_STATIC_LIB) target_compile_options(mimalloc PRIVATE ${mi_cflags} ${mi_cflags_static}) diff --git a/libraries/mimalloc/ec-overrides.cc b/libraries/mimalloc/ec-overrides.cc new file mode 100644 index 000000000..39ddca5d0 --- /dev/null +++ b/libraries/mimalloc/ec-overrides.cc @@ -0,0 +1 @@ +#include \ No newline at end of file diff --git a/libraries/mimalloc/include/mimalloc-override.h b/libraries/mimalloc/include/mimalloc-override.h index 48a8a6226..a36588da8 100644 --- a/libraries/mimalloc/include/mimalloc-override.h +++ b/libraries/mimalloc/include/mimalloc-override.h @@ -15,7 +15,7 @@ each source file in a project (but be careful when using external code to not accidentally mix pointers from different allocators). -----------------------------------------------------------------------------*/ -#include +#include "mimalloc.h" // Standard C allocation #define malloc(n) mi_malloc(n) @@ -29,12 +29,18 @@ not accidentally mix pointers from different allocators). // Microsoft extensions #define _expand(p,n) mi_expand(p,n) -#define _msize(p) mi_usable_size(p) +// EDGE-Classic, uncommenting as causes compilation issue on MSVC and unlikely to be used by EC code +// If it is, this WILL cause problems, though should be caught by ASAN/mimalloc in that case +// #define _msize(p) mi_usable_size(p) #define _recalloc(p,n,c) mi_recalloc(p,n,c) #define _strdup(s) mi_strdup(s) #define _strndup(s,n) mi_strndup(s,n) -#define _wcsdup(s) (wchar_t*)mi_wcsdup((const unsigned short*)(s)) + +// EDGE-Classic, uncommenting as causes compilation issue on MSVC and unlikely to be used by EC code +// If it is, this WILL cause problems, though should be caught by ASAN/mimalloc in that case +// #define _wcsdup(s) (wchar_t*)mi_wcsdup((const unsigned short*)(s)) + #define _mbsdup(s) mi_mbsdup(s) #define _dupenv_s(b,n,v) mi_dupenv_s(b,n,v) #define _wdupenv_s(b,n,v) mi_wdupenv_s((unsigned short*)(b),n,(const unsigned short*)(v)) @@ -59,7 +65,9 @@ not accidentally mix pointers from different allocators). #define _aligned_malloc(n,a) mi_malloc_aligned(n,a) #define _aligned_realloc(p,n,a) mi_realloc_aligned(p,n,a) #define _aligned_recalloc(p,s,n,a) mi_aligned_recalloc(p,s,n,a) -#define _aligned_msize(p,a,o) mi_usable_size(p) +// EDGE-Classic, uncommenting as causes compilation issue on MSVC and unlikely to be used by EC code +// If it is, this WILL cause problems, though should be caught by ASAN/mimalloc in that case +// #define _aligned_msize(p,a,o) mi_usable_size(p) #define _aligned_free(p) mi_free(p) #define _aligned_offset_malloc(n,a,o) mi_malloc_aligned_at(n,a,o) #define _aligned_offset_realloc(p,n,a,o) mi_realloc_aligned_at(p,n,a,o) diff --git a/source_files/edge/con_main.cc b/source_files/edge/con_main.cc index cf9a3eec5..8d069ca4d 100644 --- a/source_files/edge/con_main.cc +++ b/source_files/edge/con_main.cc @@ -18,6 +18,7 @@ #include "con_main.h" +#include #include #include @@ -536,6 +537,22 @@ int ConsoleCommandClear(char **argv, int argc) return 0; } +static void MemoryPrint(const char *msg, void *arg) +{ + EPI_UNUSED(arg); + LogPrint("%s", msg); +} + +static int ConsoleCommandMemory(char **argv, int argc) +{ + EPI_UNUSED(argv); + EPI_UNUSED(argc); + + LogPrint("---- mimalloc memory stats ---\n\n"); + mi_stats_print_out(MemoryPrint, nullptr); + return 0; +} + //---------------------------------------------------------------------------- // oh lordy.... @@ -631,7 +648,7 @@ const ConsoleCommand builtin_commands[] = {{"cat", ConsoleCommandType}, {"version", ConsoleCommandVersion}, {"quit", ConsoleCommandQuitEDGE}, {"exit", ConsoleCommandQuitEDGE}, - + {"memory", ConsoleCommandMemory}, // end of list {nullptr, nullptr}}; diff --git a/source_files/edge/p_mobj.cc b/source_files/edge/p_mobj.cc index 091b36fa3..5b647e283 100644 --- a/source_files/edge/p_mobj.cc +++ b/source_files/edge/p_mobj.cc @@ -134,14 +134,14 @@ static void AddItemToQueue(const MapObject *mo) MapObject *MapObject::Allocate() { - void *buffer = Mem_Alloc(sizeof(MapObject)); + void *buffer = malloc(sizeof(MapObject)); return new (buffer) MapObject(); } void MapObject::Delete() { this->~MapObject(); - Mem_Free(this); + free(this); } bool MapObject::IsRemoved() const diff --git a/source_files/edge/r_misc.cc b/source_files/edge/r_misc.cc index f25c3bbe2..bfc17c7f2 100644 --- a/source_files/edge/r_misc.cc +++ b/source_files/edge/r_misc.cc @@ -326,7 +326,7 @@ void AllocateDrawStructs(void) draw_subsectors.reserve(kDefaultDrawSubsectors); draw_mirrors.reserve(kDefaultDrawMirrors); - draw_memory_buffer = Mem_Alloc(size); + draw_memory_buffer = malloc(size); uint8_t *dst = (uint8_t *)draw_memory_buffer; @@ -371,7 +371,7 @@ void FreeBSP(void) { if (draw_memory_buffer) { - Mem_Free(draw_memory_buffer); + free(draw_memory_buffer); draw_memory_buffer = nullptr; } @@ -379,27 +379,27 @@ void FreeBSP(void) for (size_t i = kDefaultDrawThings; i < draw_things.size(); i++) { - Mem_Free(draw_things[i]); + free(draw_things[i]); } for (size_t i = kDefaultDrawFloors; i < draw_floors.size(); i++) { - Mem_Free(draw_floors[i]); + free(draw_floors[i]); } for (size_t i = kDefaultDrawSegs; i < draw_segs.size(); i++) { - Mem_Free(draw_segs[i]); + free(draw_segs[i]); } for (size_t i = kDefaultDrawSubsectors; i < draw_subsectors.size(); i++) { - Mem_Free(draw_subsectors[i]); + free(draw_subsectors[i]); } for (size_t i = kDefaultDrawMirrors; i < draw_mirrors.size(); i++) { - Mem_Free(draw_mirrors[i]); + free(draw_mirrors[i]); } draw_things.clear(); @@ -414,7 +414,7 @@ void FreeBSP(void) DrawThing *GetDrawThing() { if (draw_thing_position == draw_things.size()) - draw_things.push_back(new (Mem_Alloc(sizeof(DrawThing))) DrawThing()); + draw_things.push_back(new (malloc(sizeof(DrawThing))) DrawThing()); return draw_things[draw_thing_position++]; } @@ -422,7 +422,7 @@ DrawThing *GetDrawThing() DrawFloor *GetDrawFloor() { if (draw_floor_position == draw_floors.size()) - draw_floors.push_back(new (Mem_Alloc(sizeof(DrawFloor))) DrawFloor()); + draw_floors.push_back(new (malloc(sizeof(DrawFloor))) DrawFloor()); return draw_floors[draw_floor_position++]; } @@ -430,7 +430,7 @@ DrawFloor *GetDrawFloor() DrawSeg *GetDrawSeg() { if (draw_seg_position == draw_segs.size()) - draw_segs.push_back(new (Mem_Alloc(sizeof(DrawSeg))) DrawSeg()); + draw_segs.push_back(new (malloc(sizeof(DrawSeg))) DrawSeg()); return draw_segs[draw_seg_position++]; } @@ -438,7 +438,7 @@ DrawSeg *GetDrawSeg() DrawSubsector *GetDrawSub() { if (draw_subsector_position == draw_subsectors.size()) - draw_subsectors.push_back(new (Mem_Alloc(sizeof(DrawSubsector))) DrawSubsector()); + draw_subsectors.push_back(new (malloc(sizeof(DrawSubsector))) DrawSubsector()); return draw_subsectors[draw_subsector_position++]; } @@ -446,7 +446,7 @@ DrawSubsector *GetDrawSub() DrawMirror *GetDrawMirror() { if (draw_mirror_position == draw_mirrors.size()) - draw_mirrors.push_back(new (Mem_Alloc(sizeof(DrawMirror))) DrawMirror()); + draw_mirrors.push_back(new (malloc(sizeof(DrawMirror))) DrawMirror()); return draw_mirrors[draw_mirror_position++]; } diff --git a/source_files/edge/script/compat/lua_vm.cc b/source_files/edge/script/compat/lua_vm.cc index adda034c9..546785d4f 100644 --- a/source_files/edge/script/compat/lua_vm.cc +++ b/source_files/edge/script/compat/lua_vm.cc @@ -248,12 +248,12 @@ static void *LUA_DefaultAllocator(void *user, void *ptr, size_t osize, size_t ns { if (ptr) { - Mem_Free(ptr); + free(ptr); } return NULL; } else - return Mem_Realloc(ptr, nsize); + return realloc(ptr, nsize); } lua_State *LuaCreateVM() diff --git a/source_files/epi/epi.h b/source_files/epi/epi.h index 9f23a2b52..f95050998 100644 --- a/source_files/epi/epi.h +++ b/source_files/epi/epi.h @@ -21,17 +21,6 @@ #include #include -#if !defined(EDGE_WEB) && !defined(__MINGW32__) -#include -#define Mem_Alloc mi_malloc -#define Mem_Realloc mi_realloc -#define Mem_Free mi_free -#else -#define Mem_Alloc malloc -#define Mem_Realloc realloc -#define Mem_Free free -#endif - /* Important functions provided by Engine code */ #ifdef __GNUC__ [[noreturn]] void FatalError(const char *error, ...) __attribute__((format(printf, 1, 2)));