implemented (disabled by default) sized delete support

gcc 5 and clang++-3.7 support sized deallocation from C++14. We are
taking advantage of that by defining sized versions of operator delete.

This is off by default so that if some existing programs that define own
global operator delete without sized variant are not broken by
tcmalloc's sized delete operator.

There is also risk of breaking exiting code that deletes objects using
wrong class (i.e. base class) without having virtual destructors.
This commit is contained in:
Aliaksey Kandratsenka 2015-10-04 21:12:28 -07:00
parent fdb443e8e5
commit 1e7b733a21
7 changed files with 59 additions and 10 deletions

View File

@ -323,16 +323,28 @@ 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_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=yes,
perftools_cv_sized_deallocation_result=no)
CXXFLAGS="$OLD_CXXFLAGS"
AC_LANG_POP(C++)])
AC_ARG_ENABLE([sized-delete],
[AS_HELP_STRING([--enable-sized-delete],
[build sized delete operator])],
[enable_sized_delete="$enableval"],
[enable_sized_delete="no"])
AS_IF([test "x$enable_sized_delete" = xyes],
[AC_DEFINE([ENABLE_SIZED_DELETE], 1, [Build sized deletion operators])
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],
[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=no)
CXXFLAGS="$OLD_CXXFLAGS"
AC_LANG_POP(C++)])])
AM_CONDITIONAL(HAVE_SIZED_DEALLOCATION,
test "$perftools_cv_sized_deallocation_result" = yes)

View File

@ -122,12 +122,14 @@ extern "C" {
PERFTOOLS_DLL_DECL void* tc_new_nothrow(size_t size,
const std::nothrow_t&) __THROW;
PERFTOOLS_DLL_DECL void tc_delete(void* p) __THROW;
PERFTOOLS_DLL_DECL void tc_delete_sized(void* p, size_t size) throw();
PERFTOOLS_DLL_DECL void tc_delete_nothrow(void* p,
const std::nothrow_t&) __THROW;
PERFTOOLS_DLL_DECL void* tc_newarray(size_t size);
PERFTOOLS_DLL_DECL void* tc_newarray_nothrow(size_t size,
const std::nothrow_t&) __THROW;
PERFTOOLS_DLL_DECL void tc_deletearray(void* p) __THROW;
PERFTOOLS_DLL_DECL void tc_deletearray_sized(void* p, size_t size) throw();
PERFTOOLS_DLL_DECL void tc_deletearray_nothrow(void* p,
const std::nothrow_t&) __THROW;
}

View File

@ -71,6 +71,13 @@ 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
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
extern "C" {
void* malloc(size_t size) __THROW ALIAS(tc_malloc);
void free(void* ptr) __THROW ALIAS(tc_free);

View File

@ -66,6 +66,12 @@ void operator delete(void* ptr, const std::nothrow_t& nt) __THROW {
void operator delete[](void* ptr, const std::nothrow_t& nt) __THROW {
return tc_deletearray_nothrow(ptr, nt);
}
#ifdef ENABLE_SIZED_DELETE
void operator delete(void* p, size_t s) __THROW { tc_delete_sized(p, s); }
void operator delete[](void* p, size_t s) __THROW{ tc_deletearray_sized(p); }
#endif
extern "C" {
void* malloc(size_t s) __THROW { return tc_malloc(s); }
void free(void* p) __THROW { tc_free(p); }

View File

@ -1595,6 +1595,24 @@ extern "C" PERFTOOLS_DLL_DECL void tc_free_sized(void *ptr, size_t size) __THROW
do_free_with_callback(ptr, &InvalidFree, true, size);
}
#if defined(__GNUC__) && !defined(WIN32)
extern "C" PERFTOOLS_DLL_DECL void tc_delete_sized(void *p, size_t size) throw()
__attribute__((alias("tc_free_sized")));
extern "C" PERFTOOLS_DLL_DECL void tc_deletearray_sized(void *p, size_t size) throw()
__attribute__((alias("tc_free_sized")));
#else
extern "C" PERFTOOLS_DLL_DECL void tc_delete_sized(void *p, size_t size) throw() {
tc_free_sized(p, size);
}
extern "C" PERFTOOLS_DLL_DECL void tc_deletearray_sized(void *p, size_t size) throw() {
tc_free_sized(p, size);
}
#endif
extern "C" PERFTOOLS_DLL_DECL void* tc_calloc(size_t n,
size_t elem_size) __THROW {
void* result = do_calloc(n, elem_size);

View File

@ -112,12 +112,14 @@ extern "C" {
PERFTOOLS_DLL_DECL void* tc_new_nothrow(size_t size,
const std::nothrow_t&) __THROW;
PERFTOOLS_DLL_DECL void tc_delete(void* p) __THROW;
PERFTOOLS_DLL_DECL void tc_delete_sized(void* p, size_t size) throw();
PERFTOOLS_DLL_DECL void tc_delete_nothrow(void* p,
const std::nothrow_t&) __THROW;
PERFTOOLS_DLL_DECL void* tc_newarray(size_t size);
PERFTOOLS_DLL_DECL void* tc_newarray_nothrow(size_t size,
const std::nothrow_t&) __THROW;
PERFTOOLS_DLL_DECL void tc_deletearray(void* p) __THROW;
PERFTOOLS_DLL_DECL void tc_deletearray_sized(void* p, size_t size) throw();
PERFTOOLS_DLL_DECL void tc_deletearray_nothrow(void* p,
const std::nothrow_t&) __THROW;
}

View File

@ -112,12 +112,14 @@ extern "C" {
PERFTOOLS_DLL_DECL void* tc_new_nothrow(size_t size,
const std::nothrow_t&) __THROW;
PERFTOOLS_DLL_DECL void tc_delete(void* p) __THROW;
PERFTOOLS_DLL_DECL void tc_delete_sized(void* p, size_t size) throw();
PERFTOOLS_DLL_DECL void tc_delete_nothrow(void* p,
const std::nothrow_t&) __THROW;
PERFTOOLS_DLL_DECL void* tc_newarray(size_t size);
PERFTOOLS_DLL_DECL void* tc_newarray_nothrow(size_t size,
const std::nothrow_t&) __THROW;
PERFTOOLS_DLL_DECL void tc_deletearray(void* p) __THROW;
PERFTOOLS_DLL_DECL void tc_deletearray_sized(void* p, size_t size) throw();
PERFTOOLS_DLL_DECL void tc_deletearray_nothrow(void* p,
const std::nothrow_t&) __THROW;
}