DeltaTree.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421
  1. //===--- DeltaTree.cpp - B-Tree for Rewrite Delta tracking ----------------===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. //
  10. // This file implements the DeltaTree and related classes.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #include "clang/Rewrite/DeltaTree.h"
  14. #include "llvm/Support/Casting.h"
  15. #include <cstring>
  16. using namespace clang;
  17. using llvm::cast;
  18. using llvm::dyn_cast;
  19. namespace {
  20. struct SourceDelta;
  21. class DeltaTreeNode;
  22. class DeltaTreeInteriorNode;
  23. }
  24. /// The DeltaTree class is a multiway search tree (BTree) structure with some
  25. /// fancy features. B-Trees are are generally more memory and cache efficient
  26. /// than binary trees, because they store multiple keys/values in each node.
  27. ///
  28. /// DeltaTree implements a key/value mapping from FileIndex to Delta, allowing
  29. /// fast lookup by FileIndex. However, an added (important) bonus is that it
  30. /// can also efficiently tell us the full accumulated delta for a specific
  31. /// file offset as well, without traversing the whole tree.
  32. ///
  33. /// The nodes of the tree are made up of instances of two classes:
  34. /// DeltaTreeNode and DeltaTreeInteriorNode. The later subclasses the
  35. /// former and adds children pointers. Each node knows the full delta of all
  36. /// entries (recursively) contained inside of it, which allows us to get the
  37. /// full delta implied by a whole subtree in constant time.
  38. namespace {
  39. /// SourceDelta - As code in the original input buffer is added and deleted,
  40. /// SourceDelta records are used to keep track of how the input SourceLocation
  41. /// object is mapped into the output buffer.
  42. struct SourceDelta {
  43. unsigned FileLoc;
  44. int Delta;
  45. static SourceDelta get(unsigned Loc, int D) {
  46. SourceDelta Delta;
  47. Delta.FileLoc = Loc;
  48. Delta.Delta = D;
  49. return Delta;
  50. }
  51. };
  52. } // end anonymous namespace
  53. namespace {
  54. /// DeltaTreeNode - The common part of all nodes.
  55. ///
  56. class DeltaTreeNode {
  57. friend class DeltaTreeInteriorNode;
  58. /// WidthFactor - This controls the number of K/V slots held in the BTree:
  59. /// how wide it is. Each level of the BTree is guaranteed to have at least
  60. /// WidthFactor-1 K/V pairs (unless the whole tree is less full than that)
  61. /// and may have at most 2*WidthFactor-1 K/V pairs.
  62. enum { WidthFactor = 8 };
  63. /// Values - This tracks the SourceDelta's currently in this node.
  64. ///
  65. SourceDelta Values[2*WidthFactor-1];
  66. /// NumValuesUsed - This tracks the number of values this node currently
  67. /// holds.
  68. unsigned char NumValuesUsed;
  69. /// IsLeaf - This is true if this is a leaf of the btree. If false, this is
  70. /// an interior node, and is actually an instance of DeltaTreeInteriorNode.
  71. bool IsLeaf;
  72. /// FullDelta - This is the full delta of all the values in this node and
  73. /// all children nodes.
  74. int FullDelta;
  75. public:
  76. DeltaTreeNode(bool isLeaf = true)
  77. : NumValuesUsed(0), IsLeaf(isLeaf), FullDelta(0) {}
  78. bool isLeaf() const { return IsLeaf; }
  79. int getFullDelta() const { return FullDelta; }
  80. bool isFull() const { return NumValuesUsed == 2*WidthFactor-1; }
  81. unsigned getNumValuesUsed() const { return NumValuesUsed; }
  82. const SourceDelta &getValue(unsigned i) const {
  83. assert(i < NumValuesUsed && "Invalid value #");
  84. return Values[i];
  85. }
  86. SourceDelta &getValue(unsigned i) {
  87. assert(i < NumValuesUsed && "Invalid value #");
  88. return Values[i];
  89. }
  90. /// AddDeltaNonFull - Add a delta to this tree and/or it's children, knowing
  91. /// that this node is not currently full.
  92. void AddDeltaNonFull(unsigned FileIndex, int Delta);
  93. /// RecomputeFullDeltaLocally - Recompute the FullDelta field by doing a
  94. /// local walk over our contained deltas.
  95. void RecomputeFullDeltaLocally();
  96. void Destroy();
  97. static inline bool classof(const DeltaTreeNode *) { return true; }
  98. };
  99. } // end anonymous namespace
  100. namespace {
  101. /// DeltaTreeInteriorNode - When isLeaf = false, a node has child pointers.
  102. /// This class tracks them.
  103. class DeltaTreeInteriorNode : public DeltaTreeNode {
  104. DeltaTreeNode *Children[2*WidthFactor];
  105. ~DeltaTreeInteriorNode() {
  106. for (unsigned i = 0, e = NumValuesUsed+1; i != e; ++i)
  107. Children[i]->Destroy();
  108. }
  109. friend class DeltaTreeNode;
  110. public:
  111. DeltaTreeInteriorNode() : DeltaTreeNode(false /*nonleaf*/) {}
  112. DeltaTreeInteriorNode(DeltaTreeNode *FirstChild)
  113. : DeltaTreeNode(false /*nonleaf*/) {
  114. FullDelta = FirstChild->FullDelta;
  115. Children[0] = FirstChild;
  116. }
  117. const DeltaTreeNode *getChild(unsigned i) const {
  118. assert(i < getNumValuesUsed()+1 && "Invalid child");
  119. return Children[i];
  120. }
  121. DeltaTreeNode *getChild(unsigned i) {
  122. assert(i < getNumValuesUsed()+1 && "Invalid child");
  123. return Children[i];
  124. }
  125. static inline bool classof(const DeltaTreeInteriorNode *) { return true; }
  126. static inline bool classof(const DeltaTreeNode *N) { return !N->isLeaf(); }
  127. private:
  128. void SplitChild(unsigned ChildNo);
  129. };
  130. }
  131. /// Destroy - A 'virtual' destructor.
  132. void DeltaTreeNode::Destroy() {
  133. if (isLeaf())
  134. delete this;
  135. else
  136. delete cast<DeltaTreeInteriorNode>(this);
  137. }
  138. /// RecomputeFullDeltaLocally - Recompute the FullDelta field by doing a
  139. /// local walk over our contained deltas.
  140. void DeltaTreeNode::RecomputeFullDeltaLocally() {
  141. int NewFullDelta = 0;
  142. for (unsigned i = 0, e = getNumValuesUsed(); i != e; ++i)
  143. NewFullDelta += Values[i].Delta;
  144. if (DeltaTreeInteriorNode *IN = dyn_cast<DeltaTreeInteriorNode>(this))
  145. for (unsigned i = 0, e = getNumValuesUsed()+1; i != e; ++i)
  146. NewFullDelta += IN->getChild(i)->getFullDelta();
  147. FullDelta = NewFullDelta;
  148. }
  149. /// AddDeltaNonFull - Add a delta to this tree and/or it's children, knowing
  150. /// that this node is not currently full.
  151. void DeltaTreeNode::AddDeltaNonFull(unsigned FileIndex, int Delta) {
  152. assert(!isFull() && "AddDeltaNonFull on a full tree?");
  153. // Maintain full delta for this node.
  154. FullDelta += Delta;
  155. // Find the insertion point, the first delta whose index is >= FileIndex.
  156. unsigned i = 0, e = getNumValuesUsed();
  157. while (i != e && FileIndex > getValue(i).FileLoc)
  158. ++i;
  159. // If we found an a record for exactly this file index, just merge this
  160. // value into the preexisting record and finish early.
  161. if (i != e && getValue(i).FileLoc == FileIndex) {
  162. // NOTE: Delta could drop to zero here. This means that the next delta
  163. // entry is useless and could be removed. Supporting erases is
  164. // significantly more complex though, so we just leave an entry with
  165. // Delta=0 in the tree.
  166. Values[i].Delta += Delta;
  167. return;
  168. }
  169. if (DeltaTreeInteriorNode *IN = dyn_cast<DeltaTreeInteriorNode>(this)) {
  170. // Insertion into an interior node propagates the value down to a child.
  171. DeltaTreeNode *Child = IN->getChild(i);
  172. // If the child tree is full, split it, pulling an element up into our
  173. // node.
  174. if (Child->isFull()) {
  175. IN->SplitChild(i);
  176. SourceDelta &MedianVal = getValue(i);
  177. // If the median value we pulled up is exactly our insert position, add
  178. // the delta and return.
  179. if (MedianVal.FileLoc == FileIndex) {
  180. MedianVal.Delta += Delta;
  181. return;
  182. }
  183. // If the median value pulled up is less than our current search point,
  184. // include those deltas and search down the RHS now.
  185. if (MedianVal.FileLoc < FileIndex)
  186. Child = IN->getChild(i+1);
  187. }
  188. Child->AddDeltaNonFull(FileIndex, Delta);
  189. } else {
  190. // For an insertion into a non-full leaf node, just insert the value in
  191. // its sorted position. This requires moving later values over.
  192. if (i != e)
  193. memmove(&Values[i+1], &Values[i], sizeof(Values[0])*(e-i));
  194. Values[i] = SourceDelta::get(FileIndex, Delta);
  195. ++NumValuesUsed;
  196. }
  197. }
  198. /// SplitChild - At this point, we know that the current node is not full and
  199. /// that the specified child of this node is. Split the child in half at its
  200. /// median, propagating one value up into us. Child may be either an interior
  201. /// or leaf node.
  202. void DeltaTreeInteriorNode::SplitChild(unsigned ChildNo) {
  203. DeltaTreeNode *Child = getChild(ChildNo);
  204. assert(!isFull() && Child->isFull() && "Inconsistent constraints");
  205. // Since the child is full, it contains 2*WidthFactor-1 values. We move
  206. // the first 'WidthFactor-1' values to the LHS child (which we leave in the
  207. // original child), propagate one value up into us, and move the last
  208. // 'WidthFactor-1' values into thew RHS child.
  209. // Create the new child node.
  210. DeltaTreeNode *NewNode;
  211. if (DeltaTreeInteriorNode *CIN = dyn_cast<DeltaTreeInteriorNode>(Child)) {
  212. // If the child is an interior node, also move over 'WidthFactor' grand
  213. // children into the new node.
  214. NewNode = new DeltaTreeInteriorNode();
  215. memcpy(&((DeltaTreeInteriorNode*)NewNode)->Children[0],
  216. &CIN->Children[WidthFactor],
  217. WidthFactor*sizeof(CIN->Children[0]));
  218. } else {
  219. // Just create the child node.
  220. NewNode = new DeltaTreeNode();
  221. }
  222. // Move over the last 'WidthFactor-1' values from Child to NewNode.
  223. memcpy(&NewNode->Values[0], &Child->Values[WidthFactor],
  224. (WidthFactor-1)*sizeof(Child->Values[0]));
  225. // Decrease the number of values in the two children.
  226. NewNode->NumValuesUsed = Child->NumValuesUsed = WidthFactor-1;
  227. // Recompute the two children's full delta. Our delta hasn't changed, but
  228. // their delta has.
  229. NewNode->RecomputeFullDeltaLocally();
  230. Child->RecomputeFullDeltaLocally();
  231. // Now that we have two nodes and a new element, insert the median value
  232. // into ourself by moving all the later values/children down, then inserting
  233. // the new one.
  234. if (getNumValuesUsed() != ChildNo)
  235. memmove(&Children[ChildNo+2], &Children[ChildNo+1],
  236. (getNumValuesUsed()-ChildNo)*sizeof(Children[0]));
  237. Children[ChildNo+1] = NewNode;
  238. if (getNumValuesUsed() != ChildNo)
  239. memmove(&Values[ChildNo+1], &Values[ChildNo],
  240. (getNumValuesUsed()-ChildNo)*sizeof(Values[0]));
  241. Values[ChildNo] = Child->Values[WidthFactor-1];
  242. ++NumValuesUsed;
  243. }
  244. //===----------------------------------------------------------------------===//
  245. // DeltaTree Implementation
  246. //===----------------------------------------------------------------------===//
  247. //#define VERIFY_TREE
  248. #ifdef VERIFY_TREE
  249. /// VerifyTree - Walk the btree performing assertions on various properties to
  250. /// verify consistency. This is useful for debugging new changes to the tree.
  251. static void VerifyTree(const DeltaTreeNode *N) {
  252. const DeltaTreeInteriorNode *IN = dyn_cast<DeltaTreeInteriorNode>(N);
  253. if (IN == 0) {
  254. // Verify leaves, just ensure that FullDelta matches up and the elements
  255. // are in proper order.
  256. int FullDelta = 0;
  257. for (unsigned i = 0, e = N->getNumValuesUsed(); i != e; ++i) {
  258. if (i)
  259. assert(N->getValue(i-1).FileLoc < N->getValue(i).FileLoc);
  260. FullDelta += N->getValue(i).Delta;
  261. }
  262. assert(FullDelta == N->getFullDelta());
  263. return;
  264. }
  265. // Verify interior nodes: Ensure that FullDelta matches up and the
  266. // elements are in proper order and the children are in proper order.
  267. int FullDelta = 0;
  268. for (unsigned i = 0, e = IN->getNumValuesUsed(); i != e; ++i) {
  269. const SourceDelta &IVal = N->getValue(i);
  270. const DeltaTreeNode *IChild = IN->getChild(i);
  271. if (i)
  272. assert(IN->getValue(i-1).FileLoc < IVal.FileLoc);
  273. FullDelta += IVal.Delta;
  274. FullDelta += IChild->getFullDelta();
  275. // The largest value in child #i should be smaller than FileLoc.
  276. assert(IChild->getValue(IChild->getNumValuesUsed()-1).FileLoc <
  277. IVal.FileLoc);
  278. // The smallest value in child #i+1 should be larger than FileLoc.
  279. assert(IN->getChild(i+1)->getValue(0).FileLoc > IVal.FileLoc);
  280. VerifyTree(IChild);
  281. }
  282. FullDelta += IN->getChild(IN->getNumValuesUsed())->getFullDelta();
  283. assert(FullDelta == N->getFullDelta());
  284. }
  285. #endif // VERIFY_TREE
  286. static DeltaTreeNode *getRoot(void *Root) {
  287. return (DeltaTreeNode*)Root;
  288. }
  289. DeltaTree::DeltaTree() {
  290. Root = new DeltaTreeNode();
  291. }
  292. DeltaTree::DeltaTree(const DeltaTree &RHS) {
  293. // Currently we only support copying when the RHS is empty.
  294. assert(getRoot(RHS.Root)->getNumValuesUsed() == 0 &&
  295. "Can only copy empty tree");
  296. Root = new DeltaTreeNode();
  297. }
  298. DeltaTree::~DeltaTree() {
  299. getRoot(Root)->Destroy();
  300. }
  301. /// getDeltaAt - Return the accumulated delta at the specified file offset.
  302. /// This includes all insertions or delections that occurred *before* the
  303. /// specified file index.
  304. int DeltaTree::getDeltaAt(unsigned FileIndex) const {
  305. const DeltaTreeNode *Node = getRoot(Root);
  306. int Result = 0;
  307. // Walk down the tree.
  308. while (1) {
  309. // For all nodes, include any local deltas before the specified file
  310. // index by summing them up directly. Keep track of how many were
  311. // included.
  312. unsigned NumValsGreater = 0;
  313. for (unsigned e = Node->getNumValuesUsed(); NumValsGreater != e;
  314. ++NumValsGreater) {
  315. const SourceDelta &Val = Node->getValue(NumValsGreater);
  316. if (Val.FileLoc >= FileIndex)
  317. break;
  318. Result += Val.Delta;
  319. }
  320. // If we have an interior node, include information about children and
  321. // recurse. Otherwise, if we have a leaf, we're done.
  322. const DeltaTreeInteriorNode *IN = dyn_cast<DeltaTreeInteriorNode>(Node);
  323. if (!IN) return Result;
  324. // Include any children to the left of the values we skipped, all of
  325. // their deltas should be included as well.
  326. for (unsigned i = 0; i != NumValsGreater; ++i)
  327. Result += IN->getChild(i)->getFullDelta();
  328. // If we found exactly the value we were looking for, break off the
  329. // search early. There is no need to search the RHS of the value for
  330. // partial results.
  331. if (NumValsGreater != Node->getNumValuesUsed() &&
  332. Node->getValue(NumValsGreater).FileLoc == FileIndex)
  333. return Result;
  334. // Otherwise, traverse down the tree. The selected subtree may be
  335. // partially included in the range.
  336. Node = IN->getChild(NumValsGreater);
  337. }
  338. // NOT REACHED.
  339. }
  340. /// AddDelta - When a change is made that shifts around the text buffer,
  341. /// this method is used to record that info. It inserts a delta of 'Delta'
  342. /// into the current DeltaTree at offset FileIndex.
  343. void DeltaTree::AddDelta(unsigned FileIndex, int Delta) {
  344. assert(Delta && "Adding a noop?");
  345. // If the root is full, create a new dummy (non-empty) interior node that
  346. // points to it, allowing the old root to be split.
  347. if (getRoot(Root)->isFull())
  348. Root = new DeltaTreeInteriorNode(getRoot(Root));
  349. getRoot(Root)->AddDeltaNonFull(FileIndex, Delta);
  350. #ifdef VERIFY_TREE
  351. VerifyTree(Root);
  352. #endif
  353. }