[COFF] Replace OutputSection* with uint16_t index in Chunk
authorReid Kleckner <rnk@google.com>
Fri, 24 May 2019 18:25:49 +0000 (18:25 +0000)
committerReid Kleckner <rnk@google.com>
Fri, 24 May 2019 18:25:49 +0000 (18:25 +0000)
Shaves another 8 bytes off of SectionChunk, the most commonly allocated
type in LLD.

These indices are only valid after we've assigned chunks to output
sections and removed empty sections, so do that in a new pass.

Reviewers: ruiu, aganea

Differential Revision: https://reviews.llvm.org/D62356

llvm-svn: 361657

lld/COFF/Chunks.cpp
lld/COFF/Chunks.h
lld/COFF/PDB.cpp
lld/COFF/Writer.cpp
lld/test/COFF/strtab-size.s

index b016ac1e86d3591eb033a282105ba67a1fffd896..5af3b52eda93dd064b373a19cfaefa267d446ced 100644 (file)
@@ -53,7 +53,7 @@ SectionChunk::SectionChunk(ObjFile *F, const coff_section *H)
 // SectionChunk is one of the most frequently allocated classes, so it is
 // important to keep it as compact as possible. As of this writing, the number
 // below is the size of this class on x64 platforms.
-static_assert(sizeof(SectionChunk) <= 104, "SectionChunk grew unexpectedly");
+static_assert(sizeof(SectionChunk) <= 96, "SectionChunk grew unexpectedly");
 
 static void add16(uint8_t *P, int16_t V) { write16le(P, read16le(P) + V); }
 static void add32(uint8_t *P, int32_t V) { write32le(P, read32le(P) + V); }
@@ -858,7 +858,7 @@ uint8_t Baserel::getDefaultType() {
 MergeChunk *MergeChunk::Instances[Log2MaxSectionAlignment + 1] = {};
 
 MergeChunk::MergeChunk(uint32_t Alignment)
-    : Builder(StringTableBuilder::RAW, Alignment) {
+    : Chunk(OtherKind), Builder(StringTableBuilder::RAW, Alignment) {
   setAlignment(Alignment);
 }
 
@@ -886,7 +886,6 @@ void MergeChunk::assignSubsectionRVAs() {
     if (!C->Live)
       continue;
     size_t Off = Builder.getOffset(toStringRef(C->getContents()));
-    C->setOutputSection(Out);
     C->setRVA(RVA + Off);
   }
 }
index 672003b31f98fbefcc6e89434be42f8579f357f0..619a4886cd931f00defd29c0c4c89386a7762a14 100644 (file)
@@ -103,8 +103,9 @@ public:
 
   // An output section has pointers to chunks in the section, and each
   // chunk has a back pointer to an output section.
-  void setOutputSection(OutputSection *O) { Out = O; }
-  OutputSection *getOutputSection() const { return Out; }
+  void setOutputSectionIdx(uint16_t O) { OSIdx = O; }
+  uint16_t getOutputSectionIdx() const { return OSIdx; }
+  OutputSection *getOutputSection() const;
 
   // Windows-specific.
   // Collect all locations that contain absolute addresses for base relocations.
@@ -125,11 +126,12 @@ protected:
   // value.
   uint8_t P2Align = 0;
 
+  // The output section index for this chunk. The first valid section number is
+  // one.
+  uint16_t OSIdx = 0;
+
   // The RVA of this chunk in the output. The writer sets a value.
   uint32_t RVA = 0;
-
-  // The output section for this chunk.
-  OutputSection *Out = nullptr;
 };
 
 // A chunk corresponding a section of an input file.
