llvm.org GIT mirror llvm / ddd0e65
Detemplatize NodeRef. It is now possible to navigate the B+-tree using NodeRef::subtree() and NodeRef::size() without knowing the key and value template types used in the tree. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@119880 91177308-0d34-0410-b5e6-96231b3b80d8 Jakob Stoklund Olesen 9 years ago
1 changed file(s) with 97 addition(s) and 101 deletion(s). Raw diff Collapse all Expand all
377377 enum { NumLowBitsAvailable = Log2CacheLine };
378378 };
379379
380 template
381380 class NodeRef {
382 public:
383 typedef LeafNode::LeafSize, Traits> Leaf;
384 typedef BranchNode::BranchSize,
385 Traits> Branch;
386
387 private:
388381 PointerIntPair pip;
389382
390383 public:
394387 /// operator bool - Detect a null ref.
395388 operator bool() const { return pip.getOpaqueValue(); }
396389
397 /// NodeRef - Create a reference to the leaf node p with n elements.
398 NodeRef(Leaf *p, unsigned n) : pip(p, n - 1) {}
399
400 /// NodeRef - Create a reference to the branch node p with n elements.
401 NodeRef(Branch *p, unsigned n) : pip(p, n - 1) {}
390 /// NodeRef - Create a reference to the node p with n elements.
391 template
392 NodeRef(NodeT *p, unsigned n) : pip(p, n - 1) {
393 assert(n <= NodeT::Capacity && "Size too big for node");
394 }
402395
403396 /// size - Return the number of elements in the referenced node.
404397 unsigned size() const { return pip.getInt() + 1; }
406399 /// setSize - Update the node size.
407400 void setSize(unsigned n) { pip.setInt(n - 1); }
408401
409 /// leaf - Return the referenced leaf node.
410 /// Note there are no dynamic type checks.
411 Leaf &leaf() const {
412 return *reinterpret_cast(pip.getPointer());
413 }
414
415 /// branch - Return the referenced branch node.
416 /// Note there are no dynamic type checks.
417 Branch &branch() const {
418 return *reinterpret_cast(pip.getPointer());
402 /// subtree - Access the i'th subtree reference in a branch node.
403 /// This depends on branch nodes storing the NodeRef array as their first
404 /// member.
405 NodeRef &subtree(unsigned i) {
406 return reinterpret_cast(pip.getPointer())[i];
407 }
408
409 /// get - Dereference as a NodeT reference.
410 template
411 NodeT &get() const {
412 return *reinterpret_cast(pip.getPointer());
419413 }
420414
421415 bool operator==(const NodeRef &RHS) const {
441435 //
442436 // These constraints are always satisfied:
443437 //
444 // - Traits::stopLess(key[i].start, key[i].stop) - Non-empty, sane intervals.
445 //
446 // - Traits::stopLess(key[i].stop, key[i + 1].start) - Sorted.
447 //
448 // - val[i] != val[i + 1] ||
449 // !Traits::adjacent(key[i].stop, key[i + 1].start) - Fully coalesced.
438 // - Traits::stopLess(start(i), stop(i)) - Non-empty, sane intervals.
439 //
440 // - Traits::stopLess(stop(i), start(i + 1) - Sorted.
441 //
442 // - value(i) != value(i + 1) || !Traits::adjacent(stop(i), start(i + 1))
443 // - Fully coalesced.
450444 //
451445 //===----------------------------------------------------------------------===//
452446
633627 //===----------------------------------------------------------------------===//
634628
635629 template
636 class BranchNode : public NodeBase, KeyT, N> {
637 typedef NodeRef NodeRefT;
630 class BranchNode : public NodeBase {
638631 public:
639632 const KeyT &stop(unsigned i) const { return this->second[i]; }
640 const NodeRefT &subtree(unsigned i) const { return this->first[i]; }
633 const NodeRef &subtree(unsigned i) const { return this->first[i]; }
641634
642635 KeyT &stop(unsigned i) { return this->second[i]; }
643 NodeRefT &subtree(unsigned i) { return this->first[i]; }
636 NodeRef &subtree(unsigned i) { return this->first[i]; }
644637
645638 /// findFrom - Find the first subtree after i that may contain x.
646639 /// @param i Starting index for the search.
674667 /// safeLookup - Get the subtree containing x, Assuming that x is in range.
675668 /// @param x Key to search for.
676669 /// @return Subtree containing x
677 NodeRefT safeLookup(KeyT x) const {
670 NodeRef safeLookup(KeyT x) const {
678671 return subtree(safeFind(0, x));
679672 }
680673
683676 /// @param Size Number of elements in node.
684677 /// @param Node Subtree to insert.
685678 /// @param Stop Last key in subtree.
686 void insert(unsigned i, unsigned Size, NodeRefT Node, KeyT Stop) {
679 void insert(unsigned i, unsigned Size, NodeRef Node, KeyT Stop) {
687680 assert(Size < N && "branch node overflow");
688681 assert(i <= Size && "Bad insert position");
689682 this->shift(i, Size);
699692 errs() << "\"];\n";
700693 for (unsigned i = 0; i != Size; ++i)
701694 errs() << " N" << this << ":s" << i << " -> N"
702 << &subtree(i).branch() << ";\n";
695 << &subtree(i).template get() << ";\n";
703696 }
704697 #endif
705698
716709 unsigned N = IntervalMapImpl::NodeSizer::LeafSize,
717710 typename Traits = IntervalMapInfo >
718711 class IntervalMap {
719 typedef IntervalMapImpl::NodeRef NodeRef;
720 typedef IntervalMapImpl::NodeSizer NodeSizer;
721 typedef typename NodeRef::Leaf Leaf;
722 typedef typename NodeRef::Branch Branch;
712 typedef IntervalMapImpl::NodeSizer Sizer;
713 typedef IntervalMapImpl::LeafNode Leaf;
714 typedef IntervalMapImpl::BranchNode
715 Branch;
723716 typedef IntervalMapImpl::LeafNode RootLeaf;
724717 typedef IntervalMapImpl::IdxPair IdxPair;
725718
727720 // corresponding RootBranch capacity.
728721 enum {
729722 DesiredRootBranchCap = (sizeof(RootLeaf) - sizeof(KeyT)) /
730 (sizeof(KeyT) + sizeof(NodeRef)),
723 (sizeof(KeyT) + sizeof(IntervalMapImpl::NodeRef)),
731724 RootBranchCap = DesiredRootBranchCap ? DesiredRootBranchCap : 1
732725 };
733726
734 typedef IntervalMapImpl::BranchNode RootBranch;
727 typedef IntervalMapImpl::BranchNode
728 RootBranch;
735729
736730 // When branched, we store a global start key as well as the branch node.
737731 struct RootBranchData {
745739 };
746740
747741 public:
748 typedef typename NodeSizer::Allocator Allocator;
742 typedef typename Sizer::Allocator Allocator;
749743
750744 private:
751745 // The root data is either a RootLeaf or a RootBranchData instance.
836830 bool branched() const { return height > 0; }
837831
838832 ValT treeSafeLookup(KeyT x, ValT NotFound) const;
839 void visitNodes(void (IntervalMap::*f)(NodeRef, unsigned Level));
840 void deleteNode(NodeRef Node, unsigned Level);
833 void visitNodes(void (IntervalMap::*f)(IntervalMapImpl::NodeRef,
834 unsigned Level));
835 void deleteNode(IntervalMapImpl::NodeRef Node, unsigned Level);
841836
842837 public:
843838 explicit IntervalMap(Allocator &a) : height(0), rootSize(0), allocator(a) {
932927
933928 #ifndef NDEBUG
934929 void dump();
935 void dumpNode(NodeRef Node, unsigned Height);
930 void dumpNode(IntervalMapImpl::NodeRef Node, unsigned Height);
936931 #endif
937932 };
938933
943938 treeSafeLookup(KeyT x, ValT NotFound) const {
944939 assert(branched() && "treeLookup assumes a branched root");
945940
946 NodeRef NR = rootBranch().safeLookup(x);
941 IntervalMapImpl::NodeRef NR = rootBranch().safeLookup(x);
947942 for (unsigned h = height-1; h; --h)
948 NR = NR.branch().safeLookup(x);
949 return NR.leaf().safeLookup(x, NotFound);
943 NR = NR.get().safeLookup(x);
944 return NR.get().safeLookup(x, NotFound);
950945 }
951946
952947
955950 template
956951 IntervalMapImpl::IdxPair IntervalMap::
957952 branchRoot(unsigned Position) {
953 using namespace IntervalMapImpl;
958954 // How many external leaf nodes to hold RootLeaf+1?
959955 const unsigned Nodes = RootLeaf::Capacity / Leaf::Capacity + 1;
960956
974970 NodeRef node[Nodes];
975971 for (unsigned n = 0; n != Nodes; ++n) {
976972 node[n] = NodeRef(allocLeaf(), size[n]);
977 node[n].leaf().copy(rootLeaf(), pos, 0, size[n]);
973 node[n].template get().copy(rootLeaf(), pos, 0, size[n]);
978974 pos += size[n];
979975 }
980976
981977 // Destroy the old leaf node, construct branch node instead.
982978 switchRootToBranch();
983979 for (unsigned n = 0; n != Nodes; ++n) {
984 rootBranch().stop(n) = node[n].leaf().stop(size[n]-1);
980 rootBranch().stop(n) = node[n].template get().stop(size[n]-1);
985981 rootBranch().subtree(n) = node[n];
986982 }
987 rootBranchStart() = node[0].leaf().start(0);
983 rootBranchStart() = node[0].template get().start(0);
988984 rootSize = Nodes;
989985 return NewOffset;
990986 }
994990 template
995991 IntervalMapImpl::IdxPair IntervalMap::
996992 splitRoot(unsigned Position) {
993 using namespace IntervalMapImpl;
997994 // How many external leaf nodes to hold RootBranch+1?
998995 const unsigned Nodes = RootBranch::Capacity / Branch::Capacity + 1;
999996
10131010 NodeRef Node[Nodes];
10141011 for (unsigned n = 0; n != Nodes; ++n) {
10151012 Node[n] = NodeRef(allocBranch(), Size[n]);
1016 Node[n].branch().copy(rootBranch(), Pos, 0, Size[n]);
1013 Node[n].template get().copy(rootBranch(), Pos, 0, Size[n]);
10171014 Pos += Size[n];
10181015 }
10191016
10201017 for (unsigned n = 0; n != Nodes; ++n) {
1021 rootBranch().stop(n) = Node[n].branch().stop(Size[n]-1);
1018 rootBranch().stop(n) = Node[n].template get().stop(Size[n]-1);
10221019 rootBranch().subtree(n) = Node[n];
10231020 }
10241021 rootSize = Nodes;
10281025 /// visitNodes - Visit each external node.
10291026 template
10301027 void IntervalMap::
1031 visitNodes(void (IntervalMap::*f)(NodeRef, unsigned Height)) {
1028 visitNodes(void (IntervalMap::*f)(IntervalMapImpl::NodeRef, unsigned Height)) {
10321029 if (!branched())
10331030 return;
1034 SmallVector<NodeRef, 4> Refs, NextRefs;
1031 SmallVector<IntervalMapImpl::NodeRef, 4> Refs, NextRefs;
10351032
10361033 // Collect level 0 nodes from the root.
10371034 for (unsigned i = 0; i != rootSize; ++i)
10401037 // Visit all branch nodes.
10411038 for (unsigned h = height - 1; h; --h) {
10421039 for (unsigned i = 0, e = Refs.size(); i != e; ++i) {
1043 Branch &B = Refs[i].branch();
10441040 for (unsigned j = 0, s = Refs[i].size(); j != s; ++j)
1045 NextRefs.push_back(B.subtree(j));
1041 NextRefs.push_back(Refs[i].subtree(j));
10461042 (this->*f)(Refs[i], h);
10471043 }
10481044 Refs.clear();
10561052
10571053 template
10581054 void IntervalMap::
1059 deleteNode(NodeRef Node, unsigned Level) {
1055 deleteNode(IntervalMapImpl::NodeRef Node, unsigned Level) {
10601056 if (Level)
1061 deleteBranch(&Node.branch());
1057 deleteBranch(&Node.get());
10621058 else
1063 deleteLeaf(&Node.leaf());
1059 deleteLeaf(&Node.get());
10641060 }
10651061
10661062 template
10761072 #ifndef NDEBUG
10771073 template
10781074 void IntervalMap::
1079 dumpNode(NodeRef Node, unsigned Height) {
1075 dumpNode(IntervalMapImpl::NodeRef Node, unsigned Height) {
10801076 if (Height)
1081 Node.branch().dump(Node.size());
1077 Node.get().dump(Node.size());
10821078 else
1083 Node.leaf().dump(Node.size());
1079 Node.get().dump(Node.size());
10841080 }
10851081
10861082 template
11051101 public std::iterator {
11061102 protected:
11071103 friend class IntervalMap;
1108 typedef std::pair<NodeRef, unsigned> PathEntry;
1104 typedef std::pair<IntervalMapImpl::NodeRef, unsigned> PathEntry;
11091105 typedef SmallVector Path;
11101106
11111107 // The map referred to.
11201116 // Otherwise, when branched these conditions hold:
11211117 //
11221118 // 1. path.front().first == rootBranch().subtree(rootOffset)
1123 // 2. path[i].first == path[i-1].first.branch().subtree(path[i-1].second)
1119 // 2. path[i].first == path[i-1].first.subtree(path[i-1].second)
11241120 // 3. path.size() == map->height.
11251121 //
11261122 // Thus, path.back() always refers to the current leaf node unless the root is
11371133 return map->branched();
11381134 }
11391135
1140 NodeRef pathNode(unsigned h) const { return path[h].first; }
1141 NodeRef &pathNode(unsigned h) { return path[h].first; }
1136 IntervalMapImpl::NodeRef pathNode(unsigned h) const { return path[h].first; }
1137 IntervalMapImpl::NodeRef &pathNode(unsigned h) { return path[h].first; }
11421138 unsigned pathOffset(unsigned h) const { return path[h].second; }
11431139 unsigned &pathOffset(unsigned h) { return path[h].second; }
11441140
11451141 Leaf &treeLeaf() const {
11461142 assert(branched() && path.size() == map->height);
1147 return path.back().first.leaf();
1143 return path.back().first.get();
11481144 }
11491145 unsigned treeLeafSize() const {
11501146 assert(branched() && path.size() == map->height);
11601156 }
11611157
11621158 // Get the next node ptr for an incomplete path.
1163 NodeRef pathNextDown() {
1159 IntervalMapImpl::NodeRef pathNextDown() {
11641160 assert(path.size() < map->height && "Path is already complete");
11651161
11661162 if (path.empty())
11671163 return map->rootBranch().subtree(rootOffset);
11681164 else
1169 return path.back().first.branch().subtree(path.back().second);
1165 return path.back().first.subtree(path.back().second);
11701166 }
11711167
11721168 void pathFillLeft();
11731169 void pathFillFind(KeyT x);
11741170 void pathFillRight();
11751171
1176 NodeRef leftSibling(unsigned level) const;
1177 NodeRef rightSibling(unsigned level) const;
1172 IntervalMapImpl::NodeRef leftSibling(unsigned level) const;
1173 IntervalMapImpl::NodeRef rightSibling(unsigned level) const;
11781174
11791175 void treeIncrement();
11801176 void treeDecrement();
12991295 template
13001296 void IntervalMap::
13011297 const_iterator::pathFillLeft() {
1302 NodeRef NR = pathNextDown();
1298 IntervalMapImpl::NodeRef NR = pathNextDown();
13031299 for (unsigned i = map->height - path.size() - 1; i; --i) {
13041300 path.push_back(PathEntry(NR, 0));
1305 NR = NR.branch().subtree(0);
1301 NR = NR.subtree(0);
13061302 }
13071303 path.push_back(PathEntry(NR, 0));
13081304 }
13111307 template
13121308 void IntervalMap::
13131309 const_iterator::pathFillFind(KeyT x) {
1314 NodeRef NR = pathNextDown();
1310 IntervalMapImpl::NodeRef NR = pathNextDown();
13151311 for (unsigned i = map->height - path.size() - 1; i; --i) {
1316 unsigned p = NR.branch().safeFind(0, x);
1312 unsigned p = NR.get().safeFind(0, x);
13171313 path.push_back(PathEntry(NR, p));
1318 NR = NR.branch().subtree(p);
1319 }
1320 path.push_back(PathEntry(NR, NR.leaf().safeFind(0, x)));
1314 NR = NR.subtree(p);
1315 }
1316 path.push_back(PathEntry(NR, NR.get().safeFind(0, x)));
13211317 }
13221318
13231319 // pathFillRight - Complete path by adding rightmost entries.
13241320 template
13251321 void IntervalMap::
13261322 const_iterator::pathFillRight() {
1327 NodeRef NR = pathNextDown();
1323 IntervalMapImpl::NodeRef NR = pathNextDown();
13281324 for (unsigned i = map->height - path.size() - 1; i; --i) {
13291325 unsigned p = NR.size() - 1;
13301326 path.push_back(PathEntry(NR, p));
1331 NR = NR.branch().subtree(p);
1327 NR = NR.subtree(p);
13321328 }
13331329 path.push_back(PathEntry(NR, NR.size() - 1));
13341330 }
13371333 /// @param level 0 is just below the root, map->height - 1 for the leaves.
13381334 /// @return The left sibling NodeRef, or NULL.
13391335 template
1340 typename IntervalMap::NodeRef
1341 IntervalMap::
1336 IntervalMapImpl::NodeRef IntervalMap::
13421337 const_iterator::leftSibling(unsigned level) const {
1338 using namespace IntervalMapImpl;
13431339 assert(branched() && "Not at a branched node");
13441340 assert(level <= path.size() && "Bad level");
13451341
13541350
13551351 // NR is the subtree containing our left sibling.
13561352 NodeRef NR = h ?
1357 pathNode(h - 1).branch().subtree(pathOffset(h - 1) - 1) :
1353 pathNode(h - 1).subtree(pathOffset(h - 1) - 1) :
13581354 map->rootBranch().subtree(rootOffset - 1);
13591355
13601356 // Keep right all the way down.
13611357 for (; h != level; ++h)
1362 NR = NR.branch().subtree(NR.size() - 1);
1358 NR = NR.subtree(NR.size() - 1);
13631359 return NR;
13641360 }
13651361
13671363 /// @param level 0 is just below the root, map->height - 1 for the leaves.
13681364 /// @return The right sibling NodeRef, or NULL.
13691365 template
1370 typename IntervalMap::NodeRef
1371 IntervalMap::
1366 IntervalMapImpl::NodeRef IntervalMap::
13721367 const_iterator::rightSibling(unsigned level) const {
1368 using namespace IntervalMapImpl;
13731369 assert(branched() && "Not at a branched node");
13741370 assert(level <= this->path.size() && "Bad level");
13751371
13841380
13851381 // NR is the subtree containing our right sibling.
13861382 NodeRef NR = h ?
1387 pathNode(h - 1).branch().subtree(pathOffset(h - 1) + 1) :
1383 pathNode(h - 1).subtree(pathOffset(h - 1) + 1) :
13881384 map->rootBranch().subtree(rootOffset + 1);
13891385
13901386 // Keep left all the way down.
13911387 for (; h != level; ++h)
1392 NR = NR.branch().subtree(0);
1388 NR = NR.subtree(0);
13931389 return NR;
13941390 }
13951391
14921488
14931489 void setNodeSize(unsigned Level, unsigned Size);
14941490 void setNodeStop(unsigned Level, KeyT Stop);
1495 void insertNode(unsigned Level, NodeRef Node, KeyT Stop);
1491 void insertNode(unsigned Level, IntervalMapImpl::NodeRef Node, KeyT Stop);
14961492 void overflowLeaf();
14971493 void treeInsert(KeyT a, KeyT b, ValT y);
14981494
15111507 iterator::setNodeSize(unsigned Level, unsigned Size) {
15121508 this->pathNode(Level).setSize(Size);
15131509 if (Level)
1514 this->pathNode(Level-1).branch()
1515 .subtree(this->pathOffset(Level-1)).setSize(Size);
1510 this->pathNode(Level-1).subtree(this->pathOffset(Level-1)).setSize(Size);
15161511 else
15171512 this->map->rootBranch().subtree(this->rootOffset).setSize(Size);
15181513 }
15221517 void IntervalMap::
15231518 iterator::setNodeStop(unsigned Level, KeyT Stop) {
15241519 while (Level--) {
1525 this->pathNode(Level).branch().stop(this->pathOffset(Level)) = Stop;
1520 this->pathNode(Level).template get()
1521 .stop(this->pathOffset(Level)) = Stop;
15261522 if (this->pathOffset(Level) != this->pathNode(Level).size() - 1)
15271523 return;
15281524 }
15331529 /// Leave the current path pointing at the new node.
15341530 template
15351531 void IntervalMap::
1536 iterator::insertNode(unsigned Level, NodeRef Node, KeyT Stop) {
1532 iterator::insertNode(unsigned Level, IntervalMapImpl::NodeRef Node, KeyT Stop) {
15371533 if (!Level) {
15381534 // Insert into the root branch node.
15391535 IntervalMap &IM = *this->map;
15581554 }
15591555
15601556 // Insert into the branch node at level-1.
1561 NodeRef NR = this->pathNode(Level-1);
1557 IntervalMapImpl::NodeRef NR = this->pathNode(Level-1);
15621558 unsigned Offset = this->pathOffset(Level-1);
15631559 assert(NR.size() < Branch::Capacity && "Branch overflow");
1564 NR.branch().insert(Offset, NR.size(), Node, Stop);
1560 NR.get().insert(Offset, NR.size(), Node, Stop);
15651561 setNodeSize(Level - 1, NR.size() + 1);
15661562 }
15671563
16231619 template
16241620 void IntervalMap::
16251621 iterator::overflowLeaf() {
1622 using namespace IntervalMapImpl;
16261623 unsigned CurSize[4];
16271624 Leaf *Node[4];
16281625 unsigned Nodes = 0;
16331630 NodeRef LeftSib = this->leftSibling(this->map->height-1);
16341631 if (LeftSib) {
16351632 Offset += Elements = CurSize[Nodes] = LeftSib.size();
1636 Node[Nodes++] = &LeftSib.leaf();
1633 Node[Nodes++] = &LeftSib.get();
16371634 }
16381635
16391636 // Current leaf node.
16441641 NodeRef RightSib = this->rightSibling(this->map->height-1);
16451642 if (RightSib) {
16461643 Offset += Elements = CurSize[Nodes] = RightSib.size();
1647 Node[Nodes++] = &RightSib.leaf();
1644 Node[Nodes++] = &RightSib.get();
16481645 }
16491646
16501647 // Do we need to allocate a new node?
16611658
16621659 // Compute the new element distribution.
16631660 unsigned NewSize[4];
1664 IdxPair NewOffset =
1665 IntervalMapImpl::distribute(Nodes, Elements, Leaf::Capacity,
1666 CurSize, NewSize, Offset, true);
1661 IdxPair NewOffset = distribute(Nodes, Elements, Leaf::Capacity,
1662 CurSize, NewSize, Offset, true);
16671663
16681664 // Move current location to the leftmost node.
16691665 if (LeftSib)