RFC: Speeding up libstdc++.so with --dynamic-list-data
H. J. Lu
hjl@lucon.org
Tue Jan 9 22:57:00 GMT 2007
On Tue, Jan 09, 2007 at 07:52:42AM -0800, H. J. Lu wrote:
> >
> > What about just --dynamic-list-cpp that enables the new behavior and
> > implies --dynamic-list-cpp-typeinfo (I know that it is useless in this
> > particular case, since C++ typeinfo is data, but in general such an
> > option sounds more useful than only --dynamic-list-cpp-new).
>
> I think you only need --dynamic-list-cpp-new for building libstdc++.so.
> -Bsymbolic-functions should be sufficient for other C++ shared
> libraries.
>
Here is a patch for --dynamic-list-cpp-new with a testcase.
H.J.
---
ld/
2007-01-09 H.J. Lu <hongjiu.lu@intel.com>
* NEWS: Mention --dynamic-list-cpp-new.
* ld.texinfo: Document --dynamic-list-cpp-new.
* ldlang.c (lang_append_dynamic_list_cpp_new): New.
* ldlang.h (lang_append_dynamic_list_cpp_new): Likewise.
* lexsup.c (option_values): Add OPTION_DYNAMIC_LIST_CPP_NEW.
(ld_options): Add entry for --dynamic-list-cpp-new.
(parse_args): Handle OPTION_DYNAMIC_LIST_CPP_NEW.
ld/testsuite/
2007-01-09 H.J. Lu <hongjiu.lu@intel.com>
* ld-elf/del.cc: New.
* ld-elf/dl5.cc: Likewise.
* ld-elf/dl5.out: Likewise.
* ld-elf/new.cc: Likewise.
* ld-elf/shared.exp: Add --dynamic-list-cpp-new testcase.
--- ld/NEWS.new 2007-01-09 11:34:46.000000000 -0800
+++ ld/NEWS 2007-01-09 11:34:53.000000000 -0800
@@ -1,4 +1,7 @@
-*- text -*-
+* ELF: Add --dynamic-list-cpp-new, which puts C++ operator new and
+ delete on the dynamic list.
+
* ELF: Add -Bsymbolic-functions and --dynamic-list-data, builtin list
for --dynamic-list, which puts global data symbols on the dynamic list.
--- ld/ld.texinfo.new 2007-01-09 11:22:59.000000000 -0800
+++ ld/ld.texinfo 2007-01-09 11:31:50.000000000 -0800
@@ -1155,6 +1155,11 @@ scope and node name. See @ref{VERSION}
@item --dynamic-list-data
Include all global data symbols to the dynamic list.
+@kindex --dynamic-list-cpp-new
+@item --dynamic-list-cpp-new
+Provide the builtin dynamic list for C++ operator new and delete. It
+is mainly useful for building shared libstdc++.
+
@kindex --dynamic-list-cpp-typeinfo
@item --dynamic-list-cpp-typeinfo
Provide the builtin dynamic list for C++ runtime type identification.
--- ld/ldlang.c.new 2007-01-09 11:22:59.000000000 -0800
+++ ld/ldlang.c 2007-01-09 11:22:59.000000000 -0800
@@ -7086,3 +7086,24 @@ lang_append_dynamic_list_cpp_typeinfo (v
lang_append_dynamic_list (dynamic);
}
+
+/* Append the list of C++ operator new and delete dynamic symbols to the
+ existing one. */
+
+void
+lang_append_dynamic_list_cpp_new (void)
+{
+ const char * symbols [] =
+ {
+ "operator new*",
+ "operator delete*"
+ };
+ struct bfd_elf_version_expr *dynamic = NULL;
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE (symbols); i++)
+ dynamic = lang_new_vers_pattern (dynamic, symbols [i], "C++",
+ FALSE);
+
+ lang_append_dynamic_list (dynamic);
+}
--- ld/ldlang.h.new 2006-10-24 23:49:21.000000000 -0700
+++ ld/ldlang.h 2007-01-09 11:22:59.000000000 -0800
@@ -607,6 +607,7 @@ extern void lang_register_vers_node
(const char *, struct bfd_elf_version_tree *, struct bfd_elf_version_deps *);
extern void lang_append_dynamic_list (struct bfd_elf_version_expr *);
extern void lang_append_dynamic_list_cpp_typeinfo (void);
+extern void lang_append_dynamic_list_cpp_new (void);
bfd_boolean unique_section_p
(const asection *);
extern void lang_add_unique
--- ld/lexsup.c.new 2007-01-09 11:22:59.000000000 -0800
+++ ld/lexsup.c 2007-01-09 11:24:13.000000000 -0800
@@ -108,6 +108,7 @@ enum option_values
OPTION_VERSION_SCRIPT,
OPTION_VERSION_EXPORTS_SECTION,
OPTION_DYNAMIC_LIST,
+ OPTION_DYNAMIC_LIST_CPP_NEW,
OPTION_DYNAMIC_LIST_CPP_TYPEINFO,
OPTION_DYNAMIC_LIST_DATA,
OPTION_WARN_COMMON,
@@ -508,6 +509,8 @@ static const struct ld_option ld_options
'\0', NULL, N_("Bind global function references locally"), ONE_DASH },
{ {"dynamic-list-data", no_argument, NULL, OPTION_DYNAMIC_LIST_DATA},
'\0', NULL, N_("Add data symbols to dynamic list"), TWO_DASHES },
+ { {"dynamic-list-cpp-new", no_argument, NULL, OPTION_DYNAMIC_LIST_CPP_NEW},
+ '\0', NULL, N_("Use C++ operator new/delete dynamic list"), TWO_DASHES },
{ {"dynamic-list-cpp-typeinfo", no_argument, NULL, OPTION_DYNAMIC_LIST_CPP_TYPEINFO},
'\0', NULL, N_("Use C++ typeinfo dynamic list"), TWO_DASHES },
{ {"dynamic-list", required_argument, NULL, OPTION_DYNAMIC_LIST},
@@ -1257,6 +1260,10 @@ parse_args (unsigned argc, char **argv)
lang_append_dynamic_list_cpp_typeinfo ();
link_info.dynamic = TRUE;
break;
+ case OPTION_DYNAMIC_LIST_CPP_NEW:
+ lang_append_dynamic_list_cpp_new ();
+ link_info.dynamic = TRUE;
+ break;
case OPTION_DYNAMIC_LIST:
/* This option indicates a small script that only specifies
a dynamic list. Read it, but don't assume that we've
--- ld/testsuite/ld-elf/del.cc.new 2007-01-09 14:48:18.000000000 -0800
+++ ld/testsuite/ld-elf/del.cc 2007-01-09 12:58:35.000000000 -0800
@@ -0,0 +1,29 @@
+#include <new>
+
+extern "C" void free (void *);
+
+void
+operator delete (void *ptr, const std::nothrow_t&) throw ()
+{
+ if (ptr)
+ free (ptr);
+}
+
+void
+operator delete (void *ptr) throw ()
+{
+ if (ptr)
+ free (ptr);
+}
+
+void
+operator delete[] (void *ptr) throw ()
+{
+ ::operator delete (ptr);
+}
+
+void
+operator delete[] (void *ptr, const std::nothrow_t&) throw ()
+{
+ ::operator delete (ptr);
+}
--- ld/testsuite/ld-elf/dl5.cc.new 2007-01-09 14:48:18.000000000 -0800
+++ ld/testsuite/ld-elf/dl5.cc 2007-01-09 14:46:22.000000000 -0800
@@ -0,0 +1,61 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <new>
+
+int pass = 0;
+
+void *
+operator new (size_t sz, const std::nothrow_t&) throw ()
+{
+ void *p;
+ pass++;
+ p = malloc(sz);
+ return p;
+}
+
+void *
+operator new (size_t sz) throw (std::bad_alloc)
+{
+ void *p;
+ pass++;
+ p = malloc(sz);
+ return p;
+}
+
+void
+operator delete (void *ptr) throw ()
+{
+ pass++;
+ if (ptr)
+ free (ptr);
+}
+
+class A
+{
+public:
+ A() {}
+ ~A() { }
+ int a;
+ int b;
+};
+
+
+int
+main (void)
+{
+ A *bb = new A[10];
+ delete [] bb;
+ bb = new (std::nothrow) A [10];
+ delete [] bb;
+
+ if (pass == 4)
+ {
+ printf ("PASS\n");
+ return 0;
+ }
+ else
+ {
+ printf ("FAIL\n");
+ return 1;
+ }
+}
--- ld/testsuite/ld-elf/dl5.out.new 2007-01-09 14:48:18.000000000 -0800
+++ ld/testsuite/ld-elf/dl5.out 2007-01-09 14:47:38.000000000 -0800
@@ -0,0 +1 @@
+PASS
--- ld/testsuite/ld-elf/new.cc.new 2007-01-09 14:48:18.000000000 -0800
+++ ld/testsuite/ld-elf/new.cc 2007-01-09 11:49:37.000000000 -0800
@@ -0,0 +1,48 @@
+#include <new>
+#include <exception_defines.h>
+
+using std::bad_alloc;
+
+extern "C" void *malloc (std::size_t);
+extern "C" void abort (void);
+
+void *
+operator new (std::size_t sz, const std::nothrow_t&) throw()
+{
+ void *p;
+
+ /* malloc (0) is unpredictable; avoid it. */
+ if (sz == 0)
+ sz = 1;
+ p = (void *) malloc (sz);
+ return p;
+}
+
+void *
+operator new (std::size_t sz) throw (std::bad_alloc)
+{
+ void *p;
+
+ /* malloc (0) is unpredictable; avoid it. */
+ if (sz == 0)
+ sz = 1;
+ p = (void *) malloc (sz);
+ while (p == 0)
+ {
+ ::abort();
+ }
+
+ return p;
+}
+
+void*
+operator new[] (std::size_t sz) throw (std::bad_alloc)
+{
+ return ::operator new(sz);
+}
+
+void *
+operator new[] (std::size_t sz, const std::nothrow_t& nothrow) throw()
+{
+ return ::operator new(sz, nothrow);
+}
--- ld/testsuite/ld-elf/shared.exp.new 2007-01-09 11:22:59.000000000 -0800
+++ ld/testsuite/ld-elf/shared.exp 2007-01-09 14:47:17.000000000 -0800
@@ -171,6 +171,9 @@ set build_cxx_tests {
{"Build libdl3a.so with --dynamic-list-cpp-typeinfo"
"-shared -Wl,--dynamic-list-cpp-typeinfo" "-fPIC"
{dl3.cc} {} "libdl3c.so" "c++"}
+ {"Build libdnew.so with -Bsymbolic-functions -dynamic-list-cpp-new"
+ "-shared -Wl,-Bsymbolic-functions,--dynamic-list-cpp-new" "-fPIC"
+ {del.cc new.cc} {} "libnew.so" "c++"}
}
set run_cxx_tests {
@@ -183,6 +186,9 @@ set run_cxx_tests {
{"Run with libdl3c.so"
"tmpdir/libdl3c.so" ""
{dl3main.cc} "dl3c" "dl3a.out" "" "c++"}
+ {"Run with libnew.so"
+ "tmpdir/libnew.so" ""
+ {dl5.cc} "dl5" "dl5.out" "" "c++"}
}
run_cc_link_tests $build_cxx_tests
More information about the Binutils
mailing list