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

Reply via email to