14514f5e3Sopenharmony_ci/*
24514f5e3Sopenharmony_ci * Copyright (c) 2022 Huawei Device Co., Ltd.
34514f5e3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
44514f5e3Sopenharmony_ci * you may not use this file except in compliance with the License.
54514f5e3Sopenharmony_ci * You may obtain a copy of the License at
64514f5e3Sopenharmony_ci *
74514f5e3Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
84514f5e3Sopenharmony_ci *
94514f5e3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
104514f5e3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
114514f5e3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
124514f5e3Sopenharmony_ci * See the License for the specific language governing permissions and
134514f5e3Sopenharmony_ci * limitations under the License.
144514f5e3Sopenharmony_ci */
154514f5e3Sopenharmony_ci
164514f5e3Sopenharmony_ci#include "ecmascript/mem/heap_region_allocator.h"
174514f5e3Sopenharmony_ci
184514f5e3Sopenharmony_ci#include "ecmascript/jit/jit.h"
194514f5e3Sopenharmony_ci#include "ecmascript/mem/mem_map_allocator.h"
204514f5e3Sopenharmony_ci
214514f5e3Sopenharmony_cinamespace panda::ecmascript {
224514f5e3Sopenharmony_ciconstexpr size_t PANDA_POOL_ALIGNMENT_IN_BYTES = 256_KB;
234514f5e3Sopenharmony_ci
244514f5e3Sopenharmony_ciRegion *HeapRegionAllocator::AllocateAlignedRegion(Space *space, size_t capacity, JSThread* thread, BaseHeap *heap,
254514f5e3Sopenharmony_ci                                                   bool isFresh)
264514f5e3Sopenharmony_ci{
274514f5e3Sopenharmony_ci    if (capacity == 0) { // LOCV_EXCL_BR_LINE
284514f5e3Sopenharmony_ci        LOG_ECMA_MEM(FATAL) << "capacity must have a size bigger than 0";
294514f5e3Sopenharmony_ci        UNREACHABLE();
304514f5e3Sopenharmony_ci    }
314514f5e3Sopenharmony_ci    RegionSpaceFlag flags = space->GetRegionFlag();
324514f5e3Sopenharmony_ci    RegionTypeFlag typeFlag = isFresh ? RegionTypeFlag::FRESH : RegionTypeFlag::DEFAULT;
334514f5e3Sopenharmony_ci    bool isRegular = (flags != RegionSpaceFlag::IN_HUGE_OBJECT_SPACE &&
344514f5e3Sopenharmony_ci        flags != RegionSpaceFlag::IN_HUGE_MACHINE_CODE_SPACE &&
354514f5e3Sopenharmony_ci        flags != RegionSpaceFlag::IN_SHARED_HUGE_OBJECT_SPACE);
364514f5e3Sopenharmony_ci    bool isMachineCode = (flags == RegionSpaceFlag::IN_MACHINE_CODE_SPACE ||
374514f5e3Sopenharmony_ci        flags == RegionSpaceFlag::IN_HUGE_MACHINE_CODE_SPACE);
384514f5e3Sopenharmony_ci    auto tid = thread ? thread->GetThreadId() : JSThread::GetCurrentThreadId();
394514f5e3Sopenharmony_ci    auto pool = MemMapAllocator::GetInstance()->Allocate(tid, capacity, DEFAULT_REGION_SIZE,
404514f5e3Sopenharmony_ci                                                         ToSpaceTypeName(space->GetSpaceType()),
414514f5e3Sopenharmony_ci                                                         isRegular, isMachineCode,
424514f5e3Sopenharmony_ci                                                         Jit::GetInstance()->IsEnableJitFort());
434514f5e3Sopenharmony_ci    void *mapMem = pool.GetMem();
444514f5e3Sopenharmony_ci    if (mapMem == nullptr) { // LOCV_EXCL_BR_LINE
454514f5e3Sopenharmony_ci        if (thread != nullptr && thread->GetEcmaVM()->IsInitialized()) {
464514f5e3Sopenharmony_ci            Heap *localHeap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
474514f5e3Sopenharmony_ci            localHeap->DumpHeapSnapshotBeforeOOM();
484514f5e3Sopenharmony_ci            heap->ThrowOutOfMemoryErrorForDefault(thread, DEFAULT_REGION_SIZE,
494514f5e3Sopenharmony_ci                "HeapRegionAllocator::AllocateAlignedRegion", false);
504514f5e3Sopenharmony_ci        }
514514f5e3Sopenharmony_ci        LOG_ECMA_MEM(FATAL) << "pool is empty " << annoMemoryUsage_.load(std::memory_order_relaxed);
524514f5e3Sopenharmony_ci        UNREACHABLE();
534514f5e3Sopenharmony_ci    }
544514f5e3Sopenharmony_ci#if ECMASCRIPT_ENABLE_ZAP_MEM
554514f5e3Sopenharmony_ci    if (memset_s(mapMem, capacity, 0, capacity) != EOK) { // LOCV_EXCL_BR_LINE
564514f5e3Sopenharmony_ci        LOG_FULL(FATAL) << "memset_s failed";
574514f5e3Sopenharmony_ci        UNREACHABLE();
584514f5e3Sopenharmony_ci    }
594514f5e3Sopenharmony_ci#endif
604514f5e3Sopenharmony_ci    IncreaseAnnoMemoryUsage(capacity);
614514f5e3Sopenharmony_ci
624514f5e3Sopenharmony_ci    uintptr_t mem = ToUintPtr(mapMem);
634514f5e3Sopenharmony_ci    // Check that the address is 256K byte aligned
644514f5e3Sopenharmony_ci    LOG_ECMA_IF(AlignUp(mem, PANDA_POOL_ALIGNMENT_IN_BYTES) != mem, FATAL) << "region not align by 256KB";
654514f5e3Sopenharmony_ci    // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
664514f5e3Sopenharmony_ci    uintptr_t begin = AlignUp(mem + sizeof(Region), static_cast<size_t>(MemAlignment::MEM_ALIGN_REGION));
674514f5e3Sopenharmony_ci    uintptr_t end = mem + capacity;
684514f5e3Sopenharmony_ci
694514f5e3Sopenharmony_ci    Region *region = new (ToVoidPtr(mem)) Region(heap->GetNativeAreaAllocator(), mem, begin, end, flags, typeFlag);
704514f5e3Sopenharmony_ci    region->Initialize();
714514f5e3Sopenharmony_ci    std::atomic_thread_fence(std::memory_order_seq_cst);
724514f5e3Sopenharmony_ci    return region;
734514f5e3Sopenharmony_ci}
744514f5e3Sopenharmony_ci
754514f5e3Sopenharmony_civoid HeapRegionAllocator::FreeRegion(Region *region, size_t cachedSize)
764514f5e3Sopenharmony_ci{
774514f5e3Sopenharmony_ci    auto size = region->GetCapacity();
784514f5e3Sopenharmony_ci    bool isRegular = !region->InHugeObjectSpace() && !region->InHugeMachineCodeSpace() &&
794514f5e3Sopenharmony_ci        !region->InSharedHugeObjectSpace();
804514f5e3Sopenharmony_ci    auto allocateBase = region->GetAllocateBase();
814514f5e3Sopenharmony_ci
824514f5e3Sopenharmony_ci    DecreaseAnnoMemoryUsage(size);
834514f5e3Sopenharmony_ci    region->Invalidate();
844514f5e3Sopenharmony_ci    region->ClearMembers();
854514f5e3Sopenharmony_ci#if ECMASCRIPT_ENABLE_ZAP_MEM
864514f5e3Sopenharmony_ci    if (memset_s(ToVoidPtr(allocateBase), size, INVALID_VALUE, size) != EOK) { // LOCV_EXCL_BR_LINE
874514f5e3Sopenharmony_ci        LOG_FULL(FATAL) << "memset_s failed";
884514f5e3Sopenharmony_ci        UNREACHABLE();
894514f5e3Sopenharmony_ci    }
904514f5e3Sopenharmony_ci#endif
914514f5e3Sopenharmony_ci    MemMapAllocator::GetInstance()->CacheOrFree(ToVoidPtr(allocateBase),
924514f5e3Sopenharmony_ci                                                size, isRegular, cachedSize);
934514f5e3Sopenharmony_ci}
944514f5e3Sopenharmony_ci}  // namespace panda::ecmascript
95