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
23 namespace panda::ecmascript {
24 using LiteralTag = panda_file::LiteralTag;
25 using StringData = panda_file::StringData;
26 using LiteralDataAccessor = panda_file::LiteralDataAccessor;
27 using LiteralValue = panda_file::LiteralDataAccessor::LiteralValue;
28
ExtractObjectDatas(JSThread * thread,const JSPandaFile * jsPandaFile,size_t index,JSMutableHandle<TaggedArray> elements,JSMutableHandle<TaggedArray> properties,JSHandle<ConstantPool> constpool,const CString & entryPoint)29 void 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
GetDatasIgnoreTypeForClass(JSThread * thread,const JSPandaFile * jsPandaFile,size_t index,JSHandle<ConstantPool> constpool,const CString & entryPoint)130 JSHandle<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
GetDatasIgnoreType(JSThread * thread,const JSPandaFile * jsPandaFile,size_t index,JSHandle<ConstantPool> constpool,const CString & entryPoint)143 JSHandle<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
EnumerateLiteralVals(JSThread * thread,LiteralDataAccessor & lda,const JSPandaFile * jsPandaFile,size_t index,JSHandle<ConstantPool> constpool,const CString & entryPoint)151 JSHandle<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
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 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
CreateJSFunctionInLiteral(EcmaVM * vm,const JSHandle<Method> & method,FunctionKind kind,ClassKind classKind)286 JSHandle<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
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)321 JSHandle<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 jsFunc->SetModule(thread, module.GetTaggedValue());
355 jsFunc->SetLength(length);
356 return jsFunc;
357 }
358
GetMethodOffsets(const JSPandaFile * jsPandaFile,size_t index,std::vector<uint32_t> & methodOffsets)359 void LiteralDataExtractor::GetMethodOffsets(const JSPandaFile *jsPandaFile, size_t index,
360 std::vector<uint32_t> &methodOffsets)
361 {
362 LiteralDataAccessor lda = jsPandaFile->GetLiteralDataAccessor();
363 lda.EnumerateLiteralVals(index, [&methodOffsets](const LiteralValue &value, const LiteralTag &tag) {
364 switch (tag) {
365 case LiteralTag::METHOD:
366 case LiteralTag::GETTER:
367 case LiteralTag::SETTER:
368 case LiteralTag::ASYNCGENERATORMETHOD:
369 case LiteralTag::GENERATORMETHOD: {
370 methodOffsets.emplace_back(std::get<uint32_t>(value));
371 break;
372 }
373 default: {
374 break;
375 }
376 }
377 });
378 }
379
GetMethodOffsets(const JSPandaFile * jsPandaFile,EntityId id,std::vector<uint32_t> & methodOffsets)380 void LiteralDataExtractor::GetMethodOffsets(const JSPandaFile *jsPandaFile, EntityId id,
381 std::vector<uint32_t> &methodOffsets)
382 {
383 LiteralDataAccessor lda = jsPandaFile->GetLiteralDataAccessor();
384 lda.EnumerateLiteralVals(id, [&methodOffsets](const LiteralValue &value, const LiteralTag &tag) {
385 switch (tag) {
386 case LiteralTag::METHOD:
387 case LiteralTag::GETTER:
388 case LiteralTag::SETTER:
389 case LiteralTag::ASYNCGENERATORMETHOD:
390 case LiteralTag::GENERATORMETHOD: {
391 methodOffsets.emplace_back(std::get<uint32_t>(value));
392 break;
393 }
394 default: {
395 break;
396 }
397 }
398 });
399 }
400
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)401 void LiteralDataExtractor::ExtractObjectDatas(JSThread *thread, const JSPandaFile *jsPandaFile, EntityId id,
402 JSMutableHandle<TaggedArray> elements,
403 JSMutableHandle<TaggedArray> properties,
404 JSHandle<ConstantPool> constpool, const CString &entry,
405 bool isLoadedAOT, JSHandle<AOTLiteralInfo> entryIndexes)
406 {
407 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
408 LiteralDataAccessor lda = jsPandaFile->GetLiteralDataAccessor();
409 uint32_t num = lda.GetLiteralValsNum(id) / 2; // 2: half
410 elements.Update(factory->NewOldSpaceTaggedArray(num).GetTaggedValue());
411 properties.Update(factory->NewOldSpaceTaggedArray(num).GetTaggedValue());
412 uint32_t epos = 0;
413 uint32_t ppos = 0;
414 const uint8_t pairSize = 2;
415 uint32_t methodId = 0;
416 int pos = 0;
417 FunctionKind kind;
418 lda.EnumerateLiteralVals(
419 id, [elements, properties, &entryIndexes, &pos, &epos, &ppos, factory, thread, jsPandaFile,
420 &methodId, &kind, &constpool, &entry, &isLoadedAOT](const LiteralValue &value, const LiteralTag &tag) {
421 JSTaggedValue jt = JSTaggedValue::Null();
422 bool flag = false;
423 switch (tag) {
424 case LiteralTag::INTEGER: {
425 jt = JSTaggedValue(std::get<uint32_t>(value));
426 break;
427 }
428 case LiteralTag::DOUBLE: {
429 jt = JSTaggedValue(std::get<double>(value));
430 break;
431 }
432 case LiteralTag::BOOL: {
433 jt = JSTaggedValue(std::get<bool>(value));
434 break;
435 }
436 case LiteralTag::STRING: {
437 StringData sd = jsPandaFile->GetStringData(EntityId(std::get<uint32_t>(value)));
438 EcmaString *str = factory->GetRawStringFromStringTable(sd, MemSpaceType::SHARED_OLD_SPACE);
439 jt = JSTaggedValue(str);
440 uint32_t elementIndex = 0;
441 if (JSTaggedValue::ToElementIndex(jt, &elementIndex) && ppos % pairSize == 0) {
442 flag = true;
443 }
444 break;
445 }
446 case LiteralTag::METHOD: {
447 methodId = std::get<uint32_t>(value);
448 kind = FunctionKind::NORMAL_FUNCTION;
449 break;
450 }
451 case LiteralTag::GETTER: {
452 methodId = std::get<uint32_t>(value);
453 kind = FunctionKind::GETTER_FUNCTION;
454 break;
455 }
456 case LiteralTag::SETTER: {
457 methodId = std::get<uint32_t>(value);
458 kind = FunctionKind::SETTER_FUNCTION;
459 break;
460 }
461 case LiteralTag::GENERATORMETHOD: {
462 methodId = std::get<uint32_t>(value);
463 kind = FunctionKind::GENERATOR_FUNCTION;
464 break;
465 }
466
467 case LiteralTag::ASYNCGENERATORMETHOD: {
468 methodId = std::get<uint32_t>(value);
469 kind = FunctionKind::ASYNC_GENERATOR_FUNCTION;
470 break;
471 }
472
473 case LiteralTag::METHODAFFILIATE: {
474 uint16_t length = std::get<uint16_t>(value);
475 int entryIndex = 0;
476 bool needSetAotFlag = (isLoadedAOT && (epos % pairSize == 0) && !flag);
477 if (needSetAotFlag) {
478 entryIndex = entryIndexes->GetObjectFromCache(pos++).GetInt();
479 // -1 : this jsfunction is a large function
480 if (entryIndex == -1) {
481 needSetAotFlag = false;
482 }
483 }
484 JSHandle<JSFunction> jsFunc =
485 DefineMethodInLiteral(thread, jsPandaFile, methodId, constpool, kind,
486 length, entry, needSetAotFlag, entryIndex);
487 jt = jsFunc.GetTaggedValue();
488 break;
489 }
490 case LiteralTag::ACCESSOR: {
491 JSHandle<AccessorData> accessor = factory->NewAccessorData();
492 jt = accessor.GetTaggedValue();
493 break;
494 }
495 case LiteralTag::NULLVALUE: {
496 break;
497 }
498 default: {
499 LOG_ECMA(FATAL) << "this branch is unreachable";
500 UNREACHABLE();
501 break;
502 }
503 }
504 if (tag != LiteralTag::METHOD && tag != LiteralTag::GETTER && tag != LiteralTag::SETTER &&
505 tag != LiteralTag::GENERATORMETHOD && tag != LiteralTag::ASYNCGENERATORMETHOD) {
506 if ((epos % pairSize == 0) && !flag) {
507 properties->Set(thread, ppos++, jt);
508 } else {
509 elements->Set(thread, epos++, jt);
510 }
511 }
512 });
513 }
514
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)515 JSHandle<TaggedArray> LiteralDataExtractor::GetDatasIgnoreTypeForClass(JSThread *thread, const JSPandaFile *jsPandaFile,
516 EntityId id, JSHandle<ConstantPool> constpool,
517 const CString &entryPoint, bool isLoadedAOT,
518 JSHandle<AOTLiteralInfo> entryIndexes,
519 ElementsKind *newKind,
520 JSHandle<JSTaggedValue> sendableEnv,
521 ClassKind classKind)
522 {
523 ASSERT(jsPandaFile != nullptr);
524 LiteralDataAccessor lda = jsPandaFile->GetLiteralDataAccessor();
525 uint32_t num = lda.GetLiteralValsNum(id) / 2; // 2: half
526 // The num is 1, indicating that the current class has no member variable.
527 if (num == 1) {
528 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
529 return factory->EmptyArray();
530 }
531 return GetDatasIgnoreType(
532 thread, jsPandaFile, id, constpool, entryPoint, isLoadedAOT, entryIndexes, newKind, sendableEnv, classKind);
533 }
534
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)535 JSHandle<TaggedArray> LiteralDataExtractor::GetDatasIgnoreType(JSThread *thread, const JSPandaFile *jsPandaFile,
536 EntityId id, JSHandle<ConstantPool> constpool,
537 const CString &entryPoint, bool isLoadedAOT,
538 JSHandle<AOTLiteralInfo> entryIndexes,
539 ElementsKind *newKind,
540 JSHandle<JSTaggedValue> sendableEnv,
541 ClassKind classKind)
542 {
543 ASSERT(jsPandaFile != nullptr);
544 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
545 LiteralDataAccessor lda = jsPandaFile->GetLiteralDataAccessor();
546 uint32_t num = lda.GetLiteralValsNum(id) / 2; // 2: half
547 JSHandle<TaggedArray> literals;
548 if (classKind == ClassKind::SENDABLE) {
549 literals = JSHandle<TaggedArray>(factory->NewSCOWTaggedArray(num));
550 } else {
551 literals = JSHandle<TaggedArray>(factory->NewCOWTaggedArray(num));
552 }
553 uint32_t pos = 0;
554 uint32_t methodId = 0;
555 FunctionKind kind;
556 int index = 0;
557 lda.EnumerateLiteralVals(
558 id, [literals, &pos, factory, thread, jsPandaFile, &methodId, &kind, &constpool,
559 &entryPoint, &entryIndexes, &index, isLoadedAOT, newKind, classKind, &sendableEnv]
560 (const LiteralValue &value, const LiteralTag &tag) {
561 JSTaggedValue jt = JSTaggedValue::Null();
562 switch (tag) {
563 case LiteralTag::INTEGER: {
564 jt = JSTaggedValue(std::get<uint32_t>(value));
565 break;
566 }
567 case LiteralTag::DOUBLE: {
568 jt = JSTaggedValue(std::get<double>(value));
569 break;
570 }
571 case LiteralTag::BOOL: {
572 jt = JSTaggedValue(std::get<bool>(value));
573 break;
574 }
575 case LiteralTag::STRING: {
576 StringData sd = jsPandaFile->GetStringData(EntityId(std::get<uint32_t>(value)));
577 EcmaString *str = factory->GetRawStringFromStringTable(sd, MemSpaceType::SHARED_OLD_SPACE);
578 jt = JSTaggedValue(str);
579 break;
580 }
581 case LiteralTag::METHOD: {
582 methodId = std::get<uint32_t>(value);
583 kind = FunctionKind::NORMAL_FUNCTION;
584 break;
585 }
586 case LiteralTag::GETTER: {
587 methodId = std::get<uint32_t>(value);
588 kind = FunctionKind::GETTER_FUNCTION;
589 break;
590 }
591 case LiteralTag::SETTER: {
592 methodId = std::get<uint32_t>(value);
593 kind = FunctionKind::SETTER_FUNCTION;
594 break;
595 }
596 case LiteralTag::GENERATORMETHOD: {
597 methodId = std::get<uint32_t>(value);
598 kind = FunctionKind::GENERATOR_FUNCTION;
599 break;
600 }
601 case LiteralTag::ASYNCGENERATORMETHOD: {
602 methodId = std::get<uint32_t>(value);
603 kind = FunctionKind::ASYNC_GENERATOR_FUNCTION;
604 break;
605 }
606 case LiteralTag::METHODAFFILIATE: {
607 uint16_t length = std::get<uint16_t>(value);
608 int entryIndex = 0;
609 bool needSetAotFlag = isLoadedAOT;
610 if (isLoadedAOT) {
611 entryIndex = entryIndexes->GetObjectFromCache(index++).GetInt();
612 if (entryIndex == -1) {
613 needSetAotFlag = false;
614 }
615 }
616 JSHandle<FunctionTemplate> funcTemp = DefineFunctionTemplate(thread, jsPandaFile, methodId,
617 constpool, kind, length, entryPoint, needSetAotFlag, entryIndex, sendableEnv, classKind);
618 jt = funcTemp.GetTaggedValue();
619 break;
620 }
621 case LiteralTag::ACCESSOR: {
622 JSHandle<AccessorData> accessor = factory->NewAccessorData();
623 jt = accessor.GetTaggedValue();
624 break;
625 }
626 case LiteralTag::LITERALARRAY: {
627 jt = JSTaggedValue(std::get<uint32_t>(value));
628 break;
629 }
630 case LiteralTag::NULLVALUE: {
631 break;
632 }
633 default: {
634 LOG_ECMA(FATAL) << "this branch is unreachable";
635 UNREACHABLE();
636 break;
637 }
638 }
639 if (tag != LiteralTag::METHOD && tag != LiteralTag::GETTER && tag != LiteralTag::SETTER &&
640 tag != LiteralTag::GENERATORMETHOD && tag != LiteralTag::ASYNCGENERATORMETHOD) {
641 if (newKind != nullptr) {
642 *newKind = Elements::ToElementsKind(jt, *newKind);
643 }
644 literals->Set(thread, pos++, jt);
645 } else {
646 uint32_t oldLength = literals->GetLength();
647 ASSERT(oldLength > 0);
648 literals->Trim(thread, oldLength - 1);
649 }
650 });
651 return literals;
652 }
653 } // namespace panda::ecmascript
654