• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "ecmascript/mem/heap_region_allocator.h"
17 
18 #include "ecmascript/jit/jit.h"
19 #include "ecmascript/mem/mem_map_allocator.h"
20 
21 namespace panda::ecmascript {
22 constexpr size_t PANDA_POOL_ALIGNMENT_IN_BYTES = 256_KB;
23 
AllocateAlignedRegion(Space * space,size_t capacity,JSThread * thread,BaseHeap * heap,bool isFresh)24 Region *HeapRegionAllocator::AllocateAlignedRegion(Space *space, size_t capacity, JSThread* thread, BaseHeap *heap,
25                                                    bool isFresh)
26 {
27     if (capacity == 0) {
28         LOG_ECMA_MEM(FATAL) << "capacity must have a size bigger than 0";
29         UNREACHABLE();
30     }
31     RegionSpaceFlag flags = space->GetRegionFlag();
32     RegionTypeFlag typeFlag = isFresh ? RegionTypeFlag::FRESH : RegionTypeFlag::DEFAULT;
33     bool isRegular = (flags != RegionSpaceFlag::IN_HUGE_OBJECT_SPACE &&
34         flags != RegionSpaceFlag::IN_HUGE_MACHINE_CODE_SPACE &&
35         flags != RegionSpaceFlag::IN_SHARED_HUGE_OBJECT_SPACE);
36     bool isMachineCode = (flags == RegionSpaceFlag::IN_MACHINE_CODE_SPACE ||
37         flags == RegionSpaceFlag::IN_HUGE_MACHINE_CODE_SPACE);
38     auto tid = thread ? thread->GetThreadId() : JSThread::GetCurrentThreadId();
39     auto pool = MemMapAllocator::GetInstance()->Allocate(tid, capacity, DEFAULT_REGION_SIZE,
40                                                          ToSpaceTypeName(space->GetSpaceType()),
41                                                          isRegular, isMachineCode,
42                                                          Jit::GetInstance()->IsEnableJitFort());
43     void *mapMem = pool.GetMem();
44     if (mapMem == nullptr) {
45         if (thread != nullptr && thread->GetEcmaVM()->IsInitialized()) {
46             Heap *localHeap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
47             if (!localHeap->InGC()) {
48                 LOG_ECMA_MEM(INFO)
49                     << "HeapRegionAllocator::AllocateAlignedRegion, is inGC and not DumpHeapSnapshotBeforeOOM";
50                 localHeap->DumpHeapSnapshotBeforeOOM();
51             }
52             heap->ThrowOutOfMemoryErrorForDefault(thread, DEFAULT_REGION_SIZE,
53                 "HeapRegionAllocator::AllocateAlignedRegion", false);
54         }
55         LOG_ECMA_MEM(FATAL) << "pool is empty " << annoMemoryUsage_.load(std::memory_order_relaxed);
56         UNREACHABLE();
57     }
58 #if ECMASCRIPT_ENABLE_ZAP_MEM
59     if (memset_s(mapMem, capacity, 0, capacity) != EOK) {
60         LOG_FULL(FATAL) << "memset_s failed";
61         UNREACHABLE();
62     }
63 #endif
64     IncreaseAnnoMemoryUsage(capacity);
65 
66     uintptr_t mem = ToUintPtr(mapMem);
67     // Check that the address is 256K byte aligned
68     LOG_ECMA_IF(AlignUp(mem, PANDA_POOL_ALIGNMENT_IN_BYTES) != mem, FATAL) << "region not align by 256KB";
69     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
70     uintptr_t begin = AlignUp(mem + sizeof(Region), static_cast<size_t>(MemAlignment::MEM_ALIGN_REGION));
71     uintptr_t end = mem + capacity;
72 
73     Region *region = new (ToVoidPtr(mem)) Region(heap->GetNativeAreaAllocator(), mem, begin, end, flags, typeFlag);
74     region->Initialize();
75     std::atomic_thread_fence(std::memory_order_seq_cst);
76     return region;
77 }
78 
FreeRegion(Region * region,size_t cachedSize)79 void HeapRegionAllocator::FreeRegion(Region *region, size_t cachedSize)
80 {
81     auto size = region->GetCapacity();
82     bool isRegular = !region->InHugeObjectSpace() && !region->InHugeMachineCodeSpace() &&
83         !region->InSharedHugeObjectSpace();
84     auto allocateBase = region->GetAllocateBase();
85 
86     DecreaseAnnoMemoryUsage(size);
87     region->Invalidate();
88     region->ClearMembers();
89 #if ECMASCRIPT_ENABLE_ZAP_MEM
90     if (memset_s(ToVoidPtr(allocateBase), size, INVALID_VALUE, size) != EOK) {
91         LOG_FULL(FATAL) << "memset_s failed";
92         UNREACHABLE();
93     }
94 #endif
95     MemMapAllocator::GetInstance()->CacheOrFree(ToVoidPtr(allocateBase),
96                                                 size, isRegular, cachedSize);
97 }
98 }  // namespace panda::ecmascript
99