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
23namespace panda::ecmascript {
24using LiteralTag = panda_file::LiteralTag;
25using StringData = panda_file::StringData;
26using LiteralDataAccessor = panda_file::LiteralDataAccessor;
27using LiteralValue = panda_file::LiteralDataAccessor::LiteralValue;
28
29void 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
130JSHandle<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
143JSHandle<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
151JSHandle<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
241JSHandle<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
286JSHandle<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
321JSHandle<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
360void 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
381void 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
402void 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
516JSHandle<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
536JSHandle<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