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/compiler/js-heap-broker.h" 61cb0ef41Sopenharmony_ci 71cb0ef41Sopenharmony_ci#ifdef ENABLE_SLOW_DCHECKS 81cb0ef41Sopenharmony_ci#include <algorithm> 91cb0ef41Sopenharmony_ci#endif 101cb0ef41Sopenharmony_ci 111cb0ef41Sopenharmony_ci#include "src/codegen/code-factory.h" 121cb0ef41Sopenharmony_ci#include "src/codegen/optimized-compilation-info.h" 131cb0ef41Sopenharmony_ci#include "src/handles/handles-inl.h" 141cb0ef41Sopenharmony_ci#include "src/heap/heap-inl.h" 151cb0ef41Sopenharmony_ci#include "src/ic/handler-configuration-inl.h" 161cb0ef41Sopenharmony_ci#include "src/init/bootstrapper.h" 171cb0ef41Sopenharmony_ci#include "src/objects/allocation-site-inl.h" 181cb0ef41Sopenharmony_ci#include "src/objects/data-handler-inl.h" 191cb0ef41Sopenharmony_ci#include "src/objects/feedback-cell.h" 201cb0ef41Sopenharmony_ci#include "src/objects/js-array-inl.h" 211cb0ef41Sopenharmony_ci#include "src/objects/literal-objects-inl.h" 221cb0ef41Sopenharmony_ci#include "src/objects/map-updater.h" 231cb0ef41Sopenharmony_ci#include "src/objects/objects-inl.h" 241cb0ef41Sopenharmony_ci#include "src/objects/oddball.h" 251cb0ef41Sopenharmony_ci#include "src/objects/property-cell.h" 261cb0ef41Sopenharmony_ci 271cb0ef41Sopenharmony_cinamespace v8 { 281cb0ef41Sopenharmony_cinamespace internal { 291cb0ef41Sopenharmony_cinamespace compiler { 301cb0ef41Sopenharmony_ci 311cb0ef41Sopenharmony_ci#define TRACE(broker, x) TRACE_BROKER(broker, x) 321cb0ef41Sopenharmony_ci 331cb0ef41Sopenharmony_ci#ifdef V8_STATIC_CONSTEXPR_VARIABLES_NEED_DEFINITIONS 341cb0ef41Sopenharmony_ci// These definitions are here in order to please the linker, which in debug mode 351cb0ef41Sopenharmony_ci// sometimes requires static constants to be defined in .cc files. 361cb0ef41Sopenharmony_ci// This is, however, deprecated (and unnecessary) in C++17. 371cb0ef41Sopenharmony_ciconst uint32_t JSHeapBroker::kMinimalRefsBucketCount; 381cb0ef41Sopenharmony_ciconst uint32_t JSHeapBroker::kInitialRefsBucketCount; 391cb0ef41Sopenharmony_ci#endif 401cb0ef41Sopenharmony_ci 411cb0ef41Sopenharmony_civoid JSHeapBroker::IncrementTracingIndentation() { ++trace_indentation_; } 421cb0ef41Sopenharmony_ci 431cb0ef41Sopenharmony_civoid JSHeapBroker::DecrementTracingIndentation() { --trace_indentation_; } 441cb0ef41Sopenharmony_ci 451cb0ef41Sopenharmony_ciJSHeapBroker::JSHeapBroker(Isolate* isolate, Zone* broker_zone, 461cb0ef41Sopenharmony_ci bool tracing_enabled, CodeKind code_kind) 471cb0ef41Sopenharmony_ci : isolate_(isolate), 481cb0ef41Sopenharmony_ci#if V8_COMPRESS_POINTERS 491cb0ef41Sopenharmony_ci cage_base_(isolate), 501cb0ef41Sopenharmony_ci#endif // V8_COMPRESS_POINTERS 511cb0ef41Sopenharmony_ci zone_(broker_zone), 521cb0ef41Sopenharmony_ci // Note that this initialization of {refs_} with the minimal initial 531cb0ef41Sopenharmony_ci // capacity is redundant in the normal use case (concurrent compilation 541cb0ef41Sopenharmony_ci // enabled, standard objects to be serialized), as the map is going to be 551cb0ef41Sopenharmony_ci // replaced immediately with a larger-capacity one. It doesn't seem to 561cb0ef41Sopenharmony_ci // affect the performance in a noticeable way though. 571cb0ef41Sopenharmony_ci refs_(zone()->New<RefsMap>(kMinimalRefsBucketCount, AddressMatcher(), 581cb0ef41Sopenharmony_ci zone())), 591cb0ef41Sopenharmony_ci root_index_map_(isolate), 601cb0ef41Sopenharmony_ci array_and_object_prototypes_(zone()), 611cb0ef41Sopenharmony_ci tracing_enabled_(tracing_enabled), 621cb0ef41Sopenharmony_ci code_kind_(code_kind), 631cb0ef41Sopenharmony_ci feedback_(zone()), 641cb0ef41Sopenharmony_ci property_access_infos_(zone()) { 651cb0ef41Sopenharmony_ci TRACE(this, "Constructing heap broker"); 661cb0ef41Sopenharmony_ci} 671cb0ef41Sopenharmony_ci 681cb0ef41Sopenharmony_ciJSHeapBroker::~JSHeapBroker() { DCHECK_NULL(local_isolate_); } 691cb0ef41Sopenharmony_ci 701cb0ef41Sopenharmony_civoid JSHeapBroker::SetPersistentAndCopyCanonicalHandlesForTesting( 711cb0ef41Sopenharmony_ci std::unique_ptr<PersistentHandles> persistent_handles, 721cb0ef41Sopenharmony_ci std::unique_ptr<CanonicalHandlesMap> canonical_handles) { 731cb0ef41Sopenharmony_ci set_persistent_handles(std::move(persistent_handles)); 741cb0ef41Sopenharmony_ci CopyCanonicalHandlesForTesting(std::move(canonical_handles)); 751cb0ef41Sopenharmony_ci} 761cb0ef41Sopenharmony_ci 771cb0ef41Sopenharmony_civoid JSHeapBroker::CopyCanonicalHandlesForTesting( 781cb0ef41Sopenharmony_ci std::unique_ptr<CanonicalHandlesMap> canonical_handles) { 791cb0ef41Sopenharmony_ci DCHECK_NULL(canonical_handles_); 801cb0ef41Sopenharmony_ci canonical_handles_ = std::make_unique<CanonicalHandlesMap>( 811cb0ef41Sopenharmony_ci isolate_->heap(), ZoneAllocationPolicy(zone())); 821cb0ef41Sopenharmony_ci 831cb0ef41Sopenharmony_ci CanonicalHandlesMap::IteratableScope it_scope(canonical_handles.get()); 841cb0ef41Sopenharmony_ci for (auto it = it_scope.begin(); it != it_scope.end(); ++it) { 851cb0ef41Sopenharmony_ci Address* entry = *it.entry(); 861cb0ef41Sopenharmony_ci Object key = it.key(); 871cb0ef41Sopenharmony_ci canonical_handles_->Insert(key, entry); 881cb0ef41Sopenharmony_ci } 891cb0ef41Sopenharmony_ci} 901cb0ef41Sopenharmony_ci 911cb0ef41Sopenharmony_cistd::string JSHeapBroker::Trace() const { 921cb0ef41Sopenharmony_ci std::ostringstream oss; 931cb0ef41Sopenharmony_ci oss << "[" << this << "] "; 941cb0ef41Sopenharmony_ci for (unsigned i = 0; i < trace_indentation_ * 2; ++i) oss.put(' '); 951cb0ef41Sopenharmony_ci return oss.str(); 961cb0ef41Sopenharmony_ci} 971cb0ef41Sopenharmony_ci 981cb0ef41Sopenharmony_civoid JSHeapBroker::AttachLocalIsolate(OptimizedCompilationInfo* info, 991cb0ef41Sopenharmony_ci LocalIsolate* local_isolate) { 1001cb0ef41Sopenharmony_ci set_canonical_handles(info->DetachCanonicalHandles()); 1011cb0ef41Sopenharmony_ci DCHECK_NULL(local_isolate_); 1021cb0ef41Sopenharmony_ci local_isolate_ = local_isolate; 1031cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(local_isolate_); 1041cb0ef41Sopenharmony_ci local_isolate_->heap()->AttachPersistentHandles( 1051cb0ef41Sopenharmony_ci info->DetachPersistentHandles()); 1061cb0ef41Sopenharmony_ci} 1071cb0ef41Sopenharmony_ci 1081cb0ef41Sopenharmony_civoid JSHeapBroker::DetachLocalIsolate(OptimizedCompilationInfo* info) { 1091cb0ef41Sopenharmony_ci DCHECK_NULL(ph_); 1101cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(local_isolate_); 1111cb0ef41Sopenharmony_ci std::unique_ptr<PersistentHandles> ph = 1121cb0ef41Sopenharmony_ci local_isolate_->heap()->DetachPersistentHandles(); 1131cb0ef41Sopenharmony_ci local_isolate_ = nullptr; 1141cb0ef41Sopenharmony_ci info->set_canonical_handles(DetachCanonicalHandles()); 1151cb0ef41Sopenharmony_ci info->set_persistent_handles(std::move(ph)); 1161cb0ef41Sopenharmony_ci} 1171cb0ef41Sopenharmony_ci 1181cb0ef41Sopenharmony_civoid JSHeapBroker::StopSerializing() { 1191cb0ef41Sopenharmony_ci CHECK_EQ(mode_, kSerializing); 1201cb0ef41Sopenharmony_ci TRACE(this, "Stopping serialization"); 1211cb0ef41Sopenharmony_ci mode_ = kSerialized; 1221cb0ef41Sopenharmony_ci} 1231cb0ef41Sopenharmony_ci 1241cb0ef41Sopenharmony_civoid JSHeapBroker::Retire() { 1251cb0ef41Sopenharmony_ci CHECK_EQ(mode_, kSerialized); 1261cb0ef41Sopenharmony_ci TRACE(this, "Retiring"); 1271cb0ef41Sopenharmony_ci mode_ = kRetired; 1281cb0ef41Sopenharmony_ci} 1291cb0ef41Sopenharmony_ci 1301cb0ef41Sopenharmony_civoid JSHeapBroker::SetTargetNativeContextRef( 1311cb0ef41Sopenharmony_ci Handle<NativeContext> native_context) { 1321cb0ef41Sopenharmony_ci DCHECK((mode() == kDisabled && !target_native_context_.has_value()) || 1331cb0ef41Sopenharmony_ci (mode() == kSerializing && 1341cb0ef41Sopenharmony_ci target_native_context_->object().is_identical_to(native_context))); 1351cb0ef41Sopenharmony_ci target_native_context_ = MakeRef(this, *native_context); 1361cb0ef41Sopenharmony_ci} 1371cb0ef41Sopenharmony_ci 1381cb0ef41Sopenharmony_civoid JSHeapBroker::CollectArrayAndObjectPrototypes() { 1391cb0ef41Sopenharmony_ci DisallowGarbageCollection no_gc; 1401cb0ef41Sopenharmony_ci CHECK_EQ(mode(), kSerializing); 1411cb0ef41Sopenharmony_ci CHECK(array_and_object_prototypes_.empty()); 1421cb0ef41Sopenharmony_ci 1431cb0ef41Sopenharmony_ci Object maybe_context = isolate()->heap()->native_contexts_list(); 1441cb0ef41Sopenharmony_ci while (!maybe_context.IsUndefined(isolate())) { 1451cb0ef41Sopenharmony_ci Context context = Context::cast(maybe_context); 1461cb0ef41Sopenharmony_ci Object array_prot = context.get(Context::INITIAL_ARRAY_PROTOTYPE_INDEX); 1471cb0ef41Sopenharmony_ci Object object_prot = context.get(Context::INITIAL_OBJECT_PROTOTYPE_INDEX); 1481cb0ef41Sopenharmony_ci array_and_object_prototypes_.emplace(JSObject::cast(array_prot), isolate()); 1491cb0ef41Sopenharmony_ci array_and_object_prototypes_.emplace(JSObject::cast(object_prot), 1501cb0ef41Sopenharmony_ci isolate()); 1511cb0ef41Sopenharmony_ci maybe_context = context.next_context_link(); 1521cb0ef41Sopenharmony_ci } 1531cb0ef41Sopenharmony_ci 1541cb0ef41Sopenharmony_ci CHECK(!array_and_object_prototypes_.empty()); 1551cb0ef41Sopenharmony_ci} 1561cb0ef41Sopenharmony_ci 1571cb0ef41Sopenharmony_ciStringRef JSHeapBroker::GetTypedArrayStringTag(ElementsKind kind) { 1581cb0ef41Sopenharmony_ci DCHECK(IsTypedArrayElementsKind(kind)); 1591cb0ef41Sopenharmony_ci switch (kind) { 1601cb0ef41Sopenharmony_ci#define TYPED_ARRAY_STRING_TAG(Type, type, TYPE, ctype) \ 1611cb0ef41Sopenharmony_ci case ElementsKind::TYPE##_ELEMENTS: \ 1621cb0ef41Sopenharmony_ci return MakeRef(this, isolate()->factory()->Type##Array_string()); 1631cb0ef41Sopenharmony_ci TYPED_ARRAYS(TYPED_ARRAY_STRING_TAG) 1641cb0ef41Sopenharmony_ci#undef TYPED_ARRAY_STRING_TAG 1651cb0ef41Sopenharmony_ci default: 1661cb0ef41Sopenharmony_ci UNREACHABLE(); 1671cb0ef41Sopenharmony_ci } 1681cb0ef41Sopenharmony_ci} 1691cb0ef41Sopenharmony_ci 1701cb0ef41Sopenharmony_cibool JSHeapBroker::IsArrayOrObjectPrototype(const JSObjectRef& object) const { 1711cb0ef41Sopenharmony_ci return IsArrayOrObjectPrototype(object.object()); 1721cb0ef41Sopenharmony_ci} 1731cb0ef41Sopenharmony_ci 1741cb0ef41Sopenharmony_cibool JSHeapBroker::IsArrayOrObjectPrototype(Handle<JSObject> object) const { 1751cb0ef41Sopenharmony_ci if (mode() == kDisabled) { 1761cb0ef41Sopenharmony_ci return isolate()->IsInAnyContext(*object, 1771cb0ef41Sopenharmony_ci Context::INITIAL_ARRAY_PROTOTYPE_INDEX) || 1781cb0ef41Sopenharmony_ci isolate()->IsInAnyContext(*object, 1791cb0ef41Sopenharmony_ci Context::INITIAL_OBJECT_PROTOTYPE_INDEX); 1801cb0ef41Sopenharmony_ci } 1811cb0ef41Sopenharmony_ci CHECK(!array_and_object_prototypes_.empty()); 1821cb0ef41Sopenharmony_ci return array_and_object_prototypes_.find(object) != 1831cb0ef41Sopenharmony_ci array_and_object_prototypes_.end(); 1841cb0ef41Sopenharmony_ci} 1851cb0ef41Sopenharmony_ci 1861cb0ef41Sopenharmony_ciObjectData* JSHeapBroker::TryGetOrCreateData(Object object, 1871cb0ef41Sopenharmony_ci GetOrCreateDataFlags flags) { 1881cb0ef41Sopenharmony_ci return TryGetOrCreateData(CanonicalPersistentHandle(object), flags); 1891cb0ef41Sopenharmony_ci} 1901cb0ef41Sopenharmony_ci 1911cb0ef41Sopenharmony_ciObjectData* JSHeapBroker::GetOrCreateData(Handle<Object> object, 1921cb0ef41Sopenharmony_ci GetOrCreateDataFlags flags) { 1931cb0ef41Sopenharmony_ci ObjectData* return_value = TryGetOrCreateData(object, flags | kCrashOnError); 1941cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(return_value); 1951cb0ef41Sopenharmony_ci return return_value; 1961cb0ef41Sopenharmony_ci} 1971cb0ef41Sopenharmony_ci 1981cb0ef41Sopenharmony_ciObjectData* JSHeapBroker::GetOrCreateData(Object object, 1991cb0ef41Sopenharmony_ci GetOrCreateDataFlags flags) { 2001cb0ef41Sopenharmony_ci return GetOrCreateData(CanonicalPersistentHandle(object), flags); 2011cb0ef41Sopenharmony_ci} 2021cb0ef41Sopenharmony_ci 2031cb0ef41Sopenharmony_cibool JSHeapBroker::StackHasOverflowed() const { 2041cb0ef41Sopenharmony_ci DCHECK_IMPLIES(local_isolate_ == nullptr, 2051cb0ef41Sopenharmony_ci ThreadId::Current() == isolate_->thread_id()); 2061cb0ef41Sopenharmony_ci return (local_isolate_ != nullptr) 2071cb0ef41Sopenharmony_ci ? StackLimitCheck::HasOverflowed(local_isolate_) 2081cb0ef41Sopenharmony_ci : StackLimitCheck(isolate_).HasOverflowed(); 2091cb0ef41Sopenharmony_ci} 2101cb0ef41Sopenharmony_ci 2111cb0ef41Sopenharmony_cibool JSHeapBroker::ObjectMayBeUninitialized(Handle<Object> object) const { 2121cb0ef41Sopenharmony_ci return ObjectMayBeUninitialized(*object); 2131cb0ef41Sopenharmony_ci} 2141cb0ef41Sopenharmony_ci 2151cb0ef41Sopenharmony_cibool JSHeapBroker::ObjectMayBeUninitialized(Object object) const { 2161cb0ef41Sopenharmony_ci if (!object.IsHeapObject()) return false; 2171cb0ef41Sopenharmony_ci return ObjectMayBeUninitialized(HeapObject::cast(object)); 2181cb0ef41Sopenharmony_ci} 2191cb0ef41Sopenharmony_ci 2201cb0ef41Sopenharmony_cibool JSHeapBroker::ObjectMayBeUninitialized(HeapObject object) const { 2211cb0ef41Sopenharmony_ci return !IsMainThread() && isolate()->heap()->IsPendingAllocation(object); 2221cb0ef41Sopenharmony_ci} 2231cb0ef41Sopenharmony_ci 2241cb0ef41Sopenharmony_ciProcessedFeedback::ProcessedFeedback(Kind kind, FeedbackSlotKind slot_kind) 2251cb0ef41Sopenharmony_ci : kind_(kind), slot_kind_(slot_kind) {} 2261cb0ef41Sopenharmony_ci 2271cb0ef41Sopenharmony_ciKeyedAccessMode ElementAccessFeedback::keyed_mode() const { 2281cb0ef41Sopenharmony_ci return keyed_mode_; 2291cb0ef41Sopenharmony_ci} 2301cb0ef41Sopenharmony_ci 2311cb0ef41Sopenharmony_ciZoneVector<ElementAccessFeedback::TransitionGroup> const& 2321cb0ef41Sopenharmony_ciElementAccessFeedback::transition_groups() const { 2331cb0ef41Sopenharmony_ci return transition_groups_; 2341cb0ef41Sopenharmony_ci} 2351cb0ef41Sopenharmony_ci 2361cb0ef41Sopenharmony_ciElementAccessFeedback const& ElementAccessFeedback::Refine( 2371cb0ef41Sopenharmony_ci JSHeapBroker* broker, ZoneVector<MapRef> const& inferred_maps) const { 2381cb0ef41Sopenharmony_ci ElementAccessFeedback& refined_feedback = 2391cb0ef41Sopenharmony_ci *broker->zone()->New<ElementAccessFeedback>(broker->zone(), keyed_mode(), 2401cb0ef41Sopenharmony_ci slot_kind()); 2411cb0ef41Sopenharmony_ci if (inferred_maps.empty()) return refined_feedback; 2421cb0ef41Sopenharmony_ci 2431cb0ef41Sopenharmony_ci ZoneRefUnorderedSet<MapRef> inferred(broker->zone()); 2441cb0ef41Sopenharmony_ci inferred.insert(inferred_maps.begin(), inferred_maps.end()); 2451cb0ef41Sopenharmony_ci 2461cb0ef41Sopenharmony_ci for (auto const& group : transition_groups()) { 2471cb0ef41Sopenharmony_ci DCHECK(!group.empty()); 2481cb0ef41Sopenharmony_ci TransitionGroup new_group(broker->zone()); 2491cb0ef41Sopenharmony_ci for (size_t i = 1; i < group.size(); ++i) { 2501cb0ef41Sopenharmony_ci MapRef source = MakeRefAssumeMemoryFence(broker, *group[i]); 2511cb0ef41Sopenharmony_ci if (inferred.find(source) != inferred.end()) { 2521cb0ef41Sopenharmony_ci new_group.push_back(source.object()); 2531cb0ef41Sopenharmony_ci } 2541cb0ef41Sopenharmony_ci } 2551cb0ef41Sopenharmony_ci 2561cb0ef41Sopenharmony_ci MapRef target = MakeRefAssumeMemoryFence(broker, *group.front()); 2571cb0ef41Sopenharmony_ci bool const keep_target = 2581cb0ef41Sopenharmony_ci inferred.find(target) != inferred.end() || new_group.size() > 1; 2591cb0ef41Sopenharmony_ci if (keep_target) { 2601cb0ef41Sopenharmony_ci new_group.push_back(target.object()); 2611cb0ef41Sopenharmony_ci // The target must be at the front, the order of sources doesn't matter. 2621cb0ef41Sopenharmony_ci std::swap(new_group[0], new_group[new_group.size() - 1]); 2631cb0ef41Sopenharmony_ci } 2641cb0ef41Sopenharmony_ci 2651cb0ef41Sopenharmony_ci if (!new_group.empty()) { 2661cb0ef41Sopenharmony_ci DCHECK(new_group.size() == 1 || 2671cb0ef41Sopenharmony_ci new_group.front().equals(target.object())); 2681cb0ef41Sopenharmony_ci refined_feedback.transition_groups_.push_back(std::move(new_group)); 2691cb0ef41Sopenharmony_ci } 2701cb0ef41Sopenharmony_ci } 2711cb0ef41Sopenharmony_ci return refined_feedback; 2721cb0ef41Sopenharmony_ci} 2731cb0ef41Sopenharmony_ci 2741cb0ef41Sopenharmony_ciInsufficientFeedback::InsufficientFeedback(FeedbackSlotKind slot_kind) 2751cb0ef41Sopenharmony_ci : ProcessedFeedback(kInsufficient, slot_kind) {} 2761cb0ef41Sopenharmony_ci 2771cb0ef41Sopenharmony_ciGlobalAccessFeedback::GlobalAccessFeedback(PropertyCellRef cell, 2781cb0ef41Sopenharmony_ci FeedbackSlotKind slot_kind) 2791cb0ef41Sopenharmony_ci : ProcessedFeedback(kGlobalAccess, slot_kind), 2801cb0ef41Sopenharmony_ci cell_or_context_(cell), 2811cb0ef41Sopenharmony_ci index_and_immutable_(0 /* doesn't matter */) { 2821cb0ef41Sopenharmony_ci DCHECK(IsGlobalICKind(slot_kind)); 2831cb0ef41Sopenharmony_ci} 2841cb0ef41Sopenharmony_ci 2851cb0ef41Sopenharmony_ciGlobalAccessFeedback::GlobalAccessFeedback(FeedbackSlotKind slot_kind) 2861cb0ef41Sopenharmony_ci : ProcessedFeedback(kGlobalAccess, slot_kind), 2871cb0ef41Sopenharmony_ci index_and_immutable_(0 /* doesn't matter */) { 2881cb0ef41Sopenharmony_ci DCHECK(IsGlobalICKind(slot_kind)); 2891cb0ef41Sopenharmony_ci} 2901cb0ef41Sopenharmony_ci 2911cb0ef41Sopenharmony_ciGlobalAccessFeedback::GlobalAccessFeedback(ContextRef script_context, 2921cb0ef41Sopenharmony_ci int slot_index, bool immutable, 2931cb0ef41Sopenharmony_ci FeedbackSlotKind slot_kind) 2941cb0ef41Sopenharmony_ci : ProcessedFeedback(kGlobalAccess, slot_kind), 2951cb0ef41Sopenharmony_ci cell_or_context_(script_context), 2961cb0ef41Sopenharmony_ci index_and_immutable_(FeedbackNexus::SlotIndexBits::encode(slot_index) | 2971cb0ef41Sopenharmony_ci FeedbackNexus::ImmutabilityBit::encode(immutable)) { 2981cb0ef41Sopenharmony_ci DCHECK_EQ(this->slot_index(), slot_index); 2991cb0ef41Sopenharmony_ci DCHECK_EQ(this->immutable(), immutable); 3001cb0ef41Sopenharmony_ci DCHECK(IsGlobalICKind(slot_kind)); 3011cb0ef41Sopenharmony_ci} 3021cb0ef41Sopenharmony_ci 3031cb0ef41Sopenharmony_cibool GlobalAccessFeedback::IsMegamorphic() const { 3041cb0ef41Sopenharmony_ci return !cell_or_context_.has_value(); 3051cb0ef41Sopenharmony_ci} 3061cb0ef41Sopenharmony_cibool GlobalAccessFeedback::IsPropertyCell() const { 3071cb0ef41Sopenharmony_ci return cell_or_context_.has_value() && cell_or_context_->IsPropertyCell(); 3081cb0ef41Sopenharmony_ci} 3091cb0ef41Sopenharmony_cibool GlobalAccessFeedback::IsScriptContextSlot() const { 3101cb0ef41Sopenharmony_ci return cell_or_context_.has_value() && cell_or_context_->IsContext(); 3111cb0ef41Sopenharmony_ci} 3121cb0ef41Sopenharmony_ciPropertyCellRef GlobalAccessFeedback::property_cell() const { 3131cb0ef41Sopenharmony_ci CHECK(IsPropertyCell()); 3141cb0ef41Sopenharmony_ci return cell_or_context_->AsPropertyCell(); 3151cb0ef41Sopenharmony_ci} 3161cb0ef41Sopenharmony_ciContextRef GlobalAccessFeedback::script_context() const { 3171cb0ef41Sopenharmony_ci CHECK(IsScriptContextSlot()); 3181cb0ef41Sopenharmony_ci return cell_or_context_->AsContext(); 3191cb0ef41Sopenharmony_ci} 3201cb0ef41Sopenharmony_ciint GlobalAccessFeedback::slot_index() const { 3211cb0ef41Sopenharmony_ci DCHECK(IsScriptContextSlot()); 3221cb0ef41Sopenharmony_ci return FeedbackNexus::SlotIndexBits::decode(index_and_immutable_); 3231cb0ef41Sopenharmony_ci} 3241cb0ef41Sopenharmony_cibool GlobalAccessFeedback::immutable() const { 3251cb0ef41Sopenharmony_ci DCHECK(IsScriptContextSlot()); 3261cb0ef41Sopenharmony_ci return FeedbackNexus::ImmutabilityBit::decode(index_and_immutable_); 3271cb0ef41Sopenharmony_ci} 3281cb0ef41Sopenharmony_ci 3291cb0ef41Sopenharmony_cibase::Optional<ObjectRef> GlobalAccessFeedback::GetConstantHint() const { 3301cb0ef41Sopenharmony_ci if (IsPropertyCell()) { 3311cb0ef41Sopenharmony_ci bool cell_cached = property_cell().Cache(); 3321cb0ef41Sopenharmony_ci CHECK(cell_cached); // Can't fail on the main thread. 3331cb0ef41Sopenharmony_ci return property_cell().value(); 3341cb0ef41Sopenharmony_ci } else if (IsScriptContextSlot() && immutable()) { 3351cb0ef41Sopenharmony_ci return script_context().get(slot_index()); 3361cb0ef41Sopenharmony_ci } else { 3371cb0ef41Sopenharmony_ci return base::nullopt; 3381cb0ef41Sopenharmony_ci } 3391cb0ef41Sopenharmony_ci} 3401cb0ef41Sopenharmony_ci 3411cb0ef41Sopenharmony_ciKeyedAccessMode KeyedAccessMode::FromNexus(FeedbackNexus const& nexus) { 3421cb0ef41Sopenharmony_ci FeedbackSlotKind kind = nexus.kind(); 3431cb0ef41Sopenharmony_ci if (IsKeyedLoadICKind(kind)) { 3441cb0ef41Sopenharmony_ci return KeyedAccessMode(AccessMode::kLoad, nexus.GetKeyedAccessLoadMode()); 3451cb0ef41Sopenharmony_ci } 3461cb0ef41Sopenharmony_ci if (IsKeyedHasICKind(kind)) { 3471cb0ef41Sopenharmony_ci return KeyedAccessMode(AccessMode::kHas, nexus.GetKeyedAccessLoadMode()); 3481cb0ef41Sopenharmony_ci } 3491cb0ef41Sopenharmony_ci if (IsDefineKeyedOwnICKind(kind)) { 3501cb0ef41Sopenharmony_ci return KeyedAccessMode(AccessMode::kDefine, 3511cb0ef41Sopenharmony_ci nexus.GetKeyedAccessStoreMode()); 3521cb0ef41Sopenharmony_ci } 3531cb0ef41Sopenharmony_ci if (IsKeyedStoreICKind(kind)) { 3541cb0ef41Sopenharmony_ci return KeyedAccessMode(AccessMode::kStore, nexus.GetKeyedAccessStoreMode()); 3551cb0ef41Sopenharmony_ci } 3561cb0ef41Sopenharmony_ci if (IsStoreInArrayLiteralICKind(kind) || 3571cb0ef41Sopenharmony_ci IsDefineKeyedOwnPropertyInLiteralKind(kind)) { 3581cb0ef41Sopenharmony_ci return KeyedAccessMode(AccessMode::kStoreInLiteral, 3591cb0ef41Sopenharmony_ci nexus.GetKeyedAccessStoreMode()); 3601cb0ef41Sopenharmony_ci } 3611cb0ef41Sopenharmony_ci UNREACHABLE(); 3621cb0ef41Sopenharmony_ci} 3631cb0ef41Sopenharmony_ci 3641cb0ef41Sopenharmony_ciAccessMode KeyedAccessMode::access_mode() const { return access_mode_; } 3651cb0ef41Sopenharmony_ci 3661cb0ef41Sopenharmony_cibool KeyedAccessMode::IsLoad() const { 3671cb0ef41Sopenharmony_ci return access_mode_ == AccessMode::kLoad || access_mode_ == AccessMode::kHas; 3681cb0ef41Sopenharmony_ci} 3691cb0ef41Sopenharmony_cibool KeyedAccessMode::IsStore() const { 3701cb0ef41Sopenharmony_ci return access_mode_ == AccessMode::kStore || 3711cb0ef41Sopenharmony_ci access_mode_ == AccessMode::kDefine || 3721cb0ef41Sopenharmony_ci access_mode_ == AccessMode::kStoreInLiteral; 3731cb0ef41Sopenharmony_ci} 3741cb0ef41Sopenharmony_ci 3751cb0ef41Sopenharmony_ciKeyedAccessLoadMode KeyedAccessMode::load_mode() const { 3761cb0ef41Sopenharmony_ci CHECK(IsLoad()); 3771cb0ef41Sopenharmony_ci return load_store_mode_.load_mode; 3781cb0ef41Sopenharmony_ci} 3791cb0ef41Sopenharmony_ci 3801cb0ef41Sopenharmony_ciKeyedAccessStoreMode KeyedAccessMode::store_mode() const { 3811cb0ef41Sopenharmony_ci CHECK(IsStore()); 3821cb0ef41Sopenharmony_ci return load_store_mode_.store_mode; 3831cb0ef41Sopenharmony_ci} 3841cb0ef41Sopenharmony_ci 3851cb0ef41Sopenharmony_ciKeyedAccessMode::LoadStoreMode::LoadStoreMode(KeyedAccessLoadMode load_mode) 3861cb0ef41Sopenharmony_ci : load_mode(load_mode) {} 3871cb0ef41Sopenharmony_ciKeyedAccessMode::LoadStoreMode::LoadStoreMode(KeyedAccessStoreMode store_mode) 3881cb0ef41Sopenharmony_ci : store_mode(store_mode) {} 3891cb0ef41Sopenharmony_ci 3901cb0ef41Sopenharmony_ciKeyedAccessMode::KeyedAccessMode(AccessMode access_mode, 3911cb0ef41Sopenharmony_ci KeyedAccessLoadMode load_mode) 3921cb0ef41Sopenharmony_ci : access_mode_(access_mode), load_store_mode_(load_mode) { 3931cb0ef41Sopenharmony_ci CHECK(!IsStore()); 3941cb0ef41Sopenharmony_ci CHECK(IsLoad()); 3951cb0ef41Sopenharmony_ci} 3961cb0ef41Sopenharmony_ciKeyedAccessMode::KeyedAccessMode(AccessMode access_mode, 3971cb0ef41Sopenharmony_ci KeyedAccessStoreMode store_mode) 3981cb0ef41Sopenharmony_ci : access_mode_(access_mode), load_store_mode_(store_mode) { 3991cb0ef41Sopenharmony_ci CHECK(!IsLoad()); 4001cb0ef41Sopenharmony_ci CHECK(IsStore()); 4011cb0ef41Sopenharmony_ci} 4021cb0ef41Sopenharmony_ci 4031cb0ef41Sopenharmony_ciElementAccessFeedback::ElementAccessFeedback(Zone* zone, 4041cb0ef41Sopenharmony_ci KeyedAccessMode const& keyed_mode, 4051cb0ef41Sopenharmony_ci FeedbackSlotKind slot_kind) 4061cb0ef41Sopenharmony_ci : ProcessedFeedback(kElementAccess, slot_kind), 4071cb0ef41Sopenharmony_ci keyed_mode_(keyed_mode), 4081cb0ef41Sopenharmony_ci transition_groups_(zone) { 4091cb0ef41Sopenharmony_ci DCHECK(IsKeyedLoadICKind(slot_kind) || IsKeyedHasICKind(slot_kind) || 4101cb0ef41Sopenharmony_ci IsDefineKeyedOwnPropertyInLiteralKind(slot_kind) || 4111cb0ef41Sopenharmony_ci IsKeyedStoreICKind(slot_kind) || 4121cb0ef41Sopenharmony_ci IsStoreInArrayLiteralICKind(slot_kind) || 4131cb0ef41Sopenharmony_ci IsDefineKeyedOwnICKind(slot_kind)); 4141cb0ef41Sopenharmony_ci} 4151cb0ef41Sopenharmony_ci 4161cb0ef41Sopenharmony_cibool ElementAccessFeedback::HasOnlyStringMaps(JSHeapBroker* broker) const { 4171cb0ef41Sopenharmony_ci for (auto const& group : transition_groups()) { 4181cb0ef41Sopenharmony_ci for (Handle<Map> map : group) { 4191cb0ef41Sopenharmony_ci // We assume a memory fence because {map} was read earlier from 4201cb0ef41Sopenharmony_ci // the feedback vector and was store ordered on insertion into the 4211cb0ef41Sopenharmony_ci // vector. 4221cb0ef41Sopenharmony_ci if (!MakeRefAssumeMemoryFence(broker, map).IsStringMap()) return false; 4231cb0ef41Sopenharmony_ci } 4241cb0ef41Sopenharmony_ci } 4251cb0ef41Sopenharmony_ci return true; 4261cb0ef41Sopenharmony_ci} 4271cb0ef41Sopenharmony_ci 4281cb0ef41Sopenharmony_ciNamedAccessFeedback::NamedAccessFeedback(NameRef const& name, 4291cb0ef41Sopenharmony_ci ZoneVector<MapRef> const& maps, 4301cb0ef41Sopenharmony_ci FeedbackSlotKind slot_kind) 4311cb0ef41Sopenharmony_ci : ProcessedFeedback(kNamedAccess, slot_kind), name_(name), maps_(maps) { 4321cb0ef41Sopenharmony_ci DCHECK(IsLoadICKind(slot_kind) || IsSetNamedICKind(slot_kind) || 4331cb0ef41Sopenharmony_ci IsDefineNamedOwnICKind(slot_kind) || IsKeyedLoadICKind(slot_kind) || 4341cb0ef41Sopenharmony_ci IsKeyedHasICKind(slot_kind) || IsKeyedStoreICKind(slot_kind) || 4351cb0ef41Sopenharmony_ci IsStoreInArrayLiteralICKind(slot_kind) || 4361cb0ef41Sopenharmony_ci IsDefineKeyedOwnPropertyInLiteralKind(slot_kind) || 4371cb0ef41Sopenharmony_ci IsDefineKeyedOwnICKind(slot_kind)); 4381cb0ef41Sopenharmony_ci} 4391cb0ef41Sopenharmony_ci 4401cb0ef41Sopenharmony_civoid JSHeapBroker::SetFeedback(FeedbackSource const& source, 4411cb0ef41Sopenharmony_ci ProcessedFeedback const* feedback) { 4421cb0ef41Sopenharmony_ci CHECK(source.IsValid()); 4431cb0ef41Sopenharmony_ci auto insertion = feedback_.insert({source, feedback}); 4441cb0ef41Sopenharmony_ci CHECK(insertion.second); 4451cb0ef41Sopenharmony_ci} 4461cb0ef41Sopenharmony_ci 4471cb0ef41Sopenharmony_cibool JSHeapBroker::HasFeedback(FeedbackSource const& source) const { 4481cb0ef41Sopenharmony_ci DCHECK(source.IsValid()); 4491cb0ef41Sopenharmony_ci return feedback_.find(source) != feedback_.end(); 4501cb0ef41Sopenharmony_ci} 4511cb0ef41Sopenharmony_ci 4521cb0ef41Sopenharmony_ciProcessedFeedback const& JSHeapBroker::GetFeedback( 4531cb0ef41Sopenharmony_ci FeedbackSource const& source) const { 4541cb0ef41Sopenharmony_ci DCHECK(source.IsValid()); 4551cb0ef41Sopenharmony_ci auto it = feedback_.find(source); 4561cb0ef41Sopenharmony_ci CHECK_NE(it, feedback_.end()); 4571cb0ef41Sopenharmony_ci return *it->second; 4581cb0ef41Sopenharmony_ci} 4591cb0ef41Sopenharmony_ci 4601cb0ef41Sopenharmony_ciFeedbackSlotKind JSHeapBroker::GetFeedbackSlotKind( 4611cb0ef41Sopenharmony_ci FeedbackSource const& source) const { 4621cb0ef41Sopenharmony_ci if (HasFeedback(source)) return GetFeedback(source).slot_kind(); 4631cb0ef41Sopenharmony_ci FeedbackNexus nexus(source.vector, source.slot, feedback_nexus_config()); 4641cb0ef41Sopenharmony_ci return nexus.kind(); 4651cb0ef41Sopenharmony_ci} 4661cb0ef41Sopenharmony_ci 4671cb0ef41Sopenharmony_cibool JSHeapBroker::FeedbackIsInsufficient(FeedbackSource const& source) const { 4681cb0ef41Sopenharmony_ci if (HasFeedback(source)) return GetFeedback(source).IsInsufficient(); 4691cb0ef41Sopenharmony_ci return FeedbackNexus(source.vector, source.slot, feedback_nexus_config()) 4701cb0ef41Sopenharmony_ci .IsUninitialized(); 4711cb0ef41Sopenharmony_ci} 4721cb0ef41Sopenharmony_ci 4731cb0ef41Sopenharmony_ciconst ProcessedFeedback& JSHeapBroker::NewInsufficientFeedback( 4741cb0ef41Sopenharmony_ci FeedbackSlotKind kind) const { 4751cb0ef41Sopenharmony_ci return *zone()->New<InsufficientFeedback>(kind); 4761cb0ef41Sopenharmony_ci} 4771cb0ef41Sopenharmony_ci 4781cb0ef41Sopenharmony_ciProcessedFeedback const& JSHeapBroker::ReadFeedbackForPropertyAccess( 4791cb0ef41Sopenharmony_ci FeedbackSource const& source, AccessMode mode, 4801cb0ef41Sopenharmony_ci base::Optional<NameRef> static_name) { 4811cb0ef41Sopenharmony_ci FeedbackNexus nexus(source.vector, source.slot, feedback_nexus_config()); 4821cb0ef41Sopenharmony_ci FeedbackSlotKind kind = nexus.kind(); 4831cb0ef41Sopenharmony_ci if (nexus.IsUninitialized()) return NewInsufficientFeedback(kind); 4841cb0ef41Sopenharmony_ci 4851cb0ef41Sopenharmony_ci ZoneVector<MapRef> maps(zone()); 4861cb0ef41Sopenharmony_ci { 4871cb0ef41Sopenharmony_ci std::vector<MapAndHandler> maps_and_handlers_unfiltered; 4881cb0ef41Sopenharmony_ci nexus.ExtractMapsAndFeedback(&maps_and_handlers_unfiltered); 4891cb0ef41Sopenharmony_ci 4901cb0ef41Sopenharmony_ci for (const MapAndHandler& map_and_handler : maps_and_handlers_unfiltered) { 4911cb0ef41Sopenharmony_ci MapRef map = MakeRefAssumeMemoryFence(this, *map_and_handler.first); 4921cb0ef41Sopenharmony_ci // May change concurrently at any time - must be guarded by a dependency 4931cb0ef41Sopenharmony_ci // if non-deprecation is important. 4941cb0ef41Sopenharmony_ci if (map.is_deprecated()) { 4951cb0ef41Sopenharmony_ci // TODO(ishell): support fast map updating if we enable it. 4961cb0ef41Sopenharmony_ci CHECK(!FLAG_fast_map_update); 4971cb0ef41Sopenharmony_ci base::Optional<Map> maybe_map = MapUpdater::TryUpdateNoLock( 4981cb0ef41Sopenharmony_ci isolate(), *map.object(), ConcurrencyMode::kConcurrent); 4991cb0ef41Sopenharmony_ci if (maybe_map.has_value()) { 5001cb0ef41Sopenharmony_ci map = MakeRefAssumeMemoryFence(this, maybe_map.value()); 5011cb0ef41Sopenharmony_ci } else { 5021cb0ef41Sopenharmony_ci continue; // Couldn't update the deprecated map. 5031cb0ef41Sopenharmony_ci } 5041cb0ef41Sopenharmony_ci } 5051cb0ef41Sopenharmony_ci if (map.is_abandoned_prototype_map()) continue; 5061cb0ef41Sopenharmony_ci maps.push_back(map); 5071cb0ef41Sopenharmony_ci } 5081cb0ef41Sopenharmony_ci } 5091cb0ef41Sopenharmony_ci 5101cb0ef41Sopenharmony_ci base::Optional<NameRef> name = 5111cb0ef41Sopenharmony_ci static_name.has_value() ? static_name : GetNameFeedback(nexus); 5121cb0ef41Sopenharmony_ci 5131cb0ef41Sopenharmony_ci // If no maps were found for a non-megamorphic access, then our maps died 5141cb0ef41Sopenharmony_ci // and we should soft-deopt. 5151cb0ef41Sopenharmony_ci if (maps.empty() && nexus.ic_state() != InlineCacheState::MEGAMORPHIC) { 5161cb0ef41Sopenharmony_ci return NewInsufficientFeedback(kind); 5171cb0ef41Sopenharmony_ci } 5181cb0ef41Sopenharmony_ci 5191cb0ef41Sopenharmony_ci if (name.has_value()) { 5201cb0ef41Sopenharmony_ci // We rely on this invariant in JSGenericLowering. 5211cb0ef41Sopenharmony_ci DCHECK_IMPLIES(maps.empty(), 5221cb0ef41Sopenharmony_ci nexus.ic_state() == InlineCacheState::MEGAMORPHIC); 5231cb0ef41Sopenharmony_ci return *zone()->New<NamedAccessFeedback>(*name, maps, kind); 5241cb0ef41Sopenharmony_ci } else if (nexus.GetKeyType() == IcCheckType::kElement && !maps.empty()) { 5251cb0ef41Sopenharmony_ci return ProcessFeedbackMapsForElementAccess( 5261cb0ef41Sopenharmony_ci maps, KeyedAccessMode::FromNexus(nexus), kind); 5271cb0ef41Sopenharmony_ci } else { 5281cb0ef41Sopenharmony_ci // No actionable feedback. 5291cb0ef41Sopenharmony_ci DCHECK(maps.empty()); 5301cb0ef41Sopenharmony_ci DCHECK_EQ(nexus.ic_state(), InlineCacheState::MEGAMORPHIC); 5311cb0ef41Sopenharmony_ci // TODO(neis): Using ElementAccessFeedback here is kind of an abuse. 5321cb0ef41Sopenharmony_ci return *zone()->New<ElementAccessFeedback>( 5331cb0ef41Sopenharmony_ci zone(), KeyedAccessMode::FromNexus(nexus), kind); 5341cb0ef41Sopenharmony_ci } 5351cb0ef41Sopenharmony_ci} 5361cb0ef41Sopenharmony_ci 5371cb0ef41Sopenharmony_ciProcessedFeedback const& JSHeapBroker::ReadFeedbackForGlobalAccess( 5381cb0ef41Sopenharmony_ci FeedbackSource const& source) { 5391cb0ef41Sopenharmony_ci FeedbackNexus nexus(source.vector, source.slot, feedback_nexus_config()); 5401cb0ef41Sopenharmony_ci DCHECK(nexus.kind() == FeedbackSlotKind::kLoadGlobalInsideTypeof || 5411cb0ef41Sopenharmony_ci nexus.kind() == FeedbackSlotKind::kLoadGlobalNotInsideTypeof || 5421cb0ef41Sopenharmony_ci nexus.kind() == FeedbackSlotKind::kStoreGlobalSloppy || 5431cb0ef41Sopenharmony_ci nexus.kind() == FeedbackSlotKind::kStoreGlobalStrict); 5441cb0ef41Sopenharmony_ci if (nexus.IsUninitialized()) return NewInsufficientFeedback(nexus.kind()); 5451cb0ef41Sopenharmony_ci if (nexus.ic_state() != InlineCacheState::MONOMORPHIC || 5461cb0ef41Sopenharmony_ci nexus.GetFeedback()->IsCleared()) { 5471cb0ef41Sopenharmony_ci return *zone()->New<GlobalAccessFeedback>(nexus.kind()); 5481cb0ef41Sopenharmony_ci } 5491cb0ef41Sopenharmony_ci 5501cb0ef41Sopenharmony_ci Handle<Object> feedback_value = 5511cb0ef41Sopenharmony_ci CanonicalPersistentHandle(nexus.GetFeedback()->GetHeapObjectOrSmi()); 5521cb0ef41Sopenharmony_ci 5531cb0ef41Sopenharmony_ci if (feedback_value->IsSmi()) { 5541cb0ef41Sopenharmony_ci // The wanted name belongs to a script-scope variable and the feedback 5551cb0ef41Sopenharmony_ci // tells us where to find its value. 5561cb0ef41Sopenharmony_ci int const number = feedback_value->Number(); 5571cb0ef41Sopenharmony_ci int const script_context_index = 5581cb0ef41Sopenharmony_ci FeedbackNexus::ContextIndexBits::decode(number); 5591cb0ef41Sopenharmony_ci int const context_slot_index = FeedbackNexus::SlotIndexBits::decode(number); 5601cb0ef41Sopenharmony_ci ContextRef context = MakeRefAssumeMemoryFence( 5611cb0ef41Sopenharmony_ci this, 5621cb0ef41Sopenharmony_ci target_native_context().script_context_table().object()->get_context( 5631cb0ef41Sopenharmony_ci script_context_index, kAcquireLoad)); 5641cb0ef41Sopenharmony_ci 5651cb0ef41Sopenharmony_ci base::Optional<ObjectRef> contents = context.get(context_slot_index); 5661cb0ef41Sopenharmony_ci if (contents.has_value()) CHECK(!contents->IsTheHole()); 5671cb0ef41Sopenharmony_ci 5681cb0ef41Sopenharmony_ci return *zone()->New<GlobalAccessFeedback>( 5691cb0ef41Sopenharmony_ci context, context_slot_index, 5701cb0ef41Sopenharmony_ci FeedbackNexus::ImmutabilityBit::decode(number), nexus.kind()); 5711cb0ef41Sopenharmony_ci } 5721cb0ef41Sopenharmony_ci 5731cb0ef41Sopenharmony_ci CHECK(feedback_value->IsPropertyCell()); 5741cb0ef41Sopenharmony_ci // The wanted name belongs (or did belong) to a property on the global 5751cb0ef41Sopenharmony_ci // object and the feedback is the cell holding its value. 5761cb0ef41Sopenharmony_ci return *zone()->New<GlobalAccessFeedback>( 5771cb0ef41Sopenharmony_ci MakeRefAssumeMemoryFence(this, 5781cb0ef41Sopenharmony_ci Handle<PropertyCell>::cast(feedback_value)), 5791cb0ef41Sopenharmony_ci nexus.kind()); 5801cb0ef41Sopenharmony_ci} 5811cb0ef41Sopenharmony_ci 5821cb0ef41Sopenharmony_ciProcessedFeedback const& JSHeapBroker::ReadFeedbackForBinaryOperation( 5831cb0ef41Sopenharmony_ci FeedbackSource const& source) const { 5841cb0ef41Sopenharmony_ci FeedbackNexus nexus(source.vector, source.slot, feedback_nexus_config()); 5851cb0ef41Sopenharmony_ci if (nexus.IsUninitialized()) return NewInsufficientFeedback(nexus.kind()); 5861cb0ef41Sopenharmony_ci BinaryOperationHint hint = nexus.GetBinaryOperationFeedback(); 5871cb0ef41Sopenharmony_ci DCHECK_NE(hint, BinaryOperationHint::kNone); // Not uninitialized. 5881cb0ef41Sopenharmony_ci return *zone()->New<BinaryOperationFeedback>(hint, nexus.kind()); 5891cb0ef41Sopenharmony_ci} 5901cb0ef41Sopenharmony_ci 5911cb0ef41Sopenharmony_ciProcessedFeedback const& JSHeapBroker::ReadFeedbackForCompareOperation( 5921cb0ef41Sopenharmony_ci FeedbackSource const& source) const { 5931cb0ef41Sopenharmony_ci FeedbackNexus nexus(source.vector, source.slot, feedback_nexus_config()); 5941cb0ef41Sopenharmony_ci if (nexus.IsUninitialized()) return NewInsufficientFeedback(nexus.kind()); 5951cb0ef41Sopenharmony_ci CompareOperationHint hint = nexus.GetCompareOperationFeedback(); 5961cb0ef41Sopenharmony_ci DCHECK_NE(hint, CompareOperationHint::kNone); // Not uninitialized. 5971cb0ef41Sopenharmony_ci return *zone()->New<CompareOperationFeedback>(hint, nexus.kind()); 5981cb0ef41Sopenharmony_ci} 5991cb0ef41Sopenharmony_ci 6001cb0ef41Sopenharmony_ciProcessedFeedback const& JSHeapBroker::ReadFeedbackForForIn( 6011cb0ef41Sopenharmony_ci FeedbackSource const& source) const { 6021cb0ef41Sopenharmony_ci FeedbackNexus nexus(source.vector, source.slot, feedback_nexus_config()); 6031cb0ef41Sopenharmony_ci if (nexus.IsUninitialized()) return NewInsufficientFeedback(nexus.kind()); 6041cb0ef41Sopenharmony_ci ForInHint hint = nexus.GetForInFeedback(); 6051cb0ef41Sopenharmony_ci DCHECK_NE(hint, ForInHint::kNone); // Not uninitialized. 6061cb0ef41Sopenharmony_ci return *zone()->New<ForInFeedback>(hint, nexus.kind()); 6071cb0ef41Sopenharmony_ci} 6081cb0ef41Sopenharmony_ci 6091cb0ef41Sopenharmony_ciProcessedFeedback const& JSHeapBroker::ReadFeedbackForInstanceOf( 6101cb0ef41Sopenharmony_ci FeedbackSource const& source) { 6111cb0ef41Sopenharmony_ci FeedbackNexus nexus(source.vector, source.slot, feedback_nexus_config()); 6121cb0ef41Sopenharmony_ci if (nexus.IsUninitialized()) return NewInsufficientFeedback(nexus.kind()); 6131cb0ef41Sopenharmony_ci 6141cb0ef41Sopenharmony_ci base::Optional<JSObjectRef> optional_constructor; 6151cb0ef41Sopenharmony_ci { 6161cb0ef41Sopenharmony_ci MaybeHandle<JSObject> maybe_constructor = nexus.GetConstructorFeedback(); 6171cb0ef41Sopenharmony_ci Handle<JSObject> constructor; 6181cb0ef41Sopenharmony_ci if (maybe_constructor.ToHandle(&constructor)) { 6191cb0ef41Sopenharmony_ci optional_constructor = MakeRefAssumeMemoryFence(this, *constructor); 6201cb0ef41Sopenharmony_ci } 6211cb0ef41Sopenharmony_ci } 6221cb0ef41Sopenharmony_ci return *zone()->New<InstanceOfFeedback>(optional_constructor, nexus.kind()); 6231cb0ef41Sopenharmony_ci} 6241cb0ef41Sopenharmony_ci 6251cb0ef41Sopenharmony_ciProcessedFeedback const& JSHeapBroker::ReadFeedbackForArrayOrObjectLiteral( 6261cb0ef41Sopenharmony_ci FeedbackSource const& source) { 6271cb0ef41Sopenharmony_ci FeedbackNexus nexus(source.vector, source.slot, feedback_nexus_config()); 6281cb0ef41Sopenharmony_ci if (nexus.IsUninitialized()) return NewInsufficientFeedback(nexus.kind()); 6291cb0ef41Sopenharmony_ci 6301cb0ef41Sopenharmony_ci HeapObject object; 6311cb0ef41Sopenharmony_ci if (!nexus.GetFeedback()->GetHeapObject(&object)) { 6321cb0ef41Sopenharmony_ci return NewInsufficientFeedback(nexus.kind()); 6331cb0ef41Sopenharmony_ci } 6341cb0ef41Sopenharmony_ci 6351cb0ef41Sopenharmony_ci AllocationSiteRef site = 6361cb0ef41Sopenharmony_ci MakeRefAssumeMemoryFence(this, AllocationSite::cast(object)); 6371cb0ef41Sopenharmony_ci return *zone()->New<LiteralFeedback>(site, nexus.kind()); 6381cb0ef41Sopenharmony_ci} 6391cb0ef41Sopenharmony_ci 6401cb0ef41Sopenharmony_ciProcessedFeedback const& JSHeapBroker::ReadFeedbackForRegExpLiteral( 6411cb0ef41Sopenharmony_ci FeedbackSource const& source) { 6421cb0ef41Sopenharmony_ci FeedbackNexus nexus(source.vector, source.slot, feedback_nexus_config()); 6431cb0ef41Sopenharmony_ci if (nexus.IsUninitialized()) return NewInsufficientFeedback(nexus.kind()); 6441cb0ef41Sopenharmony_ci 6451cb0ef41Sopenharmony_ci HeapObject object; 6461cb0ef41Sopenharmony_ci if (!nexus.GetFeedback()->GetHeapObject(&object)) { 6471cb0ef41Sopenharmony_ci return NewInsufficientFeedback(nexus.kind()); 6481cb0ef41Sopenharmony_ci } 6491cb0ef41Sopenharmony_ci 6501cb0ef41Sopenharmony_ci RegExpBoilerplateDescriptionRef boilerplate = MakeRefAssumeMemoryFence( 6511cb0ef41Sopenharmony_ci this, RegExpBoilerplateDescription::cast(object)); 6521cb0ef41Sopenharmony_ci return *zone()->New<RegExpLiteralFeedback>(boilerplate, nexus.kind()); 6531cb0ef41Sopenharmony_ci} 6541cb0ef41Sopenharmony_ci 6551cb0ef41Sopenharmony_ciProcessedFeedback const& JSHeapBroker::ReadFeedbackForTemplateObject( 6561cb0ef41Sopenharmony_ci FeedbackSource const& source) { 6571cb0ef41Sopenharmony_ci FeedbackNexus nexus(source.vector, source.slot, feedback_nexus_config()); 6581cb0ef41Sopenharmony_ci if (nexus.IsUninitialized()) return NewInsufficientFeedback(nexus.kind()); 6591cb0ef41Sopenharmony_ci 6601cb0ef41Sopenharmony_ci HeapObject object; 6611cb0ef41Sopenharmony_ci if (!nexus.GetFeedback()->GetHeapObject(&object)) { 6621cb0ef41Sopenharmony_ci return NewInsufficientFeedback(nexus.kind()); 6631cb0ef41Sopenharmony_ci } 6641cb0ef41Sopenharmony_ci 6651cb0ef41Sopenharmony_ci JSArrayRef array = MakeRefAssumeMemoryFence(this, JSArray::cast(object)); 6661cb0ef41Sopenharmony_ci return *zone()->New<TemplateObjectFeedback>(array, nexus.kind()); 6671cb0ef41Sopenharmony_ci} 6681cb0ef41Sopenharmony_ci 6691cb0ef41Sopenharmony_ciProcessedFeedback const& JSHeapBroker::ReadFeedbackForCall( 6701cb0ef41Sopenharmony_ci FeedbackSource const& source) { 6711cb0ef41Sopenharmony_ci FeedbackNexus nexus(source.vector, source.slot, feedback_nexus_config()); 6721cb0ef41Sopenharmony_ci if (nexus.IsUninitialized()) return NewInsufficientFeedback(nexus.kind()); 6731cb0ef41Sopenharmony_ci 6741cb0ef41Sopenharmony_ci base::Optional<HeapObjectRef> target_ref; 6751cb0ef41Sopenharmony_ci { 6761cb0ef41Sopenharmony_ci MaybeObject maybe_target = nexus.GetFeedback(); 6771cb0ef41Sopenharmony_ci HeapObject target_object; 6781cb0ef41Sopenharmony_ci if (maybe_target->GetHeapObject(&target_object)) { 6791cb0ef41Sopenharmony_ci target_ref = MakeRefAssumeMemoryFence(this, target_object); 6801cb0ef41Sopenharmony_ci } 6811cb0ef41Sopenharmony_ci } 6821cb0ef41Sopenharmony_ci 6831cb0ef41Sopenharmony_ci float frequency = nexus.ComputeCallFrequency(); 6841cb0ef41Sopenharmony_ci SpeculationMode mode = nexus.GetSpeculationMode(); 6851cb0ef41Sopenharmony_ci CallFeedbackContent content = nexus.GetCallFeedbackContent(); 6861cb0ef41Sopenharmony_ci return *zone()->New<CallFeedback>(target_ref, frequency, mode, content, 6871cb0ef41Sopenharmony_ci nexus.kind()); 6881cb0ef41Sopenharmony_ci} 6891cb0ef41Sopenharmony_ci 6901cb0ef41Sopenharmony_ciBinaryOperationHint JSHeapBroker::GetFeedbackForBinaryOperation( 6911cb0ef41Sopenharmony_ci FeedbackSource const& source) { 6921cb0ef41Sopenharmony_ci ProcessedFeedback const& feedback = ProcessFeedbackForBinaryOperation(source); 6931cb0ef41Sopenharmony_ci return feedback.IsInsufficient() ? BinaryOperationHint::kNone 6941cb0ef41Sopenharmony_ci : feedback.AsBinaryOperation().value(); 6951cb0ef41Sopenharmony_ci} 6961cb0ef41Sopenharmony_ci 6971cb0ef41Sopenharmony_ciCompareOperationHint JSHeapBroker::GetFeedbackForCompareOperation( 6981cb0ef41Sopenharmony_ci FeedbackSource const& source) { 6991cb0ef41Sopenharmony_ci ProcessedFeedback const& feedback = 7001cb0ef41Sopenharmony_ci ProcessFeedbackForCompareOperation(source); 7011cb0ef41Sopenharmony_ci return feedback.IsInsufficient() ? CompareOperationHint::kNone 7021cb0ef41Sopenharmony_ci : feedback.AsCompareOperation().value(); 7031cb0ef41Sopenharmony_ci} 7041cb0ef41Sopenharmony_ci 7051cb0ef41Sopenharmony_ciForInHint JSHeapBroker::GetFeedbackForForIn(FeedbackSource const& source) { 7061cb0ef41Sopenharmony_ci ProcessedFeedback const& feedback = ProcessFeedbackForForIn(source); 7071cb0ef41Sopenharmony_ci return feedback.IsInsufficient() ? ForInHint::kNone 7081cb0ef41Sopenharmony_ci : feedback.AsForIn().value(); 7091cb0ef41Sopenharmony_ci} 7101cb0ef41Sopenharmony_ci 7111cb0ef41Sopenharmony_ciProcessedFeedback const& JSHeapBroker::GetFeedbackForArrayOrObjectLiteral( 7121cb0ef41Sopenharmony_ci FeedbackSource const& source) { 7131cb0ef41Sopenharmony_ci if (HasFeedback(source)) return GetFeedback(source); 7141cb0ef41Sopenharmony_ci ProcessedFeedback const& feedback = 7151cb0ef41Sopenharmony_ci ReadFeedbackForArrayOrObjectLiteral(source); 7161cb0ef41Sopenharmony_ci SetFeedback(source, &feedback); 7171cb0ef41Sopenharmony_ci return feedback; 7181cb0ef41Sopenharmony_ci} 7191cb0ef41Sopenharmony_ci 7201cb0ef41Sopenharmony_ciProcessedFeedback const& JSHeapBroker::GetFeedbackForRegExpLiteral( 7211cb0ef41Sopenharmony_ci FeedbackSource const& source) { 7221cb0ef41Sopenharmony_ci if (HasFeedback(source)) return GetFeedback(source); 7231cb0ef41Sopenharmony_ci ProcessedFeedback const& feedback = ReadFeedbackForRegExpLiteral(source); 7241cb0ef41Sopenharmony_ci SetFeedback(source, &feedback); 7251cb0ef41Sopenharmony_ci return feedback; 7261cb0ef41Sopenharmony_ci} 7271cb0ef41Sopenharmony_ci 7281cb0ef41Sopenharmony_ciProcessedFeedback const& JSHeapBroker::GetFeedbackForTemplateObject( 7291cb0ef41Sopenharmony_ci FeedbackSource const& source) { 7301cb0ef41Sopenharmony_ci if (HasFeedback(source)) return GetFeedback(source); 7311cb0ef41Sopenharmony_ci ProcessedFeedback const& feedback = ReadFeedbackForTemplateObject(source); 7321cb0ef41Sopenharmony_ci SetFeedback(source, &feedback); 7331cb0ef41Sopenharmony_ci return feedback; 7341cb0ef41Sopenharmony_ci} 7351cb0ef41Sopenharmony_ci 7361cb0ef41Sopenharmony_ciProcessedFeedback const& JSHeapBroker::ProcessFeedbackForBinaryOperation( 7371cb0ef41Sopenharmony_ci FeedbackSource const& source) { 7381cb0ef41Sopenharmony_ci if (HasFeedback(source)) return GetFeedback(source); 7391cb0ef41Sopenharmony_ci ProcessedFeedback const& feedback = ReadFeedbackForBinaryOperation(source); 7401cb0ef41Sopenharmony_ci SetFeedback(source, &feedback); 7411cb0ef41Sopenharmony_ci return feedback; 7421cb0ef41Sopenharmony_ci} 7431cb0ef41Sopenharmony_ci 7441cb0ef41Sopenharmony_ciProcessedFeedback const& JSHeapBroker::ProcessFeedbackForCompareOperation( 7451cb0ef41Sopenharmony_ci FeedbackSource const& source) { 7461cb0ef41Sopenharmony_ci if (HasFeedback(source)) return GetFeedback(source); 7471cb0ef41Sopenharmony_ci ProcessedFeedback const& feedback = ReadFeedbackForCompareOperation(source); 7481cb0ef41Sopenharmony_ci SetFeedback(source, &feedback); 7491cb0ef41Sopenharmony_ci return feedback; 7501cb0ef41Sopenharmony_ci} 7511cb0ef41Sopenharmony_ci 7521cb0ef41Sopenharmony_ciProcessedFeedback const& JSHeapBroker::ProcessFeedbackForForIn( 7531cb0ef41Sopenharmony_ci FeedbackSource const& source) { 7541cb0ef41Sopenharmony_ci if (HasFeedback(source)) return GetFeedback(source); 7551cb0ef41Sopenharmony_ci ProcessedFeedback const& feedback = ReadFeedbackForForIn(source); 7561cb0ef41Sopenharmony_ci SetFeedback(source, &feedback); 7571cb0ef41Sopenharmony_ci return feedback; 7581cb0ef41Sopenharmony_ci} 7591cb0ef41Sopenharmony_ci 7601cb0ef41Sopenharmony_ciProcessedFeedback const& JSHeapBroker::GetFeedbackForPropertyAccess( 7611cb0ef41Sopenharmony_ci FeedbackSource const& source, AccessMode mode, 7621cb0ef41Sopenharmony_ci base::Optional<NameRef> static_name) { 7631cb0ef41Sopenharmony_ci if (HasFeedback(source)) return GetFeedback(source); 7641cb0ef41Sopenharmony_ci ProcessedFeedback const& feedback = 7651cb0ef41Sopenharmony_ci ReadFeedbackForPropertyAccess(source, mode, static_name); 7661cb0ef41Sopenharmony_ci SetFeedback(source, &feedback); 7671cb0ef41Sopenharmony_ci return feedback; 7681cb0ef41Sopenharmony_ci} 7691cb0ef41Sopenharmony_ci 7701cb0ef41Sopenharmony_ciProcessedFeedback const& JSHeapBroker::GetFeedbackForInstanceOf( 7711cb0ef41Sopenharmony_ci FeedbackSource const& source) { 7721cb0ef41Sopenharmony_ci if (HasFeedback(source)) return GetFeedback(source); 7731cb0ef41Sopenharmony_ci ProcessedFeedback const& feedback = ReadFeedbackForInstanceOf(source); 7741cb0ef41Sopenharmony_ci SetFeedback(source, &feedback); 7751cb0ef41Sopenharmony_ci return feedback; 7761cb0ef41Sopenharmony_ci} 7771cb0ef41Sopenharmony_ci 7781cb0ef41Sopenharmony_ciProcessedFeedback const& JSHeapBroker::GetFeedbackForCall( 7791cb0ef41Sopenharmony_ci FeedbackSource const& source) { 7801cb0ef41Sopenharmony_ci if (HasFeedback(source)) return GetFeedback(source); 7811cb0ef41Sopenharmony_ci ProcessedFeedback const& feedback = ReadFeedbackForCall(source); 7821cb0ef41Sopenharmony_ci SetFeedback(source, &feedback); 7831cb0ef41Sopenharmony_ci return feedback; 7841cb0ef41Sopenharmony_ci} 7851cb0ef41Sopenharmony_ci 7861cb0ef41Sopenharmony_ciProcessedFeedback const& JSHeapBroker::GetFeedbackForGlobalAccess( 7871cb0ef41Sopenharmony_ci FeedbackSource const& source) { 7881cb0ef41Sopenharmony_ci if (HasFeedback(source)) return GetFeedback(source); 7891cb0ef41Sopenharmony_ci ProcessedFeedback const& feedback = ReadFeedbackForGlobalAccess(source); 7901cb0ef41Sopenharmony_ci SetFeedback(source, &feedback); 7911cb0ef41Sopenharmony_ci return feedback; 7921cb0ef41Sopenharmony_ci} 7931cb0ef41Sopenharmony_ci 7941cb0ef41Sopenharmony_ciElementAccessFeedback const& JSHeapBroker::ProcessFeedbackMapsForElementAccess( 7951cb0ef41Sopenharmony_ci ZoneVector<MapRef>& maps, KeyedAccessMode const& keyed_mode, 7961cb0ef41Sopenharmony_ci FeedbackSlotKind slot_kind) { 7971cb0ef41Sopenharmony_ci DCHECK(!maps.empty()); 7981cb0ef41Sopenharmony_ci 7991cb0ef41Sopenharmony_ci // Collect possible transition targets. 8001cb0ef41Sopenharmony_ci MapHandles possible_transition_targets; 8011cb0ef41Sopenharmony_ci possible_transition_targets.reserve(maps.size()); 8021cb0ef41Sopenharmony_ci for (MapRef& map : maps) { 8031cb0ef41Sopenharmony_ci if (map.CanInlineElementAccess() && 8041cb0ef41Sopenharmony_ci IsFastElementsKind(map.elements_kind()) && 8051cb0ef41Sopenharmony_ci GetInitialFastElementsKind() != map.elements_kind()) { 8061cb0ef41Sopenharmony_ci possible_transition_targets.push_back(map.object()); 8071cb0ef41Sopenharmony_ci } 8081cb0ef41Sopenharmony_ci } 8091cb0ef41Sopenharmony_ci 8101cb0ef41Sopenharmony_ci using TransitionGroup = ElementAccessFeedback::TransitionGroup; 8111cb0ef41Sopenharmony_ci struct HandleLess { 8121cb0ef41Sopenharmony_ci bool operator()(Handle<Map> x, Handle<Map> y) const { 8131cb0ef41Sopenharmony_ci return x.address() < y.address(); 8141cb0ef41Sopenharmony_ci } 8151cb0ef41Sopenharmony_ci }; 8161cb0ef41Sopenharmony_ci ZoneMap<Handle<Map>, TransitionGroup, HandleLess> transition_groups(zone()); 8171cb0ef41Sopenharmony_ci 8181cb0ef41Sopenharmony_ci // Separate the actual receiver maps and the possible transition sources. 8191cb0ef41Sopenharmony_ci for (const MapRef& map : maps) { 8201cb0ef41Sopenharmony_ci Map transition_target; 8211cb0ef41Sopenharmony_ci 8221cb0ef41Sopenharmony_ci // Don't generate elements kind transitions from stable maps. 8231cb0ef41Sopenharmony_ci if (!map.is_stable()) { 8241cb0ef41Sopenharmony_ci // The lock is needed for UnusedPropertyFields (called deep inside 8251cb0ef41Sopenharmony_ci // FindElementsKindTransitionedMap). 8261cb0ef41Sopenharmony_ci MapUpdaterGuardIfNeeded mumd_scope(this); 8271cb0ef41Sopenharmony_ci 8281cb0ef41Sopenharmony_ci transition_target = map.object()->FindElementsKindTransitionedMap( 8291cb0ef41Sopenharmony_ci isolate(), possible_transition_targets, ConcurrencyMode::kConcurrent); 8301cb0ef41Sopenharmony_ci } 8311cb0ef41Sopenharmony_ci 8321cb0ef41Sopenharmony_ci if (transition_target.is_null()) { 8331cb0ef41Sopenharmony_ci TransitionGroup group(1, map.object(), zone()); 8341cb0ef41Sopenharmony_ci transition_groups.insert({map.object(), group}); 8351cb0ef41Sopenharmony_ci } else { 8361cb0ef41Sopenharmony_ci Handle<Map> target = CanonicalPersistentHandle(transition_target); 8371cb0ef41Sopenharmony_ci TransitionGroup new_group(1, target, zone()); 8381cb0ef41Sopenharmony_ci TransitionGroup& actual_group = 8391cb0ef41Sopenharmony_ci transition_groups.insert({target, new_group}).first->second; 8401cb0ef41Sopenharmony_ci actual_group.push_back(map.object()); 8411cb0ef41Sopenharmony_ci } 8421cb0ef41Sopenharmony_ci } 8431cb0ef41Sopenharmony_ci 8441cb0ef41Sopenharmony_ci ElementAccessFeedback* result = 8451cb0ef41Sopenharmony_ci zone()->New<ElementAccessFeedback>(zone(), keyed_mode, slot_kind); 8461cb0ef41Sopenharmony_ci for (auto entry : transition_groups) { 8471cb0ef41Sopenharmony_ci result->AddGroup(std::move(entry.second)); 8481cb0ef41Sopenharmony_ci } 8491cb0ef41Sopenharmony_ci 8501cb0ef41Sopenharmony_ci CHECK(!result->transition_groups().empty()); 8511cb0ef41Sopenharmony_ci return *result; 8521cb0ef41Sopenharmony_ci} 8531cb0ef41Sopenharmony_ci 8541cb0ef41Sopenharmony_civoid ElementAccessFeedback::AddGroup(TransitionGroup&& group) { 8551cb0ef41Sopenharmony_ci CHECK(!group.empty()); 8561cb0ef41Sopenharmony_ci transition_groups_.push_back(std::move(group)); 8571cb0ef41Sopenharmony_ci 8581cb0ef41Sopenharmony_ci#ifdef ENABLE_SLOW_DCHECKS 8591cb0ef41Sopenharmony_ci // Check that each of the group's maps occurs exactly once in the whole 8601cb0ef41Sopenharmony_ci // feedback. This implies that "a source is not a target". 8611cb0ef41Sopenharmony_ci for (Handle<Map> map : group) { 8621cb0ef41Sopenharmony_ci int count = 0; 8631cb0ef41Sopenharmony_ci for (TransitionGroup const& some_group : transition_groups()) { 8641cb0ef41Sopenharmony_ci count += std::count_if( 8651cb0ef41Sopenharmony_ci some_group.begin(), some_group.end(), 8661cb0ef41Sopenharmony_ci [&](Handle<Map> some_map) { return some_map.equals(map); }); 8671cb0ef41Sopenharmony_ci } 8681cb0ef41Sopenharmony_ci CHECK_EQ(count, 1); 8691cb0ef41Sopenharmony_ci } 8701cb0ef41Sopenharmony_ci#endif 8711cb0ef41Sopenharmony_ci} 8721cb0ef41Sopenharmony_ci 8731cb0ef41Sopenharmony_cibase::Optional<NameRef> JSHeapBroker::GetNameFeedback( 8741cb0ef41Sopenharmony_ci FeedbackNexus const& nexus) { 8751cb0ef41Sopenharmony_ci Name raw_name = nexus.GetName(); 8761cb0ef41Sopenharmony_ci if (raw_name.is_null()) return base::nullopt; 8771cb0ef41Sopenharmony_ci return MakeRefAssumeMemoryFence(this, raw_name); 8781cb0ef41Sopenharmony_ci} 8791cb0ef41Sopenharmony_ci 8801cb0ef41Sopenharmony_ciPropertyAccessInfo JSHeapBroker::GetPropertyAccessInfo( 8811cb0ef41Sopenharmony_ci MapRef map, NameRef name, AccessMode access_mode, 8821cb0ef41Sopenharmony_ci CompilationDependencies* dependencies) { 8831cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(dependencies); 8841cb0ef41Sopenharmony_ci 8851cb0ef41Sopenharmony_ci PropertyAccessTarget target({map, name, access_mode}); 8861cb0ef41Sopenharmony_ci auto it = property_access_infos_.find(target); 8871cb0ef41Sopenharmony_ci if (it != property_access_infos_.end()) return it->second; 8881cb0ef41Sopenharmony_ci 8891cb0ef41Sopenharmony_ci AccessInfoFactory factory(this, dependencies, zone()); 8901cb0ef41Sopenharmony_ci PropertyAccessInfo access_info = 8911cb0ef41Sopenharmony_ci factory.ComputePropertyAccessInfo(map, name, access_mode); 8921cb0ef41Sopenharmony_ci TRACE(this, "Storing PropertyAccessInfo for " 8931cb0ef41Sopenharmony_ci << access_mode << " of property " << name << " on map " 8941cb0ef41Sopenharmony_ci << map); 8951cb0ef41Sopenharmony_ci property_access_infos_.insert({target, access_info}); 8961cb0ef41Sopenharmony_ci return access_info; 8971cb0ef41Sopenharmony_ci} 8981cb0ef41Sopenharmony_ci 8991cb0ef41Sopenharmony_ciBinaryOperationFeedback const& ProcessedFeedback::AsBinaryOperation() const { 9001cb0ef41Sopenharmony_ci CHECK_EQ(kBinaryOperation, kind()); 9011cb0ef41Sopenharmony_ci return *static_cast<BinaryOperationFeedback const*>(this); 9021cb0ef41Sopenharmony_ci} 9031cb0ef41Sopenharmony_ci 9041cb0ef41Sopenharmony_ciCallFeedback const& ProcessedFeedback::AsCall() const { 9051cb0ef41Sopenharmony_ci CHECK_EQ(kCall, kind()); 9061cb0ef41Sopenharmony_ci return *static_cast<CallFeedback const*>(this); 9071cb0ef41Sopenharmony_ci} 9081cb0ef41Sopenharmony_ci 9091cb0ef41Sopenharmony_ciCompareOperationFeedback const& ProcessedFeedback::AsCompareOperation() const { 9101cb0ef41Sopenharmony_ci CHECK_EQ(kCompareOperation, kind()); 9111cb0ef41Sopenharmony_ci return *static_cast<CompareOperationFeedback const*>(this); 9121cb0ef41Sopenharmony_ci} 9131cb0ef41Sopenharmony_ci 9141cb0ef41Sopenharmony_ciElementAccessFeedback const& ProcessedFeedback::AsElementAccess() const { 9151cb0ef41Sopenharmony_ci CHECK_EQ(kElementAccess, kind()); 9161cb0ef41Sopenharmony_ci return *static_cast<ElementAccessFeedback const*>(this); 9171cb0ef41Sopenharmony_ci} 9181cb0ef41Sopenharmony_ci 9191cb0ef41Sopenharmony_ciForInFeedback const& ProcessedFeedback::AsForIn() const { 9201cb0ef41Sopenharmony_ci CHECK_EQ(kForIn, kind()); 9211cb0ef41Sopenharmony_ci return *static_cast<ForInFeedback const*>(this); 9221cb0ef41Sopenharmony_ci} 9231cb0ef41Sopenharmony_ci 9241cb0ef41Sopenharmony_ciGlobalAccessFeedback const& ProcessedFeedback::AsGlobalAccess() const { 9251cb0ef41Sopenharmony_ci CHECK_EQ(kGlobalAccess, kind()); 9261cb0ef41Sopenharmony_ci return *static_cast<GlobalAccessFeedback const*>(this); 9271cb0ef41Sopenharmony_ci} 9281cb0ef41Sopenharmony_ci 9291cb0ef41Sopenharmony_ciInstanceOfFeedback const& ProcessedFeedback::AsInstanceOf() const { 9301cb0ef41Sopenharmony_ci CHECK_EQ(kInstanceOf, kind()); 9311cb0ef41Sopenharmony_ci return *static_cast<InstanceOfFeedback const*>(this); 9321cb0ef41Sopenharmony_ci} 9331cb0ef41Sopenharmony_ci 9341cb0ef41Sopenharmony_ciNamedAccessFeedback const& ProcessedFeedback::AsNamedAccess() const { 9351cb0ef41Sopenharmony_ci CHECK_EQ(kNamedAccess, kind()); 9361cb0ef41Sopenharmony_ci return *static_cast<NamedAccessFeedback const*>(this); 9371cb0ef41Sopenharmony_ci} 9381cb0ef41Sopenharmony_ci 9391cb0ef41Sopenharmony_ciLiteralFeedback const& ProcessedFeedback::AsLiteral() const { 9401cb0ef41Sopenharmony_ci CHECK_EQ(kLiteral, kind()); 9411cb0ef41Sopenharmony_ci return *static_cast<LiteralFeedback const*>(this); 9421cb0ef41Sopenharmony_ci} 9431cb0ef41Sopenharmony_ci 9441cb0ef41Sopenharmony_ciRegExpLiteralFeedback const& ProcessedFeedback::AsRegExpLiteral() const { 9451cb0ef41Sopenharmony_ci CHECK_EQ(kRegExpLiteral, kind()); 9461cb0ef41Sopenharmony_ci return *static_cast<RegExpLiteralFeedback const*>(this); 9471cb0ef41Sopenharmony_ci} 9481cb0ef41Sopenharmony_ci 9491cb0ef41Sopenharmony_ciTemplateObjectFeedback const& ProcessedFeedback::AsTemplateObject() const { 9501cb0ef41Sopenharmony_ci CHECK_EQ(kTemplateObject, kind()); 9511cb0ef41Sopenharmony_ci return *static_cast<TemplateObjectFeedback const*>(this); 9521cb0ef41Sopenharmony_ci} 9531cb0ef41Sopenharmony_ci 9541cb0ef41Sopenharmony_ci#undef TRACE 9551cb0ef41Sopenharmony_ci 9561cb0ef41Sopenharmony_ci} // namespace compiler 9571cb0ef41Sopenharmony_ci} // namespace internal 9581cb0ef41Sopenharmony_ci} // namespace v8 959