PR ld/10515
[binutils-gdb.git] / gold / stringpool.cc
index 0e92ec1cf729797e573a119662bc96f1f39a15f9..05d1d68e5d5a3ceba1d98313fdc6f5eec060dd64 100644 (file)
@@ -1,6 +1,6 @@
 // stringpool.cc -- a string pool for gold
 
-// Copyright 2006, 2007 Free Software Foundation, Inc.
+// Copyright 2006, 2007, 2008 Free Software Foundation, Inc.
 // Written by Ian Lance Taylor <iant@google.com>.
 
 // This file is part of gold.
@@ -36,8 +36,10 @@ namespace gold
 template<typename Stringpool_char>
 Stringpool_template<Stringpool_char>::Stringpool_template()
   : string_set_(), key_to_offset_(), strings_(), strtab_size_(0),
-    zero_null_(true)
+    zero_null_(true), optimize_(false)
 {
+  if (parameters->options_valid() && parameters->options().optimize() >= 2)
+    this->optimize_ = true;
 }
 
 template<typename Stringpool_char>
@@ -151,28 +153,16 @@ size_t
 Stringpool_template<Stringpool_char>::string_hash(const Stringpool_char* s,
                                                  size_t length)
 {
-  // Fowler/Noll/Vo (FNV) hash (type FNV-1a).
+  // This is the hash function used by the dynamic linker for
+  // DT_GNU_HASH entries.  I compared this to a Fowler/Noll/Vo hash
+  // for a C++ program with 385,775 global symbols.  This hash
+  // function was very slightly worse.  However, it is much faster to
+  // compute.  Overall wall clock time was a win.
   const unsigned char* p = reinterpret_cast<const unsigned char*>(s);
-  if (sizeof(size_t) > 4)
-    {
-      size_t result = static_cast<size_t>(14695981039346656037ULL);
-      for (size_t i = 0; i < length * sizeof(Stringpool_char); ++i)
-       {
-         result ^= static_cast<size_t>(*p++);
-         result *= 1099511628211ULL;
-       }
-      return result;
-    }
-  else
-    {
-      size_t result = 2166136261UL;
-      for (size_t i = 0; i < length * sizeof(Stringpool_char); ++i)
-       {
-         result ^= static_cast<size_t>(*p++);
-         result *= 16777619UL;
-       }
-      return result;
-    }
+  size_t h = 5381;
+  for (size_t i = 0; i < length * sizeof(Stringpool_char); ++i)
+    h = h * 33 + *p++;
+  return h;
 }
 
 // Add the string S to the list of canonical strings.  Return a
@@ -260,7 +250,8 @@ Stringpool_template<Stringpool_char>::add_with_length(const Stringpool_char* s,
 {
   typedef std::pair<typename String_set_type::iterator, bool> Insert_type;
 
-  const Key k = this->key_to_offset_.size();
+  // We add 1 so that 0 is always invalid.
+  const Key k = this->key_to_offset_.size() + 1;
 
   if (!copy)
     {
@@ -406,13 +397,13 @@ Stringpool_template<Stringpool_char>::set_string_offsets()
   // 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->optimize_)
     {
       for (typename String_set_type::iterator curr = this->string_set_.begin();
            curr != this->string_set_.end();
            curr++)
         {
-         section_offset_type* poff = &this->key_to_offset_[curr->second];
+         section_offset_type* poff = &this->key_to_offset_[curr->second - 1];
           if (this->zero_null_ && curr->first.string[0] == 0)
             *poff = 0;
           else
@@ -458,7 +449,7 @@ Stringpool_template<Stringpool_char>::set_string_offsets()
               this_offset = offset;
               offset += ((*curr)->first.length + 1) * charsize;
             }
-         this->key_to_offset_[(*curr)->second] = this_offset;
+         this->key_to_offset_[(*curr)->second - 1] = this_offset;
          last_offset = this_offset;
         }
     }
@@ -487,7 +478,7 @@ Stringpool_template<Stringpool_char>::get_offset_with_length(
   Hashkey hk(s, length);
   typename String_set_type::const_iterator p = this->string_set_.find(hk);
   if (p != this->string_set_.end())
-    return this->key_to_offset_[p->second];
+    return this->key_to_offset_[p->second - 1];
   gold_unreachable();
 }
 
@@ -508,7 +499,7 @@ Stringpool_template<Stringpool_char>::write_to_buffer(
        ++p)
     {
       const int len = (p->first.length + 1) * sizeof(Stringpool_char);
-      const section_offset_type offset = this->key_to_offset_[p->second];
+      const section_offset_type offset = this->key_to_offset_[p->second - 1];
       gold_assert(static_cast<section_size_type>(offset) + len
                  <= this->strtab_size_);
       memcpy(buffer + offset, p->first.string, len);