llvm.org GIT mirror llvm / 6c76f5f
Generalize overflowLeaf to also handle overflows in branch nodes. This doesn't quite work yet because the calls to treeDecrement and treeIncrement operate at the leaf level, not on pathNode(Level) as required. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@120068 91177308-0d34-0410-b5e6-96231b3b80d8 Jakob Stoklund Olesen 9 years ago
1 changed file(s) with 54 addition(s) and 33 deletion(s). Raw diff Collapse all Expand all
10191019 rootBranch().subtree(n) = Node[n];
10201020 }
10211021 rootSize = Nodes;
1022 ++height;
10221023 return NewOffset;
10231024 }
10241025
14881489
14891490 void setNodeSize(unsigned Level, unsigned Size);
14901491 void setNodeStop(unsigned Level, KeyT Stop);
1491 void insertNode(unsigned Level, IntervalMapImpl::NodeRef Node, KeyT Stop);
1492 void overflowLeaf();
1492 bool insertNode(unsigned Level, IntervalMapImpl::NodeRef Node, KeyT Stop);
1493 template bool overflow(unsigned Level);
14931494 void treeInsert(KeyT a, KeyT b, ValT y);
14941495
14951496 public:
15271528
15281529 /// insertNode - insert a node before the current path at level.
15291530 /// Leave the current path pointing at the new node.
1530 template
1531 void IntervalMap::
1531 /// @param Level path index of the node to be inserted.
1532 /// @param Node The node to be inserted.
1533 /// @param Stop The last index in the new node.
1534 /// @return True if the tree height was increased.
1535 template
1536 bool IntervalMap::
15321537 iterator::insertNode(unsigned Level, IntervalMapImpl::NodeRef Node, KeyT Stop) {
1538 bool SplitRoot = false;
1539
15331540 if (!Level) {
15341541 // Insert into the root branch node.
15351542 IntervalMap &IM = *this->map;
15361543 if (IM.rootSize < RootBranch::Capacity) {
15371544 IM.rootBranch().insert(this->rootOffset, IM.rootSize, Node, Stop);
15381545 ++IM.rootSize;
1539 return;
1546 return SplitRoot;
15401547 }
15411548
15421549 // We need to split the root while keeping our position.
1550 SplitRoot = true;
15431551 IdxPair Offset = IM.splitRoot(this->rootOffset);
15441552 this->rootOffset = Offset.first;
15451553 this->path.insert(this->path.begin(),std::make_pair(
15541562 }
15551563
15561564 // Insert into the branch node at level-1.
1565 if (this->pathNode(Level-1).size() == Branch::Capacity) {
1566 assert(!SplitRoot && "Cannot overflow after splitting the root");
1567 SplitRoot = overflow(Level - 1);
1568 Level += SplitRoot;
1569 }
15571570 IntervalMapImpl::NodeRef NR = this->pathNode(Level-1);
15581571 unsigned Offset = this->pathOffset(Level-1);
1559 assert(NR.size() < Branch::Capacity && "Branch overflow");
15601572 NR.get().insert(Offset, NR.size(), Node, Stop);
15611573 setNodeSize(Level - 1, NR.size() + 1);
1574 return SplitRoot;
15621575 }
15631576
15641577 // insert
16021615 return;
16031616 }
16041617 // Leaf node has no space.
1605 overflowLeaf();
1618 overflow(this->map->height - 1);
16061619 IP = this->treeLeaf().insertFrom(this->treeLeafOffset(),
16071620 this->treeLeafSize(), a, b, y);
16081621 this->treeLeafOffset() = IP.first;
16131626 // FIXME: Handle cross-node coalescing.
16141627 }
16151628
1616 // overflowLeaf - Distribute entries of the current leaf node evenly among
1617 // its siblings and ensure that the current node is not full.
1618 // This may require allocating a new node.
1619 template
1620 void IntervalMap::
1621 iterator::overflowLeaf() {
1629 /// overflow - Distribute entries of the current node evenly among
1630 /// its siblings and ensure that the current node is not full.
1631 /// This may require allocating a new node.
1632 /// @param NodeT The type of node at Level (Leaf or Branch).
1633 /// @param Level path index of the overflowing node.
1634 /// @return True when the tree height was changed.
1635 template
1636 template
1637 bool IntervalMap::
1638 iterator::overflow(unsigned Level) {
16221639 using namespace IntervalMapImpl;
16231640 unsigned CurSize[4];
1624 Leaf *Node[4];
1641 NodeT *Node[4];
16251642 unsigned Nodes = 0;
16261643 unsigned Elements = 0;
1627 unsigned Offset = this->treeLeafOffset();
1644 unsigned Offset = this->pathOffset(Level);
16281645
16291646 // Do we have a left sibling?
1630 NodeRef LeftSib = this->leftSibling(this->map->height-1);
1647 NodeRef LeftSib = this->leftSibling(Level);
16311648 if (LeftSib) {
16321649 Offset += Elements = CurSize[Nodes] = LeftSib.size();
1633 Node[Nodes++] = &LeftSib.get();
1634 }
1635
1636 // Current leaf node.
1637 Elements += CurSize[Nodes] = this->treeLeafSize();
1638 Node[Nodes++] = &this->treeLeaf();
1650 Node[Nodes++] = &LeftSib.get();
1651 }
1652
1653 // Current node.
1654 NodeRef CurNode = this->pathNode(Level);
1655 Elements += CurSize[Nodes] = CurNode.size();
1656 Node[Nodes++] = &CurNode.get();
16391657
16401658 // Do we have a right sibling?
1641 NodeRef RightSib = this->rightSibling(this->map->height-1);
1659 NodeRef RightSib = this->rightSibling(Level);
16421660 if (RightSib) {
16431661 Offset += Elements = CurSize[Nodes] = RightSib.size();
1644 Node[Nodes++] = &RightSib.get<Leaf>();
1662 Node[Nodes++] = &RightSib.get<NodeT>();
16451663 }
16461664
16471665 // Do we need to allocate a new node?
16481666 unsigned NewNode = 0;
1649 if (Elements + 1 > Nodes * Leaf::Capacity) {
1667 if (Elements + 1 > Nodes * NodeT::Capacity) {
16501668 // Insert NewNode at the penultimate position, or after a single node.
16511669 NewNode = Nodes == 1 ? 1 : Nodes - 1;
16521670 CurSize[Nodes] = CurSize[NewNode];
16531671 Node[Nodes] = Node[NewNode];
16541672 CurSize[NewNode] = 0;
1655 Node[NewNode] = this->map->allocLeaf();
1673 Node[NewNode] = new(this->map->allocator.template Allocate())NodeT();
16561674 ++Nodes;
16571675 }
16581676
16591677 // Compute the new element distribution.
16601678 unsigned NewSize[4];
1661 IdxPair NewOffset = distribute(Nodes, Elements, Leaf::Capacity,
1679 IdxPair NewOffset = distribute(Nodes, Elements, NodeT::Capacity,
16621680 CurSize, NewSize, Offset, true);
16631681
16641682 // Move current location to the leftmost node.
17011719 #endif
17021720
17031721 // Elements have been rearranged, now update node sizes and stops.
1722 bool SplitRoot = false;
17041723 unsigned Pos = 0;
17051724 for (;;) {
17061725 KeyT Stop = Node[Pos]->stop(NewSize[Pos]-1);
1707 if (NewNode && Pos == NewNode)
1708 insertNode(this->map->height - 1, NodeRef(Node[Pos], NewSize[Pos]), Stop);
1709 else {
1710 setNodeSize(this->map->height - 1, NewSize[Pos]);
1711 setNodeStop(this->map->height - 1, Stop);
1726 if (NewNode && Pos == NewNode) {
1727 SplitRoot = insertNode(Level, NodeRef(Node[Pos], NewSize[Pos]), Stop);
1728 Level += SplitRoot;
1729 } else {
1730 setNodeSize(Level, NewSize[Pos]);
1731 setNodeStop(Level, Stop);
17121732 }
17131733 if (Pos + 1 == Nodes)
17141734 break;
17211741 this->treeDecrement();
17221742 --Pos;
17231743 }
1724 this->treeLeafOffset() = NewOffset.second;
1744 this->pathOffset(Level) = NewOffset.second;
1745 return SplitRoot;
17251746 }
17261747
17271748 } // namespace llvm