From Craig Silverstein: Minimal --script implementation.
[deliverable/binutils-gdb.git] / gold / stringpool.cc
index c0a4ae72c99973006b417394a394a082593fba34..bb571f0fba2e90d80dd5b1ae76333d8018ab282b 100644 (file)
@@ -1,5 +1,25 @@
 // stringpool.cc -- a string pool for gold
 
+// Copyright 2006, 2007 Free Software Foundation, Inc.
+// Written by Ian Lance Taylor <iant@google.com>.
+
+// This file is part of gold.
+
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+// MA 02110-1301, USA.
+
 #include "gold.h"
 
 #include <cstring>
@@ -7,6 +27,7 @@
 #include <vector>
 
 #include "output.h"
+#include "parameters.h"
 #include "stringpool.h"
 
 namespace gold
@@ -15,7 +36,7 @@ namespace gold
 template<typename Stringpool_char>
 Stringpool_template<Stringpool_char>::Stringpool_template()
   : string_set_(), strings_(), strtab_size_(0), next_index_(1),
-    zero_null_(true)
+    next_uncopied_key_(-1), zero_null_(true)
 {
 }
 
@@ -90,7 +111,7 @@ Stringpool_template<Stringpool_char>::Stringpool_hash::operator()(
          const char* p = reinterpret_cast<const char*>(s);
          for (size_t i = 0; i < sizeof(Stringpool_char); ++i)
            {
-             result &= (size_t) *p++;
+             result ^= (size_t) *p++;
              result *= 1099511628211ULL;
            }
          ++s;
@@ -184,7 +205,8 @@ Stringpool_template<Stringpool_char>::add_string(const Stringpool_char* s,
 
 template<typename Stringpool_char>
 const Stringpool_char*
-Stringpool_template<Stringpool_char>::add(const Stringpool_char* s, Key* pkey)
+Stringpool_template<Stringpool_char>::add(const Stringpool_char* s, bool copy,
+                                          Key* pkey)
 {
   // FIXME: This will look up the entry twice in the hash table.  The
   // problem is that we can't insert S before we canonicalize it.  I
@@ -201,7 +223,15 @@ Stringpool_template<Stringpool_char>::add(const Stringpool_char* s, Key* pkey)
     }
 
   Key k;
-  const Stringpool_char* ret = this->add_string(s, &k);
+  const Stringpool_char* ret;
+  if (copy)
+    ret = this->add_string(s, &k);
+  else
+    {
+      ret = s;
+      k = this->next_uncopied_key_;
+      --this->next_uncopied_key_;
+    }
 
   const off_t ozero = 0;
   std::pair<const Stringpool_char*, Val> element(ret,
@@ -220,13 +250,14 @@ Stringpool_template<Stringpool_char>::add(const Stringpool_char* s, Key* pkey)
 
 template<typename Stringpool_char>
 const Stringpool_char*
-Stringpool_template<Stringpool_char>::add(const Stringpool_char* s, size_t len,
-                                Key* pkey)
+Stringpool_template<Stringpool_char>::add_prefix(const Stringpool_char* s,
+                                                 size_t len,
+                                                 Key* pkey)
 {
   // FIXME: This implementation should be rewritten when we rewrite
   // the hash table to avoid copying.
   std::basic_string<Stringpool_char> st(s, len);
-  return this->add(st, pkey);
+  return this->add(st.c_str(), true, pkey);
 }
 
 template<typename Stringpool_char>
@@ -303,42 +334,65 @@ Stringpool_template<Stringpool_char>::set_string_offsets()
       return;
     }
 
-  size_t count = this->string_set_.size();
-
-  std::vector<Stringpool_sort_info> v;
-  v.reserve(count);
-
-  for (typename String_set_type::iterator p = this->string_set_.begin();
-       p != this->string_set_.end();
-       ++p)
-    v.push_back(Stringpool_sort_info(p, string_length(p->first)));
-
-  std::sort(v.begin(), v.end(), Stringpool_sort_comparison());
-
   const size_t charsize = sizeof(Stringpool_char);
 
   // Offset 0 may be reserved for the empty string.
   off_t offset = this->zero_null_ ? charsize : 0;
 
-  for (typename std::vector<Stringpool_sort_info>::iterator last = v.end(),
-         curr = v.begin();
-       curr != v.end();
-       last = curr++)
+  // Sorting to find suffixes can take over 25% of the total CPU time
+  // used by the linker.  Since it's merely an optimization to reduce
+  // the strtab size, and gives a relatively small benefit (it's
+  // typically rare for a symbol to be a suffix of another), we only
+  // take the time to sort when the user asks for heavy optimization.
+  if (parameters->optimization_level() < 2)
     {
-      if (this->zero_null_ && curr->it->first[0] == 0)
-       curr->it->second.second = 0;
-      else if (last != v.end()
-               && is_suffix(curr->it->first, curr->string_length,
-                            last->it->first, last->string_length))
-       curr->it->second.second = (last->it->second.second
-                                   + ((last->string_length
-                                       - curr->string_length)
-                                      * charsize));
-      else
-       {
-         curr->it->second.second = offset;
-         offset += (curr->string_length + 1) * charsize;
-       }
+      for (typename String_set_type::iterator curr = this->string_set_.begin();
+           curr != this->string_set_.end();
+           curr++)
+        {
+          if (this->zero_null_ && curr->first[0] == 0)
+            curr->second.second = 0;
+          else
+            {
+              curr->second.second = offset;
+              offset += (string_length(curr->first) + 1) * charsize;
+            }
+        }
+    }
+  else
+    {
+      size_t count = this->string_set_.size();
+
+      std::vector<Stringpool_sort_info> v;
+      v.reserve(count);
+
+      for (typename String_set_type::iterator p = this->string_set_.begin();
+           p != this->string_set_.end();
+           ++p)
+        v.push_back(Stringpool_sort_info(p, string_length(p->first)));
+
+      std::sort(v.begin(), v.end(), Stringpool_sort_comparison());
+
+      for (typename std::vector<Stringpool_sort_info>::iterator last = v.end(),
+             curr = v.begin();
+           curr != v.end();
+           last = curr++)
+        {
+          if (this->zero_null_ && curr->it->first[0] == 0)
+            curr->it->second.second = 0;
+          else if (last != v.end()
+                   && is_suffix(curr->it->first, curr->string_length,
+                                last->it->first, last->string_length))
+            curr->it->second.second = (last->it->second.second
+                                       + ((last->string_length
+                                           - curr->string_length)
+                                          * charsize));
+          else
+            {
+              curr->it->second.second = offset;
+              offset += (curr->string_length + 1) * charsize;
+            }
+        }
     }
 
   this->strtab_size_ = offset;
This page took 0.025778 seconds and 4 git commands to generate.