In the tcmalloc memory allocator(http://google-perftools.googlecode.com/svn/trunk/doc/tcmalloc.html), deallocation involves a costly lookup to get the size of the deleted object. The size is required to find the right free list to release back the object. By passing the size of the object to the delete call, this lookup can be avoided. This patch adds support for operator delete(void*, size_t) guarded by a -fsized-delete flag. It also adds a default implementation of delete(void *, size_t) that ignores the size parameter.
Bootstraps and no test regressions. OK for google/gcc-4_6 branch? --------------- 2011-12-11 Easwaran Raman <era...@google.com> * common.opt (fsized-delete): New option. cp/ChangeLog.google-4_6: 2011-12-11 Easwaran Raman <era...@google.com> * decl.c (cxx_init_decl_processing): Specify a function that takes a void* and size_t for DELETE_EXPR. * call.c (build_op_delete_call): If fsized-delete is used, use the variant that takes size_t as the second parameter except when deleteting a pointer of type void *. testsuite/ChangeLog.google-4_6: 2011-12-11 Easwaran Raman <era...@google.com> * g++.dg/other/sized-delete-1.C: New test. libstdc++-v3/ChangeLog.google-4_6: 2011-12-11 Easwaran Raman <era...@google.com> * libsupc++/del_op.cc (delete): Define a new variant void operator delete(void*, std::size_t). * libsupc++/new (delete): Declare void operator delete(void*, std::size_t) throw(); * testsuite/util/testsuite_abi.cc (check_version): Add new known version GLIBCXX_3.4.17. * config/abi/post/x86_64-linux-gnu/baseline_symbols.txt: Add new symbol _ZdlPvm@@GLIBCXX_3.4.17. * config/abi/pre/gnu.ver: Add new symbol _ZdlPvm at version GLIBCXX_3.4.17.
Index: libstdc++-v3/libsupc++/del_op.cc =================================================================== --- libstdc++-v3/libsupc++/del_op.cc (revision 182213) +++ libstdc++-v3/libsupc++/del_op.cc (working copy) @@ -46,3 +46,11 @@ operator delete(void* ptr) throw () if (ptr) std::free(ptr); } + +_GLIBCXX_WEAK_DEFINITION void +operator delete(void* ptr, + std::size_t bytes __attribute__((__unused__))) throw () +{ + if (ptr) + std::free(ptr); +} Index: libstdc++-v3/libsupc++/new =================================================================== --- libstdc++-v3/libsupc++/new (revision 182213) +++ libstdc++-v3/libsupc++/new (working copy) @@ -93,6 +93,7 @@ namespace std void* operator new(std::size_t) throw (std::bad_alloc); void* operator new[](std::size_t) throw (std::bad_alloc); void operator delete(void*) throw(); +void operator delete(void*, std::size_t) throw(); void operator delete[](void*) throw(); void* operator new(std::size_t, const std::nothrow_t&) throw(); void* operator new[](std::size_t, const std::nothrow_t&) throw(); Index: libstdc++-v3/testsuite/util/testsuite_abi.cc =================================================================== --- libstdc++-v3/testsuite/util/testsuite_abi.cc (revision 182213) +++ libstdc++-v3/testsuite/util/testsuite_abi.cc (working copy) @@ -194,6 +194,7 @@ check_version(symbol& test, bool added) known_versions.push_back("GLIBCXX_3.4.14"); known_versions.push_back("GLIBCXX_3.4.15"); known_versions.push_back("GLIBCXX_3.4.16"); + known_versions.push_back("GLIBCXX_3.4.17"); known_versions.push_back("GLIBCXX_LDBL_3.4"); known_versions.push_back("GLIBCXX_LDBL_3.4.7"); known_versions.push_back("GLIBCXX_LDBL_3.4.10"); @@ -560,4 +561,3 @@ demangle(const std::string& mangled) } return name; } - Index: libstdc++-v3/config/abi/post/x86_64-linux-gnu/baseline_symbols.txt =================================================================== --- libstdc++-v3/config/abi/post/x86_64-linux-gnu/baseline_symbols.txt (revision 182213) +++ libstdc++-v3/config/abi/post/x86_64-linux-gnu/baseline_symbols.txt (working copy) @@ -2422,6 +2422,7 @@ FUNC:_ZTv0_n24_NSt9strstreamD1Ev@@GLIBCXX_3.4 FUNC:_ZdaPv@@GLIBCXX_3.4 FUNC:_ZdaPvRKSt9nothrow_t@@GLIBCXX_3.4 FUNC:_ZdlPv@@GLIBCXX_3.4 +FUNC:_ZdlPvm@@GLIBCXX_3.4.17 FUNC:_ZdlPvRKSt9nothrow_t@@GLIBCXX_3.4 FUNC:_Znam@@GLIBCXX_3.4 FUNC:_ZnamRKSt9nothrow_t@@GLIBCXX_3.4 Index: libstdc++-v3/config/abi/pre/gnu.ver =================================================================== --- libstdc++-v3/config/abi/pre/gnu.ver (revision 182213) +++ libstdc++-v3/config/abi/pre/gnu.ver (working copy) @@ -1279,6 +1279,13 @@ GLIBCXX_3.4.16 { } GLIBCXX_3.4.15; +GLIBCXX_3.4.17 { + + # operator delete(void*, , unsigned long) + _ZdlPvm; + +} GLIBCXX_3.4.16; + # Symbols in the support library (libsupc++) have their own tag. CXXABI_1.3 { Index: gcc/testsuite/g++.dg/other/sized-delete-1.C =================================================================== --- gcc/testsuite/g++.dg/other/sized-delete-1.C (revision 0) +++ gcc/testsuite/g++.dg/other/sized-delete-1.C (revision 0) @@ -0,0 +1,14 @@ +// { dg-do link} +// { dg-options "-O -fsized-delete" } +// { dg-final { scan-assembler "_ZdlPv\[mj\]" } } +struct A +{ + int a[100]; +}; + +int main(void) +{ + A *a = new A; + delete a; + return 0; +} Index: gcc/cp/decl.c =================================================================== --- gcc/cp/decl.c (revision 182213) +++ gcc/cp/decl.c (working copy) @@ -3519,6 +3519,7 @@ cxx_init_decl_processing (void) { tree void_ftype; tree void_ftype_ptr; + tree void_ftype_ptr_sizetype; build_common_tree_nodes (flag_signed_char); @@ -3584,8 +3585,14 @@ cxx_init_decl_processing (void) void_ftype = build_function_type_list (void_type_node, NULL_TREE); void_ftype_ptr = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE); + void_ftype_ptr_sizetype = build_function_type_list (void_type_node, + ptr_type_node, + size_type_node, + NULL_TREE); void_ftype_ptr = build_exception_variant (void_ftype_ptr, empty_except_spec); + void_ftype_ptr_sizetype + = build_exception_variant (void_ftype_ptr_sizetype, empty_except_spec); /* C++ extensions */ @@ -3635,7 +3642,7 @@ cxx_init_decl_processing (void) current_lang_name = lang_name_cplusplus; { - tree newtype, deltype; + tree newtype, deltype, deltype2; tree ptr_ftype_sizetype; tree new_eh_spec; @@ -3664,8 +3671,10 @@ cxx_init_decl_processing (void) newtype = build_exception_variant (ptr_ftype_sizetype, new_eh_spec); deltype = build_exception_variant (void_ftype_ptr, empty_except_spec); + deltype2 = build_exception_variant (void_ftype_ptr_sizetype, empty_except_spec); push_cp_library_fn (NEW_EXPR, newtype); push_cp_library_fn (VEC_NEW_EXPR, newtype); + push_cp_library_fn (DELETE_EXPR, deltype2); global_delete_fndecl = push_cp_library_fn (DELETE_EXPR, deltype); push_cp_library_fn (VEC_DELETE_EXPR, deltype); Index: gcc/cp/call.c =================================================================== --- gcc/cp/call.c (revision 182213) +++ gcc/cp/call.c (working copy) @@ -5264,8 +5264,22 @@ build_op_delete_call (enum tree_code code, tree ad usual deallocation function." So (void*) beats (void*, size_t). */ - if (FUNCTION_ARG_CHAIN (fn) == void_list_node) - break; + /* If type is not void, pick (void*, size_t) version (which comes + first). */ + if (!flag_sized_delete || TREE_CODE (type) == VOID_TYPE ) + { + /* If -fsized-delete is not passed or if a void * is deleted, + prefer delete (void *) version. */ + if (FUNCTION_ARG_CHAIN (fn) == void_list_node) + break; + } + else + { + /* If -fsized-delete is passed and it is not a void *, + prefer delete (void *, size_t) version. */ + if (FUNCTION_ARG_CHAIN (fn) != void_list_node) + break; + } } } Index: gcc/common.opt =================================================================== --- gcc/common.opt (revision 182213) +++ gcc/common.opt (working copy) @@ -1898,6 +1898,10 @@ fsingle-precision-constant Common Report Var(flag_single_precision_constant) Optimization Convert floating point constants to single precision constants +fsized-delete +Common Report Var(flag_sized_delete) Optimization +Support delete operator with objetc's size as the second parameter. + fsplit-ivs-in-unroller Common Report Var(flag_split_ivs_in_unroller) Init(1) Optimization Split lifetimes of induction variables when loops are unrolled