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