Skip to content

Commit 68830c3

Browse files
committed
Integrate mimalloc allocator
1 parent 53be3b7 commit 68830c3

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+17545
-8
lines changed

SConstruct

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1187,6 +1187,9 @@ SConscript("main/SCsub")
11871187

11881188
SConscript("platform/" + env["platform"] + "/SCsub") # Build selected platform.
11891189

1190+
if "mimalloc" in env.get("supported", []):
1191+
SConscript("mimalloc/SCsub")
1192+
11901193
# Microsoft Visual Studio Project Generation
11911194
if env["vsproj"]:
11921195
methods.generate_cpp_hint_file("cpp.hint")

drivers/unix/os_unix.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,11 @@
8686
#define RTLD_DEEPBIND 0
8787
#endif
8888

89+
#define GODOT_DLOPEN_MODE_BASE RTLD_NOW
8990
#ifndef SANITIZERS_ENABLED
90-
#define GODOT_DLOPEN_MODE RTLD_NOW | RTLD_DEEPBIND
91+
#define GODOT_DLOPEN_MODE_GDEXTENSION RTLD_DEEPBIND
9192
#else
92-
#define GODOT_DLOPEN_MODE RTLD_NOW
93+
#define GODOT_DLOPEN_MODE_GDEXTENSION 0
9394
#endif
9495

