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/base/string_helper.h"
19 #include "ecmascript/ecma_string.h"
20 #include "ecmascript/global_env.h"
21 #include "ecmascript/js_thread.h"
22 #include "ecmascript/jspandafile/js_pandafile.h"
23 #include "ecmascript/module/js_module_manager.h"
24 #include "ecmascript/tagged_array-inl.h"
25
26 namespace panda::ecmascript {
27 using LiteralTag = panda_file::LiteralTag;
28 using StringData = panda_file::StringData;
29 using LiteralValue = panda_file::LiteralDataAccessor::LiteralValue;
30
ExtractObjectDatas(JSThread * thread,const JSPandaFile * jsPandaFile,size_t index,JSMutableHandle<TaggedArray> elements,JSMutableHandle<TaggedArray> properties,JSHandle<ConstantPool> constpool,const CString & entryPoint)31 void LiteralDataExtractor::ExtractObjectDatas(JSThread *thread, const JSPandaFile *jsPandaFile, size_t index,
32 JSMutableHandle<TaggedArray> elements,
33 JSMutableHandle<TaggedArray> properties,
34 JSHandle<ConstantPool> constpool,
35 const CString &entryPoint)
36 {
37 EcmaVM *vm = thread->GetEcmaVM();
38 ObjectFactory *factory = vm->GetFactory();
39
40 LOG_ECMA(VERBOSE) << "Panda File" << jsPandaFile->GetJSPandaFileDesc();
41 const panda_file::File *pf = jsPandaFile->GetPandaFile();
42 panda_file::File::EntityId literalArraysId = pf->GetLiteralArraysId();
43 panda_file::LiteralDataAccessor lda(*pf, literalArraysId);
44
45 uint32_t num = lda.GetLiteralValsNum(index) / 2; // 2: half
46 elements.Update(factory->NewOldSpaceTaggedArray(num).GetTaggedValue());
47 properties.Update(factory->NewOldSpaceTaggedArray(num).GetTaggedValue());
48 uint32_t epos = 0;
49 uint32_t ppos = 0;
50 const uint8_t pairSize = 2;
51 uint32_t methodId;
52 FunctionKind kind;
53 lda.EnumerateLiteralVals(
54 index, [elements, properties, &epos, &ppos, vm, factory, thread, jsPandaFile, pf,
55 &methodId, &kind, &constpool, &entryPoint]
56 (const LiteralValue &value, const LiteralTag &tag) {
57 JSTaggedValue jt = JSTaggedValue::Null();
58 bool flag = false;
59 switch (tag) {
60 case LiteralTag::INTEGER: {
61 jt = JSTaggedValue(std::get<uint32_t>(value));
62 break;
63 }
64 case LiteralTag::DOUBLE: {
65 jt = JSTaggedValue(std::get<double>(value));
66 break;
67 }
68 case LiteralTag::BOOL: {
69 jt = JSTaggedValue(std::get<bool>(value));
70 break;
71 }
72 case LiteralTag::STRING: {
73 StringData sd = pf->GetStringData(panda_file::File::EntityId(std::get<uint32_t>(value)));
74 EcmaString *str = factory->GetRawStringFromStringTable(sd.data, sd.utf16_length, sd.is_ascii,
75 MemSpaceType::OLD_SPACE);
76 jt = JSTaggedValue(str);
77 uint32_t index = 0;
78 if (JSTaggedValue::ToElementIndex(jt, &index) && ppos % pairSize == 0) {
79 flag = true;
80 }
81 break;
82 }
83 case LiteralTag::METHOD: {
84 methodId = std::get<uint32_t>(value);
85 kind = FunctionKind::NORMAL_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::METHODAFFILIATE: {
94 uint16_t length = std::get<uint16_t>(value);
95 auto methodLiteral = jsPandaFile->FindMethodLiteral(methodId);
96 ASSERT(methodLiteral != nullptr);
97 methodLiteral->SetFunctionKind(kind);
98
99 JSHandle<Method> method = factory->NewMethod(methodLiteral);
100 if (jsPandaFile->IsNewVersion()) {
101 JSHandle<ConstantPool> newConstpool =
102 vm->FindOrCreateConstPool(jsPandaFile, panda_file::File::EntityId(methodId));
103 method->SetConstantPool(thread, newConstpool);
104 } else {
105 method->SetConstantPool(thread, constpool.GetTaggedValue());
106 }
107 JSHandle<JSFunction> jsFunc =
108 DefineMethodInLiteral(thread, jsPandaFile, method, kind, length, entryPoint);
109 jt = jsFunc.GetTaggedValue();
110 break;
111 }
112 case LiteralTag::ACCESSOR: {
113 JSHandle<AccessorData> accessor = factory->NewAccessorData();
114 jt = JSTaggedValue(accessor.GetTaggedValue());
115 break;
116 }
117 case LiteralTag::NULLVALUE: {
118 break;
119 }
120 default: {
121 UNREACHABLE();
122 break;
123 }
124 }
125 if (tag != LiteralTag::METHOD && tag != LiteralTag::GENERATORMETHOD) {
126 if (epos % pairSize == 0 && !flag) {
127 properties->Set(thread, ppos++, jt);
128 } else {
129 elements->Set(thread, epos++, jt);
130 }
131 }
132 });
133 }
134
GetDatasIgnoreTypeForClass(JSThread * thread,const JSPandaFile * jsPandaFile,size_t index,JSHandle<ConstantPool> constpool,const CString & entryPoint)135 JSHandle<TaggedArray> LiteralDataExtractor::GetDatasIgnoreTypeForClass(JSThread *thread,
136 const JSPandaFile *jsPandaFile, size_t index, JSHandle<ConstantPool> constpool, const CString &entryPoint)
137 {
138 const panda_file::File *pf = jsPandaFile->GetPandaFile();
139 panda_file::File::EntityId literalArraysId = pf->GetLiteralArraysId();
140 panda_file::LiteralDataAccessor lda(*pf, literalArraysId);
141 uint32_t num = lda.GetLiteralValsNum(index) / 2; // 2: half
142 // The num is 1, indicating that the current class has no member variable.
143 if (num == 1) {
144 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
145 return factory->EmptyArray();
146 }
147 return EnumerateLiteralVals(thread, lda, jsPandaFile, index, constpool, entryPoint);
148 }
149
GetDatasIgnoreType(JSThread * thread,const JSPandaFile * jsPandaFile,size_t index,JSHandle<ConstantPool> constpool,const CString & entryPoint)150 JSHandle<TaggedArray> LiteralDataExtractor::GetDatasIgnoreType(JSThread *thread, const JSPandaFile *jsPandaFile,
151 size_t index, JSHandle<ConstantPool> constpool,
152 const CString &entryPoint)
153 {
154 LOG_ECMA(VERBOSE) << "Panda File" << jsPandaFile->GetJSPandaFileDesc();
155 const panda_file::File *pf = jsPandaFile->GetPandaFile();
156 panda_file::File::EntityId literalArraysId = pf->GetLiteralArraysId();
157 panda_file::LiteralDataAccessor lda(*pf, literalArraysId);
158 return EnumerateLiteralVals(thread, lda, jsPandaFile, index, constpool, entryPoint);
159 }
160
EnumerateLiteralVals(JSThread * thread,panda_file::LiteralDataAccessor & lda,const JSPandaFile * jsPandaFile,size_t index,JSHandle<ConstantPool> constpool,const CString & entryPoint)161 JSHandle<TaggedArray> LiteralDataExtractor::EnumerateLiteralVals(JSThread *thread, panda_file::LiteralDataAccessor &lda,
162 const JSPandaFile *jsPandaFile, size_t index, JSHandle<ConstantPool> constpool, const CString &entryPoint)
163 {
164 EcmaVM *vm = thread->GetEcmaVM();
165 ObjectFactory *factory = vm->GetFactory();
166 uint32_t num = lda.GetLiteralValsNum(index) / 2; // 2: half
167 JSHandle<TaggedArray> literals = factory->NewOldSpaceTaggedArray(num);
168 uint32_t pos = 0;
169 uint32_t methodId;
170 FunctionKind kind;
171 lda.EnumerateLiteralVals(
172 index, [literals, &pos, vm, factory, thread, jsPandaFile, &methodId, &kind, &constpool, &entryPoint]
173 (const panda_file::LiteralDataAccessor::LiteralValue &value, const LiteralTag &tag) {
174 JSTaggedValue jt = JSTaggedValue::Null();
175 switch (tag) {
176 case LiteralTag::INTEGER: {
177 jt = JSTaggedValue(std::get<uint32_t>(value));
178 break;
179 }
180 case LiteralTag::DOUBLE: {
181 jt = JSTaggedValue(std::get<double>(value));
182 break;
183 }
184 case LiteralTag::BOOL: {
185 jt = JSTaggedValue(std::get<bool>(value));
186 break;
187 }
188 case LiteralTag::STRING: {
189 const panda_file::File *pf = jsPandaFile->GetPandaFile();
190 StringData sd = pf->GetStringData(panda_file::File::EntityId(std::get<uint32_t>(value)));
191 EcmaString *str = factory->GetRawStringFromStringTable(sd.data, sd.utf16_length, sd.is_ascii,
192 MemSpaceType::OLD_SPACE);
193 jt = JSTaggedValue(str);
194 break;
195 }
196 case LiteralTag::METHOD: {
197 methodId = std::get<uint32_t>(value);
198 kind = FunctionKind::NORMAL_FUNCTION;
199 break;
200 }
201 case LiteralTag::GENERATORMETHOD: {
202 methodId = std::get<uint32_t>(value);
203 kind = FunctionKind::GENERATOR_FUNCTION;
204 break;
205 }
206 case LiteralTag::METHODAFFILIATE: {
207 uint16_t length = std::get<uint16_t>(value);
208 auto methodLiteral = jsPandaFile->FindMethodLiteral(methodId);
209 ASSERT(methodLiteral != nullptr);
210
211 JSHandle<Method> method = factory->NewMethod(methodLiteral);
212 if (jsPandaFile->IsNewVersion()) {
213 JSHandle<ConstantPool> newConstpool =
214 vm->FindOrCreateConstPool(jsPandaFile, panda_file::File::EntityId(methodId));
215 method->SetConstantPool(thread, newConstpool);
216 } else {
217 method->SetConstantPool(thread, constpool);
218 }
219 JSHandle<JSFunction> jsFunc =
220 DefineMethodInLiteral(thread, jsPandaFile, method, kind, length, entryPoint);
221 jt = jsFunc.GetTaggedValue();
222 break;
223 }
224 case LiteralTag::ACCESSOR: {
225 JSHandle<AccessorData> accessor = factory->NewAccessorData();
226 jt = accessor.GetTaggedValue();
227 break;
228 }
229 case LiteralTag::NULLVALUE: {
230 break;
231 }
232 default: {
233 UNREACHABLE();
234 break;
235 }
236 }
237 if (tag != LiteralTag::METHOD && tag != LiteralTag::GENERATORMETHOD) {
238 literals->Set(thread, pos++, jt);
239 } else {
240 uint32_t oldLength = literals->GetLength();
241 literals->Trim(thread, oldLength - 1);
242 }
243 });
244 return literals;
245 }
246
DefineMethodInLiteral(JSThread * thread,const JSPandaFile * jsPandaFile,JSHandle<Method> method,FunctionKind kind,uint16_t length,const CString & entryPoint)247 JSHandle<JSFunction> LiteralDataExtractor::DefineMethodInLiteral(JSThread *thread, const JSPandaFile *jsPandaFile,
248 JSHandle<Method> method,
249 FunctionKind kind, uint16_t length,
250 const CString &entryPoint)
251 {
252 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
253 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
254 JSHandle<JSHClass> functionClass;
255 if (kind == FunctionKind::NORMAL_FUNCTION) {
256 functionClass = JSHandle<JSHClass>::Cast(env->GetFunctionClassWithoutProto());
257 } else {
258 functionClass = JSHandle<JSHClass>::Cast(env->GetGeneratorFunctionClass());
259 }
260 JSHandle<JSFunction> jsFunc = factory->NewJSFunctionByHClass(method, functionClass, MemSpaceType::OLD_SPACE);
261
262 jsFunc->SetPropertyInlinedProps(thread, JSFunction::LENGTH_INLINE_PROPERTY_INDEX, JSTaggedValue(length));
263 CString moduleName = jsPandaFile->GetJSPandaFileDesc();
264 CString entry = JSPandaFile::ENTRY_FUNCTION_NAME;
265 if (!entryPoint.empty()) {
266 moduleName = entryPoint;
267 entry = entryPoint;
268 }
269 if (jsPandaFile->IsModule(thread, entry)) {
270 EcmaVM *vm = thread->GetEcmaVM();
271 JSHandle<SourceTextModule> module = vm->GetModuleManager()->HostGetImportedModule(moduleName);
272 jsFunc->SetModule(thread, module.GetTaggedValue());
273 }
274 return jsFunc;
275 }
276
GetMethodOffsets(const JSPandaFile * jsPandaFile,size_t index,std::vector<uint32_t> & methodOffsets)277 void LiteralDataExtractor::GetMethodOffsets(const JSPandaFile *jsPandaFile, size_t index,
278 std::vector<uint32_t> &methodOffsets)
279 {
280 const panda_file::File *pf = jsPandaFile->GetPandaFile();
281 panda_file::File::EntityId literalArraysId = pf->GetLiteralArraysId();
282 panda_file::LiteralDataAccessor lda(*pf, literalArraysId);
283
284 lda.EnumerateLiteralVals(
285 index, [&methodOffsets]
286 (const panda_file::LiteralDataAccessor::LiteralValue &value, const LiteralTag &tag) {
287 switch (tag) {
288 case LiteralTag::METHOD:
289 case LiteralTag::GENERATORMETHOD: {
290 methodOffsets.emplace_back(std::get<uint32_t>(value));
291 break;
292 }
293 default: {
294 break;
295 }
296 }
297 });
298 }
299
GetMethodOffsets(const JSPandaFile * jsPandaFile,panda_file::File::EntityId index,std::vector<uint32_t> & methodOffsets)300 void LiteralDataExtractor::GetMethodOffsets(const JSPandaFile *jsPandaFile, panda_file::File::EntityId index,
301 std::vector<uint32_t> &methodOffsets)
302 {
303 const panda_file::File *pf = jsPandaFile->GetPandaFile();
304 panda_file::File::EntityId literalArraysId = pf->GetLiteralArraysId();
305 panda_file::LiteralDataAccessor lda(*pf, literalArraysId);
306
307 lda.EnumerateLiteralVals(
308 index, [&methodOffsets]
309 (const panda_file::LiteralDataAccessor::LiteralValue &value, const LiteralTag &tag) {
310 switch (tag) {
311 case LiteralTag::METHOD:
312 case LiteralTag::GENERATORMETHOD: {
313 methodOffsets.emplace_back(std::get<uint32_t>(value));
314 break;
315 }
316 default: {
317 break;
318 }
319 }
320 });
321 }
322
ExtractObjectDatas(JSThread * thread,const JSPandaFile * jsPandaFile,panda_file::File::EntityId index,JSMutableHandle<TaggedArray> elements,JSMutableHandle<TaggedArray> properties,JSHandle<ConstantPool> constpool,const CString & entry)323 void LiteralDataExtractor::ExtractObjectDatas(JSThread *thread, const JSPandaFile *jsPandaFile,
324 panda_file::File::EntityId index,
325 JSMutableHandle<TaggedArray> elements,
326 JSMutableHandle<TaggedArray> properties,
327 JSHandle<ConstantPool> constpool, const CString &entry)
328 {
329 EcmaVM *vm = thread->GetEcmaVM();
330 ObjectFactory *factory = vm->GetFactory();
331
332 LOG_ECMA(VERBOSE) << "Panda File" << jsPandaFile->GetJSPandaFileDesc();
333 const panda_file::File *pf = jsPandaFile->GetPandaFile();
334 panda_file::File::EntityId literalArraysId = pf->GetLiteralArraysId();
335 panda_file::LiteralDataAccessor lda(*pf, literalArraysId);
336
337 uint32_t num = lda.GetLiteralValsNum(index) / 2; // 2: half
338 elements.Update(factory->NewOldSpaceTaggedArray(num).GetTaggedValue());
339 properties.Update(factory->NewOldSpaceTaggedArray(num).GetTaggedValue());
340 uint32_t epos = 0;
341 uint32_t ppos = 0;
342 const uint8_t pairSize = 2;
343 uint32_t methodId;
344 FunctionKind kind;
345 lda.EnumerateLiteralVals(
346 index, [elements, properties, &epos, &ppos, vm, factory, thread, jsPandaFile,
347 pf, &methodId, &kind, &constpool, &entry]
348 (const LiteralValue &value, const LiteralTag &tag) {
349 JSTaggedValue jt = JSTaggedValue::Null();
350 bool flag = false;
351 switch (tag) {
352 case LiteralTag::INTEGER: {
353 jt = JSTaggedValue(std::get<uint32_t>(value));
354 break;
355 }
356 case LiteralTag::DOUBLE: {
357 jt = JSTaggedValue(std::get<double>(value));
358 break;
359 }
360 case LiteralTag::BOOL: {
361 jt = JSTaggedValue(std::get<bool>(value));
362 break;
363 }
364 case LiteralTag::STRING: {
365 StringData sd = pf->GetStringData(panda_file::File::EntityId(std::get<uint32_t>(value)));
366 EcmaString *str = factory->GetRawStringFromStringTable(sd.data, sd.utf16_length, sd.is_ascii,
367 MemSpaceType::OLD_SPACE);
368 jt = JSTaggedValue(str);
369 uint32_t index = 0;
370 if (JSTaggedValue::ToElementIndex(jt, &index) && ppos % pairSize == 0) {
371 flag = true;
372 }
373 break;
374 }
375 case LiteralTag::METHOD: {
376 methodId = std::get<uint32_t>(value);
377 kind = FunctionKind::NORMAL_FUNCTION;
378 break;
379 }
380 case LiteralTag::GENERATORMETHOD: {
381 methodId = std::get<uint32_t>(value);
382 kind = FunctionKind::GENERATOR_FUNCTION;
383 break;
384 }
385 case LiteralTag::METHODAFFILIATE: {
386 uint16_t length = std::get<uint16_t>(value);
387 auto methodLiteral = jsPandaFile->FindMethodLiteral(methodId);
388 ASSERT(methodLiteral != nullptr);
389 // Should replace with ASSERT(kind == methodLiteral->GetFunctionKind())
390 methodLiteral->SetFunctionKind(kind);
391
392 JSHandle<Method> method = factory->NewMethod(methodLiteral);
393 if (jsPandaFile->IsNewVersion()) {
394 JSHandle<ConstantPool> newConstpool =
395 vm->FindOrCreateConstPool(jsPandaFile, panda_file::File::EntityId(methodId));
396 method->SetConstantPool(thread, newConstpool);
397 } else {
398 method->SetConstantPool(thread, constpool.GetTaggedValue());
399 }
400 JSHandle<JSFunction> jsFunc = DefineMethodInLiteral(thread, jsPandaFile, method, kind, length, entry);
401 jt = jsFunc.GetTaggedValue();
402 break;
403 }
404 case LiteralTag::ACCESSOR: {
405 JSHandle<AccessorData> accessor = factory->NewAccessorData();
406 jt = JSTaggedValue(accessor.GetTaggedValue());
407 break;
408 }
409 case LiteralTag::NULLVALUE: {
410 break;
411 }
412 default: {
413 UNREACHABLE();
414 break;
415 }
416 }
417 if (tag != LiteralTag::METHOD && tag != LiteralTag::GENERATORMETHOD) {
418 if (epos % pairSize == 0 && !flag) {
419 properties->Set(thread, ppos++, jt);
420 } else {
421 elements->Set(thread, epos++, jt);
422 }
423 }
424 });
425 }
426
GetDatasIgnoreType(JSThread * thread,const JSPandaFile * jsPandaFile,panda_file::File::EntityId index,JSHandle<ConstantPool> constpool,const CString & entryPoint)427 JSHandle<TaggedArray> LiteralDataExtractor::GetDatasIgnoreType(JSThread *thread, const JSPandaFile *jsPandaFile,
428 panda_file::File::EntityId index,
429 JSHandle<ConstantPool> constpool,
430 const CString &entryPoint)
431 {
432 EcmaVM *vm = thread->GetEcmaVM();
433 ObjectFactory *factory = vm->GetFactory();
434
435 LOG_ECMA(VERBOSE) << "Panda File" << jsPandaFile->GetJSPandaFileDesc();
436 const panda_file::File *pf = jsPandaFile->GetPandaFile();
437 panda_file::File::EntityId literalArraysId = pf->GetLiteralArraysId();
438 panda_file::LiteralDataAccessor lda(*pf, literalArraysId);
439
440 uint32_t num = lda.GetLiteralValsNum(index) / 2; // 2: half
441 JSHandle<TaggedArray> literals = JSHandle<TaggedArray>(factory->NewCOWTaggedArray(num));
442 uint32_t pos = 0;
443 uint32_t methodId;
444 FunctionKind kind;
445 lda.EnumerateLiteralVals(
446 index, [literals, &pos, vm, factory, thread, jsPandaFile, &methodId, &kind, &constpool, &entryPoint]
447 (const panda_file::LiteralDataAccessor::LiteralValue &value, const LiteralTag &tag) {
448 JSTaggedValue jt = JSTaggedValue::Null();
449 switch (tag) {
450 case LiteralTag::INTEGER: {
451 jt = JSTaggedValue(std::get<uint32_t>(value));
452 break;
453 }
454 case LiteralTag::DOUBLE: {
455 jt = JSTaggedValue(std::get<double>(value));
456 break;
457 }
458 case LiteralTag::BOOL: {
459 jt = JSTaggedValue(std::get<bool>(value));
460 break;
461 }
462 case LiteralTag::STRING: {
463 const panda_file::File *pf = jsPandaFile->GetPandaFile();
464 StringData sd = pf->GetStringData(panda_file::File::EntityId(std::get<uint32_t>(value)));
465 EcmaString *str = factory->GetRawStringFromStringTable(sd.data, sd.utf16_length, sd.is_ascii,
466 MemSpaceType::OLD_SPACE);
467 jt = JSTaggedValue(str);
468 break;
469 }
470 case LiteralTag::METHOD: {
471 methodId = std::get<uint32_t>(value);
472 kind = FunctionKind::NORMAL_FUNCTION;
473 break;
474 }
475 case LiteralTag::GENERATORMETHOD: {
476 methodId = std::get<uint32_t>(value);
477 kind = FunctionKind::GENERATOR_FUNCTION;
478 break;
479 }
480 case LiteralTag::METHODAFFILIATE: {
481 uint16_t length = std::get<uint16_t>(value);
482 auto methodLiteral = jsPandaFile->FindMethodLiteral(methodId);
483 ASSERT(methodLiteral != nullptr);
484
485 JSHandle<Method> method = factory->NewMethod(methodLiteral);
486 if (jsPandaFile->IsNewVersion()) {
487 JSHandle<ConstantPool> newConstpool =
488 vm->FindOrCreateConstPool(jsPandaFile, panda_file::File::EntityId(methodId));
489 method->SetConstantPool(thread, newConstpool);
490 } else {
491 method->SetConstantPool(thread, constpool.GetTaggedValue());
492 }
493 JSHandle<JSFunction> jsFunc =
494 DefineMethodInLiteral(thread, jsPandaFile, method, kind, length, entryPoint);
495 jt = jsFunc.GetTaggedValue();
496 break;
497 }
498 case LiteralTag::ACCESSOR: {
499 JSHandle<AccessorData> accessor = factory->NewAccessorData();
500 jt = accessor.GetTaggedValue();
501 break;
502 }
503 case LiteralTag::NULLVALUE: {
504 break;
505 }
506 default: {
507 UNREACHABLE();
508 break;
509 }
510 }
511 if (tag != LiteralTag::METHOD && tag != LiteralTag::GENERATORMETHOD) {
512 literals->Set(thread, pos++, jt);
513 } else {
514 uint32_t oldLength = literals->GetLength();
515 literals->Trim(thread, oldLength - 1);
516 }
517 });
518 return literals;
519 }
520
521 // use for parsing specific literal which record TS type info
GetTypeLiteral(JSThread * thread,const JSPandaFile * jsPandaFile,panda_file::File::EntityId offset)522 JSHandle<TaggedArray> LiteralDataExtractor::GetTypeLiteral(JSThread *thread, const JSPandaFile *jsPandaFile,
523 panda_file::File::EntityId offset)
524 {
525 const panda_file::File *pf = jsPandaFile->GetPandaFile();
526 panda_file::File::EntityId literalArraysId = pf->GetLiteralArraysId();
527 panda_file::LiteralDataAccessor lda(*pf, literalArraysId);
528
529 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
530 uint32_t num = lda.GetLiteralValsNum(offset) / 2; // 2: half
531 JSHandle<TaggedArray> literals = factory->NewOldSpaceTaggedArray(num);
532 uint32_t pos = 0;
533 lda.EnumerateLiteralVals(
534 offset, [literals, &pos, factory, thread, pf]
535 (const panda_file::LiteralDataAccessor::LiteralValue &value, const LiteralTag &tag) {
536 JSTaggedValue jt = JSTaggedValue::Null();
537 switch (tag) {
538 case LiteralTag::INTEGER: {
539 jt = JSTaggedValue(bit_cast<int32_t>(std::get<uint32_t>(value)));
540 break;
541 }
542 case LiteralTag::LITERALARRAY: {
543 ASSERT(std::get<uint32_t>(value) > LITERALARRAY_VALUE_LOW_BOUNDARY);
544 jt = JSTaggedValue(std::get<uint32_t>(value));
545 break;
546 }
547 case LiteralTag::BUILTINTYPEINDEX: {
548 jt = JSTaggedValue(std::get<uint8_t>(value));
549 break;
550 }
551 case LiteralTag::STRING: {
552 StringData sd = pf->GetStringData(panda_file::File::EntityId(std::get<uint32_t>(value)));
553 EcmaString *str = factory->GetRawStringFromStringTable(sd.data, sd.utf16_length, sd.is_ascii,
554 MemSpaceType::OLD_SPACE);
555 jt = JSTaggedValue(str);
556 break;
557 }
558 default: {
559 LOG_FULL(FATAL) << "type literal should not exist LiteralTag: " << static_cast<uint8_t>(tag);
560 break;
561 }
562 }
563 literals->Set(thread, pos++, jt);
564 });
565 return literals;
566 }
567 } // namespace panda::ecmascript
568