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