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#ifndef V8_COMPILER_JS_HEAP_BROKER_H_
61cb0ef41Sopenharmony_ci#define V8_COMPILER_JS_HEAP_BROKER_H_
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_ci#include "src/base/compiler-specific.h"
91cb0ef41Sopenharmony_ci#include "src/base/optional.h"
101cb0ef41Sopenharmony_ci#include "src/base/platform/mutex.h"
111cb0ef41Sopenharmony_ci#include "src/common/globals.h"
121cb0ef41Sopenharmony_ci#include "src/compiler/access-info.h"
131cb0ef41Sopenharmony_ci#include "src/compiler/feedback-source.h"
141cb0ef41Sopenharmony_ci#include "src/compiler/globals.h"
151cb0ef41Sopenharmony_ci#include "src/compiler/heap-refs.h"
161cb0ef41Sopenharmony_ci#include "src/compiler/processed-feedback.h"
171cb0ef41Sopenharmony_ci#include "src/compiler/refs-map.h"
181cb0ef41Sopenharmony_ci#include "src/execution/local-isolate.h"
191cb0ef41Sopenharmony_ci#include "src/handles/handles.h"
201cb0ef41Sopenharmony_ci#include "src/handles/persistent-handles.h"
211cb0ef41Sopenharmony_ci#include "src/heap/local-heap.h"
221cb0ef41Sopenharmony_ci#include "src/heap/parked-scope.h"
231cb0ef41Sopenharmony_ci#include "src/interpreter/bytecode-array-iterator.h"
241cb0ef41Sopenharmony_ci#include "src/objects/code-kind.h"
251cb0ef41Sopenharmony_ci#include "src/objects/feedback-vector.h"
261cb0ef41Sopenharmony_ci#include "src/objects/function-kind.h"
271cb0ef41Sopenharmony_ci#include "src/objects/objects.h"
281cb0ef41Sopenharmony_ci#include "src/utils/address-map.h"
291cb0ef41Sopenharmony_ci#include "src/utils/identity-map.h"
301cb0ef41Sopenharmony_ci#include "src/utils/ostreams.h"
311cb0ef41Sopenharmony_ci#include "src/zone/zone-containers.h"
321cb0ef41Sopenharmony_ci
331cb0ef41Sopenharmony_cinamespace v8 {
341cb0ef41Sopenharmony_cinamespace internal {
351cb0ef41Sopenharmony_ci
361cb0ef41Sopenharmony_cinamespace maglev {
371cb0ef41Sopenharmony_ciclass MaglevCompilationInfo;
381cb0ef41Sopenharmony_ci}
391cb0ef41Sopenharmony_ci
401cb0ef41Sopenharmony_cinamespace compiler {
411cb0ef41Sopenharmony_ci
421cb0ef41Sopenharmony_ciclass ObjectRef;
431cb0ef41Sopenharmony_ci
441cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream& os, const ObjectRef& ref);
451cb0ef41Sopenharmony_ci
461cb0ef41Sopenharmony_ci#define TRACE_BROKER(broker, x)                                      \
471cb0ef41Sopenharmony_ci  do {                                                               \
481cb0ef41Sopenharmony_ci    if (broker->tracing_enabled() && FLAG_trace_heap_broker_verbose) \
491cb0ef41Sopenharmony_ci      StdoutStream{} << broker->Trace() << x << '\n';                \
501cb0ef41Sopenharmony_ci  } while (false)
511cb0ef41Sopenharmony_ci
521cb0ef41Sopenharmony_ci#define TRACE_BROKER_MEMORY(broker, x)                              \
531cb0ef41Sopenharmony_ci  do {                                                              \
541cb0ef41Sopenharmony_ci    if (broker->tracing_enabled() && FLAG_trace_heap_broker_memory) \
551cb0ef41Sopenharmony_ci      StdoutStream{} << broker->Trace() << x << std::endl;          \
561cb0ef41Sopenharmony_ci  } while (false)
571cb0ef41Sopenharmony_ci
581cb0ef41Sopenharmony_ci#define TRACE_BROKER_MISSING(broker, x)                                        \
591cb0ef41Sopenharmony_ci  do {                                                                         \
601cb0ef41Sopenharmony_ci    if (broker->tracing_enabled())                                             \
611cb0ef41Sopenharmony_ci      StdoutStream{} << broker->Trace() << "Missing " << x << " (" << __FILE__ \
621cb0ef41Sopenharmony_ci                     << ":" << __LINE__ << ")" << std::endl;                   \
631cb0ef41Sopenharmony_ci  } while (false)
641cb0ef41Sopenharmony_ci
651cb0ef41Sopenharmony_cistruct PropertyAccessTarget {
661cb0ef41Sopenharmony_ci  MapRef map;
671cb0ef41Sopenharmony_ci  NameRef name;
681cb0ef41Sopenharmony_ci  AccessMode mode;
691cb0ef41Sopenharmony_ci
701cb0ef41Sopenharmony_ci  struct Hash {
711cb0ef41Sopenharmony_ci    size_t operator()(const PropertyAccessTarget& pair) const {
721cb0ef41Sopenharmony_ci      return base::hash_combine(
731cb0ef41Sopenharmony_ci          base::hash_combine(pair.map.object().address(),
741cb0ef41Sopenharmony_ci                             pair.name.object().address()),
751cb0ef41Sopenharmony_ci          static_cast<int>(pair.mode));
761cb0ef41Sopenharmony_ci    }
771cb0ef41Sopenharmony_ci  };
781cb0ef41Sopenharmony_ci  struct Equal {
791cb0ef41Sopenharmony_ci    bool operator()(const PropertyAccessTarget& lhs,
801cb0ef41Sopenharmony_ci                    const PropertyAccessTarget& rhs) const {
811cb0ef41Sopenharmony_ci      return lhs.map.equals(rhs.map) && lhs.name.equals(rhs.name) &&
821cb0ef41Sopenharmony_ci             lhs.mode == rhs.mode;
831cb0ef41Sopenharmony_ci    }
841cb0ef41Sopenharmony_ci  };
851cb0ef41Sopenharmony_ci};
861cb0ef41Sopenharmony_ci
871cb0ef41Sopenharmony_cienum GetOrCreateDataFlag {
881cb0ef41Sopenharmony_ci  // If set, a failure to create the data object results in a crash.
891cb0ef41Sopenharmony_ci  kCrashOnError = 1 << 0,
901cb0ef41Sopenharmony_ci  // If set, data construction assumes that the given object is protected by
911cb0ef41Sopenharmony_ci  // a memory fence (e.g. acquire-release) and thus fields required for
921cb0ef41Sopenharmony_ci  // construction (like Object::map) are safe to read. The protection can
931cb0ef41Sopenharmony_ci  // extend to some other situations as well.
941cb0ef41Sopenharmony_ci  kAssumeMemoryFence = 1 << 1,
951cb0ef41Sopenharmony_ci};
961cb0ef41Sopenharmony_ciusing GetOrCreateDataFlags = base::Flags<GetOrCreateDataFlag>;
971cb0ef41Sopenharmony_ciDEFINE_OPERATORS_FOR_FLAGS(GetOrCreateDataFlags)
981cb0ef41Sopenharmony_ci
991cb0ef41Sopenharmony_ciclass V8_EXPORT_PRIVATE JSHeapBroker {
1001cb0ef41Sopenharmony_ci public:
1011cb0ef41Sopenharmony_ci  JSHeapBroker(Isolate* isolate, Zone* broker_zone, bool tracing_enabled,
1021cb0ef41Sopenharmony_ci               CodeKind code_kind);
1031cb0ef41Sopenharmony_ci
1041cb0ef41Sopenharmony_ci  // For use only in tests, sets default values for some arguments. Avoids
1051cb0ef41Sopenharmony_ci  // churn when new flags are added.
1061cb0ef41Sopenharmony_ci  JSHeapBroker(Isolate* isolate, Zone* broker_zone)
1071cb0ef41Sopenharmony_ci      : JSHeapBroker(isolate, broker_zone, FLAG_trace_heap_broker,
1081cb0ef41Sopenharmony_ci                     CodeKind::TURBOFAN) {}
1091cb0ef41Sopenharmony_ci
1101cb0ef41Sopenharmony_ci  ~JSHeapBroker();
1111cb0ef41Sopenharmony_ci
1121cb0ef41Sopenharmony_ci  // The compilation target's native context. We need the setter because at
1131cb0ef41Sopenharmony_ci  // broker construction time we don't yet have the canonical handle.
1141cb0ef41Sopenharmony_ci  NativeContextRef target_native_context() const {
1151cb0ef41Sopenharmony_ci    return target_native_context_.value();
1161cb0ef41Sopenharmony_ci  }
1171cb0ef41Sopenharmony_ci  void SetTargetNativeContextRef(Handle<NativeContext> native_context);
1181cb0ef41Sopenharmony_ci
1191cb0ef41Sopenharmony_ci  void InitializeAndStartSerializing();
1201cb0ef41Sopenharmony_ci
1211cb0ef41Sopenharmony_ci  Isolate* isolate() const { return isolate_; }
1221cb0ef41Sopenharmony_ci
1231cb0ef41Sopenharmony_ci  // The pointer compression cage base value used for decompression of all
1241cb0ef41Sopenharmony_ci  // tagged values except references to Code objects.
1251cb0ef41Sopenharmony_ci  PtrComprCageBase cage_base() const {
1261cb0ef41Sopenharmony_ci#if V8_COMPRESS_POINTERS
1271cb0ef41Sopenharmony_ci    return cage_base_;
1281cb0ef41Sopenharmony_ci#else
1291cb0ef41Sopenharmony_ci    return PtrComprCageBase{};
1301cb0ef41Sopenharmony_ci#endif  // V8_COMPRESS_POINTERS
1311cb0ef41Sopenharmony_ci  }
1321cb0ef41Sopenharmony_ci
1331cb0ef41Sopenharmony_ci  Zone* zone() const { return zone_; }
1341cb0ef41Sopenharmony_ci  bool tracing_enabled() const { return tracing_enabled_; }
1351cb0ef41Sopenharmony_ci
1361cb0ef41Sopenharmony_ci  NexusConfig feedback_nexus_config() const {
1371cb0ef41Sopenharmony_ci    return IsMainThread() ? NexusConfig::FromMainThread(isolate())
1381cb0ef41Sopenharmony_ci                          : NexusConfig::FromBackgroundThread(
1391cb0ef41Sopenharmony_ci                                isolate(), local_isolate()->heap());
1401cb0ef41Sopenharmony_ci  }
1411cb0ef41Sopenharmony_ci
1421cb0ef41Sopenharmony_ci  enum BrokerMode { kDisabled, kSerializing, kSerialized, kRetired };
1431cb0ef41Sopenharmony_ci  BrokerMode mode() const { return mode_; }
1441cb0ef41Sopenharmony_ci
1451cb0ef41Sopenharmony_ci  void StopSerializing();
1461cb0ef41Sopenharmony_ci  void Retire();
1471cb0ef41Sopenharmony_ci  bool SerializingAllowed() const;
1481cb0ef41Sopenharmony_ci
1491cb0ef41Sopenharmony_ci  // Remember the local isolate and initialize its local heap with the
1501cb0ef41Sopenharmony_ci  // persistent and canonical handles provided by {info}.
1511cb0ef41Sopenharmony_ci  void AttachLocalIsolate(OptimizedCompilationInfo* info,
1521cb0ef41Sopenharmony_ci                          LocalIsolate* local_isolate);
1531cb0ef41Sopenharmony_ci  // Forget about the local isolate and pass the persistent and canonical
1541cb0ef41Sopenharmony_ci  // handles provided back to {info}. {info} is responsible for disposing of
1551cb0ef41Sopenharmony_ci  // them.
1561cb0ef41Sopenharmony_ci  void DetachLocalIsolate(OptimizedCompilationInfo* info);
1571cb0ef41Sopenharmony_ci
1581cb0ef41Sopenharmony_ci  // TODO(v8:7700): Refactor this once the broker is no longer
1591cb0ef41Sopenharmony_ci  // Turbofan-specific.
1601cb0ef41Sopenharmony_ci  void AttachLocalIsolateForMaglev(maglev::MaglevCompilationInfo* info,
1611cb0ef41Sopenharmony_ci                                   LocalIsolate* local_isolate);
1621cb0ef41Sopenharmony_ci  void DetachLocalIsolateForMaglev(maglev::MaglevCompilationInfo* info);
1631cb0ef41Sopenharmony_ci
1641cb0ef41Sopenharmony_ci  bool StackHasOverflowed() const;
1651cb0ef41Sopenharmony_ci
1661cb0ef41Sopenharmony_ci#ifdef DEBUG
1671cb0ef41Sopenharmony_ci  void PrintRefsAnalysis() const;
1681cb0ef41Sopenharmony_ci#endif  // DEBUG
1691cb0ef41Sopenharmony_ci
1701cb0ef41Sopenharmony_ci  // Returns the handle from root index table for read only heap objects.
1711cb0ef41Sopenharmony_ci  Handle<Object> GetRootHandle(Object object);
1721cb0ef41Sopenharmony_ci
1731cb0ef41Sopenharmony_ci  // Never returns nullptr.
1741cb0ef41Sopenharmony_ci  ObjectData* GetOrCreateData(Handle<Object> object,
1751cb0ef41Sopenharmony_ci                              GetOrCreateDataFlags flags = {});
1761cb0ef41Sopenharmony_ci  ObjectData* GetOrCreateData(Object object, GetOrCreateDataFlags flags = {});
1771cb0ef41Sopenharmony_ci
1781cb0ef41Sopenharmony_ci  // Gets data only if we have it. However, thin wrappers will be created for
1791cb0ef41Sopenharmony_ci  // smis, read-only objects and never-serialized objects.
1801cb0ef41Sopenharmony_ci  ObjectData* TryGetOrCreateData(Handle<Object> object,
1811cb0ef41Sopenharmony_ci                                 GetOrCreateDataFlags flags = {});
1821cb0ef41Sopenharmony_ci  ObjectData* TryGetOrCreateData(Object object,
1831cb0ef41Sopenharmony_ci                                 GetOrCreateDataFlags flags = {});
1841cb0ef41Sopenharmony_ci
1851cb0ef41Sopenharmony_ci  // Check if {object} is any native context's %ArrayPrototype% or
1861cb0ef41Sopenharmony_ci  // %ObjectPrototype%.
1871cb0ef41Sopenharmony_ci  bool IsArrayOrObjectPrototype(const JSObjectRef& object) const;
1881cb0ef41Sopenharmony_ci  bool IsArrayOrObjectPrototype(Handle<JSObject> object) const;
1891cb0ef41Sopenharmony_ci
1901cb0ef41Sopenharmony_ci  bool HasFeedback(FeedbackSource const& source) const;
1911cb0ef41Sopenharmony_ci  void SetFeedback(FeedbackSource const& source,
1921cb0ef41Sopenharmony_ci                   ProcessedFeedback const* feedback);
1931cb0ef41Sopenharmony_ci  FeedbackSlotKind GetFeedbackSlotKind(FeedbackSource const& source) const;
1941cb0ef41Sopenharmony_ci
1951cb0ef41Sopenharmony_ci  ElementAccessFeedback const& ProcessFeedbackMapsForElementAccess(
1961cb0ef41Sopenharmony_ci      ZoneVector<MapRef>& maps, KeyedAccessMode const& keyed_mode,
1971cb0ef41Sopenharmony_ci      FeedbackSlotKind slot_kind);
1981cb0ef41Sopenharmony_ci
1991cb0ef41Sopenharmony_ci  // Binary, comparison and for-in hints can be fully expressed via
2001cb0ef41Sopenharmony_ci  // an enum. Insufficient feedback is signaled by <Hint enum>::kNone.
2011cb0ef41Sopenharmony_ci  BinaryOperationHint GetFeedbackForBinaryOperation(
2021cb0ef41Sopenharmony_ci      FeedbackSource const& source);
2031cb0ef41Sopenharmony_ci  CompareOperationHint GetFeedbackForCompareOperation(
2041cb0ef41Sopenharmony_ci      FeedbackSource const& source);
2051cb0ef41Sopenharmony_ci  ForInHint GetFeedbackForForIn(FeedbackSource const& source);
2061cb0ef41Sopenharmony_ci
2071cb0ef41Sopenharmony_ci  ProcessedFeedback const& GetFeedbackForCall(FeedbackSource const& source);
2081cb0ef41Sopenharmony_ci  ProcessedFeedback const& GetFeedbackForGlobalAccess(
2091cb0ef41Sopenharmony_ci      FeedbackSource const& source);
2101cb0ef41Sopenharmony_ci  ProcessedFeedback const& GetFeedbackForInstanceOf(
2111cb0ef41Sopenharmony_ci      FeedbackSource const& source);
2121cb0ef41Sopenharmony_ci  ProcessedFeedback const& GetFeedbackForArrayOrObjectLiteral(
2131cb0ef41Sopenharmony_ci      FeedbackSource const& source);
2141cb0ef41Sopenharmony_ci  ProcessedFeedback const& GetFeedbackForRegExpLiteral(
2151cb0ef41Sopenharmony_ci      FeedbackSource const& source);
2161cb0ef41Sopenharmony_ci  ProcessedFeedback const& GetFeedbackForTemplateObject(
2171cb0ef41Sopenharmony_ci      FeedbackSource const& source);
2181cb0ef41Sopenharmony_ci  ProcessedFeedback const& GetFeedbackForPropertyAccess(
2191cb0ef41Sopenharmony_ci      FeedbackSource const& source, AccessMode mode,
2201cb0ef41Sopenharmony_ci      base::Optional<NameRef> static_name);
2211cb0ef41Sopenharmony_ci
2221cb0ef41Sopenharmony_ci  ProcessedFeedback const& ProcessFeedbackForBinaryOperation(
2231cb0ef41Sopenharmony_ci      FeedbackSource const& source);
2241cb0ef41Sopenharmony_ci  ProcessedFeedback const& ProcessFeedbackForCompareOperation(
2251cb0ef41Sopenharmony_ci      FeedbackSource const& source);
2261cb0ef41Sopenharmony_ci  ProcessedFeedback const& ProcessFeedbackForForIn(
2271cb0ef41Sopenharmony_ci      FeedbackSource const& source);
2281cb0ef41Sopenharmony_ci
2291cb0ef41Sopenharmony_ci  bool FeedbackIsInsufficient(FeedbackSource const& source) const;
2301cb0ef41Sopenharmony_ci
2311cb0ef41Sopenharmony_ci  base::Optional<NameRef> GetNameFeedback(FeedbackNexus const& nexus);
2321cb0ef41Sopenharmony_ci
2331cb0ef41Sopenharmony_ci  PropertyAccessInfo GetPropertyAccessInfo(
2341cb0ef41Sopenharmony_ci      MapRef map, NameRef name, AccessMode access_mode,
2351cb0ef41Sopenharmony_ci      CompilationDependencies* dependencies);
2361cb0ef41Sopenharmony_ci
2371cb0ef41Sopenharmony_ci  StringRef GetTypedArrayStringTag(ElementsKind kind);
2381cb0ef41Sopenharmony_ci
2391cb0ef41Sopenharmony_ci  bool IsMainThread() const {
2401cb0ef41Sopenharmony_ci    return local_isolate() == nullptr || local_isolate()->is_main_thread();
2411cb0ef41Sopenharmony_ci  }
2421cb0ef41Sopenharmony_ci
2431cb0ef41Sopenharmony_ci  LocalIsolate* local_isolate() const { return local_isolate_; }
2441cb0ef41Sopenharmony_ci
2451cb0ef41Sopenharmony_ci  // TODO(jgruber): Consider always having local_isolate_ set to a real value.
2461cb0ef41Sopenharmony_ci  // This seems not entirely trivial since we currently reset local_isolate_ to
2471cb0ef41Sopenharmony_ci  // nullptr at some point in the JSHeapBroker lifecycle.
2481cb0ef41Sopenharmony_ci  LocalIsolate* local_isolate_or_isolate() const {
2491cb0ef41Sopenharmony_ci    return local_isolate() != nullptr ? local_isolate()
2501cb0ef41Sopenharmony_ci                                      : isolate()->AsLocalIsolate();
2511cb0ef41Sopenharmony_ci  }
2521cb0ef41Sopenharmony_ci
2531cb0ef41Sopenharmony_ci  // Return the corresponding canonical persistent handle for {object}. Create
2541cb0ef41Sopenharmony_ci  // one if it does not exist.
2551cb0ef41Sopenharmony_ci  // If we have the canonical map, we can create the canonical & persistent
2561cb0ef41Sopenharmony_ci  // handle through it. This commonly happens during the Execute phase.
2571cb0ef41Sopenharmony_ci  // If we don't, that means we are calling this method from serialization. If
2581cb0ef41Sopenharmony_ci  // that happens, we should be inside a canonical and a persistent handle
2591cb0ef41Sopenharmony_ci  // scope. Then, we would just use the regular handle creation.
2601cb0ef41Sopenharmony_ci  template <typename T>
2611cb0ef41Sopenharmony_ci  Handle<T> CanonicalPersistentHandle(T object) {
2621cb0ef41Sopenharmony_ci    if (canonical_handles_) {
2631cb0ef41Sopenharmony_ci      Address address = object.ptr();
2641cb0ef41Sopenharmony_ci      if (Internals::HasHeapObjectTag(address)) {
2651cb0ef41Sopenharmony_ci        RootIndex root_index;
2661cb0ef41Sopenharmony_ci        if (root_index_map_.Lookup(address, &root_index)) {
2671cb0ef41Sopenharmony_ci          return Handle<T>(isolate_->root_handle(root_index).location());
2681cb0ef41Sopenharmony_ci        }
2691cb0ef41Sopenharmony_ci      }
2701cb0ef41Sopenharmony_ci
2711cb0ef41Sopenharmony_ci      Object obj(address);
2721cb0ef41Sopenharmony_ci      auto find_result = canonical_handles_->FindOrInsert(obj);
2731cb0ef41Sopenharmony_ci      if (!find_result.already_exists) {
2741cb0ef41Sopenharmony_ci        // Allocate new PersistentHandle if one wasn't created before.
2751cb0ef41Sopenharmony_ci        DCHECK_NOT_NULL(local_isolate());
2761cb0ef41Sopenharmony_ci        *find_result.entry =
2771cb0ef41Sopenharmony_ci            local_isolate()->heap()->NewPersistentHandle(obj).location();
2781cb0ef41Sopenharmony_ci      }
2791cb0ef41Sopenharmony_ci      return Handle<T>(*find_result.entry);
2801cb0ef41Sopenharmony_ci    } else {
2811cb0ef41Sopenharmony_ci      return Handle<T>(object, isolate());
2821cb0ef41Sopenharmony_ci    }
2831cb0ef41Sopenharmony_ci  }
2841cb0ef41Sopenharmony_ci
2851cb0ef41Sopenharmony_ci  template <typename T>
2861cb0ef41Sopenharmony_ci  Handle<T> CanonicalPersistentHandle(Handle<T> object) {
2871cb0ef41Sopenharmony_ci    if (object.is_null()) return object;  // Can't deref a null handle.
2881cb0ef41Sopenharmony_ci    return CanonicalPersistentHandle<T>(*object);
2891cb0ef41Sopenharmony_ci  }
2901cb0ef41Sopenharmony_ci
2911cb0ef41Sopenharmony_ci  // Find the corresponding handle in the CanonicalHandlesMap. The entry must be
2921cb0ef41Sopenharmony_ci  // found.
2931cb0ef41Sopenharmony_ci  template <typename T>
2941cb0ef41Sopenharmony_ci  Handle<T> FindCanonicalPersistentHandleForTesting(Object object) {
2951cb0ef41Sopenharmony_ci    Address** entry = canonical_handles_->Find(object);
2961cb0ef41Sopenharmony_ci    return Handle<T>(*entry);
2971cb0ef41Sopenharmony_ci  }
2981cb0ef41Sopenharmony_ci
2991cb0ef41Sopenharmony_ci  // Set the persistent handles and copy the canonical handles over to the
3001cb0ef41Sopenharmony_ci  // JSHeapBroker.
3011cb0ef41Sopenharmony_ci  void SetPersistentAndCopyCanonicalHandlesForTesting(
3021cb0ef41Sopenharmony_ci      std::unique_ptr<PersistentHandles> persistent_handles,
3031cb0ef41Sopenharmony_ci      std::unique_ptr<CanonicalHandlesMap> canonical_handles);
3041cb0ef41Sopenharmony_ci  std::string Trace() const;
3051cb0ef41Sopenharmony_ci  void IncrementTracingIndentation();
3061cb0ef41Sopenharmony_ci  void DecrementTracingIndentation();
3071cb0ef41Sopenharmony_ci
3081cb0ef41Sopenharmony_ci  // Locks {mutex} through the duration of this scope iff it is the first
3091cb0ef41Sopenharmony_ci  // occurrence. This is done to have a recursive shared lock on {mutex}.
3101cb0ef41Sopenharmony_ci  class V8_NODISCARD RecursiveSharedMutexGuardIfNeeded {
3111cb0ef41Sopenharmony_ci   protected:
3121cb0ef41Sopenharmony_ci    RecursiveSharedMutexGuardIfNeeded(LocalIsolate* local_isolate,
3131cb0ef41Sopenharmony_ci                                      base::SharedMutex* mutex,
3141cb0ef41Sopenharmony_ci                                      int* mutex_depth_address)
3151cb0ef41Sopenharmony_ci        : mutex_depth_address_(mutex_depth_address),
3161cb0ef41Sopenharmony_ci          initial_mutex_depth_(*mutex_depth_address_),
3171cb0ef41Sopenharmony_ci          shared_mutex_guard_(local_isolate, mutex, initial_mutex_depth_ == 0) {
3181cb0ef41Sopenharmony_ci      (*mutex_depth_address_)++;
3191cb0ef41Sopenharmony_ci    }
3201cb0ef41Sopenharmony_ci
3211cb0ef41Sopenharmony_ci    ~RecursiveSharedMutexGuardIfNeeded() {
3221cb0ef41Sopenharmony_ci      DCHECK_GE((*mutex_depth_address_), 1);
3231cb0ef41Sopenharmony_ci      (*mutex_depth_address_)--;
3241cb0ef41Sopenharmony_ci      DCHECK_EQ(initial_mutex_depth_, (*mutex_depth_address_));
3251cb0ef41Sopenharmony_ci    }
3261cb0ef41Sopenharmony_ci
3271cb0ef41Sopenharmony_ci   private:
3281cb0ef41Sopenharmony_ci    int* const mutex_depth_address_;
3291cb0ef41Sopenharmony_ci    const int initial_mutex_depth_;
3301cb0ef41Sopenharmony_ci    ParkedSharedMutexGuardIf<base::kShared> shared_mutex_guard_;
3311cb0ef41Sopenharmony_ci  };
3321cb0ef41Sopenharmony_ci
3331cb0ef41Sopenharmony_ci  class MapUpdaterGuardIfNeeded final
3341cb0ef41Sopenharmony_ci      : public RecursiveSharedMutexGuardIfNeeded {
3351cb0ef41Sopenharmony_ci   public:
3361cb0ef41Sopenharmony_ci    explicit MapUpdaterGuardIfNeeded(JSHeapBroker* broker)
3371cb0ef41Sopenharmony_ci        : RecursiveSharedMutexGuardIfNeeded(
3381cb0ef41Sopenharmony_ci              broker->local_isolate_or_isolate(),
3391cb0ef41Sopenharmony_ci              broker->isolate()->map_updater_access(),
3401cb0ef41Sopenharmony_ci              &broker->map_updater_mutex_depth_) {}
3411cb0ef41Sopenharmony_ci  };
3421cb0ef41Sopenharmony_ci
3431cb0ef41Sopenharmony_ci  class BoilerplateMigrationGuardIfNeeded final
3441cb0ef41Sopenharmony_ci      : public RecursiveSharedMutexGuardIfNeeded {
3451cb0ef41Sopenharmony_ci   public:
3461cb0ef41Sopenharmony_ci    explicit BoilerplateMigrationGuardIfNeeded(JSHeapBroker* broker)
3471cb0ef41Sopenharmony_ci        : RecursiveSharedMutexGuardIfNeeded(
3481cb0ef41Sopenharmony_ci              broker->local_isolate_or_isolate(),
3491cb0ef41Sopenharmony_ci              broker->isolate()->boilerplate_migration_access(),
3501cb0ef41Sopenharmony_ci              &broker->boilerplate_migration_mutex_depth_) {}
3511cb0ef41Sopenharmony_ci  };
3521cb0ef41Sopenharmony_ci
3531cb0ef41Sopenharmony_ci  // If this returns false, the object is guaranteed to be fully initialized and
3541cb0ef41Sopenharmony_ci  // thus safe to read from a memory safety perspective. The converse does not
3551cb0ef41Sopenharmony_ci  // necessarily hold.
3561cb0ef41Sopenharmony_ci  bool ObjectMayBeUninitialized(Handle<Object> object) const;
3571cb0ef41Sopenharmony_ci  bool ObjectMayBeUninitialized(Object object) const;
3581cb0ef41Sopenharmony_ci  bool ObjectMayBeUninitialized(HeapObject object) const;
3591cb0ef41Sopenharmony_ci
3601cb0ef41Sopenharmony_ci  void set_dependencies(CompilationDependencies* dependencies) {
3611cb0ef41Sopenharmony_ci    DCHECK_NOT_NULL(dependencies);
3621cb0ef41Sopenharmony_ci    DCHECK_NULL(dependencies_);
3631cb0ef41Sopenharmony_ci    dependencies_ = dependencies;
3641cb0ef41Sopenharmony_ci  }
3651cb0ef41Sopenharmony_ci  CompilationDependencies* dependencies() const {
3661cb0ef41Sopenharmony_ci    DCHECK_NOT_NULL(dependencies_);
3671cb0ef41Sopenharmony_ci    return dependencies_;
3681cb0ef41Sopenharmony_ci  }
3691cb0ef41Sopenharmony_ci
3701cb0ef41Sopenharmony_ci private:
3711cb0ef41Sopenharmony_ci  friend class HeapObjectRef;
3721cb0ef41Sopenharmony_ci  friend class ObjectRef;
3731cb0ef41Sopenharmony_ci  friend class ObjectData;
3741cb0ef41Sopenharmony_ci  friend class PropertyCellData;
3751cb0ef41Sopenharmony_ci
3761cb0ef41Sopenharmony_ci  ProcessedFeedback const& GetFeedback(FeedbackSource const& source) const;
3771cb0ef41Sopenharmony_ci  const ProcessedFeedback& NewInsufficientFeedback(FeedbackSlotKind kind) const;
3781cb0ef41Sopenharmony_ci
3791cb0ef41Sopenharmony_ci  // Bottleneck FeedbackNexus access here, for storage in the broker
3801cb0ef41Sopenharmony_ci  // or on-the-fly usage elsewhere in the compiler.
3811cb0ef41Sopenharmony_ci  ProcessedFeedback const& ReadFeedbackForArrayOrObjectLiteral(
3821cb0ef41Sopenharmony_ci      FeedbackSource const& source);
3831cb0ef41Sopenharmony_ci  ProcessedFeedback const& ReadFeedbackForBinaryOperation(
3841cb0ef41Sopenharmony_ci      FeedbackSource const& source) const;
3851cb0ef41Sopenharmony_ci  ProcessedFeedback const& ReadFeedbackForCall(FeedbackSource const& source);
3861cb0ef41Sopenharmony_ci  ProcessedFeedback const& ReadFeedbackForCompareOperation(
3871cb0ef41Sopenharmony_ci      FeedbackSource const& source) const;
3881cb0ef41Sopenharmony_ci  ProcessedFeedback const& ReadFeedbackForForIn(
3891cb0ef41Sopenharmony_ci      FeedbackSource const& source) const;
3901cb0ef41Sopenharmony_ci  ProcessedFeedback const& ReadFeedbackForGlobalAccess(
3911cb0ef41Sopenharmony_ci      FeedbackSource const& source);
3921cb0ef41Sopenharmony_ci  ProcessedFeedback const& ReadFeedbackForInstanceOf(
3931cb0ef41Sopenharmony_ci      FeedbackSource const& source);
3941cb0ef41Sopenharmony_ci  ProcessedFeedback const& ReadFeedbackForPropertyAccess(
3951cb0ef41Sopenharmony_ci      FeedbackSource const& source, AccessMode mode,
3961cb0ef41Sopenharmony_ci      base::Optional<NameRef> static_name);
3971cb0ef41Sopenharmony_ci  ProcessedFeedback const& ReadFeedbackForRegExpLiteral(
3981cb0ef41Sopenharmony_ci      FeedbackSource const& source);
3991cb0ef41Sopenharmony_ci  ProcessedFeedback const& ReadFeedbackForTemplateObject(
4001cb0ef41Sopenharmony_ci      FeedbackSource const& source);
4011cb0ef41Sopenharmony_ci
4021cb0ef41Sopenharmony_ci  void CollectArrayAndObjectPrototypes();
4031cb0ef41Sopenharmony_ci
4041cb0ef41Sopenharmony_ci  void set_persistent_handles(
4051cb0ef41Sopenharmony_ci      std::unique_ptr<PersistentHandles> persistent_handles) {
4061cb0ef41Sopenharmony_ci    DCHECK_NULL(ph_);
4071cb0ef41Sopenharmony_ci    ph_ = std::move(persistent_handles);
4081cb0ef41Sopenharmony_ci    DCHECK_NOT_NULL(ph_);
4091cb0ef41Sopenharmony_ci  }
4101cb0ef41Sopenharmony_ci  std::unique_ptr<PersistentHandles> DetachPersistentHandles() {
4111cb0ef41Sopenharmony_ci    DCHECK_NOT_NULL(ph_);
4121cb0ef41Sopenharmony_ci    return std::move(ph_);
4131cb0ef41Sopenharmony_ci  }
4141cb0ef41Sopenharmony_ci
4151cb0ef41Sopenharmony_ci  void set_canonical_handles(
4161cb0ef41Sopenharmony_ci      std::unique_ptr<CanonicalHandlesMap> canonical_handles) {
4171cb0ef41Sopenharmony_ci    DCHECK_NULL(canonical_handles_);
4181cb0ef41Sopenharmony_ci    canonical_handles_ = std::move(canonical_handles);
4191cb0ef41Sopenharmony_ci    DCHECK_NOT_NULL(canonical_handles_);
4201cb0ef41Sopenharmony_ci  }
4211cb0ef41Sopenharmony_ci
4221cb0ef41Sopenharmony_ci  std::unique_ptr<CanonicalHandlesMap> DetachCanonicalHandles() {
4231cb0ef41Sopenharmony_ci    DCHECK_NOT_NULL(canonical_handles_);
4241cb0ef41Sopenharmony_ci    return std::move(canonical_handles_);
4251cb0ef41Sopenharmony_ci  }
4261cb0ef41Sopenharmony_ci
4271cb0ef41Sopenharmony_ci  // Copy the canonical handles over to the JSHeapBroker.
4281cb0ef41Sopenharmony_ci  void CopyCanonicalHandlesForTesting(
4291cb0ef41Sopenharmony_ci      std::unique_ptr<CanonicalHandlesMap> canonical_handles);
4301cb0ef41Sopenharmony_ci
4311cb0ef41Sopenharmony_ci  Isolate* const isolate_;
4321cb0ef41Sopenharmony_ci#if V8_COMPRESS_POINTERS
4331cb0ef41Sopenharmony_ci  const PtrComprCageBase cage_base_;
4341cb0ef41Sopenharmony_ci#endif  // V8_COMPRESS_POINTERS
4351cb0ef41Sopenharmony_ci  Zone* const zone_;
4361cb0ef41Sopenharmony_ci  base::Optional<NativeContextRef> target_native_context_;
4371cb0ef41Sopenharmony_ci  RefsMap* refs_;
4381cb0ef41Sopenharmony_ci  RootIndexMap root_index_map_;
4391cb0ef41Sopenharmony_ci  ZoneUnorderedSet<Handle<JSObject>, Handle<JSObject>::hash,
4401cb0ef41Sopenharmony_ci                   Handle<JSObject>::equal_to>
4411cb0ef41Sopenharmony_ci      array_and_object_prototypes_;
4421cb0ef41Sopenharmony_ci  BrokerMode mode_ = kDisabled;
4431cb0ef41Sopenharmony_ci  bool const tracing_enabled_;
4441cb0ef41Sopenharmony_ci  CodeKind const code_kind_;
4451cb0ef41Sopenharmony_ci  std::unique_ptr<PersistentHandles> ph_;
4461cb0ef41Sopenharmony_ci  LocalIsolate* local_isolate_ = nullptr;
4471cb0ef41Sopenharmony_ci  std::unique_ptr<CanonicalHandlesMap> canonical_handles_;
4481cb0ef41Sopenharmony_ci  unsigned trace_indentation_ = 0;
4491cb0ef41Sopenharmony_ci  ZoneUnorderedMap<FeedbackSource, ProcessedFeedback const*,
4501cb0ef41Sopenharmony_ci                   FeedbackSource::Hash, FeedbackSource::Equal>
4511cb0ef41Sopenharmony_ci      feedback_;
4521cb0ef41Sopenharmony_ci  ZoneUnorderedMap<PropertyAccessTarget, PropertyAccessInfo,
4531cb0ef41Sopenharmony_ci                   PropertyAccessTarget::Hash, PropertyAccessTarget::Equal>
4541cb0ef41Sopenharmony_ci      property_access_infos_;
4551cb0ef41Sopenharmony_ci
4561cb0ef41Sopenharmony_ci  CompilationDependencies* dependencies_ = nullptr;
4571cb0ef41Sopenharmony_ci
4581cb0ef41Sopenharmony_ci  // The MapUpdater mutex is used in recursive patterns; for example,
4591cb0ef41Sopenharmony_ci  // ComputePropertyAccessInfo may call itself recursively. Thus we need to
4601cb0ef41Sopenharmony_ci  // emulate a recursive mutex, which we do by checking if this heap broker
4611cb0ef41Sopenharmony_ci  // instance already holds the mutex when a lock is requested. This field
4621cb0ef41Sopenharmony_ci  // holds the locking depth, i.e. how many times the mutex has been
4631cb0ef41Sopenharmony_ci  // recursively locked. Only the outermost locker actually locks underneath.
4641cb0ef41Sopenharmony_ci  int map_updater_mutex_depth_ = 0;
4651cb0ef41Sopenharmony_ci  // Likewise for boilerplate migrations.
4661cb0ef41Sopenharmony_ci  int boilerplate_migration_mutex_depth_ = 0;
4671cb0ef41Sopenharmony_ci
4681cb0ef41Sopenharmony_ci  static constexpr uint32_t kMinimalRefsBucketCount = 8;
4691cb0ef41Sopenharmony_ci  STATIC_ASSERT(base::bits::IsPowerOfTwo(kMinimalRefsBucketCount));
4701cb0ef41Sopenharmony_ci  static constexpr uint32_t kInitialRefsBucketCount = 1024;
4711cb0ef41Sopenharmony_ci  STATIC_ASSERT(base::bits::IsPowerOfTwo(kInitialRefsBucketCount));
4721cb0ef41Sopenharmony_ci};
4731cb0ef41Sopenharmony_ci
4741cb0ef41Sopenharmony_ciclass V8_NODISCARD TraceScope {
4751cb0ef41Sopenharmony_ci public:
4761cb0ef41Sopenharmony_ci  TraceScope(JSHeapBroker* broker, const char* label)
4771cb0ef41Sopenharmony_ci      : TraceScope(broker, static_cast<void*>(broker), label) {}
4781cb0ef41Sopenharmony_ci
4791cb0ef41Sopenharmony_ci  TraceScope(JSHeapBroker* broker, ObjectData* data, const char* label)
4801cb0ef41Sopenharmony_ci      : TraceScope(broker, static_cast<void*>(data), label) {}
4811cb0ef41Sopenharmony_ci
4821cb0ef41Sopenharmony_ci  TraceScope(JSHeapBroker* broker, void* subject, const char* label)
4831cb0ef41Sopenharmony_ci      : broker_(broker) {
4841cb0ef41Sopenharmony_ci    TRACE_BROKER(broker_, "Running " << label << " on " << subject);
4851cb0ef41Sopenharmony_ci    broker_->IncrementTracingIndentation();
4861cb0ef41Sopenharmony_ci  }
4871cb0ef41Sopenharmony_ci
4881cb0ef41Sopenharmony_ci  ~TraceScope() { broker_->DecrementTracingIndentation(); }
4891cb0ef41Sopenharmony_ci
4901cb0ef41Sopenharmony_ci private:
4911cb0ef41Sopenharmony_ci  JSHeapBroker* const broker_;
4921cb0ef41Sopenharmony_ci};
4931cb0ef41Sopenharmony_ci
4941cb0ef41Sopenharmony_ci// Scope that unparks the LocalHeap, if:
4951cb0ef41Sopenharmony_ci//   a) We have a JSHeapBroker,
4961cb0ef41Sopenharmony_ci//   b) Said JSHeapBroker has a LocalIsolate and thus a LocalHeap,
4971cb0ef41Sopenharmony_ci//   c) Said LocalHeap has been parked and
4981cb0ef41Sopenharmony_ci//   d) The given condition evaluates to true.
4991cb0ef41Sopenharmony_ci// Used, for example, when printing the graph with --trace-turbo with a
5001cb0ef41Sopenharmony_ci// previously parked LocalHeap.
5011cb0ef41Sopenharmony_ciclass V8_NODISCARD UnparkedScopeIfNeeded {
5021cb0ef41Sopenharmony_ci public:
5031cb0ef41Sopenharmony_ci  explicit UnparkedScopeIfNeeded(JSHeapBroker* broker,
5041cb0ef41Sopenharmony_ci                                 bool extra_condition = true) {
5051cb0ef41Sopenharmony_ci    if (broker != nullptr && extra_condition) {
5061cb0ef41Sopenharmony_ci      LocalIsolate* local_isolate = broker->local_isolate();
5071cb0ef41Sopenharmony_ci      if (local_isolate != nullptr && local_isolate->heap()->IsParked()) {
5081cb0ef41Sopenharmony_ci        unparked_scope.emplace(local_isolate->heap());
5091cb0ef41Sopenharmony_ci      }
5101cb0ef41Sopenharmony_ci    }
5111cb0ef41Sopenharmony_ci  }
5121cb0ef41Sopenharmony_ci
5131cb0ef41Sopenharmony_ci private:
5141cb0ef41Sopenharmony_ci  base::Optional<UnparkedScope> unparked_scope;
5151cb0ef41Sopenharmony_ci};
5161cb0ef41Sopenharmony_ci
5171cb0ef41Sopenharmony_citemplate <class T,
5181cb0ef41Sopenharmony_ci          typename = std::enable_if_t<std::is_convertible<T*, Object*>::value>>
5191cb0ef41Sopenharmony_cibase::Optional<typename ref_traits<T>::ref_type> TryMakeRef(
5201cb0ef41Sopenharmony_ci    JSHeapBroker* broker, ObjectData* data) {
5211cb0ef41Sopenharmony_ci  if (data == nullptr) return {};
5221cb0ef41Sopenharmony_ci  return {typename ref_traits<T>::ref_type(broker, data)};
5231cb0ef41Sopenharmony_ci}
5241cb0ef41Sopenharmony_ci
5251cb0ef41Sopenharmony_ci// Usage:
5261cb0ef41Sopenharmony_ci//
5271cb0ef41Sopenharmony_ci//  base::Optional<FooRef> ref = TryMakeRef(broker, o);
5281cb0ef41Sopenharmony_ci//  if (!ref.has_value()) return {};  // bailout
5291cb0ef41Sopenharmony_ci//
5301cb0ef41Sopenharmony_ci// or
5311cb0ef41Sopenharmony_ci//
5321cb0ef41Sopenharmony_ci//  FooRef ref = MakeRef(broker, o);
5331cb0ef41Sopenharmony_citemplate <class T,
5341cb0ef41Sopenharmony_ci          typename = std::enable_if_t<std::is_convertible<T*, Object*>::value>>
5351cb0ef41Sopenharmony_cibase::Optional<typename ref_traits<T>::ref_type> TryMakeRef(
5361cb0ef41Sopenharmony_ci    JSHeapBroker* broker, T object, GetOrCreateDataFlags flags = {}) {
5371cb0ef41Sopenharmony_ci  ObjectData* data = broker->TryGetOrCreateData(object, flags);
5381cb0ef41Sopenharmony_ci  if (data == nullptr) {
5391cb0ef41Sopenharmony_ci    TRACE_BROKER_MISSING(broker, "ObjectData for " << Brief(object));
5401cb0ef41Sopenharmony_ci  }
5411cb0ef41Sopenharmony_ci  return TryMakeRef<T>(broker, data);
5421cb0ef41Sopenharmony_ci}
5431cb0ef41Sopenharmony_ci
5441cb0ef41Sopenharmony_citemplate <class T,
5451cb0ef41Sopenharmony_ci          typename = std::enable_if_t<std::is_convertible<T*, Object*>::value>>
5461cb0ef41Sopenharmony_cibase::Optional<typename ref_traits<T>::ref_type> TryMakeRef(
5471cb0ef41Sopenharmony_ci    JSHeapBroker* broker, Handle<T> object, GetOrCreateDataFlags flags = {}) {
5481cb0ef41Sopenharmony_ci  ObjectData* data = broker->TryGetOrCreateData(object, flags);
5491cb0ef41Sopenharmony_ci  if (data == nullptr) {
5501cb0ef41Sopenharmony_ci    DCHECK_EQ(flags & kCrashOnError, 0);
5511cb0ef41Sopenharmony_ci    TRACE_BROKER_MISSING(broker, "ObjectData for " << Brief(*object));
5521cb0ef41Sopenharmony_ci  }
5531cb0ef41Sopenharmony_ci  return TryMakeRef<T>(broker, data);
5541cb0ef41Sopenharmony_ci}
5551cb0ef41Sopenharmony_ci
5561cb0ef41Sopenharmony_citemplate <class T,
5571cb0ef41Sopenharmony_ci          typename = std::enable_if_t<std::is_convertible<T*, Object*>::value>>
5581cb0ef41Sopenharmony_citypename ref_traits<T>::ref_type MakeRef(JSHeapBroker* broker, T object) {
5591cb0ef41Sopenharmony_ci  return TryMakeRef(broker, object, kCrashOnError).value();
5601cb0ef41Sopenharmony_ci}
5611cb0ef41Sopenharmony_ci
5621cb0ef41Sopenharmony_citemplate <class T,
5631cb0ef41Sopenharmony_ci          typename = std::enable_if_t<std::is_convertible<T*, Object*>::value>>
5641cb0ef41Sopenharmony_citypename ref_traits<T>::ref_type MakeRef(JSHeapBroker* broker,
5651cb0ef41Sopenharmony_ci                                         Handle<T> object) {
5661cb0ef41Sopenharmony_ci  return TryMakeRef(broker, object, kCrashOnError).value();
5671cb0ef41Sopenharmony_ci}
5681cb0ef41Sopenharmony_ci
5691cb0ef41Sopenharmony_citemplate <class T,
5701cb0ef41Sopenharmony_ci          typename = std::enable_if_t<std::is_convertible<T*, Object*>::value>>
5711cb0ef41Sopenharmony_citypename ref_traits<T>::ref_type MakeRefAssumeMemoryFence(JSHeapBroker* broker,
5721cb0ef41Sopenharmony_ci                                                          T object) {
5731cb0ef41Sopenharmony_ci  return TryMakeRef(broker, object, kAssumeMemoryFence | kCrashOnError).value();
5741cb0ef41Sopenharmony_ci}
5751cb0ef41Sopenharmony_ci
5761cb0ef41Sopenharmony_citemplate <class T,
5771cb0ef41Sopenharmony_ci          typename = std::enable_if_t<std::is_convertible<T*, Object*>::value>>
5781cb0ef41Sopenharmony_citypename ref_traits<T>::ref_type MakeRefAssumeMemoryFence(JSHeapBroker* broker,
5791cb0ef41Sopenharmony_ci                                                          Handle<T> object) {
5801cb0ef41Sopenharmony_ci  return TryMakeRef(broker, object, kAssumeMemoryFence | kCrashOnError).value();
5811cb0ef41Sopenharmony_ci}
5821cb0ef41Sopenharmony_ci
5831cb0ef41Sopenharmony_ci}  // namespace compiler
5841cb0ef41Sopenharmony_ci}  // namespace internal
5851cb0ef41Sopenharmony_ci}  // namespace v8
5861cb0ef41Sopenharmony_ci
5871cb0ef41Sopenharmony_ci#endif  // V8_COMPILER_JS_HEAP_BROKER_H_
588