Index: lld/trunk/ELF/InputSection.h =================================================================== --- lld/trunk/ELF/InputSection.h +++ lld/trunk/ELF/InputSection.h @@ -87,13 +87,24 @@ // SectionPiece represents a piece of splittable section contents. struct SectionPiece { SectionPiece(size_t Off, ArrayRef Data) - : InputOff(Off), Data(Data), Live(!Config->GcSections) {} - size_t size() const { return Data.size(); } + : InputOff(Off), Data((uint8_t *)Data.data()), Size(Data.size()), + Live(!Config->GcSections) {} + + ArrayRef data() { return {Data, Size}; } + size_t size() const { return Size; } size_t InputOff; size_t OutputOff = -1; - ArrayRef Data; // slice of the input section - bool Live; + +private: + // We use bitfields because SplitInputSection is accessed by + // std::upper_bound very often. + // We want to save bits to make it cache friendly. + uint8_t *Data; + uint32_t Size : 31; + +public: + uint32_t Live : 1; }; // Usually sections are copied to the output as atomic chunks of data, Index: lld/trunk/ELF/OutputSections.cpp =================================================================== --- lld/trunk/ELF/OutputSections.cpp +++ lld/trunk/ELF/OutputSections.cpp @@ -946,7 +946,7 @@ EhInputSection *Sec, ArrayRef &Rels) { const endianness E = ELFT::TargetEndianness; - if (read32(Piece.Data.data() + 4) != 0) + if (read32(Piece.data().data() + 4) != 0) fatal("CIE expected at beginning of .eh_frame: " + Sec->getSectionName()); SymbolBody *Personality = nullptr; @@ -954,7 +954,7 @@ Personality = &Sec->getFile()->getRelocTargetSym(*Rel); // Search for an existing CIE by CIE contents/relocation target pair. - CieRecord *Cie = &CieMap[{Piece.Data, Personality}]; + CieRecord *Cie = &CieMap[{Piece.data(), Personality}]; // If not found, create a new one. if (Cie->Piece == nullptr) { @@ -995,11 +995,11 @@ DenseMap OffsetToCie; for (SectionPiece &Piece : Sec->Pieces) { // The empty record is the end marker. - if (Piece.Data.size() == 4) + if (Piece.size() == 4) return; size_t Offset = Piece.InputOff; - uint32_t ID = read32(Piece.Data.data() + 4); + uint32_t ID = read32(Piece.data().data() + 4); if (ID == 0) { OffsetToCie[Offset] = addCie(Piece, Sec, Rels); continue; @@ -1106,11 +1106,11 @@ const endianness E = ELFT::TargetEndianness; for (CieRecord *Cie : Cies) { size_t CieOffset = Cie->Piece->OutputOff; - writeCieFde(Buf + CieOffset, Cie->Piece->Data); + writeCieFde(Buf + CieOffset, Cie->Piece->data()); for (SectionPiece *Fde : Cie->FdePieces) { size_t Off = Fde->OutputOff; - writeCieFde(Buf + Off, Fde->Data); + writeCieFde(Buf + Off, Fde->data()); // FDE's second word should have the offset to an associated CIE. // Write it. @@ -1126,7 +1126,7 @@ // we obtain two addresses and pass them to EhFrameHdr object. if (Out::EhFrameHdr) { for (CieRecord *Cie : Cies) { - uint8_t Enc = getFdeEncoding(Cie->Piece->Data); + uint8_t Enc = getFdeEncoding(Cie->Piece->data()); for (SectionPiece *Fde : Cie->FdePieces) { uintX_t Pc = getFdePc(Buf, Fde->OutputOff, Enc); uintX_t FdeVA = this->getVA() + Fde->OutputOff; @@ -1170,7 +1170,7 @@ for (SectionPiece &Piece : Sec->Pieces) { if (!Piece.Live) continue; - uintX_t OutputOffset = Builder.add(toStringRef(Piece.Data)); + uintX_t OutputOffset = Builder.add(toStringRef(Piece.data())); if (!IsString || !shouldTailMerge()) Piece.OutputOff = OutputOffset; }