• 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/jspandafile/js_pandafile_manager.h"
17 #include "ecmascript/jspandafile/program_object-inl.h"
18 
19 namespace panda::ecmascript {
20 static const size_t MALLOC_SIZE_LIMIT = 2147483648; // Max internal memory used by the VM declared in options
21 
~JSPandaFileManager()22 JSPandaFileManager::~JSPandaFileManager()
23 {
24     os::memory::LockHolder lock(jsPandaFileLock_);
25     auto iter = loadedJSPandaFiles_.begin();
26     while (iter != loadedJSPandaFiles_.end()) {
27         const JSPandaFile *jsPandaFile = iter->first;
28         ReleaseJSPandaFile(jsPandaFile);
29         iter = loadedJSPandaFiles_.erase(iter);
30     }
31 }
32 
LoadPfAbc(const std::string & filename)33 const JSPandaFile *JSPandaFileManager::LoadPfAbc(const std::string &filename)
34 {
35     ECMA_BYTRACE_NAME(BYTRACE_TAG_ARK, "JSPandaFileManager::LoadJSPandaFile");
36     CString desc = ConvertToString(filename);
37     {
38         os::memory::LockHolder lock(jsPandaFileLock_);
39         const JSPandaFile *jsPandaFile = FindJSPandaFileUnlocked(desc);
40         if (jsPandaFile != nullptr) {
41             IncreaseRefJSPandaFileUnlocked(jsPandaFile);
42             return jsPandaFile;
43         }
44     }
45 
46     auto pf = panda_file::OpenPandaFileOrZip(filename, panda_file::File::READ_WRITE);
47     if (pf == nullptr) {
48         LOG_ECMA(ERROR) << "open file " << filename << " error";
49         return nullptr;
50     }
51 
52     return CreateJSPandaFile(pf.release(), desc);
53 }
54 
LoadBufferAbc(const std::string & filename,const void * buffer,size_t size)55 const JSPandaFile *JSPandaFileManager::LoadBufferAbc(const std::string &filename, const void *buffer, size_t size)
56 {
57     if (buffer == nullptr || size == 0) {
58         return nullptr;
59     }
60 
61     CString desc = ConvertToString(filename);
62     {
63         os::memory::LockHolder lock(jsPandaFileLock_);
64         const JSPandaFile *jsPandaFile = FindJSPandaFileUnlocked(desc);
65         if (jsPandaFile != nullptr) {
66             IncreaseRefJSPandaFileUnlocked(jsPandaFile);
67             return jsPandaFile;
68         }
69     }
70 
71     auto pf = panda_file::OpenPandaFileFromMemory(buffer, size);
72     if (pf == nullptr) {
73         return nullptr;
74     }
75     return CreateJSPandaFile(pf.release(), desc);
76 }
77 
GenerateProgram(EcmaVM * vm,const JSPandaFile * jsPandaFile)78 JSHandle<Program> JSPandaFileManager::GenerateProgram(EcmaVM *vm, const JSPandaFile *jsPandaFile)
79 {
80     ECMA_BYTRACE_NAME(BYTRACE_TAG_ARK, "JSPandaFileManager::GenerateProgram");
81     LOG_ECMA(INFO) << "GenerateProgram " << jsPandaFile->GetPandaFile()->GetFilename();
82     ASSERT(GetJSPandaFile(jsPandaFile->GetPandaFile()) != nullptr);
83 
84     PandaFileTranslator translator(vm, jsPandaFile);
85     auto result = translator.GenerateProgram();
86     JSThread *thread = vm->GetJSThread();
87     return JSHandle<Program>(thread, result);
88 }
89 
FindJSPandaFileUnlocked(const CString & filename)90 const JSPandaFile *JSPandaFileManager::FindJSPandaFileUnlocked(const CString &filename)
91 {
92     if (filename.empty()) {
93         return nullptr;
94     }
95     for (const auto &iter : loadedJSPandaFiles_) {
96         const JSPandaFile *pf = iter.first;
97         if (pf->GetJSPandaFileDesc() == filename) {
98             return pf;
99         }
100     }
101     return nullptr;
102 }
103 
GetJSPandaFile(const panda_file::File * pf)104 const JSPandaFile *JSPandaFileManager::GetJSPandaFile(const panda_file::File *pf)
105 {
106     os::memory::LockHolder lock(jsPandaFileLock_);
107     for (const auto &iter : loadedJSPandaFiles_) {
108         const JSPandaFile *jsPandafile = iter.first;
109         if (jsPandafile->GetPandaFile() == pf) {
110             return jsPandafile;
111         }
112     }
113     return nullptr;
114 }
115 
InsertJSPandaFile(const JSPandaFile * jsPandaFile)116 void JSPandaFileManager::InsertJSPandaFile(const JSPandaFile *jsPandaFile)
117 {
118     LOG_ECMA(INFO) << "InsertJSPandaFile " << jsPandaFile->GetPandaFile()->GetFilename();
119 
120     os::memory::LockHolder lock(jsPandaFileLock_);
121     ASSERT(loadedJSPandaFiles_.find(jsPandaFile) == loadedJSPandaFiles_.end());
122     loadedJSPandaFiles_[jsPandaFile] = 1;
123 }
124 
IncreaseRefJSPandaFileUnlocked(const JSPandaFile * jsPandaFile)125 void JSPandaFileManager::IncreaseRefJSPandaFileUnlocked(const JSPandaFile *jsPandaFile)
126 {
127     LOG_ECMA(INFO) << "IncreaseRefJSPandaFile " << jsPandaFile->GetPandaFile()->GetFilename();
128 
129     ASSERT(loadedJSPandaFiles_.find(jsPandaFile) != loadedJSPandaFiles_.end());
130     loadedJSPandaFiles_[jsPandaFile]++;
131 }
132 
DecreaseRefJSPandaFile(const JSPandaFile * jsPandaFile)133 void JSPandaFileManager::DecreaseRefJSPandaFile(const JSPandaFile *jsPandaFile)
134 {
135     LOG_ECMA(INFO) << "DecreaseRefJSPandaFile " << jsPandaFile->GetPandaFile()->GetFilename();
136 
137     os::memory::LockHolder lock(jsPandaFileLock_);
138     auto iter = loadedJSPandaFiles_.find(jsPandaFile);
139     if (iter != loadedJSPandaFiles_.end()) {
140         if (iter->second > 1) {
141             iter->second--;
142             return;
143         }
144         loadedJSPandaFiles_.erase(iter);
145     }
146     ReleaseJSPandaFile(jsPandaFile);
147 }
148 
ReleaseJSPandaFile(const JSPandaFile * jsPandaFile)149 void JSPandaFileManager::ReleaseJSPandaFile(const JSPandaFile *jsPandaFile)
150 {
151     if (jsPandaFile == nullptr) {
152         return;
153     }
154     LOG_ECMA(INFO) << "ReleaseJSPandaFile " << jsPandaFile->GetPandaFile()->GetFilename();
155     delete jsPandaFile;
156 }
157 
GetJSPtExtractor(const JSPandaFile * pf)158 tooling::JSPtExtractor *JSPandaFileManager::GetJSPtExtractor(const JSPandaFile *pf)
159 {
160     if (pf == nullptr) {
161         return nullptr;
162     }
163     return const_cast<JSPandaFile *>(pf)->GetJSPtExtractor();
164 }
165 
CreateJSPandaFile(const panda_file::File * pf,const CString & desc)166 const JSPandaFile *JSPandaFileManager::CreateJSPandaFile(const panda_file::File *pf, const CString &desc)
167 {
168     ASSERT(GetJSPandaFile(pf) == nullptr);
169 
170     JSPandaFile *newJsPandaFile = new JSPandaFile(pf, desc);
171     PandaFileTranslator::TranslateClasses(newJsPandaFile, ENTRY_FUNCTION_NAME);
172 
173     {
174         os::memory::LockHolder lock(jsPandaFileLock_);
175         const JSPandaFile *jsPandaFile = FindJSPandaFileUnlocked(desc);
176         if (jsPandaFile != nullptr) {
177             IncreaseRefJSPandaFileUnlocked(jsPandaFile);
178             ReleaseJSPandaFile(newJsPandaFile);
179             return jsPandaFile;
180         }
181         InsertJSPandaFile(newJsPandaFile);
182     }
183 
184     return newJsPandaFile;
185 }
186 
AllocateBuffer(size_t size)187 void *JSPandaFileManager::AllocateBuffer(size_t size)
188 {
189     return JSPandaFileAllocator::AllocateBuffer(size);
190 }
191 
AllocateBuffer(size_t size)192 void *JSPandaFileManager::JSPandaFileAllocator::AllocateBuffer(size_t size)
193 {
194     if (size == 0) {
195         LOG_ECMA_MEM(FATAL) << "size must have a size bigger than 0";
196         UNREACHABLE();
197     }
198     if (size >= MALLOC_SIZE_LIMIT) {
199         LOG_ECMA_MEM(FATAL) << "size must be less than the maximum";
200         UNREACHABLE();
201     }
202     // NOLINTNEXTLINE(cppcoreguidelines-no-malloc)
203     void *ptr = malloc(size);
204     if (ptr == nullptr) {
205         LOG_ECMA_MEM(FATAL) << "malloc failed";
206         UNREACHABLE();
207     }
208 #if ECMASCRIPT_ENABLE_ZAP_MEM
209     if (memset_s(ptr, size, INVALID_VALUE, size) != EOK) {
210         LOG_ECMA_MEM(FATAL) << "memset failed";
211         UNREACHABLE();
212     }
213 #endif
214     return ptr;
215 }
216 
FreeBuffer(void * mem)217 void JSPandaFileManager::FreeBuffer(void *mem)
218 {
219     JSPandaFileAllocator::FreeBuffer(mem);
220 }
221 
FreeBuffer(void * mem)222 void JSPandaFileManager::JSPandaFileAllocator::FreeBuffer(void *mem)
223 {
224     if (mem == nullptr) {
225         return;
226     }
227     // NOLINTNEXTLINE(cppcoreguidelines-no-malloc)
228     free(mem);
229 }
230 
RemoveJSPandaFile(void * pointer,void * data)231 void JSPandaFileManager::RemoveJSPandaFile(void *pointer, void *data)
232 {
233     if (pointer == nullptr || data == nullptr) {
234         return;
235     }
236     auto jsPandaFile = reinterpret_cast<JSPandaFile *>(pointer);
237     LOG_ECMA(INFO) << "RemoveJSPandaFile " << jsPandaFile->GetPandaFile()->GetFilename();
238     // dec ref in filemanager
239     JSPandaFileManager *jsPandaFileManager = static_cast<JSPandaFileManager *>(data);
240     jsPandaFileManager->DecreaseRefJSPandaFile(jsPandaFile);
241 }
242 }  // namespace panda::ecmascript
243