implemented enabling sized-delete support at runtime
Under gcc 4.5 or greater we're using ifunc function attribute to resolve sized delete operator to either plain delete implementation (default) or to sized delete (if enabled via environment variable TCMALLOC_ENABLE_SIZED_DELETE).
This commit is contained in:
parent
c2a79d063c
commit
6fdfc5a7f4
14
configure.ac
14
configure.ac
|
@ -323,6 +323,16 @@ AC_CACHE_CHECK([if the compiler supports -Wno-unused-result],
|
|||
AM_CONDITIONAL(HAVE_W_NO_UNUSED_RESULT,
|
||||
test "$perftools_cv_w_no_unused_result" = yes)
|
||||
|
||||
AC_ARG_ENABLE([dynamic-sized-delete-support],
|
||||
[AS_HELP_STRING([--disable-dynamic-sized-delete-support],
|
||||
[don't try to build run-time switch for sized delete operator])],
|
||||
[enable_dyn_sized_delete="$enableval"],
|
||||
[enable_dyn_sized_delete=yes])
|
||||
|
||||
AS_IF([test "x$enable_dyn_sized_delete" = xyes],
|
||||
[AC_DEFINE([ENABLE_DYNAMIC_SIZED_DELETE], 1,
|
||||
[Build runtime detection for sized delete])])
|
||||
|
||||
AC_ARG_ENABLE([sized-delete],
|
||||
[AS_HELP_STRING([--enable-sized-delete],
|
||||
[build sized delete operator])],
|
||||
|
@ -333,14 +343,14 @@ AS_IF([test "x$enable_sized_delete" = xyes],
|
|||
AC_MSG_NOTICE([Will build sized deallocation operators])],
|
||||
[AC_MSG_NOTICE([Will not build sized deallocation operators])])
|
||||
|
||||
AS_IF([test "x$enable_sized_delete" = xyes],
|
||||
AS_IF([test "x$enable_sized_delete" = xyes -o "x$enable_dyn_sized_delete" = xyes],
|
||||
[AC_CACHE_CHECK([if C++ compiler supports -fsized-deallocation],
|
||||
perftools_cv_sized_deallocation_result,
|
||||
[AC_LANG_PUSH(C++)
|
||||
OLD_CXXFLAGS="$CXXFLAGS"
|
||||
CXXFLAGS="$CXXFLAGS -fsized-deallocation"
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM(,)],
|
||||
perftools_cv_sized_deallocation_result="$enable_sized_delete",
|
||||
perftools_cv_sized_deallocation_result=yes,
|
||||
perftools_cv_sized_deallocation_result=no)
|
||||
CXXFLAGS="$OLD_CXXFLAGS"
|
||||
AC_LANG_POP(C++)])])
|
||||
|
|
|
@ -44,6 +44,9 @@
|
|||
#endif
|
||||
#include <gperftools/tcmalloc.h>
|
||||
|
||||
#include "getenv_safe.h" // TCMallocGetenvSafe
|
||||
#include "base/commandlineflags.h"
|
||||
|
||||
#ifndef __THROW // I guess we're not on a glibc-like system
|
||||
# define __THROW // __THROW is just an optimization, so ok to make it ""
|
||||
#endif
|
||||
|
@ -71,12 +74,60 @@ void operator delete(void* p, const std::nothrow_t& nt) __THROW
|
|||
void operator delete[](void* p, const std::nothrow_t& nt) __THROW
|
||||
ALIAS(tc_deletearray_nothrow);
|
||||
|
||||
#ifdef ENABLE_SIZED_DELETE
|
||||
#if defined(ENABLE_SIZED_DELETE)
|
||||
|
||||
void operator delete(void *p, size_t size) throw()
|
||||
ALIAS(tc_delete_sized);
|
||||
void operator delete[](void *p, size_t size) throw()
|
||||
ALIAS(tc_deletearray_sized);
|
||||
#endif
|
||||
|
||||
#elif defined(ENABLE_DYNAMIC_SIZED_DELETE) && \
|
||||
(__GNUC__ * 100 + __GNUC_MINOR__) >= 405
|
||||
|
||||
static void delegate_sized_delete(void *p, size_t s) throw() {
|
||||
(operator delete)(p);
|
||||
}
|
||||
|
||||
static void delegate_sized_deletearray(void *p, size_t s) throw() {
|
||||
(operator delete[])(p);
|
||||
}
|
||||
|
||||
extern "C" __attribute__((weak))
|
||||
int tcmalloc_sized_delete_enabled(void);
|
||||
|
||||
static bool sized_delete_enabled(void) {
|
||||
if (tcmalloc_sized_delete_enabled != 0) {
|
||||
return !!tcmalloc_sized_delete_enabled();
|
||||
}
|
||||
|
||||
const char *flag = TCMallocGetenvSafe("TCMALLOC_ENABLE_SIZED_DELETE");
|
||||
return tcmalloc::commandlineflags::StringToBool(flag, false);
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
static void *resolve_delete_sized(void) {
|
||||
if (sized_delete_enabled()) {
|
||||
return reinterpret_cast<void *>(tc_delete_sized);
|
||||
}
|
||||
return reinterpret_cast<void *>(delegate_sized_delete);
|
||||
}
|
||||
|
||||
static void *resolve_deletearray_sized(void) {
|
||||
if (sized_delete_enabled()) {
|
||||
return reinterpret_cast<void *>(tc_deletearray_sized);
|
||||
}
|
||||
return reinterpret_cast<void *>(delegate_sized_deletearray);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void operator delete(void *p, size_t size) throw()
|
||||
__attribute__((ifunc("resolve_delete_sized")));
|
||||
void operator delete[](void *p, size_t size) throw()
|
||||
__attribute__((ifunc("resolve_deletearray_sized")));
|
||||
|
||||
#endif /* !ENABLE_SIZED_DELETE && !ENABLE_DYN_SIZED_DELETE */
|
||||
|
||||
extern "C" {
|
||||
void* malloc(size_t size) __THROW ALIAS(tc_malloc);
|
||||
|
|
|
@ -77,4 +77,8 @@ echo -n "Testing $TCMALLOC_UNITTEST with TCMALLOC_HEAP_LIMIT_MB=512 ... "
|
|||
|
||||
TCMALLOC_HEAP_LIMIT_MB=512 run_unittest
|
||||
|
||||
echo -n "Testing $TCMALLOC_UNITTEST with TCMALLOC_ENABLE_SIZED_DELETE=t ..."
|
||||
|
||||
TCMALLOC_ENABLE_SIZED_DELETE=t run_unittest
|
||||
|
||||
echo "PASS"
|
||||
|
|
Loading…
Reference in New Issue