mirror of
https://github.com/decompals/wibo.git
synced 2025-12-12 22:56:13 +00:00
GlobalAlloc: Add VirtualAlloc fallback for large sizes
This commit is contained in:
@@ -6,6 +6,7 @@
|
|||||||
#include "files.h"
|
#include "files.h"
|
||||||
#include "heap.h"
|
#include "heap.h"
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
#include "mimalloc/types.h"
|
||||||
#include "modules.h"
|
#include "modules.h"
|
||||||
#include "strutil.h"
|
#include "strutil.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
@@ -170,9 +171,23 @@ void *doAlloc(UINT dwBytes, bool zero) {
|
|||||||
if (dwBytes == 0) {
|
if (dwBytes == 0) {
|
||||||
dwBytes = 1;
|
dwBytes = 1;
|
||||||
}
|
}
|
||||||
void *ret = mi_heap_malloc_aligned(wibo::heap::getGuestHeap(), dwBytes, 8);
|
void *ret;
|
||||||
|
size_t size = static_cast<size_t>(dwBytes);
|
||||||
|
if (dwBytes > MI_ARENA_MAX_OBJ_SIZE) {
|
||||||
|
// If the size is too large, allocate memory using virtualAlloc
|
||||||
|
DEBUG_LOG("doAlloc(%u, %d) -> virtualAlloc\n", dwBytes, zero);
|
||||||
|
void *addr = nullptr;
|
||||||
|
const auto result = wibo::heap::virtualAlloc(&addr, &size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
|
||||||
|
if (result != wibo::heap::VmStatus::Success) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
ret = addr;
|
||||||
|
} else {
|
||||||
|
ret = mi_heap_malloc_aligned(wibo::heap::getGuestHeap(), dwBytes, 8);
|
||||||
|
size = mi_usable_size(ret);
|
||||||
|
}
|
||||||
if (ret && zero) {
|
if (ret && zero) {
|
||||||
std::memset(ret, 0, mi_usable_size(ret));
|
std::memset(ret, 0, size);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -181,15 +196,53 @@ void *doRealloc(void *mem, UINT dwBytes, bool zero) {
|
|||||||
if (dwBytes == 0) {
|
if (dwBytes == 0) {
|
||||||
dwBytes = 1;
|
dwBytes = 1;
|
||||||
}
|
}
|
||||||
size_t oldSize = mi_usable_size(mem);
|
size_t oldSize;
|
||||||
void *ret = mi_heap_realloc_aligned(wibo::heap::getGuestHeap(), mem, dwBytes, 8);
|
void *ret;
|
||||||
size_t newSize = mi_usable_size(ret);
|
size_t newSize = static_cast<size_t>(dwBytes);
|
||||||
|
mi_heap_t *heap = wibo::heap::getGuestHeap();
|
||||||
|
if ((mem == nullptr && dwBytes <= MI_ARENA_MAX_OBJ_SIZE) || mi_is_in_heap_region(mem)) {
|
||||||
|
oldSize = mi_usable_size(mem);
|
||||||
|
ret = mi_heap_realloc_aligned(heap, mem, dwBytes, 8);
|
||||||
|
newSize = mi_usable_size(ret);
|
||||||
|
} else {
|
||||||
|
DEBUG_LOG("doRealloc(%u, %d, %d) -> virtualAlloc\n", dwBytes, zero, mem);
|
||||||
|
MEMORY_BASIC_INFORMATION info;
|
||||||
|
auto result = wibo::heap::virtualQuery(mem, &info);
|
||||||
|
if (result != wibo::heap::VmStatus::Success) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
oldSize = info.RegionSize;
|
||||||
|
result = wibo::heap::virtualAlloc(&ret, &newSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
|
||||||
|
if (result != wibo::heap::VmStatus::Success) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
std::memcpy(ret, mem, oldSize);
|
||||||
|
wibo::heap::virtualFree(mem, oldSize, MEM_RELEASE);
|
||||||
|
}
|
||||||
if (ret && zero && newSize > oldSize) {
|
if (ret && zero && newSize > oldSize) {
|
||||||
std::memset(static_cast<char *>(ret) + oldSize, 0, newSize - oldSize);
|
std::memset(static_cast<char *>(ret) + oldSize, 0, newSize - oldSize);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool doFree(void *mem) {
|
||||||
|
if (mem == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (mi_is_in_heap_region(mem)) {
|
||||||
|
mi_free(mem);
|
||||||
|
} else {
|
||||||
|
DEBUG_LOG("doFree(%p) -> virtualFree\n", mem);
|
||||||
|
MEMORY_BASIC_INFORMATION info;
|
||||||
|
auto result = wibo::heap::virtualQuery(mem, &info);
|
||||||
|
if (result != wibo::heap::VmStatus::Success || info.BaseAddress != mem) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
wibo::heap::virtualFree(mem, info.RegionSize, MEM_RELEASE);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool tryGetCurrentDirectoryPath(std::string &outPath) {
|
bool tryGetCurrentDirectoryPath(std::string &outPath) {
|
||||||
std::error_code ec;
|
std::error_code ec;
|
||||||
std::filesystem::path cwd = std::filesystem::current_path(ec);
|
std::filesystem::path cwd = std::filesystem::current_path(ec);
|
||||||
@@ -755,14 +808,21 @@ HGLOBAL WINAPI GlobalAlloc(UINT uFlags, SIZE_T dwBytes) {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
bool zero = (uFlags & GMEM_ZEROINIT) != 0;
|
bool zero = (uFlags & GMEM_ZEROINIT) != 0;
|
||||||
return doAlloc(static_cast<UINT>(dwBytes), zero);
|
void *ret = doAlloc(static_cast<UINT>(dwBytes), zero);
|
||||||
|
DEBUG_LOG("-> %p\n", ret);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
HGLOBAL WINAPI GlobalFree(HGLOBAL hMem) {
|
HGLOBAL WINAPI GlobalFree(HGLOBAL hMem) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
VERBOSE_LOG("GlobalFree(%p)\n", hMem);
|
VERBOSE_LOG("GlobalFree(%p)\n", hMem);
|
||||||
std::free(hMem);
|
if (doFree(hMem)) {
|
||||||
return nullptr;
|
DEBUG_LOG("-> success\n");
|
||||||
|
return nullptr;
|
||||||
|
} else {
|
||||||
|
DEBUG_LOG("-> failure\n");
|
||||||
|
return hMem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HGLOBAL WINAPI GlobalReAlloc(HGLOBAL hMem, SIZE_T dwBytes, UINT uFlags) {
|
HGLOBAL WINAPI GlobalReAlloc(HGLOBAL hMem, SIZE_T dwBytes, UINT uFlags) {
|
||||||
@@ -773,7 +833,9 @@ HGLOBAL WINAPI GlobalReAlloc(HGLOBAL hMem, SIZE_T dwBytes, UINT uFlags) {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
bool zero = (uFlags & GMEM_ZEROINIT) != 0;
|
bool zero = (uFlags & GMEM_ZEROINIT) != 0;
|
||||||
return doRealloc(hMem, static_cast<UINT>(dwBytes), zero);
|
void *ret = doRealloc(hMem, static_cast<UINT>(dwBytes), zero);
|
||||||
|
DEBUG_LOG("-> %p\n", ret);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
UINT WINAPI GlobalFlags(HGLOBAL hMem) {
|
UINT WINAPI GlobalFlags(HGLOBAL hMem) {
|
||||||
|
|||||||
Reference in New Issue
Block a user