1c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// Copyright 2011 the V8 project authors. All rights reserved.
23484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// Use of this source code is governed by a BSD-style license that can be
33484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// found in the LICENSE file.
4c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
5196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/store-buffer.h"
6ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
7ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org#include <algorithm>
8ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org
9196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/v8.h"
101e2d50cf3d94ff48285da107b7a9da1ad0fc873dmachenbach@chromium.org
111e2d50cf3d94ff48285da107b7a9da1ad0fc873dmachenbach@chromium.org#include "src/base/atomicops.h"
12196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/counters.h"
13196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/store-buffer-inl.h"
14c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
15c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comnamespace v8 {
16c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comnamespace internal {
17c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
18c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comStoreBuffer::StoreBuffer(Heap* heap)
19c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    : heap_(heap),
20c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      start_(NULL),
21c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      limit_(NULL),
22c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      old_start_(NULL),
23c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      old_limit_(NULL),
24c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      old_top_(NULL),
2564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      old_reserved_limit_(NULL),
26c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      old_buffer_is_sorted_(false),
27c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      old_buffer_is_filtered_(false),
28c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      during_gc_(false),
29c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      store_buffer_rebuilding_enabled_(false),
30c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      callback_(NULL),
31c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      may_move_store_buffer_entries_(true),
32c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      virtual_memory_(NULL),
33b295776b8c02617720d03b6dbcf2f912dfd2c4e7vegorov@chromium.org      hash_set_1_(NULL),
34b295776b8c02617720d03b6dbcf2f912dfd2c4e7vegorov@chromium.org      hash_set_2_(NULL),
35b295776b8c02617720d03b6dbcf2f912dfd2c4e7vegorov@chromium.org      hash_sets_are_empty_(true) {
36c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com}
37c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
38c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
39f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.comvoid StoreBuffer::SetUp() {
40c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  virtual_memory_ = new VirtualMemory(kStoreBufferSize * 3);
41c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  uintptr_t start_as_int =
42c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      reinterpret_cast<uintptr_t>(virtual_memory_->address());
43c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  start_ =
44c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      reinterpret_cast<Address*>(RoundUp(start_as_int, kStoreBufferSize * 2));
4564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  limit_ = start_ + (kStoreBufferSize / kPointerSize);
4664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
4764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  old_virtual_memory_ =
4864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      new VirtualMemory(kOldStoreBufferLength * kPointerSize);
4964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  old_top_ = old_start_ =
5064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org      reinterpret_cast<Address*>(old_virtual_memory_->address());
5164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  // Don't know the alignment requirements of the OS, but it is certainly not
5264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  // less than 0xfff.
5364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  ASSERT((reinterpret_cast<uintptr_t>(old_start_) & 0xfff) == 0);
5464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  int initial_length = static_cast<int>(OS::CommitPageSize() / kPointerSize);
5564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  ASSERT(initial_length > 0);
5664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  ASSERT(initial_length <= kOldStoreBufferLength);
5764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  old_limit_ = old_start_ + initial_length;
5864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  old_reserved_limit_ = old_start_ + kOldStoreBufferLength;
5964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
6064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  CHECK(old_virtual_memory_->Commit(
6164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org            reinterpret_cast<void*>(old_start_),
6264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org            (old_limit_ - old_start_) * kPointerSize,
6364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org            false));
64c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
65c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  ASSERT(reinterpret_cast<Address>(start_) >= virtual_memory_->address());
66c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  ASSERT(reinterpret_cast<Address>(limit_) >= virtual_memory_->address());
67c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  Address* vm_limit = reinterpret_cast<Address*>(
68c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      reinterpret_cast<char*>(virtual_memory_->address()) +
69c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com          virtual_memory_->size());
70c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  ASSERT(start_ <= vm_limit);
71c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  ASSERT(limit_ <= vm_limit);
72c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  USE(vm_limit);
73c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  ASSERT((reinterpret_cast<uintptr_t>(limit_) & kStoreBufferOverflowBit) != 0);
74c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  ASSERT((reinterpret_cast<uintptr_t>(limit_ - 1) & kStoreBufferOverflowBit) ==
75c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com         0);
76c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
7764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  CHECK(virtual_memory_->Commit(reinterpret_cast<Address>(start_),
7864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org                                kStoreBufferSize,
7964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org                                false));  // Not executable.
80c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  heap_->public_set_store_buffer_top(start_);
81c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
82b295776b8c02617720d03b6dbcf2f912dfd2c4e7vegorov@chromium.org  hash_set_1_ = new uintptr_t[kHashSetLength];
83b295776b8c02617720d03b6dbcf2f912dfd2c4e7vegorov@chromium.org  hash_set_2_ = new uintptr_t[kHashSetLength];
84b295776b8c02617720d03b6dbcf2f912dfd2c4e7vegorov@chromium.org  hash_sets_are_empty_ = false;
85c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
86b295776b8c02617720d03b6dbcf2f912dfd2c4e7vegorov@chromium.org  ClearFilteringHashSets();
87c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com}
88c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
89c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
90c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comvoid StoreBuffer::TearDown() {
91c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  delete virtual_memory_;
9264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  delete old_virtual_memory_;
93b295776b8c02617720d03b6dbcf2f912dfd2c4e7vegorov@chromium.org  delete[] hash_set_1_;
94b295776b8c02617720d03b6dbcf2f912dfd2c4e7vegorov@chromium.org  delete[] hash_set_2_;
9564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  old_start_ = old_top_ = old_limit_ = old_reserved_limit_ = NULL;
96c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  start_ = limit_ = NULL;
97c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  heap_->public_set_store_buffer_top(start_);
98c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com}
99c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
100c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
101c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comvoid StoreBuffer::StoreBufferOverflow(Isolate* isolate) {
102c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  isolate->heap()->store_buffer()->Compact();
1031510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org  isolate->counters()->store_buffer_overflows()->Increment();
104c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com}
105c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
106c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
107c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comvoid StoreBuffer::Uniq() {
108c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Remove adjacent duplicates and cells that do not point at new space.
109c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  Address previous = NULL;
110c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  Address* write = old_start_;
111c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  ASSERT(may_move_store_buffer_entries_);
112c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  for (Address* read = old_start_; read < old_top_; read++) {
113c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Address current = *read;
114c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    if (current != previous) {
115c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      if (heap_->InNewSpace(*reinterpret_cast<Object**>(current))) {
116c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        *write++ = current;
117c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      }
118c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    }
119c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    previous = current;
120c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
121c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  old_top_ = write;
122c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com}
123c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
124c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
12541728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.orgbool StoreBuffer::SpaceAvailable(intptr_t space_needed) {
12641728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org  return old_limit_ - old_top_ >= space_needed;
12741728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org}
12841728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org
12941728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org
13064e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.orgvoid StoreBuffer::EnsureSpace(intptr_t space_needed) {
13164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  while (old_limit_ - old_top_ < space_needed &&
13264e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org         old_limit_ < old_reserved_limit_) {
13364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    size_t grow = old_limit_ - old_start_;  // Double size.
13464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    CHECK(old_virtual_memory_->Commit(reinterpret_cast<void*>(old_limit_),
13564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org                                      grow * kPointerSize,
13664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org                                      false));
13764e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org    old_limit_ += grow;
13864e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  }
13964e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
14041728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org  if (SpaceAvailable(space_needed)) return;
14164e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
142c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  if (old_buffer_is_filtered_) return;
143c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  ASSERT(may_move_store_buffer_entries_);
144c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  Compact();
145c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
146c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  old_buffer_is_filtered_ = true;
147c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  bool page_has_scan_on_scavenge_flag = false;
148c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
149c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  PointerChunkIterator it(heap_);
150c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  MemoryChunk* chunk;
151c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  while ((chunk = it.next()) != NULL) {
152639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org    if (chunk->scan_on_scavenge()) {
153639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org      page_has_scan_on_scavenge_flag = true;
154639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org      break;
155639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org    }
156c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
157c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
158c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  if (page_has_scan_on_scavenge_flag) {
159c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Filter(MemoryChunk::SCAN_ON_SCAVENGE);
160c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
161c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
16241728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org  if (SpaceAvailable(space_needed)) return;
163c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
164c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Sample 1 entry in 97 and filter out the pages where we estimate that more
165c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // than 1 in 8 pointers are to new space.
166c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  static const int kSampleFinenesses = 5;
167c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  static const struct Samples {
168c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    int prime_sample_step;
169c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    int threshold;
170c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  } samples[kSampleFinenesses] =  {
171c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    { 97, ((Page::kPageSize / kPointerSize) / 97) / 8 },
172c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    { 23, ((Page::kPageSize / kPointerSize) / 23) / 16 },
173c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    { 7, ((Page::kPageSize / kPointerSize) / 7) / 32 },
174c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    { 3, ((Page::kPageSize / kPointerSize) / 3) / 256 },
175c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    { 1, 0}
176c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  };
1778a00e82ec5c3dbedfd3dcb56996c7df2452da4a5verwaest@chromium.org  for (int i = 0; i < kSampleFinenesses; i++) {
178c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    ExemptPopularPages(samples[i].prime_sample_step, samples[i].threshold);
179c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // As a last resort we mark all pages as being exempt from the store buffer.
1808a00e82ec5c3dbedfd3dcb56996c7df2452da4a5verwaest@chromium.org    ASSERT(i != (kSampleFinenesses - 1) || old_top_ == old_start_);
18141728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org    if (SpaceAvailable(space_needed)) return;
182c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
183c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  UNREACHABLE();
184c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com}
185c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
186c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
187c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// Sample the store buffer to see if some pages are taking up a lot of space
188c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// in the store buffer.
189c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comvoid StoreBuffer::ExemptPopularPages(int prime_sample_step, int threshold) {
190c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  PointerChunkIterator it(heap_);
191c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  MemoryChunk* chunk;
192c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  while ((chunk = it.next()) != NULL) {
193c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    chunk->set_store_buffer_counter(0);
194c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
195c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  bool created_new_scan_on_scavenge_pages = false;
196c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  MemoryChunk* previous_chunk = NULL;
197c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  for (Address* p = old_start_; p < old_top_; p += prime_sample_step) {
198c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Address addr = *p;
199c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    MemoryChunk* containing_chunk = NULL;
200c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    if (previous_chunk != NULL && previous_chunk->Contains(addr)) {
201c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      containing_chunk = previous_chunk;
202c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    } else {
203c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org      containing_chunk = MemoryChunk::FromAnyPointerAddress(heap_, addr);
204c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    }
205c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    int old_counter = containing_chunk->store_buffer_counter();
2069cbaabda8b4daeb06759ace10c926ab55bb69d7bulan@chromium.org    if (old_counter >= threshold) {
207c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      containing_chunk->set_scan_on_scavenge(true);
208c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      created_new_scan_on_scavenge_pages = true;
209c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    }
210c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    containing_chunk->set_store_buffer_counter(old_counter + 1);
211c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    previous_chunk = containing_chunk;
212c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
213c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  if (created_new_scan_on_scavenge_pages) {
214c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Filter(MemoryChunk::SCAN_ON_SCAVENGE);
215c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
216c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  old_buffer_is_filtered_ = true;
217c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com}
218c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
219c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
220c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comvoid StoreBuffer::Filter(int flag) {
221c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  Address* new_top = old_start_;
222c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  MemoryChunk* previous_chunk = NULL;
223c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  for (Address* p = old_start_; p < old_top_; p++) {
224c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Address addr = *p;
225c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    MemoryChunk* containing_chunk = NULL;
226c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    if (previous_chunk != NULL && previous_chunk->Contains(addr)) {
227c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      containing_chunk = previous_chunk;
228c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    } else {
229c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org      containing_chunk = MemoryChunk::FromAnyPointerAddress(heap_, addr);
230c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      previous_chunk = containing_chunk;
231c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    }
232c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    if (!containing_chunk->IsFlagSet(flag)) {
233c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      *new_top++ = addr;
234c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    }
235c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
236c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  old_top_ = new_top;
237b295776b8c02617720d03b6dbcf2f912dfd2c4e7vegorov@chromium.org
238b295776b8c02617720d03b6dbcf2f912dfd2c4e7vegorov@chromium.org  // Filtering hash sets are inconsistent with the store buffer after this
239b295776b8c02617720d03b6dbcf2f912dfd2c4e7vegorov@chromium.org  // operation.
240b295776b8c02617720d03b6dbcf2f912dfd2c4e7vegorov@chromium.org  ClearFilteringHashSets();
241c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com}
242c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
243c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
244c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comvoid StoreBuffer::SortUniq() {
245c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  Compact();
246c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  if (old_buffer_is_sorted_) return;
247ca29dd85fa02449d17188f5a6ff9a7cdf2ad9680danno@chromium.org  std::sort(old_start_, old_top_);
248c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  Uniq();
249c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
250c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  old_buffer_is_sorted_ = true;
251b295776b8c02617720d03b6dbcf2f912dfd2c4e7vegorov@chromium.org
252b295776b8c02617720d03b6dbcf2f912dfd2c4e7vegorov@chromium.org  // Filtering hash sets are inconsistent with the store buffer after this
253b295776b8c02617720d03b6dbcf2f912dfd2c4e7vegorov@chromium.org  // operation.
254b295776b8c02617720d03b6dbcf2f912dfd2c4e7vegorov@chromium.org  ClearFilteringHashSets();
255c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com}
256c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
257c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
258c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.combool StoreBuffer::PrepareForIteration() {
259c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  Compact();
260c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  PointerChunkIterator it(heap_);
261c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  MemoryChunk* chunk;
262c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  bool page_has_scan_on_scavenge_flag = false;
263c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  while ((chunk = it.next()) != NULL) {
264639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org    if (chunk->scan_on_scavenge()) {
265639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org      page_has_scan_on_scavenge_flag = true;
266639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org      break;
267639bac0c5319f96e1bbe3399fb7f7f37344928bddslomov@chromium.org    }
268c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
269c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
270c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  if (page_has_scan_on_scavenge_flag) {
271c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Filter(MemoryChunk::SCAN_ON_SCAVENGE);
272c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
273b295776b8c02617720d03b6dbcf2f912dfd2c4e7vegorov@chromium.org
274b295776b8c02617720d03b6dbcf2f912dfd2c4e7vegorov@chromium.org  // Filtering hash sets are inconsistent with the store buffer after
275b295776b8c02617720d03b6dbcf2f912dfd2c4e7vegorov@chromium.org  // iteration.
276b295776b8c02617720d03b6dbcf2f912dfd2c4e7vegorov@chromium.org  ClearFilteringHashSets();
277b295776b8c02617720d03b6dbcf2f912dfd2c4e7vegorov@chromium.org
278c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  return page_has_scan_on_scavenge_flag;
279c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com}
280c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
281c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
282c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com#ifdef DEBUG
283c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comvoid StoreBuffer::Clean() {
284b295776b8c02617720d03b6dbcf2f912dfd2c4e7vegorov@chromium.org  ClearFilteringHashSets();
285c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  Uniq();  // Also removes things that no longer point to new space.
28641728483f231e098a8dd85f109b5a30e6ccc3c39danno@chromium.org  EnsureSpace(kStoreBufferSize / 2);
287c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com}
288c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
289c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
290c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comstatic Address* in_store_buffer_1_element_cache = NULL;
291c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
292c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
293c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.combool StoreBuffer::CellIsInStoreBuffer(Address cell_address) {
294c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  if (!FLAG_enable_slow_asserts) return true;
295c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  if (in_store_buffer_1_element_cache != NULL &&
296c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      *in_store_buffer_1_element_cache == cell_address) {
297c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    return true;
298c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
299c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  Address* top = reinterpret_cast<Address*>(heap_->store_buffer_top());
300c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  for (Address* current = top - 1; current >= start_; current--) {
301c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    if (*current == cell_address) {
302c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      in_store_buffer_1_element_cache = current;
303c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      return true;
304c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    }
305c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
306c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  for (Address* current = old_top_ - 1; current >= old_start_; current--) {
307c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    if (*current == cell_address) {
308c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      in_store_buffer_1_element_cache = current;
309c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      return true;
310c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    }
311c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
312c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  return false;
313c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com}
314c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com#endif
315c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
316c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
317b295776b8c02617720d03b6dbcf2f912dfd2c4e7vegorov@chromium.orgvoid StoreBuffer::ClearFilteringHashSets() {
318b295776b8c02617720d03b6dbcf2f912dfd2c4e7vegorov@chromium.org  if (!hash_sets_are_empty_) {
319b295776b8c02617720d03b6dbcf2f912dfd2c4e7vegorov@chromium.org    memset(reinterpret_cast<void*>(hash_set_1_),
320b295776b8c02617720d03b6dbcf2f912dfd2c4e7vegorov@chromium.org           0,
321b295776b8c02617720d03b6dbcf2f912dfd2c4e7vegorov@chromium.org           sizeof(uintptr_t) * kHashSetLength);
322b295776b8c02617720d03b6dbcf2f912dfd2c4e7vegorov@chromium.org    memset(reinterpret_cast<void*>(hash_set_2_),
323b295776b8c02617720d03b6dbcf2f912dfd2c4e7vegorov@chromium.org           0,
324b295776b8c02617720d03b6dbcf2f912dfd2c4e7vegorov@chromium.org           sizeof(uintptr_t) * kHashSetLength);
325b295776b8c02617720d03b6dbcf2f912dfd2c4e7vegorov@chromium.org    hash_sets_are_empty_ = true;
326b295776b8c02617720d03b6dbcf2f912dfd2c4e7vegorov@chromium.org  }
327c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com}
328c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
329c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
330c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comvoid StoreBuffer::GCPrologue() {
331b295776b8c02617720d03b6dbcf2f912dfd2c4e7vegorov@chromium.org  ClearFilteringHashSets();
332c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  during_gc_ = true;
333c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com}
334c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
335c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
336c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org#ifdef VERIFY_HEAP
337c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comvoid StoreBuffer::VerifyPointers(LargeObjectSpace* space) {
338c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  LargeObjectIterator it(space);
339c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  for (HeapObject* object = it.Next(); object != NULL; object = it.Next()) {
340c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    if (object->IsFixedArray()) {
341c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      Address slot_address = object->address();
342c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      Address end = object->address() + object->Size();
343c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
344c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      while (slot_address < end) {
345c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        HeapObject** slot = reinterpret_cast<HeapObject**>(slot_address);
346c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        // When we are not in GC the Heap::InNewSpace() predicate
347c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        // checks that pointers which satisfy predicate point into
348c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        // the active semispace.
3499e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org        Object* object = reinterpret_cast<Object*>(
3501e2d50cf3d94ff48285da107b7a9da1ad0fc873dmachenbach@chromium.org            base::NoBarrier_Load(reinterpret_cast<base::AtomicWord*>(slot)));
3519e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org        heap_->InNewSpace(object);
352c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        slot_address += kPointerSize;
353c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      }
354c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    }
355c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
356c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com}
357c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com#endif
358c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
359c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
360c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comvoid StoreBuffer::Verify() {
361c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org#ifdef VERIFY_HEAP
362c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  VerifyPointers(heap_->lo_space());
363c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com#endif
364c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com}
365c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
366c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
367c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comvoid StoreBuffer::GCEpilogue() {
368c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  during_gc_ = false;
369c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org#ifdef VERIFY_HEAP
370394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  if (FLAG_verify_heap) {
371394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    Verify();
372394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  }
373c859c4f83f6ec3e010213dbbe447cc1f927d01c5svenpanne@chromium.org#endif
374c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com}
375c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
376c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
377c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comvoid StoreBuffer::FindPointersToNewSpaceInRegion(
378169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org    Address start,
379169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org    Address end,
380169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org    ObjectSlotCallback slot_callback,
381169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org    bool clear_maps) {
382c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  for (Address slot_address = start;
383c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com       slot_address < end;
384c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com       slot_address += kPointerSize) {
385c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Object** slot = reinterpret_cast<Object**>(slot_address);
3869e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org    Object* object = reinterpret_cast<Object*>(
3871e2d50cf3d94ff48285da107b7a9da1ad0fc873dmachenbach@chromium.org        base::NoBarrier_Load(reinterpret_cast<base::AtomicWord*>(slot)));
3889e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org    if (heap_->InNewSpace(object)) {
3899e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org      HeapObject* heap_object = reinterpret_cast<HeapObject*>(object);
3909e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org      ASSERT(heap_object->IsHeapObject());
391169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org      // The new space object was not promoted if it still contains a map
392169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org      // pointer. Clear the map field now lazily.
3939e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org      if (clear_maps) ClearDeadObject(heap_object);
3949e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org      slot_callback(reinterpret_cast<HeapObject**>(slot), heap_object);
3959e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org      object = reinterpret_cast<Object*>(
3961e2d50cf3d94ff48285da107b7a9da1ad0fc873dmachenbach@chromium.org          base::NoBarrier_Load(reinterpret_cast<base::AtomicWord*>(slot)));
3979e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org      if (heap_->InNewSpace(object)) {
398c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        EnterDirectlyIntoStoreBuffer(slot_address);
399c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      }
400c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    }
401c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
402c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com}
403c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
404c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
405c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// Compute start address of the first map following given addr.
406c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comstatic inline Address MapStartAlign(Address addr) {
407ab30bb83bf3dae0053739c57b1db9ad13c1f9e3ayangguo@chromium.org  Address page = Page::FromAddress(addr)->area_start();
408c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  return page + (((addr - page) + (Map::kSize - 1)) / Map::kSize * Map::kSize);
409c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com}
410c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
411c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
412c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// Compute end address of the first map preceding given addr.
413c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comstatic inline Address MapEndAlign(Address addr) {
414ab30bb83bf3dae0053739c57b1db9ad13c1f9e3ayangguo@chromium.org  Address page = Page::FromAllocationTop(addr)->area_start();
415c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  return page + ((addr - page) / Map::kSize * Map::kSize);
416c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com}
417c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
418c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
419c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comvoid StoreBuffer::FindPointersToNewSpaceInMaps(
420c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Address start,
421c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Address end,
422169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org    ObjectSlotCallback slot_callback,
423169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org    bool clear_maps) {
424c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  ASSERT(MapStartAlign(start) == start);
425c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  ASSERT(MapEndAlign(end) == end);
426c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
427c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  Address map_address = start;
428c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  while (map_address < end) {
429c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    ASSERT(!heap_->InNewSpace(Memory::Object_at(map_address)));
430c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    ASSERT(Memory::Object_at(map_address)->IsMap());
431c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
432c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Address pointer_fields_start = map_address + Map::kPointerFieldsBeginOffset;
433c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Address pointer_fields_end = map_address + Map::kPointerFieldsEndOffset;
434c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
435c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    FindPointersToNewSpaceInRegion(pointer_fields_start,
436c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                                   pointer_fields_end,
437169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org                                   slot_callback,
438169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org                                   clear_maps);
439c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    map_address += Map::kSize;
440c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
441c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com}
442c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
443c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
444c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comvoid StoreBuffer::FindPointersToNewSpaceInMapsRegion(
445c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Address start,
446c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Address end,
447169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org    ObjectSlotCallback slot_callback,
448169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org    bool clear_maps) {
449c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  Address map_aligned_start = MapStartAlign(start);
450c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  Address map_aligned_end   = MapEndAlign(end);
451c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
452c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  ASSERT(map_aligned_start == start);
453e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org  ASSERT(map_aligned_start <= map_aligned_end && map_aligned_end <= end);
454c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
455c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  FindPointersToNewSpaceInMaps(map_aligned_start,
456c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com                               map_aligned_end,
457169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org                               slot_callback,
458169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org                               clear_maps);
459c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com}
460c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
461c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
462c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comvoid StoreBuffer::IteratePointersInStoreBuffer(
463169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org    ObjectSlotCallback slot_callback,
464169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org    bool clear_maps) {
465c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  Address* limit = old_top_;
466c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  old_top_ = old_start_;
467c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  {
468c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    DontMoveStoreBufferEntriesScope scope(this);
469c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    for (Address* current = old_start_; current < limit; current++) {
470c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com#ifdef DEBUG
471c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      Address* saved_top = old_top_;
472c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com#endif
473c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      Object** slot = reinterpret_cast<Object**>(*current);
4749e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org      Object* object = reinterpret_cast<Object*>(
4751e2d50cf3d94ff48285da107b7a9da1ad0fc873dmachenbach@chromium.org          base::NoBarrier_Load(reinterpret_cast<base::AtomicWord*>(slot)));
476c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      if (heap_->InFromSpace(object)) {
477c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        HeapObject* heap_object = reinterpret_cast<HeapObject*>(object);
478169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org        // The new space object was not promoted if it still contains a map
479169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org        // pointer. Clear the map field now lazily.
480169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org        if (clear_maps) ClearDeadObject(heap_object);
481c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        slot_callback(reinterpret_cast<HeapObject**>(slot), heap_object);
4829e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org        object = reinterpret_cast<Object*>(
4831e2d50cf3d94ff48285da107b7a9da1ad0fc873dmachenbach@chromium.org            base::NoBarrier_Load(reinterpret_cast<base::AtomicWord*>(slot)));
4849e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org        if (heap_->InNewSpace(object)) {
485c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com          EnterDirectlyIntoStoreBuffer(reinterpret_cast<Address>(slot));
486c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        }
487c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      }
488c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      ASSERT(old_top_ == saved_top + 1 || old_top_ == saved_top);
489c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    }
490c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
491c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com}
492c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
493c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
494c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comvoid StoreBuffer::IteratePointersToNewSpace(ObjectSlotCallback slot_callback) {
495169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  IteratePointersToNewSpace(slot_callback, false);
496169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org}
497169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org
498169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org
499169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.orgvoid StoreBuffer::IteratePointersToNewSpaceAndClearMaps(
500169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org    ObjectSlotCallback slot_callback) {
501169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  IteratePointersToNewSpace(slot_callback, true);
502169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org}
503169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org
504169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org
505169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.orgvoid StoreBuffer::IteratePointersToNewSpace(ObjectSlotCallback slot_callback,
506169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org                                            bool clear_maps) {
507c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // We do not sort or remove duplicated entries from the store buffer because
508c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // we expect that callback will rebuild the store buffer thus removing
509c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // all duplicates and pointers to old space.
510c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  bool some_pages_to_scan = PrepareForIteration();
511c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
512c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // TODO(gc): we want to skip slots on evacuation candidates
513c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // but we can't simply figure that out from slot address
514c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // because slot can belong to a large object.
515169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  IteratePointersInStoreBuffer(slot_callback, clear_maps);
516c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
517c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // We are done scanning all the pointers that were in the store buffer, but
518c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // there may be some pages marked scan_on_scavenge that have pointers to new
519c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // space that are not in the store buffer.  We must scan them now.  As we
520c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // scan, the surviving pointers to new space will be added to the store
521c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // buffer.  If there are still a lot of pointers to new space then we will
522c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // keep the scan_on_scavenge flag on the page and discard the pointers that
523c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // were added to the store buffer.  If there are not many pointers to new
524c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // space left on the page we will keep the pointers in the store buffer and
525c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // remove the flag from the page.
526c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  if (some_pages_to_scan) {
527c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    if (callback_ != NULL) {
528c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      (*callback_)(heap_, NULL, kStoreBufferStartScanningPagesEvent);
529c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    }
530c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    PointerChunkIterator it(heap_);
531c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    MemoryChunk* chunk;
532c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    while ((chunk = it.next()) != NULL) {
533c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      if (chunk->scan_on_scavenge()) {
534c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        chunk->set_scan_on_scavenge(false);
535c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        if (callback_ != NULL) {
536c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com          (*callback_)(heap_, chunk, kStoreBufferScanningPageEvent);
537c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        }
538c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        if (chunk->owner() == heap_->lo_space()) {
539c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com          LargePage* large_page = reinterpret_cast<LargePage*>(chunk);
540c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com          HeapObject* array = large_page->GetObject();
541c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com          ASSERT(array->IsFixedArray());
542c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com          Address start = array->address();
543c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com          Address end = start + array->Size();
544169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org          FindPointersToNewSpaceInRegion(start, end, slot_callback, clear_maps);
545c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        } else {
546c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com          Page* page = reinterpret_cast<Page*>(chunk);
547c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com          PagedSpace* owner = reinterpret_cast<PagedSpace*>(page->owner());
548aa107b240dc43417fae8469b5c1b0f1ec9f98400machenbach@chromium.org          Address start = page->area_start();
549aa107b240dc43417fae8469b5c1b0f1ec9f98400machenbach@chromium.org          Address end = page->area_end();
550aa107b240dc43417fae8469b5c1b0f1ec9f98400machenbach@chromium.org          if (owner == heap_->map_space()) {
551aa107b240dc43417fae8469b5c1b0f1ec9f98400machenbach@chromium.org            FindPointersToNewSpaceInMapsRegion(
552aa107b240dc43417fae8469b5c1b0f1ec9f98400machenbach@chromium.org                start, end, slot_callback, clear_maps);
553aa107b240dc43417fae8469b5c1b0f1ec9f98400machenbach@chromium.org          } else {
554aa107b240dc43417fae8469b5c1b0f1ec9f98400machenbach@chromium.org            FindPointersToNewSpaceInRegion(
555aa107b240dc43417fae8469b5c1b0f1ec9f98400machenbach@chromium.org                start, end, slot_callback, clear_maps);
556aa107b240dc43417fae8469b5c1b0f1ec9f98400machenbach@chromium.org          }
557c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        }
558c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      }
559c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    }
560c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    if (callback_ != NULL) {
561c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      (*callback_)(heap_, NULL, kStoreBufferScanningPageEvent);
562c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    }
563c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
564c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com}
565c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
566c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
567c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comvoid StoreBuffer::Compact() {
568c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  Address* top = reinterpret_cast<Address*>(heap_->store_buffer_top());
569c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
570c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  if (top == start_) return;
571c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
572c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // There's no check of the limit in the loop below so we check here for
573c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // the worst case (compaction doesn't eliminate any pointers).
574c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  ASSERT(top <= limit_);
575c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  heap_->public_set_store_buffer_top(start_);
57664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  EnsureSpace(top - start_);
577c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  ASSERT(may_move_store_buffer_entries_);
578c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Goes through the addresses in the store buffer attempting to remove
579c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // duplicates.  In the interest of speed this is a lossy operation.  Some
580b295776b8c02617720d03b6dbcf2f912dfd2c4e7vegorov@chromium.org  // duplicates will remain.  We have two hash sets with different hash
581c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // functions to reduce the number of unnecessary clashes.
582b295776b8c02617720d03b6dbcf2f912dfd2c4e7vegorov@chromium.org  hash_sets_are_empty_ = false;  // Hash sets are in use.
583c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  for (Address* current = start_; current < top; current++) {
584c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    ASSERT(!heap_->cell_space()->Contains(*current));
585c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    ASSERT(!heap_->code_space()->Contains(*current));
586c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    ASSERT(!heap_->old_data_space()->Contains(*current));
587c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    uintptr_t int_addr = reinterpret_cast<uintptr_t>(*current);
588c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Shift out the last bits including any tags.
589c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    int_addr >>= kPointerSizeLog2;
590a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    // The upper part of an address is basically random because of ASLR and OS
591a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    // non-determinism, so we use only the bits within a page for hashing to
592a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    // make v8's behavior (more) deterministic.
593a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    uintptr_t hash_addr =
594a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org        int_addr & (Page::kPageAlignmentMask >> kPointerSizeLog2);
595a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    int hash1 = ((hash_addr ^ (hash_addr >> kHashSetLengthLog2)) &
596a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org                 (kHashSetLength - 1));
597b295776b8c02617720d03b6dbcf2f912dfd2c4e7vegorov@chromium.org    if (hash_set_1_[hash1] == int_addr) continue;
598a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    uintptr_t hash2 = (hash_addr - (hash_addr >> kHashSetLengthLog2));
599b295776b8c02617720d03b6dbcf2f912dfd2c4e7vegorov@chromium.org    hash2 ^= hash2 >> (kHashSetLengthLog2 * 2);
600fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org    hash2 &= (kHashSetLength - 1);
601b295776b8c02617720d03b6dbcf2f912dfd2c4e7vegorov@chromium.org    if (hash_set_2_[hash2] == int_addr) continue;
602b295776b8c02617720d03b6dbcf2f912dfd2c4e7vegorov@chromium.org    if (hash_set_1_[hash1] == 0) {
603b295776b8c02617720d03b6dbcf2f912dfd2c4e7vegorov@chromium.org      hash_set_1_[hash1] = int_addr;
604b295776b8c02617720d03b6dbcf2f912dfd2c4e7vegorov@chromium.org    } else if (hash_set_2_[hash2] == 0) {
605b295776b8c02617720d03b6dbcf2f912dfd2c4e7vegorov@chromium.org      hash_set_2_[hash2] = int_addr;
606c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    } else {
607c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // Rather than slowing down we just throw away some entries.  This will
608c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      // cause some duplicates to remain undetected.
609b295776b8c02617720d03b6dbcf2f912dfd2c4e7vegorov@chromium.org      hash_set_1_[hash1] = int_addr;
610b295776b8c02617720d03b6dbcf2f912dfd2c4e7vegorov@chromium.org      hash_set_2_[hash2] = 0;
611c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    }
612c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    old_buffer_is_sorted_ = false;
613c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    old_buffer_is_filtered_ = false;
614c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    *old_top_++ = reinterpret_cast<Address>(int_addr << kPointerSizeLog2);
615c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    ASSERT(old_top_ <= old_limit_);
616c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
617c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  heap_->isolate()->counters()->store_buffer_compactions()->Increment();
618c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com}
619c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
620c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com} }  // namespace v8::internal
621