• 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.h"
17 
18 #include "ecmascript/jspandafile/program_object.h"
19 
20 namespace panda::ecmascript {
21 namespace {
22 const CString OHOS_PKG_ABC_PATH_ROOT = "/ets/";  // abc file always under /ets/ dir in HAP/HSP
23 }  // namespace
24 bool JSPandaFile::loadedFirstPandaFile = false;
JSPandaFile(const panda_file::File * pf,const CString & descriptor)25 JSPandaFile::JSPandaFile(const panda_file::File *pf, const CString &descriptor)
26     : pf_(pf), desc_(descriptor)
27 {
28     ASSERT(pf_ != nullptr);
29     CheckIsBundlePack();
30     if (isBundlePack_) {
31         InitializeUnMergedPF();
32     } else {
33         InitializeMergedPF();
34     }
35     checksum_ = pf->GetHeader()->checksum;
36     isNewVersion_ = pf_->GetHeader()->version > OLD_VERSION;
37     if (!loadedFirstPandaFile && !isBundlePack_) {
38         // Tag the first merged abc to use constant string. The lifetime of this first panda file is the same
39         // as the vm. And make sure the first pandafile is the same at the compile time and runtime.
40         isFirstPandafile_ = false;
41         loadedFirstPandaFile = true;
42     }
43 }
44 
CheckIsBundlePack()45 void JSPandaFile::CheckIsBundlePack()
46 {
47     Span<const uint32_t> classIndexes = pf_->GetClasses();
48     for (const uint32_t index : classIndexes) {
49         panda_file::File::EntityId classId(index);
50         if (pf_->IsExternal(classId)) {
51             continue;
52         }
53         panda_file::ClassDataAccessor cda(*pf_, classId);
54         cda.EnumerateFields([&](panda_file::FieldDataAccessor &fieldAccessor) -> void {
55             panda_file::File::EntityId fieldNameId = fieldAccessor.GetNameId();
56             panda_file::File::StringData sd = GetStringData(fieldNameId);
57             const char *fieldName = utf::Mutf8AsCString(sd.data);
58             if (std::strcmp(IS_COMMON_JS, fieldName) == 0 || std::strcmp(MODULE_RECORD_IDX, fieldName) == 0) {
59                 isBundlePack_ = false;
60             }
61         });
62         if (!isBundlePack_) {
63             return;
64         }
65     }
66 }
67 
CheckIsRecordWithBundleName(const CString & entry)68 void JSPandaFile::CheckIsRecordWithBundleName(const CString &entry)
69 {
70     size_t pos = entry.find('/');
71     if (pos == CString::npos) {
72         LOG_FULL(FATAL) << "CheckIsRecordWithBundleName Invalid parameter entry";
73     }
74 
75     CString bundleName = entry.substr(0, pos);
76     size_t bundleNameLen = bundleName.length();
77     for (auto info : jsRecordInfo_) {
78         if (info.first.find(PACKAGE_PATH_SEGMENT) != CString::npos ||
79             info.first.find(NPM_PATH_SEGMENT) != CString::npos) {
80             continue;
81         }
82         CString recordName = info.first;
83         // Confirm whether the current record is new or old by judging whether the recordName has a bundleName
84         if (!(recordName.length() > bundleNameLen && (recordName.compare(0, bundleNameLen, bundleName) == 0))) {
85             isRecordWithBundleName_ = false;
86         }
87         return;
88     }
89 }
90 
~JSPandaFile()91 JSPandaFile::~JSPandaFile()
92 {
93     if (pf_ != nullptr) {
94         delete pf_;
95         pf_ = nullptr;
96     }
97 
98     constpoolMap_.clear();
99     for (auto& each : jsRecordInfo_) {
100         delete each.second;
101     }
102     jsRecordInfo_.clear();
103     methodLiteralMap_.clear();
104     ClearNameMap();
105     if (methodLiterals_ != nullptr) {
106         JSPandaFileManager::FreeBuffer(methodLiterals_);
107         methodLiterals_ = nullptr;
108     }
109 }
110 
GetOrInsertConstantPool(ConstPoolType type,uint32_t offset,const CUnorderedMap<uint32_t,uint64_t> * constpoolMap)111 uint32_t JSPandaFile::GetOrInsertConstantPool(ConstPoolType type, uint32_t offset,
112                                               const CUnorderedMap<uint32_t, uint64_t> *constpoolMap)
113 {
114     CUnorderedMap<uint32_t, uint64_t> *map = nullptr;
115     if (constpoolMap != nullptr && !IsBundlePack()) {
116         map = const_cast<CUnorderedMap<uint32_t, uint64_t> *>(constpoolMap);
117     } else {
118         map = &constpoolMap_;
119     }
120     auto it = map->find(offset);
121     if (it != map->cend()) {
122         ConstPoolValue value(it->second);
123         return value.GetConstpoolIndex();
124     }
125     ASSERT(constpoolIndex_ != UINT32_MAX);
126     uint32_t index = constpoolIndex_++;
127     ConstPoolValue value(type, index);
128     map->emplace(offset, value.GetValue());
129     return index;
130 }
131 
InitializeUnMergedPF()132 void JSPandaFile::InitializeUnMergedPF()
133 {
134     Span<const uint32_t> classIndexes = pf_->GetClasses();
135     numClasses_ = classIndexes.size();
136     JSRecordInfo* info = new JSRecordInfo();
137     for (const uint32_t index : classIndexes) {
138         panda_file::File::EntityId classId(index);
139         if (pf_->IsExternal(classId)) {
140             continue;
141         }
142         panda_file::ClassDataAccessor cda(*pf_, classId);
143         numMethods_ += cda.GetMethodsNumber();
144         const char *desc = utf::Mutf8AsCString(cda.GetDescriptor());
145         if (info->moduleRecordIdx == -1 && std::strcmp(MODULE_CLASS, desc) == 0) {
146             cda.EnumerateFields([&](panda_file::FieldDataAccessor &fieldAccessor) -> void {
147                 panda_file::File::EntityId fieldNameId = fieldAccessor.GetNameId();
148                 panda_file::File::StringData sd = GetStringData(fieldNameId);
149                 CString fieldName = utf::Mutf8AsCString(sd.data);
150                 if (fieldName != desc_) {
151                     info->moduleRecordIdx = fieldAccessor.GetValue<int32_t>().value();
152                     info->classId = index;
153                     return;
154                 }
155             });
156         }
157         if (!info->isCjs && std::strcmp(COMMONJS_CLASS, desc) == 0) {
158             info->classId = index;
159             info->isCjs = true;
160         }
161         if (!info->isSharedModule && std::strcmp(IS_SHARED_MODULE, desc) == 0) {
162             info->isSharedModule = true;
163         }
164         if (!info->hasTopLevelAwait && std::strcmp(HASTLA_CLASS, desc) == 0) {
165             info->hasTopLevelAwait = true;
166         }
167     }
168     jsRecordInfo_.insert({JSPandaFile::ENTRY_FUNCTION_NAME, info});
169     methodLiterals_ =
170         static_cast<MethodLiteral *>(JSPandaFileManager::AllocateBuffer(sizeof(MethodLiteral) * numMethods_));
171     methodLiteralMap_.reserve(numMethods_);
172 }
173 
InitializeMergedPF()174 void JSPandaFile::InitializeMergedPF()
175 {
176     Span<const uint32_t> classIndexes = pf_->GetClasses();
177     numClasses_ = classIndexes.size();
178     for (const uint32_t index : classIndexes) {
179         panda_file::File::EntityId classId(index);
180         if (pf_->IsExternal(classId)) {
181             continue;
182         }
183         panda_file::ClassDataAccessor cda(*pf_, classId);
184         numMethods_ += cda.GetMethodsNumber();
185         JSRecordInfo* info = new JSRecordInfo();
186         info->classId = index;
187         bool hasCjsFiled = false;
188         bool hasJsonFiled = false;
189         CString desc = utf::Mutf8AsCString(cda.GetDescriptor());
190         CString recordName = ParseEntryPoint(desc);
191         cda.EnumerateFields([&](panda_file::FieldDataAccessor &fieldAccessor) -> void {
192             panda_file::File::EntityId fieldNameId = fieldAccessor.GetNameId();
193             panda_file::File::StringData sd = GetStringData(fieldNameId);
194             const char *fieldName = utf::Mutf8AsCString(sd.data);
195             if (std::strcmp(IS_COMMON_JS, fieldName) == 0) {
196                 hasCjsFiled = true;
197                 info->isCjs = fieldAccessor.GetValue<bool>().value();
198             } else if (std::strcmp(IS_JSON_CONTENT, fieldName) == 0) {
199                 hasJsonFiled = true;
200                 info->isJson = true;
201                 info->jsonStringId = fieldAccessor.GetValue<uint32_t>().value();
202             } else if (std::strcmp(MODULE_RECORD_IDX, fieldName) == 0) {
203                 info->moduleRecordIdx = fieldAccessor.GetValue<int32_t>().value();
204             } else if (std::strcmp(IS_SHARED_MODULE, fieldName) == 0) {
205                 info->isSharedModule = fieldAccessor.GetValue<bool>().value();
206             } else if (std::strcmp(HAS_TOP_LEVEL_AWAIT, fieldName) == 0) {
207                 info->hasTopLevelAwait = fieldAccessor.GetValue<bool>().value();
208             } else if (std::strcmp(LAZY_IMPORT, fieldName) == 0) {
209                 info->lazyImportIdx = fieldAccessor.GetValue<uint32_t>().value();
210             } else if (std::strlen(fieldName) > PACKAGE_NAME_LEN &&
211                        std::strncmp(fieldName, PACKAGE_NAME, PACKAGE_NAME_LEN) == 0) {
212                 info->npmPackageName = fieldName + PACKAGE_NAME_LEN;
213             } else {
214                 npmEntries_.emplace(recordName, fieldName);
215             }
216         });
217         if (hasCjsFiled || hasJsonFiled) {
218             jsRecordInfo_.emplace(recordName, info);
219         } else {
220             delete info;
221         }
222     }
223     methodLiterals_ =
224         static_cast<MethodLiteral *>(JSPandaFileManager::AllocateBuffer(sizeof(MethodLiteral) * numMethods_));
225     methodLiteralMap_.reserve(numMethods_);
226 }
227 
FindMethodLiteral(uint32_t offset) const228 MethodLiteral *JSPandaFile::FindMethodLiteral(uint32_t offset) const
229 {
230     auto iter = methodLiteralMap_.find(offset);
231     if (iter == methodLiteralMap_.end()) {
232         return nullptr;
233     }
234     return iter->second;
235 }
236 
IsFirstMergedAbc() const237 bool JSPandaFile::IsFirstMergedAbc() const
238 {
239     if (isFirstPandafile_ && !IsBundlePack()) {
240         return true;
241     }
242     return false;
243 }
244 
CheckAndGetRecordInfo(const CString & recordName,JSRecordInfo ** recordInfo) const245 bool JSPandaFile::CheckAndGetRecordInfo(const CString &recordName, [[maybe_unused]] JSRecordInfo **recordInfo) const
246 {
247     if (IsBundlePack()) {
248         *recordInfo = jsRecordInfo_.begin()->second;
249         return true;
250     }
251     auto info = jsRecordInfo_.find(recordName);
252     if (info != jsRecordInfo_.end()) {
253         *recordInfo = info->second;
254         return true;
255     }
256     return false;
257 }
258 
GetRecordInfo(const CString & recordName)259 const JSRecordInfo* JSPandaFile::GetRecordInfo(const CString &recordName)
260 {
261     if (IsBundlePack()) {
262         return jsRecordInfo_.begin()->second;
263     }
264     auto info = jsRecordInfo_.find(recordName);
265     if (info != jsRecordInfo_.end()) {
266         return info->second;
267     }
268     LOG_FULL(FATAL) << "Get record info failed";
269     UNREACHABLE();
270 }
271 
GetEntryPoint(const CString & recordName) const272 CString JSPandaFile::GetEntryPoint(const CString &recordName) const
273 {
274     CString entryPoint;
275     if (FindOhmUrlInPF(recordName, entryPoint) && HasRecord(entryPoint)) {
276         return entryPoint;
277     }
278     return CString();
279 }
280 
GetRecordName(const CString & entryPoint) const281 CString JSPandaFile::GetRecordName(const CString &entryPoint) const
282 {
283     if (entryPoint.empty() || entryPoint == JSPandaFile::ENTRY_FUNCTION_NAME) {
284         return GetJSPandaFileDesc();
285     }
286     return entryPoint;
287 }
288 
FindOhmUrlInPF(const CString & recordName,CString & entryPoint) const289 bool JSPandaFile::FindOhmUrlInPF(const CString &recordName, CString &entryPoint) const
290 {
291     auto info = npmEntries_.find(recordName);
292     if (info != npmEntries_.end()) {
293         entryPoint = info->second;
294         return true;
295     }
296     return false;
297 }
298 
GetFunctionKind(panda_file::FunctionKind funcKind)299 FunctionKind JSPandaFile::GetFunctionKind(panda_file::FunctionKind funcKind)
300 {
301     FunctionKind kind;
302     if ((static_cast<uint32_t>(funcKind) & SENDABLE_FUNCTION_MASK) != 0) {
303         funcKind = static_cast<panda_file::FunctionKind>(static_cast<uint32_t>(funcKind) & (~SENDABLE_FUNCTION_MASK));
304     }
305     switch (funcKind) {
306         case panda_file::FunctionKind::NONE:
307             kind = FunctionKind::NONE_FUNCTION;
308             break;
309         case panda_file::FunctionKind::FUNCTION:
310             kind = FunctionKind::BASE_CONSTRUCTOR;
311             break;
312         case panda_file::FunctionKind::NC_FUNCTION:
313             kind = FunctionKind::ARROW_FUNCTION;
314             break;
315         case panda_file::FunctionKind::GENERATOR_FUNCTION:
316             kind = FunctionKind::GENERATOR_FUNCTION;
317             break;
318         case panda_file::FunctionKind::ASYNC_FUNCTION:
319             kind = FunctionKind::ASYNC_FUNCTION;
320             break;
321         case panda_file::FunctionKind::ASYNC_GENERATOR_FUNCTION:
322             kind = FunctionKind::ASYNC_GENERATOR_FUNCTION;
323             break;
324         case panda_file::FunctionKind::ASYNC_NC_FUNCTION:
325             kind = FunctionKind::ASYNC_ARROW_FUNCTION;
326             break;
327         case panda_file::FunctionKind::CONCURRENT_FUNCTION:
328             kind = FunctionKind::CONCURRENT_FUNCTION;
329             break;
330         default:
331             LOG_ECMA(FATAL) << "this branch is unreachable";
332             UNREACHABLE();
333     }
334     return kind;
335 }
336 
GetFunctionKind(ConstPoolType type)337 FunctionKind JSPandaFile::GetFunctionKind(ConstPoolType type)
338 {
339     FunctionKind kind;
340     switch (type) {
341         case ConstPoolType::BASE_FUNCTION:
342             kind = FunctionKind::BASE_CONSTRUCTOR;
343             break;
344         case ConstPoolType::NC_FUNCTION:
345             kind = FunctionKind::ARROW_FUNCTION;
346             break;
347         case ConstPoolType::GENERATOR_FUNCTION:
348             kind = FunctionKind::GENERATOR_FUNCTION;
349             break;
350         case ConstPoolType::ASYNC_FUNCTION:
351             kind = FunctionKind::ASYNC_FUNCTION;
352             break;
353         case ConstPoolType::CLASS_FUNCTION:
354             kind = FunctionKind::CLASS_CONSTRUCTOR;
355             break;
356         case ConstPoolType::METHOD:
357             kind = FunctionKind::NORMAL_FUNCTION;
358             break;
359         case ConstPoolType::ASYNC_GENERATOR_FUNCTION:
360             kind = FunctionKind::ASYNC_GENERATOR_FUNCTION;
361             break;
362         default:
363             LOG_ECMA(FATAL) << "this branch is unreachable";
364             UNREACHABLE();
365     }
366     return kind;
367 }
368 
369 /*
370  handle desc like: case1: /data/storage/el1/bundle/entry/ets/modules.abc -> entry/ets/modules.abc
371  case2: /data/storage/el1/bundle/entry/ets/widgets.abc -> entry/ets/widgets.abc
372  case3: /data/app/el1/bundle/public/com.xx.xx/entry/ets/modules.abc -> entry/ets/modules.abc
373  case4: /data/app/el1/bundle/public/com.xx.xx/entry/ets/widgets.abc -> entry/ets/widgets.abc
374 */
GetNormalizedFileDesc(const CString & desc)375 CString JSPandaFile::GetNormalizedFileDesc(const CString &desc)
376 {
377     auto etsTokenPos = desc.rfind(OHOS_PKG_ABC_PATH_ROOT);
378     if (etsTokenPos == std::string::npos) {
379         // file not in OHOS package.
380         return desc;
381     }
382     auto ohosModulePos = desc.rfind('/', etsTokenPos - 1);
383     if (ohosModulePos == std::string::npos) {
384         LOG_ECMA(ERROR) << "Get abcPath from desc failed. desc: " << desc;
385         return desc;
386     }
387     // substring likes {ohosModuleName}/ets/modules.abc or {ohosModuleName}/ets/widgets.abc
388     return desc.substr(ohosModulePos + 1);
389 }
390 
GetNormalizedFileDesc() const391 CString JSPandaFile::GetNormalizedFileDesc() const
392 {
393     return GetNormalizedFileDesc(desc_);
394 }
395 
GetMethodName(EntityId methodId)396 std::pair<std::string_view, bool> JSPandaFile::GetMethodName(EntityId methodId)
397 {
398     LockHolder lock(methodNameMapMutex_);
399     uint32_t id = methodId.GetOffset();
400     auto iter = methodNameMap_.find(id);
401     if (iter != methodNameMap_.end()) {
402         panda_file::StringData sd = iter->second;
403         return {std::string_view(utf::Mutf8AsCString(sd.data), sd.utf16_length), sd.is_ascii};
404     }
405 
406     panda_file::MethodDataAccessor mda(*pf_, methodId);
407     auto sd = GetStringData(mda.GetNameId());
408     methodNameMap_.emplace(id, sd);
409     return {std::string_view(utf::Mutf8AsCString(sd.data), sd.utf16_length), sd.is_ascii};
410 }
411 
GetCpuProfilerMethodName(EntityId methodId) const412 std::pair<std::string_view, bool> JSPandaFile::GetCpuProfilerMethodName(EntityId methodId) const
413 {
414     panda_file::MethodDataAccessor mda(*pf_, methodId);
415     auto sd = GetStringData(mda.GetNameId());
416     std::string_view strView(utf::Mutf8AsCString(sd.data), sd.utf16_length);
417     return {strView, sd.is_ascii};
418 }
419 
GetRecordName(EntityId methodId)420 CString JSPandaFile::GetRecordName(EntityId methodId)
421 {
422     LockHolder lock(recordNameMapMutex_);
423     uint32_t id = methodId.GetOffset();
424     auto iter = recordNameMap_.find(id);
425     if (iter != recordNameMap_.end()) {
426         return iter->second;
427     }
428 
429     panda_file::MethodDataAccessor mda(*pf_, methodId);
430     panda_file::ClassDataAccessor cda(*pf_, mda.GetClassId());
431     CString desc = utf::Mutf8AsCString(cda.GetDescriptor());
432     auto name =  JSPandaFile::ParseEntryPoint(desc);
433     recordNameMap_.emplace(id, name);
434     return name;
435 }
436 
GetRecordNameWithBundlePack(EntityId methodIdx)437 CString JSPandaFile::GetRecordNameWithBundlePack(EntityId methodIdx)
438 {
439     CString recordName = IsBundlePack() ? ENTRY_FUNCTION_NAME : GetRecordName(methodIdx);
440     ASSERT(HasRecord(recordName));
441     return recordName;
442 }
443 
444 
ClearNameMap()445 void JSPandaFile::ClearNameMap()
446 {
447     {
448         LockHolder lock(methodNameMapMutex_);
449         methodNameMap_.clear();
450     }
451     {
452         LockHolder lock(recordNameMapMutex_);
453         recordNameMap_.clear();
454     }
455 }
456 
GetClassAndMethodIndex(size_t * methodIdx)457 size_t JSPandaFile::GetClassAndMethodIndex(size_t *methodIdx)
458 {
459     LockHolder lock(classIndexMutex_);
460     size_t result = 0;
461     Span<const uint32_t> classIndexes = GetClasses();
462     uint32_t index = 0;
463     do {
464         result = classIndex_++;
465         if (result >= numClasses_) {
466             return result;
467         }
468         index = classIndexes[result];
469     } while (IsExternal(panda_file::File::EntityId(index)));
470 
471     *methodIdx = methodIndex_;
472     panda_file::File::EntityId classId(classIndexes[result]);
473     panda_file::ClassDataAccessor cda(*pf_, classId);
474     methodIndex_ += cda.GetMethodsNumber();
475     return result;
476 }
477 
Run(uint32_t threadIndex)478 bool JSPandaFile::TranslateClassesTask::Run([[maybe_unused]] uint32_t threadIndex)
479 {
480     ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "TranslateClassesTask::Run");
481     jsPandaFile_->TranslateClass(thread_, *methodNamePtr_);
482     jsPandaFile_->ReduceTaskCount();
483     return true;
484 }
485 
TranslateClass(JSThread * thread,const CString & methodName)486 void JSPandaFile::TranslateClass(JSThread *thread, const CString &methodName)
487 {
488     size_t methodIdx = 0;
489     size_t classIdx = GetClassAndMethodIndex(&methodIdx);
490     while (classIdx < numClasses_) {
491         PandaFileTranslator::TranslateClass(thread, this, methodName, methodIdx, classIdx);
492         classIdx = GetClassAndMethodIndex(&methodIdx);
493     }
494 }
495 
PostInitializeMethodTask(JSThread * thread,const std::shared_ptr<CString> & methodNamePtr)496 void JSPandaFile::PostInitializeMethodTask(JSThread *thread, const std::shared_ptr<CString> &methodNamePtr)
497 {
498     IncreaseTaskCount();
499     Taskpool::GetCurrentTaskpool()->PostTask(
500         std::make_unique<TranslateClassesTask>(thread->GetThreadId(), thread, this, methodNamePtr));
501 }
502 
IncreaseTaskCount()503 void JSPandaFile::IncreaseTaskCount()
504 {
505     LockHolder holder(waitTranslateClassFinishedMutex_);
506     runningTaskCount_++;
507 }
508 
WaitTranslateClassTaskFinished()509 void JSPandaFile::WaitTranslateClassTaskFinished()
510 {
511     LockHolder holder(waitTranslateClassFinishedMutex_);
512     while (runningTaskCount_ > 0) {
513         waitTranslateClassFinishedCV_.Wait(&waitTranslateClassFinishedMutex_);
514     }
515 }
516 
ReduceTaskCount()517 void JSPandaFile::ReduceTaskCount()
518 {
519     LockHolder holder(waitTranslateClassFinishedMutex_);
520     runningTaskCount_--;
521     if (runningTaskCount_ == 0) {
522         waitTranslateClassFinishedCV_.SignalAll();
523     }
524 }
525 
SetAllMethodLiteralToMap()526 void JSPandaFile::SetAllMethodLiteralToMap()
527 {
528     // async to optimize SetAllMethodLiteralToMap later
529     MethodLiteral *methodLiterals = GetMethodLiterals();
530     size_t methodIdx = 0;
531     while (methodIdx < numMethods_) {
532         MethodLiteral *methodLiteral = methodLiterals + (methodIdx++);
533         SetMethodLiteralToMap(methodLiteral);
534     }
535 }
536 
TranslateClasses(JSThread * thread,const CString & methodName)537 void JSPandaFile::TranslateClasses(JSThread *thread, const CString &methodName)
538 {
539     const std::shared_ptr<CString> methodNamePtr = std::make_shared<CString>(methodName);
540     for (uint32_t i = 0; i < Taskpool::GetCurrentTaskpool()->GetTotalThreadNum(); i++) {
541         PostInitializeMethodTask(thread, methodNamePtr);
542     }
543     TranslateClass(thread, methodName);
544     WaitTranslateClassTaskFinished();
545     SetAllMethodLiteralToMap();
546 }
547 }  // namespace panda::ecmascript
548