From Craig Silverstein: rework seen handling to be based on archive
authorIan Lance Taylor <iant@google.com>
Thu, 20 Sep 2007 05:43:14 +0000 (05:43 +0000)
committerIan Lance Taylor <iant@google.com>
Thu, 20 Sep 2007 05:43:14 +0000 (05:43 +0000)
offsets rather than entries in archive symbol table.

gold/archive.cc
gold/archive.h

index 51a0f484453c052c6a4b9ea85d1a1d81cab02422..64523d2712d147a63eed8102ca9fe5f6b69901f9 100644 (file)
@@ -121,10 +121,6 @@ Archive::read_armap(off_t start, off_t size)
              program_name, this->name().c_str());
       gold_exit(false);
     }
-
-  // This array keeps track of which symbols are for archive elements
-  // which we have already included in the link.
-  this->seen_.resize(nsyms);
 }
 
 // Read the header of an archive member at OFF.  Fail if something
@@ -230,6 +226,14 @@ Archive::interpret_header(const Archive_header* hdr, off_t off,
   return member_size;
 }
 
+// A simple hash code for off_t values.
+class Seen_hash
+{
+ public:
+  size_t operator()(off_t val) const
+  { return static_cast<size_t>(val); }
+};
+
 // Select members from the archive and add them to the link.  We walk
 // through the elements in the archive map, and look each one up in
 // the symbol table.  If it exists as a strong undefined symbol, we
@@ -246,18 +250,25 @@ Archive::add_symbols(const General_options& options, Symbol_table* symtab,
 
   const size_t armap_size = this->armap_.size();
 
+  // Track which elements in the archive map have already been included
+  // in the link.  Elements are identified by their offset.
+  Unordered_set<off_t, Seen_hash> seen;
+  // This is a quick optimization, since we usually see many symbols
+  // in a row with the same offset.  last_seen holds the last offset
+  // we saw that was present in the seen_ set.
+  off_t last_seen = -1;
+
   bool added_new_object;
   do
     {
       added_new_object = false;
-      off_t last = -1;
       for (size_t i = 0; i < armap_size; ++i)
        {
-         if (this->seen_[i])
+         if (this->armap_[i].offset == last_seen)
            continue;
-         if (this->armap_[i].offset == last)
+         if (seen.find(this->armap_[i].offset) != seen.end())
            {
-             this->seen_[i] = true;
+             last_seen = this->armap_[i].offset;
              continue;
            }
 
@@ -266,16 +277,18 @@ Archive::add_symbols(const General_options& options, Symbol_table* symtab,
            continue;
          else if (!sym->is_undefined())
            {
-             this->seen_[i] = true;
+             seen.insert(this->armap_[i].offset);
+             last_seen = this->armap_[i].offset;
              continue;
            }
          else if (sym->binding() == elfcpp::STB_WEAK)
            continue;
 
          // We want to include this object in the link.
-         last = this->armap_[i].offset;
-         this->include_member(options, symtab, layout, input_objects, last);
-         this->seen_[i] = true;
+         last_seen = this->armap_[i].offset;
+         seen.insert(last_seen);
+         this->include_member(options, symtab, layout, input_objects,
+                              last_seen);
          added_new_object = true;
        }
     }
index ddd665f070c4800b0ce8cab36001aa0c2fa0a04c..33a7233a9a60595841ef89d42b74df202e95d008 100644 (file)
@@ -123,9 +123,6 @@ class Archive
   std::vector<Armap_entry> armap_;
   // The extended name table.
   std::string extended_names_;
-  // Track which symbols in the archive map are for elements which
-  // have already been included in the link.
-  std::vector<bool> seen_;
 };
 
 // This class is used to read an archive and pick out the desired