diff --git a/input_files.cc b/input_files.cc index 87786194..1ab64ded 100644 --- a/input_files.cc +++ b/input_files.cc @@ -60,9 +60,9 @@ void ObjectFile::initialize_sections() { if (entries[0] != GRP_COMDAT) error(toString(this) + ": unsupported SHT_GROUP format"); - static ConcurrentMap map; - bool *handle = map.insert(signature, false); - comdat_groups.push_back({handle, entries}); + static ConcurrentMap map; + ComdatGroup *group = map.insert(signature, ComdatGroup(this, i)); + comdat_groups.push_back({group, i}); num_comdats++; break; } @@ -120,6 +120,14 @@ void ObjectFile::initialize_symbols() { } } +void ObjectFile::remove_comdat_members(uint32_t section_idx) { + const ELF64LE::Shdr &shdr = elf_sections[section_idx]; + ArrayRef entries = + CHECK(obj.template getSectionContentsAsArray(shdr), this); + for (uint32_t i : entries) + sections[i] = nullptr; +} + void ObjectFile::read_string_pieces(const ELF64LE::Shdr &shdr) { static ConcurrentMap map1; static ConcurrentMap map2; @@ -208,17 +216,28 @@ void ObjectFile::register_undefined_symbols() { } void ObjectFile::eliminate_duplicate_comdat_groups() { - for (std::pair> pair : comdat_groups) { - bool *handle = pair.first; - ArrayRef entries = pair.second; + for (auto &pair : comdat_groups) { + ComdatGroup *g = pair.first; + uint32_t section_idx = pair.second; - if (!*handle) { - *handle = true; - continue; + ObjectFile *file = nullptr; + uint32_t idx = 0; + + while (g->lock.test_and_set(std::memory_order_acquire)); + if (g->file == nullptr) { + g->file = this; + g->section_idx = section_idx; + } else if (g->file->priority < this->priority) { + file = this; + idx = section_idx; + } else { + file = g->file; + idx = g->section_idx; } - - for (uint32_t i : entries) - sections[i] = nullptr; + g->lock.clear(std::memory_order_release); + + if (file) + file->remove_comdat_members(idx); } } diff --git a/main.cc b/main.cc index 7049d595..add8dbf0 100644 --- a/main.cc +++ b/main.cc @@ -224,8 +224,7 @@ int main(int argc, char **argv) { // Eliminate duplicate comdat groups. comdat_timer.startTimer(); - for (ObjectFile *file : files) - file->eliminate_duplicate_comdat_groups(); + for_each(files, [](ObjectFile *file) { file->eliminate_duplicate_comdat_groups(); }); comdat_timer.stopTimer(); // Bin input sections into output sections diff --git a/mold.h b/mold.h index 73ef9ff4..dc596976 100644 --- a/mold.h +++ b/mold.h @@ -349,10 +349,21 @@ extern StringTableSection *shstrtab; // input_files.cc // -class StringPiece { -public: +struct ComdatGroup { + ComdatGroup(ObjectFile *file, uint32_t i) + : file(file), section_idx(i) {} + ComdatGroup(const ComdatGroup &other) + : file(other.file), section_idx(other.section_idx) {} + + std::atomic_flag lock = ATOMIC_FLAG_INIT; + ObjectFile *file = nullptr; + uint32_t section_idx; +}; + +struct StringPiece { StringPiece(StringRef data) : data(data) {} StringPiece(const StringPiece &other) : data(other.data) {} + StringRef data; std::atomic_flag flag = ATOMIC_FLAG_INIT; }; @@ -377,11 +388,12 @@ public: private: void initialize_sections(); void initialize_symbols(); + void remove_comdat_members(uint32_t section_idx); void read_string_pieces(const ELF64LE::Shdr &shdr); MemoryBufferRef mb; std::vector symbols; - std::vector>> comdat_groups; + std::vector> comdat_groups; std::vector merged_strings_alloc; std::vector merged_strings_noalloc;