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/shared_mm/shared_mm.h"
17 namespace panda::ecmascript {
18 static constexpr size_t MALLOC_SIZE_LIMIT = 2147483648; // Max internal memory used by the VM declared in options
19
~JSSharedMemoryManager()20 JSSharedMemoryManager::~JSSharedMemoryManager()
21 {
22 LockHolder lock(jsSharedMemoryLock_);
23 auto iter = loadedJSSharedMemory_.begin();
24 while (iter != loadedJSSharedMemory_.end()) {
25 const void *pointer = ToVoidPtr(iter->first);
26 FreeBuffer(const_cast<void *>(pointer));
27 iter = loadedJSSharedMemory_.erase(iter);
28 }
29 }
30
CreateOrLoad(void ** pointer,size_t size)31 bool JSSharedMemoryManager::CreateOrLoad(void **pointer, size_t size)
32 {
33 if (*pointer != nullptr) {
34 if (loadedJSSharedMemory_.find((uint64_t)*pointer) != loadedJSSharedMemory_.end()) {
35 IncreaseRefSharedMemory(*pointer);
36 }
37 return false;
38 }
39 *pointer = AllocateBuffer(size);
40 InsertSharedMemory(*pointer);
41 return true;
42 }
43
InsertSharedMemory(const void * pointer)44 void JSSharedMemoryManager::InsertSharedMemory(const void *pointer)
45 {
46 LockHolder lock(jsSharedMemoryLock_);
47 if (loadedJSSharedMemory_.find((uint64_t)pointer) == loadedJSSharedMemory_.end()) {
48 loadedJSSharedMemory_[(uint64_t)pointer] = 1;
49 }
50 }
51
IncreaseRefSharedMemory(const void * pointer)52 void JSSharedMemoryManager::IncreaseRefSharedMemory(const void *pointer)
53 {
54 LockHolder lock(jsSharedMemoryLock_);
55 if (loadedJSSharedMemory_.find((uint64_t)pointer) != loadedJSSharedMemory_.end()) {
56 loadedJSSharedMemory_[(uint64_t)pointer]++;
57 }
58 }
59
DecreaseRefSharedMemory(const void * pointer)60 void JSSharedMemoryManager::DecreaseRefSharedMemory(const void *pointer)
61 {
62 LockHolder lock(jsSharedMemoryLock_);
63 auto iter = loadedJSSharedMemory_.find((uint64_t)pointer);
64 if (iter != loadedJSSharedMemory_.end()) {
65 if (iter->second > 1) {
66 iter->second--;
67 return;
68 }
69 loadedJSSharedMemory_.erase(iter);
70 FreeBuffer(const_cast<void *>(pointer));
71 }
72 }
73
AllocateBuffer(size_t size)74 void *JSSharedMemoryManager::AllocateBuffer(size_t size)
75 {
76 if (size == 0) {
77 LOG_ECMA_MEM(FATAL) << "size must have a size bigger than 0";
78 UNREACHABLE();
79 }
80 if (size >= MALLOC_SIZE_LIMIT) {
81 LOG_ECMA_MEM(FATAL) << "size must be less than the maximum";
82 UNREACHABLE();
83 }
84 // NOLINTNEXTLINE(cppcoreguidelines-no-malloc)
85 void *ptr = malloc(size);
86 if (ptr == nullptr) {
87 LOG_ECMA_MEM(FATAL) << "malloc failed";
88 UNREACHABLE();
89 }
90 #if ECMASCRIPT_ENABLE_ZAP_MEM
91 if (memset_s(ptr, size, INVALID_VALUE, size) != EOK) {
92 LOG_ECMA_MEM(FATAL) << "memset failed";
93 UNREACHABLE();
94 }
95 #endif
96 return ptr;
97 }
98
FreeBuffer(void * mem)99 void JSSharedMemoryManager::FreeBuffer(void *mem)
100 {
101 if (mem == nullptr) {
102 return;
103 }
104 // NOLINTNEXTLINE(cppcoreguidelines-no-malloc)
105 free(mem);
106 }
107
RemoveSharedMemory(void * env,void * pointer,void * data)108 void JSSharedMemoryManager::RemoveSharedMemory([[maybe_unused]] void *env, void *pointer, void *data)
109 {
110 if (pointer == nullptr || data == nullptr) {
111 return;
112 }
113 // dec ref in menorymanager
114 JSSharedMemoryManager *jsSharedMemoryManager = static_cast<JSSharedMemoryManager *>(data);
115 jsSharedMemoryManager->DecreaseRefSharedMemory(pointer);
116 }
117 } // namespace panda::ecmascript
118