1*0d150db2SJacques Pienaar //===- DeltaTree.cpp - B-Tree for Rewrite Delta tracking ------------------===// 2*0d150db2SJacques Pienaar // 3*0d150db2SJacques Pienaar // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0d150db2SJacques Pienaar // See https://llvm.org/LICENSE.txt for license information. 5*0d150db2SJacques Pienaar // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0d150db2SJacques Pienaar // 7*0d150db2SJacques Pienaar //===----------------------------------------------------------------------===// 8*0d150db2SJacques Pienaar // 9*0d150db2SJacques Pienaar // This file implements the DeltaTree and related classes. 10*0d150db2SJacques Pienaar // 11*0d150db2SJacques Pienaar //===----------------------------------------------------------------------===// 12*0d150db2SJacques Pienaar 13*0d150db2SJacques Pienaar #include "llvm/ADT/DeltaTree.h" 14*0d150db2SJacques Pienaar #include "llvm/Support/Casting.h" 15*0d150db2SJacques Pienaar #include <cassert> 16*0d150db2SJacques Pienaar #include <cstring> 17*0d150db2SJacques Pienaar 18*0d150db2SJacques Pienaar using namespace llvm; 19*0d150db2SJacques Pienaar 20*0d150db2SJacques Pienaar /// The DeltaTree class is a multiway search tree (BTree) structure with some 21*0d150db2SJacques Pienaar /// fancy features. B-Trees are generally more memory and cache efficient 22*0d150db2SJacques Pienaar /// than binary trees, because they store multiple keys/values in each node. 23*0d150db2SJacques Pienaar /// 24*0d150db2SJacques Pienaar /// DeltaTree implements a key/value mapping from FileIndex to Delta, allowing 25*0d150db2SJacques Pienaar /// fast lookup by FileIndex. However, an added (important) bonus is that it 26*0d150db2SJacques Pienaar /// can also efficiently tell us the full accumulated delta for a specific 27*0d150db2SJacques Pienaar /// file offset as well, without traversing the whole tree. 28*0d150db2SJacques Pienaar /// 29*0d150db2SJacques Pienaar /// The nodes of the tree are made up of instances of two classes: 30*0d150db2SJacques Pienaar /// DeltaTreeNode and DeltaTreeInteriorNode. The later subclasses the 31*0d150db2SJacques Pienaar /// former and adds children pointers. Each node knows the full delta of all 32*0d150db2SJacques Pienaar /// entries (recursively) contained inside of it, which allows us to get the 33*0d150db2SJacques Pienaar /// full delta implied by a whole subtree in constant time. 34*0d150db2SJacques Pienaar 35*0d150db2SJacques Pienaar namespace { 36*0d150db2SJacques Pienaar 37*0d150db2SJacques Pienaar /// SourceDelta - As code in the original input buffer is added and deleted, 38*0d150db2SJacques Pienaar /// SourceDelta records are used to keep track of how the input SourceLocation 39*0d150db2SJacques Pienaar /// object is mapped into the output buffer. 40*0d150db2SJacques Pienaar struct SourceDelta { 41*0d150db2SJacques Pienaar unsigned FileLoc; 42*0d150db2SJacques Pienaar int Delta; 43*0d150db2SJacques Pienaar 44*0d150db2SJacques Pienaar static SourceDelta get(unsigned Loc, int D) { 45*0d150db2SJacques Pienaar SourceDelta Delta; 46*0d150db2SJacques Pienaar Delta.FileLoc = Loc; 47*0d150db2SJacques Pienaar Delta.Delta = D; 48*0d150db2SJacques Pienaar return Delta; 49*0d150db2SJacques Pienaar } 50*0d150db2SJacques Pienaar }; 51*0d150db2SJacques Pienaar 52*0d150db2SJacques Pienaar /// DeltaTreeNode - The common part of all nodes. 53*0d150db2SJacques Pienaar /// 54*0d150db2SJacques Pienaar class DeltaTreeNode { 55*0d150db2SJacques Pienaar public: 56*0d150db2SJacques Pienaar struct InsertResult { 57*0d150db2SJacques Pienaar DeltaTreeNode *LHS, *RHS; 58*0d150db2SJacques Pienaar SourceDelta Split; 59*0d150db2SJacques Pienaar }; 60*0d150db2SJacques Pienaar 61*0d150db2SJacques Pienaar private: 62*0d150db2SJacques Pienaar friend class DeltaTreeInteriorNode; 63*0d150db2SJacques Pienaar 64*0d150db2SJacques Pienaar /// WidthFactor - This controls the number of K/V slots held in the BTree: 65*0d150db2SJacques Pienaar /// how wide it is. Each level of the BTree is guaranteed to have at least 66*0d150db2SJacques Pienaar /// WidthFactor-1 K/V pairs (except the root) and may have at most 67*0d150db2SJacques Pienaar /// 2*WidthFactor-1 K/V pairs. 68*0d150db2SJacques Pienaar enum { WidthFactor = 8 }; 69*0d150db2SJacques Pienaar 70*0d150db2SJacques Pienaar /// Values - This tracks the SourceDelta's currently in this node. 71*0d150db2SJacques Pienaar SourceDelta Values[2 * WidthFactor - 1]; 72*0d150db2SJacques Pienaar 73*0d150db2SJacques Pienaar /// NumValuesUsed - This tracks the number of values this node currently 74*0d150db2SJacques Pienaar /// holds. 75*0d150db2SJacques Pienaar unsigned char NumValuesUsed = 0; 76*0d150db2SJacques Pienaar 77*0d150db2SJacques Pienaar /// IsLeaf - This is true if this is a leaf of the btree. If false, this is 78*0d150db2SJacques Pienaar /// an interior node, and is actually an instance of DeltaTreeInteriorNode. 79*0d150db2SJacques Pienaar bool IsLeaf; 80*0d150db2SJacques Pienaar 81*0d150db2SJacques Pienaar /// FullDelta - This is the full delta of all the values in this node and 82*0d150db2SJacques Pienaar /// all children nodes. 83*0d150db2SJacques Pienaar int FullDelta = 0; 84*0d150db2SJacques Pienaar 85*0d150db2SJacques Pienaar public: 86*0d150db2SJacques Pienaar DeltaTreeNode(bool isLeaf = true) : IsLeaf(isLeaf) {} 87*0d150db2SJacques Pienaar 88*0d150db2SJacques Pienaar bool isLeaf() const { return IsLeaf; } 89*0d150db2SJacques Pienaar int getFullDelta() const { return FullDelta; } 90*0d150db2SJacques Pienaar bool isFull() const { return NumValuesUsed == 2 * WidthFactor - 1; } 91*0d150db2SJacques Pienaar 92*0d150db2SJacques Pienaar unsigned getNumValuesUsed() const { return NumValuesUsed; } 93*0d150db2SJacques Pienaar 94*0d150db2SJacques Pienaar const SourceDelta &getValue(unsigned i) const { 95*0d150db2SJacques Pienaar assert(i < NumValuesUsed && "Invalid value #"); 96*0d150db2SJacques Pienaar return Values[i]; 97*0d150db2SJacques Pienaar } 98*0d150db2SJacques Pienaar 99*0d150db2SJacques Pienaar SourceDelta &getValue(unsigned i) { 100*0d150db2SJacques Pienaar assert(i < NumValuesUsed && "Invalid value #"); 101*0d150db2SJacques Pienaar return Values[i]; 102*0d150db2SJacques Pienaar } 103*0d150db2SJacques Pienaar 104*0d150db2SJacques Pienaar /// DoInsertion - Do an insertion of the specified FileIndex/Delta pair into 105*0d150db2SJacques Pienaar /// this node. If insertion is easy, do it and return false. Otherwise, 106*0d150db2SJacques Pienaar /// split the node, populate InsertRes with info about the split, and return 107*0d150db2SJacques Pienaar /// true. 108*0d150db2SJacques Pienaar bool DoInsertion(unsigned FileIndex, int Delta, InsertResult *InsertRes); 109*0d150db2SJacques Pienaar 110*0d150db2SJacques Pienaar void DoSplit(InsertResult &InsertRes); 111*0d150db2SJacques Pienaar 112*0d150db2SJacques Pienaar /// RecomputeFullDeltaLocally - Recompute the FullDelta field by doing a 113*0d150db2SJacques Pienaar /// local walk over our contained deltas. 114*0d150db2SJacques Pienaar void RecomputeFullDeltaLocally(); 115*0d150db2SJacques Pienaar 116*0d150db2SJacques Pienaar void Destroy(); 117*0d150db2SJacques Pienaar }; 118*0d150db2SJacques Pienaar 119*0d150db2SJacques Pienaar /// DeltaTreeInteriorNode - When isLeaf = false, a node has child pointers. 120*0d150db2SJacques Pienaar /// This class tracks them. 121*0d150db2SJacques Pienaar class DeltaTreeInteriorNode : public DeltaTreeNode { 122*0d150db2SJacques Pienaar friend class DeltaTreeNode; 123*0d150db2SJacques Pienaar 124*0d150db2SJacques Pienaar DeltaTreeNode *Children[2 * WidthFactor]; 125*0d150db2SJacques Pienaar 126*0d150db2SJacques Pienaar ~DeltaTreeInteriorNode() { 127*0d150db2SJacques Pienaar for (unsigned i = 0, e = NumValuesUsed + 1; i != e; ++i) 128*0d150db2SJacques Pienaar Children[i]->Destroy(); 129*0d150db2SJacques Pienaar } 130*0d150db2SJacques Pienaar 131*0d150db2SJacques Pienaar public: 132*0d150db2SJacques Pienaar DeltaTreeInteriorNode() : DeltaTreeNode(false /*nonleaf*/) {} 133*0d150db2SJacques Pienaar 134*0d150db2SJacques Pienaar DeltaTreeInteriorNode(const InsertResult &IR) 135*0d150db2SJacques Pienaar : DeltaTreeNode(false /*nonleaf*/) { 136*0d150db2SJacques Pienaar Children[0] = IR.LHS; 137*0d150db2SJacques Pienaar Children[1] = IR.RHS; 138*0d150db2SJacques Pienaar Values[0] = IR.Split; 139*0d150db2SJacques Pienaar FullDelta = 140*0d150db2SJacques Pienaar IR.LHS->getFullDelta() + IR.RHS->getFullDelta() + IR.Split.Delta; 141*0d150db2SJacques Pienaar NumValuesUsed = 1; 142*0d150db2SJacques Pienaar } 143*0d150db2SJacques Pienaar 144*0d150db2SJacques Pienaar const DeltaTreeNode *getChild(unsigned i) const { 145*0d150db2SJacques Pienaar assert(i < getNumValuesUsed() + 1 && "Invalid child"); 146*0d150db2SJacques Pienaar return Children[i]; 147*0d150db2SJacques Pienaar } 148*0d150db2SJacques Pienaar 149*0d150db2SJacques Pienaar DeltaTreeNode *getChild(unsigned i) { 150*0d150db2SJacques Pienaar assert(i < getNumValuesUsed() + 1 && "Invalid child"); 151*0d150db2SJacques Pienaar return Children[i]; 152*0d150db2SJacques Pienaar } 153*0d150db2SJacques Pienaar 154*0d150db2SJacques Pienaar static bool classof(const DeltaTreeNode *N) { return !N->isLeaf(); } 155*0d150db2SJacques Pienaar }; 156*0d150db2SJacques Pienaar 157*0d150db2SJacques Pienaar } // namespace 158*0d150db2SJacques Pienaar 159*0d150db2SJacques Pienaar /// Destroy - A 'virtual' destructor. 160*0d150db2SJacques Pienaar void DeltaTreeNode::Destroy() { 161*0d150db2SJacques Pienaar if (isLeaf()) 162*0d150db2SJacques Pienaar delete this; 163*0d150db2SJacques Pienaar else 164*0d150db2SJacques Pienaar delete cast<DeltaTreeInteriorNode>(this); 165*0d150db2SJacques Pienaar } 166*0d150db2SJacques Pienaar 167*0d150db2SJacques Pienaar /// RecomputeFullDeltaLocally - Recompute the FullDelta field by doing a 168*0d150db2SJacques Pienaar /// local walk over our contained deltas. 169*0d150db2SJacques Pienaar void DeltaTreeNode::RecomputeFullDeltaLocally() { 170*0d150db2SJacques Pienaar int NewFullDelta = 0; 171*0d150db2SJacques Pienaar for (unsigned i = 0, e = getNumValuesUsed(); i != e; ++i) 172*0d150db2SJacques Pienaar NewFullDelta += Values[i].Delta; 173*0d150db2SJacques Pienaar if (auto *IN = dyn_cast<DeltaTreeInteriorNode>(this)) 174*0d150db2SJacques Pienaar for (unsigned i = 0, e = getNumValuesUsed() + 1; i != e; ++i) 175*0d150db2SJacques Pienaar NewFullDelta += IN->getChild(i)->getFullDelta(); 176*0d150db2SJacques Pienaar FullDelta = NewFullDelta; 177*0d150db2SJacques Pienaar } 178*0d150db2SJacques Pienaar 179*0d150db2SJacques Pienaar /// DoInsertion - Do an insertion of the specified FileIndex/Delta pair into 180*0d150db2SJacques Pienaar /// this node. If insertion is easy, do it and return false. Otherwise, 181*0d150db2SJacques Pienaar /// split the node, populate InsertRes with info about the split, and return 182*0d150db2SJacques Pienaar /// true. 183*0d150db2SJacques Pienaar bool DeltaTreeNode::DoInsertion(unsigned FileIndex, int Delta, 184*0d150db2SJacques Pienaar InsertResult *InsertRes) { 185*0d150db2SJacques Pienaar // Maintain full delta for this node. 186*0d150db2SJacques Pienaar FullDelta += Delta; 187*0d150db2SJacques Pienaar 188*0d150db2SJacques Pienaar // Find the insertion point, the first delta whose index is >= FileIndex. 189*0d150db2SJacques Pienaar unsigned i = 0, e = getNumValuesUsed(); 190*0d150db2SJacques Pienaar while (i != e && FileIndex > getValue(i).FileLoc) 191*0d150db2SJacques Pienaar ++i; 192*0d150db2SJacques Pienaar 193*0d150db2SJacques Pienaar // If we found an a record for exactly this file index, just merge this 194*0d150db2SJacques Pienaar // value into the pre-existing record and finish early. 195*0d150db2SJacques Pienaar if (i != e && getValue(i).FileLoc == FileIndex) { 196*0d150db2SJacques Pienaar // NOTE: Delta could drop to zero here. This means that the delta entry is 197*0d150db2SJacques Pienaar // useless and could be removed. Supporting erases is more complex than 198*0d150db2SJacques Pienaar // leaving an entry with Delta=0, so we just leave an entry with Delta=0 in 199*0d150db2SJacques Pienaar // the tree. 200*0d150db2SJacques Pienaar Values[i].Delta += Delta; 201*0d150db2SJacques Pienaar return false; 202*0d150db2SJacques Pienaar } 203*0d150db2SJacques Pienaar 204*0d150db2SJacques Pienaar // Otherwise, we found an insertion point, and we know that the value at the 205*0d150db2SJacques Pienaar // specified index is > FileIndex. Handle the leaf case first. 206*0d150db2SJacques Pienaar if (isLeaf()) { 207*0d150db2SJacques Pienaar if (!isFull()) { 208*0d150db2SJacques Pienaar // For an insertion into a non-full leaf node, just insert the value in 209*0d150db2SJacques Pienaar // its sorted position. This requires moving later values over. 210*0d150db2SJacques Pienaar if (i != e) 211*0d150db2SJacques Pienaar memmove(&Values[i + 1], &Values[i], sizeof(Values[0]) * (e - i)); 212*0d150db2SJacques Pienaar Values[i] = SourceDelta::get(FileIndex, Delta); 213*0d150db2SJacques Pienaar ++NumValuesUsed; 214*0d150db2SJacques Pienaar return false; 215*0d150db2SJacques Pienaar } 216*0d150db2SJacques Pienaar 217*0d150db2SJacques Pienaar // Otherwise, if this is leaf is full, split the node at its median, insert 218*0d150db2SJacques Pienaar // the value into one of the children, and return the result. 219*0d150db2SJacques Pienaar assert(InsertRes && "No result location specified"); 220*0d150db2SJacques Pienaar DoSplit(*InsertRes); 221*0d150db2SJacques Pienaar 222*0d150db2SJacques Pienaar if (InsertRes->Split.FileLoc > FileIndex) 223*0d150db2SJacques Pienaar InsertRes->LHS->DoInsertion(FileIndex, Delta, nullptr /*can't fail*/); 224*0d150db2SJacques Pienaar else 225*0d150db2SJacques Pienaar InsertRes->RHS->DoInsertion(FileIndex, Delta, nullptr /*can't fail*/); 226*0d150db2SJacques Pienaar return true; 227*0d150db2SJacques Pienaar } 228*0d150db2SJacques Pienaar 229*0d150db2SJacques Pienaar // Otherwise, this is an interior node. Send the request down the tree. 230*0d150db2SJacques Pienaar auto *IN = cast<DeltaTreeInteriorNode>(this); 231*0d150db2SJacques Pienaar if (!IN->Children[i]->DoInsertion(FileIndex, Delta, InsertRes)) 232*0d150db2SJacques Pienaar return false; // If there was space in the child, just return. 233*0d150db2SJacques Pienaar 234*0d150db2SJacques Pienaar // Okay, this split the subtree, producing a new value and two children to 235*0d150db2SJacques Pienaar // insert here. If this node is non-full, we can just insert it directly. 236*0d150db2SJacques Pienaar if (!isFull()) { 237*0d150db2SJacques Pienaar // Now that we have two nodes and a new element, insert the perclated value 238*0d150db2SJacques Pienaar // into ourself by moving all the later values/children down, then inserting 239*0d150db2SJacques Pienaar // the new one. 240*0d150db2SJacques Pienaar if (i != e) 241*0d150db2SJacques Pienaar memmove(&IN->Children[i + 2], &IN->Children[i + 1], 242*0d150db2SJacques Pienaar (e - i) * sizeof(IN->Children[0])); 243*0d150db2SJacques Pienaar IN->Children[i] = InsertRes->LHS; 244*0d150db2SJacques Pienaar IN->Children[i + 1] = InsertRes->RHS; 245*0d150db2SJacques Pienaar 246*0d150db2SJacques Pienaar if (e != i) 247*0d150db2SJacques Pienaar memmove(&Values[i + 1], &Values[i], (e - i) * sizeof(Values[0])); 248*0d150db2SJacques Pienaar Values[i] = InsertRes->Split; 249*0d150db2SJacques Pienaar ++NumValuesUsed; 250*0d150db2SJacques Pienaar return false; 251*0d150db2SJacques Pienaar } 252*0d150db2SJacques Pienaar 253*0d150db2SJacques Pienaar // Finally, if this interior node was full and a node is percolated up, split 254*0d150db2SJacques Pienaar // ourself and return that up the chain. Start by saving all our info to 255*0d150db2SJacques Pienaar // avoid having the split clobber it. 256*0d150db2SJacques Pienaar IN->Children[i] = InsertRes->LHS; 257*0d150db2SJacques Pienaar DeltaTreeNode *SubRHS = InsertRes->RHS; 258*0d150db2SJacques Pienaar SourceDelta SubSplit = InsertRes->Split; 259*0d150db2SJacques Pienaar 260*0d150db2SJacques Pienaar // Do the split. 261*0d150db2SJacques Pienaar DoSplit(*InsertRes); 262*0d150db2SJacques Pienaar 263*0d150db2SJacques Pienaar // Figure out where to insert SubRHS/NewSplit. 264*0d150db2SJacques Pienaar DeltaTreeInteriorNode *InsertSide; 265*0d150db2SJacques Pienaar if (SubSplit.FileLoc < InsertRes->Split.FileLoc) 266*0d150db2SJacques Pienaar InsertSide = cast<DeltaTreeInteriorNode>(InsertRes->LHS); 267*0d150db2SJacques Pienaar else 268*0d150db2SJacques Pienaar InsertSide = cast<DeltaTreeInteriorNode>(InsertRes->RHS); 269*0d150db2SJacques Pienaar 270*0d150db2SJacques Pienaar // We now have a non-empty interior node 'InsertSide' to insert 271*0d150db2SJacques Pienaar // SubRHS/SubSplit into. Find out where to insert SubSplit. 272*0d150db2SJacques Pienaar 273*0d150db2SJacques Pienaar // Find the insertion point, the first delta whose index is >SubSplit.FileLoc. 274*0d150db2SJacques Pienaar i = 0; 275*0d150db2SJacques Pienaar e = InsertSide->getNumValuesUsed(); 276*0d150db2SJacques Pienaar while (i != e && SubSplit.FileLoc > InsertSide->getValue(i).FileLoc) 277*0d150db2SJacques Pienaar ++i; 278*0d150db2SJacques Pienaar 279*0d150db2SJacques Pienaar // Now we know that i is the place to insert the split value into. Insert it 280*0d150db2SJacques Pienaar // and the child right after it. 281*0d150db2SJacques Pienaar if (i != e) 282*0d150db2SJacques Pienaar memmove(&InsertSide->Children[i + 2], &InsertSide->Children[i + 1], 283*0d150db2SJacques Pienaar (e - i) * sizeof(IN->Children[0])); 284*0d150db2SJacques Pienaar InsertSide->Children[i + 1] = SubRHS; 285*0d150db2SJacques Pienaar 286*0d150db2SJacques Pienaar if (e != i) 287*0d150db2SJacques Pienaar memmove(&InsertSide->Values[i + 1], &InsertSide->Values[i], 288*0d150db2SJacques Pienaar (e - i) * sizeof(Values[0])); 289*0d150db2SJacques Pienaar InsertSide->Values[i] = SubSplit; 290*0d150db2SJacques Pienaar ++InsertSide->NumValuesUsed; 291*0d150db2SJacques Pienaar InsertSide->FullDelta += SubSplit.Delta + SubRHS->getFullDelta(); 292*0d150db2SJacques Pienaar return true; 293*0d150db2SJacques Pienaar } 294*0d150db2SJacques Pienaar 295*0d150db2SJacques Pienaar /// DoSplit - Split the currently full node (which has 2*WidthFactor-1 values) 296*0d150db2SJacques Pienaar /// into two subtrees each with "WidthFactor-1" values and a pivot value. 297*0d150db2SJacques Pienaar /// Return the pieces in InsertRes. 298*0d150db2SJacques Pienaar void DeltaTreeNode::DoSplit(InsertResult &InsertRes) { 299*0d150db2SJacques Pienaar assert(isFull() && "Why split a non-full node?"); 300*0d150db2SJacques Pienaar 301*0d150db2SJacques Pienaar // Since this node is full, it contains 2*WidthFactor-1 values. We move 302*0d150db2SJacques Pienaar // the first 'WidthFactor-1' values to the LHS child (which we leave in this 303*0d150db2SJacques Pienaar // node), propagate one value up, and move the last 'WidthFactor-1' values 304*0d150db2SJacques Pienaar // into the RHS child. 305*0d150db2SJacques Pienaar 306*0d150db2SJacques Pienaar // Create the new child node. 307*0d150db2SJacques Pienaar DeltaTreeNode *NewNode; 308*0d150db2SJacques Pienaar if (auto *IN = dyn_cast<DeltaTreeInteriorNode>(this)) { 309*0d150db2SJacques Pienaar // If this is an interior node, also move over 'WidthFactor' children 310*0d150db2SJacques Pienaar // into the new node. 311*0d150db2SJacques Pienaar DeltaTreeInteriorNode *New = new DeltaTreeInteriorNode(); 312*0d150db2SJacques Pienaar memcpy(&New->Children[0], &IN->Children[WidthFactor], 313*0d150db2SJacques Pienaar WidthFactor * sizeof(IN->Children[0])); 314*0d150db2SJacques Pienaar NewNode = New; 315*0d150db2SJacques Pienaar } else { 316*0d150db2SJacques Pienaar // Just create the new leaf node. 317*0d150db2SJacques Pienaar NewNode = new DeltaTreeNode(); 318*0d150db2SJacques Pienaar } 319*0d150db2SJacques Pienaar 320*0d150db2SJacques Pienaar // Move over the last 'WidthFactor-1' values from here to NewNode. 321*0d150db2SJacques Pienaar memcpy(&NewNode->Values[0], &Values[WidthFactor], 322*0d150db2SJacques Pienaar (WidthFactor - 1) * sizeof(Values[0])); 323*0d150db2SJacques Pienaar 324*0d150db2SJacques Pienaar // Decrease the number of values in the two nodes. 325*0d150db2SJacques Pienaar NewNode->NumValuesUsed = NumValuesUsed = WidthFactor - 1; 326*0d150db2SJacques Pienaar 327*0d150db2SJacques Pienaar // Recompute the two nodes' full delta. 328*0d150db2SJacques Pienaar NewNode->RecomputeFullDeltaLocally(); 329*0d150db2SJacques Pienaar RecomputeFullDeltaLocally(); 330*0d150db2SJacques Pienaar 331*0d150db2SJacques Pienaar InsertRes.LHS = this; 332*0d150db2SJacques Pienaar InsertRes.RHS = NewNode; 333*0d150db2SJacques Pienaar InsertRes.Split = Values[WidthFactor - 1]; 334*0d150db2SJacques Pienaar } 335*0d150db2SJacques Pienaar 336*0d150db2SJacques Pienaar //===----------------------------------------------------------------------===// 337*0d150db2SJacques Pienaar // DeltaTree Implementation 338*0d150db2SJacques Pienaar //===----------------------------------------------------------------------===// 339*0d150db2SJacques Pienaar 340*0d150db2SJacques Pienaar // #define VERIFY_TREE 341*0d150db2SJacques Pienaar 342*0d150db2SJacques Pienaar #ifdef VERIFY_TREE 343*0d150db2SJacques Pienaar /// VerifyTree - Walk the btree performing assertions on various properties to 344*0d150db2SJacques Pienaar /// verify consistency. This is useful for debugging new changes to the tree. 345*0d150db2SJacques Pienaar static void VerifyTree(const DeltaTreeNode *N) { 346*0d150db2SJacques Pienaar const auto *IN = dyn_cast<DeltaTreeInteriorNode>(N); 347*0d150db2SJacques Pienaar if (IN == 0) { 348*0d150db2SJacques Pienaar // Verify leaves, just ensure that FullDelta matches up and the elements 349*0d150db2SJacques Pienaar // are in proper order. 350*0d150db2SJacques Pienaar int FullDelta = 0; 351*0d150db2SJacques Pienaar for (unsigned i = 0, e = N->getNumValuesUsed(); i != e; ++i) { 352*0d150db2SJacques Pienaar if (i) 353*0d150db2SJacques Pienaar assert(N->getValue(i - 1).FileLoc < N->getValue(i).FileLoc); 354*0d150db2SJacques Pienaar FullDelta += N->getValue(i).Delta; 355*0d150db2SJacques Pienaar } 356*0d150db2SJacques Pienaar assert(FullDelta == N->getFullDelta()); 357*0d150db2SJacques Pienaar return; 358*0d150db2SJacques Pienaar } 359*0d150db2SJacques Pienaar 360*0d150db2SJacques Pienaar // Verify interior nodes: Ensure that FullDelta matches up and the 361*0d150db2SJacques Pienaar // elements are in proper order and the children are in proper order. 362*0d150db2SJacques Pienaar int FullDelta = 0; 363*0d150db2SJacques Pienaar for (unsigned i = 0, e = IN->getNumValuesUsed(); i != e; ++i) { 364*0d150db2SJacques Pienaar const SourceDelta &IVal = N->getValue(i); 365*0d150db2SJacques Pienaar const DeltaTreeNode *IChild = IN->getChild(i); 366*0d150db2SJacques Pienaar if (i) 367*0d150db2SJacques Pienaar assert(IN->getValue(i - 1).FileLoc < IVal.FileLoc); 368*0d150db2SJacques Pienaar FullDelta += IVal.Delta; 369*0d150db2SJacques Pienaar FullDelta += IChild->getFullDelta(); 370*0d150db2SJacques Pienaar 371*0d150db2SJacques Pienaar // The largest value in child #i should be smaller than FileLoc. 372*0d150db2SJacques Pienaar assert(IChild->getValue(IChild->getNumValuesUsed() - 1).FileLoc < 373*0d150db2SJacques Pienaar IVal.FileLoc); 374*0d150db2SJacques Pienaar 375*0d150db2SJacques Pienaar // The smallest value in child #i+1 should be larger than FileLoc. 376*0d150db2SJacques Pienaar assert(IN->getChild(i + 1)->getValue(0).FileLoc > IVal.FileLoc); 377*0d150db2SJacques Pienaar VerifyTree(IChild); 378*0d150db2SJacques Pienaar } 379*0d150db2SJacques Pienaar 380*0d150db2SJacques Pienaar FullDelta += IN->getChild(IN->getNumValuesUsed())->getFullDelta(); 381*0d150db2SJacques Pienaar 382*0d150db2SJacques Pienaar assert(FullDelta == N->getFullDelta()); 383*0d150db2SJacques Pienaar } 384*0d150db2SJacques Pienaar #endif // VERIFY_TREE 385*0d150db2SJacques Pienaar 386*0d150db2SJacques Pienaar static DeltaTreeNode *getRoot(void *Root) { return (DeltaTreeNode *)Root; } 387*0d150db2SJacques Pienaar 388*0d150db2SJacques Pienaar DeltaTree::DeltaTree() { Root = new DeltaTreeNode(); } 389*0d150db2SJacques Pienaar 390*0d150db2SJacques Pienaar DeltaTree::DeltaTree(const DeltaTree &RHS) { 391*0d150db2SJacques Pienaar // Currently we only support copying when the RHS is empty. 392*0d150db2SJacques Pienaar assert(getRoot(RHS.Root)->getNumValuesUsed() == 0 && 393*0d150db2SJacques Pienaar "Can only copy empty tree"); 394*0d150db2SJacques Pienaar Root = new DeltaTreeNode(); 395*0d150db2SJacques Pienaar } 396*0d150db2SJacques Pienaar 397*0d150db2SJacques Pienaar DeltaTree::~DeltaTree() { getRoot(Root)->Destroy(); } 398*0d150db2SJacques Pienaar 399*0d150db2SJacques Pienaar /// getDeltaAt - Return the accumulated delta at the specified file offset. 400*0d150db2SJacques Pienaar /// This includes all insertions or delections that occurred *before* the 401*0d150db2SJacques Pienaar /// specified file index. 402*0d150db2SJacques Pienaar int DeltaTree::getDeltaAt(unsigned FileIndex) const { 403*0d150db2SJacques Pienaar const DeltaTreeNode *Node = getRoot(Root); 404*0d150db2SJacques Pienaar 405*0d150db2SJacques Pienaar int Result = 0; 406*0d150db2SJacques Pienaar 407*0d150db2SJacques Pienaar // Walk down the tree. 408*0d150db2SJacques Pienaar while (true) { 409*0d150db2SJacques Pienaar // For all nodes, include any local deltas before the specified file 410*0d150db2SJacques Pienaar // index by summing them up directly. Keep track of how many were 411*0d150db2SJacques Pienaar // included. 412*0d150db2SJacques Pienaar unsigned NumValsGreater = 0; 413*0d150db2SJacques Pienaar for (unsigned e = Node->getNumValuesUsed(); NumValsGreater != e; 414*0d150db2SJacques Pienaar ++NumValsGreater) { 415*0d150db2SJacques Pienaar const SourceDelta &Val = Node->getValue(NumValsGreater); 416*0d150db2SJacques Pienaar 417*0d150db2SJacques Pienaar if (Val.FileLoc >= FileIndex) 418*0d150db2SJacques Pienaar break; 419*0d150db2SJacques Pienaar Result += Val.Delta; 420*0d150db2SJacques Pienaar } 421*0d150db2SJacques Pienaar 422*0d150db2SJacques Pienaar // If we have an interior node, include information about children and 423*0d150db2SJacques Pienaar // recurse. Otherwise, if we have a leaf, we're done. 424*0d150db2SJacques Pienaar const auto *IN = dyn_cast<DeltaTreeInteriorNode>(Node); 425*0d150db2SJacques Pienaar if (!IN) 426*0d150db2SJacques Pienaar return Result; 427*0d150db2SJacques Pienaar 428*0d150db2SJacques Pienaar // Include any children to the left of the values we skipped, all of 429*0d150db2SJacques Pienaar // their deltas should be included as well. 430*0d150db2SJacques Pienaar for (unsigned i = 0; i != NumValsGreater; ++i) 431*0d150db2SJacques Pienaar Result += IN->getChild(i)->getFullDelta(); 432*0d150db2SJacques Pienaar 433*0d150db2SJacques Pienaar // If we found exactly the value we were looking for, break off the 434*0d150db2SJacques Pienaar // search early. There is no need to search the RHS of the value for 435*0d150db2SJacques Pienaar // partial results. 436*0d150db2SJacques Pienaar if (NumValsGreater != Node->getNumValuesUsed() && 437*0d150db2SJacques Pienaar Node->getValue(NumValsGreater).FileLoc == FileIndex) 438*0d150db2SJacques Pienaar return Result + IN->getChild(NumValsGreater)->getFullDelta(); 439*0d150db2SJacques Pienaar 440*0d150db2SJacques Pienaar // Otherwise, traverse down the tree. The selected subtree may be 441*0d150db2SJacques Pienaar // partially included in the range. 442*0d150db2SJacques Pienaar Node = IN->getChild(NumValsGreater); 443*0d150db2SJacques Pienaar } 444*0d150db2SJacques Pienaar // NOT REACHED. 445*0d150db2SJacques Pienaar } 446*0d150db2SJacques Pienaar 447*0d150db2SJacques Pienaar /// AddDelta - When a change is made that shifts around the text buffer, 448*0d150db2SJacques Pienaar /// this method is used to record that info. It inserts a delta of 'Delta' 449*0d150db2SJacques Pienaar /// into the current DeltaTree at offset FileIndex. 450*0d150db2SJacques Pienaar void DeltaTree::AddDelta(unsigned FileIndex, int Delta) { 451*0d150db2SJacques Pienaar assert(Delta && "Adding a noop?"); 452*0d150db2SJacques Pienaar DeltaTreeNode *MyRoot = getRoot(Root); 453*0d150db2SJacques Pienaar 454*0d150db2SJacques Pienaar DeltaTreeNode::InsertResult InsertRes; 455*0d150db2SJacques Pienaar if (MyRoot->DoInsertion(FileIndex, Delta, &InsertRes)) { 456*0d150db2SJacques Pienaar Root = new DeltaTreeInteriorNode(InsertRes); 457*0d150db2SJacques Pienaar #ifdef VERIFY_TREE 458*0d150db2SJacques Pienaar MyRoot = Root; 459*0d150db2SJacques Pienaar #endif 460*0d150db2SJacques Pienaar } 461*0d150db2SJacques Pienaar 462*0d150db2SJacques Pienaar #ifdef VERIFY_TREE 463*0d150db2SJacques Pienaar VerifyTree(MyRoot); 464*0d150db2SJacques Pienaar #endif 465*0d150db2SJacques Pienaar } 466