Revert "[libc] Use best-fit binary trie to make malloc logarithmic" (#117065)
[llvm-project.git] / lld / COFF / MarkLive.cpp
blob3c09baa73a9f7bb68a9e01f7dda2bbc4584d94a4
1 //===- MarkLive.cpp -------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #include "COFFLinkerContext.h"
10 #include "Chunks.h"
11 #include "Symbols.h"
12 #include "lld/Common/Timer.h"
13 #include "llvm/ADT/STLExtras.h"
14 #include "llvm/Support/TimeProfiler.h"
15 #include <vector>
17 namespace lld::coff {
19 // Set live bit on for each reachable chunk. Unmarked (unreachable)
20 // COMDAT chunks will be ignored by Writer, so they will be excluded
21 // from the final output.
22 void markLive(COFFLinkerContext &ctx) {
23 llvm::TimeTraceScope timeScope("Mark live");
24 ScopedTimer t(ctx.gcTimer);
26 // We build up a worklist of sections which have been marked as live. We only
27 // push into the worklist when we discover an unmarked section, and we mark
28 // as we push, so sections never appear twice in the list.
29 SmallVector<SectionChunk *, 256> worklist;
31 // COMDAT section chunks are dead by default. Add non-COMDAT chunks. Do not
32 // traverse DWARF sections. They are live, but they should not keep other
33 // sections alive.
34 for (Chunk *c : ctx.symtab.getChunks())
35 if (auto *sc = dyn_cast<SectionChunk>(c))
36 if (sc->live && !sc->isDWARF())
37 worklist.push_back(sc);
39 auto enqueue = [&](SectionChunk *c) {
40 if (c->live)
41 return;
42 c->live = true;
43 worklist.push_back(c);
46 std::function<void(Symbol *)> addSym;
48 auto addImportFile = [&](ImportFile *file) {
49 file->live = true;
50 if (file->impchkThunk && file->impchkThunk->exitThunk)
51 addSym(file->impchkThunk->exitThunk);
54 addSym = [&](Symbol *b) {
55 if (auto *sym = dyn_cast<DefinedRegular>(b)) {
56 enqueue(sym->getChunk());
57 } else if (auto *sym = dyn_cast<DefinedImportData>(b)) {
58 addImportFile(sym->file);
59 } else if (auto *sym = dyn_cast<DefinedImportThunk>(b)) {
60 addImportFile(sym->wrappedSym->file);
61 sym->getChunk()->live = true;
65 // Add GC root chunks.
66 for (Symbol *b : ctx.config.gcroot)
67 addSym(b);
69 while (!worklist.empty()) {
70 SectionChunk *sc = worklist.pop_back_val();
71 assert(sc->live && "We mark as live when pushing onto the worklist!");
73 // Mark all symbols listed in the relocation table for this section.
74 for (Symbol *b : sc->symbols())
75 if (b)
76 addSym(b);
78 // Mark associative sections if any.
79 for (SectionChunk &c : sc->children())
80 enqueue(&c);
82 // Mark EC entry thunks.
83 if (Defined *entryThunk = sc->getEntryThunk())
84 addSym(entryThunk);