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/os.h"
19 
20 #if ECMASCRIPT_ENABLE_ZAP_MEM
21 #include "securec.h"
22 #endif
23 namespace panda::ecmascript {
AllocateArea(size_t capacity)24 Area *NativeAreaAllocator::AllocateArea(size_t capacity)
25 {
26     size_t headerSize = sizeof(Area);
27     if (capacity < headerSize) { // LOCV_EXCL_BR_LINE
28         LOG_ECMA_MEM(FATAL) << "capacity must have a size not less than sizeof Area.";
29         UNREACHABLE();
30     }
31     if (cachedArea_ != nullptr && capacity <= cachedArea_->GetSize()) {
32         auto result = cachedArea_;
33         cachedArea_ = nullptr;
34         return result;
35     }
36     // NOLINTNEXTLINE(cppcoreguidelines-no-malloc)
37     void *mem = malloc(capacity);
38     if (mem == nullptr) { // LOCV_EXCL_BR_LINE
39         LOG_ECMA_MEM(FATAL) << "malloc failed, current alloc size = " << capacity
40                             << ", total allocated size = " << nativeMemoryUsage_.load(std::memory_order_relaxed);
41         UNREACHABLE();
42     }
43 #if ECMASCRIPT_ENABLE_ZAP_MEM
44     if (memset_s(mem, capacity, 0, capacity) != EOK) { // LOCV_EXCL_BR_LINE
45         LOG_FULL(FATAL) << "memset_s failed";
46         UNREACHABLE();
47     }
48 #endif
49     IncreaseNativeMemoryUsage(capacity);
50     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
51     uintptr_t begin = reinterpret_cast<uintptr_t>(mem) + headerSize;
52     capacity -= headerSize;
53     return new (mem) Area(begin, capacity);
54 }
55 
FreeArea(Area *area)56 void NativeAreaAllocator::FreeArea(Area *area)
57 {
58     if (area == nullptr) {
59         return;
60     }
61     if (cachedArea_ == nullptr && area->GetSize() <= MAX_CACHED_CHUNK_AREA_SIZE) {
62         cachedArea_ = area;
63         return;
64     }
65     auto size = area->GetSize() + sizeof(Area);
66     DecreaseNativeMemoryUsage(size);
67 #if ECMASCRIPT_ENABLE_ZAP_MEM
68     if (memset_s(area, size, INVALID_VALUE, size) != EOK) { // LOCV_EXCL_BR_LINE
69         LOG_FULL(FATAL) << "memset_s failed";
70         UNREACHABLE();
71     }
72 #endif
73     // NOLINTNEXTLINE(cppcoreguidelines-no-malloc)
74     free(reinterpret_cast<std::byte *>(area));
75 }
76 
Free(void *mem, size_t size)77 void NativeAreaAllocator::Free(void *mem, size_t size)
78 {
79     if (mem == nullptr) {
80         return;
81     }
82     DecreaseNativeMemoryUsage(size);
83 #if ECMASCRIPT_ENABLE_ZAP_MEM
84     if (memset_s(mem, size, INVALID_VALUE, size) != EOK) { // LOCV_EXCL_BR_LINE
85         LOG_FULL(FATAL) << "memset_s failed";
86         UNREACHABLE();
87     }
88 #endif
89     // NOLINTNEXTLINE(cppcoreguidelines-no-malloc)
90     free(mem);
91 }
92 
AllocateBuffer(size_t size)93 void *NativeAreaAllocator::AllocateBuffer(size_t size)
94 {
95     if (size == 0) { // LOCV_EXCL_BR_LINE
96         LOG_ECMA_MEM(FATAL) << "size must have a size bigger than 0";
97         UNREACHABLE();
98     }
99     // NOLINTNEXTLINE(cppcoreguidelines-no-malloc)
100     void *ptr = malloc(size);
101     if (ptr == nullptr) { // LOCV_EXCL_BR_LINE
102         LOG_ECMA_MEM(FATAL) << "malloc failed, current alloc size = " << size
103                             << ", total allocated size = " << nativeMemoryUsage_.load(std::memory_order_relaxed);
104         UNREACHABLE();
105     }
106 #if ECMASCRIPT_ENABLE_ZAP_MEM
107     if (memset_s(ptr, size, INVALID_VALUE, size) != EOK) { // LOCV_EXCL_BR_LINE
108         LOG_FULL(FATAL) << "memset_s failed";
109         UNREACHABLE();
110     }
111 #endif
112     IncreaseNativeMemoryUsage(MallocUsableSize(ptr));
113     return ptr;
114 }
115 
FreeBuffer(void *mem)116 void NativeAreaAllocator::FreeBuffer(void *mem)
117 {
118     if (mem == nullptr) {
119         return;
120     }
121     size_t size = MallocUsableSize(mem);
122     DecreaseNativeMemoryUsage(size);
123 
124 #if ECMASCRIPT_ENABLE_ZAP_MEM
125     if (memset_s(mem, size, INVALID_VALUE, size) != EOK) { // LOCV_EXCL_BR_LINE
126         LOG_FULL(FATAL) << "memset_s failed";
127         UNREACHABLE();
128     }
129 #endif
130     // NOLINTNEXTLINE(cppcoreguidelines-no-malloc)
131     free(mem);
132 }
133 
FreeBufferFunc([[maybe_unused]] void *env, void *buffer, void *data)134 void NativeAreaAllocator::FreeBufferFunc([[maybe_unused]] void *env, void *buffer, void *data)
135 {
136     if (buffer == nullptr || data == nullptr) {
137         return;
138     }
139     NativeAreaAllocator* allocator = reinterpret_cast<NativeAreaAllocator*>(data);
140     allocator->FreeBuffer(buffer);
141 }
142 }  // namespace panda::ecmascript
143