11cb0ef41Sopenharmony_ci// Copyright 2019 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/memory-lowering.h"
61cb0ef41Sopenharmony_ci
71cb0ef41Sopenharmony_ci#include "src/codegen/interface-descriptors-inl.h"
81cb0ef41Sopenharmony_ci#include "src/compiler/access-builder.h"
91cb0ef41Sopenharmony_ci#include "src/compiler/js-graph.h"
101cb0ef41Sopenharmony_ci#include "src/compiler/linkage.h"
111cb0ef41Sopenharmony_ci#include "src/compiler/node-matchers.h"
121cb0ef41Sopenharmony_ci#include "src/compiler/node-properties.h"
131cb0ef41Sopenharmony_ci#include "src/compiler/node.h"
141cb0ef41Sopenharmony_ci#include "src/compiler/simplified-operator.h"
151cb0ef41Sopenharmony_ci#include "src/roots/roots-inl.h"
161cb0ef41Sopenharmony_ci#include "src/sandbox/external-pointer.h"
171cb0ef41Sopenharmony_ci
181cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY
191cb0ef41Sopenharmony_ci#include "src/wasm/wasm-linkage.h"
201cb0ef41Sopenharmony_ci#include "src/wasm/wasm-objects.h"
211cb0ef41Sopenharmony_ci#endif
221cb0ef41Sopenharmony_cinamespace v8 {
231cb0ef41Sopenharmony_cinamespace internal {
241cb0ef41Sopenharmony_cinamespace compiler {
251cb0ef41Sopenharmony_ci
261cb0ef41Sopenharmony_ci// An allocation group represents a set of allocations that have been folded
271cb0ef41Sopenharmony_ci// together.
281cb0ef41Sopenharmony_ciclass MemoryLowering::AllocationGroup final : public ZoneObject {
291cb0ef41Sopenharmony_ci public:
301cb0ef41Sopenharmony_ci  AllocationGroup(Node* node, AllocationType allocation, Zone* zone);
311cb0ef41Sopenharmony_ci  AllocationGroup(Node* node, AllocationType allocation, Node* size,
321cb0ef41Sopenharmony_ci                  Zone* zone);
331cb0ef41Sopenharmony_ci  ~AllocationGroup() = default;
341cb0ef41Sopenharmony_ci
351cb0ef41Sopenharmony_ci  void Add(Node* object);
361cb0ef41Sopenharmony_ci  bool Contains(Node* object) const;
371cb0ef41Sopenharmony_ci  bool IsYoungGenerationAllocation() const {
381cb0ef41Sopenharmony_ci    return allocation() == AllocationType::kYoung;
391cb0ef41Sopenharmony_ci  }
401cb0ef41Sopenharmony_ci
411cb0ef41Sopenharmony_ci  AllocationType allocation() const { return allocation_; }
421cb0ef41Sopenharmony_ci  Node* size() const { return size_; }
431cb0ef41Sopenharmony_ci
441cb0ef41Sopenharmony_ci private:
451cb0ef41Sopenharmony_ci  ZoneSet<NodeId> node_ids_;
461cb0ef41Sopenharmony_ci  AllocationType const allocation_;
471cb0ef41Sopenharmony_ci  Node* const size_;
481cb0ef41Sopenharmony_ci
491cb0ef41Sopenharmony_ci  static inline AllocationType CheckAllocationType(AllocationType allocation) {
501cb0ef41Sopenharmony_ci    // For non-generational heap, all young allocations are redirected to old
511cb0ef41Sopenharmony_ci    // space.
521cb0ef41Sopenharmony_ci    if (FLAG_single_generation && allocation == AllocationType::kYoung) {
531cb0ef41Sopenharmony_ci      return AllocationType::kOld;
541cb0ef41Sopenharmony_ci    }
551cb0ef41Sopenharmony_ci    return allocation;
561cb0ef41Sopenharmony_ci  }
571cb0ef41Sopenharmony_ci
581cb0ef41Sopenharmony_ci  DISALLOW_IMPLICIT_CONSTRUCTORS(AllocationGroup);
591cb0ef41Sopenharmony_ci};
601cb0ef41Sopenharmony_ci
611cb0ef41Sopenharmony_ciMemoryLowering::MemoryLowering(JSGraph* jsgraph, Zone* zone,
621cb0ef41Sopenharmony_ci                               JSGraphAssembler* graph_assembler,
631cb0ef41Sopenharmony_ci                               AllocationFolding allocation_folding,
641cb0ef41Sopenharmony_ci                               WriteBarrierAssertFailedCallback callback,
651cb0ef41Sopenharmony_ci                               const char* function_debug_name)
661cb0ef41Sopenharmony_ci    : isolate_(jsgraph->isolate()),
671cb0ef41Sopenharmony_ci      zone_(zone),
681cb0ef41Sopenharmony_ci      graph_(jsgraph->graph()),
691cb0ef41Sopenharmony_ci      common_(jsgraph->common()),
701cb0ef41Sopenharmony_ci      machine_(jsgraph->machine()),
711cb0ef41Sopenharmony_ci      graph_assembler_(graph_assembler),
721cb0ef41Sopenharmony_ci      allocation_folding_(allocation_folding),
731cb0ef41Sopenharmony_ci      write_barrier_assert_failed_(callback),
741cb0ef41Sopenharmony_ci      function_debug_name_(function_debug_name) {}
751cb0ef41Sopenharmony_ci
761cb0ef41Sopenharmony_ciZone* MemoryLowering::graph_zone() const { return graph()->zone(); }
771cb0ef41Sopenharmony_ci
781cb0ef41Sopenharmony_ciReduction MemoryLowering::Reduce(Node* node) {
791cb0ef41Sopenharmony_ci  switch (node->opcode()) {
801cb0ef41Sopenharmony_ci    case IrOpcode::kAllocate:
811cb0ef41Sopenharmony_ci      // Allocate nodes were purged from the graph in effect-control
821cb0ef41Sopenharmony_ci      // linearization.
831cb0ef41Sopenharmony_ci      UNREACHABLE();
841cb0ef41Sopenharmony_ci    case IrOpcode::kAllocateRaw:
851cb0ef41Sopenharmony_ci      return ReduceAllocateRaw(node);
861cb0ef41Sopenharmony_ci    case IrOpcode::kLoadFromObject:
871cb0ef41Sopenharmony_ci    case IrOpcode::kLoadImmutableFromObject:
881cb0ef41Sopenharmony_ci      return ReduceLoadFromObject(node);
891cb0ef41Sopenharmony_ci    case IrOpcode::kLoadElement:
901cb0ef41Sopenharmony_ci      return ReduceLoadElement(node);
911cb0ef41Sopenharmony_ci    case IrOpcode::kLoadField:
921cb0ef41Sopenharmony_ci      return ReduceLoadField(node);
931cb0ef41Sopenharmony_ci    case IrOpcode::kStoreToObject:
941cb0ef41Sopenharmony_ci    case IrOpcode::kInitializeImmutableInObject:
951cb0ef41Sopenharmony_ci      return ReduceStoreToObject(node);
961cb0ef41Sopenharmony_ci    case IrOpcode::kStoreElement:
971cb0ef41Sopenharmony_ci      return ReduceStoreElement(node);
981cb0ef41Sopenharmony_ci    case IrOpcode::kStoreField:
991cb0ef41Sopenharmony_ci      return ReduceStoreField(node);
1001cb0ef41Sopenharmony_ci    case IrOpcode::kStore:
1011cb0ef41Sopenharmony_ci      return ReduceStore(node);
1021cb0ef41Sopenharmony_ci    default:
1031cb0ef41Sopenharmony_ci      return NoChange();
1041cb0ef41Sopenharmony_ci  }
1051cb0ef41Sopenharmony_ci}
1061cb0ef41Sopenharmony_ci
1071cb0ef41Sopenharmony_civoid MemoryLowering::EnsureAllocateOperator() {
1081cb0ef41Sopenharmony_ci  if (allocate_operator_.is_set()) return;
1091cb0ef41Sopenharmony_ci
1101cb0ef41Sopenharmony_ci  auto descriptor = AllocateDescriptor{};
1111cb0ef41Sopenharmony_ci  StubCallMode mode = isolate_ != nullptr ? StubCallMode::kCallCodeObject
1121cb0ef41Sopenharmony_ci                                          : StubCallMode::kCallBuiltinPointer;
1131cb0ef41Sopenharmony_ci  auto call_descriptor = Linkage::GetStubCallDescriptor(
1141cb0ef41Sopenharmony_ci      graph_zone(), descriptor, descriptor.GetStackParameterCount(),
1151cb0ef41Sopenharmony_ci      CallDescriptor::kCanUseRoots, Operator::kNoThrow, mode);
1161cb0ef41Sopenharmony_ci  allocate_operator_.set(common()->Call(call_descriptor));
1171cb0ef41Sopenharmony_ci}
1181cb0ef41Sopenharmony_ci
1191cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY
1201cb0ef41Sopenharmony_ciNode* MemoryLowering::GetWasmInstanceNode() {
1211cb0ef41Sopenharmony_ci  if (wasm_instance_node_.is_set()) return wasm_instance_node_.get();
1221cb0ef41Sopenharmony_ci  for (Node* use : graph()->start()->uses()) {
1231cb0ef41Sopenharmony_ci    if (use->opcode() == IrOpcode::kParameter &&
1241cb0ef41Sopenharmony_ci        ParameterIndexOf(use->op()) == wasm::kWasmInstanceParameterIndex) {
1251cb0ef41Sopenharmony_ci      wasm_instance_node_.set(use);
1261cb0ef41Sopenharmony_ci      return use;
1271cb0ef41Sopenharmony_ci    }
1281cb0ef41Sopenharmony_ci  }
1291cb0ef41Sopenharmony_ci  UNREACHABLE();  // The instance node must have been created before.
1301cb0ef41Sopenharmony_ci}
1311cb0ef41Sopenharmony_ci#endif  // V8_ENABLE_WEBASSEMBLY
1321cb0ef41Sopenharmony_ci
1331cb0ef41Sopenharmony_ci#define __ gasm()->
1341cb0ef41Sopenharmony_ci
1351cb0ef41Sopenharmony_ciReduction MemoryLowering::ReduceAllocateRaw(
1361cb0ef41Sopenharmony_ci    Node* node, AllocationType allocation_type,
1371cb0ef41Sopenharmony_ci    AllowLargeObjects allow_large_objects, AllocationState const** state_ptr) {
1381cb0ef41Sopenharmony_ci  DCHECK_EQ(IrOpcode::kAllocateRaw, node->opcode());
1391cb0ef41Sopenharmony_ci  DCHECK_IMPLIES(allocation_folding_ == AllocationFolding::kDoAllocationFolding,
1401cb0ef41Sopenharmony_ci                 state_ptr != nullptr);
1411cb0ef41Sopenharmony_ci  if (FLAG_single_generation && allocation_type == AllocationType::kYoung) {
1421cb0ef41Sopenharmony_ci    allocation_type = AllocationType::kOld;
1431cb0ef41Sopenharmony_ci  }
1441cb0ef41Sopenharmony_ci  // Code objects may have a maximum size smaller than kMaxHeapObjectSize due to
1451cb0ef41Sopenharmony_ci  // guard pages. If we need to support allocating code here we would need to
1461cb0ef41Sopenharmony_ci  // call MemoryChunkLayout::MaxRegularCodeObjectSize() at runtime.
1471cb0ef41Sopenharmony_ci  DCHECK_NE(allocation_type, AllocationType::kCode);
1481cb0ef41Sopenharmony_ci  Node* value;
1491cb0ef41Sopenharmony_ci  Node* size = node->InputAt(0);
1501cb0ef41Sopenharmony_ci  Node* effect = node->InputAt(1);
1511cb0ef41Sopenharmony_ci  Node* control = node->InputAt(2);
1521cb0ef41Sopenharmony_ci
1531cb0ef41Sopenharmony_ci  gasm()->InitializeEffectControl(effect, control);
1541cb0ef41Sopenharmony_ci
1551cb0ef41Sopenharmony_ci  Node* allocate_builtin;
1561cb0ef41Sopenharmony_ci  if (isolate_ != nullptr) {
1571cb0ef41Sopenharmony_ci    if (allocation_type == AllocationType::kYoung) {
1581cb0ef41Sopenharmony_ci      if (allow_large_objects == AllowLargeObjects::kTrue) {
1591cb0ef41Sopenharmony_ci        allocate_builtin = __ AllocateInYoungGenerationStubConstant();
1601cb0ef41Sopenharmony_ci      } else {
1611cb0ef41Sopenharmony_ci        allocate_builtin = __ AllocateRegularInYoungGenerationStubConstant();
1621cb0ef41Sopenharmony_ci      }
1631cb0ef41Sopenharmony_ci    } else {
1641cb0ef41Sopenharmony_ci      if (allow_large_objects == AllowLargeObjects::kTrue) {
1651cb0ef41Sopenharmony_ci        allocate_builtin = __ AllocateInOldGenerationStubConstant();
1661cb0ef41Sopenharmony_ci      } else {
1671cb0ef41Sopenharmony_ci        allocate_builtin = __ AllocateRegularInOldGenerationStubConstant();
1681cb0ef41Sopenharmony_ci      }
1691cb0ef41Sopenharmony_ci    }
1701cb0ef41Sopenharmony_ci  } else {
1711cb0ef41Sopenharmony_ci    // This lowering is used by Wasm, where we compile isolate-independent
1721cb0ef41Sopenharmony_ci    // code. Builtin calls simply encode the target builtin ID, which will
1731cb0ef41Sopenharmony_ci    // be patched to the builtin's address later.
1741cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY
1751cb0ef41Sopenharmony_ci    Builtin builtin;
1761cb0ef41Sopenharmony_ci    if (allocation_type == AllocationType::kYoung) {
1771cb0ef41Sopenharmony_ci      if (allow_large_objects == AllowLargeObjects::kTrue) {
1781cb0ef41Sopenharmony_ci        builtin = Builtin::kAllocateInYoungGeneration;
1791cb0ef41Sopenharmony_ci      } else {
1801cb0ef41Sopenharmony_ci        builtin = Builtin::kAllocateRegularInYoungGeneration;
1811cb0ef41Sopenharmony_ci      }
1821cb0ef41Sopenharmony_ci    } else {
1831cb0ef41Sopenharmony_ci      if (allow_large_objects == AllowLargeObjects::kTrue) {
1841cb0ef41Sopenharmony_ci        builtin = Builtin::kAllocateInOldGeneration;
1851cb0ef41Sopenharmony_ci      } else {
1861cb0ef41Sopenharmony_ci        builtin = Builtin::kAllocateRegularInOldGeneration;
1871cb0ef41Sopenharmony_ci      }
1881cb0ef41Sopenharmony_ci    }
1891cb0ef41Sopenharmony_ci    static_assert(std::is_same<Smi, BuiltinPtr>(), "BuiltinPtr must be Smi");
1901cb0ef41Sopenharmony_ci    allocate_builtin =
1911cb0ef41Sopenharmony_ci        graph()->NewNode(common()->NumberConstant(static_cast<int>(builtin)));
1921cb0ef41Sopenharmony_ci#else
1931cb0ef41Sopenharmony_ci    UNREACHABLE();
1941cb0ef41Sopenharmony_ci#endif
1951cb0ef41Sopenharmony_ci  }
1961cb0ef41Sopenharmony_ci
1971cb0ef41Sopenharmony_ci  // Determine the top/limit addresses.
1981cb0ef41Sopenharmony_ci  Node* top_address;
1991cb0ef41Sopenharmony_ci  Node* limit_address;
2001cb0ef41Sopenharmony_ci  if (isolate_ != nullptr) {
2011cb0ef41Sopenharmony_ci    top_address = __ ExternalConstant(
2021cb0ef41Sopenharmony_ci        allocation_type == AllocationType::kYoung
2031cb0ef41Sopenharmony_ci            ? ExternalReference::new_space_allocation_top_address(isolate())
2041cb0ef41Sopenharmony_ci            : ExternalReference::old_space_allocation_top_address(isolate()));
2051cb0ef41Sopenharmony_ci    limit_address = __ ExternalConstant(
2061cb0ef41Sopenharmony_ci        allocation_type == AllocationType::kYoung
2071cb0ef41Sopenharmony_ci            ? ExternalReference::new_space_allocation_limit_address(isolate())
2081cb0ef41Sopenharmony_ci            : ExternalReference::old_space_allocation_limit_address(isolate()));
2091cb0ef41Sopenharmony_ci  } else {
2101cb0ef41Sopenharmony_ci    // Wasm mode: producing isolate-independent code, loading the isolate
2111cb0ef41Sopenharmony_ci    // address at runtime.
2121cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY
2131cb0ef41Sopenharmony_ci    Node* instance_node = GetWasmInstanceNode();
2141cb0ef41Sopenharmony_ci    int top_address_offset =
2151cb0ef41Sopenharmony_ci        allocation_type == AllocationType::kYoung
2161cb0ef41Sopenharmony_ci            ? WasmInstanceObject::kNewAllocationTopAddressOffset
2171cb0ef41Sopenharmony_ci            : WasmInstanceObject::kOldAllocationTopAddressOffset;
2181cb0ef41Sopenharmony_ci    int limit_address_offset =
2191cb0ef41Sopenharmony_ci        allocation_type == AllocationType::kYoung
2201cb0ef41Sopenharmony_ci            ? WasmInstanceObject::kNewAllocationLimitAddressOffset
2211cb0ef41Sopenharmony_ci            : WasmInstanceObject::kOldAllocationLimitAddressOffset;
2221cb0ef41Sopenharmony_ci    top_address =
2231cb0ef41Sopenharmony_ci        __ Load(MachineType::Pointer(), instance_node,
2241cb0ef41Sopenharmony_ci                __ IntPtrConstant(top_address_offset - kHeapObjectTag));
2251cb0ef41Sopenharmony_ci    limit_address =
2261cb0ef41Sopenharmony_ci        __ Load(MachineType::Pointer(), instance_node,
2271cb0ef41Sopenharmony_ci                __ IntPtrConstant(limit_address_offset - kHeapObjectTag));
2281cb0ef41Sopenharmony_ci#else
2291cb0ef41Sopenharmony_ci    UNREACHABLE();
2301cb0ef41Sopenharmony_ci#endif  // V8_ENABLE_WEBASSEMBLY
2311cb0ef41Sopenharmony_ci  }
2321cb0ef41Sopenharmony_ci
2331cb0ef41Sopenharmony_ci  // Check if we can fold this allocation into a previous allocation represented
2341cb0ef41Sopenharmony_ci  // by the incoming {state}.
2351cb0ef41Sopenharmony_ci  IntPtrMatcher m(size);
2361cb0ef41Sopenharmony_ci  if (m.IsInRange(0, kMaxRegularHeapObjectSize) && FLAG_inline_new &&
2371cb0ef41Sopenharmony_ci      allocation_folding_ == AllocationFolding::kDoAllocationFolding) {
2381cb0ef41Sopenharmony_ci    intptr_t const object_size = m.ResolvedValue();
2391cb0ef41Sopenharmony_ci    AllocationState const* state = *state_ptr;
2401cb0ef41Sopenharmony_ci    if (state->size() <= kMaxRegularHeapObjectSize - object_size &&
2411cb0ef41Sopenharmony_ci        state->group()->allocation() == allocation_type) {
2421cb0ef41Sopenharmony_ci      // We can fold this Allocate {node} into the allocation {group}
2431cb0ef41Sopenharmony_ci      // represented by the given {state}. Compute the upper bound for
2441cb0ef41Sopenharmony_ci      // the new {state}.
2451cb0ef41Sopenharmony_ci      intptr_t const state_size = state->size() + object_size;
2461cb0ef41Sopenharmony_ci
2471cb0ef41Sopenharmony_ci      // Update the reservation check to the actual maximum upper bound.
2481cb0ef41Sopenharmony_ci      AllocationGroup* const group = state->group();
2491cb0ef41Sopenharmony_ci      if (machine()->Is64()) {
2501cb0ef41Sopenharmony_ci        if (OpParameter<int64_t>(group->size()->op()) < state_size) {
2511cb0ef41Sopenharmony_ci          NodeProperties::ChangeOp(group->size(),
2521cb0ef41Sopenharmony_ci                                   common()->Int64Constant(state_size));
2531cb0ef41Sopenharmony_ci        }
2541cb0ef41Sopenharmony_ci      } else {
2551cb0ef41Sopenharmony_ci        if (OpParameter<int32_t>(group->size()->op()) < state_size) {
2561cb0ef41Sopenharmony_ci          NodeProperties::ChangeOp(
2571cb0ef41Sopenharmony_ci              group->size(),
2581cb0ef41Sopenharmony_ci              common()->Int32Constant(static_cast<int32_t>(state_size)));
2591cb0ef41Sopenharmony_ci        }
2601cb0ef41Sopenharmony_ci      }
2611cb0ef41Sopenharmony_ci
2621cb0ef41Sopenharmony_ci      // Update the allocation top with the new object allocation.
2631cb0ef41Sopenharmony_ci      // TODO(bmeurer): Defer writing back top as much as possible.
2641cb0ef41Sopenharmony_ci      Node* top = __ IntAdd(state->top(), size);
2651cb0ef41Sopenharmony_ci      __ Store(StoreRepresentation(MachineType::PointerRepresentation(),
2661cb0ef41Sopenharmony_ci                                   kNoWriteBarrier),
2671cb0ef41Sopenharmony_ci               top_address, __ IntPtrConstant(0), top);
2681cb0ef41Sopenharmony_ci
2691cb0ef41Sopenharmony_ci      // Compute the effective inner allocated address.
2701cb0ef41Sopenharmony_ci      value = __ BitcastWordToTagged(
2711cb0ef41Sopenharmony_ci          __ IntAdd(state->top(), __ IntPtrConstant(kHeapObjectTag)));
2721cb0ef41Sopenharmony_ci      effect = gasm()->effect();
2731cb0ef41Sopenharmony_ci      control = gasm()->control();
2741cb0ef41Sopenharmony_ci
2751cb0ef41Sopenharmony_ci      // Extend the allocation {group}.
2761cb0ef41Sopenharmony_ci      group->Add(value);
2771cb0ef41Sopenharmony_ci      *state_ptr =
2781cb0ef41Sopenharmony_ci          AllocationState::Open(group, state_size, top, effect, zone());
2791cb0ef41Sopenharmony_ci    } else {
2801cb0ef41Sopenharmony_ci      auto call_runtime = __ MakeDeferredLabel();
2811cb0ef41Sopenharmony_ci      auto done = __ MakeLabel(MachineType::PointerRepresentation());
2821cb0ef41Sopenharmony_ci
2831cb0ef41Sopenharmony_ci      // Setup a mutable reservation size node; will be patched as we fold
2841cb0ef41Sopenharmony_ci      // additional allocations into this new group.
2851cb0ef41Sopenharmony_ci      Node* reservation_size = __ UniqueIntPtrConstant(object_size);
2861cb0ef41Sopenharmony_ci
2871cb0ef41Sopenharmony_ci      // Load allocation top and limit.
2881cb0ef41Sopenharmony_ci      Node* top =
2891cb0ef41Sopenharmony_ci          __ Load(MachineType::Pointer(), top_address, __ IntPtrConstant(0));
2901cb0ef41Sopenharmony_ci      Node* limit =
2911cb0ef41Sopenharmony_ci          __ Load(MachineType::Pointer(), limit_address, __ IntPtrConstant(0));
2921cb0ef41Sopenharmony_ci
2931cb0ef41Sopenharmony_ci      // Check if we need to collect garbage before we can start bump pointer
2941cb0ef41Sopenharmony_ci      // allocation (always done for folded allocations).
2951cb0ef41Sopenharmony_ci      Node* check = __ UintLessThan(__ IntAdd(top, reservation_size), limit);
2961cb0ef41Sopenharmony_ci
2971cb0ef41Sopenharmony_ci      __ GotoIfNot(check, &call_runtime);
2981cb0ef41Sopenharmony_ci      __ Goto(&done, top);
2991cb0ef41Sopenharmony_ci
3001cb0ef41Sopenharmony_ci      __ Bind(&call_runtime);
3011cb0ef41Sopenharmony_ci      {
3021cb0ef41Sopenharmony_ci        EnsureAllocateOperator();
3031cb0ef41Sopenharmony_ci        Node* vfalse = __ BitcastTaggedToWord(__ Call(
3041cb0ef41Sopenharmony_ci            allocate_operator_.get(), allocate_builtin, reservation_size));
3051cb0ef41Sopenharmony_ci        vfalse = __ IntSub(vfalse, __ IntPtrConstant(kHeapObjectTag));
3061cb0ef41Sopenharmony_ci        __ Goto(&done, vfalse);
3071cb0ef41Sopenharmony_ci      }
3081cb0ef41Sopenharmony_ci
3091cb0ef41Sopenharmony_ci      __ Bind(&done);
3101cb0ef41Sopenharmony_ci
3111cb0ef41Sopenharmony_ci      // Compute the new top and write it back.
3121cb0ef41Sopenharmony_ci      top = __ IntAdd(done.PhiAt(0), __ IntPtrConstant(object_size));
3131cb0ef41Sopenharmony_ci      __ Store(StoreRepresentation(MachineType::PointerRepresentation(),
3141cb0ef41Sopenharmony_ci                                   kNoWriteBarrier),
3151cb0ef41Sopenharmony_ci               top_address, __ IntPtrConstant(0), top);
3161cb0ef41Sopenharmony_ci
3171cb0ef41Sopenharmony_ci      // Compute the initial object address.
3181cb0ef41Sopenharmony_ci      value = __ BitcastWordToTagged(
3191cb0ef41Sopenharmony_ci          __ IntAdd(done.PhiAt(0), __ IntPtrConstant(kHeapObjectTag)));
3201cb0ef41Sopenharmony_ci      effect = gasm()->effect();
3211cb0ef41Sopenharmony_ci      control = gasm()->control();
3221cb0ef41Sopenharmony_ci
3231cb0ef41Sopenharmony_ci      // Start a new allocation group.
3241cb0ef41Sopenharmony_ci      AllocationGroup* group = zone()->New<AllocationGroup>(
3251cb0ef41Sopenharmony_ci          value, allocation_type, reservation_size, zone());
3261cb0ef41Sopenharmony_ci      *state_ptr =
3271cb0ef41Sopenharmony_ci          AllocationState::Open(group, object_size, top, effect, zone());
3281cb0ef41Sopenharmony_ci    }
3291cb0ef41Sopenharmony_ci  } else {
3301cb0ef41Sopenharmony_ci    auto call_runtime = __ MakeDeferredLabel();
3311cb0ef41Sopenharmony_ci    auto done = __ MakeLabel(MachineRepresentation::kTaggedPointer);
3321cb0ef41Sopenharmony_ci
3331cb0ef41Sopenharmony_ci    // Load allocation top and limit.
3341cb0ef41Sopenharmony_ci    Node* top =
3351cb0ef41Sopenharmony_ci        __ Load(MachineType::Pointer(), top_address, __ IntPtrConstant(0));
3361cb0ef41Sopenharmony_ci    Node* limit =
3371cb0ef41Sopenharmony_ci        __ Load(MachineType::Pointer(), limit_address, __ IntPtrConstant(0));
3381cb0ef41Sopenharmony_ci
3391cb0ef41Sopenharmony_ci    // Compute the new top.
3401cb0ef41Sopenharmony_ci    Node* new_top = __ IntAdd(top, size);
3411cb0ef41Sopenharmony_ci
3421cb0ef41Sopenharmony_ci    // Check if we can do bump pointer allocation here.
3431cb0ef41Sopenharmony_ci    Node* check = __ UintLessThan(new_top, limit);
3441cb0ef41Sopenharmony_ci    __ GotoIfNot(check, &call_runtime);
3451cb0ef41Sopenharmony_ci    if (allow_large_objects == AllowLargeObjects::kTrue) {
3461cb0ef41Sopenharmony_ci      __ GotoIfNot(
3471cb0ef41Sopenharmony_ci          __ UintLessThan(size, __ IntPtrConstant(kMaxRegularHeapObjectSize)),
3481cb0ef41Sopenharmony_ci          &call_runtime);
3491cb0ef41Sopenharmony_ci    }
3501cb0ef41Sopenharmony_ci    __ Store(StoreRepresentation(MachineType::PointerRepresentation(),
3511cb0ef41Sopenharmony_ci                                 kNoWriteBarrier),
3521cb0ef41Sopenharmony_ci             top_address, __ IntPtrConstant(0), new_top);
3531cb0ef41Sopenharmony_ci    __ Goto(&done, __ BitcastWordToTagged(
3541cb0ef41Sopenharmony_ci                       __ IntAdd(top, __ IntPtrConstant(kHeapObjectTag))));
3551cb0ef41Sopenharmony_ci
3561cb0ef41Sopenharmony_ci    __ Bind(&call_runtime);
3571cb0ef41Sopenharmony_ci    EnsureAllocateOperator();
3581cb0ef41Sopenharmony_ci    __ Goto(&done, __ Call(allocate_operator_.get(), allocate_builtin, size));
3591cb0ef41Sopenharmony_ci
3601cb0ef41Sopenharmony_ci    __ Bind(&done);
3611cb0ef41Sopenharmony_ci    value = done.PhiAt(0);
3621cb0ef41Sopenharmony_ci    effect = gasm()->effect();
3631cb0ef41Sopenharmony_ci    control = gasm()->control();
3641cb0ef41Sopenharmony_ci
3651cb0ef41Sopenharmony_ci    if (state_ptr) {
3661cb0ef41Sopenharmony_ci      // Create an unfoldable allocation group.
3671cb0ef41Sopenharmony_ci      AllocationGroup* group =
3681cb0ef41Sopenharmony_ci          zone()->New<AllocationGroup>(value, allocation_type, zone());
3691cb0ef41Sopenharmony_ci      *state_ptr = AllocationState::Closed(group, effect, zone());
3701cb0ef41Sopenharmony_ci    }
3711cb0ef41Sopenharmony_ci  }
3721cb0ef41Sopenharmony_ci
3731cb0ef41Sopenharmony_ci  return Replace(value);
3741cb0ef41Sopenharmony_ci}
3751cb0ef41Sopenharmony_ci
3761cb0ef41Sopenharmony_ciReduction MemoryLowering::ReduceLoadFromObject(Node* node) {
3771cb0ef41Sopenharmony_ci  DCHECK(node->opcode() == IrOpcode::kLoadFromObject ||
3781cb0ef41Sopenharmony_ci         node->opcode() == IrOpcode::kLoadImmutableFromObject);
3791cb0ef41Sopenharmony_ci  ObjectAccess const& access = ObjectAccessOf(node->op());
3801cb0ef41Sopenharmony_ci
3811cb0ef41Sopenharmony_ci  MachineType machine_type = access.machine_type;
3821cb0ef41Sopenharmony_ci
3831cb0ef41Sopenharmony_ci  if (machine_type.IsMapWord()) {
3841cb0ef41Sopenharmony_ci    CHECK_EQ(machine_type.semantic(), MachineSemantic::kAny);
3851cb0ef41Sopenharmony_ci    return ReduceLoadMap(node);
3861cb0ef41Sopenharmony_ci  }
3871cb0ef41Sopenharmony_ci
3881cb0ef41Sopenharmony_ci  MachineRepresentation rep = machine_type.representation();
3891cb0ef41Sopenharmony_ci  const Operator* load_op =
3901cb0ef41Sopenharmony_ci      ElementSizeInBytes(rep) > kTaggedSize &&
3911cb0ef41Sopenharmony_ci              !machine()->UnalignedLoadSupported(machine_type.representation())
3921cb0ef41Sopenharmony_ci          ? machine()->UnalignedLoad(machine_type)
3931cb0ef41Sopenharmony_ci          : machine()->Load(machine_type);
3941cb0ef41Sopenharmony_ci  NodeProperties::ChangeOp(node, load_op);
3951cb0ef41Sopenharmony_ci  return Changed(node);
3961cb0ef41Sopenharmony_ci}
3971cb0ef41Sopenharmony_ci
3981cb0ef41Sopenharmony_ciReduction MemoryLowering::ReduceLoadElement(Node* node) {
3991cb0ef41Sopenharmony_ci  DCHECK_EQ(IrOpcode::kLoadElement, node->opcode());
4001cb0ef41Sopenharmony_ci  ElementAccess const& access = ElementAccessOf(node->op());
4011cb0ef41Sopenharmony_ci  Node* index = node->InputAt(1);
4021cb0ef41Sopenharmony_ci  node->ReplaceInput(1, ComputeIndex(access, index));
4031cb0ef41Sopenharmony_ci  MachineType type = access.machine_type;
4041cb0ef41Sopenharmony_ci  DCHECK(!type.IsMapWord());
4051cb0ef41Sopenharmony_ci  NodeProperties::ChangeOp(node, machine()->Load(type));
4061cb0ef41Sopenharmony_ci  return Changed(node);
4071cb0ef41Sopenharmony_ci}
4081cb0ef41Sopenharmony_ci
4091cb0ef41Sopenharmony_ciNode* MemoryLowering::DecodeExternalPointer(
4101cb0ef41Sopenharmony_ci    Node* node, ExternalPointerTag external_pointer_tag) {
4111cb0ef41Sopenharmony_ci#ifdef V8_SANDBOXED_EXTERNAL_POINTERS
4121cb0ef41Sopenharmony_ci  DCHECK(V8_SANDBOXED_EXTERNAL_POINTERS_BOOL);
4131cb0ef41Sopenharmony_ci  DCHECK(node->opcode() == IrOpcode::kLoad);
4141cb0ef41Sopenharmony_ci  DCHECK_EQ(kExternalPointerSize, kUInt32Size);
4151cb0ef41Sopenharmony_ci  DCHECK_NE(kExternalPointerNullTag, external_pointer_tag);
4161cb0ef41Sopenharmony_ci  Node* effect = NodeProperties::GetEffectInput(node);
4171cb0ef41Sopenharmony_ci  Node* control = NodeProperties::GetControlInput(node);
4181cb0ef41Sopenharmony_ci  __ InitializeEffectControl(effect, control);
4191cb0ef41Sopenharmony_ci
4201cb0ef41Sopenharmony_ci  // Clone the load node and put it here.
4211cb0ef41Sopenharmony_ci  // TODO(turbofan): consider adding GraphAssembler::Clone() suitable for
4221cb0ef41Sopenharmony_ci  // cloning nodes from arbitrary locaions in effect/control chains.
4231cb0ef41Sopenharmony_ci  STATIC_ASSERT(kExternalPointerIndexShift > kSystemPointerSizeLog2);
4241cb0ef41Sopenharmony_ci  Node* shifted_index = __ AddNode(graph()->CloneNode(node));
4251cb0ef41Sopenharmony_ci  Node* shift_amount =
4261cb0ef41Sopenharmony_ci      __ Int32Constant(kExternalPointerIndexShift - kSystemPointerSizeLog2);
4271cb0ef41Sopenharmony_ci  Node* offset = __ Word32Shr(shifted_index, shift_amount);
4281cb0ef41Sopenharmony_ci
4291cb0ef41Sopenharmony_ci  // Uncomment this to generate a breakpoint for debugging purposes.
4301cb0ef41Sopenharmony_ci  // __ DebugBreak();
4311cb0ef41Sopenharmony_ci
4321cb0ef41Sopenharmony_ci  // Decode loaded external pointer.
4331cb0ef41Sopenharmony_ci  //
4341cb0ef41Sopenharmony_ci  // Here we access the external pointer table through an ExternalReference.
4351cb0ef41Sopenharmony_ci  // Alternatively, we could also hardcode the address of the table since it is
4361cb0ef41Sopenharmony_ci  // never reallocated. However, in that case we must be able to guarantee that
4371cb0ef41Sopenharmony_ci  // the generated code is never executed under a different Isolate, as that
4381cb0ef41Sopenharmony_ci  // would allow access to external objects from different Isolates. It also
4391cb0ef41Sopenharmony_ci  // would break if the code is serialized/deserialized at some point.
4401cb0ef41Sopenharmony_ci  Node* table_address = __ ExternalConstant(
4411cb0ef41Sopenharmony_ci      ExternalReference::external_pointer_table_address(isolate()));
4421cb0ef41Sopenharmony_ci  Node* table = __ Load(MachineType::Pointer(), table_address,
4431cb0ef41Sopenharmony_ci                        Internals::kExternalPointerTableBufferOffset);
4441cb0ef41Sopenharmony_ci  Node* decoded_ptr =
4451cb0ef41Sopenharmony_ci      __ Load(MachineType::Pointer(), table, __ ChangeUint32ToUint64(offset));
4461cb0ef41Sopenharmony_ci  Node* tag = __ IntPtrConstant(~external_pointer_tag);
4471cb0ef41Sopenharmony_ci  decoded_ptr = __ WordAnd(decoded_ptr, tag);
4481cb0ef41Sopenharmony_ci  return decoded_ptr;
4491cb0ef41Sopenharmony_ci#else
4501cb0ef41Sopenharmony_ci  return node;
4511cb0ef41Sopenharmony_ci#endif  // V8_SANDBOXED_EXTERNAL_POINTERS
4521cb0ef41Sopenharmony_ci}
4531cb0ef41Sopenharmony_ci
4541cb0ef41Sopenharmony_ciReduction MemoryLowering::ReduceLoadMap(Node* node) {
4551cb0ef41Sopenharmony_ci#ifdef V8_MAP_PACKING
4561cb0ef41Sopenharmony_ci  NodeProperties::ChangeOp(node, machine()->Load(MachineType::AnyTagged()));
4571cb0ef41Sopenharmony_ci
4581cb0ef41Sopenharmony_ci  Node* effect = NodeProperties::GetEffectInput(node);
4591cb0ef41Sopenharmony_ci  Node* control = NodeProperties::GetControlInput(node);
4601cb0ef41Sopenharmony_ci  __ InitializeEffectControl(effect, control);
4611cb0ef41Sopenharmony_ci
4621cb0ef41Sopenharmony_ci  node = __ AddNode(graph()->CloneNode(node));
4631cb0ef41Sopenharmony_ci  return Replace(__ UnpackMapWord(node));
4641cb0ef41Sopenharmony_ci#else
4651cb0ef41Sopenharmony_ci  NodeProperties::ChangeOp(node, machine()->Load(MachineType::TaggedPointer()));
4661cb0ef41Sopenharmony_ci  return Changed(node);
4671cb0ef41Sopenharmony_ci#endif
4681cb0ef41Sopenharmony_ci}
4691cb0ef41Sopenharmony_ci
4701cb0ef41Sopenharmony_ciReduction MemoryLowering::ReduceLoadField(Node* node) {
4711cb0ef41Sopenharmony_ci  DCHECK_EQ(IrOpcode::kLoadField, node->opcode());
4721cb0ef41Sopenharmony_ci  FieldAccess const& access = FieldAccessOf(node->op());
4731cb0ef41Sopenharmony_ci  Node* offset = __ IntPtrConstant(access.offset - access.tag());
4741cb0ef41Sopenharmony_ci  node->InsertInput(graph_zone(), 1, offset);
4751cb0ef41Sopenharmony_ci  MachineType type = access.machine_type;
4761cb0ef41Sopenharmony_ci  if (V8_SANDBOXED_EXTERNAL_POINTERS_BOOL &&
4771cb0ef41Sopenharmony_ci      access.type.Is(Type::ExternalPointer())) {
4781cb0ef41Sopenharmony_ci    // External pointer table indices are stored as 32-bit numbers
4791cb0ef41Sopenharmony_ci    type = MachineType::Uint32();
4801cb0ef41Sopenharmony_ci  }
4811cb0ef41Sopenharmony_ci
4821cb0ef41Sopenharmony_ci  if (type.IsMapWord()) {
4831cb0ef41Sopenharmony_ci    DCHECK(!access.type.Is(Type::ExternalPointer()));
4841cb0ef41Sopenharmony_ci    return ReduceLoadMap(node);
4851cb0ef41Sopenharmony_ci  }
4861cb0ef41Sopenharmony_ci
4871cb0ef41Sopenharmony_ci  NodeProperties::ChangeOp(node, machine()->Load(type));
4881cb0ef41Sopenharmony_ci
4891cb0ef41Sopenharmony_ci#ifdef V8_SANDBOXED_EXTERNAL_POINTERS
4901cb0ef41Sopenharmony_ci  if (access.type.Is(Type::ExternalPointer())) {
4911cb0ef41Sopenharmony_ci    ExternalPointerTag tag = access.external_pointer_tag;
4921cb0ef41Sopenharmony_ci    DCHECK_NE(kExternalPointerNullTag, tag);
4931cb0ef41Sopenharmony_ci    node = DecodeExternalPointer(node, tag);
4941cb0ef41Sopenharmony_ci    return Replace(node);
4951cb0ef41Sopenharmony_ci  }
4961cb0ef41Sopenharmony_ci#endif
4971cb0ef41Sopenharmony_ci
4981cb0ef41Sopenharmony_ci  return Changed(node);
4991cb0ef41Sopenharmony_ci}
5001cb0ef41Sopenharmony_ci
5011cb0ef41Sopenharmony_ciReduction MemoryLowering::ReduceStoreToObject(Node* node,
5021cb0ef41Sopenharmony_ci                                              AllocationState const* state) {
5031cb0ef41Sopenharmony_ci  DCHECK(node->opcode() == IrOpcode::kStoreToObject ||
5041cb0ef41Sopenharmony_ci         node->opcode() == IrOpcode::kInitializeImmutableInObject);
5051cb0ef41Sopenharmony_ci  ObjectAccess const& access = ObjectAccessOf(node->op());
5061cb0ef41Sopenharmony_ci  Node* object = node->InputAt(0);
5071cb0ef41Sopenharmony_ci  Node* value = node->InputAt(2);
5081cb0ef41Sopenharmony_ci
5091cb0ef41Sopenharmony_ci  WriteBarrierKind write_barrier_kind = ComputeWriteBarrierKind(
5101cb0ef41Sopenharmony_ci      node, object, value, state, access.write_barrier_kind);
5111cb0ef41Sopenharmony_ci  DCHECK(!access.machine_type.IsMapWord());
5121cb0ef41Sopenharmony_ci  MachineRepresentation rep = access.machine_type.representation();
5131cb0ef41Sopenharmony_ci  StoreRepresentation store_rep(rep, write_barrier_kind);
5141cb0ef41Sopenharmony_ci  const Operator* store_op = ElementSizeInBytes(rep) > kTaggedSize &&
5151cb0ef41Sopenharmony_ci                                     !machine()->UnalignedStoreSupported(rep)
5161cb0ef41Sopenharmony_ci                                 ? machine()->UnalignedStore(rep)
5171cb0ef41Sopenharmony_ci                                 : machine()->Store(store_rep);
5181cb0ef41Sopenharmony_ci  NodeProperties::ChangeOp(node, store_op);
5191cb0ef41Sopenharmony_ci  return Changed(node);
5201cb0ef41Sopenharmony_ci}
5211cb0ef41Sopenharmony_ci
5221cb0ef41Sopenharmony_ciReduction MemoryLowering::ReduceStoreElement(Node* node,
5231cb0ef41Sopenharmony_ci                                             AllocationState const* state) {
5241cb0ef41Sopenharmony_ci  DCHECK_EQ(IrOpcode::kStoreElement, node->opcode());
5251cb0ef41Sopenharmony_ci  ElementAccess const& access = ElementAccessOf(node->op());
5261cb0ef41Sopenharmony_ci  Node* object = node->InputAt(0);
5271cb0ef41Sopenharmony_ci  Node* index = node->InputAt(1);
5281cb0ef41Sopenharmony_ci  Node* value = node->InputAt(2);
5291cb0ef41Sopenharmony_ci  node->ReplaceInput(1, ComputeIndex(access, index));
5301cb0ef41Sopenharmony_ci  WriteBarrierKind write_barrier_kind = ComputeWriteBarrierKind(
5311cb0ef41Sopenharmony_ci      node, object, value, state, access.write_barrier_kind);
5321cb0ef41Sopenharmony_ci  NodeProperties::ChangeOp(
5331cb0ef41Sopenharmony_ci      node, machine()->Store(StoreRepresentation(
5341cb0ef41Sopenharmony_ci                access.machine_type.representation(), write_barrier_kind)));
5351cb0ef41Sopenharmony_ci  return Changed(node);
5361cb0ef41Sopenharmony_ci}
5371cb0ef41Sopenharmony_ci
5381cb0ef41Sopenharmony_ciReduction MemoryLowering::ReduceStoreField(Node* node,
5391cb0ef41Sopenharmony_ci                                           AllocationState const* state) {
5401cb0ef41Sopenharmony_ci  DCHECK_EQ(IrOpcode::kStoreField, node->opcode());
5411cb0ef41Sopenharmony_ci  FieldAccess const& access = FieldAccessOf(node->op());
5421cb0ef41Sopenharmony_ci  // External pointer must never be stored by optimized code.
5431cb0ef41Sopenharmony_ci  DCHECK_IMPLIES(V8_SANDBOXED_EXTERNAL_POINTERS_BOOL,
5441cb0ef41Sopenharmony_ci                 !access.type.Is(Type::ExternalPointer()));
5451cb0ef41Sopenharmony_ci  // SandboxedPointers are not currently stored by optimized code.
5461cb0ef41Sopenharmony_ci  DCHECK(!access.type.Is(Type::SandboxedPointer()));
5471cb0ef41Sopenharmony_ci  MachineType machine_type = access.machine_type;
5481cb0ef41Sopenharmony_ci  Node* object = node->InputAt(0);
5491cb0ef41Sopenharmony_ci  Node* value = node->InputAt(1);
5501cb0ef41Sopenharmony_ci
5511cb0ef41Sopenharmony_ci  Node* effect = NodeProperties::GetEffectInput(node);
5521cb0ef41Sopenharmony_ci  Node* control = NodeProperties::GetControlInput(node);
5531cb0ef41Sopenharmony_ci  __ InitializeEffectControl(effect, control);
5541cb0ef41Sopenharmony_ci
5551cb0ef41Sopenharmony_ci  WriteBarrierKind write_barrier_kind = ComputeWriteBarrierKind(
5561cb0ef41Sopenharmony_ci      node, object, value, state, access.write_barrier_kind);
5571cb0ef41Sopenharmony_ci  Node* offset = __ IntPtrConstant(access.offset - access.tag());
5581cb0ef41Sopenharmony_ci  node->InsertInput(graph_zone(), 1, offset);
5591cb0ef41Sopenharmony_ci
5601cb0ef41Sopenharmony_ci  if (machine_type.IsMapWord()) {
5611cb0ef41Sopenharmony_ci    machine_type = MachineType::TaggedPointer();
5621cb0ef41Sopenharmony_ci#ifdef V8_MAP_PACKING
5631cb0ef41Sopenharmony_ci    Node* mapword = __ PackMapWord(TNode<Map>::UncheckedCast(value));
5641cb0ef41Sopenharmony_ci    node->ReplaceInput(2, mapword);
5651cb0ef41Sopenharmony_ci#endif
5661cb0ef41Sopenharmony_ci  }
5671cb0ef41Sopenharmony_ci  NodeProperties::ChangeOp(
5681cb0ef41Sopenharmony_ci      node, machine()->Store(StoreRepresentation(machine_type.representation(),
5691cb0ef41Sopenharmony_ci                                                 write_barrier_kind)));
5701cb0ef41Sopenharmony_ci  return Changed(node);
5711cb0ef41Sopenharmony_ci}
5721cb0ef41Sopenharmony_ci
5731cb0ef41Sopenharmony_ciReduction MemoryLowering::ReduceStore(Node* node,
5741cb0ef41Sopenharmony_ci                                      AllocationState const* state) {
5751cb0ef41Sopenharmony_ci  DCHECK_EQ(IrOpcode::kStore, node->opcode());
5761cb0ef41Sopenharmony_ci  StoreRepresentation representation = StoreRepresentationOf(node->op());
5771cb0ef41Sopenharmony_ci  Node* object = node->InputAt(0);
5781cb0ef41Sopenharmony_ci  Node* value = node->InputAt(2);
5791cb0ef41Sopenharmony_ci  WriteBarrierKind write_barrier_kind = ComputeWriteBarrierKind(
5801cb0ef41Sopenharmony_ci      node, object, value, state, representation.write_barrier_kind());
5811cb0ef41Sopenharmony_ci  if (write_barrier_kind != representation.write_barrier_kind()) {
5821cb0ef41Sopenharmony_ci    NodeProperties::ChangeOp(
5831cb0ef41Sopenharmony_ci        node, machine()->Store(StoreRepresentation(
5841cb0ef41Sopenharmony_ci                  representation.representation(), write_barrier_kind)));
5851cb0ef41Sopenharmony_ci    return Changed(node);
5861cb0ef41Sopenharmony_ci  }
5871cb0ef41Sopenharmony_ci  return NoChange();
5881cb0ef41Sopenharmony_ci}
5891cb0ef41Sopenharmony_ci
5901cb0ef41Sopenharmony_ciNode* MemoryLowering::ComputeIndex(ElementAccess const& access, Node* index) {
5911cb0ef41Sopenharmony_ci  int const element_size_shift =
5921cb0ef41Sopenharmony_ci      ElementSizeLog2Of(access.machine_type.representation());
5931cb0ef41Sopenharmony_ci  if (element_size_shift) {
5941cb0ef41Sopenharmony_ci    index = __ WordShl(index, __ IntPtrConstant(element_size_shift));
5951cb0ef41Sopenharmony_ci  }
5961cb0ef41Sopenharmony_ci  int const fixed_offset = access.header_size - access.tag();
5971cb0ef41Sopenharmony_ci  if (fixed_offset) {
5981cb0ef41Sopenharmony_ci    index = __ IntAdd(index, __ IntPtrConstant(fixed_offset));
5991cb0ef41Sopenharmony_ci  }
6001cb0ef41Sopenharmony_ci  return index;
6011cb0ef41Sopenharmony_ci}
6021cb0ef41Sopenharmony_ci
6031cb0ef41Sopenharmony_ci#undef __
6041cb0ef41Sopenharmony_ci
6051cb0ef41Sopenharmony_cinamespace {
6061cb0ef41Sopenharmony_ci
6071cb0ef41Sopenharmony_cibool ValueNeedsWriteBarrier(Node* value, Isolate* isolate) {
6081cb0ef41Sopenharmony_ci  while (true) {
6091cb0ef41Sopenharmony_ci    switch (value->opcode()) {
6101cb0ef41Sopenharmony_ci      case IrOpcode::kBitcastWordToTaggedSigned:
6111cb0ef41Sopenharmony_ci        return false;
6121cb0ef41Sopenharmony_ci      case IrOpcode::kHeapConstant: {
6131cb0ef41Sopenharmony_ci        RootIndex root_index;
6141cb0ef41Sopenharmony_ci        if (isolate->roots_table().IsRootHandle(HeapConstantOf(value->op()),
6151cb0ef41Sopenharmony_ci                                                &root_index) &&
6161cb0ef41Sopenharmony_ci            RootsTable::IsImmortalImmovable(root_index)) {
6171cb0ef41Sopenharmony_ci          return false;
6181cb0ef41Sopenharmony_ci        }
6191cb0ef41Sopenharmony_ci        break;
6201cb0ef41Sopenharmony_ci      }
6211cb0ef41Sopenharmony_ci      default:
6221cb0ef41Sopenharmony_ci        break;
6231cb0ef41Sopenharmony_ci    }
6241cb0ef41Sopenharmony_ci    return true;
6251cb0ef41Sopenharmony_ci  }
6261cb0ef41Sopenharmony_ci}
6271cb0ef41Sopenharmony_ci
6281cb0ef41Sopenharmony_ci}  // namespace
6291cb0ef41Sopenharmony_ci
6301cb0ef41Sopenharmony_ciReduction MemoryLowering::ReduceAllocateRaw(Node* node) {
6311cb0ef41Sopenharmony_ci  DCHECK_EQ(IrOpcode::kAllocateRaw, node->opcode());
6321cb0ef41Sopenharmony_ci  const AllocateParameters& allocation = AllocateParametersOf(node->op());
6331cb0ef41Sopenharmony_ci  return ReduceAllocateRaw(node, allocation.allocation_type(),
6341cb0ef41Sopenharmony_ci                           allocation.allow_large_objects(), nullptr);
6351cb0ef41Sopenharmony_ci}
6361cb0ef41Sopenharmony_ci
6371cb0ef41Sopenharmony_ciWriteBarrierKind MemoryLowering::ComputeWriteBarrierKind(
6381cb0ef41Sopenharmony_ci    Node* node, Node* object, Node* value, AllocationState const* state,
6391cb0ef41Sopenharmony_ci    WriteBarrierKind write_barrier_kind) {
6401cb0ef41Sopenharmony_ci  if (state && state->IsYoungGenerationAllocation() &&
6411cb0ef41Sopenharmony_ci      state->group()->Contains(object)) {
6421cb0ef41Sopenharmony_ci    write_barrier_kind = kNoWriteBarrier;
6431cb0ef41Sopenharmony_ci  }
6441cb0ef41Sopenharmony_ci  if (!ValueNeedsWriteBarrier(value, isolate())) {
6451cb0ef41Sopenharmony_ci    write_barrier_kind = kNoWriteBarrier;
6461cb0ef41Sopenharmony_ci  }
6471cb0ef41Sopenharmony_ci  if (FLAG_disable_write_barriers) {
6481cb0ef41Sopenharmony_ci    write_barrier_kind = kNoWriteBarrier;
6491cb0ef41Sopenharmony_ci  }
6501cb0ef41Sopenharmony_ci  if (write_barrier_kind == WriteBarrierKind::kAssertNoWriteBarrier) {
6511cb0ef41Sopenharmony_ci    write_barrier_assert_failed_(node, object, function_debug_name_, zone());
6521cb0ef41Sopenharmony_ci  }
6531cb0ef41Sopenharmony_ci  return write_barrier_kind;
6541cb0ef41Sopenharmony_ci}
6551cb0ef41Sopenharmony_ci
6561cb0ef41Sopenharmony_ciMemoryLowering::AllocationGroup::AllocationGroup(Node* node,
6571cb0ef41Sopenharmony_ci                                                 AllocationType allocation,
6581cb0ef41Sopenharmony_ci                                                 Zone* zone)
6591cb0ef41Sopenharmony_ci    : node_ids_(zone),
6601cb0ef41Sopenharmony_ci      allocation_(CheckAllocationType(allocation)),
6611cb0ef41Sopenharmony_ci      size_(nullptr) {
6621cb0ef41Sopenharmony_ci  node_ids_.insert(node->id());
6631cb0ef41Sopenharmony_ci}
6641cb0ef41Sopenharmony_ci
6651cb0ef41Sopenharmony_ciMemoryLowering::AllocationGroup::AllocationGroup(Node* node,
6661cb0ef41Sopenharmony_ci                                                 AllocationType allocation,
6671cb0ef41Sopenharmony_ci                                                 Node* size, Zone* zone)
6681cb0ef41Sopenharmony_ci    : node_ids_(zone),
6691cb0ef41Sopenharmony_ci      allocation_(CheckAllocationType(allocation)),
6701cb0ef41Sopenharmony_ci      size_(size) {
6711cb0ef41Sopenharmony_ci  node_ids_.insert(node->id());
6721cb0ef41Sopenharmony_ci}
6731cb0ef41Sopenharmony_ci
6741cb0ef41Sopenharmony_civoid MemoryLowering::AllocationGroup::Add(Node* node) {
6751cb0ef41Sopenharmony_ci  node_ids_.insert(node->id());
6761cb0ef41Sopenharmony_ci}
6771cb0ef41Sopenharmony_ci
6781cb0ef41Sopenharmony_cibool MemoryLowering::AllocationGroup::Contains(Node* node) const {
6791cb0ef41Sopenharmony_ci  // Additions should stay within the same allocated object, so it's safe to
6801cb0ef41Sopenharmony_ci  // ignore them.
6811cb0ef41Sopenharmony_ci  while (node_ids_.find(node->id()) == node_ids_.end()) {
6821cb0ef41Sopenharmony_ci    switch (node->opcode()) {
6831cb0ef41Sopenharmony_ci      case IrOpcode::kBitcastTaggedToWord:
6841cb0ef41Sopenharmony_ci      case IrOpcode::kBitcastWordToTagged:
6851cb0ef41Sopenharmony_ci      case IrOpcode::kInt32Add:
6861cb0ef41Sopenharmony_ci      case IrOpcode::kInt64Add:
6871cb0ef41Sopenharmony_ci        node = NodeProperties::GetValueInput(node, 0);
6881cb0ef41Sopenharmony_ci        break;
6891cb0ef41Sopenharmony_ci      default:
6901cb0ef41Sopenharmony_ci        return false;
6911cb0ef41Sopenharmony_ci    }
6921cb0ef41Sopenharmony_ci  }
6931cb0ef41Sopenharmony_ci  return true;
6941cb0ef41Sopenharmony_ci}
6951cb0ef41Sopenharmony_ci
6961cb0ef41Sopenharmony_ciMemoryLowering::AllocationState::AllocationState()
6971cb0ef41Sopenharmony_ci    : group_(nullptr),
6981cb0ef41Sopenharmony_ci      size_(std::numeric_limits<int>::max()),
6991cb0ef41Sopenharmony_ci      top_(nullptr),
7001cb0ef41Sopenharmony_ci      effect_(nullptr) {}
7011cb0ef41Sopenharmony_ci
7021cb0ef41Sopenharmony_ciMemoryLowering::AllocationState::AllocationState(AllocationGroup* group,
7031cb0ef41Sopenharmony_ci                                                 Node* effect)
7041cb0ef41Sopenharmony_ci    : group_(group),
7051cb0ef41Sopenharmony_ci      size_(std::numeric_limits<int>::max()),
7061cb0ef41Sopenharmony_ci      top_(nullptr),
7071cb0ef41Sopenharmony_ci      effect_(effect) {}
7081cb0ef41Sopenharmony_ci
7091cb0ef41Sopenharmony_ciMemoryLowering::AllocationState::AllocationState(AllocationGroup* group,
7101cb0ef41Sopenharmony_ci                                                 intptr_t size, Node* top,
7111cb0ef41Sopenharmony_ci                                                 Node* effect)
7121cb0ef41Sopenharmony_ci    : group_(group), size_(size), top_(top), effect_(effect) {}
7131cb0ef41Sopenharmony_ci
7141cb0ef41Sopenharmony_cibool MemoryLowering::AllocationState::IsYoungGenerationAllocation() const {
7151cb0ef41Sopenharmony_ci  return group() && group()->IsYoungGenerationAllocation();
7161cb0ef41Sopenharmony_ci}
7171cb0ef41Sopenharmony_ci
7181cb0ef41Sopenharmony_ci}  // namespace compiler
7191cb0ef41Sopenharmony_ci}  // namespace internal
7201cb0ef41Sopenharmony_ci}  // namespace v8
721