1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "src/heap/store-buffer.h"
6
7 #include <algorithm>
8
9 #include "src/counters.h"
10 #include "src/heap/incremental-marking.h"
11 #include "src/isolate.h"
12 #include "src/objects-inl.h"
13 #include "src/v8.h"
14
15 namespace v8 {
16 namespace internal {
17
StoreBuffer(Heap * heap)18 StoreBuffer::StoreBuffer(Heap* heap)
19 : heap_(heap),
20 top_(nullptr),
21 start_(nullptr),
22 limit_(nullptr),
23 virtual_memory_(nullptr) {}
24
SetUp()25 void StoreBuffer::SetUp() {
26 // Allocate 3x the buffer size, so that we can start the new store buffer
27 // aligned to 2x the size. This lets us use a bit test to detect the end of
28 // the area.
29 virtual_memory_ = new base::VirtualMemory(kStoreBufferSize * 2);
30 uintptr_t start_as_int =
31 reinterpret_cast<uintptr_t>(virtual_memory_->address());
32 start_ = reinterpret_cast<Address*>(RoundUp(start_as_int, kStoreBufferSize));
33 limit_ = start_ + (kStoreBufferSize / kPointerSize);
34
35 DCHECK(reinterpret_cast<Address>(start_) >= virtual_memory_->address());
36 DCHECK(reinterpret_cast<Address>(limit_) >= virtual_memory_->address());
37 Address* vm_limit = reinterpret_cast<Address*>(
38 reinterpret_cast<char*>(virtual_memory_->address()) +
39 virtual_memory_->size());
40 DCHECK(start_ <= vm_limit);
41 DCHECK(limit_ <= vm_limit);
42 USE(vm_limit);
43 DCHECK((reinterpret_cast<uintptr_t>(limit_) & kStoreBufferMask) == 0);
44
45 if (!virtual_memory_->Commit(reinterpret_cast<Address>(start_),
46 kStoreBufferSize,
47 false)) { // Not executable.
48 V8::FatalProcessOutOfMemory("StoreBuffer::SetUp");
49 }
50 top_ = start_;
51 }
52
53
TearDown()54 void StoreBuffer::TearDown() {
55 delete virtual_memory_;
56 top_ = start_ = limit_ = nullptr;
57 }
58
59
StoreBufferOverflow(Isolate * isolate)60 void StoreBuffer::StoreBufferOverflow(Isolate* isolate) {
61 isolate->heap()->store_buffer()->MoveEntriesToRememberedSet();
62 isolate->counters()->store_buffer_overflows()->Increment();
63 }
64
MoveEntriesToRememberedSet()65 void StoreBuffer::MoveEntriesToRememberedSet() {
66 if (top_ == start_) return;
67 DCHECK(top_ <= limit_);
68 for (Address* current = start_; current < top_; current++) {
69 DCHECK(!heap_->code_space()->Contains(*current));
70 Address addr = *current;
71 Page* page = Page::FromAnyPointerAddress(heap_, addr);
72 RememberedSet<OLD_TO_NEW>::Insert(page, addr);
73 }
74 top_ = start_;
75 }
76
77 } // namespace internal
78 } // namespace v8
79