11cb0ef41Sopenharmony_ci// Copyright 2018 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci#include "src/heap/slot-set.h"
61cb0ef41Sopenharmony_ci
71cb0ef41Sopenharmony_ci#include "src/base/logging.h"
81cb0ef41Sopenharmony_ci#include "src/heap/memory-chunk-layout.h"
91cb0ef41Sopenharmony_ci
101cb0ef41Sopenharmony_cinamespace v8 {
111cb0ef41Sopenharmony_cinamespace internal {
121cb0ef41Sopenharmony_ci
131cb0ef41Sopenharmony_ciTypedSlots::~TypedSlots() {
141cb0ef41Sopenharmony_ci  Chunk* chunk = head_;
151cb0ef41Sopenharmony_ci  while (chunk != nullptr) {
161cb0ef41Sopenharmony_ci    Chunk* next = chunk->next;
171cb0ef41Sopenharmony_ci    delete chunk;
181cb0ef41Sopenharmony_ci    chunk = next;
191cb0ef41Sopenharmony_ci  }
201cb0ef41Sopenharmony_ci  head_ = nullptr;
211cb0ef41Sopenharmony_ci  tail_ = nullptr;
221cb0ef41Sopenharmony_ci}
231cb0ef41Sopenharmony_ci
241cb0ef41Sopenharmony_civoid TypedSlots::Insert(SlotType type, uint32_t offset) {
251cb0ef41Sopenharmony_ci  TypedSlot slot = {TypeField::encode(type) | OffsetField::encode(offset)};
261cb0ef41Sopenharmony_ci  Chunk* chunk = EnsureChunk();
271cb0ef41Sopenharmony_ci  DCHECK_LT(chunk->buffer.size(), chunk->buffer.capacity());
281cb0ef41Sopenharmony_ci  chunk->buffer.push_back(slot);
291cb0ef41Sopenharmony_ci}
301cb0ef41Sopenharmony_ci
311cb0ef41Sopenharmony_civoid TypedSlots::Merge(TypedSlots* other) {
321cb0ef41Sopenharmony_ci  if (other->head_ == nullptr) {
331cb0ef41Sopenharmony_ci    return;
341cb0ef41Sopenharmony_ci  }
351cb0ef41Sopenharmony_ci  if (head_ == nullptr) {
361cb0ef41Sopenharmony_ci    head_ = other->head_;
371cb0ef41Sopenharmony_ci    tail_ = other->tail_;
381cb0ef41Sopenharmony_ci  } else {
391cb0ef41Sopenharmony_ci    tail_->next = other->head_;
401cb0ef41Sopenharmony_ci    tail_ = other->tail_;
411cb0ef41Sopenharmony_ci  }
421cb0ef41Sopenharmony_ci  other->head_ = nullptr;
431cb0ef41Sopenharmony_ci  other->tail_ = nullptr;
441cb0ef41Sopenharmony_ci}
451cb0ef41Sopenharmony_ci
461cb0ef41Sopenharmony_ciTypedSlots::Chunk* TypedSlots::EnsureChunk() {
471cb0ef41Sopenharmony_ci  if (!head_) {
481cb0ef41Sopenharmony_ci    head_ = tail_ = NewChunk(nullptr, kInitialBufferSize);
491cb0ef41Sopenharmony_ci  }
501cb0ef41Sopenharmony_ci  if (head_->buffer.size() == head_->buffer.capacity()) {
511cb0ef41Sopenharmony_ci    head_ = NewChunk(head_, NextCapacity(head_->buffer.capacity()));
521cb0ef41Sopenharmony_ci  }
531cb0ef41Sopenharmony_ci  return head_;
541cb0ef41Sopenharmony_ci}
551cb0ef41Sopenharmony_ci
561cb0ef41Sopenharmony_ciTypedSlots::Chunk* TypedSlots::NewChunk(Chunk* next, size_t capacity) {
571cb0ef41Sopenharmony_ci  Chunk* chunk = new Chunk;
581cb0ef41Sopenharmony_ci  chunk->next = next;
591cb0ef41Sopenharmony_ci  chunk->buffer.reserve(capacity);
601cb0ef41Sopenharmony_ci  DCHECK_EQ(chunk->buffer.capacity(), capacity);
611cb0ef41Sopenharmony_ci  return chunk;
621cb0ef41Sopenharmony_ci}
631cb0ef41Sopenharmony_ci
641cb0ef41Sopenharmony_civoid TypedSlotSet::ClearInvalidSlots(const FreeRangesMap& invalid_ranges) {
651cb0ef41Sopenharmony_ci  IterateSlotsInRanges([](TypedSlot* slot) { *slot = ClearedTypedSlot(); },
661cb0ef41Sopenharmony_ci                       invalid_ranges);
671cb0ef41Sopenharmony_ci}
681cb0ef41Sopenharmony_ci
691cb0ef41Sopenharmony_civoid TypedSlotSet::AssertNoInvalidSlots(const FreeRangesMap& invalid_ranges) {
701cb0ef41Sopenharmony_ci  IterateSlotsInRanges(
711cb0ef41Sopenharmony_ci      [](TypedSlot* slot) {
721cb0ef41Sopenharmony_ci        CHECK_WITH_MSG(false, "No slot in ranges expected.");
731cb0ef41Sopenharmony_ci      },
741cb0ef41Sopenharmony_ci      invalid_ranges);
751cb0ef41Sopenharmony_ci}
761cb0ef41Sopenharmony_ci
771cb0ef41Sopenharmony_citemplate <typename Callback>
781cb0ef41Sopenharmony_civoid TypedSlotSet::IterateSlotsInRanges(Callback callback,
791cb0ef41Sopenharmony_ci                                        const FreeRangesMap& ranges) {
801cb0ef41Sopenharmony_ci  if (ranges.empty()) return;
811cb0ef41Sopenharmony_ci
821cb0ef41Sopenharmony_ci  Chunk* chunk = LoadHead();
831cb0ef41Sopenharmony_ci  while (chunk != nullptr) {
841cb0ef41Sopenharmony_ci    for (TypedSlot& slot : chunk->buffer) {
851cb0ef41Sopenharmony_ci      SlotType type = TypeField::decode(slot.type_and_offset);
861cb0ef41Sopenharmony_ci      if (type == SlotType::kCleared) continue;
871cb0ef41Sopenharmony_ci      uint32_t offset = OffsetField::decode(slot.type_and_offset);
881cb0ef41Sopenharmony_ci      FreeRangesMap::const_iterator upper_bound = ranges.upper_bound(offset);
891cb0ef41Sopenharmony_ci      if (upper_bound == ranges.begin()) continue;
901cb0ef41Sopenharmony_ci      // upper_bounds points to the invalid range after the given slot. Hence,
911cb0ef41Sopenharmony_ci      // we have to go to the previous element.
921cb0ef41Sopenharmony_ci      upper_bound--;
931cb0ef41Sopenharmony_ci      DCHECK_LE(upper_bound->first, offset);
941cb0ef41Sopenharmony_ci      if (upper_bound->second > offset) {
951cb0ef41Sopenharmony_ci        callback(&slot);
961cb0ef41Sopenharmony_ci      }
971cb0ef41Sopenharmony_ci    }
981cb0ef41Sopenharmony_ci    chunk = LoadNext(chunk);
991cb0ef41Sopenharmony_ci  }
1001cb0ef41Sopenharmony_ci}
1011cb0ef41Sopenharmony_ci
1021cb0ef41Sopenharmony_ci}  // namespace internal
1031cb0ef41Sopenharmony_ci}  // namespace v8
104