current commit
261004.7 · deps: update V8 to 15.2.124.38
// Copyright 2021 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/deoptimizer/materialized-object-store.h"

#include "src/base/numerics/safe_conversions.h"
#include "src/execution/isolate.h"
#include "src/heap/heap-inl.h"
#include "src/objects/fixed-array-inl.h"
#include "src/objects/oddball.h"

namespace v8 {
namespace internal {

DirectHandle<FixedArray> MaterializedObjectStore::Get(Address fp) {
  std::optional<uint32_t> index = StackIdToIndex(fp);
  if (!index.has_value()) {
    return Handle<FixedArray>::null();
  }
  DirectHandle<FixedArray> array = GetStackEntries();
  CHECK_GT(array->ulength().value(), *index);
  return Cast<FixedArray>(Handle<Object>(array->get(*index), isolate()));
}

void MaterializedObjectStore::Set(
    Address fp, DirectHandle<FixedArray> materialized_objects) {
  std::optional<uint32_t> index = StackIdToIndex(fp);
  if (!index.has_value()) {
    index = base::checked_cast<uint32_t>(frame_fps_.size());
    frame_fps_.push_back(fp);
  }

  DirectHandle<FixedArray> array = EnsureStackEntries(*index + 1);
  array->set(*index, *materialized_objects);
}

bool MaterializedObjectStore::Remove(Address fp) {
  auto it = std::find(frame_fps_.begin(), frame_fps_.end(), fp);
  if (it == frame_fps_.end()) return false;
  uint32_t index = static_cast<uint32_t>(std::distance(frame_fps_.begin(), it));

  frame_fps_.erase(it);
  Tagged<FixedArray> array = isolate()->heap()->materialized_objects();

  CHECK_LT(index, array->ulength().value());
  uint32_t fps_size = base::checked_cast<uint32_t>(frame_fps_.size());
  for (uint32_t i = index; i < fps_size; i++) {
    array->set(i, array->get(i + 1));
  }
  array->set(fps_size, ReadOnlyRoots(isolate()).undefined_value());
  return true;
}

std::optional<uint32_t> MaterializedObjectStore::StackIdToIndex(Address fp) {
  auto it = std::find(frame_fps_.begin(), frame_fps_.end(), fp);
  return it == frame_fps_.end() ? std::nullopt
                                : std::make_optional(static_cast<uint32_t>(
                                      std::distance(frame_fps_.begin(), it)));
}

DirectHandle<FixedArray> MaterializedObjectStore::GetStackEntries() {
  return DirectHandle<FixedArray>(isolate()->heap()->materialized_objects(),
                                  isolate());
}

DirectHandle<FixedArray> MaterializedObjectStore::EnsureStackEntries(
    uint32_t length) {
  DirectHandle<FixedArray> array = GetStackEntries();
  uint32_t array_len = array->ulength().value();
  if (array_len >= length) {
    return array;
  }

  uint32_t new_length = length > 10 ? length : 10;
  if (new_length < 2 * array_len) {
    new_length = 2 * array_len;
  }

  DirectHandle<FixedArray> new_array =
      isolate()->factory()->NewFixedArray(new_length, AllocationType::kOld);
  for (uint32_t i = 0; i < array_len; i++) {
    new_array->set(i, array->get(i));
  }
  Tagged<HeapObject> undefined_value =
      ReadOnlyRoots(isolate()).undefined_value();
  for (uint32_t i = array_len; i < length; i++) {
    new_array->set(i, undefined_value);
  }
  isolate()->heap()->SetRootMaterializedObjects(*new_array);
  return new_array;
}

}  // namespace internal
}  // namespace v8