current commit
261007.21 · deps: update V8 to 15.5.35.20
// 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.

#ifndef V8_OBJECTS_PROTOTYPE_INFO_INL_H_
#define V8_OBJECTS_PROTOTYPE_INFO_INL_H_

#include "src/objects/prototype-info.h"
// Include the non-inl header before the rest of the headers.

#include "src/heap/heap-write-barrier-inl.h"
#include "src/ic/handler-configuration.h"
#include "src/objects/fixed-array-inl.h"
#include "src/objects/map-inl.h"
#include "src/objects/maybe-object.h"
#include "src/objects/module.h"
#include "src/objects/struct-inl.h"

// Has to be the last include (doesn't have include guards):
#include "src/objects/object-macros.h"

namespace v8 {
namespace internal {

Tagged<UnionOf<JSModuleNamespace, Undefined>> PrototypeInfo::module_namespace()
    const {
  return module_namespace_.load();
}
void PrototypeInfo::set_module_namespace(
    Tagged<UnionOf<JSModuleNamespace, Undefined>> value,
    WriteBarrierMode mode) {
  module_namespace_.store(this, value, mode);
}

Tagged<UnionOf<WeakArrayList, Zero>> PrototypeInfo::prototype_users() const {
  return prototype_users_.load();
}
void PrototypeInfo::set_prototype_users(
    Tagged<UnionOf<WeakArrayList, Zero>> value, WriteBarrierMode mode) {
  prototype_users_.store(this, value, mode);
}

Tagged<UnionOf<FixedArray, Zero, Undefined>>
PrototypeInfo::prototype_chain_enum_cache() const {
  return prototype_chain_enum_cache_.load();
}
void PrototypeInfo::set_prototype_chain_enum_cache(
    Tagged<UnionOf<FixedArray, Zero, Undefined>> value, WriteBarrierMode mode) {
  prototype_chain_enum_cache_.store(this, value, mode);
}

int PrototypeInfo::registry_slot() const {
  return registry_slot_.load().value();
}
void PrototypeInfo::set_registry_slot(int value) {
  registry_slot_.store(this, Smi::FromInt(value));
}

int PrototypeInfo::bit_field() const { return bit_field_.load().value(); }
void PrototypeInfo::set_bit_field(int value) {
  bit_field_.store(this, Smi::FromInt(value));
}

Tagged<UnionOf<WeakArrayList, Undefined>> PrototypeInfo::derived_maps() const {
  return derived_maps_.load();
}
Tagged<UnionOf<WeakArrayList, Undefined>> PrototypeInfo::derived_maps(
    AcquireLoadTag) const {
  return derived_maps_.Acquire_Load();
}
void PrototypeInfo::set_derived_maps(
    Tagged<UnionOf<WeakArrayList, Undefined>> value, WriteBarrierMode mode) {
  derived_maps_.store(this, value, mode);
}
void PrototypeInfo::set_derived_maps(
    Tagged<UnionOf<WeakArrayList, Undefined>> value, ReleaseStoreTag,
    WriteBarrierMode mode) {
  derived_maps_.Release_Store(this, value, mode);
}

Tagged<UnionOf<PrototypeSharedClosureInfo, Undefined>>
PrototypeInfo::prototype_shared_closure_info() const {
  return prototype_shared_closure_info_.load();
}
void PrototypeInfo::set_prototype_shared_closure_info(
    Tagged<UnionOf<PrototypeSharedClosureInfo, Undefined>> value,
    WriteBarrierMode mode) {
  prototype_shared_closure_info_.store(this, value, mode);
}

Tagged<UnionOf<LoadHandler, Zero>> PrototypeInfo::cached_handler(
    int index) const {
  DCHECK_GE(index, 0);
  DCHECK_LT(index, kCachedHandlerCount);
  return cached_handler_[index].load();
}
void PrototypeInfo::set_cached_handler(int index,
                                       Tagged<UnionOf<LoadHandler, Zero>> value,
                                       WriteBarrierMode mode) {
  DCHECK_GE(index, 0);
  DCHECK_LT(index, kCachedHandlerCount);
  cached_handler_[index].store(this, value, mode);
}

Tagged<MaybeObject> PrototypeInfo::ObjectCreateMap() {
  auto derived = derived_maps();
  if (IsUndefined(derived)) {
    return Tagged<MaybeObject>();
  }
  // Index 0 is the map for object create
  Tagged<WeakArrayList> derived_list = Cast<WeakArrayList>(derived);
  DCHECK_GT(derived_list->length().value(), 0);
  Tagged<MaybeObject> el = derived_list->Get(0);
  DCHECK(el.IsWeakOrCleared());
  return el;
}

Tagged<MaybeObject> PrototypeInfo::ObjectCreateMap(AcquireLoadTag tag) {
  auto derived = derived_maps(tag);
  if (IsUndefined(derived)) {
    return Tagged<MaybeObject>();
  }
  // Index 0 is the map for object create
  Tagged<WeakArrayList> derived_list = Cast<WeakArrayList>(derived);
  DCHECK_GT(derived_list->length().value(), 0);
  Tagged<MaybeObject> el = derived_list->get(0, kAcquireLoad);
  DCHECK(el.IsWeakOrCleared());
  return el;
}

// static
void PrototypeInfo::SetObjectCreateMap(DirectHandle<PrototypeInfo> info,
                                       DirectHandle<Map> map,
                                       Isolate* isolate) {
  if (IsUndefined(info->derived_maps())) {
    Tagged<WeakArrayList> derived = *isolate->factory()->NewWeakArrayList(1);
    derived->Set(0, MakeWeak(*map));
    derived->set_length(1);
    info->set_derived_maps(derived, kReleaseStore);
  } else {
    Tagged<WeakArrayList> derived = Cast<WeakArrayList>(info->derived_maps());
    DCHECK(derived->Get(0).IsCleared());
    DCHECK_GT(derived->length().value(), 0);
    derived->set(0, MakeWeak(*map), kReleaseStore);
  }
}

Tagged<MaybeObject> PrototypeInfo::GetDerivedMap(DirectHandle<Map> from) {
  if (IsUndefined(derived_maps())) {
    return Tagged<MaybeObject>();
  }
  auto derived = Cast<WeakArrayList>(derived_maps());
  const uint32_t derived_length = derived->length().value();
  // Index 0 is the map for object create
  for (uint32_t i = 1; i < derived_length; ++i) {
    Tagged<MaybeObject> el = derived->Get(i);
    Tagged<Map> map_obj;
    if (el.GetHeapObjectIfWeak(&map_obj)) {
      Tagged<Map> to = Cast<Map>(map_obj);
      if (to->GetConstructor() == from->GetConstructor() &&
          to->instance_type() == from->instance_type()) {
        return el;
      }
    }
  }
  return Tagged<MaybeObject>();
}

// static
void PrototypeInfo::AddDerivedMap(DirectHandle<PrototypeInfo> info,
                                  DirectHandle<Map> to, Isolate* isolate) {
  if (IsUndefined(info->derived_maps())) {
    // Index 0 is the map for object create
    Tagged<WeakArrayList> derived = *isolate->factory()->NewWeakArrayList(2);
    // GetConstructMap assumes a weak pointer.
    derived->Set(0, kClearedWeakValue);
    derived->Set(1, MakeWeak(*to));
    derived->set_length(2);
    info->set_derived_maps(derived, kReleaseStore);
    return;
  }
  auto derived = handle(Cast<WeakArrayList>(info->derived_maps()), isolate);
  const uint32_t derived_length = derived->length().value();
  // Index 0 is the map for object create
  uint32_t i = 1;
  for (; i < derived_length; ++i) {
    Tagged<MaybeObject> el = derived->Get(i);
    if (el.IsCleared()) {
      derived->Set(i, MakeWeak(*to));
      return;
    }
  }

  auto bigger = WeakArrayList::EnsureSpace(isolate, derived, i + 1);
  bigger->Set(i, MakeWeak(*to));
  bigger->set_length(i + 1);
  if (*bigger != *derived) {
    info->set_derived_maps(*bigger, kReleaseStore);
  }
}

BOOL_ACCESSORS(PrototypeInfo, bit_field, should_be_fast_map,
               ShouldBeFastBit::kShift)

// TODO(375937549): Convert index to uint32_t.
void PrototypeUsers::MarkSlotEmpty(Tagged<WeakArrayList> array, int index) {
  DCHECK_GT(index, 0);
  DCHECK_LT(static_cast<uint32_t>(index), array->length().value());
  // Chain the empty slots into a linked list (each empty slot contains the
  // index of the next empty slot).
  array->Set(index, empty_slot_index(array));
  set_empty_slot_index(array, index);
}

Tagged<Smi> PrototypeUsers::empty_slot_index(Tagged<WeakArrayList> array) {
  return array->Get(kEmptySlotIndex).ToSmi();
}

void PrototypeUsers::set_empty_slot_index(Tagged<WeakArrayList> array,
                                          int index) {
  array->Set(kEmptySlotIndex, Smi::FromInt(index));
}

}  // namespace internal
}  // namespace v8

#include "src/objects/object-macros-undef.h"

#endif  // V8_OBJECTS_PROTOTYPE_INFO_INL_H_