Line data Source code
1 : // Copyright 2018 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/slot-set.h"
6 :
7 : namespace v8 {
8 : namespace internal {
9 :
10 20600 : TypedSlots::~TypedSlots() {
11 10065 : Chunk* chunk = head_;
12 31139 : while (chunk != nullptr) {
13 10537 : Chunk* next = chunk->next;
14 10537 : delete[] chunk->buffer;
15 10537 : delete chunk;
16 : chunk = next;
17 : }
18 10065 : head_ = nullptr;
19 10065 : tail_ = nullptr;
20 10535 : }
21 :
22 420910 : void TypedSlots::Insert(SlotType type, uint32_t offset) {
23 420910 : TypedSlot slot = {TypeField::encode(type) | OffsetField::encode(offset)};
24 420910 : Chunk* chunk = EnsureChunk();
25 : DCHECK_LT(chunk->count, chunk->capacity);
26 420916 : chunk->buffer[chunk->count] = slot;
27 420916 : ++chunk->count;
28 420916 : }
29 :
30 469 : void TypedSlots::Merge(TypedSlots* other) {
31 469 : if (other->head_ == nullptr) {
32 : return;
33 : }
34 469 : if (head_ == nullptr) {
35 338 : head_ = other->head_;
36 338 : tail_ = other->tail_;
37 : } else {
38 131 : tail_->next = other->head_;
39 131 : tail_ = other->tail_;
40 : }
41 469 : other->head_ = nullptr;
42 469 : other->tail_ = nullptr;
43 : }
44 :
45 420918 : TypedSlots::Chunk* TypedSlots::EnsureChunk() {
46 420918 : if (!head_) {
47 9727 : head_ = tail_ = NewChunk(nullptr, kInitialBufferSize);
48 : }
49 420918 : if (head_->count == head_->capacity) {
50 810 : head_ = NewChunk(head_, NextCapacity(head_->capacity));
51 : }
52 420918 : return head_;
53 : }
54 :
55 10537 : TypedSlots::Chunk* TypedSlots::NewChunk(Chunk* next, int capacity) {
56 10537 : Chunk* chunk = new Chunk;
57 10537 : chunk->next = next;
58 10537 : chunk->buffer = new TypedSlot[capacity];
59 10537 : chunk->capacity = capacity;
60 10537 : chunk->count = 0;
61 10537 : return chunk;
62 : }
63 :
64 28781 : TypedSlotSet::~TypedSlotSet() { FreeToBeFreedChunks(); }
65 :
66 10449 : void TypedSlotSet::FreeToBeFreedChunks() {
67 10449 : base::MutexGuard guard(&to_be_freed_chunks_mutex_);
68 10449 : std::stack<std::unique_ptr<Chunk>> empty;
69 : to_be_freed_chunks_.swap(empty);
70 10449 : }
71 :
72 916 : void TypedSlotSet::ClearInvalidSlots(
73 : const std::map<uint32_t, uint32_t>& invalid_ranges) {
74 : Chunk* chunk = LoadHead();
75 2838 : while (chunk != nullptr) {
76 961 : TypedSlot* buffer = chunk->buffer;
77 961 : int count = chunk->count;
78 40395 : for (int i = 0; i < count; i++) {
79 19717 : TypedSlot slot = LoadTypedSlot(buffer + i);
80 : SlotType type = TypeField::decode(slot.type_and_offset);
81 19717 : if (type == CLEARED_SLOT) continue;
82 10450 : uint32_t offset = OffsetField::decode(slot.type_and_offset);
83 : std::map<uint32_t, uint32_t>::const_iterator upper_bound =
84 : invalid_ranges.upper_bound(offset);
85 10450 : if (upper_bound == invalid_ranges.begin()) continue;
86 : // upper_bounds points to the invalid range after the given slot. Hence,
87 : // we have to go to the previous element.
88 : upper_bound--;
89 : DCHECK_LE(upper_bound->first, offset);
90 9542 : if (upper_bound->second > offset) {
91 : ClearTypedSlot(buffer + i);
92 : }
93 : }
94 : chunk = LoadNext(chunk);
95 : }
96 916 : }
97 :
98 : } // namespace internal
99 122036 : } // namespace v8
|