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 20667 : TypedSlots::~TypedSlots() {
11 10097 : Chunk* chunk = head_;
12 31339 : while (chunk != nullptr) {
13 10621 : Chunk* next = chunk->next;
14 10621 : delete[] chunk->buffer;
15 10621 : delete chunk;
16 : chunk = next;
17 : }
18 10097 : head_ = nullptr;
19 10097 : tail_ = nullptr;
20 10570 : }
21 :
22 490649 : void TypedSlots::Insert(SlotType type, uint32_t offset) {
23 490649 : TypedSlot slot = {TypeField::encode(type) | OffsetField::encode(offset)};
24 490649 : Chunk* chunk = EnsureChunk();
25 : DCHECK_LT(chunk->count, chunk->capacity);
26 490644 : chunk->buffer[chunk->count] = slot;
27 490644 : ++chunk->count;
28 490644 : }
29 :
30 472 : void TypedSlots::Merge(TypedSlots* other) {
31 472 : if (other->head_ == nullptr) {
32 : return;
33 : }
34 472 : if (head_ == nullptr) {
35 354 : head_ = other->head_;
36 354 : tail_ = other->tail_;
37 : } else {
38 118 : tail_->next = other->head_;
39 118 : tail_ = other->tail_;
40 : }
41 472 : other->head_ = nullptr;
42 472 : other->tail_ = nullptr;
43 : }
44 :
45 490653 : TypedSlots::Chunk* TypedSlots::EnsureChunk() {
46 490653 : if (!head_) {
47 9743 : head_ = tail_ = NewChunk(nullptr, kInitialBufferSize);
48 : }
49 490653 : if (head_->count == head_->capacity) {
50 878 : head_ = NewChunk(head_, NextCapacity(head_->capacity));
51 : }
52 490653 : return head_;
53 : }
54 :
55 10621 : TypedSlots::Chunk* TypedSlots::NewChunk(Chunk* next, int capacity) {
56 10621 : Chunk* chunk = new Chunk;
57 10621 : chunk->next = next;
58 10621 : chunk->buffer = new TypedSlot[capacity];
59 10621 : chunk->capacity = capacity;
60 10621 : chunk->count = 0;
61 10621 : return chunk;
62 : }
63 :
64 28868 : TypedSlotSet::~TypedSlotSet() { FreeToBeFreedChunks(); }
65 :
66 10484 : void TypedSlotSet::FreeToBeFreedChunks() {
67 10484 : base::MutexGuard guard(&to_be_freed_chunks_mutex_);
68 10484 : std::stack<std::unique_ptr<Chunk>> empty;
69 : to_be_freed_chunks_.swap(empty);
70 10484 : }
71 :
72 922 : void TypedSlotSet::ClearInvalidSlots(
73 : const std::map<uint32_t, uint32_t>& invalid_ranges) {
74 : Chunk* chunk = LoadHead();
75 2856 : while (chunk != nullptr) {
76 967 : TypedSlot* buffer = chunk->buffer;
77 967 : int count = chunk->count;
78 38969 : for (int i = 0; i < count; i++) {
79 19001 : TypedSlot slot = LoadTypedSlot(buffer + i);
80 : SlotType type = TypeField::decode(slot.type_and_offset);
81 19001 : if (type == CLEARED_SLOT) continue;
82 9840 : 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 9840 : 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 9360 : if (upper_bound->second > offset) {
91 : ClearTypedSlot(buffer + i);
92 : }
93 : }
94 : chunk = LoadNext(chunk);
95 : }
96 922 : }
97 :
98 : } // namespace internal
99 122036 : } // namespace v8
|