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