1 /*
2  * Copyright (c) 2021-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/literal_data_extractor.h"
17 
18 #include "ecmascript/compiler/aot_file/aot_file_manager.h"
19 #include "ecmascript/global_env.h"
20 #include "ecmascript/module/js_shared_module_manager.h"
21 #include "ecmascript/patch/quick_fix_helper.h"
22 
23 namespace panda::ecmascript {
24 using LiteralTag = panda_file::LiteralTag;
25 using StringData = panda_file::StringData;
26 using LiteralDataAccessor = panda_file::LiteralDataAccessor;
27 using LiteralValue = panda_file::LiteralDataAccessor::LiteralValue;
28 
ExtractObjectDatas(JSThread *thread, const JSPandaFile *jsPandaFile, size_t index, JSMutableHandle<TaggedArray> elements, JSMutableHandle<TaggedArray> properties, JSHandle<ConstantPool> constpool, const CString &entryPoint)29 void LiteralDataExtractor::ExtractObjectDatas(JSThread *thread, const JSPandaFile *jsPandaFile, size_t index,
30                                               JSMutableHandle<TaggedArray> elements,
31                                               JSMutableHandle<TaggedArray> properties,
32                                               JSHandle<ConstantPool> constpool,
33                                               const CString &entryPoint)
34 {
35     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
36     LiteralDataAccessor lda = jsPandaFile->GetLiteralDataAccessor();
37     uint32_t num = lda.GetLiteralValsNum(index) / 2;  // 2: half
38     elements.Update(factory->NewOldSpaceTaggedArray(num).GetTaggedValue());
39     properties.Update(factory->NewOldSpaceTaggedArray(num).GetTaggedValue());
40     uint32_t epos = 0;
41     uint32_t ppos = 0;
42     const uint8_t pairSize = 2;
43     uint32_t methodId = 0;
44     FunctionKind kind;
45     lda.EnumerateLiteralVals(
46         index, [elements, properties, &epos, &ppos, factory, thread, jsPandaFile,
47                 &methodId, &kind, &constpool, &entryPoint](const LiteralValue &value, const LiteralTag &tag) {
48         JSTaggedValue jt = JSTaggedValue::Null();
49         bool flag = false;
50         switch (tag) {
51             case LiteralTag::INTEGER: {
52                 jt = JSTaggedValue(std::get<uint32_t>(value));
53                 break;
54             }
55             case LiteralTag::DOUBLE: {
56                 jt = JSTaggedValue(std::get<double>(value));
57                 break;
58             }
59             case LiteralTag::BOOL: {
60                 jt = JSTaggedValue(std::get<bool>(value));
61                 break;
62             }
63             case LiteralTag::STRING: {
64                 StringData sd = jsPandaFile->GetStringData(EntityId(std::get<uint32_t>(value)));
65                 EcmaString *str = factory->GetRawStringFromStringTable(sd, MemSpaceType::SHARED_OLD_SPACE);
66                 jt = JSTaggedValue(str);
67                 uint32_t elementIndex = 0;
68                 if (JSTaggedValue::ToElementIndex(jt, &elementIndex) && ppos % pairSize == 0) {
69                     flag = true;
70                 }
71                 break;
72             }
73             case LiteralTag::METHOD: {
74                 methodId = std::get<uint32_t>(value);
75                 kind = FunctionKind::NORMAL_FUNCTION;
76                 break;
77             }
78             case LiteralTag::GETTER: {
79                 methodId = std::get<uint32_t>(value);
80                 kind = FunctionKind::GETTER_FUNCTION;
81                 break;
82             }
83             case LiteralTag::SETTER: {
84                 methodId = std::get<uint32_t>(value);
85                 kind = FunctionKind::SETTER_FUNCTION;
86                 break;
87             }
88             case LiteralTag::GENERATORMETHOD: {
89                 methodId = std::get<uint32_t>(value);
90                 kind = FunctionKind::GENERATOR_FUNCTION;
91                 break;
92             }
93             case LiteralTag::ASYNCGENERATORMETHOD: {
94                 methodId = std::get<uint32_t>(value);
95                 kind = FunctionKind::ASYNC_GENERATOR_FUNCTION;
96                 break;
97             }
98             case LiteralTag::METHODAFFILIATE: {
99                 uint16_t length = std::get<uint16_t>(value);
100                 JSHandle<JSFunction> jsFunc =
101                     DefineMethodInLiteral(thread, jsPandaFile, methodId, constpool, kind, length, entryPoint);
102                 jt = jsFunc.GetTaggedValue();
103                 break;
104             }
105             case LiteralTag::ACCESSOR: {
106                 JSHandle<AccessorData> accessor = factory->NewAccessorData();
107                 jt = accessor.GetTaggedValue();
108                 break;
109             }
110             case LiteralTag::NULLVALUE: {
111                 break;
112             }
113             default: {
114                 LOG_ECMA(FATAL) << "this branch is unreachable";
115                 UNREACHABLE();
116                 break;
117             }
118         }
119         if (tag != LiteralTag::METHOD && tag != LiteralTag::GETTER && tag != LiteralTag::SETTER &&
120             tag != LiteralTag::GENERATORMETHOD && tag != LiteralTag::ASYNCGENERATORMETHOD) {
121             if (epos % pairSize == 0 && !flag) {
122                 properties->Set(thread, ppos++, jt);
123             } else {
124                 elements->Set(thread, epos++, jt);
125             }
126         }
127     });
128 }
129 
GetDatasIgnoreTypeForClass(JSThread *thread, const JSPandaFile *jsPandaFile, size_t index, JSHandle<ConstantPool> constpool, const CString &entryPoint)130 JSHandle<TaggedArray> LiteralDataExtractor::GetDatasIgnoreTypeForClass(JSThread *thread,
131     const JSPandaFile *jsPandaFile, size_t index, JSHandle<ConstantPool> constpool, const CString &entryPoint)
132 {
133     LiteralDataAccessor lda = jsPandaFile->GetLiteralDataAccessor();
134     uint32_t num = lda.GetLiteralValsNum(index) / 2;  // 2: half
135     // The num is 1, indicating that the current class has no member variable.
136     if (num == 1) {
137         ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
138         return factory->EmptyArray();
139     }
140     return EnumerateLiteralVals(thread, lda, jsPandaFile, index, constpool, entryPoint);
141 }
142 
GetDatasIgnoreType(JSThread *thread, const JSPandaFile *jsPandaFile, size_t index, JSHandle<ConstantPool> constpool, const CString &entryPoint)143 JSHandle<TaggedArray> LiteralDataExtractor::GetDatasIgnoreType(JSThread *thread, const JSPandaFile *jsPandaFile,
144                                                                size_t index, JSHandle<ConstantPool> constpool,
145                                                                const CString &entryPoint)
146 {
147     LiteralDataAccessor lda = jsPandaFile->GetLiteralDataAccessor();
148     return EnumerateLiteralVals(thread, lda, jsPandaFile, index, constpool, entryPoint);
149 }
150 
EnumerateLiteralVals(JSThread *thread, LiteralDataAccessor &lda, const JSPandaFile *jsPandaFile, size_t index, JSHandle<ConstantPool> constpool, const CString &entryPoint)151 JSHandle<TaggedArray> LiteralDataExtractor::EnumerateLiteralVals(JSThread *thread, LiteralDataAccessor &lda,
152     const JSPandaFile *jsPandaFile, size_t index, JSHandle<ConstantPool> constpool, const CString &entryPoint)
153 {
154     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
155     uint32_t num = lda.GetLiteralValsNum(index) / 2;  // 2: half
156     JSHandle<TaggedArray> literals = factory->NewOldSpaceTaggedArray(num);
157     uint32_t pos = 0;
158     uint32_t methodId = 0;
159     FunctionKind kind;
160     lda.EnumerateLiteralVals(
161         index, [literals, &pos, factory, thread, jsPandaFile, &methodId, &kind, &constpool, &entryPoint]
162         (const LiteralValue &value, const LiteralTag &tag) {
163             JSTaggedValue jt = JSTaggedValue::Null();
164             switch (tag) {
165                 case LiteralTag::INTEGER: {
166                     jt = JSTaggedValue(std::get<uint32_t>(value));
167                     break;
168                 }
169                 case LiteralTag::DOUBLE: {
170                     jt = JSTaggedValue(std::get<double>(value));
171                     break;
172                 }
173                 case LiteralTag::BOOL: {
174                     jt = JSTaggedValue(std::get<bool>(value));
175                     break;
176                 }
177                 case LiteralTag::STRING: {
178                     StringData sd = jsPandaFile->GetStringData(EntityId(std::get<uint32_t>(value)));
179                     EcmaString *str = factory->GetRawStringFromStringTable(sd, MemSpaceType::SHARED_OLD_SPACE);
180                     jt = JSTaggedValue(str);
181                     break;
182                 }
183                 case LiteralTag::METHOD: {
184                     methodId = std::get<uint32_t>(value);
185                     kind = FunctionKind::NORMAL_FUNCTION;
186                     break;
187                 }
188                 case LiteralTag::GETTER: {
189                     methodId = std::get<uint32_t>(value);
190                     kind = FunctionKind::GETTER_FUNCTION;
191                     break;
192                 }
193                 case LiteralTag::SETTER: {
194                     methodId = std::get<uint32_t>(value);
195                     kind = FunctionKind::SETTER_FUNCTION;
196                     break;
197                 }
198                 case LiteralTag::GENERATORMETHOD: {
199                     methodId = std::get<uint32_t>(value);
200                     kind = FunctionKind::GENERATOR_FUNCTION;
201                     break;
202                 }
203                 case LiteralTag::ASYNCGENERATORMETHOD: {
204                     methodId = std::get<uint32_t>(value);
205                     kind = FunctionKind::ASYNC_GENERATOR_FUNCTION;
206                     break;
207                 }
208                 case LiteralTag::METHODAFFILIATE: {
209                     uint16_t length = std::get<uint16_t>(value);
210                     JSHandle<FunctionTemplate> jsFunc =
211                         DefineFunctionTemplate(thread, jsPandaFile, methodId, constpool, kind, length, entryPoint);
212                     jt = jsFunc.GetTaggedValue();
213                     break;
214                 }
215                 case LiteralTag::ACCESSOR: {
216                     JSHandle<AccessorData> accessor = factory->NewAccessorData();
217                     jt = accessor.GetTaggedValue();
218                     break;
219                 }
220                 case LiteralTag::NULLVALUE: {
221                     break;
222                 }
223                 default: {
224                     LOG_ECMA(FATAL) << "this branch is unreachable";
225                     UNREACHABLE();
226                     break;
227                 }
228             }
229             if (tag != LiteralTag::METHOD && tag != LiteralTag::GETTER && tag != LiteralTag::SETTER &&
230                 tag != LiteralTag::GENERATORMETHOD && tag != LiteralTag::ASYNCGENERATORMETHOD) {
231                 literals->Set(thread, pos++, jt);
232             } else {
233                 uint32_t oldLength = literals->GetLength();
234                 ASSERT(oldLength > 0);
235                 literals->Trim(thread, oldLength - 1);
236             }
237         });
238     return literals;
239 }
240 
DefineFunctionTemplate(JSThread *thread, const JSPandaFile *jsPandaFile, uint32_t offset, JSHandle<ConstantPool> constpool, FunctionKind kind, uint16_t length, const CString &entryPoint, bool isLoadedAOT, uint32_t entryIndex, JSHandle<JSTaggedValue> sendableEnv, ClassKind classKind)241 JSHandle<FunctionTemplate> LiteralDataExtractor::DefineFunctionTemplate(JSThread *thread,
242                                                                         const JSPandaFile *jsPandaFile,
243                                                                         uint32_t offset,
244                                                                         JSHandle<ConstantPool> constpool,
245                                                                         FunctionKind kind, uint16_t length,
246                                                                         const CString &entryPoint,
247                                                                         bool isLoadedAOT, uint32_t entryIndex,
248                                                                         JSHandle<JSTaggedValue> sendableEnv,
249                                                                         ClassKind classKind)
250 {
251     EcmaVM *vm = thread->GetEcmaVM();
252     ObjectFactory *factory = vm->GetFactory();
253 
254     // New Method
255     auto methodLiteral = jsPandaFile->FindMethodLiteral(offset);
256     CHECK_INPUT_NULLPTR(methodLiteral,
257                         "DefineFunctionTemplate:methodLiteral is nullptr, offset: " + std::to_string(offset));
258     FunctionKind literalKind = methodLiteral->GetFunctionKind();
259     if (literalKind == FunctionKind::NONE_FUNCTION || classKind == ClassKind::SENDABLE) {
260         methodLiteral->SetFunctionKind(kind);
261     } else {
262         kind = literalKind;
263     }
264     JSHandle<Method> method = factory->NewSMethod(jsPandaFile, methodLiteral, constpool, entryIndex, isLoadedAOT);
265     if (classKind == ClassKind::SENDABLE) {
266         method->SetIsSendable(true);
267     }
268 
269     // Generate Module
270     JSHandle<JSTaggedValue> module = SharedModuleManager::GetInstance()->GenerateFuncModule(thread, jsPandaFile,
271                                                                                             entryPoint, classKind);
272     if (module->IsSourceTextModule()) {
273         SourceTextModule::Cast(module->GetTaggedObject())->SetSendableEnv(thread, sendableEnv);
274     }
275 
276     // New FunctionTemplate
277     JSHandle<FunctionTemplate> funcTemp;
278     if (classKind == ClassKind::SENDABLE) {
279         funcTemp = factory->NewSFunctionTemplate(method, module, length);
280     } else {
281         funcTemp = factory->NewFunctionTemplate(method, module, length);
282     }
283     return funcTemp;
284 }
285 
CreateJSFunctionInLiteral(EcmaVM *vm, const JSHandle<Method> &method, FunctionKind kind, ClassKind classKind)286 JSHandle<JSFunction> LiteralDataExtractor::CreateJSFunctionInLiteral(EcmaVM *vm,
287                                                                      const JSHandle<Method> &method,
288                                                                      FunctionKind kind,
289                                                                      ClassKind classKind)
290 {
291     ObjectFactory *factory = vm->GetFactory();
292     JSHandle<GlobalEnv> env = vm->GetGlobalEnv();
293     JSHandle<JSFunction> jsFunc;
294     JSHandle<JSHClass> functionClass;
295     if (classKind == ClassKind::SENDABLE) {
296         if (kind == FunctionKind::NORMAL_FUNCTION ||
297             kind == FunctionKind::GETTER_FUNCTION ||
298             kind == FunctionKind::SETTER_FUNCTION) {
299             functionClass = JSHandle<JSHClass>::Cast(env->GetSFunctionClassWithoutProto());
300         } else if (kind == FunctionKind::ASYNC_FUNCTION) {
301             functionClass = JSHandle<JSHClass>::Cast(env->GetAsyncFunctionClass());
302         } else {
303             functionClass = JSHandle<JSHClass>::Cast(env->GetGeneratorFunctionClass());
304         }
305         jsFunc = factory->NewSFunctionByHClass(method, functionClass);
306     } else {
307         if (kind == FunctionKind::NORMAL_FUNCTION ||
308             kind == FunctionKind::GETTER_FUNCTION ||
309             kind == FunctionKind::SETTER_FUNCTION) {
310             functionClass = JSHandle<JSHClass>::Cast(env->GetFunctionClassWithoutProto());
311         } else if (kind == FunctionKind::ASYNC_FUNCTION) {
312             functionClass = JSHandle<JSHClass>::Cast(env->GetAsyncFunctionClass());
313         } else {
314             functionClass = JSHandle<JSHClass>::Cast(env->GetGeneratorFunctionClass());
315         }
316         jsFunc = factory->NewJSFunctionByHClass(method, functionClass, MemSpaceType::OLD_SPACE);
317     }
318     return jsFunc;
319 }
320 
DefineMethodInLiteral(JSThread *thread, const JSPandaFile *jsPandaFile, uint32_t offset, JSHandle<ConstantPool> constpool, FunctionKind kind, uint16_t length, const CString &entryPoint, bool isLoadedAOT, uint32_t entryIndex, JSHandle<JSTaggedValue> sendableEnv, ClassKind classKind)321 JSHandle<JSFunction> LiteralDataExtractor::DefineMethodInLiteral(JSThread *thread, const JSPandaFile *jsPandaFile,
322                                                                  uint32_t offset, JSHandle<ConstantPool> constpool,
323                                                                  FunctionKind kind, uint16_t length,
324                                                                  const CString &entryPoint,
325                                                                  bool isLoadedAOT, uint32_t entryIndex,
326                                                                  JSHandle<JSTaggedValue> sendableEnv,
327                                                                  ClassKind classKind)
328 {
329     EcmaVM *vm = thread->GetEcmaVM();
330     ObjectFactory *factory = vm->GetFactory();
331 
332     auto methodLiteral = jsPandaFile->FindMethodLiteral(offset);
333     CHECK_INPUT_NULLPTR(methodLiteral,
334                         "DefineMethodInLiteral:methodLiteral is nullptr, offset: " + std::to_string(offset));
335     FunctionKind literalKind = methodLiteral->GetFunctionKind();
336     if (literalKind == FunctionKind::NONE_FUNCTION || classKind == ClassKind::SENDABLE) {
337         methodLiteral->SetFunctionKind(kind);
338     } else {
339         kind = literalKind;
340     }
341     bool canFastCall = false;
342     JSHandle<Method> method =
343         factory->NewSMethod(jsPandaFile, methodLiteral, constpool, entryIndex, isLoadedAOT, &canFastCall);
344     if (classKind == ClassKind::SENDABLE) {
345         method->SetIsSendable(true);
346     }
347     JSHandle<JSHClass> functionClass;
348     JSHandle<JSFunction> jsFunc = CreateJSFunctionInLiteral(vm, method, kind, classKind);
349     JSHandle<JSTaggedValue> module = SharedModuleManager::GetInstance()->GenerateFuncModule(thread, jsPandaFile,
350                                                                                             entryPoint, classKind);
351     if (module->IsSourceTextModule()) {
352         SourceTextModule::Cast(module->GetTaggedObject())->SetSendableEnv(thread, sendableEnv);
353     }
354 
355     jsFunc->SetModule(thread, module.GetTaggedValue());
356     jsFunc->SetLength(length);
357     return jsFunc;
358 }
359 
GetMethodOffsets(const JSPandaFile *jsPandaFile, size_t index, std::vector<uint32_t> &methodOffsets)360 void LiteralDataExtractor::GetMethodOffsets(const JSPandaFile *jsPandaFile, size_t index,
361                                             std::vector<uint32_t> &methodOffsets)
362 {
363     LiteralDataAccessor lda = jsPandaFile->GetLiteralDataAccessor();
364     lda.EnumerateLiteralVals(index, [&methodOffsets](const LiteralValue &value, const LiteralTag &tag) {
365         switch (tag) {
366             case LiteralTag::METHOD:
367             case LiteralTag::GETTER:
368             case LiteralTag::SETTER:
369             case LiteralTag::ASYNCGENERATORMETHOD:
370             case LiteralTag::GENERATORMETHOD: {
371                 methodOffsets.emplace_back(std::get<uint32_t>(value));
372                 break;
373             }
374             default: {
375                 break;
376             }
377         }
378     });
379 }
380 
GetMethodOffsets(const JSPandaFile *jsPandaFile, EntityId id, std::vector<uint32_t> &methodOffsets)381 void LiteralDataExtractor::GetMethodOffsets(const JSPandaFile *jsPandaFile, EntityId id,
382                                             std::vector<uint32_t> &methodOffsets)
383 {
384     LiteralDataAccessor lda = jsPandaFile->GetLiteralDataAccessor();
385     lda.EnumerateLiteralVals(id, [&methodOffsets](const LiteralValue &value, const LiteralTag &tag) {
386         switch (tag) {
387             case LiteralTag::METHOD:
388             case LiteralTag::GETTER:
389             case LiteralTag::SETTER:
390             case LiteralTag::ASYNCGENERATORMETHOD:
391             case LiteralTag::GENERATORMETHOD: {
392                 methodOffsets.emplace_back(std::get<uint32_t>(value));
393                 break;
394             }
395             default: {
396                 break;
397             }
398         }
399     });
400 }
401 
ExtractObjectDatas(JSThread *thread, const JSPandaFile *jsPandaFile, EntityId id, JSMutableHandle<TaggedArray> elements, JSMutableHandle<TaggedArray> properties, JSHandle<ConstantPool> constpool, const CString &entry, bool isLoadedAOT, JSHandle<AOTLiteralInfo> entryIndexes)402 void LiteralDataExtractor::ExtractObjectDatas(JSThread *thread, const JSPandaFile *jsPandaFile, EntityId id,
403                                               JSMutableHandle<TaggedArray> elements,
404                                               JSMutableHandle<TaggedArray> properties,
405                                               JSHandle<ConstantPool> constpool, const CString &entry,
406                                               bool isLoadedAOT, JSHandle<AOTLiteralInfo> entryIndexes)
407 {
408     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
409     LiteralDataAccessor lda = jsPandaFile->GetLiteralDataAccessor();
410     uint32_t num = lda.GetLiteralValsNum(id) / 2;  // 2: half
411     elements.Update(factory->NewOldSpaceTaggedArray(num).GetTaggedValue());
412     properties.Update(factory->NewOldSpaceTaggedArray(num).GetTaggedValue());
413     uint32_t epos = 0;
414     uint32_t ppos = 0;
415     const uint8_t pairSize = 2;
416     uint32_t methodId = 0;
417     int pos = 0;
418     FunctionKind kind;
419     lda.EnumerateLiteralVals(
420         id, [elements, properties, &entryIndexes, &pos, &epos, &ppos, factory, thread, jsPandaFile,
421                 &methodId, &kind, &constpool, &entry, &isLoadedAOT](const LiteralValue &value, const LiteralTag &tag) {
422         JSTaggedValue jt = JSTaggedValue::Null();
423         bool flag = false;
424         switch (tag) {
425             case LiteralTag::INTEGER: {
426                 jt = JSTaggedValue(static_cast<int32_t>(std::get<uint32_t>(value)));
427                 break;
428             }
429             case LiteralTag::DOUBLE: {
430                 jt = JSTaggedValue(std::get<double>(value));
431                 break;
432             }
433             case LiteralTag::BOOL: {
434                 jt = JSTaggedValue(std::get<bool>(value));
435                 break;
436             }
437             case LiteralTag::STRING: {
438                 StringData sd = jsPandaFile->GetStringData(EntityId(std::get<uint32_t>(value)));
439                 EcmaString *str = factory->GetRawStringFromStringTable(sd, MemSpaceType::SHARED_OLD_SPACE);
440                 jt = JSTaggedValue(str);
441                 uint32_t elementIndex = 0;
442                 if (JSTaggedValue::ToElementIndex(jt, &elementIndex) && ppos % pairSize == 0) {
443                     flag = true;
444                 }
445                 break;
446             }
447             case LiteralTag::METHOD: {
448                 methodId = std::get<uint32_t>(value);
449                 kind = FunctionKind::NORMAL_FUNCTION;
450                 break;
451             }
452             case LiteralTag::GETTER: {
453                 methodId = std::get<uint32_t>(value);
454                 kind = FunctionKind::GETTER_FUNCTION;
455                 break;
456             }
457             case LiteralTag::SETTER: {
458                 methodId = std::get<uint32_t>(value);
459                 kind = FunctionKind::SETTER_FUNCTION;
460                 break;
461             }
462             case LiteralTag::GENERATORMETHOD: {
463                 methodId = std::get<uint32_t>(value);
464                 kind = FunctionKind::GENERATOR_FUNCTION;
465                 break;
466             }
467 
468             case LiteralTag::ASYNCGENERATORMETHOD: {
469                 methodId = std::get<uint32_t>(value);
470                 kind = FunctionKind::ASYNC_GENERATOR_FUNCTION;
471                 break;
472             }
473 
474             case LiteralTag::METHODAFFILIATE: {
475                 uint16_t length = std::get<uint16_t>(value);
476                 int entryIndex = 0;
477                 bool needSetAotFlag = (isLoadedAOT && (epos % pairSize == 0) && !flag);
478                 if (needSetAotFlag) {
479                     entryIndex = entryIndexes->GetObjectFromCache(pos++).GetInt();
480                     // -1 : this jsfunction is a large function
481                     if (entryIndex == -1) {
482                         needSetAotFlag = false;
483                     }
484                 }
485                 JSHandle<JSFunction> jsFunc =
486                     DefineMethodInLiteral(thread, jsPandaFile, methodId, constpool, kind,
487                                           length, entry, needSetAotFlag, entryIndex);
488                 jt = jsFunc.GetTaggedValue();
489                 break;
490             }
491             case LiteralTag::ACCESSOR: {
492                 JSHandle<AccessorData> accessor = factory->NewAccessorData();
493                 jt = accessor.GetTaggedValue();
494                 break;
495             }
496             case LiteralTag::NULLVALUE: {
497                 break;
498             }
499             default: {
500                 LOG_ECMA(FATAL) << "this branch is unreachable";
501                 UNREACHABLE();
502                 break;
503             }
504         }
505         if (tag != LiteralTag::METHOD && tag != LiteralTag::GETTER && tag != LiteralTag::SETTER &&
506             tag != LiteralTag::GENERATORMETHOD && tag != LiteralTag::ASYNCGENERATORMETHOD) {
507             if ((epos % pairSize == 0) && !flag) {
508                 properties->Set(thread, ppos++, jt);
509             } else {
510                 elements->Set(thread, epos++, jt);
511             }
512         }
513     });
514 }
515 
GetDatasIgnoreTypeForClass(JSThread *thread, const JSPandaFile *jsPandaFile, EntityId id, JSHandle<ConstantPool> constpool, const CString &entryPoint, bool isLoadedAOT, JSHandle<AOTLiteralInfo> entryIndexes, ElementsKind *newKind, JSHandle<JSTaggedValue> sendableEnv, ClassKind classKind)516 JSHandle<TaggedArray> LiteralDataExtractor::GetDatasIgnoreTypeForClass(JSThread *thread, const JSPandaFile *jsPandaFile,
517                                                                        EntityId id, JSHandle<ConstantPool> constpool,
518                                                                        const CString &entryPoint, bool isLoadedAOT,
519                                                                        JSHandle<AOTLiteralInfo> entryIndexes,
520                                                                        ElementsKind *newKind,
521                                                                        JSHandle<JSTaggedValue> sendableEnv,
522                                                                        ClassKind classKind)
523 {
524     ASSERT(jsPandaFile != nullptr);
525     LiteralDataAccessor lda = jsPandaFile->GetLiteralDataAccessor();
526     uint32_t num = lda.GetLiteralValsNum(id) / 2;  // 2: half
527     // The num is 1, indicating that the current class has no member variable.
528     if (num == 1) {
529         ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
530         return factory->EmptyArray();
531     }
532     return GetDatasIgnoreType(
533         thread, jsPandaFile, id, constpool, entryPoint, isLoadedAOT, entryIndexes, newKind, sendableEnv, classKind);
534 }
535 
GetDatasIgnoreType(JSThread *thread, const JSPandaFile *jsPandaFile, EntityId id, JSHandle<ConstantPool> constpool, const CString &entryPoint, bool isLoadedAOT, JSHandle<AOTLiteralInfo> entryIndexes, ElementsKind *newKind, JSHandle<JSTaggedValue> sendableEnv, ClassKind classKind)536 JSHandle<TaggedArray> LiteralDataExtractor::GetDatasIgnoreType(JSThread *thread, const JSPandaFile *jsPandaFile,
537                                                                EntityId id, JSHandle<ConstantPool> constpool,
538                                                                const CString &entryPoint, bool isLoadedAOT,
539                                                                JSHandle<AOTLiteralInfo> entryIndexes,
540                                                                ElementsKind *newKind,
541                                                                JSHandle<JSTaggedValue> sendableEnv,
542                                                                ClassKind classKind)
543 {
544     ASSERT(jsPandaFile != nullptr);
545     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
546     LiteralDataAccessor lda = jsPandaFile->GetLiteralDataAccessor();
547     uint32_t num = lda.GetLiteralValsNum(id) / 2;  // 2: half
548     JSHandle<TaggedArray> literals;
549     if (classKind == ClassKind::SENDABLE) {
550         literals = JSHandle<TaggedArray>(factory->NewSCOWTaggedArray(num));
551     } else {
552         literals = JSHandle<TaggedArray>(factory->NewCOWTaggedArray(num));
553     }
554     uint32_t pos = 0;
555     uint32_t methodId = 0;
556     FunctionKind kind;
557     int index = 0;
558     lda.EnumerateLiteralVals(
559         id, [literals, &pos, factory, thread, jsPandaFile, &methodId, &kind, &constpool,
560             &entryPoint, &entryIndexes, &index, isLoadedAOT, newKind, classKind, &sendableEnv]
561         (const LiteralValue &value, const LiteralTag &tag) {
562             JSTaggedValue jt = JSTaggedValue::Null();
563             switch (tag) {
564                 case LiteralTag::INTEGER: {
565                     jt = JSTaggedValue(std::get<uint32_t>(value));
566                     break;
567                 }
568                 case LiteralTag::DOUBLE: {
569                     jt = JSTaggedValue(std::get<double>(value));
570                     break;
571                 }
572                 case LiteralTag::BOOL: {
573                     jt = JSTaggedValue(std::get<bool>(value));
574                     break;
575                 }
576                 case LiteralTag::STRING: {
577                     StringData sd = jsPandaFile->GetStringData(EntityId(std::get<uint32_t>(value)));
578                     EcmaString *str = factory->GetRawStringFromStringTable(sd, MemSpaceType::SHARED_OLD_SPACE);
579                     jt = JSTaggedValue(str);
580                     break;
581                 }
582                 case LiteralTag::METHOD: {
583                     methodId = std::get<uint32_t>(value);
584                     kind = FunctionKind::NORMAL_FUNCTION;
585                     break;
586                 }
587                 case LiteralTag::GETTER: {
588                     methodId = std::get<uint32_t>(value);
589                     kind = FunctionKind::GETTER_FUNCTION;
590                     break;
591                 }
592                 case LiteralTag::SETTER: {
593                     methodId = std::get<uint32_t>(value);
594                     kind = FunctionKind::SETTER_FUNCTION;
595                     break;
596                 }
597                 case LiteralTag::GENERATORMETHOD: {
598                     methodId = std::get<uint32_t>(value);
599                     kind = FunctionKind::GENERATOR_FUNCTION;
600                     break;
601                 }
602                 case LiteralTag::ASYNCGENERATORMETHOD: {
603                     methodId = std::get<uint32_t>(value);
604                     kind = FunctionKind::ASYNC_GENERATOR_FUNCTION;
605                     break;
606                 }
607                 case LiteralTag::METHODAFFILIATE: {
608                     uint16_t length = std::get<uint16_t>(value);
609                     int entryIndex = 0;
610                     bool needSetAotFlag = isLoadedAOT;
611                     if (isLoadedAOT) {
612                         entryIndex = entryIndexes->GetObjectFromCache(index++).GetInt();
613                         if (entryIndex == -1) {
614                             needSetAotFlag = false;
615                         }
616                     }
617                     JSHandle<FunctionTemplate> funcTemp = DefineFunctionTemplate(thread, jsPandaFile, methodId,
618                         constpool, kind, length, entryPoint, needSetAotFlag, entryIndex, sendableEnv, classKind);
619                     jt = funcTemp.GetTaggedValue();
620                     break;
621                 }
622                 case LiteralTag::ACCESSOR: {
623                     JSHandle<AccessorData> accessor = factory->NewAccessorData();
624                     jt = accessor.GetTaggedValue();
625                     break;
626                 }
627                 case LiteralTag::LITERALARRAY: {
628                     jt = JSTaggedValue(std::get<uint32_t>(value));
629                     break;
630                 }
631                 case LiteralTag::NULLVALUE: {
632                     break;
633                 }
634                 default: {
635                     LOG_ECMA(FATAL) << "this branch is unreachable";
636                     UNREACHABLE();
637                     break;
638                 }
639             }
640             if (tag != LiteralTag::METHOD && tag != LiteralTag::GETTER && tag != LiteralTag::SETTER &&
641                 tag != LiteralTag::GENERATORMETHOD && tag != LiteralTag::ASYNCGENERATORMETHOD) {
642                 if (newKind != nullptr) {
643                     *newKind = Elements::ToElementsKind(jt, *newKind);
644                 }
645                 literals->Set(thread, pos++, jt);
646             } else {
647                 uint32_t oldLength = literals->GetLength();
648                 ASSERT(oldLength > 0);
649                 literals->Trim(thread, oldLength - 1);
650             }
651         });
652     return literals;
653 }
654 }  // namespace panda::ecmascript
655