diff --git a/lld/COFF/Chunks.h b/lld/COFF/Chunks.h
--- a/lld/COFF/Chunks.h
+++ b/lld/COFF/Chunks.h
@@ -50,7 +50,7 @@
 // doesn't even have actual data (if common or bss).
 class Chunk {
 public:
-  enum Kind { SectionKind, OtherKind };
+  enum Kind : uint8_t { SectionKind, OtherKind };
   Kind kind() const { return ChunkKind; }
   virtual ~Chunk() = default;
 
@@ -114,6 +114,12 @@
   Chunk(Kind K = OtherKind) : ChunkKind(K) {}
   const Kind ChunkKind;
 
+public:
+  // Whether this section needs to be kept distinct from other sections during
+  // ICF. This is set by the driver using address-significance tables.
+  bool KeepUnique = false;
+
+protected:
   // The RVA of this chunk in the output. The writer sets a value.
   uint64_t RVA = 0;
 
@@ -123,10 +129,6 @@
 public:
   // The offset from beginning of the output section. The writer sets a value.
   uint64_t OutputSectionOff = 0;
-
-  // Whether this section needs to be kept distinct from other sections during
-  // ICF. This is set by the driver using address-significance tables.
-  bool KeepUnique = false;
 };
 
 // A chunk corresponding a section of an input file.
@@ -217,36 +219,41 @@
 
   bool isHotPatchable() const override { return File->HotPatchable; }
 
-  // A pointer pointing to a replacement for this chunk.
-  // Initially it points to "this" object. If this chunk is merged
-  // with other chunk by ICF, it points to another chunk,
-  // and this chunk is considered as dead.
-  SectionChunk *Repl;
-
-  // The CRC of the contents as described in the COFF spec 4.5.5.
-  // Auxiliary Format 5: Section Definitions. Used for ICF.
-  uint32_t Checksum = 0;
-
-  const coff_section *Header;
-
   // The file that this chunk was created from.
   ObjFile *File;
 
+  // Pointer to the COFF section header in the input file.
+  const coff_section *Header;
+
   // The COMDAT leader symbol if this is a COMDAT chunk.
   DefinedRegular *Sym = nullptr;
 
-  // The COMDAT selection if this is a COMDAT chunk.
-  llvm::COFF::COMDATType Selection = (llvm::COFF::COMDATType)0;
-
+  // Relocations for this section.
   ArrayRef<coff_relocation> Relocs;
 
-  // Used by the garbage collector.
-  bool Live;
-
   // When inserting a thunk, we need to adjust a relocation to point to
   // the thunk instead of the actual original target Symbol.
   std::vector<Symbol *> RelocTargets;
 
+  // The CRC of the contents as described in the COFF spec 4.5.5.
+  // Auxiliary Format 5: Section Definitions. Used for ICF.
+  uint32_t Checksum = 0;
+
+  // Indicates whether the section should be included in the output file.
+  // Sections may become dead if the garbage collector discards them, if ICF
+  // replaces them, or if they are associated with a non-prevailing comdat
+  // section.
+  bool Live;
+
+  // The COMDAT selection if this is a COMDAT chunk.
+  llvm::COFF::COMDATType Selection = (llvm::COFF::COMDATType)0;
+
+  // A pointer pointing to a replacement for this chunk.
+  // Initially it points to "this" object. If this chunk is merged
+  // with other chunk by ICF, it points to another chunk,
+  // and this chunk is considered as dead.
+  SectionChunk *Repl;
+
 private:
   StringRef SectionName;
   std::vector<SectionChunk *> AssocChildren;
diff --git a/lld/COFF/Chunks.cpp b/lld/COFF/Chunks.cpp
--- a/lld/COFF/Chunks.cpp
+++ b/lld/COFF/Chunks.cpp
@@ -44,6 +44,48 @@
   Live = !Config->DoGC || !isCOMDAT();
 }
 
+namespace {
+// This class exists just for the purpose of calculating the expected size of
+// Chunk.
+struct ChunkFields {
+  uintptr_t VPtr;
+  uint32_t Alignment;
+  uint8_t ChunkKind;
+  bool KeepUnique;
+  uint64_t RVA;
+  uintptr_t Out;
+  uint64_t OutputSectionOff;
+};
+
+// Chunk is one of the most frequently allocated classes, so it is important to
+// keep it as compact as possible.
+static_assert(sizeof(Chunk) == sizeof(ChunkFields),
+              "Chunk grew unexpectedly");
+
+// This class exists just for the purpose of calculating the expected size of
+// SectionChunk.
+struct SectionChunkFields {
+  ChunkFields ChunkBase;
+  uintptr_t File;
+  uintptr_t Header;
+  uintptr_t Sym;
+  uintptr_t Relocs[2];
+  uintptr_t RelocTargets[3];
+  uint32_t Checksum;
+  bool Live;
+  uint8_t Selection;
+  uintptr_t Repl;
+  uintptr_t SectionName[2];
+  uintptr_t AssocChildren[3];
+  uint32_t Class[2];
+};
+
+// SectionChunk is one of the most frequently allocated classes, so it is
+// important to keep it as compact as possible.
+static_assert(sizeof(SectionChunk) == sizeof(SectionChunkFields),
+              "SectionChunk grew unexpectedly");
+} // namespace
+
 // Initialize the RelocTargets vector, to allow redirecting certain relocations
 // to a thunk instead of the actual symbol the relocation's symbol table index
 // indicates.
diff --git a/llvm/include/llvm/BinaryFormat/COFF.h b/llvm/include/llvm/BinaryFormat/COFF.h
--- a/llvm/include/llvm/BinaryFormat/COFF.h
+++ b/llvm/include/llvm/BinaryFormat/COFF.h
@@ -402,7 +402,7 @@
   IMAGE_REL_ARM64_REL32 = 0x0011,
 };
 
-enum COMDATType : unsigned {
+enum COMDATType : uint8_t {
   IMAGE_COMDAT_SELECT_NODUPLICATES = 1,
   IMAGE_COMDAT_SELECT_ANY,
   IMAGE_COMDAT_SELECT_SAME_SIZE,