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/mem_map_allocator.h"
17 #include "ecmascript/platform/map.h"
18 #include "ecmascript/platform/os.h"
19
20 namespace panda::ecmascript {
GetInstance()21 MemMapAllocator *MemMapAllocator::GetInstance()
22 {
23 static MemMapAllocator *vmAllocator_ = new MemMapAllocator();
24 return vmAllocator_;
25 }
26
Allocate(size_t size,size_t alignment,bool regular,bool isMachineCode)27 MemMap MemMapAllocator::Allocate(size_t size, size_t alignment, bool regular, bool isMachineCode)
28 {
29 if (UNLIKELY(memMapTotalSize_ + size > capacity_)) {
30 LOG_GC(ERROR) << "memory map overflow";
31 return MemMap();
32 }
33
34 MemMap mem;
35 if (regular) {
36 mem = memMapPool_.GetMemFromCache(size);
37 if (mem.GetMem() != nullptr) {
38 memMapTotalSize_ += size;
39 int prot = isMachineCode ? PAGE_PROT_EXEC_READ : PAGE_PROT_READWRITE;
40 PageTagType type = isMachineCode ? PageTagType::MACHINE_CODE : PageTagType::HEAP;
41 PageProtect(mem.GetMem(), mem.GetSize(), prot);
42 PageTag(mem.GetMem(), size, type);
43 return mem;
44 }
45 mem = PageMap(REGULAR_REGION_MMAP_SIZE, PAGE_PROT_NONE, alignment);
46 memMapPool_.InsertMemMap(mem);
47 mem = memMapPool_.SplitMemFromCache(mem);
48 } else {
49 mem = memMapFreeList_.GetMemFromList(size);
50 }
51 if (mem.GetMem() != nullptr) {
52 int prot = isMachineCode ? PAGE_PROT_EXEC_READ : PAGE_PROT_READWRITE;
53 PageTagType type = isMachineCode ? PageTagType::MACHINE_CODE : PageTagType::HEAP;
54 PageProtect(mem.GetMem(), mem.GetSize(), prot);
55 PageTag(mem.GetMem(), mem.GetSize(), type);
56 memMapTotalSize_ += mem.GetSize();
57 }
58 return mem;
59 }
60
Free(void * mem,size_t size,bool isRegular)61 void MemMapAllocator::Free(void *mem, size_t size, bool isRegular)
62 {
63 memMapTotalSize_ -= size;
64 PageTag(mem, size, PageTagType::MEMPOOL_CACHE);
65 PageProtect(mem, size, PAGE_PROT_NONE);
66 PageRelease(mem, size);
67 if (isRegular) {
68 memMapPool_.AddMemToCache(mem, size);
69 } else {
70 memMapFreeList_.AddMemToList(MemMap(mem, size));
71 }
72 }
73
AdapterSuitablePoolCapacity()74 void MemMapAllocator::AdapterSuitablePoolCapacity()
75 {
76 size_t physicalSize = PhysicalSize();
77 capacity_ = std::max<size_t>(physicalSize / PHY_SIZE_MULTIPLE, MIN_MEM_POOL_CAPACITY);
78 if (capacity_ > LARGE_POOL_SIZE) {
79 capacity_ = std::max<size_t>(capacity_, STANDARD_POOL_SIZE);
80 } else if (capacity_ >= MEDIUM_POOL_SIZE) {
81 capacity_ = std::min<size_t>(capacity_, STANDARD_POOL_SIZE);
82 } else if (capacity_ >= LOW_POOL_SIZE) {
83 capacity_ = std::max<size_t>(capacity_, 128_MB);
84 }
85 LOG_GC(INFO) << "Ark Auto adapter memory pool capacity:" << capacity_;
86 }
87 } // namespace panda::ecmascript
88