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(thread, 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 case LiteralTag::ETS_IMPLEMENTS:{
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
273 // for classLiteral. The SENDABLE kind will generate new module.
274 if (module->IsSourceTextModule() && classKind == ClassKind::SENDABLE) {
275 SourceTextModule::Cast(module->GetTaggedObject())->SetSendableEnv(thread, sendableEnv);
276 }
277
278 // New FunctionTemplate
279 JSHandle<FunctionTemplate> funcTemp;
280 if (classKind == ClassKind::SENDABLE) {
281 funcTemp = factory->NewSFunctionTemplate(method, module, length);
282 } else {
283 funcTemp = factory->NewFunctionTemplate(method, module, length);
284 }
285 return funcTemp;
286 }
287
CreateJSFunctionInLiteral(EcmaVM * vm,const JSHandle<Method> & method,FunctionKind kind,ClassKind classKind)288 JSHandle<JSFunction> LiteralDataExtractor::CreateJSFunctionInLiteral(EcmaVM *vm,
289 const JSHandle<Method> &method,
290 FunctionKind kind,
291 ClassKind classKind)
292 {
293 ObjectFactory *factory = vm->GetFactory();
294 JSHandle<GlobalEnv> env = vm->GetGlobalEnv();
295 JSHandle<JSFunction> jsFunc;
296 JSHandle<JSHClass> functionClass;
297 if (classKind == ClassKind::SENDABLE) {
298 if (kind == FunctionKind::NORMAL_FUNCTION ||
299 kind == FunctionKind::GETTER_FUNCTION ||
300 kind == FunctionKind::SETTER_FUNCTION) {
301 functionClass = JSHandle<JSHClass>::Cast(env->GetSFunctionClassWithoutProto());
302 } else if (kind == FunctionKind::ASYNC_FUNCTION) {
303 functionClass = JSHandle<JSHClass>::Cast(env->GetAsyncFunctionClass());
304 } else {
305 functionClass = JSHandle<JSHClass>::Cast(env->GetGeneratorFunctionClass());
306 }
307 jsFunc = factory->NewSFunctionByHClass(method, functionClass);
308 } else {
309 if (kind == FunctionKind::NORMAL_FUNCTION ||
310 kind == FunctionKind::GETTER_FUNCTION ||
311 kind == FunctionKind::SETTER_FUNCTION) {
312 functionClass = JSHandle<JSHClass>::Cast(env->GetFunctionClassWithoutProto());
313 } else if (kind == FunctionKind::ASYNC_FUNCTION) {
314 functionClass = JSHandle<JSHClass>::Cast(env->GetAsyncFunctionClass());
315 } else {
316 functionClass = JSHandle<JSHClass>::Cast(env->GetGeneratorFunctionClass());
317 }
318 jsFunc = factory->NewJSFunctionByHClass(method, functionClass, MemSpaceType::OLD_SPACE);
319 }
320 return jsFunc;
321 }
322
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)323 JSHandle<JSFunction> LiteralDataExtractor::DefineMethodInLiteral(JSThread *thread, const JSPandaFile *jsPandaFile,
324 uint32_t offset, JSHandle<ConstantPool> constpool,
325 FunctionKind kind, uint16_t length,
326 const CString &entryPoint,
327 bool isLoadedAOT, uint32_t entryIndex,
328 JSHandle<JSTaggedValue> sendableEnv,
329 ClassKind classKind)
330 {
331 EcmaVM *vm = thread->GetEcmaVM();
332 ObjectFactory *factory = vm->GetFactory();
333
334 auto methodLiteral = jsPandaFile->FindMethodLiteral(offset);
335 CHECK_INPUT_NULLPTR(methodLiteral,
336 "DefineMethodInLiteral:methodLiteral is nullptr, offset: " + std::to_string(offset));
337 FunctionKind literalKind = methodLiteral->GetFunctionKind();
338 if (literalKind == FunctionKind::NONE_FUNCTION || classKind == ClassKind::SENDABLE) {
339 methodLiteral->SetFunctionKind(kind);
340 } else {
341 kind = literalKind;
342 }
343 bool canFastCall = false;
344 JSHandle<Method> method =
345 factory->NewSMethod(jsPandaFile, methodLiteral, constpool, entryIndex, isLoadedAOT, &canFastCall);
346 if (classKind == ClassKind::SENDABLE) {
347 method->SetIsSendable(true);
348 }
349 JSHandle<JSHClass> functionClass;
350 JSHandle<JSFunction> jsFunc = CreateJSFunctionInLiteral(vm, method, kind, classKind);
351 JSHandle<JSTaggedValue> module = SharedModuleManager::GetInstance()->GenerateFuncModule(thread, jsPandaFile,
352 entryPoint, classKind);
353
354 // for objectLiteral and arrayLiteral. The NON_SENDABLE kind does not need to reset sendableEnv.
355 if (module->IsSourceTextModule() && classKind == ClassKind::SENDABLE) {
356 SourceTextModule::Cast(module->GetTaggedObject())->SetSendableEnv(thread, sendableEnv);
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(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(thread, 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(thread, 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 case LiteralTag::ETS_IMPLEMENTS:{
581 StringData sd = jsPandaFile->GetStringData(EntityId(std::get<uint32_t>(value)));
582 EcmaString *str = factory->GetRawStringFromStringTable(sd, MemSpaceType::SHARED_OLD_SPACE);
583 jt = JSTaggedValue(str);
584 break;
585 }
586 case LiteralTag::METHOD: {
587 methodId = std::get<uint32_t>(value);
588 kind = FunctionKind::NORMAL_FUNCTION;
589 break;
590 }
591 case LiteralTag::GETTER: {
592 methodId = std::get<uint32_t>(value);
593 kind = FunctionKind::GETTER_FUNCTION;
594 break;
595 }
596 case LiteralTag::SETTER: {
597 methodId = std::get<uint32_t>(value);
598 kind = FunctionKind::SETTER_FUNCTION;
599 break;
600 }
601 case LiteralTag::GENERATORMETHOD: {
602 methodId = std::get<uint32_t>(value);
603 kind = FunctionKind::GENERATOR_FUNCTION;
604 break;
605 }
606 case LiteralTag::ASYNCGENERATORMETHOD: {
607 methodId = std::get<uint32_t>(value);
608 kind = FunctionKind::ASYNC_GENERATOR_FUNCTION;
609 break;
610 }
611 case LiteralTag::METHODAFFILIATE: {
612 uint16_t length = std::get<uint16_t>(value);
613 int entryIndex = 0;
614 bool needSetAotFlag = isLoadedAOT;
615 if (isLoadedAOT) {
616 entryIndex = entryIndexes->GetObjectFromCache(thread, index++).GetInt();
617 if (entryIndex == -1) {
618 needSetAotFlag = false;
619 }
620 }
621 JSHandle<FunctionTemplate> funcTemp = DefineFunctionTemplate(thread, jsPandaFile, methodId,
622 constpool, kind, length, entryPoint, needSetAotFlag, entryIndex, sendableEnv, classKind);
623 jt = funcTemp.GetTaggedValue();
624 break;
625 }
626 case LiteralTag::ACCESSOR: {
627 JSHandle<AccessorData> accessor = factory->NewAccessorData();
628 jt = accessor.GetTaggedValue();
629 break;
630 }
631 case LiteralTag::LITERALARRAY: {
632 jt = JSTaggedValue(std::get<uint32_t>(value));
633 break;
634 }
635 case LiteralTag::NULLVALUE: {
636 break;
637 }
638 default: {
639 LOG_ECMA(FATAL) << "this branch is unreachable";
640 UNREACHABLE();
641 break;
642 }
643 }
644 if (tag != LiteralTag::METHOD && tag != LiteralTag::GETTER && tag != LiteralTag::SETTER &&
645 tag != LiteralTag::GENERATORMETHOD && tag != LiteralTag::ASYNCGENERATORMETHOD) {
646 if (newKind != nullptr) {
647 *newKind = Elements::ToElementsKind(jt, *newKind);
648 }
649 literals->Set(thread, pos++, jt);
650 } else {
651 uint32_t oldLength = literals->GetLength();
652 ASSERT(oldLength > 0);
653 literals->Trim(thread, oldLength - 1);
654 }
655 });
656 return literals;
657 }
658 } // namespace panda::ecmascript
659