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 "pandagen.h"
17
18 #include <compiler/base/catchTable.h>
19 #include <compiler/base/lexenv.h>
20 #include <compiler/base/literals.h>
21 #include <compiler/core/compilerContext.h>
22 #include <compiler/function/asyncGeneratorFunctionBuilder.h>
23 #include <compiler/function/generatorFunctionBuilder.h>
24 #include <ir/base/classDefinition.h>
25 #include <ir/base/scriptFunction.h>
26 #include <ir/base/spreadElement.h>
27 #include <ir/expressions/callExpression.h>
28 #include <ir/expressions/functionExpression.h>
29 #include <ir/expressions/literals/numberLiteral.h>
30 #include <ir/expressions/literals/stringLiteral.h>
31 #include <ir/expressions/newExpression.h>
32 #include <ir/module/importSpecifier.h>
33 #include <ir/module/importDefaultSpecifier.h>
34
35 namespace panda::es2panda::compiler {
36
37 // PandaGen
38
SetFunctionKind()39 void PandaGen::SetFunctionKind()
40 {
41 int targetApiVersion = Binder()->Program()->TargetApiVersion();
42 if (rootNode_->IsProgram()) {
43 funcKind_ = panda::panda_file::FunctionKind::FUNCTION;
44 return;
45 }
46
47 auto *func = rootNode_->AsScriptFunction();
48 if (func->IsConcurrent()) {
49 funcKind_ = panda::panda_file::FunctionKind::CONCURRENT_FUNCTION;
50 return;
51 }
52
53 if (func->IsMethod()) {
54 if (func->IsAsync()) {
55 funcKind_ = panda::panda_file::FunctionKind::ASYNC_FUNCTION;
56 }
57 return;
58 }
59
60 if (func->IsAsync()) {
61 if (func->IsGenerator()) {
62 funcKind_ = panda::panda_file::FunctionKind::ASYNC_GENERATOR_FUNCTION;
63 return;
64 }
65
66 if (func->IsArrow()) {
67 funcKind_ = panda::panda_file::FunctionKind::ASYNC_NC_FUNCTION;
68 return;
69 }
70
71 funcKind_ = panda::panda_file::FunctionKind::ASYNC_FUNCTION;
72
73 if (func->IsSendable() && targetApiVersion >= util::Helpers::SENDABLE_FUNCTION_MIN_SUPPORTED_API_VERSION) {
74 funcKind_ |= panda::panda_file::FunctionKind::SENDABLE_FUNCTION;
75 }
76 return;
77 }
78
79 if (func->IsGenerator()) {
80 funcKind_ = panda::panda_file::FunctionKind::GENERATOR_FUNCTION;
81 return;
82 }
83
84 if (func->IsArrow()) {
85 funcKind_ = panda::panda_file::FunctionKind::NC_FUNCTION;
86 return;
87 }
88
89 funcKind_ = panda::panda_file::FunctionKind::FUNCTION;
90
91 if (func->IsSendable() && targetApiVersion >= util::Helpers::SENDABLE_FUNCTION_MIN_SUPPORTED_API_VERSION) {
92 funcKind_ |= panda::panda_file::FunctionKind::SENDABLE_FUNCTION;
93 }
94 }
95
SetInSendable()96 void PandaGen::SetInSendable()
97 {
98 if (rootNode_->IsProgram()) {
99 return;
100 }
101
102 auto *func = rootNode_->AsScriptFunction();
103 inSendable_ = func->InSendable();
104 }
105
GetExpectedPropertyCount() const106 size_t PandaGen::GetExpectedPropertyCount() const
107 {
108 if (rootNode_->IsProgram() ||
109 !util::Helpers::IsEnableExpectedPropertyCountApiVersion(context_->Binder()->Program()->TargetApiVersion())) {
110 return 0;
111 }
112
113 auto *func = rootNode_->AsScriptFunction();
114 /**
115 * The expected property count only includes class fields and properties declared in the constructor.
116 * Properties defined in regular methods are not counted because they are only dynamically added
117 * to the instance after the method is called, and are not part of the instance during creation.
118 */
119 if (func->IsConstructor()) {
120 return util::Helpers::GetClassDefiniton(func)->ExpectedPropertyCount();
121 }
122 if (func->IsMethod()) {
123 return 0;
124 }
125
126 return func->ExpectedPropertyCount();
127 }
128
AllocLabel()129 Label *PandaGen::AllocLabel()
130 {
131 std::string id = std::string {Label::PREFIX} + std::to_string(labelId_++);
132 return ra_.AllocLabel(std::move(id));
133 }
134
IsDebug() const135 bool PandaGen::IsDebug() const
136 {
137 return context_->IsDebug();
138 }
139
EnableColumn() const140 bool PandaGen::EnableColumn() const
141 {
142 return context_->EnableColumn();
143 }
144
isDebuggerEvaluateExpressionMode() const145 bool PandaGen::isDebuggerEvaluateExpressionMode() const
146 {
147 return context_->isDebuggerEvaluateExpressionMode();
148 }
149
SourceFile() const150 std::string PandaGen::SourceFile() const
151 {
152 return context_->SourceFile();
153 }
154
ParamCount() const155 uint32_t PandaGen::ParamCount() const
156 {
157 if (rootNode_->IsProgram()) {
158 return 0;
159 }
160
161 return rootNode_->AsScriptFunction()->Params().size();
162 }
163
FormalParametersCount() const164 uint32_t PandaGen::FormalParametersCount() const
165 {
166 if (rootNode_->IsProgram()) {
167 return 0;
168 }
169
170 ASSERT(rootNode_->IsScriptFunction());
171
172 return rootNode_->AsScriptFunction()->FormalParamsLength();
173 }
174
InternalParamCount() const175 uint32_t PandaGen::InternalParamCount() const
176 {
177 if (rootNode_->IsProgram() && context_->Binder()->Program()->IsCommonjs()) {
178 return binder::Binder::CJS_MANDATORY_PARAMS_NUMBER;
179 }
180 return ParamCount() + binder::Binder::MANDATORY_PARAMS_NUMBER;
181 }
182
InternalName() const183 const util::StringView &PandaGen::InternalName() const
184 {
185 return topScope_->InternalName();
186 }
187
FunctionName() const188 const util::StringView &PandaGen::FunctionName() const
189 {
190 return topScope_->Name();
191 }
192
Binder() const193 binder::Binder *PandaGen::Binder() const
194 {
195 return context_->Binder();
196 }
197
SourceLang() const198 pandasm::extensions::Language PandaGen::SourceLang() const
199 {
200 return context_->SourceLang();
201 }
202
FunctionInit(CatchTable * catchTable)203 void PandaGen::FunctionInit(CatchTable *catchTable)
204 {
205 if (rootNode_->IsProgram()) {
206 if (context_->Binder()->Program()->HasTLA()) {
207 builder_ = allocator_->New<AsyncFunctionBuilder>(this, catchTable);
208 } else {
209 builder_ = allocator_->New<FunctionBuilder>(this, catchTable);
210 }
211 return;
212 }
213
214 const ir::ScriptFunction *func = rootNode_->AsScriptFunction();
215
216 if (func->IsAsync()) {
217 if (func->IsGenerator()) {
218 builder_ = allocator_->New<AsyncGeneratorFunctionBuilder>(this, catchTable);
219 return;
220 }
221
222 builder_ = allocator_->New<AsyncFunctionBuilder>(this, catchTable);
223 return;
224 }
225
226 if (func->IsGenerator()) {
227 builder_ = allocator_->New<GeneratorFunctionBuilder>(this, catchTable);
228 return;
229 }
230
231 builder_ = allocator_->New<FunctionBuilder>(this, catchTable);
232 }
233
FunctionHasFinalizer() const234 bool PandaGen::FunctionHasFinalizer() const
235 {
236 if (rootNode_->IsProgram()) {
237 return context_->Binder()->Program()->HasTLA();
238 }
239
240 const ir::ScriptFunction *func = rootNode_->AsScriptFunction();
241
242 return func->IsAsync() || func->IsGenerator();
243 }
244
IsAsyncFunction() const245 bool PandaGen::IsAsyncFunction() const
246 {
247 if (rootNode_->IsProgram() && context_->Binder()->Program()->HasTLA()) {
248 return true;
249 }
250 const ir::ScriptFunction *func = rootNode_->AsScriptFunction();
251 return func->IsAsync() && !func->IsGenerator();
252 }
253
FunctionEnter()254 void PandaGen::FunctionEnter()
255 {
256 if (rootNode_->IsProgram() && context_->Binder()->Program()->HasTLA()) {
257 builder_->Prepare(nullptr);
258 return;
259 }
260 builder_->Prepare(rootNode_->AsScriptFunction());
261 }
262
FunctionExit()263 void PandaGen::FunctionExit()
264 {
265 if (rootNode_->IsProgram() && context_->Binder()->Program()->HasTLA()) {
266 builder_->CleanUp(nullptr);
267 return;
268 }
269 builder_->CleanUp(rootNode_->AsScriptFunction());
270 }
271
InitializeLexEnv(const ir::AstNode * node)272 void PandaGen::InitializeLexEnv(const ir::AstNode *node)
273 {
274 FrontAllocator fa(this);
275
276 if (topScope_->NeedLexEnv()) {
277 NewLexicalEnv(node, topScope_->LexicalSlots(), topScope_);
278 }
279
280 if (topScope_->NeedSendableEnv()) {
281 NewSendableEnv(node, topScope_->SendableSlots());
282 }
283 }
284
CopyFunctionArguments(const ir::AstNode * node)285 void PandaGen::CopyFunctionArguments(const ir::AstNode *node)
286 {
287 FrontAllocator fa(this);
288 VReg targetReg = totalRegs_;
289
290 for (const auto *param : topScope_->ParamScope()->Params()) {
291 if (param->LexicalBound()) {
292 StoreLexicalVar(node, 0, param->LexIdx(), targetReg++);
293 continue;
294 }
295 MoveVreg(node, param->Vreg(), targetReg++);
296 }
297 }
298
NewLiteralBuffer()299 LiteralBuffer *PandaGen::NewLiteralBuffer()
300 {
301 LiteralBuffer *buf = allocator_->New<LiteralBuffer>(allocator_);
302 CHECK_NOT_NULL(buf);
303 return buf;
304 }
305
AddLiteralBuffer(LiteralBuffer * buf)306 int32_t PandaGen::AddLiteralBuffer(LiteralBuffer *buf)
307 {
308 CHECK_NOT_NULL(buf);
309 buffStorage_.push_back(buf);
310 buf->SetIndex(context_->NewLiteralIndex());
311 return buf->Index();
312 }
313
AddLexicalVarNamesForDebugInfo(ArenaMap<uint32_t,std::pair<util::StringView,int>> & lexicalVars)314 int32_t PandaGen::AddLexicalVarNamesForDebugInfo(ArenaMap<uint32_t, std::pair<util::StringView, int>> &lexicalVars)
315 {
316 auto *buf = NewLiteralBuffer();
317 buf->Add(Allocator()->New<ir::NumberLiteral>(lexicalVars.size()));
318 for (auto &iter : lexicalVars) {
319 // The slot is set to UINT32_MAX when the variable is a patchvar while its value is not stored in the slot
320 // The patchvar info should not be added to the DebugInfo since its value cannot be found in slot UINT32_MAX
321 if (iter.first != UINT32_MAX) {
322 buf->Add(Allocator()->New<ir::StringLiteral>(iter.second.first));
323 buf->Add(Allocator()->New<ir::NumberLiteral>(iter.first));
324 }
325 }
326 return AddLiteralBuffer(buf);
327 }
328
GetFunctionObject(const ir::AstNode * node)329 void PandaGen::GetFunctionObject(const ir::AstNode *node)
330 {
331 LoadAccFromLexEnv(node, scope_->Find(binder::Binder::MANDATORY_PARAM_FUNC));
332 }
333
GetNewTarget(const ir::AstNode * node)334 void PandaGen::GetNewTarget(const ir::AstNode *node)
335 {
336 LoadAccFromLexEnv(node, scope_->Find(binder::Binder::MANDATORY_PARAM_NEW_TARGET));
337 }
338
GetThis(const ir::AstNode * node)339 void PandaGen::GetThis(const ir::AstNode *node)
340 {
341 LoadAccFromLexEnv(node, scope_->Find(binder::Binder::MANDATORY_PARAM_THIS));
342 }
343
SetThis(const ir::AstNode * node)344 void PandaGen::SetThis(const ir::AstNode *node)
345 {
346 StoreAccToLexEnv(node, scope_->Find(binder::Binder::MANDATORY_PARAM_THIS), true);
347 }
348
LoadVar(const ir::Identifier * node,const binder::ScopeFindResult & result)349 void PandaGen::LoadVar(const ir::Identifier *node, const binder::ScopeFindResult &result)
350 {
351 auto *var = result.variable;
352
353 if (!var || var->Declaration()->IsDeclare()) {
354 TryLoadGlobalByName(node, result.name);
355 return;
356 }
357
358 if (var->IsGlobalVariable()) {
359 LoadGlobalVar(node, var->Name());
360 return;
361 }
362
363 if (var->IsModuleVariable()) {
364 var->HasFlag(binder::VariableFlags::LOCAL_EXPORT) ? LoadLocalModuleVariable(node, var->AsModuleVariable()) :
365 LoadExternalModuleVariable(node, var->AsModuleVariable());
366 if (var->Declaration()->IsLetOrConstOrClassDecl()) {
367 ThrowUndefinedIfHole(node, var->Name());
368 }
369 return;
370 }
371
372 ASSERT(var->IsLocalVariable());
373
374 if (var->Declaration()->IsLetOrConstOrClassDecl() && result.scope->IsGlobalScope()) {
375 TryLoadGlobalByName(node, result.name);
376 return;
377 }
378
379 LoadAccFromLexEnv(node, result);
380 }
381
StoreVar(const ir::AstNode * node,const binder::ScopeFindResult & result,bool isDeclaration)382 void PandaGen::StoreVar(const ir::AstNode *node, const binder::ScopeFindResult &result, bool isDeclaration)
383 {
384 binder::Variable *var = result.variable;
385
386 if (!var) {
387 TryStoreGlobalByName(node, result.name);
388 return;
389 }
390
391 if (var->IsGlobalVariable()) {
392 StoreGlobalVar(node, var->Name());
393 return;
394 }
395
396 if (var->IsModuleVariable()) {
397 if (!isDeclaration && var->Declaration()->IsConstDecl()) {
398 ThrowConstAssignment(node, var->Name());
399 return;
400 }
401
402 if (!isDeclaration &&
403 (var->Declaration()->IsLetDecl() || var->Declaration()->IsClassDecl())) {
404 RegScope rs(this);
405 VReg valueReg = AllocReg();
406 StoreAccumulator(node, valueReg);
407 LoadLocalModuleVariable(node, var->AsModuleVariable());
408 ThrowUndefinedIfHole(node, var->Name());
409 LoadAccumulator(node, valueReg);
410 }
411
412 StoreModuleVariable(node, var->AsModuleVariable());
413 return;
414 }
415
416 ASSERT(var->IsLocalVariable());
417
418 if (var->Declaration()->IsLetOrConstOrClassDecl() && result.scope->IsGlobalScope()) {
419 if (!isDeclaration) {
420 TryStoreGlobalByName(node, var->Name());
421 } else if (var->Declaration()->IsLetDecl() || var->Declaration()->IsClassDecl()) {
422 StLetOrClassToGlobalRecord(node, var->Name());
423 } else if (var->Declaration()->IsConstDecl()) {
424 StConstToGlobalRecord(node, var->Name());
425 }
426
427 return;
428 }
429
430 StoreAccToLexEnv(node, result, isDeclaration);
431 }
432
StoreAccumulator(const ir::AstNode * node,VReg vreg)433 void PandaGen::StoreAccumulator(const ir::AstNode *node, VReg vreg)
434 {
435 ra_.Emit<Sta>(node, vreg);
436 }
437
LoadAccFromArgs(const ir::AstNode * node)438 void PandaGen::LoadAccFromArgs(const ir::AstNode *node)
439 {
440 const auto *varScope = scope_->AsVariableScope();
441
442 if (!varScope->HasFlag(binder::VariableScopeFlags::USE_ARGS)) {
443 return;
444 }
445
446 binder::ScopeFindResult res = scope_->Find(binder::Binder::FUNCTION_ARGUMENTS);
447 ASSERT(res.scope);
448
449 GetUnmappedArgs(node);
450 StoreAccToLexEnv(node, res, true);
451 }
452
LoadObjProperty(const ir::AstNode * node,VReg obj,const Operand & prop)453 void PandaGen::LoadObjProperty(const ir::AstNode *node, VReg obj, const Operand &prop)
454 {
455 if (std::holds_alternative<VReg>(prop)) {
456 LoadAccumulator(node, std::get<VReg>(prop));
457 LoadObjByValue(node, obj);
458 return;
459 }
460
461 if (std::holds_alternative<int64_t>(prop)) {
462 LoadObjByIndex(node, obj, std::get<int64_t>(prop));
463 return;
464 }
465
466 ASSERT(std::holds_alternative<util::StringView>(prop));
467 LoadObjByName(node, obj, std::get<util::StringView>(prop));
468 }
469
StoreObjProperty(const ir::AstNode * node,VReg obj,const Operand & prop)470 void PandaGen::StoreObjProperty(const ir::AstNode *node, VReg obj, const Operand &prop)
471 {
472 if (std::holds_alternative<VReg>(prop)) {
473 StoreObjByValue(node, obj, std::get<VReg>(prop));
474 return;
475 }
476
477 if (std::holds_alternative<int64_t>(prop)) {
478 StoreObjByIndex(node, obj, std::get<int64_t>(prop));
479 return;
480 }
481
482 ASSERT(std::holds_alternative<util::StringView>(prop));
483 StoreObjByName(node, obj, std::get<util::StringView>(prop));
484 }
485
DefineOwnProperty(const ir::AstNode * node,VReg obj,const Operand & prop)486 void PandaGen::DefineOwnProperty(const ir::AstNode *node, VReg obj, const Operand &prop)
487 {
488 if (std::holds_alternative<VReg>(prop)) {
489 DefineFieldByValue(node, obj, std::get<VReg>(prop));
490 return;
491 }
492
493 if (std::holds_alternative<int64_t>(prop)) {
494 DefineFieldByIndex(node, obj, std::get<int64_t>(prop));
495 return;
496 }
497
498 ASSERT(std::holds_alternative<util::StringView>(prop));
499 DefineFieldByName(node, obj, std::get<util::StringView>(prop));
500 }
501
DefineClassPrivateField(const ir::AstNode * node,uint32_t level,uint32_t slot,VReg obj)502 void PandaGen::DefineClassPrivateField(const ir::AstNode *node, uint32_t level, uint32_t slot, VReg obj)
503 {
504 ra_.Emit<CallruntimeDefineprivateproperty>(node, 0, level, slot, obj);
505 }
506
StoreOwnProperty(const ir::AstNode * node,VReg obj,const Operand & prop,bool nameSetting)507 void PandaGen::StoreOwnProperty(const ir::AstNode *node, VReg obj, const Operand &prop, bool nameSetting)
508 {
509 if (std::holds_alternative<VReg>(prop)) {
510 StOwnByValue(node, obj, std::get<VReg>(prop), nameSetting);
511 return;
512 }
513
514 if (std::holds_alternative<int64_t>(prop)) {
515 StOwnByIndex(node, obj, std::get<int64_t>(prop));
516 return;
517 }
518
519 ASSERT(std::holds_alternative<util::StringView>(prop));
520 StOwnByName(node, obj, std::get<util::StringView>(prop), nameSetting);
521 }
522
523 constexpr size_t DEBUGGER_GET_SET_ARGS_NUM = 2;
524
LoadObjByNameViaDebugger(const ir::AstNode * node,const util::StringView & name,bool throwUndefinedIfHole)525 void PandaGen::LoadObjByNameViaDebugger(const ir::AstNode *node, const util::StringView &name,
526 bool throwUndefinedIfHole)
527 {
528 RegScope rs(this);
529 VReg global = AllocReg();
530 LoadConst(node, compiler::Constant::JS_GLOBAL);
531 StoreAccumulator(node, global);
532 LoadObjByName(node, global, "debuggerGetValue");
533 VReg debuggerGetValueReg = AllocReg();
534 StoreAccumulator(node, debuggerGetValueReg);
535 VReg variableReg = AllocReg();
536 LoadAccumulatorString(node, name);
537 StoreAccumulator(node, variableReg);
538 VReg boolFlag = AllocReg();
539 if (throwUndefinedIfHole) {
540 LoadConst(node, compiler::Constant::JS_TRUE);
541 } else {
542 LoadConst(node, compiler::Constant::JS_FALSE);
543 }
544 StoreAccumulator(node, boolFlag);
545 Call(node, debuggerGetValueReg, DEBUGGER_GET_SET_ARGS_NUM);
546 }
547
TryLoadGlobalByName(const ir::AstNode * node,const util::StringView & name)548 void PandaGen::TryLoadGlobalByName(const ir::AstNode *node, const util::StringView &name)
549 {
550 if (isDebuggerEvaluateExpressionMode()) {
551 LoadObjByNameViaDebugger(node, name, true);
552 } else {
553 ra_.Emit<Tryldglobalbyname>(node, 0, name);
554 }
555 strings_.insert(name);
556 }
557
StoreObjByNameViaDebugger(const ir::AstNode * node,const util::StringView & name)558 void PandaGen::StoreObjByNameViaDebugger(const ir::AstNode *node, const util::StringView &name)
559 {
560 RegScope rs(this);
561 VReg valueReg = AllocReg();
562 StoreAccumulator(node, valueReg);
563 VReg global = AllocReg();
564 LoadConst(node, compiler::Constant::JS_GLOBAL);
565 StoreAccumulator(node, global);
566 LoadObjByName(node, global, "debuggerSetValue");
567 VReg debuggerSetValueReg = AllocReg();
568 StoreAccumulator(node, debuggerSetValueReg);
569 VReg variableReg = AllocReg();
570 LoadAccumulatorString(node, name);
571 StoreAccumulator(node, variableReg);
572 MoveVreg(node, AllocReg(), valueReg);
573 Call(node, debuggerSetValueReg, DEBUGGER_GET_SET_ARGS_NUM);
574 }
575
TryStoreGlobalByName(const ir::AstNode * node,const util::StringView & name)576 void PandaGen::TryStoreGlobalByName(const ir::AstNode *node, const util::StringView &name)
577 {
578 if (isDebuggerEvaluateExpressionMode()) {
579 StoreObjByNameViaDebugger(node, name);
580 } else {
581 ra_.Emit<Trystglobalbyname>(node, 0, name);
582 }
583 strings_.insert(name);
584 }
585
LoadObjByName(const ir::AstNode * node,VReg obj,const util::StringView & prop)586 void PandaGen::LoadObjByName(const ir::AstNode *node, VReg obj, const util::StringView &prop)
587 {
588 LoadAccumulator(node, obj); // object is load to acc
589 ra_.Emit<Ldobjbyname>(node, 0, prop);
590 strings_.insert(prop);
591 }
592
StoreObjByName(const ir::AstNode * node,VReg obj,const util::StringView & prop)593 void PandaGen::StoreObjByName(const ir::AstNode *node, VReg obj, const util::StringView &prop)
594 {
595 ra_.Emit<Stobjbyname>(node, 0, prop, obj);
596 strings_.insert(prop);
597 }
598
DefineFieldByName(const ir::AstNode * node,VReg obj,const util::StringView & prop)599 void PandaGen::DefineFieldByName(const ir::AstNode *node, VReg obj, const util::StringView &prop)
600 {
601 if (util::Helpers::IsDefaultApiVersion(Binder()->Program()->TargetApiVersion(),
602 Binder()->Program()->GetTargetApiSubVersion())) {
603 ra_.Emit<Definefieldbyname>(node, 0, prop, obj);
604 strings_.insert(prop);
605 return;
606 }
607
608 ra_.Emit<Definepropertybyname>(node, 0, prop, obj);
609 strings_.insert(prop);
610 }
611
LoadObjByIndex(const ir::AstNode * node,VReg obj,int64_t index)612 void PandaGen::LoadObjByIndex(const ir::AstNode *node, VReg obj, int64_t index)
613 {
614 LoadAccumulator(node, obj); // object is load to acc
615 if (index <= util::Helpers::MAX_INT16) {
616 ra_.Emit<Ldobjbyindex>(node, 0, index);
617 return;
618 }
619
620 ra_.Emit<WideLdobjbyindex>(node, index);
621 }
622
LoadObjByValue(const ir::AstNode * node,VReg obj)623 void PandaGen::LoadObjByValue(const ir::AstNode *node, VReg obj)
624 {
625 ra_.Emit<Ldobjbyvalue>(node, 0, obj); // prop is in acc
626 }
627
StoreObjByValue(const ir::AstNode * node,VReg obj,VReg prop)628 void PandaGen::StoreObjByValue(const ir::AstNode *node, VReg obj, VReg prop)
629 {
630 ra_.Emit<Stobjbyvalue>(node, 0, obj, prop);
631 }
632
StoreObjByIndex(const ir::AstNode * node,VReg obj,int64_t index)633 void PandaGen::StoreObjByIndex(const ir::AstNode *node, VReg obj, int64_t index)
634 {
635 if (index <= util::Helpers::MAX_INT16) {
636 ra_.Emit<Stobjbyindex>(node, 0, obj, index);
637 return;
638 }
639
640 ra_.Emit<WideStobjbyindex>(node, obj, index);
641 }
642
DefineFieldByValue(const ir::AstNode * node,VReg obj,VReg prop)643 void PandaGen::DefineFieldByValue(const ir::AstNode *node, VReg obj, VReg prop)
644 {
645 ra_.Emit<CallruntimeDefinefieldbyvalue>(node, 0, prop, obj);
646 }
647
DefineFieldByIndex(const ir::AstNode * node,VReg obj,int64_t index)648 void PandaGen::DefineFieldByIndex(const ir::AstNode *node, VReg obj, int64_t index)
649 {
650 ra_.Emit<CallruntimeDefinefieldbyindex>(node, 0, index, obj);
651 }
652
StOwnByName(const ir::AstNode * node,VReg obj,const util::StringView & prop,bool nameSetting)653 void PandaGen::StOwnByName(const ir::AstNode *node, VReg obj, const util::StringView &prop, bool nameSetting)
654 {
655 nameSetting ? ra_.Emit<Stownbynamewithnameset>(node, 0, prop, obj) :
656 ra_.Emit<Stownbyname>(node, 0, prop, obj);
657 strings_.insert(prop);
658 }
659
StOwnByValue(const ir::AstNode * node,VReg obj,VReg prop,bool nameSetting)660 void PandaGen::StOwnByValue(const ir::AstNode *node, VReg obj, VReg prop, bool nameSetting)
661 {
662 nameSetting ? ra_.Emit<Stownbyvaluewithnameset>(node, 0, obj, prop) :
663 ra_.Emit<Stownbyvalue>(node, 0, obj, prop);
664 }
665
StOwnByIndex(const ir::AstNode * node,VReg obj,int64_t index)666 void PandaGen::StOwnByIndex(const ir::AstNode *node, VReg obj, int64_t index)
667 {
668 if (index <= util::Helpers::MAX_INT16) {
669 ra_.Emit<Stownbyindex>(node, 0, obj, index);
670 return;
671 }
672
673 ra_.Emit<WideStownbyindex>(node, obj, index);
674 }
675
DeleteObjProperty(const ir::AstNode * node,VReg obj,const Operand & prop)676 void PandaGen::DeleteObjProperty(const ir::AstNode *node, VReg obj, const Operand &prop)
677 {
678 if (std::holds_alternative<VReg>(prop)) {
679 LoadAccumulator(node, std::get<VReg>(prop));
680 } else if (std::holds_alternative<int64_t>(prop)) {
681 LoadAccumulatorInt(node, static_cast<size_t>(std::get<int64_t>(prop)));
682 } else {
683 ASSERT(std::holds_alternative<util::StringView>(prop));
684 LoadAccumulatorString(node, std::get<util::StringView>(prop));
685 }
686
687 ra_.Emit<Delobjprop>(node, obj); // property is load to acc
688 }
689
LoadAccumulator(const ir::AstNode * node,VReg reg)690 void PandaGen::LoadAccumulator(const ir::AstNode *node, VReg reg)
691 {
692 ra_.Emit<Lda>(node, reg);
693 }
694
LoadGlobalVar(const ir::AstNode * node,const util::StringView & name)695 void PandaGen::LoadGlobalVar(const ir::AstNode *node, const util::StringView &name)
696 {
697 ra_.Emit<Ldglobalvar>(node, 0, name);
698 strings_.insert(name);
699 }
700
StoreGlobalVar(const ir::AstNode * node,const util::StringView & name)701 void PandaGen::StoreGlobalVar(const ir::AstNode *node, const util::StringView &name)
702 {
703 ra_.Emit<Stglobalvar>(node, 0, name);
704 strings_.insert(name);
705 }
706
LoadAccFromLexEnv(const ir::AstNode * node,const binder::ScopeFindResult & result)707 void PandaGen::LoadAccFromLexEnv(const ir::AstNode *node, const binder::ScopeFindResult &result)
708 {
709 VirtualLoadVar::Expand(this, node, result);
710 }
711
StoreAccToLexEnv(const ir::AstNode * node,const binder::ScopeFindResult & result,bool isDeclaration)712 void PandaGen::StoreAccToLexEnv(const ir::AstNode *node, const binder::ScopeFindResult &result, bool isDeclaration)
713 {
714 VirtualStoreVar::Expand(this, node, result, isDeclaration);
715 }
716
LoadAccumulatorString(const ir::AstNode * node,const util::StringView & str)717 void PandaGen::LoadAccumulatorString(const ir::AstNode *node, const util::StringView &str)
718 {
719 ra_.Emit<LdaStr>(node, str);
720 strings_.insert(str);
721 }
722
LoadAccumulatorFloat(const ir::AstNode * node,double num)723 void PandaGen::LoadAccumulatorFloat(const ir::AstNode *node, double num)
724 {
725 ra_.Emit<Fldai>(node, num);
726 }
727
LoadAccumulatorInt(const ir::AstNode * node,int32_t num)728 void PandaGen::LoadAccumulatorInt(const ir::AstNode *node, int32_t num)
729 {
730 ra_.Emit<Ldai>(node, num);
731 }
732
LoadAccumulatorInt(const ir::AstNode * node,size_t num)733 void PandaGen::LoadAccumulatorInt(const ir::AstNode *node, size_t num)
734 {
735 ra_.Emit<Ldai>(node, static_cast<int64_t>(num));
736 }
737
LoadAccumulatorBigInt(const ir::AstNode * node,const util::StringView & num)738 void PandaGen::LoadAccumulatorBigInt(const ir::AstNode *node, const util::StringView &num)
739 {
740 ra_.Emit<Ldbigint>(node, num);
741 strings_.insert(num);
742 }
743
StoreConst(const ir::AstNode * node,VReg reg,Constant id)744 void PandaGen::StoreConst(const ir::AstNode *node, VReg reg, Constant id)
745 {
746 LoadConst(node, id);
747 StoreAccumulator(node, reg);
748 }
749
LoadConst(const ir::AstNode * node,Constant id)750 void PandaGen::LoadConst(const ir::AstNode *node, Constant id)
751 {
752 switch (id) {
753 case Constant::JS_HOLE: {
754 ra_.Emit<Ldhole>(node);
755 break;
756 }
757 case Constant::JS_NAN: {
758 ra_.Emit<Ldnan>(node);
759 break;
760 }
761 case Constant::JS_INFINITY: {
762 ra_.Emit<Ldinfinity>(node);
763 break;
764 }
765 case Constant::JS_GLOBAL: {
766 ra_.Emit<Ldglobal>(node);
767 break;
768 }
769 case Constant::JS_UNDEFINED: {
770 ra_.Emit<Ldundefined>(node);
771 break;
772 }
773 case Constant::JS_SYMBOL: {
774 ra_.Emit<Ldsymbol>(node);
775 break;
776 }
777 case Constant::JS_NULL: {
778 ra_.Emit<Ldnull>(node);
779 break;
780 }
781 case Constant::JS_TRUE: {
782 ra_.Emit<Ldtrue>(node);
783 break;
784 }
785 case Constant::JS_FALSE: {
786 ra_.Emit<Ldfalse>(node);
787 break;
788 }
789 default: {
790 UNREACHABLE();
791 }
792 }
793 }
794
MoveVreg(const ir::AstNode * node,VReg vd,VReg vs)795 void PandaGen::MoveVreg(const ir::AstNode *node, VReg vd, VReg vs)
796 {
797 ra_.Emit<Mov>(node, vd, vs);
798 }
799
SetLabel(const ir::AstNode * node,Label * label)800 void PandaGen::SetLabel([[maybe_unused]] const ir::AstNode *node, Label *label)
801 {
802 ra_.AddLabel(label);
803 }
804
Branch(const ir::AstNode * node,Label * label)805 void PandaGen::Branch(const ir::AstNode *node, Label *label)
806 {
807 ra_.Emit<Jmp>(node, label);
808 }
809
CheckControlFlowChange() const810 bool PandaGen::CheckControlFlowChange() const
811 {
812 const auto *iter = dynamicContext_;
813
814 while (iter) {
815 if (iter->HasFinalizer()) {
816 return true;
817 }
818
819 iter = iter->Prev();
820 }
821
822 return false;
823 }
824
ControlFlowChangeBreak(const ir::Identifier * label)825 Label *PandaGen::ControlFlowChangeBreak(const ir::Identifier *label)
826 {
827 auto *iter = dynamicContext_;
828
829 util::StringView labelName = label ? label->Name() : LabelTarget::BREAK_LABEL;
830 Label *breakTarget = nullptr;
831
832 while (iter) {
833 iter->AbortContext(ControlFlowChange::BREAK, labelName);
834
835 const auto &labelTargetName = iter->Target().BreakLabel();
836
837 if (iter->Target().BreakTarget()) {
838 breakTarget = iter->Target().BreakTarget();
839 }
840
841 if (labelTargetName == labelName) {
842 break;
843 }
844
845 iter = iter->Prev();
846 }
847
848 return breakTarget;
849 }
850
ControlFlowChangeContinue(const ir::Identifier * label)851 Label *PandaGen::ControlFlowChangeContinue(const ir::Identifier *label)
852 {
853 auto *iter = dynamicContext_;
854 util::StringView labelName = label ? label->Name() : LabelTarget::CONTINUE_LABEL;
855 Label *continueTarget = nullptr;
856
857 while (iter) {
858 iter->AbortContext(ControlFlowChange::CONTINUE, labelName);
859
860 const auto &labelTargetName = iter->Target().ContinueLabel();
861
862 if (iter->Target().ContinueTarget()) {
863 continueTarget = iter->Target().ContinueTarget();
864 }
865
866 if (labelTargetName == labelName) {
867 break;
868 }
869
870 iter = iter->Prev();
871 }
872
873 return continueTarget;
874 }
875
ControlFlowChangeReturn()876 void PandaGen::ControlFlowChangeReturn()
877 {
878 auto *iter = dynamicContext_;
879 while (iter) {
880 iter->AbortContext(ControlFlowChange::BREAK, LabelTarget::RETURN_LABEL);
881 iter = iter->Prev();
882 }
883 }
884
Condition(const ir::AstNode * node,lexer::TokenType op,VReg lhs,Label * ifFalse)885 void PandaGen::Condition(const ir::AstNode *node, lexer::TokenType op, VReg lhs, Label *ifFalse)
886 {
887 switch (op) {
888 case lexer::TokenType::PUNCTUATOR_EQUAL: {
889 Equal(node, lhs);
890 break;
891 }
892 case lexer::TokenType::PUNCTUATOR_NOT_EQUAL: {
893 NotEqual(node, lhs);
894 break;
895 }
896 case lexer::TokenType::PUNCTUATOR_STRICT_EQUAL: {
897 StrictEqual(node, lhs);
898 break;
899 }
900 case lexer::TokenType::PUNCTUATOR_NOT_STRICT_EQUAL: {
901 StrictNotEqual(node, lhs);
902 break;
903 }
904 case lexer::TokenType::PUNCTUATOR_LESS_THAN: {
905 LessThan(node, lhs);
906 break;
907 }
908 case lexer::TokenType::PUNCTUATOR_LESS_THAN_EQUAL: {
909 LessEqual(node, lhs);
910 break;
911 }
912 case lexer::TokenType::PUNCTUATOR_GREATER_THAN: {
913 GreaterThan(node, lhs);
914 break;
915 }
916 case lexer::TokenType::PUNCTUATOR_GREATER_THAN_EQUAL: {
917 GreaterEqual(node, lhs);
918 break;
919 }
920 default: {
921 UNREACHABLE();
922 }
923 }
924
925 ra_.Emit<Jeqz>(node, ifFalse);
926 }
927
Unary(const ir::AstNode * node,lexer::TokenType op,VReg operand)928 void PandaGen::Unary(const ir::AstNode *node, lexer::TokenType op, VReg operand)
929 {
930 switch (op) {
931 case lexer::TokenType::PUNCTUATOR_PLUS: {
932 ToNumber(node, operand);
933 break;
934 }
935 case lexer::TokenType::PUNCTUATOR_MINUS: {
936 LoadAccumulator(node, operand);
937 ra_.Emit<Neg>(node, 0);
938 break;
939 }
940 case lexer::TokenType::PUNCTUATOR_TILDE: {
941 LoadAccumulator(node, operand);
942 ra_.Emit<Not>(node, 0);
943 break;
944 }
945 case lexer::TokenType::PUNCTUATOR_EXCLAMATION_MARK: {
946 Negate(node);
947 break;
948 }
949 case lexer::TokenType::PUNCTUATOR_PLUS_PLUS: {
950 LoadAccumulator(node, operand);
951 ra_.Emit<Inc>(node, 0);
952 break;
953 }
954 case lexer::TokenType::PUNCTUATOR_MINUS_MINUS: {
955 LoadAccumulator(node, operand);
956 ra_.Emit<Dec>(node, 0);
957 break;
958 }
959 case lexer::TokenType::KEYW_VOID:
960 case lexer::TokenType::KEYW_DELETE: {
961 LoadConst(node, Constant::JS_UNDEFINED);
962 break;
963 }
964 default: {
965 UNREACHABLE();
966 }
967 }
968 }
969
Binary(const ir::AstNode * node,lexer::TokenType op,VReg lhs)970 void PandaGen::Binary(const ir::AstNode *node, lexer::TokenType op, VReg lhs)
971 {
972 switch (op) {
973 case lexer::TokenType::PUNCTUATOR_EQUAL: {
974 Equal(node, lhs);
975 break;
976 }
977 case lexer::TokenType::PUNCTUATOR_NOT_EQUAL: {
978 NotEqual(node, lhs);
979 break;
980 }
981 case lexer::TokenType::PUNCTUATOR_STRICT_EQUAL: {
982 StrictEqual(node, lhs);
983 break;
984 }
985 case lexer::TokenType::PUNCTUATOR_NOT_STRICT_EQUAL: {
986 StrictNotEqual(node, lhs);
987 break;
988 }
989 case lexer::TokenType::PUNCTUATOR_LESS_THAN: {
990 LessThan(node, lhs);
991 break;
992 }
993 case lexer::TokenType::PUNCTUATOR_LESS_THAN_EQUAL: {
994 LessEqual(node, lhs);
995 break;
996 }
997 case lexer::TokenType::PUNCTUATOR_GREATER_THAN: {
998 GreaterThan(node, lhs);
999 break;
1000 }
1001 case lexer::TokenType::PUNCTUATOR_GREATER_THAN_EQUAL: {
1002 GreaterEqual(node, lhs);
1003 break;
1004 }
1005 case lexer::TokenType::PUNCTUATOR_PLUS:
1006 case lexer::TokenType::PUNCTUATOR_PLUS_EQUAL: {
1007 ra_.Emit<Add2>(node, 0, lhs);
1008 break;
1009 }
1010 case lexer::TokenType::PUNCTUATOR_MINUS:
1011 case lexer::TokenType::PUNCTUATOR_MINUS_EQUAL: {
1012 ra_.Emit<Sub2>(node, 0, lhs);
1013 break;
1014 }
1015 case lexer::TokenType::PUNCTUATOR_MULTIPLY:
1016 case lexer::TokenType::PUNCTUATOR_MULTIPLY_EQUAL: {
1017 ra_.Emit<Mul2>(node, 0, lhs);
1018 break;
1019 }
1020 case lexer::TokenType::PUNCTUATOR_DIVIDE:
1021 case lexer::TokenType::PUNCTUATOR_DIVIDE_EQUAL: {
1022 ra_.Emit<Div2>(node, 0, lhs);
1023 break;
1024 }
1025 case lexer::TokenType::PUNCTUATOR_MOD:
1026 case lexer::TokenType::PUNCTUATOR_MOD_EQUAL: {
1027 ra_.Emit<Mod2>(node, 0, lhs);
1028 break;
1029 }
1030 case lexer::TokenType::PUNCTUATOR_EXPONENTIATION_EQUAL:
1031 case lexer::TokenType::PUNCTUATOR_EXPONENTIATION: {
1032 ra_.Emit<Exp>(node, 0, lhs);
1033 break;
1034 }
1035 case lexer::TokenType::PUNCTUATOR_LEFT_SHIFT:
1036 case lexer::TokenType::PUNCTUATOR_LEFT_SHIFT_EQUAL: {
1037 ra_.Emit<Shl2>(node, 0, lhs);
1038 break;
1039 }
1040 case lexer::TokenType::PUNCTUATOR_RIGHT_SHIFT:
1041 case lexer::TokenType::PUNCTUATOR_RIGHT_SHIFT_EQUAL: {
1042 ra_.Emit<Ashr2>(node, 0, lhs);
1043 break;
1044 }
1045 case lexer::TokenType::PUNCTUATOR_UNSIGNED_RIGHT_SHIFT:
1046 case lexer::TokenType::PUNCTUATOR_UNSIGNED_RIGHT_SHIFT_EQUAL: {
1047 ra_.Emit<Shr2>(node, 0, lhs);
1048 break;
1049 }
1050 case lexer::TokenType::PUNCTUATOR_BITWISE_AND:
1051 case lexer::TokenType::PUNCTUATOR_BITWISE_AND_EQUAL: {
1052 ra_.Emit<And2>(node, 0, lhs);
1053 break;
1054 }
1055 case lexer::TokenType::PUNCTUATOR_BITWISE_OR:
1056 case lexer::TokenType::PUNCTUATOR_BITWISE_OR_EQUAL: {
1057 ra_.Emit<Or2>(node, 0, lhs);
1058 break;
1059 }
1060 case lexer::TokenType::PUNCTUATOR_BITWISE_XOR:
1061 case lexer::TokenType::PUNCTUATOR_BITWISE_XOR_EQUAL: {
1062 ra_.Emit<Xor2>(node, 0, lhs);
1063 break;
1064 }
1065 case lexer::TokenType::KEYW_IN: {
1066 ra_.Emit<Isin>(node, 0, lhs);
1067 break;
1068 }
1069 case lexer::TokenType::KEYW_INSTANCEOF: {
1070 ra_.Emit<Instanceof>(node, 0, lhs);
1071 break;
1072 }
1073 default: {
1074 UNREACHABLE();
1075 }
1076 }
1077 }
1078
Equal(const ir::AstNode * node,VReg lhs)1079 void PandaGen::Equal(const ir::AstNode *node, VReg lhs)
1080 {
1081 ra_.Emit<Eq>(node, 0, lhs);
1082 }
1083
NotEqual(const ir::AstNode * node,VReg lhs)1084 void PandaGen::NotEqual(const ir::AstNode *node, VReg lhs)
1085 {
1086 ra_.Emit<Noteq>(node, 0, lhs);
1087 }
1088
StrictEqual(const ir::AstNode * node,VReg lhs)1089 void PandaGen::StrictEqual(const ir::AstNode *node, VReg lhs)
1090 {
1091 ra_.Emit<Stricteq>(node, 0, lhs);
1092 }
1093
StrictNotEqual(const ir::AstNode * node,VReg lhs)1094 void PandaGen::StrictNotEqual(const ir::AstNode *node, VReg lhs)
1095 {
1096 ra_.Emit<Strictnoteq>(node, 0, lhs);
1097 }
1098
LessThan(const ir::AstNode * node,VReg lhs)1099 void PandaGen::LessThan(const ir::AstNode *node, VReg lhs)
1100 {
1101 ra_.Emit<Less>(node, 0, lhs);
1102 }
1103
LessEqual(const ir::AstNode * node,VReg lhs)1104 void PandaGen::LessEqual(const ir::AstNode *node, VReg lhs)
1105 {
1106 ra_.Emit<Lesseq>(node, 0, lhs);
1107 }
1108
GreaterThan(const ir::AstNode * node,VReg lhs)1109 void PandaGen::GreaterThan(const ir::AstNode *node, VReg lhs)
1110 {
1111 ra_.Emit<Greater>(node, 0, lhs);
1112 }
1113
GreaterEqual(const ir::AstNode * node,VReg lhs)1114 void PandaGen::GreaterEqual(const ir::AstNode *node, VReg lhs)
1115 {
1116 ra_.Emit<Greatereq>(node, 0, lhs);
1117 }
1118
IsTrue(const ir::AstNode * node)1119 void PandaGen::IsTrue(const ir::AstNode *node)
1120 {
1121 if (util::Helpers::IsDefaultApiVersion(Binder()->Program()->TargetApiVersion(),
1122 Binder()->Program()->GetTargetApiSubVersion())) {
1123 ra_.Emit<Istrue>(node);
1124 return;
1125 }
1126
1127 ra_.Emit<CallruntimeIstrue>(node, 0);
1128 }
1129
BranchIfUndefined(const ir::AstNode * node,Label * target)1130 void PandaGen::BranchIfUndefined(const ir::AstNode *node, Label *target)
1131 {
1132 RegScope rs(this);
1133 VReg tmp = AllocReg();
1134 StoreAccumulator(node, tmp);
1135 LoadConst(node, Constant::JS_UNDEFINED);
1136 Equal(node, tmp);
1137 ra_.Emit<Jnez>(node, target);
1138 }
1139
BranchIfStrictUndefined(const ir::AstNode * node,class Label * target)1140 void PandaGen::BranchIfStrictUndefined(const ir::AstNode *node, class Label *target)
1141 {
1142 RegScope rs(this);
1143 VReg tmp = AllocReg();
1144 StoreAccumulator(node, tmp);
1145 LoadConst(node, Constant::JS_UNDEFINED);
1146 StrictEqual(node, tmp);
1147 ra_.Emit<Jnez>(node, target);
1148 }
1149
BranchIfNotUndefined(const ir::AstNode * node,Label * target)1150 void PandaGen::BranchIfNotUndefined(const ir::AstNode *node, Label *target)
1151 {
1152 RegScope rs(this);
1153 VReg tmp = AllocReg();
1154 StoreAccumulator(node, tmp);
1155 LoadConst(node, Constant::JS_UNDEFINED);
1156 Equal(node, tmp);
1157 ra_.Emit<Jeqz>(node, target);
1158 }
1159
BranchIfStrictNotUndefined(const ir::AstNode * node,class Label * target)1160 void PandaGen::BranchIfStrictNotUndefined(const ir::AstNode *node, class Label *target)
1161 {
1162 RegScope rs(this);
1163 VReg tmp = AllocReg();
1164 StoreAccumulator(node, tmp);
1165 LoadConst(node, Constant::JS_UNDEFINED);
1166 StrictEqual(node, tmp);
1167 ra_.Emit<Jeqz>(node, target);
1168 }
1169
BranchIfTrue(const ir::AstNode * node,Label * target)1170 void PandaGen::BranchIfTrue(const ir::AstNode *node, Label *target)
1171 {
1172 IsTrue(node);
1173 ra_.Emit<Jnez>(node, target);
1174 }
1175
BranchIfNotTrue(const ir::AstNode * node,Label * target)1176 void PandaGen::BranchIfNotTrue(const ir::AstNode *node, Label *target)
1177 {
1178 IsTrue(node);
1179 BranchIfFalse(node, target);
1180 }
1181
BranchIfFalse(const ir::AstNode * node,Label * target)1182 void PandaGen::BranchIfFalse(const ir::AstNode *node, Label *target)
1183 {
1184 if (util::Helpers::IsDefaultApiVersion(Binder()->Program()->TargetApiVersion(),
1185 Binder()->Program()->GetTargetApiSubVersion())) {
1186 ra_.Emit<Isfalse>(node);
1187 ra_.Emit<Jnez>(node, target);
1188 return;
1189 }
1190
1191 ra_.Emit<CallruntimeIsfalse>(node, 0);
1192 ra_.Emit<Jnez>(node, target);
1193 }
1194
BranchIfStrictNull(const ir::AstNode * node,class Label * target)1195 void PandaGen::BranchIfStrictNull(const ir::AstNode *node, class Label *target)
1196 {
1197 RegScope rs(this);
1198 VReg tmp = AllocReg();
1199 StoreAccumulator(node, tmp);
1200 LoadConst(node, Constant::JS_NULL);
1201 ra_.Emit<Stricteq>(node, 0, tmp);
1202 ra_.Emit<Jnez>(node, target);
1203 }
1204
EmitThrow(const ir::AstNode * node)1205 void PandaGen::EmitThrow(const ir::AstNode *node)
1206 {
1207 ra_.Emit<Throw>(node);
1208 }
1209
EmitRethrow(const ir::AstNode * node)1210 void PandaGen::EmitRethrow(const ir::AstNode *node)
1211 {
1212 RegScope rs(this);
1213 auto *skipThrow = AllocLabel();
1214 auto *doThrow = AllocLabel();
1215
1216 VReg exception = AllocReg();
1217 StoreAccumulator(node, exception);
1218
1219 VReg hole = AllocReg();
1220 StoreConst(node, hole, Constant::JS_HOLE);
1221
1222 LoadAccumulator(node, exception);
1223 NotEqual(node, hole);
1224 ra_.Emit<Jeqz>(node, skipThrow);
1225
1226 SetLabel(node, doThrow);
1227 LoadAccumulator(node, exception);
1228 EmitThrow(node);
1229
1230 SetLabel(node, skipThrow);
1231 }
1232
EmitReturn(const ir::AstNode * node)1233 void PandaGen::EmitReturn(const ir::AstNode *node)
1234 {
1235 ra_.Emit<Return>(node);
1236 }
1237
EmitReturnUndefined(const ir::AstNode * node)1238 void PandaGen::EmitReturnUndefined(const ir::AstNode *node)
1239 {
1240 ra_.Emit<Returnundefined>(node);
1241 }
1242
ImplicitReturn(const ir::AstNode * node)1243 void PandaGen::ImplicitReturn(const ir::AstNode *node)
1244 {
1245 builder_->ImplicitReturn(node);
1246 }
1247
DirectReturn(const ir::AstNode * node)1248 void PandaGen::DirectReturn(const ir::AstNode *node)
1249 {
1250 builder_->DirectReturn(node);
1251 }
1252
ExplicitReturn(const ir::AstNode * node)1253 void PandaGen::ExplicitReturn(const ir::AstNode *node)
1254 {
1255 builder_->ExplicitReturn(node);
1256 }
1257
ValidateClassDirectReturn(const ir::AstNode * node)1258 void PandaGen::ValidateClassDirectReturn(const ir::AstNode *node)
1259 {
1260 const ir::ScriptFunction *func = util::Helpers::GetContainingFunction(node);
1261
1262 if (!func || !func->IsConstructor()) {
1263 return;
1264 }
1265
1266 RegScope rs(this);
1267 VReg value = AllocReg();
1268 StoreAccumulator(node, value);
1269
1270 auto *notUndefined = AllocLabel();
1271 auto *condEnd = AllocLabel();
1272
1273 BranchIfStrictNotUndefined(node, notUndefined);
1274 GetThis(func);
1275 ThrowIfSuperNotCorrectCall(func, 0);
1276
1277 auto *iter = dynamicContext_;
1278 while (iter) {
1279 if (iter->Type() == DynamicContextType::LEX_ENV) {
1280 auto *envContext = static_cast<LexEnvContext *>(iter);
1281 envContext->HandleForUpdateDirectReturnContext();
1282 }
1283 iter = iter->Prev();
1284 }
1285 Branch(node, condEnd);
1286
1287 SetLabel(node, notUndefined);
1288 LoadAccumulator(node, value);
1289
1290 SetLabel(node, condEnd);
1291 }
1292
EmitAwait(const ir::AstNode * node)1293 void PandaGen::EmitAwait(const ir::AstNode *node)
1294 {
1295 builder_->Await(node);
1296 }
1297
CallThis(const ir::AstNode * node,VReg startReg,size_t argCount)1298 void PandaGen::CallThis(const ir::AstNode *node, VReg startReg, size_t argCount)
1299 {
1300 LoadAccumulator(node, startReg); // callee is load to acc
1301 VReg thisReg = startReg + 1; // This dependency is used in other places, do not modify.
1302 switch (argCount) {
1303 case 1: { // no args
1304 ra_.Emit<Callthis0>(node, 0, thisReg);
1305 break;
1306 }
1307 case 2: { // 1 arg
1308 VReg arg0 = thisReg + 1;
1309 ra_.Emit<Callthis1>(node, 0, thisReg, arg0);
1310 break;
1311 }
1312 case 3: { // 2 args
1313 VReg arg0 = thisReg + 1;
1314 VReg arg1 = arg0 + 1;
1315 ra_.Emit<Callthis2>(node, 0, thisReg, arg0, arg1);
1316 break;
1317 }
1318 case 4: { // 3 args
1319 VReg arg0 = thisReg + 1;
1320 VReg arg1 = arg0 + 1;
1321 VReg arg2 = arg1 + 1;
1322 ra_.Emit<Callthis3>(node, 0, thisReg, arg0, arg1, arg2);
1323 break;
1324 }
1325 default: {
1326 int64_t actualArgs = static_cast<int64_t>(argCount) - 1;
1327 if (actualArgs <= util::Helpers::MAX_INT8) {
1328 ra_.EmitRange<Callthisrange>(node, argCount, 0, actualArgs, thisReg);
1329 break;
1330 }
1331
1332 ra_.EmitRange<WideCallthisrange>(node, argCount, actualArgs, thisReg);
1333 break;
1334 }
1335 }
1336 }
1337
Call(const ir::AstNode * node,VReg startReg,size_t argCount)1338 void PandaGen::Call(const ir::AstNode *node, VReg startReg, size_t argCount)
1339 {
1340 LoadAccumulator(node, startReg); // callee is load to acc
1341 switch (argCount) {
1342 case 0: { // 0 args
1343 ra_.Emit<Callarg0>(node, 0);
1344 break;
1345 }
1346 case 1: { // 1 arg
1347 VReg arg0 = startReg + 1;
1348 ra_.Emit<Callarg1>(node, 0, arg0);
1349 break;
1350 }
1351 case 2: { // 2 args
1352 VReg arg0 = startReg + 1;
1353 VReg arg1 = arg0 + 1;
1354 ra_.Emit<Callargs2>(node, 0, arg0, arg1);
1355 break;
1356 }
1357 case 3: { // 3 args
1358 VReg arg0 = startReg + 1;
1359 VReg arg1 = arg0 + 1;
1360 VReg arg2 = arg1 + 1;
1361 ra_.Emit<Callargs3>(node, 0, arg0, arg1, arg2);
1362 break;
1363 }
1364 default: {
1365 VReg arg0 = startReg + 1;
1366 if (argCount <= util::Helpers::MAX_INT8) {
1367 ra_.EmitRange<Callrange>(node, argCount, 0, argCount, arg0);
1368 break;
1369 }
1370
1371 ra_.EmitRange<WideCallrange>(node, argCount, argCount, arg0);
1372 break;
1373 }
1374 }
1375 }
1376
SuperCall(const ir::AstNode * node,VReg startReg,size_t argCount)1377 void PandaGen::SuperCall(const ir::AstNode *node, VReg startReg, size_t argCount)
1378 {
1379 if (RootNode()->AsScriptFunction()->IsArrow()) {
1380 GetFunctionObject(node); // load funcobj to acc for super call in arrow function
1381 if (argCount <= util::Helpers::MAX_INT8) {
1382 ra_.EmitRange<Supercallarrowrange>(node, argCount, 0, static_cast<int64_t>(argCount), startReg);
1383 } else {
1384 ra_.EmitRange<WideSupercallarrowrange>(node, argCount, static_cast<int64_t>(argCount), startReg);
1385 }
1386 return;
1387 }
1388
1389 if (argCount <= util::Helpers::MAX_INT8) {
1390 // no need to load funcobj to acc for super call in other kinds of functions
1391 ra_.EmitRange<Supercallthisrange>(node, argCount, 0, static_cast<int64_t>(argCount), startReg);
1392 return;
1393 }
1394
1395 ra_.EmitRange<WideSupercallthisrange>(node, argCount, static_cast<int64_t>(argCount), startReg);
1396 }
1397
SuperCallSpread(const ir::AstNode * node,VReg vs)1398 void PandaGen::SuperCallSpread(const ir::AstNode *node, VReg vs)
1399 {
1400 ra_.Emit<Supercallspread>(node, 0, vs);
1401 }
1402
SuperCallForwardAllArgs(const ir::AstNode * node,VReg funcObj)1403 void PandaGen::SuperCallForwardAllArgs(const ir::AstNode *node, VReg funcObj)
1404 {
1405 ra_.Emit<CallruntimeSupercallforwardallargs>(node, funcObj);
1406 }
1407
NotifyConcurrentResult(const ir::AstNode * node)1408 void PandaGen::NotifyConcurrentResult(const ir::AstNode *node)
1409 {
1410 if (IsConcurrent()) {
1411 ra_.Emit<CallruntimeNotifyconcurrentresult>(node);
1412 }
1413 }
1414
CallInit(const ir::AstNode * node,VReg thisReg)1415 void PandaGen::CallInit(const ir::AstNode *node, VReg thisReg)
1416 {
1417 // callee is in acc
1418 ra_.Emit<CallruntimeCallinit>(node, 0, thisReg);
1419 }
1420
NewObject(const ir::AstNode * node,VReg startReg,size_t argCount)1421 void PandaGen::NewObject(const ir::AstNode *node, VReg startReg, size_t argCount)
1422 {
1423 if (argCount <= util::Helpers::MAX_INT8) {
1424 ra_.EmitRange<Newobjrange>(node, argCount, 0, static_cast<int64_t>(argCount), startReg);
1425 return;
1426 }
1427
1428 ra_.EmitRange<WideNewobjrange>(node, argCount, static_cast<int64_t>(argCount), startReg);
1429 }
1430
DefineFunction(const ir::AstNode * node,const ir::ScriptFunction * realNode,const util::StringView & name)1431 void PandaGen::DefineFunction(const ir::AstNode *node, const ir::ScriptFunction *realNode, const util::StringView &name)
1432 {
1433 if (realNode->IsOverload() || realNode->Declare()) {
1434 return;
1435 }
1436
1437 auto formalParamCnt = realNode->FormalParamsLength();
1438 if (realNode->IsMethod()) {
1439 ra_.Emit<Definemethod>(node, 0, name, static_cast<int64_t>(formalParamCnt));
1440 } else {
1441 ra_.Emit<Definefunc>(node, 0, name, static_cast<int64_t>(formalParamCnt));
1442 }
1443
1444 strings_.insert(name);
1445 }
1446
TypeOf(const ir::AstNode * node)1447 void PandaGen::TypeOf(const ir::AstNode *node)
1448 {
1449 ra_.Emit<Typeof>(node, 0);
1450 }
1451
CallSpread(const ir::AstNode * node,VReg func,VReg thisReg,VReg args)1452 void PandaGen::CallSpread(const ir::AstNode *node, VReg func, VReg thisReg, VReg args)
1453 {
1454 LoadAccumulator(node, func); // callee is load to acc
1455 ra_.Emit<Apply>(node, 0, thisReg, args);
1456 }
1457
NewObjSpread(const ir::AstNode * node,VReg obj)1458 void PandaGen::NewObjSpread(const ir::AstNode *node, VReg obj)
1459 {
1460 ra_.Emit<Newobjapply>(node, 0, obj);
1461 }
1462
GetUnmappedArgs(const ir::AstNode * node)1463 void PandaGen::GetUnmappedArgs(const ir::AstNode *node)
1464 {
1465 ra_.Emit<Getunmappedargs>(node);
1466 }
1467
Negate(const ir::AstNode * node)1468 void PandaGen::Negate(const ir::AstNode *node)
1469 {
1470 auto *falseLabel = AllocLabel();
1471 auto *endLabel = AllocLabel();
1472 BranchIfTrue(node, falseLabel);
1473 LoadConst(node, Constant::JS_TRUE);
1474 Branch(node, endLabel);
1475 SetLabel(node, falseLabel);
1476 LoadConst(node, Constant::JS_FALSE);
1477 SetLabel(node, endLabel);
1478 }
1479
ToNumber(const ir::AstNode * node,VReg arg)1480 void PandaGen::ToNumber(const ir::AstNode *node, VReg arg)
1481 {
1482 LoadAccumulator(node, arg);
1483 ra_.Emit<Tonumber>(node, 0);
1484 }
1485
ToNumeric(const ir::AstNode * node,VReg arg)1486 void PandaGen::ToNumeric(const ir::AstNode *node, VReg arg)
1487 {
1488 LoadAccumulator(node, arg);
1489 ra_.Emit<Tonumeric>(node, 0);
1490 }
1491
CreateGeneratorObj(const ir::AstNode * node,VReg funcObj)1492 void PandaGen::CreateGeneratorObj(const ir::AstNode *node, VReg funcObj)
1493 {
1494 ra_.Emit<Creategeneratorobj>(node, funcObj);
1495 }
1496
CreateAsyncGeneratorObj(const ir::AstNode * node,VReg funcObj)1497 void PandaGen::CreateAsyncGeneratorObj(const ir::AstNode *node, VReg funcObj)
1498 {
1499 ra_.Emit<Createasyncgeneratorobj>(node, funcObj);
1500 }
1501
CreateIterResultObject(const ir::AstNode * node,VReg value,VReg done)1502 void PandaGen::CreateIterResultObject(const ir::AstNode *node, VReg value, VReg done)
1503 {
1504 ra_.Emit<Createiterresultobj>(node, value, done);
1505 }
1506
SuspendGenerator(const ir::AstNode * node,VReg genObj)1507 void PandaGen::SuspendGenerator(const ir::AstNode *node, VReg genObj)
1508 {
1509 ra_.Emit<Suspendgenerator>(node, genObj); // iterResult is in acc
1510 }
1511
GeneratorYield(const ir::AstNode * node,VReg genObj)1512 void PandaGen::GeneratorYield(const ir::AstNode *node, VReg genObj)
1513 {
1514 LoadAccumulator(node, genObj);
1515 ra_.Emit<Setgeneratorstate>(node, static_cast<int32_t>(GeneratorState::SUSPENDED_YIELD));
1516 }
1517
GeneratorComplete(const ir::AstNode * node,VReg genObj)1518 void PandaGen::GeneratorComplete(const ir::AstNode *node, VReg genObj)
1519 {
1520 LoadAccumulator(node, genObj);
1521 ra_.Emit<Setgeneratorstate>(node, static_cast<int32_t>(GeneratorState::COMPLETED));
1522 }
1523
ResumeGenerator(const ir::AstNode * node,VReg genObj)1524 void PandaGen::ResumeGenerator(const ir::AstNode *node, VReg genObj)
1525 {
1526 LoadAccumulator(node, genObj);
1527 ra_.Emit<Resumegenerator>(node);
1528 }
1529
GetResumeMode(const ir::AstNode * node,VReg genObj)1530 void PandaGen::GetResumeMode(const ir::AstNode *node, VReg genObj)
1531 {
1532 LoadAccumulator(node, genObj);
1533 ra_.Emit<Getresumemode>(node);
1534 }
1535
AsyncFunctionEnter(const ir::AstNode * node)1536 void PandaGen::AsyncFunctionEnter(const ir::AstNode *node)
1537 {
1538 ra_.Emit<Asyncfunctionenter>(node);
1539 }
1540
AsyncFunctionAwait(const ir::AstNode * node,VReg asyncFuncObj)1541 void PandaGen::AsyncFunctionAwait(const ir::AstNode *node, VReg asyncFuncObj)
1542 {
1543 ra_.Emit<Asyncfunctionawaituncaught>(node, asyncFuncObj); // receivedValue is in acc
1544 }
1545
AsyncFunctionResolve(const ir::AstNode * node,VReg asyncFuncObj)1546 void PandaGen::AsyncFunctionResolve(const ir::AstNode *node, VReg asyncFuncObj)
1547 {
1548 ra_.Emit<Asyncfunctionresolve>(node, asyncFuncObj); // use retVal in acc
1549 }
1550
AsyncFunctionReject(const ir::AstNode * node,VReg asyncFuncObj)1551 void PandaGen::AsyncFunctionReject(const ir::AstNode *node, VReg asyncFuncObj)
1552 {
1553 ra_.Emit<Asyncfunctionreject>(node, asyncFuncObj); // exception is in acc
1554 }
1555
AsyncGeneratorResolve(const ir::AstNode * node,VReg asyncGenObj,VReg value,VReg canSuspend)1556 void PandaGen::AsyncGeneratorResolve(const ir::AstNode *node, VReg asyncGenObj, VReg value, VReg canSuspend)
1557 {
1558 ra_.Emit<Asyncgeneratorresolve>(node, asyncGenObj, value, canSuspend);
1559 }
1560
AsyncGeneratorReject(const ir::AstNode * node,VReg asyncGenObj)1561 void PandaGen::AsyncGeneratorReject(const ir::AstNode *node, VReg asyncGenObj)
1562 {
1563 ra_.Emit<Asyncgeneratorreject>(node, asyncGenObj); // value is in acc
1564 }
1565
GetTemplateObject(const ir::AstNode * node,VReg value)1566 void PandaGen::GetTemplateObject(const ir::AstNode *node, VReg value)
1567 {
1568 LoadAccumulator(node, value);
1569 ra_.Emit<Gettemplateobject>(node, 0);
1570 }
1571
CopyRestArgs(const ir::AstNode * node,uint32_t index)1572 void PandaGen::CopyRestArgs(const ir::AstNode *node, uint32_t index)
1573 {
1574 index <= util::Helpers::MAX_INT8 ? ra_.Emit<Copyrestargs>(node, index) : ra_.Emit<WideCopyrestargs>(node, index);
1575 }
1576
GetPropIterator(const ir::AstNode * node)1577 void PandaGen::GetPropIterator(const ir::AstNode *node)
1578 {
1579 ra_.Emit<Getpropiterator>(node);
1580 }
1581
GetNextPropName(const ir::AstNode * node,VReg iter)1582 void PandaGen::GetNextPropName(const ir::AstNode *node, VReg iter)
1583 {
1584 ra_.Emit<Getnextpropname>(node, iter);
1585 }
1586
CreateEmptyObject(const ir::AstNode * node)1587 void PandaGen::CreateEmptyObject(const ir::AstNode *node)
1588 {
1589 ra_.Emit<Createemptyobject>(node);
1590 }
1591
CreateObjectWithBuffer(const ir::AstNode * node,uint32_t idx)1592 void PandaGen::CreateObjectWithBuffer(const ir::AstNode *node, uint32_t idx)
1593 {
1594 ASSERT(util::Helpers::IsInteger<uint32_t>(idx));
1595 std::string idxStr = std::string(context_->Binder()->Program()->RecordName()) + "_" + std::to_string(idx);
1596 util::UString litId(idxStr, allocator_);
1597 ra_.Emit<Createobjectwithbuffer>(node, 0, litId.View());
1598 }
1599
SetObjectWithProto(const ir::AstNode * node,VReg proto,VReg obj)1600 void PandaGen::SetObjectWithProto(const ir::AstNode *node, VReg proto, VReg obj)
1601 {
1602 LoadAccumulator(node, obj);
1603 ra_.Emit<Setobjectwithproto>(node, 0, proto);
1604 }
1605
CopyDataProperties(const ir::AstNode * node,VReg dst)1606 void PandaGen::CopyDataProperties(const ir::AstNode *node, VReg dst)
1607 {
1608 ra_.Emit<Copydataproperties>(node, dst); // use acc as srcObj
1609 }
1610
DefineGetterSetterByValue(const ir::AstNode * node,VReg obj,VReg name,VReg getter,VReg setter,bool setName)1611 void PandaGen::DefineGetterSetterByValue(const ir::AstNode *node, VReg obj, VReg name, VReg getter, VReg setter,
1612 bool setName)
1613 {
1614 LoadConst(node, setName ? Constant::JS_TRUE : Constant::JS_FALSE);
1615 ra_.Emit<Definegettersetterbyvalue>(node, obj, name, getter, setter);
1616 }
1617
CreateEmptyArray(const ir::AstNode * node)1618 void PandaGen::CreateEmptyArray(const ir::AstNode *node)
1619 {
1620 ra_.Emit<Createemptyarray>(node, 0);
1621 }
1622
CreateArrayWithBuffer(const ir::AstNode * node,uint32_t idx)1623 void PandaGen::CreateArrayWithBuffer(const ir::AstNode *node, uint32_t idx)
1624 {
1625 ASSERT(util::Helpers::IsInteger<uint32_t>(idx));
1626 std::string idxStr = std::string(context_->Binder()->Program()->RecordName()) + "_" + std::to_string(idx);
1627 util::UString litId(idxStr, allocator_);
1628 ra_.Emit<Createarraywithbuffer>(node, 0, litId.View());
1629 }
1630
CreateArray(const ir::AstNode * node,const ArenaVector<ir::Expression * > & elements,VReg obj)1631 void PandaGen::CreateArray(const ir::AstNode *node, const ArenaVector<ir::Expression *> &elements, VReg obj)
1632 {
1633 if (elements.empty()) {
1634 CreateEmptyArray(node);
1635 StoreAccumulator(node, obj);
1636 return;
1637 }
1638
1639 auto *buf = NewLiteralBuffer();
1640
1641 size_t i = 0;
1642 // This loop handles constant literal data by collecting it into a literal buffer
1643 // until a non-constant element is encountered.
1644 while (i < elements.size() && util::Helpers::IsConstantExpr(elements[i])) {
1645 buf->Add(elements[i]->AsLiteral());
1646 i++;
1647 }
1648
1649 if (buf->IsEmpty()) {
1650 CreateEmptyArray(node);
1651 } else {
1652 uint32_t bufIdx = static_cast<uint32_t>(AddLiteralBuffer(buf));
1653 CreateArrayWithBuffer(node, bufIdx);
1654 }
1655
1656 StoreAccumulator(node, obj);
1657
1658 if (i == elements.size()) {
1659 return;
1660 }
1661
1662 bool hasSpread = false;
1663
1664 // This loop handles array elements until a spread element is encountered
1665 for (; i < elements.size(); i++) {
1666 const ir::Expression *elem = elements[i];
1667
1668 if (elem->IsOmittedExpression()) {
1669 continue;
1670 }
1671
1672 if (elem->IsSpreadElement()) {
1673 // The next loop will handle arrays that have a spread element
1674 hasSpread = true;
1675 break;
1676 }
1677
1678 elem->Compile(this);
1679 StOwnByIndex(elem, obj, i);
1680 }
1681
1682 RegScope rs(this);
1683 VReg idxReg {};
1684
1685 if (hasSpread) {
1686 idxReg = AllocReg();
1687 LoadAccumulatorInt(node, i);
1688 StoreAccumulator(node, idxReg);
1689 }
1690
1691 // This loop handles arrays that contain spread elements
1692 for (; i < elements.size(); i++) {
1693 const ir::Expression *elem = elements[i];
1694
1695 if (elem->IsSpreadElement()) {
1696 elem->AsSpreadElement()->Argument()->Compile(this);
1697
1698 StoreArraySpread(elem, obj, idxReg);
1699
1700 LoadObjByName(node, obj, "length");
1701 StoreAccumulator(elem, idxReg);
1702 continue;
1703 }
1704
1705 if (!elem->IsOmittedExpression()) {
1706 elem->Compile(this);
1707 StOwnByValue(elem, obj, idxReg);
1708 }
1709
1710 Unary(elem, lexer::TokenType::PUNCTUATOR_PLUS_PLUS, idxReg);
1711 StoreAccumulator(elem, idxReg);
1712 }
1713
1714 // If the last element is omitted, we also have to update the length property
1715 if (elements.back()->IsOmittedExpression()) {
1716 // if there was a spread value then acc already contains the length
1717 if (!hasSpread) {
1718 LoadAccumulatorInt(node, i);
1719 }
1720
1721 StOwnByName(node, obj, "length");
1722 }
1723
1724 LoadAccumulator(node, obj);
1725 }
1726
StoreArraySpread(const ir::AstNode * node,VReg array,VReg index)1727 void PandaGen::StoreArraySpread(const ir::AstNode *node, VReg array, VReg index)
1728 {
1729 ra_.Emit<Starrayspread>(node, array, index);
1730 }
1731
ThrowIfNotObject(const ir::AstNode * node,VReg obj)1732 void PandaGen::ThrowIfNotObject(const ir::AstNode *node, VReg obj)
1733 {
1734 ra_.Emit<ThrowIfnotobject>(node, obj);
1735 }
1736
ThrowThrowNotExist(const ir::AstNode * node)1737 void PandaGen::ThrowThrowNotExist(const ir::AstNode *node)
1738 {
1739 ra_.Emit<ThrowNotexists>(node);
1740 }
1741
GetIterator(const ir::AstNode * node)1742 void PandaGen::GetIterator(const ir::AstNode *node)
1743 {
1744 ra_.Emit<Getiterator>(node, 0);
1745 }
1746
GetAsyncIterator(const ir::AstNode * node)1747 void PandaGen::GetAsyncIterator(const ir::AstNode *node)
1748 {
1749 ra_.Emit<Getasynciterator>(node, 0);
1750 }
1751
CreateObjectWithExcludedKeys(const ir::AstNode * node,VReg obj,VReg argStart,size_t argCount)1752 void PandaGen::CreateObjectWithExcludedKeys(const ir::AstNode *node, VReg obj, VReg argStart, size_t argCount)
1753 {
1754 ASSERT(argStart == obj + 1);
1755 if (argCount == 0) {
1756 LoadConst(node, Constant::JS_UNDEFINED);
1757 StoreAccumulator(node, argStart);
1758 }
1759
1760 size_t argRegCnt = (argCount == 0 ? argCount : argCount - 1);
1761
1762 if (argRegCnt <= util::Helpers::MAX_INT8) {
1763 ra_.EmitRange<Createobjectwithexcludedkeys>(node, argCount, static_cast<int64_t>(argRegCnt), obj, argStart);
1764 return;
1765 }
1766
1767 ra_.EmitRange<WideCreateobjectwithexcludedkeys>(node, argCount, static_cast<int64_t>(argRegCnt), obj, argStart);
1768 }
1769
ThrowObjectNonCoercible(const ir::AstNode * node)1770 void PandaGen::ThrowObjectNonCoercible(const ir::AstNode *node)
1771 {
1772 ra_.Emit<ThrowPatternnoncoercible>(node);
1773 }
1774
CloseIterator(const ir::AstNode * node,VReg iter)1775 void PandaGen::CloseIterator(const ir::AstNode *node, VReg iter)
1776 {
1777 ra_.Emit<Closeiterator>(node, 0, iter);
1778 }
1779
DefineClassWithBuffer(const ir::AstNode * node,const util::StringView & ctorId,int32_t litIdx,VReg base)1780 void PandaGen::DefineClassWithBuffer(const ir::AstNode *node, const util::StringView &ctorId, int32_t litIdx, VReg base)
1781 {
1782 auto formalParamCnt = node->AsClassDefinition()->Ctor()->Function()->FormalParamsLength();
1783 std::string idxStr = std::string(context_->Binder()->Program()->RecordName()) + "_" + std::to_string(litIdx);
1784 util::UString litId(idxStr, allocator_);
1785 ra_.Emit<Defineclasswithbuffer>(node, 0, ctorId, litId.View(), static_cast<int64_t>(formalParamCnt), base);
1786 strings_.insert(ctorId);
1787 }
1788
DefineSendableClass(const ir::AstNode * node,const util::StringView & ctorId,int32_t litIdx,VReg base)1789 void PandaGen::DefineSendableClass(const ir::AstNode *node, const util::StringView &ctorId, int32_t litIdx, VReg base)
1790 {
1791 auto formalParamCnt = node->AsClassDefinition()->Ctor()->Function()->FormalParamsLength();
1792 std::string idxStr = std::string(context_->Binder()->Program()->RecordName()) + "_" + std::to_string(litIdx);
1793 util::UString litId(idxStr, allocator_);
1794 ra_.Emit<CallruntimeDefinesendableclass>(node, 0, ctorId, litId.View(), static_cast<int64_t>(formalParamCnt), base);
1795 strings_.insert(ctorId);
1796 }
1797
LoadSendableClass(const ir::AstNode * node,int32_t level)1798 void PandaGen::LoadSendableClass(const ir::AstNode *node, int32_t level)
1799 {
1800 ra_.Emit<CallruntimeLdsendableclass>(node, level);
1801 }
1802
LoadLocalModuleVariable(const ir::AstNode * node,const binder::ModuleVariable * variable)1803 void PandaGen::LoadLocalModuleVariable(const ir::AstNode *node, const binder::ModuleVariable *variable)
1804 {
1805 auto index = variable->Index();
1806 if (inSendable_ &&
1807 Binder()->Program()->TargetApiVersion() >=
1808 util::Helpers::SENDABLE_CLASS_USING_LOCAL_MODULE_VAR_MIN_SUPPORTED_API_VERSION) {
1809 index <= util::Helpers::MAX_INT8 ? ra_.Emit<CallruntimeLdsendablelocalmodulevar>(node, index) :
1810 ra_.Emit<CallruntimeWideldsendablelocalmodulevar>(node, index);
1811 return;
1812 }
1813
1814 index <= util::Helpers::MAX_INT8 ? ra_.Emit<Ldlocalmodulevar>(node, index) :
1815 ra_.Emit<WideLdlocalmodulevar>(node, index);
1816 }
1817
LoadExternalModuleVariable(const ir::AstNode * node,const binder::ModuleVariable * variable)1818 void PandaGen::LoadExternalModuleVariable(const ir::AstNode *node, const binder::ModuleVariable *variable)
1819 {
1820 auto index = variable->Index();
1821
1822 auto targetApiVersion = Binder()->Program()->TargetApiVersion();
1823 bool isLazy = variable->Declaration()->Node()->IsImportSpecifier() ?
1824 variable->Declaration()->Node()->AsImportSpecifier()->IsLazy() : false;
1825 if (!isLazy) {
1826 isLazy = variable->Declaration()->Node()->IsImportDefaultSpecifier() ?
1827 variable->Declaration()->Node()->AsImportDefaultSpecifier()->IsLazy() : false;
1828 }
1829
1830 if (isLazy) {
1831 // Change the behavior of using imported object in sendable class since api12
1832 if (inSendable_ && targetApiVersion >= util::Helpers::SENDABLE_LAZY_LOADING_MIN_SUPPORTED_API_VERSION) {
1833 index <= util::Helpers::MAX_INT8 ? ra_.Emit<CallruntimeLdlazysendablemodulevar>(node, index) :
1834 ra_.Emit<CallruntimeWideldlazysendablemodulevar>(node, index);
1835 return;
1836 }
1837
1838 index <= util::Helpers::MAX_INT8 ? ra_.Emit<CallruntimeLdlazymodulevar>(node, index) :
1839 ra_.Emit<CallruntimeWideldlazymodulevar>(node, index);
1840 return;
1841 }
1842
1843 // Change the behavior of using imported object in sendable class since api12
1844 if (inSendable_ && targetApiVersion >= util::Helpers::SENDABLE_LAZY_LOADING_MIN_SUPPORTED_API_VERSION) {
1845 index <= util::Helpers::MAX_INT8 ? ra_.Emit<CallruntimeLdsendableexternalmodulevar>(node, index) :
1846 ra_.Emit<CallruntimeWideldsendableexternalmodulevar>(node, index);
1847 return;
1848 }
1849
1850 index <= util::Helpers::MAX_INT8 ? ra_.Emit<Ldexternalmodulevar>(node, index) :
1851 ra_.Emit<WideLdexternalmodulevar>(node, index);
1852 }
1853
StoreModuleVariable(const ir::AstNode * node,const binder::ModuleVariable * variable)1854 void PandaGen::StoreModuleVariable(const ir::AstNode *node, const binder::ModuleVariable *variable)
1855 {
1856 auto index = variable->Index();
1857 index <= util::Helpers::MAX_INT8 ? ra_.Emit<Stmodulevar>(node, index) :
1858 ra_.Emit<WideStmodulevar>(node, index);
1859 }
1860
GetModuleNamespace(const ir::AstNode * node,uint32_t index)1861 void PandaGen::GetModuleNamespace(const ir::AstNode *node, uint32_t index)
1862 {
1863 index <= util::Helpers::MAX_INT8 ? ra_.Emit<Getmodulenamespace>(node, index) :
1864 ra_.Emit<WideGetmodulenamespace>(node, index);
1865 }
1866
DynamicImportCall(const ir::AstNode * node)1867 void PandaGen::DynamicImportCall(const ir::AstNode *node)
1868 {
1869 ra_.Emit<Dynamicimport>(node);
1870 }
1871
StSuperByName(const ir::AstNode * node,VReg obj,const util::StringView & key)1872 void PandaGen::StSuperByName(const ir::AstNode *node, VReg obj, const util::StringView &key)
1873 {
1874 ra_.Emit<Stsuperbyname>(node, 0, key, obj);
1875 strings_.insert(key);
1876 }
1877
LdSuperByName(const ir::AstNode * node,VReg obj,const util::StringView & key)1878 void PandaGen::LdSuperByName(const ir::AstNode *node, VReg obj, const util::StringView &key)
1879 {
1880 LoadAccumulator(node, obj); // object is load to acc
1881 ra_.Emit<Ldsuperbyname>(node, 0, key);
1882 strings_.insert(key);
1883 }
1884
StSuperByValue(const ir::AstNode * node,VReg obj,VReg prop)1885 void PandaGen::StSuperByValue(const ir::AstNode *node, VReg obj, VReg prop)
1886 {
1887 ra_.Emit<Stsuperbyvalue>(node, 0, obj, prop);
1888 }
1889
LdSuperByValue(const ir::AstNode * node,VReg obj)1890 void PandaGen::LdSuperByValue(const ir::AstNode *node, VReg obj)
1891 {
1892 ra_.Emit<Ldsuperbyvalue>(node, 0, obj); // prop is in acc
1893 }
1894
StoreSuperProperty(const ir::AstNode * node,VReg obj,const Operand & prop)1895 void PandaGen::StoreSuperProperty(const ir::AstNode *node, VReg obj, const Operand &prop)
1896 {
1897 if (std::holds_alternative<util::StringView>(prop)) {
1898 StSuperByName(node, obj, std::get<util::StringView>(prop));
1899 return;
1900 }
1901
1902 if (std::holds_alternative<VReg>(prop)) {
1903 StSuperByValue(node, obj, std::get<VReg>(prop));
1904 return;
1905 }
1906
1907 ASSERT(std::holds_alternative<int64_t>(prop));
1908 RegScope rs(this);
1909 VReg property = AllocReg();
1910 VReg value = AllocReg();
1911
1912 StoreAccumulator(node, value);
1913 LoadAccumulatorInt(node, static_cast<size_t>(std::get<int64_t>(prop)));
1914 StoreAccumulator(node, property);
1915 LoadAccumulator(node, value);
1916 StSuperByValue(node, obj, property);
1917 }
1918
LoadSuperProperty(const ir::AstNode * node,VReg obj,const Operand & prop)1919 void PandaGen::LoadSuperProperty(const ir::AstNode *node, VReg obj, const Operand &prop)
1920 {
1921 if (std::holds_alternative<util::StringView>(prop)) {
1922 LdSuperByName(node, obj, std::get<util::StringView>(prop));
1923 return;
1924 }
1925
1926 if (std::holds_alternative<VReg>(prop)) {
1927 LoadAccumulator(node, std::get<VReg>(prop));
1928 LdSuperByValue(node, obj);
1929 return;
1930 }
1931
1932 ASSERT(std::holds_alternative<int64_t>(prop));
1933
1934 LoadAccumulatorInt(node, static_cast<size_t>(std::get<int64_t>(prop)));
1935 LdSuperByValue(node, obj);
1936 }
1937
LoadLexicalVar(const ir::AstNode * node,uint32_t level,uint32_t slot)1938 void PandaGen::LoadLexicalVar(const ir::AstNode *node, uint32_t level, uint32_t slot)
1939 {
1940 if ((level > util::Helpers::MAX_INT8) || (slot > util::Helpers::MAX_INT8)) {
1941 ra_.Emit<WideLdlexvar>(node, level, slot);
1942 return;
1943 }
1944
1945 ra_.Emit<Ldlexvar>(node, level, slot);
1946 }
1947
LoadSendableVar(const ir::AstNode * node,uint32_t level,uint32_t slot)1948 void PandaGen::LoadSendableVar(const ir::AstNode *node, uint32_t level, uint32_t slot)
1949 {
1950 if ((level > util::Helpers::MAX_INT8) || (slot > util::Helpers::MAX_INT8)) {
1951 ra_.Emit<CallruntimeWideldsendablevar>(node, level, slot);
1952 return;
1953 }
1954
1955 ra_.Emit<CallruntimeLdsendablevar>(node, level, slot);
1956 }
1957
LoadLexicalVar(const ir::AstNode * node,uint32_t level,uint32_t slot,const util::StringView & name)1958 void PandaGen::LoadLexicalVar(const ir::AstNode *node, uint32_t level, uint32_t slot, const util::StringView &name)
1959 {
1960 if (context_->PatchFixHelper() && context_->PatchFixHelper()->IsAdditionalVarInPatch(slot)) {
1961 uint32_t patchSlot = context_->PatchFixHelper()->GetPatchLexicalIdx(std::string(name));
1962 ra_.Emit<WideLdpatchvar>(node, patchSlot);
1963 return;
1964 }
1965
1966 if ((level > util::Helpers::MAX_INT8) || (slot > util::Helpers::MAX_INT8)) {
1967 ra_.Emit<WideLdlexvar>(node, level, slot);
1968 return;
1969 }
1970
1971 ra_.Emit<Ldlexvar>(node, level, slot);
1972 }
1973
StoreLexicalVar(const ir::AstNode * node,uint32_t level,uint32_t slot)1974 void PandaGen::StoreLexicalVar(const ir::AstNode *node, uint32_t level, uint32_t slot)
1975 {
1976 if ((level > util::Helpers::MAX_INT8) || (slot > util::Helpers::MAX_INT8)) {
1977 ra_.Emit<WideStlexvar>(node, level, slot);
1978 return;
1979 }
1980
1981 ra_.Emit<Stlexvar>(node, level, slot);
1982 }
1983
StoreLexicalVar(const ir::AstNode * node,uint32_t level,uint32_t slot,VReg value)1984 void PandaGen::StoreLexicalVar(const ir::AstNode *node, uint32_t level, uint32_t slot, VReg value)
1985 {
1986 LoadAccumulator(node, value);
1987 if ((level > util::Helpers::MAX_INT8) || (slot > util::Helpers::MAX_INT8)) {
1988 ra_.Emit<WideStlexvar>(node, level, slot);
1989 return;
1990 }
1991
1992 ra_.Emit<Stlexvar>(node, level, slot);
1993 }
1994
StoreSendableVar(const ir::AstNode * node,uint32_t level,uint32_t slot)1995 void PandaGen::StoreSendableVar(const ir::AstNode *node, uint32_t level, uint32_t slot)
1996 {
1997 if ((level > util::Helpers::MAX_INT8) || (slot > util::Helpers::MAX_INT8)) {
1998 ra_.Emit<CallruntimeWidestsendablevar>(node, level, slot);
1999 return;
2000 }
2001
2002 ra_.Emit<CallruntimeStsendablevar>(node, level, slot);
2003 }
2004
StoreLexicalVar(const ir::AstNode * node,uint32_t level,uint32_t slot,const binder::LocalVariable * local)2005 void PandaGen::StoreLexicalVar(const ir::AstNode *node, uint32_t level, uint32_t slot,
2006 const binder::LocalVariable *local)
2007 {
2008 if (context_->PatchFixHelper() && context_->PatchFixHelper()->IsAdditionalVarInPatch(slot)) {
2009 uint32_t patchSlot = context_->PatchFixHelper()->GetPatchLexicalIdx(std::string(local->Name()));
2010 ra_.Emit<WideStpatchvar>(node, patchSlot);
2011 return;
2012 }
2013 RegScope rs(this);
2014 VReg value = AllocReg();
2015 StoreAccumulator(node, value);
2016 StoreLexicalVar(node, level, slot, value);
2017 }
2018
ThrowIfSuperNotCorrectCall(const ir::AstNode * node,int64_t num)2019 void PandaGen::ThrowIfSuperNotCorrectCall(const ir::AstNode *node, int64_t num)
2020 {
2021 ra_.Emit<ThrowIfsupernotcorrectcall>(node, num);
2022 }
2023
ThrowUndefinedIfHole(const ir::AstNode * node,const util::StringView & name)2024 void PandaGen::ThrowUndefinedIfHole(const ir::AstNode *node, const util::StringView &name)
2025 {
2026 ra_.Emit<ThrowUndefinedifholewithname>(node, name);
2027 strings_.insert(name);
2028 }
2029
ThrowConstAssignment(const ir::AstNode * node,const util::StringView & name)2030 void PandaGen::ThrowConstAssignment(const ir::AstNode *node, const util::StringView &name)
2031 {
2032 RegScope rs(this);
2033 LoadAccumulatorString(node, name);
2034 VReg nameReg = AllocReg();
2035 StoreAccumulator(node, nameReg);
2036 ra_.Emit<ThrowConstassignment>(node, nameReg);
2037 strings_.insert(name);
2038 }
2039
PopLexEnv(const ir::AstNode * node)2040 void PandaGen::PopLexEnv(const ir::AstNode *node)
2041 {
2042 ra_.Emit<Poplexenv>(node);
2043 }
2044
GenDebugger(const ir::AstNode * node)2045 void PandaGen::GenDebugger(const ir::AstNode *node)
2046 {
2047 if (IsDebug()) {
2048 ra_.Emit<Debugger>(node);
2049 }
2050 }
2051
NewLexicalEnv(const ir::AstNode * node,uint32_t num,binder::VariableScope * scope)2052 void PandaGen::NewLexicalEnv(const ir::AstNode *node, uint32_t num, binder::VariableScope *scope)
2053 {
2054 if (IsDebug()) {
2055 int32_t scopeInfoIdx = AddLexicalVarNamesForDebugInfo(scope->GetLexicalVarNameAndTypes());
2056 NewLexEnvWithScopeInfo(node, num, scopeInfoIdx);
2057 return;
2058 }
2059
2060 NewLexEnv(node, num);
2061 }
2062
NewLexEnv(const ir::AstNode * node,uint32_t num)2063 void PandaGen::NewLexEnv(const ir::AstNode *node, uint32_t num)
2064 {
2065 num <= util::Helpers::MAX_INT8 ? ra_.Emit<Newlexenv>(node, num) : ra_.Emit<WideNewlexenv>(node, num);
2066 }
2067
NewSendableEnv(const ir::AstNode * node,uint32_t num)2068 void PandaGen::NewSendableEnv(const ir::AstNode * node, uint32_t num)
2069 {
2070 num <= util::Helpers::MAX_INT8 ? ra_.Emit<CallruntimeNewsendableenv>(node, num) :
2071 ra_.Emit<CallruntimeWidenewsendableenv>(node, num);
2072 }
2073
NewLexEnvWithScopeInfo(const ir::AstNode * node,uint32_t num,int32_t scopeInfoIdx)2074 void PandaGen::NewLexEnvWithScopeInfo(const ir::AstNode *node, uint32_t num, int32_t scopeInfoIdx)
2075 {
2076 std::string idxStr = std::string(context_->Binder()->Program()->RecordName()) + "_" + std::to_string(scopeInfoIdx);
2077 util::UString litId(idxStr, allocator_);
2078 num <= util::Helpers::MAX_INT8 ? ra_.Emit<Newlexenvwithname>(node, num, litId.View()) :
2079 ra_.Emit<WideNewlexenvwithname>(node, num, litId.View());
2080 }
2081
TryDepth() const2082 uint32_t PandaGen::TryDepth() const
2083 {
2084 const auto *iter = dynamicContext_;
2085 uint32_t depth = 0;
2086
2087 while (iter) {
2088 if (iter->HasTryCatch()) {
2089 depth++;
2090 }
2091
2092 iter = iter->Prev();
2093 }
2094
2095 return depth;
2096 }
2097
CreateCatchTable()2098 CatchTable *PandaGen::CreateCatchTable()
2099 {
2100 auto *catchTable = allocator_->New<CatchTable>(this, TryDepth());
2101 CHECK_NOT_NULL(catchTable);
2102 catchList_.push_back(catchTable);
2103 return catchTable;
2104 }
2105
SortCatchTables()2106 void PandaGen::SortCatchTables()
2107 {
2108 std::sort(catchList_.begin(), catchList_.end(),
2109 [](const CatchTable *a, const CatchTable *b) { return b->Depth() < a->Depth(); });
2110 }
2111
ToNamedPropertyKey(const ir::Expression * prop,bool isComputed)2112 Operand PandaGen::ToNamedPropertyKey(const ir::Expression *prop, bool isComputed)
2113 {
2114 VReg res {0};
2115
2116 if (isComputed) {
2117 return res;
2118 }
2119
2120 if (prop->IsIdentifier()) {
2121 return prop->AsIdentifier()->Name();
2122 }
2123
2124 if (prop->IsStringLiteral()) {
2125 const util::StringView &str = prop->AsStringLiteral()->Str();
2126
2127 // remove this when runtime handles __proto__ as property name correctly
2128 if (str.Is("__proto__")) {
2129 return res;
2130 }
2131
2132 int64_t index = util::Helpers::GetIndex(str);
2133 if (index != util::Helpers::INVALID_INDEX) {
2134 return index;
2135 }
2136
2137 return str;
2138 }
2139
2140 if (prop->IsNumberLiteral()) {
2141 auto num = prop->AsNumberLiteral()->Number<double>();
2142 if (util::Helpers::IsIndex(num)) {
2143 return static_cast<int64_t>(num);
2144 }
2145
2146 return util::Helpers::ToStringView(allocator_, num);
2147 }
2148
2149 return res;
2150 }
2151
ToPropertyKey(const ir::Expression * prop,bool isComputed)2152 Operand PandaGen::ToPropertyKey(const ir::Expression *prop, bool isComputed)
2153 {
2154 Operand op = ToNamedPropertyKey(prop, isComputed);
2155 if (std::holds_alternative<util::StringView>(op) || (std::holds_alternative<int64_t>(op) &&
2156 (std::get<int64_t>(op) <= util::Helpers::MAX_INT32))) {
2157 return op;
2158 }
2159
2160 VReg propReg = AllocReg();
2161
2162 /**
2163 * Store index to vreg when index > MAX_INT32 to simplify ASM interpreter If byindex-related instructions support
2164 * index > MAX_INT32, ASM interpreter will have to add a judgment whether index needs more than 32 bits which will
2165 * cause inefficiency of it since cases when index > MAX_INT32 can be quite rare
2166 **/
2167 if (std::holds_alternative<int64_t>(op) && (std::get<int64_t>(op) > util::Helpers::MAX_INT32)) {
2168 LoadAccumulatorFloat(prop, std::get<int64_t>(op));
2169 StoreAccumulator(prop, propReg);
2170 return propReg;
2171 }
2172
2173 ASSERT(std::holds_alternative<VReg>(op));
2174 prop->Compile(this);
2175 StoreAccumulator(prop, propReg);
2176
2177 return propReg;
2178 }
2179
LoadPropertyKey(const ir::Expression * prop,bool isComputed)2180 VReg PandaGen::LoadPropertyKey(const ir::Expression *prop, bool isComputed)
2181 {
2182 Operand op = ToNamedPropertyKey(prop, isComputed);
2183 if (std::holds_alternative<util::StringView>(op)) {
2184 LoadAccumulatorString(prop, std::get<util::StringView>(op));
2185 } else if (std::holds_alternative<int64_t>(op)) {
2186 LoadAccumulatorInt(prop, static_cast<size_t>(std::get<int64_t>(op)));
2187 } else {
2188 prop->Compile(this);
2189 }
2190
2191 VReg propReg = AllocReg();
2192 StoreAccumulator(prop, propReg);
2193
2194 return propReg;
2195 }
2196
ToComputedPropertyKey(const ir::AstNode * node)2197 void PandaGen::ToComputedPropertyKey(const ir::AstNode *node)
2198 {
2199 ra_.Emit<CallruntimeTopropertykey>(node);
2200 }
2201
StLetOrClassToGlobalRecord(const ir::AstNode * node,const util::StringView & name)2202 void PandaGen::StLetOrClassToGlobalRecord(const ir::AstNode *node, const util::StringView &name)
2203 {
2204 ra_.Emit<Sttoglobalrecord>(node, 0, name);
2205 strings_.insert(name);
2206 }
2207
StConstToGlobalRecord(const ir::AstNode * node,const util::StringView & name)2208 void PandaGen::StConstToGlobalRecord(const ir::AstNode *node, const util::StringView &name)
2209 {
2210 ra_.Emit<Stconsttoglobalrecord>(node, 0, name);
2211 strings_.insert(name);
2212 }
2213
TryCompileFunctionCallOrNewExpression(const ir::Expression * expr)2214 bool PandaGen::TryCompileFunctionCallOrNewExpression(const ir::Expression *expr)
2215 {
2216 ASSERT(expr->IsCallExpression() || expr->IsNewExpression());
2217 const auto *callee = expr->IsCallExpression() ? expr->AsCallExpression()->Callee() :
2218 expr->AsNewExpression()->Callee();
2219
2220 if (!callee->IsIdentifier()) {
2221 return false;
2222 }
2223
2224 if (callee->AsIdentifier()->Name().Is("Function")) {
2225 auto arguments = expr->IsCallExpression() ? expr->AsCallExpression()->Arguments() :
2226 expr->AsNewExpression()->Arguments();
2227 if (arguments.empty()) {
2228 return false;
2229 }
2230
2231 auto *arg = arguments[arguments.size() - 1];
2232 if (!arg->IsStringLiteral()) {
2233 return false;
2234 }
2235
2236 if (std::regex_match(arg->AsStringLiteral()->Str().Mutf8(), std::regex(" *return +this[;]? *$"))) {
2237 LoadConst(arg, Constant::JS_GLOBAL);
2238 return true;
2239 }
2240 }
2241
2242 return false;
2243 }
2244
ReArrangeIc()2245 void PandaGen::ReArrangeIc()
2246 {
2247 if (!IsIcOverFlow()) {
2248 return;
2249 }
2250
2251 ResetCurrentSlot(0);
2252
2253 for (auto *ins: Insns()) {
2254 if (!ins->InlineCacheEnabled()) {
2255 continue;
2256 }
2257
2258 if (ins->oneByteSlotOnly()) {
2259 auto inc = ins->SetIcSlot(GetCurrentSlot());
2260 IncreaseCurrentSlot(inc);
2261 }
2262 }
2263
2264 for (auto *ins: Insns()) {
2265 if (!ins->InlineCacheEnabled()) {
2266 continue;
2267 }
2268
2269 if (ins->oneByteSlotOnly()) {
2270 continue;
2271 }
2272
2273 auto inc = ins->SetIcSlot(GetCurrentSlot());
2274 IncreaseCurrentSlot(inc);
2275 }
2276 }
2277
CreatePrivateProperty(const ir::AstNode * node,uint32_t num,int32_t bufIdx)2278 void PandaGen::CreatePrivateProperty(const ir::AstNode *node, uint32_t num, int32_t bufIdx)
2279 {
2280 std::string idxStr = std::string(context_->Binder()->Program()->RecordName()) + "_" + std::to_string(bufIdx);
2281 util::UString litId(idxStr, allocator_);
2282 ra_.Emit<CallruntimeCreateprivateproperty>(node, num, litId.View());
2283 }
2284
TestIn(const ir::AstNode * node,uint32_t level,uint32_t slot)2285 void PandaGen::TestIn(const ir::AstNode *node, uint32_t level, uint32_t slot)
2286 {
2287 ra_.Emit<Testin>(node, 0, level, slot);
2288 }
2289
LoadPrivateProperty(const ir::AstNode * node,uint32_t level,uint32_t slot)2290 void PandaGen::LoadPrivateProperty(const ir::AstNode *node, uint32_t level, uint32_t slot)
2291 {
2292 ra_.Emit<Ldprivateproperty>(node, 0, level, slot);
2293 }
2294
StorePrivateProperty(const ir::AstNode * node,uint32_t level,uint32_t slot,VReg obj)2295 void PandaGen::StorePrivateProperty(const ir::AstNode *node, uint32_t level, uint32_t slot, VReg obj)
2296 {
2297 ra_.Emit<Stprivateproperty>(node, 0, level, slot, obj);
2298 }
ThrowTypeErrorIfFalse(const ir::AstNode * node,util::StringView str)2299 void PandaGen::ThrowTypeErrorIfFalse(const ir::AstNode *node, util::StringView str)
2300 {
2301 auto *trueLabel = AllocLabel();
2302 BranchIfTrue(node, trueLabel);
2303 ThrowTypeError(node, str);
2304 SetLabel(node, trueLabel);
2305 }
2306
ThrowTypeError(const ir::AstNode * node,util::StringView str)2307 void PandaGen::ThrowTypeError(const ir::AstNode *node, util::StringView str)
2308 {
2309 LoadAccumulatorString(node, str);
2310 VReg reg = AllocReg();
2311 StoreAccumulator(node, reg);
2312 TryLoadGlobalByName(node, "TypeError");
2313 ra_.Emit<Callarg1>(node, 0, reg);
2314 EmitThrow(node);
2315 }
2316
2317 } // namespace panda::es2panda::compiler
2318