| // Copyright 2018 the V8 project authors. All rights reserved. | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | #include "src/heap/slot-set.h" | 
 |  | 
 | namespace v8 { | 
 | namespace internal { | 
 |  | 
 | TypedSlots::~TypedSlots() { | 
 |   Chunk* chunk = head_; | 
 |   while (chunk != nullptr) { | 
 |     Chunk* next = chunk->next; | 
 |     delete chunk; | 
 |     chunk = next; | 
 |   } | 
 |   head_ = nullptr; | 
 |   tail_ = nullptr; | 
 | } | 
 |  | 
 | void TypedSlots::Insert(SlotType type, uint32_t offset) { | 
 |   TypedSlot slot = {TypeField::encode(type) | OffsetField::encode(offset)}; | 
 |   Chunk* chunk = EnsureChunk(); | 
 |   DCHECK_LT(chunk->buffer.size(), chunk->buffer.capacity()); | 
 |   chunk->buffer.push_back(slot); | 
 | } | 
 |  | 
 | void TypedSlots::Merge(TypedSlots* other) { | 
 |   if (other->head_ == nullptr) { | 
 |     return; | 
 |   } | 
 |   if (head_ == nullptr) { | 
 |     head_ = other->head_; | 
 |     tail_ = other->tail_; | 
 |   } else { | 
 |     tail_->next = other->head_; | 
 |     tail_ = other->tail_; | 
 |   } | 
 |   other->head_ = nullptr; | 
 |   other->tail_ = nullptr; | 
 | } | 
 |  | 
 | TypedSlots::Chunk* TypedSlots::EnsureChunk() { | 
 |   if (!head_) { | 
 |     head_ = tail_ = NewChunk(nullptr, kInitialBufferSize); | 
 |   } | 
 |   if (head_->buffer.size() == head_->buffer.capacity()) { | 
 |     head_ = NewChunk(head_, NextCapacity(head_->buffer.capacity())); | 
 |   } | 
 |   return head_; | 
 | } | 
 |  | 
 | TypedSlots::Chunk* TypedSlots::NewChunk(Chunk* next, size_t capacity) { | 
 |   Chunk* chunk = new Chunk; | 
 |   chunk->next = next; | 
 |   chunk->buffer.reserve(capacity); | 
 |   DCHECK_EQ(chunk->buffer.capacity(), capacity); | 
 |   return chunk; | 
 | } | 
 |  | 
 | void TypedSlotSet::ClearInvalidSlots( | 
 |     const std::map<uint32_t, uint32_t>& invalid_ranges) { | 
 |   Chunk* chunk = LoadHead(); | 
 |   while (chunk != nullptr) { | 
 |     for (TypedSlot& slot : chunk->buffer) { | 
 |       SlotType type = TypeField::decode(slot.type_and_offset); | 
 |       if (type == CLEARED_SLOT) continue; | 
 |       uint32_t offset = OffsetField::decode(slot.type_and_offset); | 
 |       std::map<uint32_t, uint32_t>::const_iterator upper_bound = | 
 |           invalid_ranges.upper_bound(offset); | 
 |       if (upper_bound == invalid_ranges.begin()) continue; | 
 |       // upper_bounds points to the invalid range after the given slot. Hence, | 
 |       // we have to go to the previous element. | 
 |       upper_bound--; | 
 |       DCHECK_LE(upper_bound->first, offset); | 
 |       if (upper_bound->second > offset) { | 
 |         slot = ClearedTypedSlot(); | 
 |       } | 
 |     } | 
 |     chunk = LoadNext(chunk); | 
 |   } | 
 | } | 
 |  | 
 | }  // namespace internal | 
 | }  // namespace v8 |