• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     jsFunc->SetModule(thread, module.GetTaggedValue());
355     jsFunc->SetLength(length);
356     return jsFunc;
357 }
358 
GetMethodOffsets(const JSPandaFile * jsPandaFile,size_t index,std::vector<uint32_t> & methodOffsets)359 void LiteralDataExtractor::GetMethodOffsets(const JSPandaFile *jsPandaFile, size_t index,
360                                             std::vector<uint32_t> &methodOffsets)
361 {
362     LiteralDataAccessor lda = jsPandaFile->GetLiteralDataAccessor();
363     lda.EnumerateLiteralVals(index, [&methodOffsets](const LiteralValue &value, const LiteralTag &tag) {
364         switch (tag) {
365             case LiteralTag::METHOD:
366             case LiteralTag::GETTER:
367             case LiteralTag::SETTER:
368             case LiteralTag::ASYNCGENERATORMETHOD:
369             case LiteralTag::GENERATORMETHOD: {
370                 methodOffsets.emplace_back(std::get<uint32_t>(value));
371                 break;
372             }
373             default: {
374                 break;
375             }
376         }
377     });
378 }
379 
GetMethodOffsets(const JSPandaFile * jsPandaFile,EntityId id,std::vector<uint32_t> & methodOffsets)380 void LiteralDataExtractor::GetMethodOffsets(const JSPandaFile *jsPandaFile, EntityId id,
381                                             std::vector<uint32_t> &methodOffsets)
382 {
383     LiteralDataAccessor lda = jsPandaFile->GetLiteralDataAccessor();
384     lda.EnumerateLiteralVals(id, [&methodOffsets](const LiteralValue &value, const LiteralTag &tag) {
385         switch (tag) {
386             case LiteralTag::METHOD:
387             case LiteralTag::GETTER:
388             case LiteralTag::SETTER:
389             case LiteralTag::ASYNCGENERATORMETHOD:
390             case LiteralTag::GENERATORMETHOD: {
391                 methodOffsets.emplace_back(std::get<uint32_t>(value));
392                 break;
393             }
394             default: {
395                 break;
396             }
397         }
398     });
399 }
400 
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)401 void LiteralDataExtractor::ExtractObjectDatas(JSThread *thread, const JSPandaFile *jsPandaFile, EntityId id,
402                                               JSMutableHandle<TaggedArray> elements,
403                                               JSMutableHandle<TaggedArray> properties,
404                                               JSHandle<ConstantPool> constpool, const CString &entry,
405                                               bool isLoadedAOT, JSHandle<AOTLiteralInfo> entryIndexes)
406 {
407     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
408     LiteralDataAccessor lda = jsPandaFile->GetLiteralDataAccessor();
409     uint32_t num = lda.GetLiteralValsNum(id) / 2;  // 2: half
410     elements.Update(factory->NewOldSpaceTaggedArray(num).GetTaggedValue());
411     properties.Update(factory->NewOldSpaceTaggedArray(num).GetTaggedValue());
412     uint32_t epos = 0;
413     uint32_t ppos = 0;
414     const uint8_t pairSize = 2;
415     uint32_t methodId = 0;
416     int pos = 0;
417     FunctionKind kind;
418     lda.EnumerateLiteralVals(
419         id, [elements, properties, &entryIndexes, &pos, &epos, &ppos, factory, thread, jsPandaFile,
420                 &methodId, &kind, &constpool, &entry, &isLoadedAOT](const LiteralValue &value, const LiteralTag &tag) {
421         JSTaggedValue jt = JSTaggedValue::Null();
422         bool flag = false;
423         switch (tag) {
424             case LiteralTag::INTEGER: {
425                 jt = JSTaggedValue(std::get<uint32_t>(value));
426                 break;
427             }
428             case LiteralTag::DOUBLE: {
429                 jt = JSTaggedValue(std::get<double>(value));
430                 break;
431             }
432             case LiteralTag::BOOL: {
433                 jt = JSTaggedValue(std::get<bool>(value));
434                 break;
435             }
436             case LiteralTag::STRING: {
437                 StringData sd = jsPandaFile->GetStringData(EntityId(std::get<uint32_t>(value)));
438                 EcmaString *str = factory->GetRawStringFromStringTable(sd, MemSpaceType::SHARED_OLD_SPACE);
439                 jt = JSTaggedValue(str);
440                 uint32_t elementIndex = 0;
441                 if (JSTaggedValue::ToElementIndex(jt, &elementIndex) && ppos % pairSize == 0) {
442                     flag = true;
443                 }
444                 break;
445             }
446             case LiteralTag::METHOD: {
447                 methodId = std::get<uint32_t>(value);
448                 kind = FunctionKind::NORMAL_FUNCTION;
449                 break;
450             }
451             case LiteralTag::GETTER: {
452                 methodId = std::get<uint32_t>(value);
453                 kind = FunctionKind::GETTER_FUNCTION;
454                 break;
455             }
456             case LiteralTag::SETTER: {
457                 methodId = std::get<uint32_t>(value);
458                 kind = FunctionKind::SETTER_FUNCTION;
459                 break;
460             }
461             case LiteralTag::GENERATORMETHOD: {
462                 methodId = std::get<uint32_t>(value);
463                 kind = FunctionKind::GENERATOR_FUNCTION;
464                 break;
465             }
466 
467             case LiteralTag::ASYNCGENERATORMETHOD: {
468                 methodId = std::get<uint32_t>(value);
469                 kind = FunctionKind::ASYNC_GENERATOR_FUNCTION;
470                 break;
471             }
472 
473             case LiteralTag::METHODAFFILIATE: {
474                 uint16_t length = std::get<uint16_t>(value);
475                 int entryIndex = 0;
476                 bool needSetAotFlag = (isLoadedAOT && (epos % pairSize == 0) && !flag);
477                 if (needSetAotFlag) {
478                     entryIndex = entryIndexes->GetObjectFromCache(pos++).GetInt();
479                     // -1 : this jsfunction is a large function
480                     if (entryIndex == -1) {
481                         needSetAotFlag = false;
482                     }
483                 }
484                 JSHandle<JSFunction> jsFunc =
485                     DefineMethodInLiteral(thread, jsPandaFile, methodId, constpool, kind,
486                                           length, entry, needSetAotFlag, entryIndex);
487                 jt = jsFunc.GetTaggedValue();
488                 break;
489             }
490             case LiteralTag::ACCESSOR: {
491                 JSHandle<AccessorData> accessor = factory->NewAccessorData();
492                 jt = accessor.GetTaggedValue();
493                 break;
494             }
495             case LiteralTag::NULLVALUE: {
496                 break;
497             }
498             default: {
499                 LOG_ECMA(FATAL) << "this branch is unreachable";
500                 UNREACHABLE();
501                 break;
502             }
503         }
504         if (tag != LiteralTag::METHOD && tag != LiteralTag::GETTER && tag != LiteralTag::SETTER &&
505             tag != LiteralTag::GENERATORMETHOD && tag != LiteralTag::ASYNCGENERATORMETHOD) {
506             if ((epos % pairSize == 0) && !flag) {
507                 properties->Set(thread, ppos++, jt);
508             } else {
509                 elements->Set(thread, epos++, jt);
510             }
511         }
512     });
513 }
514 
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)515 JSHandle<TaggedArray> LiteralDataExtractor::GetDatasIgnoreTypeForClass(JSThread *thread, const JSPandaFile *jsPandaFile,
516                                                                        EntityId id, JSHandle<ConstantPool> constpool,
517                                                                        const CString &entryPoint, bool isLoadedAOT,
518                                                                        JSHandle<AOTLiteralInfo> entryIndexes,
519                                                                        ElementsKind *newKind,
520                                                                        JSHandle<JSTaggedValue> sendableEnv,
521                                                                        ClassKind classKind)
522 {
523     ASSERT(jsPandaFile != nullptr);
524     LiteralDataAccessor lda = jsPandaFile->GetLiteralDataAccessor();
525     uint32_t num = lda.GetLiteralValsNum(id) / 2;  // 2: half
526     // The num is 1, indicating that the current class has no member variable.
527     if (num == 1) {
528         ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
529         return factory->EmptyArray();
530     }
531     return GetDatasIgnoreType(
532         thread, jsPandaFile, id, constpool, entryPoint, isLoadedAOT, entryIndexes, newKind, sendableEnv, classKind);
533 }
534 
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)535 JSHandle<TaggedArray> LiteralDataExtractor::GetDatasIgnoreType(JSThread *thread, const JSPandaFile *jsPandaFile,
536                                                                EntityId id, JSHandle<ConstantPool> constpool,
537                                                                const CString &entryPoint, bool isLoadedAOT,
538                                                                JSHandle<AOTLiteralInfo> entryIndexes,
539                                                                ElementsKind *newKind,
540                                                                JSHandle<JSTaggedValue> sendableEnv,
541                                                                ClassKind classKind)
542 {
543     ASSERT(jsPandaFile != nullptr);
544     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
545     LiteralDataAccessor lda = jsPandaFile->GetLiteralDataAccessor();
546     uint32_t num = lda.GetLiteralValsNum(id) / 2;  // 2: half
547     JSHandle<TaggedArray> literals;
548     if (classKind == ClassKind::SENDABLE) {
549         literals = JSHandle<TaggedArray>(factory->NewSCOWTaggedArray(num));
550     } else {
551         literals = JSHandle<TaggedArray>(factory->NewCOWTaggedArray(num));
552     }
553     uint32_t pos = 0;
554     uint32_t methodId = 0;
555     FunctionKind kind;
556     int index = 0;
557     lda.EnumerateLiteralVals(
558         id, [literals, &pos, factory, thread, jsPandaFile, &methodId, &kind, &constpool,
559             &entryPoint, &entryIndexes, &index, isLoadedAOT, newKind, classKind, &sendableEnv]
560         (const LiteralValue &value, const LiteralTag &tag) {
561             JSTaggedValue jt = JSTaggedValue::Null();
562             switch (tag) {
563                 case LiteralTag::INTEGER: {
564                     jt = JSTaggedValue(std::get<uint32_t>(value));
565                     break;
566                 }
567                 case LiteralTag::DOUBLE: {
568                     jt = JSTaggedValue(std::get<double>(value));
569                     break;
570                 }
571                 case LiteralTag::BOOL: {
572                     jt = JSTaggedValue(std::get<bool>(value));
573                     break;
574                 }
575                 case LiteralTag::STRING: {
576                     StringData sd = jsPandaFile->GetStringData(EntityId(std::get<uint32_t>(value)));
577                     EcmaString *str = factory->GetRawStringFromStringTable(sd, MemSpaceType::SHARED_OLD_SPACE);
578                     jt = JSTaggedValue(str);
579                     break;
580                 }
581                 case LiteralTag::METHOD: {
582                     methodId = std::get<uint32_t>(value);
583                     kind = FunctionKind::NORMAL_FUNCTION;
584                     break;
585                 }
586                 case LiteralTag::GETTER: {
587                     methodId = std::get<uint32_t>(value);
588                     kind = FunctionKind::GETTER_FUNCTION;
589                     break;
590                 }
591                 case LiteralTag::SETTER: {
592                     methodId = std::get<uint32_t>(value);
593                     kind = FunctionKind::SETTER_FUNCTION;
594                     break;
595                 }
596                 case LiteralTag::GENERATORMETHOD: {
597                     methodId = std::get<uint32_t>(value);
598                     kind = FunctionKind::GENERATOR_FUNCTION;
599                     break;
600                 }
601                 case LiteralTag::ASYNCGENERATORMETHOD: {
602                     methodId = std::get<uint32_t>(value);
603                     kind = FunctionKind::ASYNC_GENERATOR_FUNCTION;
604                     break;
605                 }
606                 case LiteralTag::METHODAFFILIATE: {
607                     uint16_t length = std::get<uint16_t>(value);
608                     int entryIndex = 0;
609                     bool needSetAotFlag = isLoadedAOT;
610                     if (isLoadedAOT) {
611                         entryIndex = entryIndexes->GetObjectFromCache(index++).GetInt();
612                         if (entryIndex == -1) {
613                             needSetAotFlag = false;
614                         }
615                     }
616                     JSHandle<FunctionTemplate> funcTemp = DefineFunctionTemplate(thread, jsPandaFile, methodId,
617                         constpool, kind, length, entryPoint, needSetAotFlag, entryIndex, sendableEnv, classKind);
618                     jt = funcTemp.GetTaggedValue();
619                     break;
620                 }
621                 case LiteralTag::ACCESSOR: {
622                     JSHandle<AccessorData> accessor = factory->NewAccessorData();
623                     jt = accessor.GetTaggedValue();
624                     break;
625                 }
626                 case LiteralTag::LITERALARRAY: {
627                     jt = JSTaggedValue(std::get<uint32_t>(value));
628                     break;
629                 }
630                 case LiteralTag::NULLVALUE: {
631                     break;
632                 }
633                 default: {
634                     LOG_ECMA(FATAL) << "this branch is unreachable";
635                     UNREACHABLE();
636                     break;
637                 }
638             }
639             if (tag != LiteralTag::METHOD && tag != LiteralTag::GETTER && tag != LiteralTag::SETTER &&
640                 tag != LiteralTag::GENERATORMETHOD && tag != LiteralTag::ASYNCGENERATORMETHOD) {
641                 if (newKind != nullptr) {
642                     *newKind = Elements::ToElementsKind(jt, *newKind);
643                 }
644                 literals->Set(thread, pos++, jt);
645             } else {
646                 uint32_t oldLength = literals->GetLength();
647                 ASSERT(oldLength > 0);
648                 literals->Trim(thread, oldLength - 1);
649             }
650         });
651     return literals;
652 }
653 }  // namespace panda::ecmascript
654