1 /*
2 * Copyright (c) 2021 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/native_area_allocator.h"
17
18 #include "ecmascript/platform/map.h"
19 #include "ecmascript/platform/os.h"
20
21 #if ECMASCRIPT_ENABLE_ZAP_MEM
22 #include "securec.h"
23 #endif
24 namespace panda::ecmascript {
AllocateArea(size_t capacity)25 Area *NativeAreaAllocator::AllocateArea(size_t capacity)
26 {
27 size_t headerSize = sizeof(Area);
28 if (capacity < headerSize) { // LOCV_EXCL_BR_LINE
29 LOG_ECMA_MEM(FATAL) << "capacity must have a size not less than sizeof Area.";
30 UNREACHABLE();
31 }
32 if (cachedArea_ != nullptr && capacity <= cachedArea_->GetSize()) {
33 auto result = cachedArea_;
34 cachedArea_ = nullptr;
35 return result;
36 }
37 // NOLINTNEXTLINE(cppcoreguidelines-no-malloc)
38 void *mem = malloc(capacity);
39 if (mem == nullptr) { // LOCV_EXCL_BR_LINE
40 LOG_ECMA_MEM(FATAL) << "malloc failed, current alloc size = " << capacity
41 << ", total allocated size = " << nativeMemoryUsage_.load(std::memory_order_relaxed);
42 UNREACHABLE();
43 }
44 #if ECMASCRIPT_ENABLE_ZAP_MEM
45 if (memset_s(mem, capacity, 0, capacity) != EOK) { // LOCV_EXCL_BR_LINE
46 LOG_FULL(FATAL) << "memset_s failed";
47 UNREACHABLE();
48 }
49 #endif
50 IncreaseNativeMemoryUsage(capacity);
51 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
52 uintptr_t begin = reinterpret_cast<uintptr_t>(mem) + headerSize;
53 capacity -= headerSize;
54 return new (mem) Area(begin, capacity);
55 }
56
FreeArea(Area * area)57 void NativeAreaAllocator::FreeArea(Area *area)
58 {
59 if (area == nullptr) {
60 return;
61 }
62 if (cachedArea_ == nullptr && area->GetSize() <= MAX_CACHED_CHUNK_AREA_SIZE) {
63 cachedArea_ = area;
64 return;
65 }
66 auto size = area->GetSize() + sizeof(Area);
67 DecreaseNativeMemoryUsage(size);
68 #if ECMASCRIPT_ENABLE_ZAP_MEM
69 if (memset_s(area, size, INVALID_VALUE, size) != EOK) { // LOCV_EXCL_BR_LINE
70 LOG_FULL(FATAL) << "memset_s failed";
71 UNREACHABLE();
72 }
73 #endif
74 // NOLINTNEXTLINE(cppcoreguidelines-no-malloc)
75 free(reinterpret_cast<std::byte *>(area));
76 }
77
Free(void * mem,size_t size)78 void NativeAreaAllocator::Free(void *mem, size_t size)
79 {
80 if (mem == nullptr) {
81 return;
82 }
83 DecreaseNativeMemoryUsage(size);
84 #if ECMASCRIPT_ENABLE_ZAP_MEM
85 if (memset_s(mem, size, INVALID_VALUE, size) != EOK) { // LOCV_EXCL_BR_LINE
86 LOG_FULL(FATAL) << "memset_s failed";
87 UNREACHABLE();
88 }
89 #endif
90 // NOLINTNEXTLINE(cppcoreguidelines-no-malloc)
91 free(mem);
92 }
93
AllocateBuffer(size_t size)94 void *NativeAreaAllocator::AllocateBuffer(size_t size)
95 {
96 if (size == 0) { // LOCV_EXCL_BR_LINE
97 LOG_ECMA_MEM(FATAL) << "size must have a size bigger than 0";
98 UNREACHABLE();
99 }
100 // NOLINTNEXTLINE(cppcoreguidelines-no-malloc)
101 void *ptr = malloc(size);
102 if (ptr == nullptr) { // LOCV_EXCL_BR_LINE
103 LOG_ECMA_MEM(FATAL) << "malloc failed, current alloc size = " << size
104 << ", total allocated size = " << nativeMemoryUsage_.load(std::memory_order_relaxed);
105 UNREACHABLE();
106 }
107 #if ECMASCRIPT_ENABLE_ZAP_MEM
108 if (memset_s(ptr, size, INVALID_VALUE, size) != EOK) { // LOCV_EXCL_BR_LINE
109 LOG_FULL(FATAL) << "memset_s failed";
110 UNREACHABLE();
111 }
112 #endif
113 IncreaseNativeMemoryUsage(MallocUsableSize(ptr));
114 return ptr;
115 }
116
FreeBuffer(void * mem)117 void NativeAreaAllocator::FreeBuffer(void *mem)
118 {
119 if (mem == nullptr) {
120 return;
121 }
122 size_t size = MallocUsableSize(mem);
123 DecreaseNativeMemoryUsage(size);
124
125 #if ECMASCRIPT_ENABLE_ZAP_MEM
126 if (memset_s(mem, size, INVALID_VALUE, size) != EOK) { // LOCV_EXCL_BR_LINE
127 LOG_FULL(FATAL) << "memset_s failed";
128 UNREACHABLE();
129 }
130 #endif
131 // NOLINTNEXTLINE(cppcoreguidelines-no-malloc)
132 free(mem);
133 }
134
NativeAreaPageMap(size_t size)135 void *NativeAreaAllocator::NativeAreaPageMap(size_t size)
136 {
137 if (size == 0) { // LOCV_EXCL_BR_LINE
138 LOG_ECMA_MEM(FATAL) << "size must have a size bigger than 0";
139 UNREACHABLE();
140 }
141 // NOLINTNEXTLINE(cppcoreguidelines-no-malloc)
142 size = AlignUp(size, PageSize());
143 void *ptr = PageMap(size, PAGE_PROT_READWRITE).GetMem();
144 PageTag(ptr, size, PageTagType::METHOD_LITERAL);
145 #if ECMASCRIPT_ENABLE_ZAP_MEM
146 if (memset_s(ptr, size, INVALID_VALUE, size) != EOK) { // LOCV_EXCL_BR_LINE
147 LOG_FULL(FATAL) << "memset_s failed";
148 UNREACHABLE();
149 }
150 #endif
151 IncreaseNativeMemoryUsage(size);
152 return ptr;
153 }
154
NativeAreaPageUnmap(void * mem,size_t size)155 void NativeAreaAllocator::NativeAreaPageUnmap(void *mem, size_t size)
156 {
157 if (mem == nullptr) {
158 return;
159 }
160 size = AlignUp(size, PageSize());
161 DecreaseNativeMemoryUsage(size);
162
163 #if ECMASCRIPT_ENABLE_ZAP_MEM
164 if (memset_s(mem, size, INVALID_VALUE, size) != EOK) { // LOCV_EXCL_BR_LINE
165 LOG_FULL(FATAL) << "memset_s failed";
166 UNREACHABLE();
167 }
168 #endif
169 // NOLINTNEXTLINE(cppcoreguidelines-no-malloc)
170 PageClearTag(mem, size);
171 PageUnmap(MemMap(mem, size));
172 }
173
FreeBufferFunc(void * env,void * buffer,void * data)174 void NativeAreaAllocator::FreeBufferFunc([[maybe_unused]] void *env, void *buffer, void *data)
175 {
176 if (buffer == nullptr || data == nullptr) {
177 return;
178 }
179 NativeAreaAllocator* allocator = reinterpret_cast<NativeAreaAllocator*>(data);
180 allocator->FreeBuffer(buffer);
181 }
182 } // namespace panda::ecmascript
183