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