[llvm] 58e66f2 - [JITLink] Move block ownership from LinkGraph to Section.

Lang Hames via llvm-commits llvm-commits at lists.llvm.org
Wed Oct 30 17:57:11 PDT 2019


Author: Lang Hames
Date: 2019-10-30T17:57:03-07:00
New Revision: 58e66f2f6375dd3c63f5854abd908298a73851d9

URL: https://github.com/llvm/llvm-project/commit/58e66f2f6375dd3c63f5854abd908298a73851d9
DIFF: https://github.com/llvm/llvm-project/commit/58e66f2f6375dd3c63f5854abd908298a73851d9.diff

LOG: [JITLink] Move block ownership from LinkGraph to Section.

This enables easy iteration over blocks in a specific section.

Added: 
    

Modified: 
    llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h
    llvm/lib/ExecutionEngine/JITLink/JITLink.cpp
    llvm/unittests/ExecutionEngine/JITLink/LinkGraphTests.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h b/llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h
index d88415b721ac..cef4e3340416 100644
--- a/llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h
+++ b/llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h
@@ -562,6 +562,16 @@ class Section {
   /// Returns the ordinal for this section.
   SectionOrdinal getOrdinal() const { return SecOrdinal; }
 
+  /// Returns an iterator over the blocks defined in this section.
+  iterator_range<block_iterator> blocks() {
+    return make_range(Blocks.begin(), Blocks.end());
+  }
+
+  /// Returns an iterator over the blocks defined in this section.
+  iterator_range<const_block_iterator> blocks() const {
+    return make_range(Blocks.begin(), Blocks.end());
+  }
+
   /// Returns an iterator over the symbols defined in this section.
   iterator_range<symbol_iterator> symbols() {
     return make_range(Symbols.begin(), Symbols.end());
@@ -592,10 +602,21 @@ class Section {
     Symbols.erase(&Sym);
   }
 
+  void addBlock(Block &B) {
+    assert(!Blocks.count(&B) && "Block is already in this section");
+    Blocks.insert(&B);
+  }
+
+  void removeBlock(Block &B) {
+    assert(Blocks.count(&B) && "Block is not in this section");
+    Blocks.erase(&B);
+  }
+
   StringRef Name;
   sys::Memory::ProtectionFlags Prot;
   SectionOrdinal SecOrdinal = 0;
   BlockOrdinal NextBlockOrdinal = 0;
+  BlockSet Blocks;
   SymbolSet Symbols;
 };
 
@@ -663,12 +684,11 @@ class LinkGraph {
   template <typename... ArgTs> Block &createBlock(ArgTs &&... Args) {
     Block *B = reinterpret_cast<Block *>(Allocator.Allocate<Block>());
     new (B) Block(std::forward<ArgTs>(Args)...);
-    Blocks.insert(B);
+    B->getSection().addBlock(*B);
     return *B;
   }
 
   void destroyBlock(Block &B) {
-    Blocks.erase(&B);
     B.~Block();
     Allocator.Deallocate(&B);
   }
@@ -678,69 +698,102 @@ class LinkGraph {
     Allocator.Deallocate(&S);
   }
 
+  static iterator_range<Section::block_iterator> getSectionBlocks(Section &S) {
+    return S.blocks();
+  }
+
+  static iterator_range<Section::const_block_iterator>
+  getSectionConstBlocks(Section &S) {
+    return S.blocks();
+  }
+
+  static iterator_range<Section::symbol_iterator>
+  getSectionSymbols(Section &S) {
+    return S.symbols();
+  }
+
+  static iterator_range<Section::const_symbol_iterator>
+  getSectionConstSymbols(Section &S) {
+    return S.symbols();
+  }
+
 public:
   using external_symbol_iterator = ExternalSymbolSet::iterator;
 
-  using block_iterator = BlockSet::iterator;
-
   using section_iterator = pointee_iterator<SectionList::iterator>;
   using const_section_iterator = pointee_iterator<SectionList::const_iterator>;
 
-  template <typename SectionItrT, typename SymbolItrT, typename T>
-  class defined_symbol_iterator_impl
+  template <typename OuterItrT, typename InnerItrT, typename T,
+            iterator_range<InnerItrT> getInnerRange(
+                typename OuterItrT::reference)>
+  class nested_collection_iterator
       : public iterator_facade_base<
-            defined_symbol_iterator_impl<SectionItrT, SymbolItrT, T>,
+            nested_collection_iterator<OuterItrT, InnerItrT, T, getInnerRange>,
             std::forward_iterator_tag, T> {
   public:
-    defined_symbol_iterator_impl() = default;
+    nested_collection_iterator() = default;
 
-    defined_symbol_iterator_impl(SectionItrT SecI, SectionItrT SecE)
-        : SecI(SecI), SecE(SecE),
-          SymI(SecI != SecE ? SecI->symbols().begin() : SymbolItrT()) {
-      moveToNextSymbolOrEnd();
+    nested_collection_iterator(OuterItrT OuterI, OuterItrT OuterE)
+        : OuterI(OuterI), OuterE(OuterE),
+          InnerI(getInnerBegin(OuterI, OuterE)) {
+      moveToNonEmptyInnerOrEnd();
     }
 
-    bool operator==(const defined_symbol_iterator_impl &RHS) const {
-      return (SecI == RHS.SecI) && (SymI == RHS.SymI);
+    bool operator==(const nested_collection_iterator &RHS) const {
+      return (OuterI == RHS.OuterI) && (InnerI == RHS.InnerI);
     }
 
     T operator*() const {
-      assert(SymI != SecI->symbols().end() && "Dereferencing end?");
-      return *SymI;
+      assert(InnerI != getInnerRange(*OuterI).end() && "Dereferencing end?");
+      return *InnerI;
     }
 
-    defined_symbol_iterator_impl operator++() {
-      ++SymI;
-      moveToNextSymbolOrEnd();
+    nested_collection_iterator operator++() {
+      ++InnerI;
+      moveToNonEmptyInnerOrEnd();
       return *this;
     }
 
   private:
-    void moveToNextSymbolOrEnd() {
-      while (SecI != SecE && SymI == SecI->symbols().end()) {
-        ++SecI;
-        SymI = SecI == SecE ? SymbolItrT() : SecI->symbols().begin();
+    static InnerItrT getInnerBegin(OuterItrT OuterI, OuterItrT OuterE) {
+      return OuterI != OuterE ? getInnerRange(*OuterI).begin() : InnerItrT();
+    }
+
+    void moveToNonEmptyInnerOrEnd() {
+      while (OuterI != OuterE && InnerI == getInnerRange(*OuterI).end()) {
+        ++OuterI;
+        InnerI = getInnerBegin(OuterI, OuterE);
       }
     }
 
-    SectionItrT SecI, SecE;
-    SymbolItrT SymI;
+    OuterItrT OuterI, OuterE;
+    InnerItrT InnerI;
   };
 
   using defined_symbol_iterator =
-      defined_symbol_iterator_impl<const_section_iterator,
-                                   Section::symbol_iterator, Symbol *>;
+      nested_collection_iterator<const_section_iterator,
+                                 Section::symbol_iterator, Symbol *,
+                                 getSectionSymbols>;
+
+  using const_defined_symbol_iterator =
+      nested_collection_iterator<const_section_iterator,
+                                 Section::const_symbol_iterator, const Symbol *,
+                                 getSectionConstSymbols>;
+
+  using block_iterator = nested_collection_iterator<const_section_iterator,
+                                                    Section::block_iterator,
+                                                    Block *, getSectionBlocks>;
 
-  using const_defined_symbol_iterator = defined_symbol_iterator_impl<
-      const_section_iterator, Section::const_symbol_iterator, const Symbol *>;
+  using const_block_iterator =
+      nested_collection_iterator<const_section_iterator,
+                                 Section::const_block_iterator, const Block *,
+                                 getSectionConstBlocks>;
 
   LinkGraph(std::string Name, unsigned PointerSize,
             support::endianness Endianness)
       : Name(std::move(Name)), PointerSize(PointerSize),
         Endianness(Endianness) {}
 
-  ~LinkGraph();
-
   /// Returns the name of this graph (usually the name of the original
   /// underlying MemoryBuffer).
   const std::string &getName() { return Name; }
@@ -864,6 +917,16 @@ class LinkGraph {
     return nullptr;
   }
 
+  iterator_range<block_iterator> blocks() {
+    return make_range(block_iterator(Sections.begin(), Sections.end()),
+                      block_iterator(Sections.end(), Sections.end()));
+  }
+
+  iterator_range<const_block_iterator> blocks() const {
+    return make_range(const_block_iterator(Sections.begin(), Sections.end()),
+                      const_block_iterator(Sections.end(), Sections.end()));
+  }
+
   iterator_range<external_symbol_iterator> external_symbols() {
     return make_range(ExternalSymbols.begin(), ExternalSymbols.end());
   }
@@ -883,10 +946,6 @@ class LinkGraph {
         const_defined_symbol_iterator(Sections.end(), Sections.end()));
   }
 
-  iterator_range<block_iterator> blocks() {
-    return make_range(Blocks.begin(), Blocks.end());
-  }
-
   /// Turn a defined symbol into an external one.
   void makeExternal(Symbol &Sym) {
     if (Sym.getAddressable().isAbsolute()) {
@@ -934,7 +993,7 @@ class LinkGraph {
 
   /// Remove a block.
   void removeBlock(Block &B) {
-    Blocks.erase(&B);
+    B.getSection().removeBlock(B);
     destroyBlock(B);
   }
 
@@ -955,7 +1014,6 @@ class LinkGraph {
   std::string Name;
   unsigned PointerSize;
   support::endianness Endianness;
-  BlockSet Blocks;
   SectionList Sections;
   ExternalSymbolSet ExternalSymbols;
   ExternalSymbolSet AbsoluteSymbols;

diff  --git a/llvm/lib/ExecutionEngine/JITLink/JITLink.cpp b/llvm/lib/ExecutionEngine/JITLink/JITLink.cpp
index ab45d33fe29b..9df79670d9fb 100644
--- a/llvm/lib/ExecutionEngine/JITLink/JITLink.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/JITLink.cpp
@@ -145,10 +145,6 @@ void printEdge(raw_ostream &OS, const Block &B, const Edge &E,
 Section::~Section() {
   for (auto *Sym : Symbols)
     Sym->~Symbol();
-}
-
-LinkGraph::~LinkGraph() {
-  // Destroy blocks.
   for (auto *B : Blocks)
     B->~Block();
 }

diff  --git a/llvm/unittests/ExecutionEngine/JITLink/LinkGraphTests.cpp b/llvm/unittests/ExecutionEngine/JITLink/LinkGraphTests.cpp
index cb86d09f0234..c1e1d9e740d6 100644
--- a/llvm/unittests/ExecutionEngine/JITLink/LinkGraphTests.cpp
+++ b/llvm/unittests/ExecutionEngine/JITLink/LinkGraphTests.cpp
@@ -15,6 +15,9 @@
 using namespace llvm;
 using namespace llvm::jitlink;
 
+static auto RWFlags =
+    sys::Memory::ProtectionFlags(sys::Memory::MF_READ | sys::Memory::MF_WRITE);
+
 TEST(LinkGraphTest, Construction) {
   // Check that LinkGraph construction works as expected.
   LinkGraph G("foo", 8, support::little);
@@ -27,6 +30,59 @@ TEST(LinkGraphTest, Construction) {
   EXPECT_TRUE(llvm::empty(G.blocks()));
 }
 
+TEST(LinkGraphTest, BlockAndSymbolIteration) {
+  // Check that we can iterate over blocks within Sections and across sections.
+
+  const char BlockContentBytes[] = {0x10, 0x11, 0x12, 0x13, 0x14, 0x15,
+                                    0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B,
+                                    0x1C, 0x1D, 0x1E, 0x1F, 0x00};
+  StringRef BlockContent(BlockContentBytes);
+
+  LinkGraph G("foo", 8, support::little);
+  auto &Sec1 = G.createSection("__data.1", RWFlags);
+  auto &B1 = G.createContentBlock(Sec1, BlockContent, 0x1000, 8, 0);
+  auto &B2 = G.createContentBlock(Sec1, BlockContent, 0x2000, 8, 0);
+  auto &S1 = G.addDefinedSymbol(B1, 0, "S1", 4, Linkage::Strong, Scope::Default,
+                                false, false);
+  auto &S2 = G.addDefinedSymbol(B2, 4, "S2", 4, Linkage::Strong, Scope::Default,
+                                false, false);
+
+  auto &Sec2 = G.createSection("__data.1", RWFlags);
+  auto &B3 = G.createContentBlock(Sec2, BlockContent, 0x3000, 8, 0);
+  auto &B4 = G.createContentBlock(Sec2, BlockContent, 0x4000, 8, 0);
+  auto &S3 = G.addDefinedSymbol(B3, 0, "S3", 4, Linkage::Strong, Scope::Default,
+                                false, false);
+  auto &S4 = G.addDefinedSymbol(B4, 4, "S4", 4, Linkage::Strong, Scope::Default,
+                                false, false);
+
+  // Check that iteration of blocks within a section behaves as expected.
+  EXPECT_EQ(std::distance(Sec1.blocks().begin(), Sec1.blocks().end()), 2U);
+  EXPECT_TRUE(llvm::count(Sec1.blocks(), &B1));
+  EXPECT_TRUE(llvm::count(Sec1.blocks(), &B2));
+
+  // Check that iteration of symbols within a section behaves as expected.
+  EXPECT_EQ(std::distance(Sec1.symbols().begin(), Sec1.symbols().end()), 2U);
+  EXPECT_TRUE(llvm::count(Sec1.symbols(), &S1));
+  EXPECT_TRUE(llvm::count(Sec1.symbols(), &S2));
+
+  // Check that iteration of blocks across sections behaves as expected.
+  EXPECT_EQ(std::distance(G.blocks().begin(), G.blocks().end()), 4U);
+  EXPECT_TRUE(llvm::count(G.blocks(), &B1));
+  EXPECT_TRUE(llvm::count(G.blocks(), &B2));
+  EXPECT_TRUE(llvm::count(G.blocks(), &B3));
+  EXPECT_TRUE(llvm::count(G.blocks(), &B4));
+
+  // Check that iteration of defined symbols across sections behaves as
+  // expected.
+  EXPECT_EQ(
+      std::distance(G.defined_symbols().begin(), G.defined_symbols().end()),
+      4U);
+  EXPECT_TRUE(llvm::count(G.defined_symbols(), &S1));
+  EXPECT_TRUE(llvm::count(G.defined_symbols(), &S2));
+  EXPECT_TRUE(llvm::count(G.defined_symbols(), &S3));
+  EXPECT_TRUE(llvm::count(G.defined_symbols(), &S4));
+}
+
 TEST(LinkGraphTest, SplitBlock) {
   // Check that the LinkGraph::splitBlock test works as expected.
 
@@ -36,9 +92,7 @@ TEST(LinkGraphTest, SplitBlock) {
   StringRef BlockContent(BlockContentBytes);
 
   LinkGraph G("foo", 8, support::little);
-  auto &Sec = G.createSection(
-      "test", sys::Memory::ProtectionFlags(sys::Memory::MF_READ |
-                                           sys::Memory::MF_WRITE));
+  auto &Sec = G.createSection("__data", RWFlags);
 
   // Create the block to split.
   auto &B1 = G.createContentBlock(Sec, BlockContent, 0x1000, 8, 0);


        


More information about the llvm-commits mailing list