index f237485c0bbe33bc14dc3ad216fec87cf88cda9e..242235154d05ffc8a566f49488ecf9f5e1fd0627 100644 (file)
@@ -1030,7 +1030,7 @@ void PDBLinker::mergeSymbolRecords(ObjFile *File, const CVIndexMap &IndexMap,
 static ArrayRef<uint8_t> relocateDebugChunk(BumpPtrAllocator &Alloc,
                                             SectionChunk &DebugChunk) {
   uint8_t *Buffer = Alloc.Allocate<uint8_t>(DebugChunk.getSize());
-  assert(DebugChunk.getOutputSection() == nullptr &&
+  assert(DebugChunk.getOutputSectionIdx() == 0 &&
          "debug sections should not be in output sections");
   DebugChunk.writeTo(Buffer);
   return makeArrayRef(Buffer, DebugChunk.getSize());
index 19614058a2b69ac8bbcf7d381687fcf1020dca29..0e6cc9de853f6a2116b96ea93cd94e2e240a454f 100644 (file)
@@ -78,6 +78,14 @@ static_assert(DOSStubSize % 8 == 0, "DOSStub size must be multiple of 8");
 
 static const int NumberOfDataDirectory = 16;
 
+// Global vector of all output sections. After output sections are finalized,
+// this can be indexed by Chunk::getOutputSection.
+static std::vector<OutputSection *> OutputSections;
+
+OutputSection *Chunk::getOutputSection() const {
+  return OSIdx == 0 ? nullptr : OutputSections[OSIdx - 1];
+}
+
 namespace {
 
 class DebugDirectoryChunk : public Chunk {
@@ -192,6 +200,7 @@ private:
   void assignAddresses();
   void finalizeAddresses();
   void removeEmptySections();
+  void assignOutputSectionIndices();
   void createSymbolAndStringTable();
   void openFile(StringRef OutputPath);
   template <typename PEHeaderTy> void writeHeader();
@@ -225,7 +234,6 @@ private:
 
   std::unique_ptr<FileOutputBuffer> &Buffer;
   std::map<PartialSectionKey, PartialSection *> PartialSections;
-  std::vector<OutputSection *> OutputSections;
   std::vector<char> Strtab;
   std::vector<llvm::object::coff_symbol16> OutputSymtab;
   IdataContents Idata;
@@ -284,12 +292,10 @@ void writeResult() { Writer().run(); }
 
 void OutputSection::addChunk(Chunk *C) {
   Chunks.push_back(C);
-  C->setOutputSection(this);
 }
 
 void OutputSection::insertChunkAtStart(Chunk *C) {
   Chunks.insert(Chunks.begin(), C);
-  C->setOutputSection(this);
 }
 
 void OutputSection::setPermissions(uint32_t C) {
@@ -298,8 +304,6 @@ void OutputSection::setPermissions(uint32_t C) {
 }
 
 void OutputSection::merge(OutputSection *Other) {
-  for (Chunk *C : Other->Chunks)
-    C->setOutputSection(this);
   Chunks.insert(Chunks.end(), Other->Chunks.begin(), Other->Chunks.end());
   Other->Chunks.clear();
   ContribSections.insert(ContribSections.end(), Other->ContribSections.begin(),
@@ -444,7 +448,6 @@ static bool createThunks(OutputSection *OS, int Margin) {
         Chunk *ThunkChunk = Thunk->getChunk();
         ThunkChunk->setRVA(
             ThunkInsertionRVA); // Estimate of where it will be located.
-        ThunkChunk->setOutputSection(OS);
         OS->Chunks.insert(OS->Chunks.begin() + ThunkInsertionSpot, ThunkChunk);
         ThunkInsertionSpot++;
         ThunksSize += ThunkChunk->getSize();
@@ -595,6 +598,7 @@ void Writer::run() {
   removeUnusedSections();
   finalizeAddresses();
   removeEmptySections();
+  assignOutputSectionIndices();
   setSectionPermissions();
   createSymbolAndStringTable();
 
@@ -1000,9 +1004,26 @@ void Writer::removeEmptySections() {
   OutputSections.erase(
       std::remove_if(OutputSections.begin(), OutputSections.end(), IsEmpty),
       OutputSections.end());
+}
+
+void Writer::assignOutputSectionIndices() {
+  // Assign final output section indices, and assign each chunk to its output
+  // section.
   uint32_t Idx = 1;
-  for (OutputSection *Sec : OutputSections)
-    Sec->SectionIndex = Idx++;
+  for (OutputSection *OS : OutputSections) {
+    OS->SectionIndex = Idx;
+    for (Chunk *C : OS->Chunks)
+      C->setOutputSectionIdx(Idx);
+    ++Idx;
+  }
+
+  // Merge chunks are containers of chunks, so assign those an output section
+  // too.
+  for (MergeChunk *MC : MergeChunk::Instances)
+    if (MC)
+      for (SectionChunk *SC : MC->Sections)
+        if (SC && SC->Live)
+          SC->setOutputSectionIdx(MC->getOutputSectionIdx());
 }
 
 size_t Writer::addEntryToStringTable(StringRef Str) {
@@ -1463,9 +1484,9 @@ static void maybeAddAddressTakenFunction(SymbolRVASet &AddressTakenSyms,
     // section.
     auto *D = cast<DefinedRegular>(S);
     if (D->getCOFFSymbol().getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION) {
-      Chunk *RefChunk = D->getChunk();
-      OutputSection *OS = RefChunk ? RefChunk->getOutputSection() : nullptr;
-      if (OS && OS->Header.Characteristics & IMAGE_SCN_MEM_EXECUTE)
+      SectionChunk *SC = dyn_cast<SectionChunk>(D->getChunk());
+      if (SC && SC->Live &&
+          SC->getOutputCharacteristics() & IMAGE_SCN_MEM_EXECUTE)
         addSymbolToRVASet(AddressTakenSyms, D);
     }
     break;
@@ -1744,8 +1765,9 @@ void Writer::sortExceptionTable() {
     return;
   // We assume .pdata contains function table entries only.
   auto BufAddr = [&](Chunk *C) {
-    return Buffer->getBufferStart() + C->getOutputSection()->getFileOff() +
-           C->getRVA() - C->getOutputSection()->getRVA();
+    OutputSection *OS = C->getOutputSection();
+    return Buffer->getBufferStart() + OS->getFileOff() + C->getRVA() -
+           OS->getRVA();
   };
   uint8_t *Begin = BufAddr(FirstPdata);
   uint8_t *End = BufAddr(LastPdata) + LastPdata->getSize();
index 91e4c7e012dbe8c04e628772e478de86202a6a07..574b1a0265ba612c64f39c3b4193ab5d6d45b5bc 100644 (file)
@@ -13,7 +13,7 @@
 # or disk full, cannot seek to 0x1602").
 
 # RUN: llvm-readobj --file-headers %t.exe | FileCheck %s
-# CHECK: SymbolCount: 199
+# CHECK: SymbolCount: 197
 
 .global main
 .text