9596
#if defined(MACOS_ENABLED) || (defined(__ANDROID_API__) && __ANDROID_API__ >= 28)
@@ -1056,7 +1057,11 @@ Error OS_Unix::open_dynamic_library(const String &p_path, void *&p_library_handl
10561057

10571058
ERR_FAIL_COND_V(!FileAccess::exists(path), ERR_FILE_NOT_FOUND);
10581059

1059-
p_library_handle = dlopen(path.utf8().get_data(), GODOT_DLOPEN_MODE);
1060+
int flags = GODOT_DLOPEN_MODE_BASE;
1061+
if (p_data) {
1062+
flags |= GODOT_DLOPEN_MODE_GDEXTENSION;
1063+
}
1064+
p_library_handle = dlopen(path.utf8().get_data(), flags);
10601065
ERR_FAIL_NULL_V_MSG(p_library_handle, ERR_CANT_OPEN, vformat("Can't open dynamic library: %s. Error: %s.", p_path, dlerror()));
10611066

10621067
if (p_data != nullptr && p_data->r_resolved_path != nullptr) {

mimalloc/SCsub

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
#!/usr/bin/env python
2+
from misc.utility.scons_hints import *
3+
4+
Import("env")
5+
6+
# For platforms not supported out-of-the-box by mimalloc, the following options
7+
# can be used to add support for them:
8+
# mimalloc_custom_prims (bool): If true, the prim.c file is not included. Important because otherwise it falls back to UNIX.
9+
# mimalloc_custom_tls_slot (bool): If true, mimalloc is built assuming primitives for TLS operations will be provided separately.
10+
# mimalloc_custom_get_thread_id (string): If non-empty, mimalloc will use the function named here to get the current thread id.
11+
12+
13+
mimalloc_sources = []
14+
15+
if env["platform"] == "windows":
16+
override_type = "windows"
17+
elif env.get("mimalloc_custom_prims"):
18+
override_type = "none"
19+
else:
20+
override_type = "static"
21+
22+
use_mingw_custom_tls_slot = override_type == "windows" and not env.msvc
23+
24+
# Thirdparty source files
25+
26+
env_thirdparty = env.Clone()
27+
env_thirdparty.disable_warnings()
28+
29+
thirdparty_obj = []
30+
31+
thirdparty_dir = "#thirdparty/mimalloc/"
32+
if override_type == "static":
33+
thirdparty_sources = ["src/static.c"]
34+
env_thirdparty.Append(CPPDEFINES=["MI_MALLOC_OVERRIDE"])
35+
else:
36+
thirdparty_sources = [
37+
"src/alloc.c",
38+
"src/alloc-aligned.c",
39+
"src/alloc-posix.c",
40+
"src/arena.c",
41+
"src/bitmap.c",
42+
"src/heap.c",
43+
"src/init.c",
44+
"src/libc.c",
45+
"src/options.c",
46+
"src/os.c",
47+
"src/page.c",
48+
"src/random.c",
49+
"src/segment-map.c",
50+
"src/segment.c",
51+
"src/stats.c",
52+
]
53+
if not env.get("mimalloc_custom_prims"):
54+
thirdparty_sources += ["src/prim/prim.c"]
55+
56+
thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources]
57+
58+
if use_mingw_custom_tls_slot:
59+
thirdparty_sources += ["#mimalloc/mingw_custom_tls_slot.cpp"]
60+
61+
env_thirdparty.add_source_files(thirdparty_obj, thirdparty_sources)
62+
63+
env_thirdparty.Append(CPPDEFINES=[("MI_TRACK_ASAN", 1 if env.get("use_asan") else 0)])
64+
65+
if env.get("mimalloc_custom_tls_slot") or use_mingw_custom_tls_slot:
66+
env_thirdparty.Append(CPPFLAGS=["-includemimalloc/custom_tls_slot.h"])
67+
68+
if env.get("mimalloc_custom_get_thread_id"):
69+
env_thirdparty.Append(CPPDEFINES=[("MI_PRIM_THREAD_ID", env.get("mimalloc_custom_get_thread_id"))])
70+
71+
env_thirdparty.Append(CPPPATH=[f"{thirdparty_dir}include/"])
72+
73+
mimalloc_sources += thirdparty_obj
74+
75+
76+
# Godot source files
77+
78+
if override_type == "windows":
79+
godot_obj = []
80+
81+
env_mimalloc = env_thirdparty.Clone()
82+
env_mimalloc.Append(CPPPATH=[thirdparty_dir])
83+
84+
env_mimalloc.add_source_files(godot_obj, "windows_override.cpp")
85+
86+
mimalloc_sources += godot_obj
87+
88+
if env.msvc:
89+
if env["arch"] == "x86_32":
90+
env.Append(LINKFLAGS=["/INCLUDE:_mimalloc_godot_force_override"])
91+
else:
92+
env.Append(LINKFLAGS=["/INCLUDE:mimalloc_godot_force_override"])
93+
94+
lib = env.add_library("mimalloc", mimalloc_sources)
95+
96+
# For override to work on non-Windows platforms, it must be linked first.
97+
# This way is somewhat hacky, but reliable.
98+
env.Prepend(LINKFLAGS=[f"mimalloc/{lib[0].get_path()}"])
99+
# We still add it the regular way to ensure the program depends on it.
100+
env.Prepend(LIBS=[lib])

mimalloc/custom_tls_slot.h

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/**************************************************************************/
2+
/* custom_tls_slot.h */
3+
/**************************************************************************/
4+
/* This file is part of: */
5+
/* GODOT ENGINE */
6+
/* https://godotengine.org */
7+
/**************************************************************************/
8+
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9+
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10+
/* */
11+
/* Permission is hereby granted, free of charge, to any person obtaining */
12+
/* a copy of this software and associated documentation files (the */
13+
/* "Software"), to deal in the Software without restriction, including */
14+
/* without limitation the rights to use, copy, modify, merge, publish, */
15+
/* distribute, sublicense, and/or sell copies of the Software, and to */
16+
/* permit persons to whom the Software is furnished to do so, subject to */
17+
/* the following conditions: */
18+
/* */
19+
/* The above copyright notice and this permission notice shall be */
20+
/* included in all copies or substantial portions of the Software. */
21+
/* */
22+
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23+
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24+
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25+
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26+
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27+
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28+
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29+
/**************************************************************************/
30+
31+
#pragma once
32+
33+
#include <stddef.h>
34+
35+
// This is included both in the third-party and the engine code
36+
// to ensure both mimalloc and Godot see the same, non-default,
37+
// signatures. Otherwise, for instance, in mimalloc mi_prim_tls_slot()
38+
// could be assumed to return 'int', which would truncate pointers.
39+
40+
#define MI_HAS_TLS_SLOT
41+
#define MI_TLS_SLOT 0
42+
43+
#ifdef __cplusplus
44+
extern "C" {
45+
#endif
46+
47+
void *mi_prim_tls_slot(size_t slot);
48+
void mi_prim_tls_slot_set(size_t slot, void *value);
49+
50+
#ifdef __cplusplus
51+
}
52+
#endif

mimalloc/mingw_custom_tls_slot.cpp

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/**************************************************************************/
2+
/* mingw_custom_tls_slot.cpp */
3+
/**************************************************************************/
4+
/* This file is part of: */
5+
/* GODOT ENGINE */
6+
/* https://godotengine.org */
7+
/**************************************************************************/
8+
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9+
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10+
/* */
11+
/* Permission is hereby granted, free of charge, to any person obtaining */
12+
/* a copy of this software and associated documentation files (the */
13+
/* "Software"), to deal in the Software without restriction, including */
14+
/* without limitation the rights to use, copy, modify, merge, publish, */
15+
/* distribute, sublicense, and/or sell copies of the Software, and to */
16+
/* permit persons to whom the Software is furnished to do so, subject to */
17+
/* the following conditions: */
18+
/* */
19+
/* The above copyright notice and this permission notice shall be */
20+
/* included in all copies or substantial portions of the Software. */
21+
/* */
22+
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23+
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24+
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25+
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26+
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27+
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28+
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29+
/**************************************************************************/
30+
31+
#include "core/error/error_macros.h"
32+
#include "core/typedefs.h"
33+
#include "mimalloc/custom_tls_slot.h"
34+
35+
#define WIN32_LEAN_AND_MEAN
36+
#include <windows.h>
37+
38+
static DWORD tls_slot = -1;
39+
40+
extern "C" {
41+
void *mi_prim_tls_slot(size_t slot) {
42+
DEV_ASSERT(slot == MI_TLS_SLOT);
43+
if (unlikely(tls_slot == -1)) {
44+
return nullptr;
45+
} else {
46+
return TlsGetValue(tls_slot);
47+
}
48+
}
49+
50+
void mi_prim_tls_slot_set(size_t slot, void *value) {
51+
DEV_ASSERT(slot == MI_TLS_SLOT);
52+
if (unlikely(tls_slot == -1)) {
53+
tls_slot = TlsAlloc();
54+
CRASH_COND(tls_slot == TLS_OUT_OF_INDEXES);
55+
}
56+
TlsSetValue(tls_slot, value);
57+
}
58+
}

0 commit comments

Comments
 (0)