#include "config.h"
#include "FastMalloc.h"
#include "CheckedArithmetic.h"
#include "CurrentTime.h"
#include <limits>
#include <string.h>
#include <wtf/DataLog.h>
#if OS(WINDOWS)
#include <windows.h>
#else
#include <pthread.h>
#endif
#if OS(DARWIN)
#include <mach/mach_init.h>
#include <malloc/malloc.h>
#endif
namespace WTF {
void* fastZeroedMalloc(size_t n)
{
void* result = fastMalloc(n);
memset(result, 0, n);
return result;
}
char* fastStrDup(const char* src)
{
size_t len = strlen(src) + 1;
char* dup = static_cast<char*>(fastMalloc(len));
memcpy(dup, src, len);
return dup;
}
TryMallocReturnValue tryFastZeroedMalloc(size_t n)
{
void* result;
if (!tryFastMalloc(n).getValue(result))
return 0;
memset(result, 0, n);
return result;
}
}
#if defined(USE_SYSTEM_MALLOC) && USE_SYSTEM_MALLOC
#if OS(WINDOWS)
#include <malloc.h>
#endif
namespace WTF {
size_t fastMallocGoodSize(size_t bytes)
{
#if OS(DARWIN)
return malloc_good_size(bytes);
#else
return bytes;
#endif
}
#if OS(WINDOWS)
void* fastAlignedMalloc(size_t alignment, size_t size)
{
return _aligned_malloc(size, alignment);
}
void fastAlignedFree(void* p)
{
_aligned_free(p);
}
#else
void* fastAlignedMalloc(size_t alignment, size_t size)
{
void* p = nullptr;
posix_memalign(&p, alignment, size);
return p;
}
void fastAlignedFree(void* p)
{
free(p);
}
#endif // OS(WINDOWS)
TryMallocReturnValue tryFastMalloc(size_t n)
{
return malloc(n);
}
void* fastMalloc(size_t n)
{
void* result = malloc(n);
if (!result)
CRASH();
return result;
}
TryMallocReturnValue tryFastCalloc(size_t n_elements, size_t element_size)
{
return calloc(n_elements, element_size);
}
void* fastCalloc(size_t n_elements, size_t element_size)
{
void* result = calloc(n_elements, element_size);
if (!result)
CRASH();
return result;
}
void fastFree(void* p)
{
free(p);
}
void* fastRealloc(void* p, size_t n)
{
void* result = realloc(p, n);
if (!result)
CRASH();
return result;
}
void releaseFastMallocFreeMemory() { }
void releaseFastMallocFreeMemoryForThisThread() { }
FastMallocStatistics fastMallocStatistics()
{
FastMallocStatistics statistics = { 0, 0, 0 };
return statistics;
}
size_t fastMallocSize(const void* p)
{
#if OS(DARWIN)
return malloc_size(p);
#elif OS(WINDOWS)
return _msize(const_cast<void*>(p));
#else
UNUSED_PARAM(p);
return 1;
#endif
}
}
#else // defined(USE_SYSTEM_MALLOC) && USE_SYSTEM_MALLOC
#include <bmalloc/bmalloc.h>
namespace WTF {
void* fastMalloc(size_t size)
{
return bmalloc::api::malloc(size);
}
void* fastCalloc(size_t numElements, size_t elementSize)
{
Checked<size_t> checkedSize = elementSize;
checkedSize *= numElements;
void* result = fastZeroedMalloc(checkedSize.unsafeGet());
if (!result)
CRASH();
return result;
}
void* fastRealloc(void* object, size_t size)
{
return bmalloc::api::realloc(object, size);
}
void fastFree(void* object)
{
bmalloc::api::free(object);
}
size_t fastMallocSize(const void*)
{
return 1;
}
size_t fastMallocGoodSize(size_t size)
{
return size;
}
void* fastAlignedMalloc(size_t alignment, size_t size)
{
return bmalloc::api::memalign(alignment, size);
}
void fastAlignedFree(void* p)
{
bmalloc::api::free(p);
}
TryMallocReturnValue tryFastMalloc(size_t size)
{
return bmalloc::api::tryMalloc(size);
}
TryMallocReturnValue tryFastCalloc(size_t numElements, size_t elementSize)
{
Checked<size_t, RecordOverflow> checkedSize = elementSize;
checkedSize *= numElements;
if (checkedSize.hasOverflowed())
return nullptr;
return tryFastZeroedMalloc(checkedSize.unsafeGet());
}
void releaseFastMallocFreeMemoryForThisThread()
{
bmalloc::api::scavengeThisThread();
}
void releaseFastMallocFreeMemory()
{
bmalloc::api::scavenge();
}
FastMallocStatistics fastMallocStatistics()
{
FastMallocStatistics statistics = { 0, 0, 0 };
return statistics;
}
}
#endif // defined(USE_SYSTEM_MALLOC) && USE_SYSTEM_MALLOC