1 // Copyright 2010 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef V8_SPLAY_TREE_H_
6 #define V8_SPLAY_TREE_H_
7 
8 #include "src/allocation.h"
9 
10 namespace v8 {
11 namespace internal {
12 
13 
14 // A splay tree.  The config type parameter encapsulates the different
15 // configurations of a concrete splay tree:
16 //
17 //   typedef Key: the key type
18 //   typedef Value: the value type
19 //   static const Key kNoKey: the dummy key used when no key is set
20 //   static Value kNoValue(): the dummy value used to initialize nodes
21 //   static int (Compare)(Key& a, Key& b) -> {-1, 0, 1}: comparison function
22 //
23 // The tree is also parameterized by an allocation policy
24 // (Allocator). The policy is used for allocating lists in the C free
25 // store or the zone; see zone.h.
26 
27 // Forward defined as
28 // template <typename Config, class Allocator = FreeStoreAllocationPolicy>
29 //     class SplayTree;
30 template <typename Config, class AllocationPolicy>
31 class SplayTree {
32  public:
33   typedef typename Config::Key Key;
34   typedef typename Config::Value Value;
35 
36   class Locator;
37 
38   explicit SplayTree(AllocationPolicy allocator = AllocationPolicy())
root_(nullptr)39       : root_(nullptr), allocator_(allocator) {}
40   ~SplayTree();
41 
42   V8_INLINE void* operator new(
43       size_t size, AllocationPolicy allocator = AllocationPolicy()) {
44     return allocator.New(static_cast<int>(size));
45   }
delete(void * p)46   V8_INLINE void operator delete(void* p) { AllocationPolicy::Delete(p); }
47   // Please the MSVC compiler.  We should never have to execute this.
delete(void * p,AllocationPolicy policy)48   V8_INLINE void operator delete(void* p, AllocationPolicy policy) {
49     UNREACHABLE();
50   }
51 
allocator()52   AllocationPolicy allocator() { return allocator_; }
53 
54   // Checks if there is a mapping for the key.
55   bool Contains(const Key& key);
56 
57   // Inserts the given key in this tree with the given value.  Returns
58   // true if a node was inserted, otherwise false.  If found the locator
59   // is enabled and provides access to the mapping for the key.
60   bool Insert(const Key& key, Locator* locator);
61 
62   // Looks up the key in this tree and returns true if it was found,
63   // otherwise false.  If the node is found the locator is enabled and
64   // provides access to the mapping for the key.
65   bool Find(const Key& key, Locator* locator);
66 
67   // Finds the mapping with the greatest key less than or equal to the
68   // given key.
69   bool FindGreatestLessThan(const Key& key, Locator* locator);
70 
71   // Find the mapping with the greatest key in this tree.
72   bool FindGreatest(Locator* locator);
73 
74   // Finds the mapping with the least key greater than or equal to the
75   // given key.
76   bool FindLeastGreaterThan(const Key& key, Locator* locator);
77 
78   // Find the mapping with the least key in this tree.
79   bool FindLeast(Locator* locator);
80 
81   // Move the node from one key to another.
82   bool Move(const Key& old_key, const Key& new_key);
83 
84   // Remove the node with the given key from the tree.
85   bool Remove(const Key& key);
86 
87   // Remove all keys from the tree.
Clear()88   void Clear() { ResetRoot(); }
89 
is_empty()90   bool is_empty() { return root_ == nullptr; }
91 
92   // Perform the splay operation for the given key. Moves the node with
93   // the given key to the top of the tree.  If no node has the given
94   // key, the last node on the search path is moved to the top of the
95   // tree.
96   void Splay(const Key& key);
97 
98   class Node {
99    public:
Node(const Key & key,const Value & value)100     Node(const Key& key, const Value& value)
101         : key_(key), value_(value), left_(nullptr), right_(nullptr) {}
102 
new(size_t size,AllocationPolicy allocator)103     V8_INLINE void* operator new(size_t size, AllocationPolicy allocator) {
104       return allocator.New(static_cast<int>(size));
105     }
delete(void * p)106     V8_INLINE void operator delete(void* p) {
107       return AllocationPolicy::Delete(p);
108     }
109     // Please the MSVC compiler.  We should never have to execute
110     // this.
delete(void * p,AllocationPolicy allocator)111     V8_INLINE void operator delete(void* p, AllocationPolicy allocator) {
112       UNREACHABLE();
113     }
114 
key()115     Key key() { return key_; }
value()116     Value value() { return value_; }
left()117     Node* left() { return left_; }
right()118     Node* right() { return right_; }
119 
120    private:
121     friend class SplayTree;
122     friend class Locator;
123     Key key_;
124     Value value_;
125     Node* left_;
126     Node* right_;
127   };
128 
129   // A locator provides access to a node in the tree without actually
130   // exposing the node.
131   class Locator BASE_EMBEDDED {
132    public:
Locator(Node * node)133     explicit Locator(Node* node) : node_(node) { }
Locator()134     Locator() : node_(nullptr) {}
key()135     const Key& key() { return node_->key_; }
value()136     Value& value() { return node_->value_; }
set_value(const Value & value)137     void set_value(const Value& value) { node_->value_ = value; }
bind(Node * node)138     inline void bind(Node* node) { node_ = node; }
139 
140    private:
141     Node* node_;
142   };
143 
144   template <class Callback>
145   void ForEach(Callback* callback);
146 
147  protected:
148   // Resets tree root. Existing nodes become unreachable.
ResetRoot()149   void ResetRoot() { root_ = nullptr; }
150 
151  private:
152   // Search for a node with a given key. If found, root_ points
153   // to the node.
154   bool FindInternal(const Key& key);
155 
156   // Inserts a node assuming that root_ is already set up.
157   void InsertInternal(int cmp, Node* node);
158 
159   // Removes root_ node.
160   void RemoveRootNode(const Key& key);
161 
162   template<class Callback>
163   class NodeToPairAdaptor BASE_EMBEDDED {
164    public:
NodeToPairAdaptor(Callback * callback)165     explicit NodeToPairAdaptor(Callback* callback)
166         : callback_(callback) { }
Call(Node * node)167     void Call(Node* node) {
168       callback_->Call(node->key(), node->value());
169     }
170 
171    private:
172     Callback* callback_;
173 
174     DISALLOW_COPY_AND_ASSIGN(NodeToPairAdaptor);
175   };
176 
177   class NodeDeleter BASE_EMBEDDED {
178    public:
NodeDeleter()179     NodeDeleter() { }
Call(Node * node)180     void Call(Node* node) { AllocationPolicy::Delete(node); }
181 
182    private:
183     DISALLOW_COPY_AND_ASSIGN(NodeDeleter);
184   };
185 
186   template <class Callback>
187   void ForEachNode(Callback* callback);
188 
189   Node* root_;
190   AllocationPolicy allocator_;
191 
192   DISALLOW_COPY_AND_ASSIGN(SplayTree);
193 };
194 
195 
196 }  // namespace internal
197 }  // namespace v8
198 
199 #endif  // V8_SPLAY_TREE_H_
200