Home | History | Annotate | Download | only in src
      1 // Copyright 2006-2008 the V8 project authors. All rights reserved.
      2 // Redistribution and use in source and binary forms, with or without
      3 // modification, are permitted provided that the following conditions are
      4 // met:
      5 //
      6 //     * Redistributions of source code must retain the above copyright
      7 //       notice, this list of conditions and the following disclaimer.
      8 //     * Redistributions in binary form must reproduce the above
      9 //       copyright notice, this list of conditions and the following
     10 //       disclaimer in the documentation and/or other materials provided
     11 //       with the distribution.
     12 //     * Neither the name of Google Inc. nor the names of its
     13 //       contributors may be used to endorse or promote products derived
     14 //       from this software without specific prior written permission.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 
     28 #ifndef V8_ZONE_INL_H_
     29 #define V8_ZONE_INL_H_
     30 
     31 #include "zone.h"
     32 #include "v8-counters.h"
     33 
     34 namespace v8 {
     35 namespace internal {
     36 
     37 
     38 inline void* Zone::New(int size) {
     39   ASSERT(AssertNoZoneAllocation::allow_allocation());
     40   ASSERT(ZoneScope::nesting() > 0);
     41   // Round up the requested size to fit the alignment.
     42   size = RoundUp(size, kAlignment);
     43 
     44   // Check if the requested size is available without expanding.
     45   Address result = position_;
     46   if ((position_ += size) > limit_) result = NewExpand(size);
     47 
     48   // Check that the result has the proper alignment and return it.
     49   ASSERT(IsAddressAligned(result, kAlignment, 0));
     50   return reinterpret_cast<void*>(result);
     51 }
     52 
     53 
     54 template <typename T>
     55 T* Zone::NewArray(int length) {
     56   return static_cast<T*>(Zone::New(length * sizeof(T)));
     57 }
     58 
     59 
     60 bool Zone::excess_allocation() {
     61   return segment_bytes_allocated_ > zone_excess_limit_;
     62 }
     63 
     64 
     65 void Zone::adjust_segment_bytes_allocated(int delta) {
     66   segment_bytes_allocated_ += delta;
     67   Counters::zone_segment_bytes.Set(segment_bytes_allocated_);
     68 }
     69 
     70 
     71 template <typename C>
     72 bool ZoneSplayTree<C>::Insert(const Key& key, Locator* locator) {
     73   if (is_empty()) {
     74     // If the tree is empty, insert the new node.
     75     root_ = new Node(key, C::kNoValue);
     76   } else {
     77     // Splay on the key to move the last node on the search path
     78     // for the key to the root of the tree.
     79     Splay(key);
     80     // Ignore repeated insertions with the same key.
     81     int cmp = C::Compare(key, root_->key_);
     82     if (cmp == 0) {
     83       locator->bind(root_);
     84       return false;
     85     }
     86     // Insert the new node.
     87     Node* node = new Node(key, C::kNoValue);
     88     if (cmp > 0) {
     89       node->left_ = root_;
     90       node->right_ = root_->right_;
     91       root_->right_ = NULL;
     92     } else {
     93       node->right_ = root_;
     94       node->left_ = root_->left_;
     95       root_->left_ = NULL;
     96     }
     97     root_ = node;
     98   }
     99   locator->bind(root_);
    100   return true;
    101 }
    102 
    103 
    104 template <typename C>
    105 bool ZoneSplayTree<C>::Find(const Key& key, Locator* locator) {
    106   if (is_empty())
    107     return false;
    108   Splay(key);
    109   if (C::Compare(key, root_->key_) == 0) {
    110     locator->bind(root_);
    111     return true;
    112   } else {
    113     return false;
    114   }
    115 }
    116 
    117 
    118 template <typename C>
    119 bool ZoneSplayTree<C>::FindGreatestLessThan(const Key& key,
    120                                             Locator* locator) {
    121   if (is_empty())
    122     return false;
    123   // Splay on the key to move the node with the given key or the last
    124   // node on the search path to the top of the tree.
    125   Splay(key);
    126   // Now the result is either the root node or the greatest node in
    127   // the left subtree.
    128   int cmp = C::Compare(root_->key_, key);
    129   if (cmp <= 0) {
    130     locator->bind(root_);
    131     return true;
    132   } else {
    133     Node* temp = root_;
    134     root_ = root_->left_;
    135     bool result = FindGreatest(locator);
    136     root_ = temp;
    137     return result;
    138   }
    139 }
    140 
    141 
    142 template <typename C>
    143 bool ZoneSplayTree<C>::FindLeastGreaterThan(const Key& key,
    144                                             Locator* locator) {
    145   if (is_empty())
    146     return false;
    147   // Splay on the key to move the node with the given key or the last
    148   // node on the search path to the top of the tree.
    149   Splay(key);
    150   // Now the result is either the root node or the least node in
    151   // the right subtree.
    152   int cmp = C::Compare(root_->key_, key);
    153   if (cmp >= 0) {
    154     locator->bind(root_);
    155     return true;
    156   } else {
    157     Node* temp = root_;
    158     root_ = root_->right_;
    159     bool result = FindLeast(locator);
    160     root_ = temp;
    161     return result;
    162   }
    163 }
    164 
    165 
    166 template <typename C>
    167 bool ZoneSplayTree<C>::FindGreatest(Locator* locator) {
    168   if (is_empty())
    169     return false;
    170   Node* current = root_;
    171   while (current->right_ != NULL)
    172     current = current->right_;
    173   locator->bind(current);
    174   return true;
    175 }
    176 
    177 
    178 template <typename C>
    179 bool ZoneSplayTree<C>::FindLeast(Locator* locator) {
    180   if (is_empty())
    181     return false;
    182   Node* current = root_;
    183   while (current->left_ != NULL)
    184     current = current->left_;
    185   locator->bind(current);
    186   return true;
    187 }
    188 
    189 
    190 template <typename C>
    191 bool ZoneSplayTree<C>::Remove(const Key& key) {
    192   // Bail if the tree is empty
    193   if (is_empty())
    194     return false;
    195   // Splay on the key to move the node with the given key to the top.
    196   Splay(key);
    197   // Bail if the key is not in the tree
    198   if (C::Compare(key, root_->key_) != 0)
    199     return false;
    200   if (root_->left_ == NULL) {
    201     // No left child, so the new tree is just the right child.
    202     root_ = root_->right_;
    203   } else {
    204     // Left child exists.
    205     Node* right = root_->right_;
    206     // Make the original left child the new root.
    207     root_ = root_->left_;
    208     // Splay to make sure that the new root has an empty right child.
    209     Splay(key);
    210     // Insert the original right child as the right child of the new
    211     // root.
    212     root_->right_ = right;
    213   }
    214   return true;
    215 }
    216 
    217 
    218 template <typename C>
    219 void ZoneSplayTree<C>::Splay(const Key& key) {
    220   if (is_empty())
    221     return;
    222   Node dummy_node(C::kNoKey, C::kNoValue);
    223   // Create a dummy node.  The use of the dummy node is a bit
    224   // counter-intuitive: The right child of the dummy node will hold
    225   // the L tree of the algorithm.  The left child of the dummy node
    226   // will hold the R tree of the algorithm.  Using a dummy node, left
    227   // and right will always be nodes and we avoid special cases.
    228   Node* dummy = &dummy_node;
    229   Node* left = dummy;
    230   Node* right = dummy;
    231   Node* current = root_;
    232   while (true) {
    233     int cmp = C::Compare(key, current->key_);
    234     if (cmp < 0) {
    235       if (current->left_ == NULL)
    236         break;
    237       if (C::Compare(key, current->left_->key_) < 0) {
    238         // Rotate right.
    239         Node* temp = current->left_;
    240         current->left_ = temp->right_;
    241         temp->right_ = current;
    242         current = temp;
    243         if (current->left_ == NULL)
    244           break;
    245       }
    246       // Link right.
    247       right->left_ = current;
    248       right = current;
    249       current = current->left_;
    250     } else if (cmp > 0) {
    251       if (current->right_ == NULL)
    252         break;
    253       if (C::Compare(key, current->right_->key_) > 0) {
    254         // Rotate left.
    255         Node* temp = current->right_;
    256         current->right_ = temp->left_;
    257         temp->left_ = current;
    258         current = temp;
    259         if (current->right_ == NULL)
    260           break;
    261       }
    262       // Link left.
    263       left->right_ = current;
    264       left = current;
    265       current = current->right_;
    266     } else {
    267       break;
    268     }
    269   }
    270   // Assemble.
    271   left->right_ = current->left_;
    272   right->left_ = current->right_;
    273   current->left_ = dummy->right_;
    274   current->right_ = dummy->left_;
    275   root_ = current;
    276 }
    277 
    278 
    279 template <typename Config> template <class Callback>
    280 void ZoneSplayTree<Config>::ForEach(Callback* callback) {
    281   // Pre-allocate some space for tiny trees.
    282   ZoneList<Node*> nodes_to_visit(10);
    283   nodes_to_visit.Add(root_);
    284   int pos = 0;
    285   while (pos < nodes_to_visit.length()) {
    286     Node* node = nodes_to_visit[pos++];
    287     if (node == NULL) continue;
    288     callback->Call(node->key(), node->value());
    289     nodes_to_visit.Add(node->left());
    290     nodes_to_visit.Add(node->right());
    291   }
    292 }
    293 
    294 
    295 } }  // namespace v8::internal
    296 
    297 #endif  // V8_ZONE_INL_H_
    298