mirror of
https://github.com/microsoft/mimalloc.git
synced 2025-05-04 22:49:32 +03:00
Merge branch 'dev' into dev-exp
This commit is contained in:
commit
983c96a238
9 changed files with 131 additions and 84 deletions
|
@ -30,27 +30,23 @@
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
<PlatformToolset>v141</PlatformToolset>
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
<CharacterSet>MultiByte</CharacterSet>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
<PlatformToolset>v141</PlatformToolset>
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
<CharacterSet>MultiByte</CharacterSet>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
<PlatformToolset>v141</PlatformToolset>
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
<CharacterSet>MultiByte</CharacterSet>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
<PlatformToolset>v141</PlatformToolset>
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
<CharacterSet>MultiByte</CharacterSet>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
<ImportGroup Label="ExtensionSettings">
|
<ImportGroup Label="ExtensionSettings">
|
||||||
|
@ -152,6 +148,7 @@
|
||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
<EntryPointSymbol>
|
<EntryPointSymbol>
|
||||||
</EntryPointSymbol>
|
</EntryPointSymbol>
|
||||||
|
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -165,4 +162,4 @@
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
<ImportGroup Label="ExtensionTargets">
|
<ImportGroup Label="ExtensionTargets">
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
</Project>
|
</Project>
|
|
@ -30,27 +30,23 @@
|
||||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
<PlatformToolset>v141</PlatformToolset>
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
<CharacterSet>MultiByte</CharacterSet>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
<PlatformToolset>v141</PlatformToolset>
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
<CharacterSet>MultiByte</CharacterSet>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
<PlatformToolset>v141</PlatformToolset>
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
<CharacterSet>MultiByte</CharacterSet>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
<PlatformToolset>v141</PlatformToolset>
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
<CharacterSet>MultiByte</CharacterSet>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
<ImportGroup Label="ExtensionSettings">
|
<ImportGroup Label="ExtensionSettings">
|
||||||
|
|
|
@ -30,27 +30,23 @@
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
<PlatformToolset>v141</PlatformToolset>
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
<CharacterSet>MultiByte</CharacterSet>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
<PlatformToolset>v141</PlatformToolset>
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
<CharacterSet>MultiByte</CharacterSet>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
<PlatformToolset>v141</PlatformToolset>
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
<CharacterSet>MultiByte</CharacterSet>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
<PlatformToolset>v141</PlatformToolset>
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
<CharacterSet>MultiByte</CharacterSet>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
<ImportGroup Label="ExtensionSettings">
|
<ImportGroup Label="ExtensionSettings">
|
||||||
|
|
|
@ -30,27 +30,23 @@
|
||||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
<PlatformToolset>v141</PlatformToolset>
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
<CharacterSet>MultiByte</CharacterSet>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
<PlatformToolset>v141</PlatformToolset>
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
<CharacterSet>MultiByte</CharacterSet>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
<PlatformToolset>v141</PlatformToolset>
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
<CharacterSet>MultiByte</CharacterSet>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
<PlatformToolset>v141</PlatformToolset>
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
<CharacterSet>MultiByte</CharacterSet>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
<ImportGroup Label="ExtensionSettings">
|
<ImportGroup Label="ExtensionSettings">
|
||||||
|
|
|
@ -14,12 +14,19 @@ terms of the MIT license. A copy of the license can be found in the file
|
||||||
#define MI_TLS_RECURSE_GUARD
|
#define MI_TLS_RECURSE_GUARD
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if (MI_DEBUG>0)
|
||||||
|
#define mi_trace_message(...) _mi_trace_message(__VA_ARGS__)
|
||||||
|
#else
|
||||||
|
#define mi_trace_message(...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
// "options.c"
|
// "options.c"
|
||||||
void _mi_fprintf(FILE* out, const char* fmt, ...);
|
void _mi_fprintf(FILE* out, const char* fmt, ...);
|
||||||
void _mi_error_message(const char* fmt, ...);
|
void _mi_error_message(const char* fmt, ...);
|
||||||
void _mi_warning_message(const char* fmt, ...);
|
void _mi_warning_message(const char* fmt, ...);
|
||||||
void _mi_verbose_message(const char* fmt, ...);
|
void _mi_verbose_message(const char* fmt, ...);
|
||||||
|
void _mi_trace_message(const char* fmt, ...);
|
||||||
|
|
||||||
// "init.c"
|
// "init.c"
|
||||||
extern mi_stats_t _mi_stats_main;
|
extern mi_stats_t _mi_stats_main;
|
||||||
|
@ -119,6 +126,11 @@ bool _mi_page_is_valid(mi_page_t* page);
|
||||||
Inlined definitions
|
Inlined definitions
|
||||||
----------------------------------------------------------- */
|
----------------------------------------------------------- */
|
||||||
#define UNUSED(x) (void)(x)
|
#define UNUSED(x) (void)(x)
|
||||||
|
#if (MI_DEBUG>0)
|
||||||
|
#define UNUSED_RELEASE(x)
|
||||||
|
#else
|
||||||
|
#define UNUSED_RELEASE(x) UNUSED(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
#define MI_INIT4(x) x(),x(),x(),x()
|
#define MI_INIT4(x) x(),x(),x(),x()
|
||||||
#define MI_INIT8(x) MI_INIT4(x),MI_INIT4(x)
|
#define MI_INIT8(x) MI_INIT4(x),MI_INIT4(x)
|
||||||
|
|
|
@ -261,14 +261,18 @@ static int mi_register_atexit(exit_list_t* list, cbfun_t* fn) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register a global `atexit` function
|
// Register a global `atexit` function
|
||||||
static int mi__crt_atexit(cbfun_t* fn) {
|
static int mi_atexit(cbfun_t* fn) {
|
||||||
return mi_register_atexit(&atexit_list,fn);
|
return mi_register_atexit(&atexit_list,fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mi__crt_at_quick_exit(cbfun_t* fn) {
|
static int mi_at_quick_exit(cbfun_t* fn) {
|
||||||
return mi_register_atexit(&at_quick_exit_list,fn);
|
return mi_register_atexit(&at_quick_exit_list,fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int mi_register_onexit(void* table, cbfun_t* fn) {
|
||||||
|
// TODO: how can we distinguish a quick_exit from atexit?
|
||||||
|
return mi_atexit(fn);
|
||||||
|
}
|
||||||
|
|
||||||
// Execute exit functions in a list
|
// Execute exit functions in a list
|
||||||
static void mi_execute_exit_list(exit_list_t* list) {
|
static void mi_execute_exit_list(exit_list_t* list) {
|
||||||
|
@ -375,47 +379,57 @@ typedef enum patch_apply_e {
|
||||||
PATCH_TARGET_TERM
|
PATCH_TARGET_TERM
|
||||||
} patch_apply_t;
|
} patch_apply_t;
|
||||||
|
|
||||||
|
#define MAX_ENTRIES 4 // maximum number of patched entry points (like `malloc` in ucrtbase and msvcrt)
|
||||||
|
|
||||||
typedef struct mi_patch_s {
|
typedef struct mi_patch_s {
|
||||||
const char* name; // name of the function to patch
|
const char* name; // name of the function to patch
|
||||||
int priority; // priority to patch this one (used to prioritize over multiple entries in various dll's)
|
void* target; // the address of the new target (never NULL)
|
||||||
void* original; // the resolved address of the function (or NULL)
|
void* target_term; // the address of the target during termination (or NULL)
|
||||||
void* target; // the address of the new target (never NULL)
|
patch_apply_t applied; // what target has been applied?
|
||||||
void* target_term;// the address of the target during termination (or NULL)
|
void* originals[MAX_ENTRIES]; // the resolved addresses of the function (or NULLs)
|
||||||
patch_apply_t applied; // what target has been applied?
|
mi_jump_t saves[MAX_ENTRIES]; // the saved instructions in case it was applied
|
||||||
mi_jump_t save; // the saved instructions in case it was applied
|
|
||||||
} mi_patch_t;
|
} mi_patch_t;
|
||||||
|
|
||||||
#define MI_PATCH_NAME3(name,target,term) { name, 0, NULL, &target, &term, PATCH_NONE }
|
#define MI_PATCH_NAME3(name,target,term) { name, &target, &term, PATCH_NONE, {NULL,NULL,NULL,NULL} }
|
||||||
#define MI_PATCH_NAME2(name,target) { name, 0, NULL, &target, NULL, PATCH_NONE }
|
#define MI_PATCH_NAME2(name,target) { name, &target, NULL, PATCH_NONE, {NULL,NULL,NULL,NULL} }
|
||||||
#define MI_PATCH3(name,target,term) MI_PATCH_NAME3(#name, target, term)
|
#define MI_PATCH3(name,target,term) MI_PATCH_NAME3(#name, target, term)
|
||||||
#define MI_PATCH2(name,target) MI_PATCH_NAME2(#name, target)
|
#define MI_PATCH2(name,target) MI_PATCH_NAME2(#name, target)
|
||||||
#define MI_PATCH1(name) MI_PATCH2(name,mi_##name)
|
#define MI_PATCH1(name) MI_PATCH2(name,mi_##name)
|
||||||
|
|
||||||
static mi_patch_t patches[] = {
|
static mi_patch_t patches[] = {
|
||||||
// we implement our own global exit handler (as the CRT versions do a realloc internally)
|
// we implement our own global exit handler (as the CRT versions do a realloc internally)
|
||||||
MI_PATCH2(_crt_atexit, mi__crt_atexit),
|
//MI_PATCH2(_crt_atexit, mi_atexit),
|
||||||
MI_PATCH2(_crt_at_quick_exit, mi__crt_at_quick_exit),
|
//MI_PATCH2(_crt_at_quick_exit, mi_at_quick_exit),
|
||||||
MI_PATCH2(_setmaxstdio, mi_setmaxstdio),
|
MI_PATCH2(_setmaxstdio, mi_setmaxstdio),
|
||||||
|
MI_PATCH2(_register_onexit_function, mi_register_onexit),
|
||||||
|
|
||||||
// base versions
|
// override higher level atexit functions so we can implement at_quick_exit correcty
|
||||||
|
MI_PATCH2(atexit, mi_atexit),
|
||||||
|
MI_PATCH2(at_quick_exit, mi_at_quick_exit),
|
||||||
|
|
||||||
|
// regular entries
|
||||||
|
MI_PATCH2(malloc, mi_malloc),
|
||||||
|
MI_PATCH2(calloc, mi_calloc),
|
||||||
|
MI_PATCH3(realloc, mi_realloc,mi_realloc_term),
|
||||||
|
MI_PATCH3(free, mi_free,mi_free_term),
|
||||||
|
|
||||||
|
// extended api
|
||||||
|
MI_PATCH2(_strdup, mi_strdup),
|
||||||
|
MI_PATCH2(_strndup, mi_strndup),
|
||||||
|
MI_PATCH3(_expand, mi__expand,mi__expand_term),
|
||||||
|
MI_PATCH3(_recalloc, mi_recalloc,mi__recalloc_term),
|
||||||
|
MI_PATCH3(_msize, mi_usable_size,mi__msize_term),
|
||||||
|
|
||||||
|
// base versions
|
||||||
MI_PATCH2(_malloc_base, mi_malloc),
|
MI_PATCH2(_malloc_base, mi_malloc),
|
||||||
MI_PATCH2(_calloc_base, mi_calloc),
|
MI_PATCH2(_calloc_base, mi_calloc),
|
||||||
MI_PATCH3(_realloc_base, mi_realloc,mi_realloc_term),
|
MI_PATCH3(_realloc_base, mi_realloc,mi_realloc_term),
|
||||||
MI_PATCH3(_free_base, mi_free,mi_free_term),
|
MI_PATCH3(_free_base, mi_free,mi_free_term),
|
||||||
|
|
||||||
// regular entries
|
|
||||||
MI_PATCH3(_expand, mi__expand,mi__expand_term),
|
|
||||||
MI_PATCH3(_recalloc, mi_recalloc,mi__recalloc_term),
|
|
||||||
MI_PATCH3(_msize, mi_usable_size,mi__msize_term),
|
|
||||||
|
|
||||||
// these base versions are in the crt but without import records
|
// these base versions are in the crt but without import records
|
||||||
MI_PATCH_NAME3("_recalloc_base", mi_recalloc,mi__recalloc_term),
|
MI_PATCH_NAME3("_recalloc_base", mi_recalloc,mi__recalloc_term),
|
||||||
MI_PATCH_NAME3("_msize_base", mi_usable_size,mi__msize_term),
|
MI_PATCH_NAME3("_msize_base", mi_usable_size,mi__msize_term),
|
||||||
|
|
||||||
// utility
|
|
||||||
MI_PATCH2(_strdup, mi_strdup),
|
|
||||||
MI_PATCH2(_strndup, mi_strndup),
|
|
||||||
|
|
||||||
// debug
|
// debug
|
||||||
MI_PATCH2(_malloc_dbg, mi__malloc_dbg),
|
MI_PATCH2(_malloc_dbg, mi__malloc_dbg),
|
||||||
MI_PATCH2(_realloc_dbg, mi__realloc_dbg),
|
MI_PATCH2(_realloc_dbg, mi__realloc_dbg),
|
||||||
|
@ -426,6 +440,8 @@ static mi_patch_t patches[] = {
|
||||||
MI_PATCH3(_recalloc_dbg, mi__recalloc_dbg, mi__recalloc_dbg_term),
|
MI_PATCH3(_recalloc_dbg, mi__recalloc_dbg, mi__recalloc_dbg_term),
|
||||||
MI_PATCH3(_msize_dbg, mi__msize_dbg, mi__msize_dbg_term),
|
MI_PATCH3(_msize_dbg, mi__msize_dbg, mi__msize_dbg_term),
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
// override new/delete variants for efficiency (?)
|
||||||
#ifdef _WIN64
|
#ifdef _WIN64
|
||||||
// 64 bit new/delete
|
// 64 bit new/delete
|
||||||
MI_PATCH_NAME2("??2@YAPEAX_K@Z", mi_malloc),
|
MI_PATCH_NAME2("??2@YAPEAX_K@Z", mi_malloc),
|
||||||
|
@ -447,30 +463,35 @@ static mi_patch_t patches[] = {
|
||||||
MI_PATCH_NAME3("??3@YAXPAXABUnothrow_t@std@@@Z", mi_free, mi_free_term),
|
MI_PATCH_NAME3("??3@YAXPAXABUnothrow_t@std@@@Z", mi_free, mi_free_term),
|
||||||
MI_PATCH_NAME3("??_V@YAXPAXABUnothrow_t@std@@@Z", mi_free, mi_free_term),
|
MI_PATCH_NAME3("??_V@YAXPAXABUnothrow_t@std@@@Z", mi_free, mi_free_term),
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
{ NULL, 0, NULL, NULL, NULL, PATCH_NONE }
|
{ NULL, NULL, NULL, PATCH_NONE, {NULL,NULL,NULL,NULL} }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// Apply a patch
|
// Apply a patch
|
||||||
static bool mi_patch_apply(mi_patch_t* patch, patch_apply_t apply)
|
static bool mi_patch_apply(mi_patch_t* patch, patch_apply_t apply)
|
||||||
{
|
{
|
||||||
if (patch->original == NULL) return true; // unresolved
|
if (patch->originals[0] == NULL) return true; // unresolved
|
||||||
if (apply == PATCH_TARGET_TERM && patch->target_term == NULL) apply = PATCH_TARGET; // avoid re-applying non-term variants
|
if (apply == PATCH_TARGET_TERM && patch->target_term == NULL) apply = PATCH_TARGET; // avoid re-applying non-term variants
|
||||||
if (patch->applied == apply) return false;
|
if (patch->applied == apply) return false;
|
||||||
|
|
||||||
DWORD protect = PAGE_READWRITE;
|
for (int i = 0; i < MAX_ENTRIES; i++) {
|
||||||
if (!VirtualProtect(patch->original, MI_JUMP_SIZE, PAGE_EXECUTE_READWRITE, &protect)) return false;
|
void* original = patch->originals[i];
|
||||||
if (apply == PATCH_NONE) {
|
if (original == NULL) break; // no more
|
||||||
mi_jump_restore(patch->original, &patch->save);
|
|
||||||
}
|
DWORD protect = PAGE_READWRITE;
|
||||||
else {
|
if (!VirtualProtect(original, MI_JUMP_SIZE, PAGE_EXECUTE_READWRITE, &protect)) return false;
|
||||||
void* target = (apply == PATCH_TARGET ? patch->target : patch->target_term);
|
if (apply == PATCH_NONE) {
|
||||||
mi_assert_internal(target!=NULL);
|
mi_jump_restore(original, &patch->saves[i]);
|
||||||
if (target != NULL) mi_jump_write(patch->original, target, &patch->save);
|
}
|
||||||
|
else {
|
||||||
|
void* target = (apply == PATCH_TARGET ? patch->target : patch->target_term);
|
||||||
|
mi_assert_internal(target != NULL);
|
||||||
|
if (target != NULL) mi_jump_write(original, target, &patch->saves[i]);
|
||||||
|
}
|
||||||
|
VirtualProtect(original, MI_JUMP_SIZE, protect, &protect);
|
||||||
}
|
}
|
||||||
patch->applied = apply;
|
patch->applied = apply;
|
||||||
VirtualProtect(patch->original, MI_JUMP_SIZE, protect, &protect);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -523,23 +544,29 @@ static int __cdecl mi_setmaxstdio(int newmax) {
|
||||||
// ------------------------------------------------------
|
// ------------------------------------------------------
|
||||||
|
|
||||||
// Try to resolve patches for a given module (DLL)
|
// Try to resolve patches for a given module (DLL)
|
||||||
static void mi_module_resolve(HMODULE mod, int priority) {
|
static void mi_module_resolve(const char* fname, HMODULE mod, int priority) {
|
||||||
// see if any patches apply
|
// see if any patches apply
|
||||||
for (size_t i = 0; patches[i].name != NULL; i++) {
|
for (size_t i = 0; patches[i].name != NULL; i++) {
|
||||||
mi_patch_t* patch = &patches[i];
|
mi_patch_t* patch = &patches[i];
|
||||||
if (!patch->applied && patch->priority < priority) {
|
if (patch->applied == PATCH_NONE) {
|
||||||
void* addr = GetProcAddress(mod, patch->name);
|
// find an available entry
|
||||||
if (addr != NULL) {
|
int i = 0;
|
||||||
// found it! set the address
|
while (i < MAX_ENTRIES && patch->originals[i] != NULL) i++;
|
||||||
patch->original = addr;
|
if (i < MAX_ENTRIES) {
|
||||||
patch->priority = priority;
|
void* addr = GetProcAddress(mod, patch->name);
|
||||||
|
if (addr != NULL) {
|
||||||
|
// found it! set the address
|
||||||
|
patch->originals[i] = addr;
|
||||||
|
_mi_trace_message(" override %s at %s!%p (entry %i)\n", patch->name, fname, addr, i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MIMALLOC_NAME "mimalloc-override"
|
#define MIMALLOC_NAME "mimalloc-override.dll"
|
||||||
#define UCRTBASE_NAME "ucrtbase"
|
#define UCRTBASE_NAME "ucrtbase.dll"
|
||||||
|
#define UCRTBASED_NAME "ucrtbased.dll"
|
||||||
|
|
||||||
// Resolve addresses of all patches by inspecting the loaded modules
|
// Resolve addresses of all patches by inspecting the loaded modules
|
||||||
static atexit_fun_t* crt_atexit = NULL;
|
static atexit_fun_t* crt_atexit = NULL;
|
||||||
|
@ -553,14 +580,13 @@ static bool mi_patches_resolve(void) {
|
||||||
HMODULE modules[400]; // try to stay under 4k to not trigger the guard page
|
HMODULE modules[400]; // try to stay under 4k to not trigger the guard page
|
||||||
EnumProcessModules(process, modules, sizeof(modules), &needed);
|
EnumProcessModules(process, modules, sizeof(modules), &needed);
|
||||||
if (needed == 0) return false;
|
if (needed == 0) return false;
|
||||||
size_t count = needed / sizeof(HMODULE);
|
int count = needed / sizeof(HMODULE);
|
||||||
size_t ucrtbase_index = 0;
|
int ucrtbase_index = 0;
|
||||||
size_t mimalloc_index = 0;
|
int mimalloc_index = 0;
|
||||||
// iterate through the loaded modules; do this from the end so we prefer the
|
// iterate through the loaded modules
|
||||||
// first loaded DLL as sometimes both "msvcr" and "ucrt" are both loaded and we should
|
_mi_trace_message("overriding malloc dynamically...\n");
|
||||||
// override "ucrt" in that situation.
|
for (int i = 0; i < count; i++) {
|
||||||
for (size_t i = count; i > 0; i--) {
|
HMODULE mod = modules[i];
|
||||||
HMODULE mod = modules[i-1];
|
|
||||||
char filename[MAX_PATH] = { 0 };
|
char filename[MAX_PATH] = { 0 };
|
||||||
DWORD slen = GetModuleFileName(mod, filename, MAX_PATH);
|
DWORD slen = GetModuleFileName(mod, filename, MAX_PATH);
|
||||||
if (slen > 0 && slen < MAX_PATH) {
|
if (slen > 0 && slen < MAX_PATH) {
|
||||||
|
@ -568,19 +594,23 @@ static bool mi_patches_resolve(void) {
|
||||||
filename[slen] = 0;
|
filename[slen] = 0;
|
||||||
const char* lastsep = strrchr(filename, '\\');
|
const char* lastsep = strrchr(filename, '\\');
|
||||||
const char* basename = (lastsep==NULL ? filename : lastsep+1);
|
const char* basename = (lastsep==NULL ? filename : lastsep+1);
|
||||||
|
_mi_trace_message(" %i: dynamic module %s\n", i, filename);
|
||||||
|
|
||||||
|
// remember indices so we can check load order (in debug mode)
|
||||||
|
if (_stricmp(basename, MIMALLOC_NAME) == 0) mimalloc_index = i;
|
||||||
|
if (_stricmp(basename, UCRTBASE_NAME) == 0) ucrtbase_index = i;
|
||||||
|
if (_stricmp(basename, UCRTBASED_NAME) == 0) ucrtbase_index = i;
|
||||||
|
|
||||||
|
// see if we potentially patch in this module
|
||||||
int priority = 0;
|
int priority = 0;
|
||||||
if (i == 0) priority = 2; // main module to allow static crt linking
|
if (i == 0) priority = 2; // main module to allow static crt linking
|
||||||
else if (_strnicmp(basename, "ucrt", 4) == 0) priority = 3; // new ucrtbase.dll in windows 10
|
else if (_strnicmp(basename, "ucrt", 4) == 0) priority = 3; // new ucrtbase.dll in windows 10
|
||||||
else if (_strnicmp(basename, "msvcr", 5) == 0) priority = 1; // older runtimes
|
// NOTE: don't override msvcr -- leads to crashes in setlocale (needs more testing)
|
||||||
|
// else if (_strnicmp(basename, "msvcr", 5) == 0) priority = 1; // older runtimes
|
||||||
|
|
||||||
if (priority > 0) {
|
if (priority > 0) {
|
||||||
// remember indices so we can check load order (in debug mode)
|
|
||||||
if (_stricmp(basename, MIMALLOC_NAME) == 0) mimalloc_index = i;
|
|
||||||
if (_stricmp(basename, UCRTBASE_NAME) == 0) ucrtbase_index = i;
|
|
||||||
|
|
||||||
// probably found a crt module, try to patch it
|
// probably found a crt module, try to patch it
|
||||||
mi_module_resolve(mod,priority);
|
mi_module_resolve(basename,mod,priority);
|
||||||
|
|
||||||
// try to find the atexit functions for the main process (in `ucrtbase.dll`)
|
// try to find the atexit functions for the main process (in `ucrtbase.dll`)
|
||||||
if (crt_atexit==NULL) crt_atexit = (atexit_fun_t*)GetProcAddress(mod, "_crt_atexit");
|
if (crt_atexit==NULL) crt_atexit = (atexit_fun_t*)GetProcAddress(mod, "_crt_atexit");
|
||||||
|
@ -588,13 +618,11 @@ static bool mi_patches_resolve(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#if (MI_DEBUG)
|
int diff = mimalloc_index - ucrtbase_index;
|
||||||
size_t diff = (mimalloc_index > ucrtbase_index ? mimalloc_index - ucrtbase_index : ucrtbase_index - mimalloc_index);
|
if (diff > 1) {
|
||||||
if ((mimalloc_index > 0 || ucrtbase_index > 0) && (diff != 1)) {
|
_mi_warning_message("warning: the \"mimalloc-override\" DLL seems not to load before or right after the C runtime (\"ucrtbase\").\n"
|
||||||
_mi_warning_message("warning: the \"mimalloc-override\" DLL seems not to load right before or after the C runtime (\"ucrtbase\").\n"
|
" Try to fix this by changing the linking order.\n");
|
||||||
" Try to fix this by changing the linking order.");
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -333,7 +333,9 @@ void mi_thread_init(void) mi_attr_noexcept
|
||||||
pthread_setspecific(mi_pthread_key, (void*)(_mi_thread_id()|1)); // set to a dummy value so that `mi_pthread_done` is called
|
pthread_setspecific(mi_pthread_key, (void*)(_mi_thread_id()|1)); // set to a dummy value so that `mi_pthread_done` is called
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if (MI_DEBUG>0) // not in release mode as that leads to crashes on Windows dynamic override
|
||||||
_mi_verbose_message("thread init: 0x%zx\n", _mi_thread_id());
|
_mi_verbose_message("thread init: 0x%zx\n", _mi_thread_id());
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void mi_thread_done(void) mi_attr_noexcept {
|
void mi_thread_done(void) mi_attr_noexcept {
|
||||||
|
@ -346,9 +348,11 @@ void mi_thread_done(void) mi_attr_noexcept {
|
||||||
// abandon the thread local heap
|
// abandon the thread local heap
|
||||||
if (_mi_heap_done()) return; // returns true if already ran
|
if (_mi_heap_done()) return; // returns true if already ran
|
||||||
|
|
||||||
|
#if (MI_DEBUG>0)
|
||||||
if (!_mi_is_main_thread()) {
|
if (!_mi_is_main_thread()) {
|
||||||
_mi_verbose_message("thread done: 0x%zx\n", _mi_thread_id());
|
_mi_verbose_message("thread done: 0x%zx\n", _mi_thread_id());
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@ static mi_option_desc_t options[_mi_option_last] = {
|
||||||
#endif
|
#endif
|
||||||
{ 0, UNINIT, "show_stats" },
|
{ 0, UNINIT, "show_stats" },
|
||||||
{ MI_DEBUG, UNINIT, "show_errors" },
|
{ MI_DEBUG, UNINIT, "show_errors" },
|
||||||
{ MI_DEBUG, UNINIT, "verbose" }
|
{ 0, UNINIT, "verbose" }
|
||||||
};
|
};
|
||||||
|
|
||||||
static void mi_option_init(mi_option_desc_t* desc);
|
static void mi_option_init(mi_option_desc_t* desc);
|
||||||
|
@ -105,6 +105,14 @@ void _mi_fprintf( FILE* out, const char* fmt, ... ) {
|
||||||
va_end(args);
|
va_end(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _mi_trace_message(const char* fmt, ...) {
|
||||||
|
if (mi_option_get(mi_option_verbose) <= 1) return; // only with verbose level 2 or higher
|
||||||
|
va_list args;
|
||||||
|
va_start(args, fmt);
|
||||||
|
mi_vfprintf(stderr, "mimalloc: ", fmt, args);
|
||||||
|
va_end(args);
|
||||||
|
}
|
||||||
|
|
||||||
void _mi_verbose_message(const char* fmt, ...) {
|
void _mi_verbose_message(const char* fmt, ...) {
|
||||||
if (!mi_option_is_enabled(mi_option_verbose)) return;
|
if (!mi_option_is_enabled(mi_option_verbose)) return;
|
||||||
va_list args;
|
va_list args;
|
||||||
|
|
|
@ -12,6 +12,14 @@ void free_p() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class Test {
|
||||||
|
private:
|
||||||
|
int i;
|
||||||
|
public:
|
||||||
|
Test(int x) { i = x; }
|
||||||
|
~Test() { }
|
||||||
|
};
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
mi_stats_reset();
|
mi_stats_reset();
|
||||||
atexit(free_p);
|
atexit(free_p);
|
||||||
|
@ -26,8 +34,10 @@ int main() {
|
||||||
free(p1);
|
free(p1);
|
||||||
free(p2);
|
free(p2);
|
||||||
free(s);
|
free(s);
|
||||||
|
Test* t = new Test(42);
|
||||||
|
delete t;
|
||||||
mi_collect(true);
|
mi_collect(true);
|
||||||
mi_stats_print(NULL);
|
// mi_stats_print(NULL); // MIMALLOC_VERBOSE env is set to 2
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue