11cb0ef41Sopenharmony_ci
21cb0ef41Sopenharmony_ci// Copyright 2015 the V8 project authors. All rights reserved.
31cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
41cb0ef41Sopenharmony_ci// found in the LICENSE file.
51cb0ef41Sopenharmony_ci
61cb0ef41Sopenharmony_ci#include "src/compiler/access-info.h"
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_ci#include <ostream>
91cb0ef41Sopenharmony_ci
101cb0ef41Sopenharmony_ci#include "src/builtins/accessors.h"
111cb0ef41Sopenharmony_ci#include "src/compiler/compilation-dependencies.h"
121cb0ef41Sopenharmony_ci#include "src/compiler/simplified-operator.h"
131cb0ef41Sopenharmony_ci#include "src/compiler/type-cache.h"
141cb0ef41Sopenharmony_ci#include "src/ic/call-optimization.h"
151cb0ef41Sopenharmony_ci#include "src/ic/handler-configuration.h"
161cb0ef41Sopenharmony_ci#include "src/logging/counters.h"
171cb0ef41Sopenharmony_ci#include "src/objects/cell-inl.h"
181cb0ef41Sopenharmony_ci#include "src/objects/field-index-inl.h"
191cb0ef41Sopenharmony_ci#include "src/objects/field-type.h"
201cb0ef41Sopenharmony_ci#include "src/objects/module-inl.h"
211cb0ef41Sopenharmony_ci#include "src/objects/objects-inl.h"
221cb0ef41Sopenharmony_ci#include "src/objects/struct-inl.h"
231cb0ef41Sopenharmony_ci#include "src/objects/templates.h"
241cb0ef41Sopenharmony_ci
251cb0ef41Sopenharmony_cinamespace v8 {
261cb0ef41Sopenharmony_cinamespace internal {
271cb0ef41Sopenharmony_cinamespace compiler {
281cb0ef41Sopenharmony_ci
291cb0ef41Sopenharmony_cinamespace {
301cb0ef41Sopenharmony_ci
311cb0ef41Sopenharmony_cibool CanInlinePropertyAccess(MapRef map, AccessMode access_mode) {
321cb0ef41Sopenharmony_ci  // We can inline property access to prototypes of all primitives, except
331cb0ef41Sopenharmony_ci  // the special Oddball ones that have no wrapper counterparts (i.e. Null,
341cb0ef41Sopenharmony_ci  // Undefined and TheHole).
351cb0ef41Sopenharmony_ci  // We can only inline accesses to dictionary mode holders if the access is a
361cb0ef41Sopenharmony_ci  // load and the holder is a prototype. The latter ensures a 1:1
371cb0ef41Sopenharmony_ci  // relationship between the map and the object (and therefore the property
381cb0ef41Sopenharmony_ci  // dictionary).
391cb0ef41Sopenharmony_ci  STATIC_ASSERT(ODDBALL_TYPE == LAST_PRIMITIVE_HEAP_OBJECT_TYPE);
401cb0ef41Sopenharmony_ci  if (map.object()->IsBooleanMap()) return true;
411cb0ef41Sopenharmony_ci  if (map.instance_type() < LAST_PRIMITIVE_HEAP_OBJECT_TYPE) return true;
421cb0ef41Sopenharmony_ci  if (map.object()->IsJSObjectMap()) {
431cb0ef41Sopenharmony_ci    if (map.is_dictionary_map()) {
441cb0ef41Sopenharmony_ci      if (!V8_DICT_PROPERTY_CONST_TRACKING_BOOL) return false;
451cb0ef41Sopenharmony_ci      return access_mode == AccessMode::kLoad &&
461cb0ef41Sopenharmony_ci             map.object()->is_prototype_map();
471cb0ef41Sopenharmony_ci    }
481cb0ef41Sopenharmony_ci    return !map.object()->has_named_interceptor() &&
491cb0ef41Sopenharmony_ci           // TODO(verwaest): Allowlist contexts to which we have access.
501cb0ef41Sopenharmony_ci           !map.is_access_check_needed();
511cb0ef41Sopenharmony_ci  }
521cb0ef41Sopenharmony_ci  return false;
531cb0ef41Sopenharmony_ci}
541cb0ef41Sopenharmony_ci
551cb0ef41Sopenharmony_ci#ifdef DEBUG
561cb0ef41Sopenharmony_cibool HasFieldRepresentationDependenciesOnMap(
571cb0ef41Sopenharmony_ci    ZoneVector<CompilationDependency const*>& dependencies,
581cb0ef41Sopenharmony_ci    Handle<Map> const& field_owner_map) {
591cb0ef41Sopenharmony_ci  for (auto dep : dependencies) {
601cb0ef41Sopenharmony_ci    if (CompilationDependencies::IsFieldRepresentationDependencyOnMap(
611cb0ef41Sopenharmony_ci            dep, field_owner_map)) {
621cb0ef41Sopenharmony_ci      return true;
631cb0ef41Sopenharmony_ci    }
641cb0ef41Sopenharmony_ci  }
651cb0ef41Sopenharmony_ci  return false;
661cb0ef41Sopenharmony_ci}
671cb0ef41Sopenharmony_ci#endif
681cb0ef41Sopenharmony_ci
691cb0ef41Sopenharmony_ci}  // namespace
701cb0ef41Sopenharmony_ci
711cb0ef41Sopenharmony_ci
721cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream& os, AccessMode access_mode) {
731cb0ef41Sopenharmony_ci  switch (access_mode) {
741cb0ef41Sopenharmony_ci    case AccessMode::kLoad:
751cb0ef41Sopenharmony_ci      return os << "Load";
761cb0ef41Sopenharmony_ci    case AccessMode::kStore:
771cb0ef41Sopenharmony_ci      return os << "Store";
781cb0ef41Sopenharmony_ci    case AccessMode::kStoreInLiteral:
791cb0ef41Sopenharmony_ci      return os << "StoreInLiteral";
801cb0ef41Sopenharmony_ci    case AccessMode::kHas:
811cb0ef41Sopenharmony_ci      return os << "Has";
821cb0ef41Sopenharmony_ci    case AccessMode::kDefine:
831cb0ef41Sopenharmony_ci      return os << "Define";
841cb0ef41Sopenharmony_ci  }
851cb0ef41Sopenharmony_ci  UNREACHABLE();
861cb0ef41Sopenharmony_ci}
871cb0ef41Sopenharmony_ci
881cb0ef41Sopenharmony_ciElementAccessInfo::ElementAccessInfo(
891cb0ef41Sopenharmony_ci    ZoneVector<MapRef>&& lookup_start_object_maps, ElementsKind elements_kind,
901cb0ef41Sopenharmony_ci    Zone* zone)
911cb0ef41Sopenharmony_ci    : elements_kind_(elements_kind),
921cb0ef41Sopenharmony_ci      lookup_start_object_maps_(lookup_start_object_maps),
931cb0ef41Sopenharmony_ci      transition_sources_(zone) {
941cb0ef41Sopenharmony_ci  CHECK(!lookup_start_object_maps.empty());
951cb0ef41Sopenharmony_ci}
961cb0ef41Sopenharmony_ci
971cb0ef41Sopenharmony_ci// static
981cb0ef41Sopenharmony_ciPropertyAccessInfo PropertyAccessInfo::Invalid(Zone* zone) {
991cb0ef41Sopenharmony_ci  return PropertyAccessInfo(zone);
1001cb0ef41Sopenharmony_ci}
1011cb0ef41Sopenharmony_ci
1021cb0ef41Sopenharmony_ci// static
1031cb0ef41Sopenharmony_ciPropertyAccessInfo PropertyAccessInfo::NotFound(
1041cb0ef41Sopenharmony_ci    Zone* zone, MapRef receiver_map, base::Optional<JSObjectRef> holder) {
1051cb0ef41Sopenharmony_ci  return PropertyAccessInfo(zone, kNotFound, holder, {{receiver_map}, zone});
1061cb0ef41Sopenharmony_ci}
1071cb0ef41Sopenharmony_ci
1081cb0ef41Sopenharmony_ci// static
1091cb0ef41Sopenharmony_ciPropertyAccessInfo PropertyAccessInfo::DataField(
1101cb0ef41Sopenharmony_ci    Zone* zone, MapRef receiver_map,
1111cb0ef41Sopenharmony_ci    ZoneVector<CompilationDependency const*>&& dependencies,
1121cb0ef41Sopenharmony_ci    FieldIndex field_index, Representation field_representation,
1131cb0ef41Sopenharmony_ci    Type field_type, MapRef field_owner_map, base::Optional<MapRef> field_map,
1141cb0ef41Sopenharmony_ci    base::Optional<JSObjectRef> holder, base::Optional<MapRef> transition_map) {
1151cb0ef41Sopenharmony_ci  DCHECK(!field_representation.IsNone());
1161cb0ef41Sopenharmony_ci  DCHECK_IMPLIES(
1171cb0ef41Sopenharmony_ci      field_representation.IsDouble(),
1181cb0ef41Sopenharmony_ci      HasFieldRepresentationDependenciesOnMap(
1191cb0ef41Sopenharmony_ci          dependencies, transition_map.has_value()
1201cb0ef41Sopenharmony_ci                            ? transition_map->object()
1211cb0ef41Sopenharmony_ci                            : holder.has_value() ? holder->map().object()
1221cb0ef41Sopenharmony_ci                                                 : receiver_map.object()));
1231cb0ef41Sopenharmony_ci  return PropertyAccessInfo(kDataField, holder, transition_map, field_index,
1241cb0ef41Sopenharmony_ci                            field_representation, field_type, field_owner_map,
1251cb0ef41Sopenharmony_ci                            field_map, {{receiver_map}, zone},
1261cb0ef41Sopenharmony_ci                            std::move(dependencies));
1271cb0ef41Sopenharmony_ci}
1281cb0ef41Sopenharmony_ci
1291cb0ef41Sopenharmony_ci// static
1301cb0ef41Sopenharmony_ciPropertyAccessInfo PropertyAccessInfo::FastDataConstant(
1311cb0ef41Sopenharmony_ci    Zone* zone, MapRef receiver_map,
1321cb0ef41Sopenharmony_ci    ZoneVector<CompilationDependency const*>&& dependencies,
1331cb0ef41Sopenharmony_ci    FieldIndex field_index, Representation field_representation,
1341cb0ef41Sopenharmony_ci    Type field_type, MapRef field_owner_map, base::Optional<MapRef> field_map,
1351cb0ef41Sopenharmony_ci    base::Optional<JSObjectRef> holder, base::Optional<MapRef> transition_map) {
1361cb0ef41Sopenharmony_ci  DCHECK(!field_representation.IsNone());
1371cb0ef41Sopenharmony_ci  return PropertyAccessInfo(kFastDataConstant, holder, transition_map,
1381cb0ef41Sopenharmony_ci                            field_index, field_representation, field_type,
1391cb0ef41Sopenharmony_ci                            field_owner_map, field_map, {{receiver_map}, zone},
1401cb0ef41Sopenharmony_ci                            std::move(dependencies));
1411cb0ef41Sopenharmony_ci}
1421cb0ef41Sopenharmony_ci
1431cb0ef41Sopenharmony_ci// static
1441cb0ef41Sopenharmony_ciPropertyAccessInfo PropertyAccessInfo::FastAccessorConstant(
1451cb0ef41Sopenharmony_ci    Zone* zone, MapRef receiver_map, base::Optional<ObjectRef> constant,
1461cb0ef41Sopenharmony_ci    base::Optional<JSObjectRef> holder) {
1471cb0ef41Sopenharmony_ci  return PropertyAccessInfo(zone, kFastAccessorConstant, holder, constant, {},
1481cb0ef41Sopenharmony_ci                            {{receiver_map}, zone});
1491cb0ef41Sopenharmony_ci}
1501cb0ef41Sopenharmony_ci
1511cb0ef41Sopenharmony_ci// static
1521cb0ef41Sopenharmony_ciPropertyAccessInfo PropertyAccessInfo::ModuleExport(Zone* zone,
1531cb0ef41Sopenharmony_ci                                                    MapRef receiver_map,
1541cb0ef41Sopenharmony_ci                                                    CellRef cell) {
1551cb0ef41Sopenharmony_ci  return PropertyAccessInfo(zone, kModuleExport, {}, cell, {},
1561cb0ef41Sopenharmony_ci                            {{receiver_map}, zone});
1571cb0ef41Sopenharmony_ci}
1581cb0ef41Sopenharmony_ci
1591cb0ef41Sopenharmony_ci// static
1601cb0ef41Sopenharmony_ciPropertyAccessInfo PropertyAccessInfo::StringLength(Zone* zone,
1611cb0ef41Sopenharmony_ci                                                    MapRef receiver_map) {
1621cb0ef41Sopenharmony_ci  return PropertyAccessInfo(zone, kStringLength, {}, {{receiver_map}, zone});
1631cb0ef41Sopenharmony_ci}
1641cb0ef41Sopenharmony_ci
1651cb0ef41Sopenharmony_ci// static
1661cb0ef41Sopenharmony_ciPropertyAccessInfo PropertyAccessInfo::DictionaryProtoDataConstant(
1671cb0ef41Sopenharmony_ci    Zone* zone, MapRef receiver_map, JSObjectRef holder,
1681cb0ef41Sopenharmony_ci    InternalIndex dictionary_index, NameRef name) {
1691cb0ef41Sopenharmony_ci  return PropertyAccessInfo(zone, kDictionaryProtoDataConstant, holder,
1701cb0ef41Sopenharmony_ci                            {{receiver_map}, zone}, dictionary_index, name);
1711cb0ef41Sopenharmony_ci}
1721cb0ef41Sopenharmony_ci
1731cb0ef41Sopenharmony_ci// static
1741cb0ef41Sopenharmony_ciPropertyAccessInfo PropertyAccessInfo::DictionaryProtoAccessorConstant(
1751cb0ef41Sopenharmony_ci    Zone* zone, MapRef receiver_map, base::Optional<JSObjectRef> holder,
1761cb0ef41Sopenharmony_ci    ObjectRef constant, NameRef property_name) {
1771cb0ef41Sopenharmony_ci  return PropertyAccessInfo(zone, kDictionaryProtoAccessorConstant, holder,
1781cb0ef41Sopenharmony_ci                            constant, property_name, {{receiver_map}, zone});
1791cb0ef41Sopenharmony_ci}
1801cb0ef41Sopenharmony_ci
1811cb0ef41Sopenharmony_ciPropertyAccessInfo::PropertyAccessInfo(Zone* zone)
1821cb0ef41Sopenharmony_ci    : kind_(kInvalid),
1831cb0ef41Sopenharmony_ci      lookup_start_object_maps_(zone),
1841cb0ef41Sopenharmony_ci      unrecorded_dependencies_(zone),
1851cb0ef41Sopenharmony_ci      field_representation_(Representation::None()),
1861cb0ef41Sopenharmony_ci      field_type_(Type::None()),
1871cb0ef41Sopenharmony_ci      dictionary_index_(InternalIndex::NotFound()) {}
1881cb0ef41Sopenharmony_ci
1891cb0ef41Sopenharmony_ciPropertyAccessInfo::PropertyAccessInfo(
1901cb0ef41Sopenharmony_ci    Zone* zone, Kind kind, base::Optional<JSObjectRef> holder,
1911cb0ef41Sopenharmony_ci    ZoneVector<MapRef>&& lookup_start_object_maps)
1921cb0ef41Sopenharmony_ci    : kind_(kind),
1931cb0ef41Sopenharmony_ci      lookup_start_object_maps_(lookup_start_object_maps),
1941cb0ef41Sopenharmony_ci      holder_(holder),
1951cb0ef41Sopenharmony_ci      unrecorded_dependencies_(zone),
1961cb0ef41Sopenharmony_ci      field_representation_(Representation::None()),
1971cb0ef41Sopenharmony_ci      field_type_(Type::None()),
1981cb0ef41Sopenharmony_ci      dictionary_index_(InternalIndex::NotFound()) {}
1991cb0ef41Sopenharmony_ci
2001cb0ef41Sopenharmony_ciPropertyAccessInfo::PropertyAccessInfo(
2011cb0ef41Sopenharmony_ci    Zone* zone, Kind kind, base::Optional<JSObjectRef> holder,
2021cb0ef41Sopenharmony_ci    base::Optional<ObjectRef> constant, base::Optional<NameRef> name,
2031cb0ef41Sopenharmony_ci    ZoneVector<MapRef>&& lookup_start_object_maps)
2041cb0ef41Sopenharmony_ci    : kind_(kind),
2051cb0ef41Sopenharmony_ci      lookup_start_object_maps_(lookup_start_object_maps),
2061cb0ef41Sopenharmony_ci      constant_(constant),
2071cb0ef41Sopenharmony_ci      holder_(holder),
2081cb0ef41Sopenharmony_ci      unrecorded_dependencies_(zone),
2091cb0ef41Sopenharmony_ci      field_representation_(Representation::None()),
2101cb0ef41Sopenharmony_ci      field_type_(Type::Any()),
2111cb0ef41Sopenharmony_ci      dictionary_index_(InternalIndex::NotFound()),
2121cb0ef41Sopenharmony_ci      name_(name) {
2131cb0ef41Sopenharmony_ci  DCHECK_IMPLIES(kind == kDictionaryProtoAccessorConstant, name.has_value());
2141cb0ef41Sopenharmony_ci}
2151cb0ef41Sopenharmony_ci
2161cb0ef41Sopenharmony_ciPropertyAccessInfo::PropertyAccessInfo(
2171cb0ef41Sopenharmony_ci    Kind kind, base::Optional<JSObjectRef> holder,
2181cb0ef41Sopenharmony_ci    base::Optional<MapRef> transition_map, FieldIndex field_index,
2191cb0ef41Sopenharmony_ci    Representation field_representation, Type field_type,
2201cb0ef41Sopenharmony_ci    MapRef field_owner_map, base::Optional<MapRef> field_map,
2211cb0ef41Sopenharmony_ci    ZoneVector<MapRef>&& lookup_start_object_maps,
2221cb0ef41Sopenharmony_ci    ZoneVector<CompilationDependency const*>&& unrecorded_dependencies)
2231cb0ef41Sopenharmony_ci    : kind_(kind),
2241cb0ef41Sopenharmony_ci      lookup_start_object_maps_(lookup_start_object_maps),
2251cb0ef41Sopenharmony_ci      holder_(holder),
2261cb0ef41Sopenharmony_ci      unrecorded_dependencies_(std::move(unrecorded_dependencies)),
2271cb0ef41Sopenharmony_ci      transition_map_(transition_map),
2281cb0ef41Sopenharmony_ci      field_index_(field_index),
2291cb0ef41Sopenharmony_ci      field_representation_(field_representation),
2301cb0ef41Sopenharmony_ci      field_type_(field_type),
2311cb0ef41Sopenharmony_ci      field_owner_map_(field_owner_map),
2321cb0ef41Sopenharmony_ci      field_map_(field_map),
2331cb0ef41Sopenharmony_ci      dictionary_index_(InternalIndex::NotFound()) {
2341cb0ef41Sopenharmony_ci  DCHECK_IMPLIES(transition_map.has_value(),
2351cb0ef41Sopenharmony_ci                 field_owner_map.equals(transition_map.value()));
2361cb0ef41Sopenharmony_ci}
2371cb0ef41Sopenharmony_ci
2381cb0ef41Sopenharmony_ciPropertyAccessInfo::PropertyAccessInfo(
2391cb0ef41Sopenharmony_ci    Zone* zone, Kind kind, base::Optional<JSObjectRef> holder,
2401cb0ef41Sopenharmony_ci    ZoneVector<MapRef>&& lookup_start_object_maps,
2411cb0ef41Sopenharmony_ci    InternalIndex dictionary_index, NameRef name)
2421cb0ef41Sopenharmony_ci    : kind_(kind),
2431cb0ef41Sopenharmony_ci      lookup_start_object_maps_(lookup_start_object_maps),
2441cb0ef41Sopenharmony_ci      holder_(holder),
2451cb0ef41Sopenharmony_ci      unrecorded_dependencies_(zone),
2461cb0ef41Sopenharmony_ci      field_representation_(Representation::None()),
2471cb0ef41Sopenharmony_ci      field_type_(Type::Any()),
2481cb0ef41Sopenharmony_ci      dictionary_index_(dictionary_index),
2491cb0ef41Sopenharmony_ci      name_{name} {}
2501cb0ef41Sopenharmony_ci
2511cb0ef41Sopenharmony_cinamespace {
2521cb0ef41Sopenharmony_ci
2531cb0ef41Sopenharmony_citemplate <class RefT>
2541cb0ef41Sopenharmony_cibool OptionalRefEquals(base::Optional<RefT> lhs, base::Optional<RefT> rhs) {
2551cb0ef41Sopenharmony_ci  if (!lhs.has_value()) return !rhs.has_value();
2561cb0ef41Sopenharmony_ci  if (!rhs.has_value()) return false;
2571cb0ef41Sopenharmony_ci  return lhs->equals(rhs.value());
2581cb0ef41Sopenharmony_ci}
2591cb0ef41Sopenharmony_ci
2601cb0ef41Sopenharmony_citemplate <class T>
2611cb0ef41Sopenharmony_civoid AppendVector(ZoneVector<T>* dst, const ZoneVector<T>& src) {
2621cb0ef41Sopenharmony_ci  dst->insert(dst->end(), src.begin(), src.end());
2631cb0ef41Sopenharmony_ci}
2641cb0ef41Sopenharmony_ci
2651cb0ef41Sopenharmony_ci}  // namespace
2661cb0ef41Sopenharmony_ci
2671cb0ef41Sopenharmony_cibool PropertyAccessInfo::Merge(PropertyAccessInfo const* that,
2681cb0ef41Sopenharmony_ci                               AccessMode access_mode, Zone* zone) {
2691cb0ef41Sopenharmony_ci  if (kind_ != that->kind_) return false;
2701cb0ef41Sopenharmony_ci  if (!OptionalRefEquals(holder_, that->holder_)) return false;
2711cb0ef41Sopenharmony_ci
2721cb0ef41Sopenharmony_ci  switch (kind_) {
2731cb0ef41Sopenharmony_ci    case kInvalid:
2741cb0ef41Sopenharmony_ci      DCHECK_EQ(that->kind_, kInvalid);
2751cb0ef41Sopenharmony_ci      return true;
2761cb0ef41Sopenharmony_ci
2771cb0ef41Sopenharmony_ci    case kDataField:
2781cb0ef41Sopenharmony_ci    case kFastDataConstant: {
2791cb0ef41Sopenharmony_ci      // Check if we actually access the same field (we use the
2801cb0ef41Sopenharmony_ci      // GetFieldAccessStubKey method here just like the ICs do
2811cb0ef41Sopenharmony_ci      // since that way we only compare the relevant bits of the
2821cb0ef41Sopenharmony_ci      // field indices).
2831cb0ef41Sopenharmony_ci      if (field_index_.GetFieldAccessStubKey() !=
2841cb0ef41Sopenharmony_ci          that->field_index_.GetFieldAccessStubKey()) {
2851cb0ef41Sopenharmony_ci        return false;
2861cb0ef41Sopenharmony_ci      }
2871cb0ef41Sopenharmony_ci
2881cb0ef41Sopenharmony_ci      switch (access_mode) {
2891cb0ef41Sopenharmony_ci        case AccessMode::kHas:
2901cb0ef41Sopenharmony_ci        case AccessMode::kLoad: {
2911cb0ef41Sopenharmony_ci          if (!field_representation_.Equals(that->field_representation_)) {
2921cb0ef41Sopenharmony_ci            if (field_representation_.IsDouble() ||
2931cb0ef41Sopenharmony_ci                that->field_representation_.IsDouble()) {
2941cb0ef41Sopenharmony_ci              return false;
2951cb0ef41Sopenharmony_ci            }
2961cb0ef41Sopenharmony_ci            field_representation_ = Representation::Tagged();
2971cb0ef41Sopenharmony_ci          }
2981cb0ef41Sopenharmony_ci          if (!OptionalRefEquals(field_map_, that->field_map_)) {
2991cb0ef41Sopenharmony_ci            field_map_ = {};
3001cb0ef41Sopenharmony_ci          }
3011cb0ef41Sopenharmony_ci          break;
3021cb0ef41Sopenharmony_ci        }
3031cb0ef41Sopenharmony_ci        case AccessMode::kStore:
3041cb0ef41Sopenharmony_ci        case AccessMode::kStoreInLiteral:
3051cb0ef41Sopenharmony_ci        case AccessMode::kDefine: {
3061cb0ef41Sopenharmony_ci          // For stores, the field map and field representation information
3071cb0ef41Sopenharmony_ci          // must match exactly, otherwise we cannot merge the stores. We
3081cb0ef41Sopenharmony_ci          // also need to make sure that in case of transitioning stores,
3091cb0ef41Sopenharmony_ci          // the transition targets match.
3101cb0ef41Sopenharmony_ci          if (!OptionalRefEquals(field_map_, that->field_map_) ||
3111cb0ef41Sopenharmony_ci              !field_representation_.Equals(that->field_representation_) ||
3121cb0ef41Sopenharmony_ci              !OptionalRefEquals(transition_map_, that->transition_map_)) {
3131cb0ef41Sopenharmony_ci            return false;
3141cb0ef41Sopenharmony_ci          }
3151cb0ef41Sopenharmony_ci          break;
3161cb0ef41Sopenharmony_ci        }
3171cb0ef41Sopenharmony_ci      }
3181cb0ef41Sopenharmony_ci
3191cb0ef41Sopenharmony_ci      field_type_ = Type::Union(field_type_, that->field_type_, zone);
3201cb0ef41Sopenharmony_ci      AppendVector(&lookup_start_object_maps_, that->lookup_start_object_maps_);
3211cb0ef41Sopenharmony_ci      AppendVector(&unrecorded_dependencies_, that->unrecorded_dependencies_);
3221cb0ef41Sopenharmony_ci      return true;
3231cb0ef41Sopenharmony_ci    }
3241cb0ef41Sopenharmony_ci
3251cb0ef41Sopenharmony_ci    case kDictionaryProtoAccessorConstant:
3261cb0ef41Sopenharmony_ci    case kFastAccessorConstant: {
3271cb0ef41Sopenharmony_ci      // Check if we actually access the same constant.
3281cb0ef41Sopenharmony_ci      if (!OptionalRefEquals(constant_, that->constant_)) return false;
3291cb0ef41Sopenharmony_ci
3301cb0ef41Sopenharmony_ci      DCHECK(unrecorded_dependencies_.empty());
3311cb0ef41Sopenharmony_ci      DCHECK(that->unrecorded_dependencies_.empty());
3321cb0ef41Sopenharmony_ci      AppendVector(&lookup_start_object_maps_, that->lookup_start_object_maps_);
3331cb0ef41Sopenharmony_ci      return true;
3341cb0ef41Sopenharmony_ci    }
3351cb0ef41Sopenharmony_ci
3361cb0ef41Sopenharmony_ci    case kDictionaryProtoDataConstant: {
3371cb0ef41Sopenharmony_ci      DCHECK_EQ(AccessMode::kLoad, access_mode);
3381cb0ef41Sopenharmony_ci      if (dictionary_index_ != that->dictionary_index_) return false;
3391cb0ef41Sopenharmony_ci      AppendVector(&lookup_start_object_maps_, that->lookup_start_object_maps_);
3401cb0ef41Sopenharmony_ci      return true;
3411cb0ef41Sopenharmony_ci    }
3421cb0ef41Sopenharmony_ci
3431cb0ef41Sopenharmony_ci    case kNotFound:
3441cb0ef41Sopenharmony_ci    case kStringLength: {
3451cb0ef41Sopenharmony_ci      DCHECK(unrecorded_dependencies_.empty());
3461cb0ef41Sopenharmony_ci      DCHECK(that->unrecorded_dependencies_.empty());
3471cb0ef41Sopenharmony_ci      AppendVector(&lookup_start_object_maps_, that->lookup_start_object_maps_);
3481cb0ef41Sopenharmony_ci      return true;
3491cb0ef41Sopenharmony_ci    }
3501cb0ef41Sopenharmony_ci    case kModuleExport:
3511cb0ef41Sopenharmony_ci      return false;
3521cb0ef41Sopenharmony_ci  }
3531cb0ef41Sopenharmony_ci}
3541cb0ef41Sopenharmony_ci
3551cb0ef41Sopenharmony_ciConstFieldInfo PropertyAccessInfo::GetConstFieldInfo() const {
3561cb0ef41Sopenharmony_ci  return IsFastDataConstant() ? ConstFieldInfo(field_owner_map_->object())
3571cb0ef41Sopenharmony_ci                              : ConstFieldInfo::None();
3581cb0ef41Sopenharmony_ci}
3591cb0ef41Sopenharmony_ci
3601cb0ef41Sopenharmony_ciAccessInfoFactory::AccessInfoFactory(JSHeapBroker* broker,
3611cb0ef41Sopenharmony_ci                                     CompilationDependencies* dependencies,
3621cb0ef41Sopenharmony_ci                                     Zone* zone)
3631cb0ef41Sopenharmony_ci    : broker_(broker),
3641cb0ef41Sopenharmony_ci      dependencies_(dependencies),
3651cb0ef41Sopenharmony_ci      type_cache_(TypeCache::Get()),
3661cb0ef41Sopenharmony_ci      zone_(zone) {}
3671cb0ef41Sopenharmony_ci
3681cb0ef41Sopenharmony_cibase::Optional<ElementAccessInfo> AccessInfoFactory::ComputeElementAccessInfo(
3691cb0ef41Sopenharmony_ci    MapRef map, AccessMode access_mode) const {
3701cb0ef41Sopenharmony_ci  if (!map.CanInlineElementAccess()) return {};
3711cb0ef41Sopenharmony_ci  return ElementAccessInfo({{map}, zone()}, map.elements_kind(), zone());
3721cb0ef41Sopenharmony_ci}
3731cb0ef41Sopenharmony_ci
3741cb0ef41Sopenharmony_cibool AccessInfoFactory::ComputeElementAccessInfos(
3751cb0ef41Sopenharmony_ci    ElementAccessFeedback const& feedback,
3761cb0ef41Sopenharmony_ci    ZoneVector<ElementAccessInfo>* access_infos) const {
3771cb0ef41Sopenharmony_ci  AccessMode access_mode = feedback.keyed_mode().access_mode();
3781cb0ef41Sopenharmony_ci  if (access_mode == AccessMode::kLoad || access_mode == AccessMode::kHas) {
3791cb0ef41Sopenharmony_ci    // For polymorphic loads of similar elements kinds (i.e. all tagged or all
3801cb0ef41Sopenharmony_ci    // double), always use the "worst case" code without a transition.  This is
3811cb0ef41Sopenharmony_ci    // much faster than transitioning the elements to the worst case, trading a
3821cb0ef41Sopenharmony_ci    // TransitionElementsKind for a CheckMaps, avoiding mutation of the array.
3831cb0ef41Sopenharmony_ci    base::Optional<ElementAccessInfo> access_info =
3841cb0ef41Sopenharmony_ci        ConsolidateElementLoad(feedback);
3851cb0ef41Sopenharmony_ci    if (access_info.has_value()) {
3861cb0ef41Sopenharmony_ci      access_infos->push_back(*access_info);
3871cb0ef41Sopenharmony_ci      return true;
3881cb0ef41Sopenharmony_ci    }
3891cb0ef41Sopenharmony_ci  }
3901cb0ef41Sopenharmony_ci
3911cb0ef41Sopenharmony_ci  for (auto const& group : feedback.transition_groups()) {
3921cb0ef41Sopenharmony_ci    DCHECK(!group.empty());
3931cb0ef41Sopenharmony_ci    base::Optional<MapRef> target =
3941cb0ef41Sopenharmony_ci        MakeRefAssumeMemoryFence(broker(), group.front());
3951cb0ef41Sopenharmony_ci    base::Optional<ElementAccessInfo> access_info =
3961cb0ef41Sopenharmony_ci        ComputeElementAccessInfo(target.value(), access_mode);
3971cb0ef41Sopenharmony_ci    if (!access_info.has_value()) return false;
3981cb0ef41Sopenharmony_ci
3991cb0ef41Sopenharmony_ci    for (size_t i = 1; i < group.size(); ++i) {
4001cb0ef41Sopenharmony_ci      base::Optional<MapRef> map_ref =
4011cb0ef41Sopenharmony_ci          MakeRefAssumeMemoryFence(broker(), group[i]);
4021cb0ef41Sopenharmony_ci      if (!map_ref.has_value()) continue;
4031cb0ef41Sopenharmony_ci      access_info->AddTransitionSource(map_ref.value());
4041cb0ef41Sopenharmony_ci    }
4051cb0ef41Sopenharmony_ci    access_infos->push_back(*access_info);
4061cb0ef41Sopenharmony_ci  }
4071cb0ef41Sopenharmony_ci  return true;
4081cb0ef41Sopenharmony_ci}
4091cb0ef41Sopenharmony_ci
4101cb0ef41Sopenharmony_ciPropertyAccessInfo AccessInfoFactory::ComputeDataFieldAccessInfo(
4111cb0ef41Sopenharmony_ci    MapRef receiver_map, MapRef map, NameRef name,
4121cb0ef41Sopenharmony_ci    base::Optional<JSObjectRef> holder, InternalIndex descriptor,
4131cb0ef41Sopenharmony_ci    AccessMode access_mode) const {
4141cb0ef41Sopenharmony_ci  DCHECK(descriptor.is_found());
4151cb0ef41Sopenharmony_ci  // TODO(jgruber,v8:7790): Use DescriptorArrayRef instead.
4161cb0ef41Sopenharmony_ci  Handle<DescriptorArray> descriptors = map.instance_descriptors().object();
4171cb0ef41Sopenharmony_ci  PropertyDetails const details = descriptors->GetDetails(descriptor);
4181cb0ef41Sopenharmony_ci  int index = descriptors->GetFieldIndex(descriptor);
4191cb0ef41Sopenharmony_ci  Representation details_representation = details.representation();
4201cb0ef41Sopenharmony_ci  if (details_representation.IsNone()) {
4211cb0ef41Sopenharmony_ci    // The ICs collect feedback in PREMONOMORPHIC state already,
4221cb0ef41Sopenharmony_ci    // but at this point the {receiver_map} might still contain
4231cb0ef41Sopenharmony_ci    // fields for which the representation has not yet been
4241cb0ef41Sopenharmony_ci    // determined by the runtime. So we need to catch this case
4251cb0ef41Sopenharmony_ci    // here and fall back to use the regular IC logic instead.
4261cb0ef41Sopenharmony_ci    return Invalid();
4271cb0ef41Sopenharmony_ci  }
4281cb0ef41Sopenharmony_ci  FieldIndex field_index = FieldIndex::ForPropertyIndex(*map.object(), index,
4291cb0ef41Sopenharmony_ci                                                        details_representation);
4301cb0ef41Sopenharmony_ci  // Private brands are used when loading private methods, which are stored in a
4311cb0ef41Sopenharmony_ci  // BlockContext, an internal object.
4321cb0ef41Sopenharmony_ci  Type field_type = name.object()->IsPrivateBrand() ? Type::OtherInternal()
4331cb0ef41Sopenharmony_ci                                                    : Type::NonInternal();
4341cb0ef41Sopenharmony_ci  base::Optional<MapRef> field_map;
4351cb0ef41Sopenharmony_ci
4361cb0ef41Sopenharmony_ci  ZoneVector<CompilationDependency const*> unrecorded_dependencies(zone());
4371cb0ef41Sopenharmony_ci
4381cb0ef41Sopenharmony_ci  Handle<FieldType> descriptors_field_type =
4391cb0ef41Sopenharmony_ci      broker()->CanonicalPersistentHandle(
4401cb0ef41Sopenharmony_ci          descriptors->GetFieldType(descriptor));
4411cb0ef41Sopenharmony_ci  base::Optional<ObjectRef> descriptors_field_type_ref =
4421cb0ef41Sopenharmony_ci      TryMakeRef<Object>(broker(), descriptors_field_type);
4431cb0ef41Sopenharmony_ci  if (!descriptors_field_type_ref.has_value()) return Invalid();
4441cb0ef41Sopenharmony_ci
4451cb0ef41Sopenharmony_ci  if (details_representation.IsSmi()) {
4461cb0ef41Sopenharmony_ci    field_type = Type::SignedSmall();
4471cb0ef41Sopenharmony_ci    unrecorded_dependencies.push_back(
4481cb0ef41Sopenharmony_ci        dependencies()->FieldRepresentationDependencyOffTheRecord(
4491cb0ef41Sopenharmony_ci            map, descriptor, details_representation));
4501cb0ef41Sopenharmony_ci  } else if (details_representation.IsDouble()) {
4511cb0ef41Sopenharmony_ci    field_type = type_cache_->kFloat64;
4521cb0ef41Sopenharmony_ci    unrecorded_dependencies.push_back(
4531cb0ef41Sopenharmony_ci        dependencies()->FieldRepresentationDependencyOffTheRecord(
4541cb0ef41Sopenharmony_ci            map, descriptor, details_representation));
4551cb0ef41Sopenharmony_ci  } else if (details_representation.IsHeapObject()) {
4561cb0ef41Sopenharmony_ci    if (descriptors_field_type->IsNone()) {
4571cb0ef41Sopenharmony_ci      switch (access_mode) {
4581cb0ef41Sopenharmony_ci        case AccessMode::kStore:
4591cb0ef41Sopenharmony_ci        case AccessMode::kStoreInLiteral:
4601cb0ef41Sopenharmony_ci        case AccessMode::kDefine:
4611cb0ef41Sopenharmony_ci          // Store is not safe if the field type was cleared.
4621cb0ef41Sopenharmony_ci          return Invalid();
4631cb0ef41Sopenharmony_ci        case AccessMode::kLoad:
4641cb0ef41Sopenharmony_ci        case AccessMode::kHas:
4651cb0ef41Sopenharmony_ci          break;
4661cb0ef41Sopenharmony_ci      }
4671cb0ef41Sopenharmony_ci
4681cb0ef41Sopenharmony_ci      // The field type was cleared by the GC, so we don't know anything
4691cb0ef41Sopenharmony_ci      // about the contents now.
4701cb0ef41Sopenharmony_ci    }
4711cb0ef41Sopenharmony_ci    unrecorded_dependencies.push_back(
4721cb0ef41Sopenharmony_ci        dependencies()->FieldRepresentationDependencyOffTheRecord(
4731cb0ef41Sopenharmony_ci            map, descriptor, details_representation));
4741cb0ef41Sopenharmony_ci    if (descriptors_field_type->IsClass()) {
4751cb0ef41Sopenharmony_ci      // Remember the field map, and try to infer a useful type.
4761cb0ef41Sopenharmony_ci      base::Optional<MapRef> maybe_field_map =
4771cb0ef41Sopenharmony_ci          TryMakeRef(broker(), descriptors_field_type->AsClass());
4781cb0ef41Sopenharmony_ci      if (!maybe_field_map.has_value()) return Invalid();
4791cb0ef41Sopenharmony_ci      field_type = Type::For(maybe_field_map.value());
4801cb0ef41Sopenharmony_ci      field_map = maybe_field_map;
4811cb0ef41Sopenharmony_ci    }
4821cb0ef41Sopenharmony_ci  } else {
4831cb0ef41Sopenharmony_ci    CHECK(details_representation.IsTagged());
4841cb0ef41Sopenharmony_ci  }
4851cb0ef41Sopenharmony_ci  // TODO(turbofan): We may want to do this only depending on the use
4861cb0ef41Sopenharmony_ci  // of the access info.
4871cb0ef41Sopenharmony_ci  unrecorded_dependencies.push_back(
4881cb0ef41Sopenharmony_ci      dependencies()->FieldTypeDependencyOffTheRecord(
4891cb0ef41Sopenharmony_ci          map, descriptor, descriptors_field_type_ref.value()));
4901cb0ef41Sopenharmony_ci
4911cb0ef41Sopenharmony_ci  PropertyConstness constness;
4921cb0ef41Sopenharmony_ci  if (details.IsReadOnly() && !details.IsConfigurable()) {
4931cb0ef41Sopenharmony_ci    constness = PropertyConstness::kConst;
4941cb0ef41Sopenharmony_ci  } else {
4951cb0ef41Sopenharmony_ci    constness = dependencies()->DependOnFieldConstness(map, descriptor);
4961cb0ef41Sopenharmony_ci  }
4971cb0ef41Sopenharmony_ci
4981cb0ef41Sopenharmony_ci  // Note: FindFieldOwner may be called multiple times throughout one
4991cb0ef41Sopenharmony_ci  // compilation. This is safe since its result is fixed for a given map and
5001cb0ef41Sopenharmony_ci  // descriptor.
5011cb0ef41Sopenharmony_ci  MapRef field_owner_map = map.FindFieldOwner(descriptor);
5021cb0ef41Sopenharmony_ci
5031cb0ef41Sopenharmony_ci  switch (constness) {
5041cb0ef41Sopenharmony_ci    case PropertyConstness::kMutable:
5051cb0ef41Sopenharmony_ci      return PropertyAccessInfo::DataField(
5061cb0ef41Sopenharmony_ci          zone(), receiver_map, std::move(unrecorded_dependencies), field_index,
5071cb0ef41Sopenharmony_ci          details_representation, field_type, field_owner_map, field_map,
5081cb0ef41Sopenharmony_ci          holder, {});
5091cb0ef41Sopenharmony_ci
5101cb0ef41Sopenharmony_ci    case PropertyConstness::kConst:
5111cb0ef41Sopenharmony_ci      return PropertyAccessInfo::FastDataConstant(
5121cb0ef41Sopenharmony_ci          zone(), receiver_map, std::move(unrecorded_dependencies), field_index,
5131cb0ef41Sopenharmony_ci          details_representation, field_type, field_owner_map, field_map,
5141cb0ef41Sopenharmony_ci          holder, {});
5151cb0ef41Sopenharmony_ci  }
5161cb0ef41Sopenharmony_ci  UNREACHABLE();
5171cb0ef41Sopenharmony_ci}
5181cb0ef41Sopenharmony_ci
5191cb0ef41Sopenharmony_cinamespace {
5201cb0ef41Sopenharmony_ci
5211cb0ef41Sopenharmony_ciusing AccessorsObjectGetter = std::function<Handle<Object>()>;
5221cb0ef41Sopenharmony_ci
5231cb0ef41Sopenharmony_ciPropertyAccessInfo AccessorAccessInfoHelper(
5241cb0ef41Sopenharmony_ci    Isolate* isolate, Zone* zone, JSHeapBroker* broker,
5251cb0ef41Sopenharmony_ci    const AccessInfoFactory* ai_factory, MapRef receiver_map, NameRef name,
5261cb0ef41Sopenharmony_ci    MapRef map, base::Optional<JSObjectRef> holder, AccessMode access_mode,
5271cb0ef41Sopenharmony_ci    AccessorsObjectGetter get_accessors) {
5281cb0ef41Sopenharmony_ci  if (map.instance_type() == JS_MODULE_NAMESPACE_TYPE) {
5291cb0ef41Sopenharmony_ci    DCHECK(map.object()->is_prototype_map());
5301cb0ef41Sopenharmony_ci    Handle<PrototypeInfo> proto_info = broker->CanonicalPersistentHandle(
5311cb0ef41Sopenharmony_ci        PrototypeInfo::cast(map.object()->prototype_info()));
5321cb0ef41Sopenharmony_ci    Handle<JSModuleNamespace> module_namespace =
5331cb0ef41Sopenharmony_ci        broker->CanonicalPersistentHandle(
5341cb0ef41Sopenharmony_ci            JSModuleNamespace::cast(proto_info->module_namespace()));
5351cb0ef41Sopenharmony_ci    Handle<Cell> cell = broker->CanonicalPersistentHandle(
5361cb0ef41Sopenharmony_ci        Cell::cast(module_namespace->module().exports().Lookup(
5371cb0ef41Sopenharmony_ci            isolate, name.object(), Smi::ToInt(name.object()->GetHash()))));
5381cb0ef41Sopenharmony_ci    if (cell->value(kRelaxedLoad).IsTheHole(isolate)) {
5391cb0ef41Sopenharmony_ci      // This module has not been fully initialized yet.
5401cb0ef41Sopenharmony_ci      return PropertyAccessInfo::Invalid(zone);
5411cb0ef41Sopenharmony_ci    }
5421cb0ef41Sopenharmony_ci    base::Optional<CellRef> cell_ref = TryMakeRef(broker, cell);
5431cb0ef41Sopenharmony_ci    if (!cell_ref.has_value()) {
5441cb0ef41Sopenharmony_ci      return PropertyAccessInfo::Invalid(zone);
5451cb0ef41Sopenharmony_ci    }
5461cb0ef41Sopenharmony_ci    return PropertyAccessInfo::ModuleExport(zone, receiver_map,
5471cb0ef41Sopenharmony_ci                                            cell_ref.value());
5481cb0ef41Sopenharmony_ci  }
5491cb0ef41Sopenharmony_ci  if (access_mode == AccessMode::kHas) {
5501cb0ef41Sopenharmony_ci    // kHas is not supported for dictionary mode objects.
5511cb0ef41Sopenharmony_ci    DCHECK(!map.is_dictionary_map());
5521cb0ef41Sopenharmony_ci
5531cb0ef41Sopenharmony_ci    // HasProperty checks don't call getter/setters, existence is sufficient.
5541cb0ef41Sopenharmony_ci    return PropertyAccessInfo::FastAccessorConstant(zone, receiver_map, {},
5551cb0ef41Sopenharmony_ci                                                    holder);
5561cb0ef41Sopenharmony_ci  }
5571cb0ef41Sopenharmony_ci  Handle<Object> maybe_accessors = get_accessors();
5581cb0ef41Sopenharmony_ci  if (!maybe_accessors->IsAccessorPair()) {
5591cb0ef41Sopenharmony_ci    return PropertyAccessInfo::Invalid(zone);
5601cb0ef41Sopenharmony_ci  }
5611cb0ef41Sopenharmony_ci  Handle<AccessorPair> accessors = Handle<AccessorPair>::cast(maybe_accessors);
5621cb0ef41Sopenharmony_ci  Handle<Object> accessor = broker->CanonicalPersistentHandle(
5631cb0ef41Sopenharmony_ci      access_mode == AccessMode::kLoad ? accessors->getter(kAcquireLoad)
5641cb0ef41Sopenharmony_ci                                       : accessors->setter(kAcquireLoad));
5651cb0ef41Sopenharmony_ci
5661cb0ef41Sopenharmony_ci  base::Optional<ObjectRef> accessor_ref = TryMakeRef(broker, accessor);
5671cb0ef41Sopenharmony_ci  if (!accessor_ref.has_value()) return PropertyAccessInfo::Invalid(zone);
5681cb0ef41Sopenharmony_ci
5691cb0ef41Sopenharmony_ci  if (!accessor->IsJSFunction()) {
5701cb0ef41Sopenharmony_ci    CallOptimization optimization(broker->local_isolate_or_isolate(), accessor);
5711cb0ef41Sopenharmony_ci    if (!optimization.is_simple_api_call() ||
5721cb0ef41Sopenharmony_ci        optimization.IsCrossContextLazyAccessorPair(
5731cb0ef41Sopenharmony_ci            *broker->target_native_context().object(), *map.object())) {
5741cb0ef41Sopenharmony_ci      return PropertyAccessInfo::Invalid(zone);
5751cb0ef41Sopenharmony_ci    }
5761cb0ef41Sopenharmony_ci
5771cb0ef41Sopenharmony_ci    CallOptimization::HolderLookup lookup;
5781cb0ef41Sopenharmony_ci    Handle<JSObject> holder_handle = broker->CanonicalPersistentHandle(
5791cb0ef41Sopenharmony_ci        optimization.LookupHolderOfExpectedType(
5801cb0ef41Sopenharmony_ci            broker->local_isolate_or_isolate(), receiver_map.object(),
5811cb0ef41Sopenharmony_ci            &lookup));
5821cb0ef41Sopenharmony_ci    if (lookup == CallOptimization::kHolderNotFound) {
5831cb0ef41Sopenharmony_ci      return PropertyAccessInfo::Invalid(zone);
5841cb0ef41Sopenharmony_ci    }
5851cb0ef41Sopenharmony_ci    DCHECK_IMPLIES(lookup == CallOptimization::kHolderIsReceiver,
5861cb0ef41Sopenharmony_ci                   holder_handle.is_null());
5871cb0ef41Sopenharmony_ci    DCHECK_IMPLIES(lookup == CallOptimization::kHolderFound,
5881cb0ef41Sopenharmony_ci                   !holder_handle.is_null());
5891cb0ef41Sopenharmony_ci
5901cb0ef41Sopenharmony_ci    if (holder_handle.is_null()) {
5911cb0ef41Sopenharmony_ci      holder = {};
5921cb0ef41Sopenharmony_ci    } else {
5931cb0ef41Sopenharmony_ci      holder = TryMakeRef(broker, holder_handle);
5941cb0ef41Sopenharmony_ci      if (!holder.has_value()) return PropertyAccessInfo::Invalid(zone);
5951cb0ef41Sopenharmony_ci    }
5961cb0ef41Sopenharmony_ci  }
5971cb0ef41Sopenharmony_ci  if (access_mode == AccessMode::kLoad) {
5981cb0ef41Sopenharmony_ci    base::Optional<Name> cached_property_name =
5991cb0ef41Sopenharmony_ci        FunctionTemplateInfo::TryGetCachedPropertyName(isolate, *accessor);
6001cb0ef41Sopenharmony_ci    if (cached_property_name.has_value()) {
6011cb0ef41Sopenharmony_ci      base::Optional<NameRef> cached_property_name_ref =
6021cb0ef41Sopenharmony_ci          TryMakeRef(broker, cached_property_name.value());
6031cb0ef41Sopenharmony_ci      if (cached_property_name_ref.has_value()) {
6041cb0ef41Sopenharmony_ci        PropertyAccessInfo access_info = ai_factory->ComputePropertyAccessInfo(
6051cb0ef41Sopenharmony_ci            map, cached_property_name_ref.value(), access_mode);
6061cb0ef41Sopenharmony_ci        if (!access_info.IsInvalid()) return access_info;
6071cb0ef41Sopenharmony_ci      }
6081cb0ef41Sopenharmony_ci    }
6091cb0ef41Sopenharmony_ci  }
6101cb0ef41Sopenharmony_ci
6111cb0ef41Sopenharmony_ci  if (map.is_dictionary_map()) {
6121cb0ef41Sopenharmony_ci    return PropertyAccessInfo::DictionaryProtoAccessorConstant(
6131cb0ef41Sopenharmony_ci        zone, receiver_map, holder, accessor_ref.value(), name);
6141cb0ef41Sopenharmony_ci  } else {
6151cb0ef41Sopenharmony_ci    return PropertyAccessInfo::FastAccessorConstant(
6161cb0ef41Sopenharmony_ci        zone, receiver_map, accessor_ref.value(), holder);
6171cb0ef41Sopenharmony_ci  }
6181cb0ef41Sopenharmony_ci}
6191cb0ef41Sopenharmony_ci
6201cb0ef41Sopenharmony_ci}  // namespace
6211cb0ef41Sopenharmony_ci
6221cb0ef41Sopenharmony_ciPropertyAccessInfo AccessInfoFactory::ComputeAccessorDescriptorAccessInfo(
6231cb0ef41Sopenharmony_ci    MapRef receiver_map, NameRef name, MapRef holder_map,
6241cb0ef41Sopenharmony_ci    base::Optional<JSObjectRef> holder, InternalIndex descriptor,
6251cb0ef41Sopenharmony_ci    AccessMode access_mode) const {
6261cb0ef41Sopenharmony_ci  DCHECK(descriptor.is_found());
6271cb0ef41Sopenharmony_ci  Handle<DescriptorArray> descriptors = broker()->CanonicalPersistentHandle(
6281cb0ef41Sopenharmony_ci      holder_map.object()->instance_descriptors(kRelaxedLoad));
6291cb0ef41Sopenharmony_ci  SLOW_DCHECK(descriptor ==
6301cb0ef41Sopenharmony_ci              descriptors->Search(*name.object(), *holder_map.object()));
6311cb0ef41Sopenharmony_ci
6321cb0ef41Sopenharmony_ci  auto get_accessors = [&]() {
6331cb0ef41Sopenharmony_ci    return broker()->CanonicalPersistentHandle(
6341cb0ef41Sopenharmony_ci        descriptors->GetStrongValue(descriptor));
6351cb0ef41Sopenharmony_ci  };
6361cb0ef41Sopenharmony_ci  return AccessorAccessInfoHelper(isolate(), zone(), broker(), this,
6371cb0ef41Sopenharmony_ci                                  receiver_map, name, holder_map, holder,
6381cb0ef41Sopenharmony_ci                                  access_mode, get_accessors);
6391cb0ef41Sopenharmony_ci}
6401cb0ef41Sopenharmony_ci
6411cb0ef41Sopenharmony_ciPropertyAccessInfo AccessInfoFactory::ComputeDictionaryProtoAccessInfo(
6421cb0ef41Sopenharmony_ci    MapRef receiver_map, NameRef name, JSObjectRef holder,
6431cb0ef41Sopenharmony_ci    InternalIndex dictionary_index, AccessMode access_mode,
6441cb0ef41Sopenharmony_ci    PropertyDetails details) const {
6451cb0ef41Sopenharmony_ci  CHECK(V8_DICT_PROPERTY_CONST_TRACKING_BOOL);
6461cb0ef41Sopenharmony_ci  DCHECK(holder.map().object()->is_prototype_map());
6471cb0ef41Sopenharmony_ci  DCHECK_EQ(access_mode, AccessMode::kLoad);
6481cb0ef41Sopenharmony_ci
6491cb0ef41Sopenharmony_ci  // We can only inline accesses to constant properties.
6501cb0ef41Sopenharmony_ci  if (details.constness() != PropertyConstness::kConst) {
6511cb0ef41Sopenharmony_ci    return Invalid();
6521cb0ef41Sopenharmony_ci  }
6531cb0ef41Sopenharmony_ci
6541cb0ef41Sopenharmony_ci  if (details.kind() == PropertyKind::kData) {
6551cb0ef41Sopenharmony_ci    return PropertyAccessInfo::DictionaryProtoDataConstant(
6561cb0ef41Sopenharmony_ci        zone(), receiver_map, holder, dictionary_index, name);
6571cb0ef41Sopenharmony_ci  }
6581cb0ef41Sopenharmony_ci
6591cb0ef41Sopenharmony_ci  auto get_accessors = [&]() {
6601cb0ef41Sopenharmony_ci    return JSObject::DictionaryPropertyAt(isolate(), holder.object(),
6611cb0ef41Sopenharmony_ci                                          dictionary_index);
6621cb0ef41Sopenharmony_ci  };
6631cb0ef41Sopenharmony_ci  return AccessorAccessInfoHelper(isolate(), zone(), broker(), this,
6641cb0ef41Sopenharmony_ci                                  receiver_map, name, holder.map(), holder,
6651cb0ef41Sopenharmony_ci                                  access_mode, get_accessors);
6661cb0ef41Sopenharmony_ci}
6671cb0ef41Sopenharmony_ci
6681cb0ef41Sopenharmony_cibool AccessInfoFactory::TryLoadPropertyDetails(
6691cb0ef41Sopenharmony_ci    MapRef map, base::Optional<JSObjectRef> maybe_holder, NameRef name,
6701cb0ef41Sopenharmony_ci    InternalIndex* index_out, PropertyDetails* details_out) const {
6711cb0ef41Sopenharmony_ci  if (map.is_dictionary_map()) {
6721cb0ef41Sopenharmony_ci    DCHECK(V8_DICT_PROPERTY_CONST_TRACKING_BOOL);
6731cb0ef41Sopenharmony_ci    DCHECK(map.object()->is_prototype_map());
6741cb0ef41Sopenharmony_ci
6751cb0ef41Sopenharmony_ci    DisallowGarbageCollection no_gc;
6761cb0ef41Sopenharmony_ci
6771cb0ef41Sopenharmony_ci    if (!maybe_holder.has_value()) {
6781cb0ef41Sopenharmony_ci      // TODO(v8:11457) In this situation, we have a dictionary mode prototype
6791cb0ef41Sopenharmony_ci      // as a receiver. Consider other means of obtaining the holder in this
6801cb0ef41Sopenharmony_ci      // situation.
6811cb0ef41Sopenharmony_ci
6821cb0ef41Sopenharmony_ci      // Without the holder, we can't get the property details.
6831cb0ef41Sopenharmony_ci      return false;
6841cb0ef41Sopenharmony_ci    }
6851cb0ef41Sopenharmony_ci
6861cb0ef41Sopenharmony_ci    Handle<JSObject> holder = maybe_holder->object();
6871cb0ef41Sopenharmony_ci    if (V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL) {
6881cb0ef41Sopenharmony_ci      SwissNameDictionary dict = holder->property_dictionary_swiss();
6891cb0ef41Sopenharmony_ci      *index_out = dict.FindEntry(isolate(), name.object());
6901cb0ef41Sopenharmony_ci      if (index_out->is_found()) {
6911cb0ef41Sopenharmony_ci        *details_out = dict.DetailsAt(*index_out);
6921cb0ef41Sopenharmony_ci      }
6931cb0ef41Sopenharmony_ci    } else {
6941cb0ef41Sopenharmony_ci      NameDictionary dict = holder->property_dictionary();
6951cb0ef41Sopenharmony_ci      *index_out = dict.FindEntry(isolate(), name.object());
6961cb0ef41Sopenharmony_ci      if (index_out->is_found()) {
6971cb0ef41Sopenharmony_ci        *details_out = dict.DetailsAt(*index_out);
6981cb0ef41Sopenharmony_ci      }
6991cb0ef41Sopenharmony_ci    }
7001cb0ef41Sopenharmony_ci  } else {
7011cb0ef41Sopenharmony_ci    DescriptorArray descriptors = *map.instance_descriptors().object();
7021cb0ef41Sopenharmony_ci    *index_out = descriptors.Search(*name.object(), *map.object(), true);
7031cb0ef41Sopenharmony_ci    if (index_out->is_found()) {
7041cb0ef41Sopenharmony_ci      *details_out = descriptors.GetDetails(*index_out);
7051cb0ef41Sopenharmony_ci    }
7061cb0ef41Sopenharmony_ci  }
7071cb0ef41Sopenharmony_ci
7081cb0ef41Sopenharmony_ci  return true;
7091cb0ef41Sopenharmony_ci}
7101cb0ef41Sopenharmony_ci
7111cb0ef41Sopenharmony_ciPropertyAccessInfo AccessInfoFactory::ComputePropertyAccessInfo(
7121cb0ef41Sopenharmony_ci    MapRef map, NameRef name, AccessMode access_mode) const {
7131cb0ef41Sopenharmony_ci  CHECK(name.IsUniqueName());
7141cb0ef41Sopenharmony_ci
7151cb0ef41Sopenharmony_ci  // Dictionary property const tracking is unsupported with concurrent inlining.
7161cb0ef41Sopenharmony_ci  CHECK(!V8_DICT_PROPERTY_CONST_TRACKING_BOOL);
7171cb0ef41Sopenharmony_ci
7181cb0ef41Sopenharmony_ci  JSHeapBroker::MapUpdaterGuardIfNeeded mumd_scope(broker());
7191cb0ef41Sopenharmony_ci
7201cb0ef41Sopenharmony_ci  if (access_mode == AccessMode::kHas && !map.object()->IsJSReceiverMap()) {
7211cb0ef41Sopenharmony_ci    return Invalid();
7221cb0ef41Sopenharmony_ci  }
7231cb0ef41Sopenharmony_ci
7241cb0ef41Sopenharmony_ci  // Check if it is safe to inline property access for the {map}.
7251cb0ef41Sopenharmony_ci  if (!CanInlinePropertyAccess(map, access_mode)) {
7261cb0ef41Sopenharmony_ci    return Invalid();
7271cb0ef41Sopenharmony_ci  }
7281cb0ef41Sopenharmony_ci
7291cb0ef41Sopenharmony_ci  // We support fast inline cases for certain JSObject getters.
7301cb0ef41Sopenharmony_ci  if (access_mode == AccessMode::kLoad || access_mode == AccessMode::kHas) {
7311cb0ef41Sopenharmony_ci    PropertyAccessInfo access_info = LookupSpecialFieldAccessor(map, name);
7321cb0ef41Sopenharmony_ci    if (!access_info.IsInvalid()) return access_info;
7331cb0ef41Sopenharmony_ci  }
7341cb0ef41Sopenharmony_ci
7351cb0ef41Sopenharmony_ci  // Only relevant if V8_DICT_PROPERTY_CONST_TRACKING enabled.
7361cb0ef41Sopenharmony_ci  bool dictionary_prototype_on_chain = false;
7371cb0ef41Sopenharmony_ci  bool fast_mode_prototype_on_chain = false;
7381cb0ef41Sopenharmony_ci
7391cb0ef41Sopenharmony_ci  // Remember the receiver map. We use {map} as loop variable.
7401cb0ef41Sopenharmony_ci  MapRef receiver_map = map;
7411cb0ef41Sopenharmony_ci  base::Optional<JSObjectRef> holder;
7421cb0ef41Sopenharmony_ci
7431cb0ef41Sopenharmony_ci  // Perform the implicit ToObject for primitives here.
7441cb0ef41Sopenharmony_ci  // Implemented according to ES6 section 7.3.2 GetV (V, P).
7451cb0ef41Sopenharmony_ci  // Note: Keep sync'd with
7461cb0ef41Sopenharmony_ci  // CompilationDependencies::DependOnStablePrototypeChains.
7471cb0ef41Sopenharmony_ci  if (receiver_map.IsPrimitiveMap()) {
7481cb0ef41Sopenharmony_ci    base::Optional<JSFunctionRef> constructor =
7491cb0ef41Sopenharmony_ci        broker()->target_native_context().GetConstructorFunction(receiver_map);
7501cb0ef41Sopenharmony_ci    if (!constructor.has_value()) return Invalid();
7511cb0ef41Sopenharmony_ci    map = constructor->initial_map(broker()->dependencies());
7521cb0ef41Sopenharmony_ci    DCHECK(!map.IsPrimitiveMap());
7531cb0ef41Sopenharmony_ci  }
7541cb0ef41Sopenharmony_ci
7551cb0ef41Sopenharmony_ci  while (true) {
7561cb0ef41Sopenharmony_ci    PropertyDetails details = PropertyDetails::Empty();
7571cb0ef41Sopenharmony_ci    InternalIndex index = InternalIndex::NotFound();
7581cb0ef41Sopenharmony_ci    if (!TryLoadPropertyDetails(map, holder, name, &index, &details)) {
7591cb0ef41Sopenharmony_ci      return Invalid();
7601cb0ef41Sopenharmony_ci    }
7611cb0ef41Sopenharmony_ci
7621cb0ef41Sopenharmony_ci    if (index.is_found()) {
7631cb0ef41Sopenharmony_ci      if (access_mode == AccessMode::kStore ||
7641cb0ef41Sopenharmony_ci          access_mode == AccessMode::kStoreInLiteral) {
7651cb0ef41Sopenharmony_ci        DCHECK(!map.is_dictionary_map());
7661cb0ef41Sopenharmony_ci
7671cb0ef41Sopenharmony_ci        // Don't bother optimizing stores to read-only properties.
7681cb0ef41Sopenharmony_ci        if (details.IsReadOnly()) return Invalid();
7691cb0ef41Sopenharmony_ci
7701cb0ef41Sopenharmony_ci        if (details.kind() == PropertyKind::kData && holder.has_value()) {
7711cb0ef41Sopenharmony_ci          // This is a store to a property not found on the receiver but on a
7721cb0ef41Sopenharmony_ci          // prototype. According to ES6 section 9.1.9 [[Set]], we need to
7731cb0ef41Sopenharmony_ci          // create a new data property on the receiver. We can still optimize
7741cb0ef41Sopenharmony_ci          // if such a transition already exists.
7751cb0ef41Sopenharmony_ci          return LookupTransition(receiver_map, name, holder, NONE);
7761cb0ef41Sopenharmony_ci        }
7771cb0ef41Sopenharmony_ci      }
7781cb0ef41Sopenharmony_ci
7791cb0ef41Sopenharmony_ci      if (map.is_dictionary_map()) {
7801cb0ef41Sopenharmony_ci        DCHECK(V8_DICT_PROPERTY_CONST_TRACKING_BOOL);
7811cb0ef41Sopenharmony_ci
7821cb0ef41Sopenharmony_ci        if (fast_mode_prototype_on_chain) {
7831cb0ef41Sopenharmony_ci          // TODO(v8:11248) While the work on dictionary mode prototypes is in
7841cb0ef41Sopenharmony_ci          // progress, we may still see fast mode objects on the chain prior to
7851cb0ef41Sopenharmony_ci          // reaching a dictionary mode prototype holding the property . Due to
7861cb0ef41Sopenharmony_ci          // this only being an intermediate state, we don't stupport these kind
7871cb0ef41Sopenharmony_ci          // of heterogenous prototype chains.
7881cb0ef41Sopenharmony_ci          return Invalid();
7891cb0ef41Sopenharmony_ci        }
7901cb0ef41Sopenharmony_ci
7911cb0ef41Sopenharmony_ci        // TryLoadPropertyDetails only succeeds if we know the holder.
7921cb0ef41Sopenharmony_ci        return ComputeDictionaryProtoAccessInfo(
7931cb0ef41Sopenharmony_ci            receiver_map, name, holder.value(), index, access_mode, details);
7941cb0ef41Sopenharmony_ci      }
7951cb0ef41Sopenharmony_ci
7961cb0ef41Sopenharmony_ci      if (dictionary_prototype_on_chain) {
7971cb0ef41Sopenharmony_ci        // If V8_DICT_PROPERTY_CONST_TRACKING_BOOL was disabled, then a
7981cb0ef41Sopenharmony_ci        // dictionary prototype would have caused a bailout earlier.
7991cb0ef41Sopenharmony_ci        DCHECK(V8_DICT_PROPERTY_CONST_TRACKING_BOOL);
8001cb0ef41Sopenharmony_ci
8011cb0ef41Sopenharmony_ci        // TODO(v8:11248) We have a fast mode holder, but there was a dictionary
8021cb0ef41Sopenharmony_ci        // mode prototype earlier on the chain. Note that seeing a fast mode
8031cb0ef41Sopenharmony_ci        // prototype even though V8_DICT_PROPERTY_CONST_TRACKING is enabled
8041cb0ef41Sopenharmony_ci        // should only be possible while the implementation of dictionary mode
8051cb0ef41Sopenharmony_ci        // prototypes is work in progress. Eventually, enabling
8061cb0ef41Sopenharmony_ci        // V8_DICT_PROPERTY_CONST_TRACKING will guarantee that all prototypes
8071cb0ef41Sopenharmony_ci        // are always in dictionary mode, making this case unreachable. However,
8081cb0ef41Sopenharmony_ci        // due to the complications of checking dictionary mode prototypes for
8091cb0ef41Sopenharmony_ci        // modification, we don't attempt to support dictionary mode prototypes
8101cb0ef41Sopenharmony_ci        // occuring before a fast mode holder on the chain.
8111cb0ef41Sopenharmony_ci        return Invalid();
8121cb0ef41Sopenharmony_ci      }
8131cb0ef41Sopenharmony_ci      if (details.location() == PropertyLocation::kField) {
8141cb0ef41Sopenharmony_ci        if (details.kind() == PropertyKind::kData) {
8151cb0ef41Sopenharmony_ci          return ComputeDataFieldAccessInfo(receiver_map, map, name, holder,
8161cb0ef41Sopenharmony_ci                                            index, access_mode);
8171cb0ef41Sopenharmony_ci        } else {
8181cb0ef41Sopenharmony_ci          DCHECK_EQ(PropertyKind::kAccessor, details.kind());
8191cb0ef41Sopenharmony_ci          // TODO(turbofan): Add support for general accessors?
8201cb0ef41Sopenharmony_ci          return Invalid();
8211cb0ef41Sopenharmony_ci        }
8221cb0ef41Sopenharmony_ci      } else {
8231cb0ef41Sopenharmony_ci        DCHECK_EQ(PropertyLocation::kDescriptor, details.location());
8241cb0ef41Sopenharmony_ci        DCHECK_EQ(PropertyKind::kAccessor, details.kind());
8251cb0ef41Sopenharmony_ci        return ComputeAccessorDescriptorAccessInfo(receiver_map, name, map,
8261cb0ef41Sopenharmony_ci                                                   holder, index, access_mode);
8271cb0ef41Sopenharmony_ci      }
8281cb0ef41Sopenharmony_ci
8291cb0ef41Sopenharmony_ci      UNREACHABLE();
8301cb0ef41Sopenharmony_ci    }
8311cb0ef41Sopenharmony_ci
8321cb0ef41Sopenharmony_ci    // The property wasn't found on {map}. Look on the prototype if appropriate.
8331cb0ef41Sopenharmony_ci    DCHECK(!index.is_found());
8341cb0ef41Sopenharmony_ci
8351cb0ef41Sopenharmony_ci    // Don't search on the prototype chain for special indices in case of
8361cb0ef41Sopenharmony_ci    // integer indexed exotic objects (see ES6 section 9.4.5).
8371cb0ef41Sopenharmony_ci    if (map.object()->IsJSTypedArrayMap() && name.IsString()) {
8381cb0ef41Sopenharmony_ci      if (broker()->IsMainThread()) {
8391cb0ef41Sopenharmony_ci        if (IsSpecialIndex(String::cast(*name.object()))) {
8401cb0ef41Sopenharmony_ci          return Invalid();
8411cb0ef41Sopenharmony_ci        }
8421cb0ef41Sopenharmony_ci      } else {
8431cb0ef41Sopenharmony_ci        // TODO(jgruber): We are being conservative here since we can't access
8441cb0ef41Sopenharmony_ci        // string contents from background threads. Should that become possible
8451cb0ef41Sopenharmony_ci        // in the future, remove this bailout.
8461cb0ef41Sopenharmony_ci        return Invalid();
8471cb0ef41Sopenharmony_ci      }
8481cb0ef41Sopenharmony_ci    }
8491cb0ef41Sopenharmony_ci
8501cb0ef41Sopenharmony_ci    // Don't search on the prototype when storing in literals, or performing a
8511cb0ef41Sopenharmony_ci    // Define operation
8521cb0ef41Sopenharmony_ci    if (access_mode == AccessMode::kStoreInLiteral ||
8531cb0ef41Sopenharmony_ci        access_mode == AccessMode::kDefine) {
8541cb0ef41Sopenharmony_ci      PropertyAttributes attrs = NONE;
8551cb0ef41Sopenharmony_ci      if (name.object()->IsPrivate()) {
8561cb0ef41Sopenharmony_ci        // When PrivateNames are added to an object, they are by definition
8571cb0ef41Sopenharmony_ci        // non-enumerable.
8581cb0ef41Sopenharmony_ci        attrs = DONT_ENUM;
8591cb0ef41Sopenharmony_ci      }
8601cb0ef41Sopenharmony_ci      return LookupTransition(receiver_map, name, holder, attrs);
8611cb0ef41Sopenharmony_ci    }
8621cb0ef41Sopenharmony_ci
8631cb0ef41Sopenharmony_ci    // Don't lookup private symbols on the prototype chain.
8641cb0ef41Sopenharmony_ci    if (name.object()->IsPrivate()) {
8651cb0ef41Sopenharmony_ci      return Invalid();
8661cb0ef41Sopenharmony_ci    }
8671cb0ef41Sopenharmony_ci
8681cb0ef41Sopenharmony_ci    if (V8_DICT_PROPERTY_CONST_TRACKING_BOOL && holder.has_value()) {
8691cb0ef41Sopenharmony_ci      // At this point, we are past the first loop iteration.
8701cb0ef41Sopenharmony_ci      DCHECK(holder->object()->map().is_prototype_map());
8711cb0ef41Sopenharmony_ci      DCHECK(!holder->map().equals(receiver_map));
8721cb0ef41Sopenharmony_ci
8731cb0ef41Sopenharmony_ci      fast_mode_prototype_on_chain =
8741cb0ef41Sopenharmony_ci          fast_mode_prototype_on_chain || !map.is_dictionary_map();
8751cb0ef41Sopenharmony_ci      dictionary_prototype_on_chain =
8761cb0ef41Sopenharmony_ci          dictionary_prototype_on_chain || map.is_dictionary_map();
8771cb0ef41Sopenharmony_ci    }
8781cb0ef41Sopenharmony_ci
8791cb0ef41Sopenharmony_ci    // Walk up the prototype chain.
8801cb0ef41Sopenharmony_ci    // Load the map's prototype's map to guarantee that every time we use it,
8811cb0ef41Sopenharmony_ci    // we use the same Map.
8821cb0ef41Sopenharmony_ci    HeapObjectRef prototype = map.prototype();
8831cb0ef41Sopenharmony_ci
8841cb0ef41Sopenharmony_ci    MapRef map_prototype_map = prototype.map();
8851cb0ef41Sopenharmony_ci    if (!map_prototype_map.object()->IsJSObjectMap()) {
8861cb0ef41Sopenharmony_ci      // Don't allow proxies on the prototype chain.
8871cb0ef41Sopenharmony_ci      if (!prototype.IsNull()) {
8881cb0ef41Sopenharmony_ci        DCHECK(prototype.object()->IsJSProxy());
8891cb0ef41Sopenharmony_ci        return Invalid();
8901cb0ef41Sopenharmony_ci      }
8911cb0ef41Sopenharmony_ci
8921cb0ef41Sopenharmony_ci      DCHECK(prototype.IsNull());
8931cb0ef41Sopenharmony_ci
8941cb0ef41Sopenharmony_ci      if (dictionary_prototype_on_chain) {
8951cb0ef41Sopenharmony_ci        // TODO(v8:11248) See earlier comment about
8961cb0ef41Sopenharmony_ci        // dictionary_prototype_on_chain. We don't support absent properties
8971cb0ef41Sopenharmony_ci        // with dictionary mode prototypes on the chain, either. This is again
8981cb0ef41Sopenharmony_ci        // just due to how we currently deal with dependencies for dictionary
8991cb0ef41Sopenharmony_ci        // properties during finalization.
9001cb0ef41Sopenharmony_ci        return Invalid();
9011cb0ef41Sopenharmony_ci      }
9021cb0ef41Sopenharmony_ci
9031cb0ef41Sopenharmony_ci      // Store to property not found on the receiver or any prototype, we need
9041cb0ef41Sopenharmony_ci      // to transition to a new data property.
9051cb0ef41Sopenharmony_ci      // Implemented according to ES6 section 9.1.9 [[Set]] (P, V, Receiver)
9061cb0ef41Sopenharmony_ci      if (access_mode == AccessMode::kStore) {
9071cb0ef41Sopenharmony_ci        return LookupTransition(receiver_map, name, holder, NONE);
9081cb0ef41Sopenharmony_ci      }
9091cb0ef41Sopenharmony_ci
9101cb0ef41Sopenharmony_ci      // The property was not found (access returns undefined or throws
9111cb0ef41Sopenharmony_ci      // depending on the language mode of the load operation.
9121cb0ef41Sopenharmony_ci      // Implemented according to ES6 section 9.1.8 [[Get]] (P, Receiver)
9131cb0ef41Sopenharmony_ci      return PropertyAccessInfo::NotFound(zone(), receiver_map, holder);
9141cb0ef41Sopenharmony_ci    }
9151cb0ef41Sopenharmony_ci
9161cb0ef41Sopenharmony_ci    holder = prototype.AsJSObject();
9171cb0ef41Sopenharmony_ci    map = map_prototype_map;
9181cb0ef41Sopenharmony_ci
9191cb0ef41Sopenharmony_ci    if (!CanInlinePropertyAccess(map, access_mode)) {
9201cb0ef41Sopenharmony_ci      return Invalid();
9211cb0ef41Sopenharmony_ci    }
9221cb0ef41Sopenharmony_ci
9231cb0ef41Sopenharmony_ci    // Successful lookup on prototype chain needs to guarantee that all the
9241cb0ef41Sopenharmony_ci    // prototypes up to the holder have stable maps, except for dictionary-mode
9251cb0ef41Sopenharmony_ci    // prototypes. We currently do this by taking a
9261cb0ef41Sopenharmony_ci    // DependOnStablePrototypeChains dependency in the caller.
9271cb0ef41Sopenharmony_ci    //
9281cb0ef41Sopenharmony_ci    // TODO(jgruber): This is brittle and easy to miss. Consider a refactor
9291cb0ef41Sopenharmony_ci    // that moves the responsibility of taking the dependency into
9301cb0ef41Sopenharmony_ci    // AccessInfoFactory.
9311cb0ef41Sopenharmony_ci  }
9321cb0ef41Sopenharmony_ci  UNREACHABLE();
9331cb0ef41Sopenharmony_ci}
9341cb0ef41Sopenharmony_ci
9351cb0ef41Sopenharmony_ciPropertyAccessInfo AccessInfoFactory::FinalizePropertyAccessInfosAsOne(
9361cb0ef41Sopenharmony_ci    ZoneVector<PropertyAccessInfo> access_infos, AccessMode access_mode) const {
9371cb0ef41Sopenharmony_ci  ZoneVector<PropertyAccessInfo> merged_access_infos(zone());
9381cb0ef41Sopenharmony_ci  MergePropertyAccessInfos(access_infos, access_mode, &merged_access_infos);
9391cb0ef41Sopenharmony_ci  if (merged_access_infos.size() == 1) {
9401cb0ef41Sopenharmony_ci    PropertyAccessInfo& result = merged_access_infos.front();
9411cb0ef41Sopenharmony_ci    if (!result.IsInvalid()) {
9421cb0ef41Sopenharmony_ci      result.RecordDependencies(dependencies());
9431cb0ef41Sopenharmony_ci      return result;
9441cb0ef41Sopenharmony_ci    }
9451cb0ef41Sopenharmony_ci  }
9461cb0ef41Sopenharmony_ci  return Invalid();
9471cb0ef41Sopenharmony_ci}
9481cb0ef41Sopenharmony_ci
9491cb0ef41Sopenharmony_civoid PropertyAccessInfo::RecordDependencies(
9501cb0ef41Sopenharmony_ci    CompilationDependencies* dependencies) {
9511cb0ef41Sopenharmony_ci  for (CompilationDependency const* d : unrecorded_dependencies_) {
9521cb0ef41Sopenharmony_ci    dependencies->RecordDependency(d);
9531cb0ef41Sopenharmony_ci  }
9541cb0ef41Sopenharmony_ci  unrecorded_dependencies_.clear();
9551cb0ef41Sopenharmony_ci}
9561cb0ef41Sopenharmony_ci
9571cb0ef41Sopenharmony_cibool AccessInfoFactory::FinalizePropertyAccessInfos(
9581cb0ef41Sopenharmony_ci    ZoneVector<PropertyAccessInfo> access_infos, AccessMode access_mode,
9591cb0ef41Sopenharmony_ci    ZoneVector<PropertyAccessInfo>* result) const {
9601cb0ef41Sopenharmony_ci  if (access_infos.empty()) return false;
9611cb0ef41Sopenharmony_ci  MergePropertyAccessInfos(access_infos, access_mode, result);
9621cb0ef41Sopenharmony_ci  for (PropertyAccessInfo const& info : *result) {
9631cb0ef41Sopenharmony_ci    if (info.IsInvalid()) return false;
9641cb0ef41Sopenharmony_ci  }
9651cb0ef41Sopenharmony_ci  for (PropertyAccessInfo& info : *result) {
9661cb0ef41Sopenharmony_ci    info.RecordDependencies(dependencies());
9671cb0ef41Sopenharmony_ci  }
9681cb0ef41Sopenharmony_ci  return true;
9691cb0ef41Sopenharmony_ci}
9701cb0ef41Sopenharmony_ci
9711cb0ef41Sopenharmony_civoid AccessInfoFactory::MergePropertyAccessInfos(
9721cb0ef41Sopenharmony_ci    ZoneVector<PropertyAccessInfo> infos, AccessMode access_mode,
9731cb0ef41Sopenharmony_ci    ZoneVector<PropertyAccessInfo>* result) const {
9741cb0ef41Sopenharmony_ci  DCHECK(result->empty());
9751cb0ef41Sopenharmony_ci  for (auto it = infos.begin(), end = infos.end(); it != end; ++it) {
9761cb0ef41Sopenharmony_ci    bool merged = false;
9771cb0ef41Sopenharmony_ci    for (auto ot = it + 1; ot != end; ++ot) {
9781cb0ef41Sopenharmony_ci      if (ot->Merge(&(*it), access_mode, zone())) {
9791cb0ef41Sopenharmony_ci        merged = true;
9801cb0ef41Sopenharmony_ci        break;
9811cb0ef41Sopenharmony_ci      }
9821cb0ef41Sopenharmony_ci    }
9831cb0ef41Sopenharmony_ci    if (!merged) result->push_back(*it);
9841cb0ef41Sopenharmony_ci  }
9851cb0ef41Sopenharmony_ci  CHECK(!result->empty());
9861cb0ef41Sopenharmony_ci}
9871cb0ef41Sopenharmony_ci
9881cb0ef41Sopenharmony_ciIsolate* AccessInfoFactory::isolate() const { return broker()->isolate(); }
9891cb0ef41Sopenharmony_ci
9901cb0ef41Sopenharmony_cinamespace {
9911cb0ef41Sopenharmony_ci
9921cb0ef41Sopenharmony_ciMaybe<ElementsKind> GeneralizeElementsKind(ElementsKind this_kind,
9931cb0ef41Sopenharmony_ci                                           ElementsKind that_kind) {
9941cb0ef41Sopenharmony_ci  if (IsHoleyElementsKind(this_kind)) {
9951cb0ef41Sopenharmony_ci    that_kind = GetHoleyElementsKind(that_kind);
9961cb0ef41Sopenharmony_ci  } else if (IsHoleyElementsKind(that_kind)) {
9971cb0ef41Sopenharmony_ci    this_kind = GetHoleyElementsKind(this_kind);
9981cb0ef41Sopenharmony_ci  }
9991cb0ef41Sopenharmony_ci  if (this_kind == that_kind) return Just(this_kind);
10001cb0ef41Sopenharmony_ci  if (IsDoubleElementsKind(that_kind) == IsDoubleElementsKind(this_kind)) {
10011cb0ef41Sopenharmony_ci    if (IsMoreGeneralElementsKindTransition(that_kind, this_kind)) {
10021cb0ef41Sopenharmony_ci      return Just(this_kind);
10031cb0ef41Sopenharmony_ci    }
10041cb0ef41Sopenharmony_ci    if (IsMoreGeneralElementsKindTransition(this_kind, that_kind)) {
10051cb0ef41Sopenharmony_ci      return Just(that_kind);
10061cb0ef41Sopenharmony_ci    }
10071cb0ef41Sopenharmony_ci  }
10081cb0ef41Sopenharmony_ci  return Nothing<ElementsKind>();
10091cb0ef41Sopenharmony_ci}
10101cb0ef41Sopenharmony_ci
10111cb0ef41Sopenharmony_ci}  // namespace
10121cb0ef41Sopenharmony_ci
10131cb0ef41Sopenharmony_cibase::Optional<ElementAccessInfo> AccessInfoFactory::ConsolidateElementLoad(
10141cb0ef41Sopenharmony_ci    ElementAccessFeedback const& feedback) const {
10151cb0ef41Sopenharmony_ci  if (feedback.transition_groups().empty()) return {};
10161cb0ef41Sopenharmony_ci
10171cb0ef41Sopenharmony_ci  DCHECK(!feedback.transition_groups().front().empty());
10181cb0ef41Sopenharmony_ci  Handle<Map> first_map = feedback.transition_groups().front().front();
10191cb0ef41Sopenharmony_ci  base::Optional<MapRef> first_map_ref = TryMakeRef(broker(), first_map);
10201cb0ef41Sopenharmony_ci  if (!first_map_ref.has_value()) return {};
10211cb0ef41Sopenharmony_ci  InstanceType instance_type = first_map_ref->instance_type();
10221cb0ef41Sopenharmony_ci  ElementsKind elements_kind = first_map_ref->elements_kind();
10231cb0ef41Sopenharmony_ci
10241cb0ef41Sopenharmony_ci  ZoneVector<MapRef> maps(zone());
10251cb0ef41Sopenharmony_ci  for (auto const& group : feedback.transition_groups()) {
10261cb0ef41Sopenharmony_ci    for (Handle<Map> map_handle : group) {
10271cb0ef41Sopenharmony_ci      base::Optional<MapRef> map = TryMakeRef(broker(), map_handle);
10281cb0ef41Sopenharmony_ci      if (!map.has_value()) return {};
10291cb0ef41Sopenharmony_ci      if (map->instance_type() != instance_type ||
10301cb0ef41Sopenharmony_ci          !map->CanInlineElementAccess()) {
10311cb0ef41Sopenharmony_ci        return {};
10321cb0ef41Sopenharmony_ci      }
10331cb0ef41Sopenharmony_ci      if (!GeneralizeElementsKind(elements_kind, map->elements_kind())
10341cb0ef41Sopenharmony_ci               .To(&elements_kind)) {
10351cb0ef41Sopenharmony_ci        return {};
10361cb0ef41Sopenharmony_ci      }
10371cb0ef41Sopenharmony_ci      maps.push_back(map.value());
10381cb0ef41Sopenharmony_ci    }
10391cb0ef41Sopenharmony_ci  }
10401cb0ef41Sopenharmony_ci
10411cb0ef41Sopenharmony_ci  return ElementAccessInfo(std::move(maps), elements_kind, zone());
10421cb0ef41Sopenharmony_ci}
10431cb0ef41Sopenharmony_ci
10441cb0ef41Sopenharmony_ciPropertyAccessInfo AccessInfoFactory::LookupSpecialFieldAccessor(
10451cb0ef41Sopenharmony_ci    MapRef map, NameRef name) const {
10461cb0ef41Sopenharmony_ci  // Check for String::length field accessor.
10471cb0ef41Sopenharmony_ci  if (map.object()->IsStringMap()) {
10481cb0ef41Sopenharmony_ci    if (Name::Equals(isolate(), name.object(),
10491cb0ef41Sopenharmony_ci                     isolate()->factory()->length_string())) {
10501cb0ef41Sopenharmony_ci      return PropertyAccessInfo::StringLength(zone(), map);
10511cb0ef41Sopenharmony_ci    }
10521cb0ef41Sopenharmony_ci    return Invalid();
10531cb0ef41Sopenharmony_ci  }
10541cb0ef41Sopenharmony_ci  // Check for special JSObject field accessors.
10551cb0ef41Sopenharmony_ci  FieldIndex field_index;
10561cb0ef41Sopenharmony_ci  if (Accessors::IsJSObjectFieldAccessor(isolate(), map.object(), name.object(),
10571cb0ef41Sopenharmony_ci                                         &field_index)) {
10581cb0ef41Sopenharmony_ci    Type field_type = Type::NonInternal();
10591cb0ef41Sopenharmony_ci    Representation field_representation = Representation::Tagged();
10601cb0ef41Sopenharmony_ci    if (map.object()->IsJSArrayMap()) {
10611cb0ef41Sopenharmony_ci      DCHECK(Name::Equals(isolate(), isolate()->factory()->length_string(),
10621cb0ef41Sopenharmony_ci                          name.object()));
10631cb0ef41Sopenharmony_ci      // The JSArray::length property is a smi in the range
10641cb0ef41Sopenharmony_ci      // [0, FixedDoubleArray::kMaxLength] in case of fast double
10651cb0ef41Sopenharmony_ci      // elements, a smi in the range [0, FixedArray::kMaxLength]
10661cb0ef41Sopenharmony_ci      // in case of other fast elements, and [0, kMaxUInt32] in
10671cb0ef41Sopenharmony_ci      // case of other arrays.
10681cb0ef41Sopenharmony_ci      if (IsDoubleElementsKind(map.elements_kind())) {
10691cb0ef41Sopenharmony_ci        field_type = type_cache_->kFixedDoubleArrayLengthType;
10701cb0ef41Sopenharmony_ci        field_representation = Representation::Smi();
10711cb0ef41Sopenharmony_ci      } else if (IsFastElementsKind(map.elements_kind())) {
10721cb0ef41Sopenharmony_ci        field_type = type_cache_->kFixedArrayLengthType;
10731cb0ef41Sopenharmony_ci        field_representation = Representation::Smi();
10741cb0ef41Sopenharmony_ci      } else {
10751cb0ef41Sopenharmony_ci        field_type = type_cache_->kJSArrayLengthType;
10761cb0ef41Sopenharmony_ci      }
10771cb0ef41Sopenharmony_ci    }
10781cb0ef41Sopenharmony_ci    // Special fields are always mutable.
10791cb0ef41Sopenharmony_ci    return PropertyAccessInfo::DataField(zone(), map, {{}, zone()}, field_index,
10801cb0ef41Sopenharmony_ci                                         field_representation, field_type, map,
10811cb0ef41Sopenharmony_ci                                         {}, {}, {});
10821cb0ef41Sopenharmony_ci  }
10831cb0ef41Sopenharmony_ci  return Invalid();
10841cb0ef41Sopenharmony_ci}
10851cb0ef41Sopenharmony_ci
10861cb0ef41Sopenharmony_ciPropertyAccessInfo AccessInfoFactory::LookupTransition(
10871cb0ef41Sopenharmony_ci    MapRef map, NameRef name, base::Optional<JSObjectRef> holder,
10881cb0ef41Sopenharmony_ci    PropertyAttributes attrs) const {
10891cb0ef41Sopenharmony_ci  // Check if the {map} has a data transition with the given {name}.
10901cb0ef41Sopenharmony_ci  Map transition =
10911cb0ef41Sopenharmony_ci      TransitionsAccessor(isolate(), *map.object(), true)
10921cb0ef41Sopenharmony_ci          .SearchTransition(*name.object(), PropertyKind::kData, attrs);
10931cb0ef41Sopenharmony_ci  if (transition.is_null()) return Invalid();
10941cb0ef41Sopenharmony_ci  base::Optional<MapRef> maybe_transition_map =
10951cb0ef41Sopenharmony_ci      TryMakeRef(broker(), transition);
10961cb0ef41Sopenharmony_ci  if (!maybe_transition_map.has_value()) return Invalid();
10971cb0ef41Sopenharmony_ci  MapRef transition_map = maybe_transition_map.value();
10981cb0ef41Sopenharmony_ci
10991cb0ef41Sopenharmony_ci  InternalIndex const number = transition_map.object()->LastAdded();
11001cb0ef41Sopenharmony_ci  Handle<DescriptorArray> descriptors =
11011cb0ef41Sopenharmony_ci      transition_map.instance_descriptors().object();
11021cb0ef41Sopenharmony_ci  PropertyDetails const details = descriptors->GetDetails(number);
11031cb0ef41Sopenharmony_ci
11041cb0ef41Sopenharmony_ci  // Don't bother optimizing stores to read-only properties.
11051cb0ef41Sopenharmony_ci  if (details.IsReadOnly()) return Invalid();
11061cb0ef41Sopenharmony_ci
11071cb0ef41Sopenharmony_ci  // TODO(bmeurer): Handle transition to data constant?
11081cb0ef41Sopenharmony_ci  if (details.location() != PropertyLocation::kField) return Invalid();
11091cb0ef41Sopenharmony_ci
11101cb0ef41Sopenharmony_ci  int const index = details.field_index();
11111cb0ef41Sopenharmony_ci  Representation details_representation = details.representation();
11121cb0ef41Sopenharmony_ci  if (details_representation.IsNone()) return Invalid();
11131cb0ef41Sopenharmony_ci
11141cb0ef41Sopenharmony_ci  FieldIndex field_index = FieldIndex::ForPropertyIndex(
11151cb0ef41Sopenharmony_ci      *transition_map.object(), index, details_representation);
11161cb0ef41Sopenharmony_ci  Type field_type = Type::NonInternal();
11171cb0ef41Sopenharmony_ci  base::Optional<MapRef> field_map;
11181cb0ef41Sopenharmony_ci
11191cb0ef41Sopenharmony_ci  ZoneVector<CompilationDependency const*> unrecorded_dependencies(zone());
11201cb0ef41Sopenharmony_ci  if (details_representation.IsSmi()) {
11211cb0ef41Sopenharmony_ci    field_type = Type::SignedSmall();
11221cb0ef41Sopenharmony_ci    unrecorded_dependencies.push_back(
11231cb0ef41Sopenharmony_ci        dependencies()->FieldRepresentationDependencyOffTheRecord(
11241cb0ef41Sopenharmony_ci            transition_map, number, details_representation));
11251cb0ef41Sopenharmony_ci  } else if (details_representation.IsDouble()) {
11261cb0ef41Sopenharmony_ci    field_type = type_cache_->kFloat64;
11271cb0ef41Sopenharmony_ci    unrecorded_dependencies.push_back(
11281cb0ef41Sopenharmony_ci        dependencies()->FieldRepresentationDependencyOffTheRecord(
11291cb0ef41Sopenharmony_ci            transition_map, number, details_representation));
11301cb0ef41Sopenharmony_ci  } else if (details_representation.IsHeapObject()) {
11311cb0ef41Sopenharmony_ci    // Extract the field type from the property details (make sure its
11321cb0ef41Sopenharmony_ci    // representation is TaggedPointer to reflect the heap object case).
11331cb0ef41Sopenharmony_ci    // TODO(jgruber,v8:7790): Use DescriptorArrayRef instead.
11341cb0ef41Sopenharmony_ci    Handle<FieldType> descriptors_field_type =
11351cb0ef41Sopenharmony_ci        broker()->CanonicalPersistentHandle(descriptors->GetFieldType(number));
11361cb0ef41Sopenharmony_ci    base::Optional<ObjectRef> descriptors_field_type_ref =
11371cb0ef41Sopenharmony_ci        TryMakeRef<Object>(broker(), descriptors_field_type);
11381cb0ef41Sopenharmony_ci    if (!descriptors_field_type_ref.has_value()) return Invalid();
11391cb0ef41Sopenharmony_ci
11401cb0ef41Sopenharmony_ci    if (descriptors_field_type->IsNone()) {
11411cb0ef41Sopenharmony_ci      // Store is not safe if the field type was cleared.
11421cb0ef41Sopenharmony_ci      return Invalid();
11431cb0ef41Sopenharmony_ci    }
11441cb0ef41Sopenharmony_ci    unrecorded_dependencies.push_back(
11451cb0ef41Sopenharmony_ci        dependencies()->FieldRepresentationDependencyOffTheRecord(
11461cb0ef41Sopenharmony_ci            transition_map, number, details_representation));
11471cb0ef41Sopenharmony_ci    if (descriptors_field_type->IsClass()) {
11481cb0ef41Sopenharmony_ci      unrecorded_dependencies.push_back(
11491cb0ef41Sopenharmony_ci          dependencies()->FieldTypeDependencyOffTheRecord(
11501cb0ef41Sopenharmony_ci              transition_map, number, *descriptors_field_type_ref));
11511cb0ef41Sopenharmony_ci      // Remember the field map, and try to infer a useful type.
11521cb0ef41Sopenharmony_ci      base::Optional<MapRef> maybe_field_map =
11531cb0ef41Sopenharmony_ci          TryMakeRef(broker(), descriptors_field_type->AsClass());
11541cb0ef41Sopenharmony_ci      if (!maybe_field_map.has_value()) return Invalid();
11551cb0ef41Sopenharmony_ci      field_type = Type::For(maybe_field_map.value());
11561cb0ef41Sopenharmony_ci      field_map = maybe_field_map;
11571cb0ef41Sopenharmony_ci    }
11581cb0ef41Sopenharmony_ci  }
11591cb0ef41Sopenharmony_ci
11601cb0ef41Sopenharmony_ci  unrecorded_dependencies.push_back(
11611cb0ef41Sopenharmony_ci      dependencies()->TransitionDependencyOffTheRecord(transition_map));
11621cb0ef41Sopenharmony_ci  // Transitioning stores *may* store to const fields. The resulting
11631cb0ef41Sopenharmony_ci  // DataConstant access infos can be distinguished from later, i.e. redundant,
11641cb0ef41Sopenharmony_ci  // stores to the same constant field by the presence of a transition map.
11651cb0ef41Sopenharmony_ci  switch (dependencies()->DependOnFieldConstness(transition_map, number)) {
11661cb0ef41Sopenharmony_ci    case PropertyConstness::kMutable:
11671cb0ef41Sopenharmony_ci      return PropertyAccessInfo::DataField(
11681cb0ef41Sopenharmony_ci          zone(), map, std::move(unrecorded_dependencies), field_index,
11691cb0ef41Sopenharmony_ci          details_representation, field_type, transition_map, field_map, holder,
11701cb0ef41Sopenharmony_ci          transition_map);
11711cb0ef41Sopenharmony_ci    case PropertyConstness::kConst:
11721cb0ef41Sopenharmony_ci      return PropertyAccessInfo::FastDataConstant(
11731cb0ef41Sopenharmony_ci          zone(), map, std::move(unrecorded_dependencies), field_index,
11741cb0ef41Sopenharmony_ci          details_representation, field_type, transition_map, field_map, holder,
11751cb0ef41Sopenharmony_ci          transition_map);
11761cb0ef41Sopenharmony_ci  }
11771cb0ef41Sopenharmony_ci  UNREACHABLE();
11781cb0ef41Sopenharmony_ci}
11791cb0ef41Sopenharmony_ci
11801cb0ef41Sopenharmony_ci}  // namespace compiler
11811cb0ef41Sopenharmony_ci}  // namespace internal
11821cb0ef41Sopenharmony_ci}  // namespace v8
1183