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 22484 : TypedSlots::~TypedSlots() {
11 10778 : Chunk* chunk = head_;
12 33242 : while (chunk != nullptr) {
13 11232 : Chunk* next = chunk->next;
14 11232 : delete[] chunk->buffer;
15 11232 : delete chunk;
16 : chunk = next;
17 : }
18 10778 : head_ = nullptr;
19 10778 : tail_ = nullptr;
20 11706 : }
21 :
22 527611 : void TypedSlots::Insert(SlotType type, uint32_t offset) {
23 527611 : TypedSlot slot = {TypeField::encode(type) | OffsetField::encode(offset)};
24 527611 : Chunk* chunk = EnsureChunk();
25 : DCHECK_LT(chunk->count, chunk->capacity);
26 527622 : chunk->buffer[chunk->count] = slot;
27 527622 : ++chunk->count;
28 527622 : }
29 :
30 925 : void TypedSlots::Merge(TypedSlots* other) {
31 925 : if (other->head_ == nullptr) {
32 : return;
33 : }
34 925 : if (head_ == nullptr) {
35 517 : head_ = other->head_;
36 517 : tail_ = other->tail_;
37 : } else {
38 408 : tail_->next = other->head_;
39 408 : tail_ = other->tail_;
40 : }
41 925 : other->head_ = nullptr;
42 925 : other->tail_ = nullptr;
43 : }
44 :
45 527615 : TypedSlots::Chunk* TypedSlots::EnsureChunk() {
46 527615 : if (!head_) {
47 10261 : head_ = tail_ = NewChunk(nullptr, kInitialBufferSize);
48 : }
49 527615 : if (head_->count == head_->capacity) {
50 971 : head_ = NewChunk(head_, NextCapacity(head_->capacity));
51 : }
52 527615 : return head_;
53 : }
54 :
55 11232 : TypedSlots::Chunk* TypedSlots::NewChunk(Chunk* next, int capacity) {
56 11232 : Chunk* chunk = new Chunk;
57 11232 : chunk->next = next;
58 11232 : chunk->buffer = new TypedSlot[capacity];
59 11232 : chunk->capacity = capacity;
60 11232 : chunk->count = 0;
61 11232 : return chunk;
62 : }
63 :
64 29546 : TypedSlotSet::~TypedSlotSet() { FreeToBeFreedChunks(); }
65 :
66 10730 : void TypedSlotSet::FreeToBeFreedChunks() {
67 10730 : base::MutexGuard guard(&to_be_freed_chunks_mutex_);
68 10730 : std::stack<std::unique_ptr<Chunk>> empty;
69 : to_be_freed_chunks_.swap(empty);
70 10730 : }
71 :
72 937 : void TypedSlotSet::ClearInvalidSlots(
73 : const std::map<uint32_t, uint32_t>& invalid_ranges) {
74 : Chunk* chunk = LoadHead();
75 2907 : while (chunk != nullptr) {
76 985 : TypedSlot* buffer = chunk->buffer;
77 985 : int count = chunk->count;
78 42365 : for (int i = 0; i < count; i++) {
79 20690 : TypedSlot slot = LoadTypedSlot(buffer + i);
80 : SlotType type = TypeField::decode(slot.type_and_offset);
81 20690 : if (type == CLEARED_SLOT) continue;
82 10684 : 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 10684 : 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 9938 : if (upper_bound->second > offset) {
91 : ClearTypedSlot(buffer + i);
92 : }
93 : }
94 : chunk = LoadNext(chunk);
95 : }
96 937 : }
97 :
98 : } // namespace internal
99 122004 : } // namespace v8
|