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