16ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Copyright 2010 the V8 project authors. All rights reserved.
2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file.
46ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
56ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#ifndef V8_SPLAY_TREE_INL_H_
66ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#define V8_SPLAY_TREE_INL_H_
76ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/splay-tree.h"
96ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
106ded16be15dd865a9b21ea304d5273c8be299c87Steve Blocknamespace v8 {
116ded16be15dd865a9b21ea304d5273c8be299c87Steve Blocknamespace internal {
126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
146ded16be15dd865a9b21ea304d5273c8be299c87Steve Blocktemplate<typename Config, class Allocator>
156ded16be15dd865a9b21ea304d5273c8be299c87Steve BlockSplayTree<Config, Allocator>::~SplayTree() {
166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  NodeDeleter deleter;
176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ForEachNode(&deleter);
186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
216ded16be15dd865a9b21ea304d5273c8be299c87Steve Blocktemplate<typename Config, class Allocator>
22b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool SplayTree<Config, Allocator>::Insert(const Key& key,
23b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                          Locator* locator) {
246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (is_empty()) {
256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // If the tree is empty, insert the new node.
26b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    root_ = new(allocator_) Node(key, Config::NoValue());
276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Splay on the key to move the last node on the search path
296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // for the key to the root of the tree.
306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Splay(key);
316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Ignore repeated insertions with the same key.
326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int cmp = Config::Compare(key, root_->key_);
336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (cmp == 0) {
346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      locator->bind(root_);
356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return false;
366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Insert the new node.
38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Node* node = new(allocator_) Node(key, Config::NoValue());
396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    InsertInternal(cmp, node);
406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  locator->bind(root_);
426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return true;
436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
466ded16be15dd865a9b21ea304d5273c8be299c87Steve Blocktemplate<typename Config, class Allocator>
476ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid SplayTree<Config, Allocator>::InsertInternal(int cmp, Node* node) {
486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (cmp > 0) {
496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    node->left_ = root_;
506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    node->right_ = root_->right_;
516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    root_->right_ = NULL;
526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    node->right_ = root_;
546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    node->left_ = root_->left_;
556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    root_->left_ = NULL;
566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  root_ = node;
586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
616ded16be15dd865a9b21ea304d5273c8be299c87Steve Blocktemplate<typename Config, class Allocator>
626ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockbool SplayTree<Config, Allocator>::FindInternal(const Key& key) {
636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (is_empty())
646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return false;
656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Splay(key);
666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return Config::Compare(key, root_->key_) == 0;
676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
706ded16be15dd865a9b21ea304d5273c8be299c87Steve Blocktemplate<typename Config, class Allocator>
71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool SplayTree<Config, Allocator>::Contains(const Key& key) {
72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return FindInternal(key);
73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate<typename Config, class Allocator>
776ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockbool SplayTree<Config, Allocator>::Find(const Key& key, Locator* locator) {
786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (FindInternal(key)) {
796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    locator->bind(root_);
806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return true;
816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return false;
836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
876ded16be15dd865a9b21ea304d5273c8be299c87Steve Blocktemplate<typename Config, class Allocator>
886ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockbool SplayTree<Config, Allocator>::FindGreatestLessThan(const Key& key,
896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                                        Locator* locator) {
906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (is_empty())
916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return false;
926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Splay on the key to move the node with the given key or the last
936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // node on the search path to the top of the tree.
946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Splay(key);
956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Now the result is either the root node or the greatest node in
966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // the left subtree.
976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int cmp = Config::Compare(root_->key_, key);
986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (cmp <= 0) {
996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    locator->bind(root_);
1006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return true;
1016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
1026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Node* temp = root_;
1036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    root_ = root_->left_;
1046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    bool result = FindGreatest(locator);
1056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    root_ = temp;
1066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return result;
1076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
1086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
1096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1116ded16be15dd865a9b21ea304d5273c8be299c87Steve Blocktemplate<typename Config, class Allocator>
1126ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockbool SplayTree<Config, Allocator>::FindLeastGreaterThan(const Key& key,
1136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                                        Locator* locator) {
1146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (is_empty())
1156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return false;
1166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Splay on the key to move the node with the given key or the last
1176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // node on the search path to the top of the tree.
1186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Splay(key);
1196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Now the result is either the root node or the least node in
1206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // the right subtree.
1216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int cmp = Config::Compare(root_->key_, key);
1226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (cmp >= 0) {
1236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    locator->bind(root_);
1246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return true;
1256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
1266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Node* temp = root_;
1276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    root_ = root_->right_;
1286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    bool result = FindLeast(locator);
1296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    root_ = temp;
1306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return result;
1316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
1326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
1336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1356ded16be15dd865a9b21ea304d5273c8be299c87Steve Blocktemplate<typename Config, class Allocator>
1366ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockbool SplayTree<Config, Allocator>::FindGreatest(Locator* locator) {
1376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (is_empty())
1386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return false;
1396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Node* current = root_;
1406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  while (current->right_ != NULL)
1416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    current = current->right_;
1426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  locator->bind(current);
1436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return true;
1446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
1456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1476ded16be15dd865a9b21ea304d5273c8be299c87Steve Blocktemplate<typename Config, class Allocator>
1486ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockbool SplayTree<Config, Allocator>::FindLeast(Locator* locator) {
1496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (is_empty())
1506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return false;
1516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Node* current = root_;
1526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  while (current->left_ != NULL)
1536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    current = current->left_;
1546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  locator->bind(current);
1556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return true;
1566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
1576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1596ded16be15dd865a9b21ea304d5273c8be299c87Steve Blocktemplate<typename Config, class Allocator>
1606ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockbool SplayTree<Config, Allocator>::Move(const Key& old_key,
1616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                        const Key& new_key) {
1626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (!FindInternal(old_key))
1636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return false;
1646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Node* node_to_move = root_;
1656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  RemoveRootNode(old_key);
1666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Splay(new_key);
1676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int cmp = Config::Compare(new_key, root_->key_);
1686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (cmp == 0) {
1696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // A node with the target key already exists.
1706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    delete node_to_move;
1716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return false;
1726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
1736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  node_to_move->key_ = new_key;
1746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  InsertInternal(cmp, node_to_move);
1756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return true;
1766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
1776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1796ded16be15dd865a9b21ea304d5273c8be299c87Steve Blocktemplate<typename Config, class Allocator>
1806ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockbool SplayTree<Config, Allocator>::Remove(const Key& key) {
1816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (!FindInternal(key))
1826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return false;
1836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Node* node_to_remove = root_;
1846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  RemoveRootNode(key);
1856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  delete node_to_remove;
1866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return true;
1876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
1886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1906ded16be15dd865a9b21ea304d5273c8be299c87Steve Blocktemplate<typename Config, class Allocator>
1916ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid SplayTree<Config, Allocator>::RemoveRootNode(const Key& key) {
1926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (root_->left_ == NULL) {
1936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // No left child, so the new tree is just the right child.
1946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    root_ = root_->right_;
1956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  } else {
1966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Left child exists.
1976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Node* right = root_->right_;
1986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Make the original left child the new root.
1996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    root_ = root_->left_;
2006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Splay to make sure that the new root has an empty right child.
2016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Splay(key);
2026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // Insert the original right child as the right child of the new
2036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    // root.
2046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    root_->right_ = right;
2056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
2066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
2076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2096ded16be15dd865a9b21ea304d5273c8be299c87Steve Blocktemplate<typename Config, class Allocator>
2106ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid SplayTree<Config, Allocator>::Splay(const Key& key) {
2116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (is_empty())
2126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return;
2133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Node dummy_node(Config::kNoKey, Config::NoValue());
2146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Create a dummy node.  The use of the dummy node is a bit
2156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // counter-intuitive: The right child of the dummy node will hold
2166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // the L tree of the algorithm.  The left child of the dummy node
2176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // will hold the R tree of the algorithm.  Using a dummy node, left
2186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // and right will always be nodes and we avoid special cases.
2196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Node* dummy = &dummy_node;
2206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Node* left = dummy;
2216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Node* right = dummy;
2226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Node* current = root_;
2236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  while (true) {
2246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    int cmp = Config::Compare(key, current->key_);
2256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (cmp < 0) {
2266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (current->left_ == NULL)
2276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        break;
2286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (Config::Compare(key, current->left_->key_) < 0) {
2296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        // Rotate right.
2306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        Node* temp = current->left_;
2316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        current->left_ = temp->right_;
2326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        temp->right_ = current;
2336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        current = temp;
2346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        if (current->left_ == NULL)
2356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          break;
2366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
2376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // Link right.
2386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      right->left_ = current;
2396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      right = current;
2406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      current = current->left_;
2416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else if (cmp > 0) {
2426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (current->right_ == NULL)
2436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        break;
2446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (Config::Compare(key, current->right_->key_) > 0) {
2456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        // Rotate left.
2466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        Node* temp = current->right_;
2476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        current->right_ = temp->left_;
2486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        temp->left_ = current;
2496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        current = temp;
2506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        if (current->right_ == NULL)
2516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          break;
2526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
2536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      // Link left.
2546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      left->right_ = current;
2556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      left = current;
2566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      current = current->right_;
2576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    } else {
2586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      break;
2596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
2606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
2616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Assemble.
2626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  left->right_ = current->left_;
2636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  right->left_ = current->right_;
2646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  current->left_ = dummy->right_;
2656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  current->right_ = dummy->left_;
2666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  root_ = current;
2676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
2686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2706ded16be15dd865a9b21ea304d5273c8be299c87Steve Blocktemplate <typename Config, class Allocator> template <class Callback>
2716ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid SplayTree<Config, Allocator>::ForEach(Callback* callback) {
2726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  NodeToPairAdaptor<Callback> callback_adaptor(callback);
2736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ForEachNode(&callback_adaptor);
2746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
2756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2776ded16be15dd865a9b21ea304d5273c8be299c87Steve Blocktemplate <typename Config, class Allocator> template <class Callback>
2786ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid SplayTree<Config, Allocator>::ForEachNode(Callback* callback) {
279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (root_ == NULL) return;
2806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Pre-allocate some space for tiny trees.
281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  List<Node*, Allocator> nodes_to_visit(10, allocator_);
282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  nodes_to_visit.Add(root_, allocator_);
2836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int pos = 0;
2846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  while (pos < nodes_to_visit.length()) {
2856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Node* node = nodes_to_visit[pos++];
286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (node->left() != NULL) nodes_to_visit.Add(node->left(), allocator_);
287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (node->right() != NULL) nodes_to_visit.Add(node->right(), allocator_);
2886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    callback->Call(node);
2896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
2906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
2916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
293014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace internal
294014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace v8
2956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#endif  // V8_SPLAY_TREE_INL_H_
297