13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2011 the V8 project authors. All rights reserved.
23ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Redistribution and use in source and binary forms, with or without
33ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// modification, are permitted provided that the following conditions are
43ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// met:
53ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//
63ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//     * Redistributions of source code must retain the above copyright
73ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//       notice, this list of conditions and the following disclaimer.
83ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//     * Redistributions in binary form must reproduce the above
93ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//       copyright notice, this list of conditions and the following
103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//       disclaimer in the documentation and/or other materials provided
113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//       with the distribution.
123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//     * Neither the name of Google Inc. nor the names of its
133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//       contributors may be used to endorse or promote products derived
143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//       from this software without specific prior written permission.
153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//
163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#include "v8.h"
293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#include "store-buffer.h"
313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#include "store-buffer-inl.h"
323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#include "v8-counters.h"
333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochnamespace v8 {
353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochnamespace internal {
363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
373ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochStoreBuffer::StoreBuffer(Heap* heap)
383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    : heap_(heap),
393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      start_(NULL),
403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      limit_(NULL),
413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      old_start_(NULL),
423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      old_limit_(NULL),
433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      old_top_(NULL),
443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      old_reserved_limit_(NULL),
453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      old_buffer_is_sorted_(false),
463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      old_buffer_is_filtered_(false),
473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      during_gc_(false),
483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      store_buffer_rebuilding_enabled_(false),
493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      callback_(NULL),
503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      may_move_store_buffer_entries_(true),
513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      virtual_memory_(NULL),
523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      hash_set_1_(NULL),
533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      hash_set_2_(NULL),
543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      hash_sets_are_empty_(true) {
553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StoreBuffer::SetUp() {
593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  virtual_memory_ = new VirtualMemory(kStoreBufferSize * 3);
603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  uintptr_t start_as_int =
613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      reinterpret_cast<uintptr_t>(virtual_memory_->address());
623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  start_ =
633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      reinterpret_cast<Address*>(RoundUp(start_as_int, kStoreBufferSize * 2));
643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  limit_ = start_ + (kStoreBufferSize / kPointerSize);
653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  old_virtual_memory_ =
673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      new VirtualMemory(kOldStoreBufferLength * kPointerSize);
683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  old_top_ = old_start_ =
693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      reinterpret_cast<Address*>(old_virtual_memory_->address());
703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Don't know the alignment requirements of the OS, but it is certainly not
713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // less than 0xfff.
723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT((reinterpret_cast<uintptr_t>(old_start_) & 0xfff) == 0);
733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int initial_length = static_cast<int>(OS::CommitPageSize() / kPointerSize);
743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(initial_length > 0);
753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(initial_length <= kOldStoreBufferLength);
763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  old_limit_ = old_start_ + initial_length;
773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  old_reserved_limit_ = old_start_ + kOldStoreBufferLength;
783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK(old_virtual_memory_->Commit(
803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            reinterpret_cast<void*>(old_start_),
813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            (old_limit_ - old_start_) * kPointerSize,
823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            false));
833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(reinterpret_cast<Address>(start_) >= virtual_memory_->address());
853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(reinterpret_cast<Address>(limit_) >= virtual_memory_->address());
863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Address* vm_limit = reinterpret_cast<Address*>(
873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      reinterpret_cast<char*>(virtual_memory_->address()) +
883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          virtual_memory_->size());
893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(start_ <= vm_limit);
903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(limit_ <= vm_limit);
913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  USE(vm_limit);
923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT((reinterpret_cast<uintptr_t>(limit_) & kStoreBufferOverflowBit) != 0);
933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT((reinterpret_cast<uintptr_t>(limit_ - 1) & kStoreBufferOverflowBit) ==
943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch         0);
953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CHECK(virtual_memory_->Commit(reinterpret_cast<Address>(start_),
973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                kStoreBufferSize,
983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                false));  // Not executable.
993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  heap_->public_set_store_buffer_top(start_);
1003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  hash_set_1_ = new uintptr_t[kHashSetLength];
1023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  hash_set_2_ = new uintptr_t[kHashSetLength];
1033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  hash_sets_are_empty_ = false;
1043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ClearFilteringHashSets();
1063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
1073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StoreBuffer::TearDown() {
1103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  delete virtual_memory_;
1113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  delete old_virtual_memory_;
1123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  delete[] hash_set_1_;
1133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  delete[] hash_set_2_;
1143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  old_start_ = old_top_ = old_limit_ = old_reserved_limit_ = NULL;
1153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  start_ = limit_ = NULL;
1163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  heap_->public_set_store_buffer_top(start_);
1173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
1183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StoreBuffer::StoreBufferOverflow(Isolate* isolate) {
1213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  isolate->heap()->store_buffer()->Compact();
1223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
1233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#if V8_TARGET_ARCH_X64
1263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic int CompareAddresses(const void* void_a, const void* void_b) {
1273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  intptr_t a =
1283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      reinterpret_cast<intptr_t>(*reinterpret_cast<const Address*>(void_a));
1293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  intptr_t b =
1303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      reinterpret_cast<intptr_t>(*reinterpret_cast<const Address*>(void_b));
1313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Unfortunately if int is smaller than intptr_t there is no branch-free
1323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // way to return a number with the same sign as the difference between the
1333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // pointers.
1343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (a == b) return 0;
1353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (a < b) return -1;
1363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(a > b);
1373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return 1;
1383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
1393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#else
1403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic int CompareAddresses(const void* void_a, const void* void_b) {
1413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  intptr_t a =
1423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      reinterpret_cast<intptr_t>(*reinterpret_cast<const Address*>(void_a));
1433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  intptr_t b =
1443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      reinterpret_cast<intptr_t>(*reinterpret_cast<const Address*>(void_b));
1453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(sizeof(1) == sizeof(a));
1463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Shift down to avoid wraparound.
1473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return (a >> kPointerSizeLog2) - (b >> kPointerSizeLog2);
1483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
1493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif
1503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StoreBuffer::Uniq() {
1533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Remove adjacent duplicates and cells that do not point at new space.
1543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Address previous = NULL;
1553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Address* write = old_start_;
1563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(may_move_store_buffer_entries_);
1573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (Address* read = old_start_; read < old_top_; read++) {
1583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Address current = *read;
1593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (current != previous) {
1603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (heap_->InNewSpace(*reinterpret_cast<Object**>(current))) {
1613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        *write++ = current;
1623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
1633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
1643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    previous = current;
1653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  old_top_ = write;
1673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
1683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StoreBuffer::EnsureSpace(intptr_t space_needed) {
1713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  while (old_limit_ - old_top_ < space_needed &&
1723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch         old_limit_ < old_reserved_limit_) {
1733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    size_t grow = old_limit_ - old_start_;  // Double size.
1743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CHECK(old_virtual_memory_->Commit(reinterpret_cast<void*>(old_limit_),
1753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      grow * kPointerSize,
1763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      false));
1773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    old_limit_ += grow;
1783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (old_limit_ - old_top_ >= space_needed) return;
1813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (old_buffer_is_filtered_) return;
1833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(may_move_store_buffer_entries_);
1843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Compact();
1853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  old_buffer_is_filtered_ = true;
1873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool page_has_scan_on_scavenge_flag = false;
1883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PointerChunkIterator it(heap_);
1903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  MemoryChunk* chunk;
1913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  while ((chunk = it.next()) != NULL) {
1923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (chunk->scan_on_scavenge()) page_has_scan_on_scavenge_flag = true;
1933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (page_has_scan_on_scavenge_flag) {
1963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Filter(MemoryChunk::SCAN_ON_SCAVENGE);
1973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // If filtering out the entries from scan_on_scavenge pages got us down to
2003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // less than half full, then we are satisfied with that.
2013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (old_limit_ - old_top_ > old_top_ - old_start_) return;
2023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Sample 1 entry in 97 and filter out the pages where we estimate that more
2043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // than 1 in 8 pointers are to new space.
2053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static const int kSampleFinenesses = 5;
2063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static const struct Samples {
2073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int prime_sample_step;
2083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int threshold;
2093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } samples[kSampleFinenesses] =  {
2103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    { 97, ((Page::kPageSize / kPointerSize) / 97) / 8 },
2113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    { 23, ((Page::kPageSize / kPointerSize) / 23) / 16 },
2123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    { 7, ((Page::kPageSize / kPointerSize) / 7) / 32 },
2133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    { 3, ((Page::kPageSize / kPointerSize) / 3) / 256 },
2143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    { 1, 0}
2153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  };
2163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = kSampleFinenesses - 1; i >= 0; i--) {
2173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ExemptPopularPages(samples[i].prime_sample_step, samples[i].threshold);
2183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // As a last resort we mark all pages as being exempt from the store buffer.
2193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(i != 0 || old_top_ == old_start_);
2203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (old_limit_ - old_top_ > old_top_ - old_start_) return;
2213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
2223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  UNREACHABLE();
2233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
2243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Sample the store buffer to see if some pages are taking up a lot of space
2273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// in the store buffer.
2283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StoreBuffer::ExemptPopularPages(int prime_sample_step, int threshold) {
2293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PointerChunkIterator it(heap_);
2303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  MemoryChunk* chunk;
2313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  while ((chunk = it.next()) != NULL) {
2323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    chunk->set_store_buffer_counter(0);
2333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
2343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool created_new_scan_on_scavenge_pages = false;
2353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  MemoryChunk* previous_chunk = NULL;
2363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (Address* p = old_start_; p < old_top_; p += prime_sample_step) {
2373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Address addr = *p;
2383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    MemoryChunk* containing_chunk = NULL;
2393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (previous_chunk != NULL && previous_chunk->Contains(addr)) {
2403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      containing_chunk = previous_chunk;
2413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
2423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      containing_chunk = MemoryChunk::FromAnyPointerAddress(addr);
2433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
2443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int old_counter = containing_chunk->store_buffer_counter();
2453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (old_counter == threshold) {
2463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      containing_chunk->set_scan_on_scavenge(true);
2473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      created_new_scan_on_scavenge_pages = true;
2483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
2493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    containing_chunk->set_store_buffer_counter(old_counter + 1);
2503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    previous_chunk = containing_chunk;
2513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
2523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (created_new_scan_on_scavenge_pages) {
2533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Filter(MemoryChunk::SCAN_ON_SCAVENGE);
2543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
2553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  old_buffer_is_filtered_ = true;
2563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
2573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StoreBuffer::Filter(int flag) {
2603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Address* new_top = old_start_;
2613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  MemoryChunk* previous_chunk = NULL;
2623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (Address* p = old_start_; p < old_top_; p++) {
2633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Address addr = *p;
2643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    MemoryChunk* containing_chunk = NULL;
2653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (previous_chunk != NULL && previous_chunk->Contains(addr)) {
2663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      containing_chunk = previous_chunk;
2673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
2683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      containing_chunk = MemoryChunk::FromAnyPointerAddress(addr);
2693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      previous_chunk = containing_chunk;
2703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
2713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (!containing_chunk->IsFlagSet(flag)) {
2723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      *new_top++ = addr;
2733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
2743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
2753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  old_top_ = new_top;
2763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Filtering hash sets are inconsistent with the store buffer after this
2783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // operation.
2793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ClearFilteringHashSets();
2803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
2813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StoreBuffer::SortUniq() {
2843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Compact();
2853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (old_buffer_is_sorted_) return;
2863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  qsort(reinterpret_cast<void*>(old_start_),
2873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        old_top_ - old_start_,
2883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        sizeof(*old_top_),
2893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        &CompareAddresses);
2903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Uniq();
2913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  old_buffer_is_sorted_ = true;
2933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Filtering hash sets are inconsistent with the store buffer after this
2953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // operation.
2963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ClearFilteringHashSets();
2973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
2983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool StoreBuffer::PrepareForIteration() {
3013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Compact();
3023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PointerChunkIterator it(heap_);
3033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  MemoryChunk* chunk;
3043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool page_has_scan_on_scavenge_flag = false;
3053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  while ((chunk = it.next()) != NULL) {
3063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (chunk->scan_on_scavenge()) page_has_scan_on_scavenge_flag = true;
3073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
3083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (page_has_scan_on_scavenge_flag) {
3103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Filter(MemoryChunk::SCAN_ON_SCAVENGE);
3113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
3123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Filtering hash sets are inconsistent with the store buffer after
3143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // iteration.
3153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ClearFilteringHashSets();
3163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return page_has_scan_on_scavenge_flag;
3183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
3193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#ifdef DEBUG
3223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StoreBuffer::Clean() {
3233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ClearFilteringHashSets();
3243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Uniq();  // Also removes things that no longer point to new space.
3253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CheckForFullBuffer();
3263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
3273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic Address* in_store_buffer_1_element_cache = NULL;
3303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool StoreBuffer::CellIsInStoreBuffer(Address cell_address) {
3333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!FLAG_enable_slow_asserts) return true;
3343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (in_store_buffer_1_element_cache != NULL &&
3353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      *in_store_buffer_1_element_cache == cell_address) {
3363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return true;
3373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
3383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Address* top = reinterpret_cast<Address*>(heap_->store_buffer_top());
3393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (Address* current = top - 1; current >= start_; current--) {
3403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (*current == cell_address) {
3413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      in_store_buffer_1_element_cache = current;
3423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return true;
3433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
3443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
3453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (Address* current = old_top_ - 1; current >= old_start_; current--) {
3463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (*current == cell_address) {
3473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      in_store_buffer_1_element_cache = current;
3483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return true;
3493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
3503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
3513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return false;
3523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
3533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif
3543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StoreBuffer::ClearFilteringHashSets() {
3573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!hash_sets_are_empty_) {
3583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    memset(reinterpret_cast<void*>(hash_set_1_),
3593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           0,
3603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           sizeof(uintptr_t) * kHashSetLength);
3613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    memset(reinterpret_cast<void*>(hash_set_2_),
3623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           0,
3633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           sizeof(uintptr_t) * kHashSetLength);
3643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    hash_sets_are_empty_ = true;
3653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
3663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
3673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StoreBuffer::GCPrologue() {
3703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ClearFilteringHashSets();
3713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  during_gc_ = true;
3723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
3733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#ifdef DEBUG
3763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void DummyScavengePointer(HeapObject** p, HeapObject* o) {
3773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Do nothing.
3783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
3793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StoreBuffer::VerifyPointers(PagedSpace* space,
3823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 RegionCallback region_callback) {
3833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PageIterator it(space);
3843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  while (it.has_next()) {
3863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Page* page = it.next();
3873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FindPointersToNewSpaceOnPage(
3883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        reinterpret_cast<PagedSpace*>(page->owner()),
3893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        page,
3903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        region_callback,
3913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        &DummyScavengePointer);
3923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
3933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
3943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StoreBuffer::VerifyPointers(LargeObjectSpace* space) {
3973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LargeObjectIterator it(space);
3983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (HeapObject* object = it.Next(); object != NULL; object = it.Next()) {
3993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (object->IsFixedArray()) {
4003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Address slot_address = object->address();
4013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Address end = object->address() + object->Size();
4023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      while (slot_address < end) {
4043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        HeapObject** slot = reinterpret_cast<HeapObject**>(slot_address);
4053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // When we are not in GC the Heap::InNewSpace() predicate
4063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // checks that pointers which satisfy predicate point into
4073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // the active semispace.
4083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        heap_->InNewSpace(*slot);
4093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        slot_address += kPointerSize;
4103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
4113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
4123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
4143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif
4153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StoreBuffer::Verify() {
4183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#ifdef DEBUG
4193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  VerifyPointers(heap_->old_pointer_space(),
4203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                 &StoreBuffer::FindPointersToNewSpaceInRegion);
4213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  VerifyPointers(heap_->map_space(),
4223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                 &StoreBuffer::FindPointersToNewSpaceInMapsRegion);
4233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  VerifyPointers(heap_->lo_space());
4243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif
4253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
4263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StoreBuffer::GCEpilogue() {
4293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  during_gc_ = false;
4303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (FLAG_verify_heap) {
4313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Verify();
4323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
4343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StoreBuffer::FindPointersToNewSpaceInRegion(
4373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Address start, Address end, ObjectSlotCallback slot_callback) {
4383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (Address slot_address = start;
4393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch       slot_address < end;
4403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch       slot_address += kPointerSize) {
4413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Object** slot = reinterpret_cast<Object**>(slot_address);
4423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (heap_->InNewSpace(*slot)) {
4433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      HeapObject* object = reinterpret_cast<HeapObject*>(*slot);
4443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ASSERT(object->IsHeapObject());
4453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      slot_callback(reinterpret_cast<HeapObject**>(slot), object);
4463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (heap_->InNewSpace(*slot)) {
4473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        EnterDirectlyIntoStoreBuffer(slot_address);
4483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
4493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
4503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
4523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Compute start address of the first map following given addr.
4553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic inline Address MapStartAlign(Address addr) {
4563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Address page = Page::FromAddress(addr)->area_start();
4573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return page + (((addr - page) + (Map::kSize - 1)) / Map::kSize * Map::kSize);
4583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
4593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Compute end address of the first map preceding given addr.
4623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic inline Address MapEndAlign(Address addr) {
4633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Address page = Page::FromAllocationTop(addr)->area_start();
4643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return page + ((addr - page) / Map::kSize * Map::kSize);
4653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
4663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StoreBuffer::FindPointersToNewSpaceInMaps(
4693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Address start,
4703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Address end,
4713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ObjectSlotCallback slot_callback) {
4723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(MapStartAlign(start) == start);
4733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(MapEndAlign(end) == end);
4743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Address map_address = start;
4763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  while (map_address < end) {
4773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(!heap_->InNewSpace(Memory::Object_at(map_address)));
4783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(Memory::Object_at(map_address)->IsMap());
4793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Address pointer_fields_start = map_address + Map::kPointerFieldsBeginOffset;
4813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Address pointer_fields_end = map_address + Map::kPointerFieldsEndOffset;
4823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FindPointersToNewSpaceInRegion(pointer_fields_start,
4843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                   pointer_fields_end,
4853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                   slot_callback);
4863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    map_address += Map::kSize;
4873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
4893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StoreBuffer::FindPointersToNewSpaceInMapsRegion(
4923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Address start,
4933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Address end,
4943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ObjectSlotCallback slot_callback) {
4953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Address map_aligned_start = MapStartAlign(start);
4963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Address map_aligned_end   = MapEndAlign(end);
4973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(map_aligned_start == start);
4993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(map_aligned_end == end);
5003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  FindPointersToNewSpaceInMaps(map_aligned_start,
5023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               map_aligned_end,
5033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               slot_callback);
5043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
5053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// This function iterates over all the pointers in a paged space in the heap,
5083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// looking for pointers into new space.  Within the pages there may be dead
5093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// objects that have not been overwritten by free spaces or fillers because of
5103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// lazy sweeping.  These dead objects may not contain pointers to new space.
5113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// The garbage areas that have been swept properly (these will normally be the
5123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// large ones) will be marked with free space and filler map words.  In
5133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// addition any area that has never been used at all for object allocation must
5143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// be marked with a free space or filler.  Because the free space and filler
5153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// maps do not move we can always recognize these even after a compaction.
5163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Normal objects like FixedArrays and JSObjects should not contain references
5173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// to these maps.  The special garbage section (see comment in spaces.h) is
5183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// skipped since it can contain absolutely anything.  Any objects that are
5193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// allocated during iteration may or may not be visited by the iteration, but
5203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// they will not be partially visited.
5213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StoreBuffer::FindPointersToNewSpaceOnPage(
5223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    PagedSpace* space,
5233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Page* page,
5243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    RegionCallback region_callback,
5253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ObjectSlotCallback slot_callback) {
5263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Address visitable_start = page->area_start();
5273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Address end_of_page = page->area_end();
5283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Address visitable_end = visitable_start;
5303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Object* free_space_map = heap_->free_space_map();
5323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Object* two_pointer_filler_map = heap_->two_pointer_filler_map();
5333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  while (visitable_end < end_of_page) {
5353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Object* o = *reinterpret_cast<Object**>(visitable_end);
5363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Skip fillers but not things that look like fillers in the special
5373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // garbage section which can contain anything.
5383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (o == free_space_map ||
5393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        o == two_pointer_filler_map ||
5403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        (visitable_end == space->top() && visitable_end != space->limit())) {
5413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (visitable_start != visitable_end) {
5423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // After calling this the special garbage section may have moved.
5433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        (this->*region_callback)(visitable_start,
5443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 visitable_end,
5453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 slot_callback);
5463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (visitable_end >= space->top() && visitable_end < space->limit()) {
5473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          visitable_end = space->limit();
5483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          visitable_start = visitable_end;
5493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          continue;
5503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
5513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
5523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (visitable_end == space->top() && visitable_end != space->limit()) {
5533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        visitable_start = visitable_end = space->limit();
5543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {
5553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // At this point we are either at the start of a filler or we are at
5563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // the point where the space->top() used to be before the
5573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // visit_pointer_region call above.  Either way we can skip the
5583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // object at the current spot:  We don't promise to visit objects
5593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // allocated during heap traversal, and if space->top() moved then it
5603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // must be because an object was allocated at this point.
5613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        visitable_start =
5623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            visitable_end + HeapObject::FromAddress(visitable_end)->Size();
5633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        visitable_end = visitable_start;
5643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
5653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
5663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ASSERT(o != free_space_map);
5673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ASSERT(o != two_pointer_filler_map);
5683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ASSERT(visitable_end < space->top() || visitable_end >= space->limit());
5693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      visitable_end += kPointerSize;
5703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
5713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
5723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(visitable_end == end_of_page);
5733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (visitable_start != visitable_end) {
5743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    (this->*region_callback)(visitable_start,
5753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                             visitable_end,
5763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                             slot_callback);
5773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
5783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
5793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StoreBuffer::IteratePointersInStoreBuffer(
5823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ObjectSlotCallback slot_callback) {
5833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Address* limit = old_top_;
5843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  old_top_ = old_start_;
5853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  {
5863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    DontMoveStoreBufferEntriesScope scope(this);
5873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    for (Address* current = old_start_; current < limit; current++) {
5883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#ifdef DEBUG
5893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Address* saved_top = old_top_;
5903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif
5913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Object** slot = reinterpret_cast<Object**>(*current);
5923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Object* object = *slot;
5933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (heap_->InFromSpace(object)) {
5943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        HeapObject* heap_object = reinterpret_cast<HeapObject*>(object);
5953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        slot_callback(reinterpret_cast<HeapObject**>(slot), heap_object);
5963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (heap_->InNewSpace(*slot)) {
5973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          EnterDirectlyIntoStoreBuffer(reinterpret_cast<Address>(slot));
5983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
5993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
6003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ASSERT(old_top_ == saved_top + 1 || old_top_ == saved_top);
6013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
6023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
6033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
6043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StoreBuffer::IteratePointersToNewSpace(ObjectSlotCallback slot_callback) {
6073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // We do not sort or remove duplicated entries from the store buffer because
6083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // we expect that callback will rebuild the store buffer thus removing
6093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // all duplicates and pointers to old space.
6103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool some_pages_to_scan = PrepareForIteration();
6113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // TODO(gc): we want to skip slots on evacuation candidates
6133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // but we can't simply figure that out from slot address
6143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // because slot can belong to a large object.
6153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  IteratePointersInStoreBuffer(slot_callback);
6163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // We are done scanning all the pointers that were in the store buffer, but
6183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // there may be some pages marked scan_on_scavenge that have pointers to new
6193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // space that are not in the store buffer.  We must scan them now.  As we
6203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // scan, the surviving pointers to new space will be added to the store
6213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // buffer.  If there are still a lot of pointers to new space then we will
6223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // keep the scan_on_scavenge flag on the page and discard the pointers that
6233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // were added to the store buffer.  If there are not many pointers to new
6243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // space left on the page we will keep the pointers in the store buffer and
6253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // remove the flag from the page.
6263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (some_pages_to_scan) {
6273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (callback_ != NULL) {
6283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      (*callback_)(heap_, NULL, kStoreBufferStartScanningPagesEvent);
6293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
6303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    PointerChunkIterator it(heap_);
6313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    MemoryChunk* chunk;
6323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    while ((chunk = it.next()) != NULL) {
6333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (chunk->scan_on_scavenge()) {
6343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        chunk->set_scan_on_scavenge(false);
6353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (callback_ != NULL) {
6363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          (*callback_)(heap_, chunk, kStoreBufferScanningPageEvent);
6373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
6383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (chunk->owner() == heap_->lo_space()) {
6393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          LargePage* large_page = reinterpret_cast<LargePage*>(chunk);
6403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          HeapObject* array = large_page->GetObject();
6413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          ASSERT(array->IsFixedArray());
6423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          Address start = array->address();
6433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          Address end = start + array->Size();
6443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          FindPointersToNewSpaceInRegion(start, end, slot_callback);
6453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        } else {
6463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          Page* page = reinterpret_cast<Page*>(chunk);
6473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          PagedSpace* owner = reinterpret_cast<PagedSpace*>(page->owner());
6483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          FindPointersToNewSpaceOnPage(
6493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              owner,
6503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              page,
6513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              (owner == heap_->map_space() ?
6523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                 &StoreBuffer::FindPointersToNewSpaceInMapsRegion :
6533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                 &StoreBuffer::FindPointersToNewSpaceInRegion),
6543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              slot_callback);
6553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
6563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
6573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
6583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (callback_ != NULL) {
6593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      (*callback_)(heap_, NULL, kStoreBufferScanningPageEvent);
6603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
6613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
6623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
6633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StoreBuffer::Compact() {
6663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Address* top = reinterpret_cast<Address*>(heap_->store_buffer_top());
6673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (top == start_) return;
6693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // There's no check of the limit in the loop below so we check here for
6713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // the worst case (compaction doesn't eliminate any pointers).
6723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(top <= limit_);
6733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  heap_->public_set_store_buffer_top(start_);
6743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  EnsureSpace(top - start_);
6753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(may_move_store_buffer_entries_);
6763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Goes through the addresses in the store buffer attempting to remove
6773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // duplicates.  In the interest of speed this is a lossy operation.  Some
6783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // duplicates will remain.  We have two hash sets with different hash
6793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // functions to reduce the number of unnecessary clashes.
6803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  hash_sets_are_empty_ = false;  // Hash sets are in use.
6813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (Address* current = start_; current < top; current++) {
6823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(!heap_->cell_space()->Contains(*current));
6833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(!heap_->code_space()->Contains(*current));
6843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(!heap_->old_data_space()->Contains(*current));
6853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    uintptr_t int_addr = reinterpret_cast<uintptr_t>(*current);
6863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Shift out the last bits including any tags.
6873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int_addr >>= kPointerSizeLog2;
6883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int hash1 =
6893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ((int_addr ^ (int_addr >> kHashSetLengthLog2)) & (kHashSetLength - 1));
6903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (hash_set_1_[hash1] == int_addr) continue;
6913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    uintptr_t hash2 = (int_addr - (int_addr >> kHashSetLengthLog2));
6923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    hash2 ^= hash2 >> (kHashSetLengthLog2 * 2);
6933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    hash2 &= (kHashSetLength - 1);
6943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (hash_set_2_[hash2] == int_addr) continue;
6953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (hash_set_1_[hash1] == 0) {
6963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      hash_set_1_[hash1] = int_addr;
6973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else if (hash_set_2_[hash2] == 0) {
6983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      hash_set_2_[hash2] = int_addr;
6993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
7003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Rather than slowing down we just throw away some entries.  This will
7013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // cause some duplicates to remain undetected.
7023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      hash_set_1_[hash1] = int_addr;
7033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      hash_set_2_[hash2] = 0;
7043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
7053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    old_buffer_is_sorted_ = false;
7063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    old_buffer_is_filtered_ = false;
7073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    *old_top_++ = reinterpret_cast<Address>(int_addr << kPointerSizeLog2);
7083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(old_top_ <= old_limit_);
7093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
7103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  heap_->isolate()->counters()->store_buffer_compactions()->Increment();
7113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CheckForFullBuffer();
7123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
7133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StoreBuffer::CheckForFullBuffer() {
7163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  EnsureSpace(kStoreBufferSize * 2);
7173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
7183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} }  // namespace v8::internal
720