• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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/compiler/call_stub_builder.h"
17 
18 #include <cstddef>
19 #include <tuple>
20 
21 #include "ecmascript/compiler/bytecodes.h"
22 #include "ecmascript/compiler/circuit_builder.h"
23 #include "ecmascript/compiler/slowpath_lowering.h"
24 #include "ecmascript/compiler/stub_builder-inl.h"
25 
26 namespace panda::ecmascript::kungfu {
27 
JSCallDispatchForBaseline(Label * exit,Label * noNeedCheckException)28 void CallStubBuilder::JSCallDispatchForBaseline(Label *exit, Label *noNeedCheckException)
29 {
30     this->isForBaseline_ = true;
31     auto env = GetEnvironment();
32     baselineBuiltinFp_ = CallNGCRuntime(glue_, RTSTUB_ID(GetBaselineBuiltinFp), {glue_});
33 
34     // 1. call initialize
35     Label funcIsHeapObject(env);
36     Label funcIsCallable(env);
37     Label funcNotCallable(env);
38     JSCallInit(exit, &funcIsHeapObject, &funcIsCallable, &funcNotCallable);
39 
40     // 2. dispatch
41     Label methodIsNative(env);
42     Label methodNotNative(env);
43     BRANCH(Int64NotEqual(Int64And(callField_, isNativeMask_), Int64(0)), &methodIsNative, &methodNotNative);
44 
45     // 3. call native
46     Bind(&methodIsNative);
47     {
48         JSCallNative(exit);
49     }
50 
51     // 4. call nonNative
52     Bind(&methodNotNative);
53     {
54         JSCallJSFunction(exit, noNeedCheckException);
55     }
56 }
57 
GetOpInfo()58 std::tuple<bool, size_t, size_t> CallCoStubBuilder::GetOpInfo()
59 {
60     switch (op_) {
61         case EcmaOpcode::CALLTHIS0_IMM8_V8:
62             return std::make_tuple(true, 2, 0);        // needThis: true, numberValueIn: 2, numberArg: 0
63         case EcmaOpcode::CALLTHIS1_IMM8_V8_V8:
64             return std::make_tuple(true, 3, 1);        // needThis: true, numberValueIn: 3, numberArg: 1
65         case EcmaOpcode::CALLTHIS2_IMM8_V8_V8_V8:
66             return std::make_tuple(true, 4, 2);	       // needThis: true, numberValueIn: 4, numberArg: 2
67         case EcmaOpcode::CALLTHIS3_IMM8_V8_V8_V8_V8:
68             return std::make_tuple(true, 5, 3);        // needThis: true, numberValueIn: 5, numberArg: 3
69         case EcmaOpcode::CALLARG0_IMM8:
70             return std::make_tuple(false, 1, 0);       // needThis: false, numberValueIn: 1, numberArg: 0
71         case EcmaOpcode::CALLARG1_IMM8_V8:
72             return std::make_tuple(false, 2, 1);       // needThis: false, numberValueIn: 2, numberArg: 1
73         case EcmaOpcode::CALLARGS2_IMM8_V8_V8:
74             return std::make_tuple(false, 3, 2);       // needThis: false, numberValueIn: 3, numberArg: 2
75         case EcmaOpcode::CALLARGS3_IMM8_V8_V8_V8:
76             return std::make_tuple(false, 4, 3);       // needThis: false, numberValueIn: 4, numberArg: 3
77         default:
78             LOG_ECMA(FATAL) << "this branch is unreachable";
79             UNREACHABLE();
80     }
81 }
82 
PrepareArgs(std::vector<GateRef> & args,std::vector<GateRef> & argsFastCall)83 void CallCoStubBuilder::PrepareArgs(std::vector<GateRef> &args, std::vector<GateRef> &argsFastCall)
84 {
85     auto env = GetEnvironment();
86     auto &builder =  *env->GetBuilder();
87     auto [needThis, numberValueIn, numberArg] = GetOpInfo();
88     actualArgc_ = builder.Int64(BytecodeCallArgc::ComputeCallArgc(numberValueIn, op_));
89     actualArgv_ = builder.IntPtr(0);
90     newTarget_ = builder.Undefined();
91     thisObj_ = builder.Undefined();
92     hirGate_ = Circuit::NullGate();
93 
94     size_t argIndex = 0;
95     glue_ = PtrArgument(argIndex++);
96     func_ = TaggedArgument(argIndex++);
97 
98     // keep same with CommonArgIdx
99     args.push_back(glue_);
100     args.push_back(actualArgc_);
101     args.push_back(actualArgv_);
102     args.push_back(func_);
103     args.push_back(newTarget_);
104 
105     // keep same with FastCallArgIdx
106     argsFastCall.push_back(glue_);
107     argsFastCall.push_back(func_);
108 
109     // solve thisobj
110     if (needThis) {
111         thisObj_ = TaggedArgument(argIndex++);
112     }
113     args.push_back(thisObj_);
114     argsFastCall.push_back(thisObj_);
115 
116     // solve args
117     for (size_t i = 0; i < numberArg; i++) {
118         args.push_back(TaggedArgument(argIndex));
119         argsFastCall.push_back(TaggedArgument(argIndex));
120         argIndex++;
121     }
122 }
123 
LowerFastCall(GateRef gate,GateRef glue,CircuitBuilder & builder,GateRef func,GateRef argc,const std::vector<GateRef> & args,const std::vector<GateRef> & argsFastCall,Variable * result,Label * exit,bool isNew)124 void CallCoStubBuilder::LowerFastCall(GateRef gate, GateRef glue, CircuitBuilder &builder, GateRef func, GateRef argc,
125     const std::vector<GateRef> &args, const std::vector<GateRef> &argsFastCall,
126     Variable *result, Label *exit, bool isNew)
127 {
128     Label isHeapObject(&builder);
129     Label isJsFcuntion(&builder);
130     Label fastCall(&builder);
131     Label notFastCall(&builder);
132     Label call(&builder);
133     Label call1(&builder);
134     Label slowCall(&builder);
135     Label callBridge(&builder);
136     Label callBridge1(&builder);
137     Label slowPath(&builder);
138     Label notCallConstructor(&builder);
139     Label isCallConstructor(&builder);
140     // use builder_ to make BRANCH_CIR work.
141     auto &builder_ = builder;
142     BRANCH_CIR(builder.TaggedIsHeapObject(func), &isHeapObject, &slowPath);
143     builder.Bind(&isHeapObject);
144     {
145         BRANCH_CIR(builder.IsJSFunction(func), &isJsFcuntion, &slowPath);
146         builder.Bind(&isJsFcuntion);
147         {
148             if (!isNew) {
149                 BRANCH_CIR(builder.IsClassConstructor(func), &slowPath, &notCallConstructor);
150                 builder.Bind(&notCallConstructor);
151             }
152             GateRef method = builder.GetMethodFromFunction(func);
153             BRANCH_CIR(builder.JudgeAotAndFastCall(func,
154                 CircuitBuilder::JudgeMethodType::HAS_AOT_FASTCALL), &fastCall, &notFastCall);
155             builder.Bind(&fastCall);
156             {
157                 GateRef expectedArgc = builder.Int64Add(builder.GetExpectedNumOfArgs(method),
158                     builder.Int64(NUM_MANDATORY_JSFUNC_ARGS));
159                 BRANCH_CIR(builder.Equal(expectedArgc, argc), &call, &callBridge);
160                 builder.Bind(&call);
161                 {
162                     builder.StartCallTimer(glue, gate, {glue, func, builder.True()}, true);
163                     GateRef code = builder.GetCodeAddr(func);
164                     auto depend = builder.GetDepend();
165                     const CallSignature *cs = RuntimeStubCSigns::GetOptimizedFastCallSign();
166                     result->WriteVariable(builder.Call(cs, glue, code, depend, argsFastCall, gate, "callFastAOT"));
167                     builder.EndCallTimer(glue, gate, {glue, func}, true);
168                     builder.Jump(exit);
169                 }
170                 builder.Bind(&callBridge);
171                 {
172                     builder.StartCallTimer(glue, gate, {glue, func, builder.True()}, true);
173                     const CallSignature *cs = RuntimeStubCSigns::Get(RTSTUB_ID(OptimizedFastCallAndPushArgv));
174                     GateRef target = builder.IntPtr(RTSTUB_ID(OptimizedFastCallAndPushArgv));
175                     auto depend = builder.GetDepend();
176                     result->WriteVariable(builder.Call(cs, glue, target, depend, args, gate, "callFastBridge"));
177                     builder.EndCallTimer(glue, gate, {glue, func}, true);
178                     builder.Jump(exit);
179                 }
180             }
181             builder.Bind(&notFastCall);
182             BRANCH_CIR(builder.JudgeAotAndFastCall(func, CircuitBuilder::JudgeMethodType::HAS_AOT),
183                 &slowCall, &slowPath);
184             builder.Bind(&slowCall);
185             {
186                 GateRef expectedArgc = builder.Int64Add(builder.GetExpectedNumOfArgs(method),
187                     builder.Int64(NUM_MANDATORY_JSFUNC_ARGS));
188                 BRANCH_CIR(builder.Equal(expectedArgc, argc), &call1, &callBridge1);
189                 builder.Bind(&call1);
190                 {
191                     builder.StartCallTimer(glue, gate, {glue, func, builder.True()}, true);
192                     GateRef code = builder.GetCodeAddr(func);
193                     auto depend = builder.GetDepend();
194                     const CallSignature *cs = RuntimeStubCSigns::GetOptimizedCallSign();
195                     result->WriteVariable(builder.Call(cs, glue, code, depend, args, gate, "callAOT"));
196                     builder.EndCallTimer(glue, gate, {glue, func}, true);
197                     builder.Jump(exit);
198                 }
199                 builder.Bind(&callBridge1);
200                 {
201                     builder.StartCallTimer(glue, gate, {glue, func, builder.True()}, true);
202                     const CallSignature *cs = RuntimeStubCSigns::Get(RTSTUB_ID(OptimizedCallAndPushArgv));
203                     GateRef target = builder.IntPtr(RTSTUB_ID(OptimizedCallAndPushArgv));
204                     auto depend = builder.GetDepend();
205                     result->WriteVariable(builder.Call(cs, glue, target, depend, args, gate, "callBridge"));
206                     builder.EndCallTimer(glue, gate, {glue, func}, true);
207                     builder.Jump(exit);
208                 }
209             }
210         }
211     }
212     builder.Bind(&slowPath);
213     {
214         if (isNew) {
215             builder.StartCallTimer(glue, gate, {glue, func, builder.True()}, true);
216             const CallSignature *cs = RuntimeStubCSigns::Get(RTSTUB_ID(JSCallNew));
217             GateRef target = builder.IntPtr(RTSTUB_ID(JSCallNew));
218             auto depend = builder.GetDepend();
219             result->WriteVariable(builder.Call(cs, glue, target, depend, args, gate, "slowNew"));
220             builder.EndCallTimer(glue, gate, {glue, func}, true);
221             builder.Jump(exit);
222         } else {
223             builder.StartCallTimer(glue, gate, {glue, func, builder.True()}, true);
224             const CallSignature *cs = RuntimeStubCSigns::Get(RTSTUB_ID(JSCall));
225             GateRef target = builder.IntPtr(RTSTUB_ID(JSCall));
226             auto depend = builder.GetDepend();
227             result->WriteVariable(builder.Call(cs, glue, target, depend, args, gate, "jscall"));
228             builder.EndCallTimer(glue, gate, {glue, func}, true);
229             builder.Jump(exit);
230         }
231     }
232 }
233 
CallStubDispatch()234 GateRef CallCoStubBuilder::CallStubDispatch()
235 {
236     std::vector<GateRef> args = {};
237     std::vector<GateRef> argsFastCall = {};
238     PrepareArgs(args, argsFastCall);
239 
240     auto env = GetEnvironment();
241     auto &builder =  *env->GetBuilder();
242     Label entry(env);
243     Label exit(env);
244     env->SubCfgEntry(&entry);
245 
246     DEFVARIABLE(result, VariableType::JS_ANY(), builder.Undefined());
247     LowerFastCall(hirGate_, glue_, builder, func_, actualArgc_, args, argsFastCall,
248                   &result, &exit, false);
249     Bind(&exit);
250     auto ret = *result;
251     env->SubCfgExit();
252     return ret;
253 }
254 
JSCallDispatch()255 GateRef CallStubBuilder::JSCallDispatch()
256 {
257     this->isForBaseline_ = false;
258     auto env = GetEnvironment();
259     Label entryPass(env);
260     Label exit(env);
261     env->SubCfgEntry(&entryPass);
262     DEFVARIABLE(result, VariableType::JS_ANY(), Exception());
263 
264     this->result_ = &result;
265 
266     // 1. call initialize
267     Label funcIsHeapObject(env);
268     Label funcIsCallable(env);
269     Label funcNotCallable(env);
270     JSCallInit(&exit, &funcIsHeapObject, &funcIsCallable, &funcNotCallable);
271 
272     // 2. dispatch
273     Label methodIsNative(env);
274     Label methodNotNative(env);
275     BRANCH(Int64NotEqual(Int64And(callField_, isNativeMask_), Int64(0)), &methodIsNative, &methodNotNative);
276 
277     // 3. call native
278     Bind(&methodIsNative);
279     {
280         JSCallNative(&exit);
281     }
282     // 4. call nonNative
283     Bind(&methodNotNative);
284     {
285         JSCallJSFunction(&exit);
286     }
287 
288     Bind(&exit);
289     auto ret = *result;
290     env->SubCfgExit();
291     return ret;
292 }
293 
JSCallInit(Label * exit,Label * funcIsHeapObject,Label * funcIsCallable,Label * funcNotCallable)294 void CallStubBuilder::JSCallInit(Label *exit, Label *funcIsHeapObject, Label *funcIsCallable, Label *funcNotCallable)
295 {
296     if (!isForBaseline_) {
297         // save pc
298         SavePcIfNeeded(glue_);
299     }
300 #if ECMASCRIPT_ENABLE_FUNCTION_CALL_TIMER
301     CallNGCRuntime(glue_, RTSTUB_ID(StartCallTimer, { glue_, func_, False()}));
302 #endif
303     if (checkIsCallable_) {
304         BRANCH_LIKELY(TaggedIsHeapObject(func_), funcIsHeapObject, funcNotCallable);
305         Bind(funcIsHeapObject);
306         GateRef hclass = LoadHClass(func_);
307         bitfield_ = Load(VariableType::INT32(), hclass, IntPtr(JSHClass::BIT_FIELD_OFFSET));
308         BRANCH_LIKELY(IsCallableFromBitField(bitfield_), funcIsCallable, funcNotCallable);
309         Bind(funcNotCallable);
310         {
311             CallRuntime(glue_, RTSTUB_ID(ThrowNotCallableException), {});
312             Jump(exit);
313         }
314         Bind(funcIsCallable);
315     } else {
316         GateRef hclass = LoadHClass(func_);
317         bitfield_ = Load(VariableType::INT32(), hclass, IntPtr(JSHClass::BIT_FIELD_OFFSET));
318     }
319     method_ = GetMethodFromJSFunctionOrProxy(func_);
320     callField_ = GetCallFieldFromMethod(method_);
321     isNativeMask_ = Int64(static_cast<uint64_t>(1) << MethodLiteral::IsNativeBit::START_BIT);
322 }
323 
JSCallNative(Label * exit)324 void CallStubBuilder::JSCallNative(Label *exit)
325 {
326     HandleProfileNativeCall();
327     newTarget_ = Undefined();
328     thisValue_ = Undefined();
329     numArgs_ = Int32Add(actualNumArgs_, Int32(NUM_MANDATORY_JSFUNC_ARGS));
330     auto env = GetEnvironment();
331     Label jsProxy(env);
332     Label notJsProxy(env);
333     BRANCH(IsJsProxy(func_), &jsProxy, &notJsProxy);
334     Bind(&jsProxy);
335     {
336         JSCallNativeInner(exit, true);
337     }
338     Bind(&notJsProxy);
339     {
340         JSCallNativeInner(exit, false);
341     }
342 }
343 
JSCallNativeInner(Label * exit,bool isJsProxy)344 void CallStubBuilder::JSCallNativeInner(Label *exit, bool isJsProxy)
345 {
346     if (isJsProxy) {
347         nativeCode_ = Load(VariableType::NATIVE_POINTER(), method_,
348             IntPtr(Method::NATIVE_POINTER_OR_BYTECODE_ARRAY_OFFSET));
349     } else {
350         nativeCode_ = Load(VariableType::NATIVE_POINTER(), func_, IntPtr(JSFunctionBase::CODE_ENTRY_OFFSET));
351     }
352     GateRef ret;
353     int idxForNative = PrepareIdxForNative();
354     std::vector<GateRef> argsForNative = PrepareArgsForNative();
355     auto env = GetEnvironment();
356     Label notFastBuiltins(env);
357     switch (callArgs_.mode) {
358         case JSCallMode::CALL_THIS_ARG0:
359         case JSCallMode::CALL_THIS_ARG1:
360         case JSCallMode::CALL_THIS_ARG2:
361         case JSCallMode::CALL_THIS_ARG3:
362         case JSCallMode::CALL_THIS_ARG2_WITH_RETURN:
363         case JSCallMode::CALL_CONSTRUCTOR_WITH_ARGV:
364         case JSCallMode::DEPRECATED_CALL_CONSTRUCTOR_WITH_ARGV:
365             if (!isJsProxy) {
366                 GateRef numArgsKeeper = numArgs_;
367                 CallFastBuiltin(&notFastBuiltins, exit, hir_);
368                 Bind(&notFastBuiltins);
369                 numArgs_ = numArgsKeeper;
370             }
371             [[fallthrough]];
372         case JSCallMode::CALL_ARG0:
373         case JSCallMode::CALL_ARG1:
374         case JSCallMode::CALL_ARG2:
375         case JSCallMode::CALL_ARG3:
376         case JSCallMode::CALL_WITH_ARGV:
377         case JSCallMode::CALL_THIS_WITH_ARGV:
378         case JSCallMode::DEPRECATED_CALL_ARG0:
379         case JSCallMode::DEPRECATED_CALL_ARG1:
380         case JSCallMode::DEPRECATED_CALL_ARG2:
381         case JSCallMode::DEPRECATED_CALL_ARG3:
382         case JSCallMode::DEPRECATED_CALL_WITH_ARGV:
383         case JSCallMode::DEPRECATED_CALL_THIS_WITH_ARGV:
384         case JSCallMode::CALL_GETTER:
385         case JSCallMode::CALL_SETTER:
386         case JSCallMode::CALL_THIS_ARG3_WITH_RETURN:
387         case JSCallMode::CALL_THIS_ARGV_WITH_RETURN:
388             ret = CallNGCRuntime(glue_, idxForNative, argsForNative, hir_);
389             break;
390         case JSCallMode::SUPER_CALL_WITH_ARGV:
391         case JSCallMode::SUPER_CALL_SPREAD_WITH_ARGV:
392             ret = CallRuntime(glue_, idxForNative, argsForNative);
393             break;
394         default:
395             LOG_ECMA(FATAL) << "this branch is unreachable";
396             UNREACHABLE();
397     }
398     result_->WriteVariable(ret);
399     Jump(exit);
400 }
401 
JSCallJSFunction(Label * exit,Label * noNeedCheckException)402 void CallStubBuilder::JSCallJSFunction(Label *exit, Label *noNeedCheckException)
403 {
404     auto env = GetEnvironment();
405 
406     Label funcIsClassConstructor(env);
407     Label funcNotClassConstructor(env);
408     Label methodNotAot(env);
409 
410     if (!AssemblerModule::IsCallNew(callArgs_.mode)) {
411         BRANCH(IsClassConstructorFromBitField(bitfield_), &funcIsClassConstructor, &funcNotClassConstructor);
412         Bind(&funcIsClassConstructor);
413         {
414             CallRuntime(glue_, RTSTUB_ID(ThrowCallConstructorException), {});
415             Jump(exit);
416         }
417         Bind(&funcNotClassConstructor);
418     }
419     HandleProfileCall();
420     if (isForBaseline_ && env->IsBaselineBuiltin()) {
421         sp_ = Argument(static_cast<size_t>(BaselineCallInputs::SP));
422     }
423     if (!isForBaseline_ && env->IsAsmInterp()) {
424         sp_ = Argument(static_cast<size_t>(InterpreterHandlerInputs::SP));
425     }
426     Label methodisAot(env);
427     Label funcHasBaselineCode(env);
428     Label funcCheckBaselineCode(env);
429     Label checkIsBaselineCompiling(env);
430     Label methodIsFastCall(env);
431     Label methodNotFastCall(env);
432     Label checkAot(env);
433     {
434         newTarget_ = Undefined();
435         thisValue_ = Undefined();
436         realNumArgs_ = Int64Add(ZExtInt32ToInt64(actualNumArgs_), Int64(NUM_MANDATORY_JSFUNC_ARGS));
437         BRANCH(IsJsProxy(func_), &methodNotAot, &checkAot);
438         Bind(&checkAot);
439         BRANCH(JudgeAotAndFastCall(func_, CircuitBuilder::JudgeMethodType::HAS_AOT_FASTCALL), &methodIsFastCall,
440             &methodNotFastCall);
441         Bind(&methodIsFastCall);
442         {
443             JSFastAotCall(exit);
444         }
445 
446         Bind(&methodNotFastCall);
447         BRANCH(JudgeAotAndFastCall(func_, CircuitBuilder::JudgeMethodType::HAS_AOT), &methodisAot,
448             &funcCheckBaselineCode);
449         Bind(&methodisAot);
450         {
451             JSSlowAotCall(exit);
452         }
453 
454         Bind(&funcCheckBaselineCode);
455         GateRef baselineCodeOffset = IntPtr(JSFunction::BASELINECODE_OFFSET);
456         GateRef baselineCode = Load(VariableType::JS_POINTER(), func_, baselineCodeOffset);
457 
458         Branch(NotEqual(baselineCode, Undefined()), &checkIsBaselineCompiling, &methodNotAot);
459         Bind(&checkIsBaselineCompiling);
460         Branch(NotEqual(baselineCode, Hole()), &funcHasBaselineCode, &methodNotAot);
461 
462         Bind(&funcHasBaselineCode);
463         {
464             GateRef res = result_->Value();
465             JSCallAsmInterpreter(true, exit, noNeedCheckException);
466             (void) res;
467         }
468 
469         Bind(&methodNotAot);
470         {
471             JSCallAsmInterpreter(false, exit, noNeedCheckException);
472         }
473     }
474 }
475 
JSFastAotCall(Label * exit)476 void CallStubBuilder::JSFastAotCall(Label *exit)
477 {
478     auto env = GetEnvironment();
479     Label fastCall(env);
480     Label fastCallBridge(env);
481     isFast_ = true;
482 
483     GateRef expectedNum = Int64And(Int64LSR(callField_, Int64(MethodLiteral::NumArgsBits::START_BIT)),
484         Int64((1LU << MethodLiteral::NumArgsBits::SIZE) - 1));
485     GateRef expectedArgc = Int64Add(expectedNum, Int64(NUM_MANDATORY_JSFUNC_ARGS));
486     BRANCH(Int64Equal(expectedArgc, realNumArgs_), &fastCall, &fastCallBridge);
487     GateRef code;
488     Bind(&fastCall);
489     {
490         isBridge_ = false;
491         code = GetAotCodeAddr(func_);
492         CallBridge(code, expectedNum, exit);
493     }
494     Bind(&fastCallBridge);
495     {
496         isBridge_ = true;
497         CallBridge(code, expectedNum, exit);
498     }
499 }
500 
JSSlowAotCall(Label * exit)501 void CallStubBuilder::JSSlowAotCall(Label *exit)
502 {
503     auto env = GetEnvironment();
504     Label slowCall(env);
505     Label slowCallBridge(env);
506     isFast_ = false;
507 
508     GateRef expectedNum = Int64And(Int64LSR(callField_, Int64(MethodLiteral::NumArgsBits::START_BIT)),
509         Int64((1LU << MethodLiteral::NumArgsBits::SIZE) - 1));
510     GateRef expectedArgc = Int64Add(expectedNum, Int64(NUM_MANDATORY_JSFUNC_ARGS));
511     BRANCH(Int64Equal(expectedArgc, realNumArgs_), &slowCall, &slowCallBridge);
512     GateRef code;
513     Bind(&slowCall);
514     {
515         isBridge_ = false;
516         code = GetAotCodeAddr(func_);
517         CallBridge(code, expectedNum, exit);
518     }
519     Bind(&slowCallBridge);
520     {
521         isBridge_ = true;
522         CallBridge(code, expectedNum, exit);
523     }
524 }
525 
CallConstructorBridge(const int idxForAot,const std::vector<GateRef> & argsForAot)526 GateRef CallStubBuilder::CallConstructorBridge(const int idxForAot, const std::vector<GateRef> &argsForAot)
527 {
528     GateRef ret;
529     switch (callArgs_.mode) {
530         case JSCallMode::CALL_CONSTRUCTOR_WITH_ARGV:
531         case JSCallMode::DEPRECATED_CALL_CONSTRUCTOR_WITH_ARGV:
532             ret = CallNGCRuntime(glue_, idxForAot, argsForAot);
533             ret = ConstructorCheck(glue_, func_, ret, callArgs_.callConstructorArgs.thisObj);
534             break;
535         case JSCallMode::SUPER_CALL_WITH_ARGV:
536         case JSCallMode::SUPER_CALL_SPREAD_WITH_ARGV:
537             ret = CallNGCRuntime(glue_, idxForAot, argsForAot, hir_);
538             ret = ConstructorCheck(glue_, func_, ret, callArgs_.superCallArgs.thisObj);
539             break;
540         default:
541             LOG_ECMA(FATAL) << "this branch is unreachable";
542             UNREACHABLE();
543     }
544     return ret;
545 }
546 
CallBridge(GateRef code,GateRef expectedNum,Label * exit)547 void CallStubBuilder::CallBridge(GateRef code, GateRef expectedNum, Label *exit)
548 {
549     int idxForAot = PrepareIdxForAot();
550     std::vector<GateRef> argsForAot = PrepareArgsForAot(expectedNum);
551     GateRef ret;
552     switch (callArgs_.mode) {
553         case JSCallMode::CALL_ARG0:
554         case JSCallMode::CALL_ARG1:
555         case JSCallMode::CALL_ARG2:
556         case JSCallMode::CALL_ARG3:
557         case JSCallMode::CALL_THIS_ARG0:
558         case JSCallMode::CALL_THIS_ARG1:
559         case JSCallMode::CALL_THIS_ARG2:
560         case JSCallMode::CALL_THIS_ARG3:
561         case JSCallMode::DEPRECATED_CALL_ARG0:
562         case JSCallMode::DEPRECATED_CALL_ARG1:
563         case JSCallMode::DEPRECATED_CALL_ARG2:
564         case JSCallMode::DEPRECATED_CALL_ARG3:
565         case JSCallMode::CALL_GETTER:
566         case JSCallMode::CALL_SETTER:
567         case JSCallMode::CALL_THIS_ARG2_WITH_RETURN:
568         case JSCallMode::CALL_THIS_ARG3_WITH_RETURN:
569             if (IsFastAotCall()) {
570                 ret = FastCallOptimized(glue_, code, argsForAot, hir_);
571             } else if (IsSlowAotCall()) {
572                 ret = CallOptimized(glue_, code, argsForAot, hir_);
573             } else {
574                 ret = CallNGCRuntime(glue_, idxForAot, argsForAot, hir_);
575             }
576             break;
577         case JSCallMode::CALL_WITH_ARGV:
578         case JSCallMode::CALL_THIS_WITH_ARGV:
579         case JSCallMode::DEPRECATED_CALL_WITH_ARGV:
580         case JSCallMode::DEPRECATED_CALL_THIS_WITH_ARGV:
581         case JSCallMode::CALL_THIS_ARGV_WITH_RETURN:
582             ret = CallNGCRuntime(glue_, idxForAot, argsForAot);
583             break;
584         case JSCallMode::CALL_CONSTRUCTOR_WITH_ARGV:
585         case JSCallMode::DEPRECATED_CALL_CONSTRUCTOR_WITH_ARGV:
586         case JSCallMode::SUPER_CALL_WITH_ARGV:
587         case JSCallMode::SUPER_CALL_SPREAD_WITH_ARGV:
588             ret = CallConstructorBridge(idxForAot, argsForAot);
589             break;
590         default:
591             LOG_ECMA(FATAL) << "this branch is unreachable";
592             UNREACHABLE();
593     }
594     result_->WriteVariable(ret);
595     Jump(exit);
596 }
597 
JSCallAsmInterpreter(bool hasBaselineCode,Label * exit,Label * noNeedCheckException)598 void CallStubBuilder::JSCallAsmInterpreter(bool hasBaselineCode, Label *exit,
599     Label *noNeedCheckException)
600 {
601     if (jumpSize_ != 0) {
602         SaveJumpSizeIfNeeded(glue_, jumpSize_);
603     }
604     SaveHotnessCounterIfNeeded(glue_, sp_, hotnessCounter_, callArgs_.mode);
605 
606     int idxForAsmInterpreter = isForBaseline_ ?
607         (hasBaselineCode ?
608             PrepareIdxForAsmInterpreterForBaselineWithBaselineCode() :
609             PrepareIdxForAsmInterpreterForBaselineWithoutBaselineCode()) :
610         (hasBaselineCode ?
611             PrepareIdxForAsmInterpreterWithBaselineCode() :
612             PrepareIdxForAsmInterpreterWithoutBaselineCode());
613     std::vector<GateRef> argsForAsmInterpreter = PrepareArgsForAsmInterpreter();
614 
615     switch (callArgs_.mode) {
616         case JSCallMode::CALL_ARG0:
617         case JSCallMode::CALL_ARG1:
618         case JSCallMode::CALL_ARG2:
619         case JSCallMode::CALL_ARG3:
620         case JSCallMode::CALL_THIS_ARG0:
621         case JSCallMode::CALL_THIS_ARG1:
622         case JSCallMode::CALL_THIS_ARG2:
623         case JSCallMode::CALL_THIS_ARG3:
624         case JSCallMode::DEPRECATED_CALL_ARG0:
625         case JSCallMode::DEPRECATED_CALL_ARG1:
626         case JSCallMode::DEPRECATED_CALL_ARG2:
627         case JSCallMode::DEPRECATED_CALL_ARG3:
628         case JSCallMode::CALL_WITH_ARGV:
629         case JSCallMode::CALL_THIS_WITH_ARGV:
630         case JSCallMode::DEPRECATED_CALL_WITH_ARGV:
631         case JSCallMode::DEPRECATED_CALL_THIS_WITH_ARGV:
632         case JSCallMode::CALL_CONSTRUCTOR_WITH_ARGV:
633         case JSCallMode::DEPRECATED_CALL_CONSTRUCTOR_WITH_ARGV:
634         case JSCallMode::SUPER_CALL_WITH_ARGV:
635         case JSCallMode::SUPER_CALL_SPREAD_WITH_ARGV:
636             *result_ = CallNGCRuntime(glue_, idxForAsmInterpreter, argsForAsmInterpreter);
637             if (!isForBaseline_) {
638                 Return();
639             }
640             break;
641         case JSCallMode::CALL_GETTER:
642         case JSCallMode::CALL_SETTER:
643         case JSCallMode::CALL_THIS_ARG2_WITH_RETURN:
644         case JSCallMode::CALL_THIS_ARG3_WITH_RETURN:
645         case JSCallMode::CALL_THIS_ARGV_WITH_RETURN:
646             if (isForBaseline_) {
647                 *result_ = CallNGCRuntime(glue_, idxForAsmInterpreter, argsForAsmInterpreter);
648             } else {
649                 *result_ = CallNGCRuntime(glue_, idxForAsmInterpreter, argsForAsmInterpreter, hir_);
650                 Jump(exit);
651             }
652             break;
653         default:
654             LOG_ECMA(FATAL) << "this branch is unreachable";
655             UNREACHABLE();
656     }
657     if (isForBaseline_) {
658         if (noNeedCheckException != nullptr) {
659             Jump(noNeedCheckException);
660         } else {
661             Jump(exit);
662         }
663     }
664 }
665 
PrepareIdxForNative()666 int CallStubBuilder::PrepareIdxForNative()
667 {
668     switch (callArgs_.mode) {
669         case JSCallMode::CALL_ARG0:
670         case JSCallMode::CALL_ARG1:
671         case JSCallMode::CALL_ARG2:
672         case JSCallMode::CALL_ARG3:
673         case JSCallMode::CALL_THIS_ARG0:
674         case JSCallMode::CALL_THIS_ARG1:
675         case JSCallMode::CALL_THIS_ARG2:
676         case JSCallMode::CALL_THIS_ARG3:
677         case JSCallMode::DEPRECATED_CALL_ARG0:
678         case JSCallMode::DEPRECATED_CALL_ARG1:
679         case JSCallMode::DEPRECATED_CALL_ARG2:
680         case JSCallMode::DEPRECATED_CALL_ARG3:
681         case JSCallMode::CALL_GETTER:
682         case JSCallMode::CALL_SETTER:
683         case JSCallMode::CALL_THIS_ARG2_WITH_RETURN:
684         case JSCallMode::CALL_THIS_ARG3_WITH_RETURN:
685             return RTSTUB_ID(PushCallArgsAndDispatchNative);
686         case JSCallMode::CALL_WITH_ARGV:
687         case JSCallMode::DEPRECATED_CALL_WITH_ARGV:
688         case JSCallMode::CALL_THIS_WITH_ARGV:
689         case JSCallMode::DEPRECATED_CALL_THIS_WITH_ARGV:
690         case JSCallMode::CALL_THIS_ARGV_WITH_RETURN:
691             return RTSTUB_ID(PushCallRangeAndDispatchNative);
692         case JSCallMode::CALL_CONSTRUCTOR_WITH_ARGV:
693         case JSCallMode::DEPRECATED_CALL_CONSTRUCTOR_WITH_ARGV:
694             return RTSTUB_ID(PushCallNewAndDispatchNative);
695         case JSCallMode::SUPER_CALL_WITH_ARGV:
696             return RTSTUB_ID(SuperCall);
697         case JSCallMode::SUPER_CALL_SPREAD_WITH_ARGV:
698             return RTSTUB_ID(SuperCallSpread);
699         default:
700             LOG_ECMA(FATAL) << "this branch is unreachable";
701             UNREACHABLE();
702     }
703 }
704 
PrepareArgsForNative()705 std::vector<GateRef> CallStubBuilder::PrepareArgsForNative()
706 {
707     std::vector<GateRef> basicArgs = PrepareBasicArgsForNative();
708     std::vector<GateRef> appendArgs = PrepareAppendArgsForNative();
709 
710     basicArgs.insert(basicArgs.end(), appendArgs.begin(), appendArgs.end());
711     return basicArgs;
712 }
713 
PrepareBasicArgsForNative()714 std::vector<GateRef> CallStubBuilder::PrepareBasicArgsForNative()
715 {
716     switch (callArgs_.mode) {
717         case JSCallMode::CALL_ARG0:
718         case JSCallMode::CALL_ARG1:
719         case JSCallMode::CALL_ARG2:
720         case JSCallMode::CALL_ARG3:
721         case JSCallMode::DEPRECATED_CALL_ARG0:
722         case JSCallMode::DEPRECATED_CALL_ARG1:
723         case JSCallMode::DEPRECATED_CALL_ARG2:
724         case JSCallMode::DEPRECATED_CALL_ARG3:
725             return { nativeCode_, glue_, numArgs_, func_, newTarget_, thisValue_ };
726         case JSCallMode::CALL_THIS_ARG0:
727         case JSCallMode::CALL_THIS_ARG1:
728         case JSCallMode::CALL_THIS_ARG2:
729         case JSCallMode::CALL_THIS_ARG3:
730         case JSCallMode::CALL_GETTER:
731         case JSCallMode::CALL_SETTER:
732         case JSCallMode::CALL_THIS_ARG2_WITH_RETURN:
733         case JSCallMode::CALL_THIS_ARG3_WITH_RETURN:
734             return { nativeCode_, glue_, numArgs_, func_, newTarget_ };
735         case JSCallMode::CALL_WITH_ARGV:
736         case JSCallMode::DEPRECATED_CALL_WITH_ARGV:
737             return { glue_, nativeCode_, func_, thisValue_ };
738         case JSCallMode::CALL_THIS_WITH_ARGV:
739         case JSCallMode::CALL_THIS_ARGV_WITH_RETURN:
740         case JSCallMode::CALL_CONSTRUCTOR_WITH_ARGV:
741         case JSCallMode::DEPRECATED_CALL_THIS_WITH_ARGV:
742         case JSCallMode::DEPRECATED_CALL_CONSTRUCTOR_WITH_ARGV:
743             return { glue_, nativeCode_, func_ };
744         case JSCallMode::SUPER_CALL_WITH_ARGV:
745         case JSCallMode::SUPER_CALL_SPREAD_WITH_ARGV:
746             return {};
747         default:
748             LOG_ECMA(FATAL) << "this branch is unreachable";
749             UNREACHABLE();
750     }
751 }
752 
PrepareAppendArgsForNative()753 std::vector<GateRef> CallStubBuilder::PrepareAppendArgsForNative()
754 {
755     switch (callArgs_.mode) {
756         case JSCallMode::CALL_ARG0:
757         case JSCallMode::DEPRECATED_CALL_ARG0:
758             return {};
759         case JSCallMode::CALL_ARG1:
760         case JSCallMode::DEPRECATED_CALL_ARG1:
761             return {
762                 callArgs_.callArgs.arg0
763             };
764         case JSCallMode::CALL_ARG2:
765         case JSCallMode::DEPRECATED_CALL_ARG2:
766             return {
767                 callArgs_.callArgs.arg0,
768                 callArgs_.callArgs.arg1
769             };
770         case JSCallMode::CALL_ARG3:
771         case JSCallMode::DEPRECATED_CALL_ARG3:
772             return {
773                 callArgs_.callArgs.arg0,
774                 callArgs_.callArgs.arg1,
775                 callArgs_.callArgs.arg2
776             };
777         case JSCallMode::CALL_THIS_ARG0:
778             return {
779                 callArgs_.callArgsWithThis.thisValue
780             };
781         case JSCallMode::CALL_THIS_ARG1:
782             return {
783                 callArgs_.callArgsWithThis.thisValue,
784                 callArgs_.callArgsWithThis.arg0
785             };
786         case JSCallMode::CALL_THIS_ARG2:
787             return {
788                 callArgs_.callArgsWithThis.thisValue,
789                 callArgs_.callArgsWithThis.arg0,
790                 callArgs_.callArgsWithThis.arg1
791             };
792         case JSCallMode::CALL_THIS_ARG3:
793             return {
794                 callArgs_.callArgsWithThis.thisValue,
795                 callArgs_.callArgsWithThis.arg0,
796                 callArgs_.callArgsWithThis.arg1,
797                 callArgs_.callArgsWithThis.arg2
798             };
799         case JSCallMode::CALL_GETTER:
800             return {
801                 callArgs_.callGetterArgs.receiver
802             };
803         case JSCallMode::CALL_SETTER:
804             return {
805                 callArgs_.callSetterArgs.receiver,
806                 callArgs_.callSetterArgs.value
807             };
808         case JSCallMode::CALL_THIS_ARG2_WITH_RETURN:
809             return {
810                 callArgs_.callThisArg2WithReturnArgs.thisValue,
811                 callArgs_.callThisArg2WithReturnArgs.arg0,
812                 callArgs_.callThisArg2WithReturnArgs.arg1
813             };
814         case JSCallMode::CALL_THIS_ARG3_WITH_RETURN:
815             return {
816                 callArgs_.callThisArg3WithReturnArgs.argHandle,
817                 callArgs_.callThisArg3WithReturnArgs.value,
818                 callArgs_.callThisArg3WithReturnArgs.key,
819                 callArgs_.callThisArg3WithReturnArgs.thisValue
820             };
821         case JSCallMode::CALL_WITH_ARGV:
822         case JSCallMode::DEPRECATED_CALL_WITH_ARGV:
823             return {
824                 callArgs_.callArgv.argc,
825                 callArgs_.callArgv.argv
826             };
827         case JSCallMode::CALL_THIS_WITH_ARGV:
828         case JSCallMode::DEPRECATED_CALL_THIS_WITH_ARGV:
829             return {
830                 callArgs_.callArgvWithThis.thisValue,
831                 callArgs_.callArgvWithThis.argc,
832                 callArgs_.callArgvWithThis.argv
833             };
834         case JSCallMode::CALL_THIS_ARGV_WITH_RETURN:
835             return {
836                 callArgs_.callThisArgvWithReturnArgs.thisValue,
837                 callArgs_.callThisArgvWithReturnArgs.argc,
838                 callArgs_.callThisArgvWithReturnArgs.argv
839             };
840         case JSCallMode::CALL_CONSTRUCTOR_WITH_ARGV:
841         case JSCallMode::DEPRECATED_CALL_CONSTRUCTOR_WITH_ARGV:
842             return {
843                 callArgs_.callConstructorArgs.thisObj,
844                 callArgs_.callConstructorArgs.argc,
845                 callArgs_.callConstructorArgs.argv
846             };
847         case JSCallMode::SUPER_CALL_WITH_ARGV:
848             return {
849                 callArgs_.superCallArgs.thisFunc,
850                 callArgs_.superCallArgs.array,
851                 IntToTaggedInt(callArgs_.superCallArgs.argc)
852             };
853         case JSCallMode::SUPER_CALL_SPREAD_WITH_ARGV:
854             return {
855                 callArgs_.superCallArgs.thisFunc,
856                 callArgs_.superCallArgs.array
857             };
858         default:
859             LOG_ECMA(FATAL) << "this branch is unreachable";
860             UNREACHABLE();
861     }
862 }
863 
PrepareIdxForAot()864 int CallStubBuilder::PrepareIdxForAot()
865 {
866     switch (callArgs_.mode) {
867         case JSCallMode::CALL_ARG0:
868         case JSCallMode::CALL_ARG1:
869         case JSCallMode::CALL_ARG2:
870         case JSCallMode::CALL_ARG3:
871         case JSCallMode::CALL_THIS_ARG0:
872         case JSCallMode::CALL_THIS_ARG1:
873         case JSCallMode::CALL_THIS_ARG2:
874         case JSCallMode::CALL_THIS_ARG3:
875         case JSCallMode::DEPRECATED_CALL_ARG0:
876         case JSCallMode::DEPRECATED_CALL_ARG1:
877         case JSCallMode::DEPRECATED_CALL_ARG2:
878         case JSCallMode::DEPRECATED_CALL_ARG3:
879         case JSCallMode::CALL_GETTER:
880         case JSCallMode::CALL_SETTER:
881         case JSCallMode::CALL_THIS_ARG2_WITH_RETURN:
882         case JSCallMode::CALL_THIS_ARG3_WITH_RETURN:
883             if (isFast_) {
884                 return RTSTUB_ID(OptimizedFastCallAndPushArgv);
885             } else {
886                 return RTSTUB_ID(OptimizedCallAndPushArgv);
887             }
888         case JSCallMode::CALL_WITH_ARGV:
889         case JSCallMode::DEPRECATED_CALL_WITH_ARGV:
890         case JSCallMode::CALL_THIS_WITH_ARGV:
891         case JSCallMode::DEPRECATED_CALL_THIS_WITH_ARGV:
892         case JSCallMode::CALL_CONSTRUCTOR_WITH_ARGV:
893         case JSCallMode::DEPRECATED_CALL_CONSTRUCTOR_WITH_ARGV:
894         case JSCallMode::CALL_THIS_ARGV_WITH_RETURN:
895         case JSCallMode::SUPER_CALL_WITH_ARGV:
896         case JSCallMode::SUPER_CALL_SPREAD_WITH_ARGV:
897             if (IsFastAotCall()) {
898                 return RTSTUB_ID(JSFastCallWithArgV);
899             } else if (IsFastAotCallWithBridge()) {
900                 return RTSTUB_ID(JSFastCallWithArgVAndPushArgv);
901             } else if (IsSlowAotCall()) {
902                 return RTSTUB_ID(JSCallWithArgV);
903             } else {
904                 return RTSTUB_ID(JSCallWithArgVAndPushArgv);
905             }
906         default:
907             LOG_ECMA(FATAL) << "this branch is unreachable";
908             UNREACHABLE();
909     }
910 }
911 
PrepareArgsForAot(GateRef expectedNum)912 std::vector<GateRef> CallStubBuilder::PrepareArgsForAot(GateRef expectedNum)
913 {
914     std::vector<GateRef> basicArgs = PrepareBasicArgsForAot();
915 
916     std::vector<GateRef> appendArgs = PrepareAppendArgsForAotStep1();
917     basicArgs.insert(basicArgs.end(), appendArgs.begin(), appendArgs.end());
918 
919     appendArgs = PrepareAppendArgsForAotStep2();
920     basicArgs.insert(basicArgs.end(), appendArgs.begin(), appendArgs.end());
921 
922     appendArgs = PrepareAppendArgsForAotStep3(expectedNum);
923     basicArgs.insert(basicArgs.end(), appendArgs.begin(), appendArgs.end());
924 
925     return basicArgs;
926 }
927 
PrepareBasicArgsForAot()928 std::vector<GateRef> CallStubBuilder::PrepareBasicArgsForAot()
929 {
930     switch (callArgs_.mode) {
931         case JSCallMode::CALL_ARG0:
932         case JSCallMode::CALL_ARG1:
933         case JSCallMode::CALL_ARG2:
934         case JSCallMode::CALL_ARG3:
935         case JSCallMode::DEPRECATED_CALL_ARG0:
936         case JSCallMode::DEPRECATED_CALL_ARG1:
937         case JSCallMode::DEPRECATED_CALL_ARG2:
938         case JSCallMode::DEPRECATED_CALL_ARG3:
939             if (IsFastAotCall()) {
940                 return { glue_, func_, thisValue_ };
941             } else {
942                 return { glue_, realNumArgs_, IntPtr(0), func_, newTarget_, thisValue_ };
943             }
944         case JSCallMode::CALL_THIS_ARG0:
945         case JSCallMode::CALL_THIS_ARG1:
946         case JSCallMode::CALL_THIS_ARG2:
947         case JSCallMode::CALL_THIS_ARG3:
948         case JSCallMode::CALL_GETTER:
949         case JSCallMode::CALL_SETTER:
950         case JSCallMode::CALL_THIS_ARG2_WITH_RETURN:
951         case JSCallMode::CALL_THIS_ARG3_WITH_RETURN:
952             if (IsFastAotCall()) {
953                 return { glue_, func_ };
954             } else {
955                 return { glue_, realNumArgs_, IntPtr(0), func_, newTarget_ };
956             }
957         case JSCallMode::CALL_WITH_ARGV:
958         case JSCallMode::DEPRECATED_CALL_WITH_ARGV:
959             if (isFast_) {
960                 return { glue_, func_, thisValue_, ZExtInt32ToInt64(actualNumArgs_) };
961             } else {
962                 return { glue_, ZExtInt32ToInt64(actualNumArgs_), func_, newTarget_, thisValue_ };
963             }
964         case JSCallMode::CALL_CONSTRUCTOR_WITH_ARGV:
965         case JSCallMode::DEPRECATED_CALL_CONSTRUCTOR_WITH_ARGV:
966             if (!isFast_) {
967                 return { glue_, ZExtInt32ToInt64(actualNumArgs_), func_, func_ };
968             }
969             [[fallthrough]];
970         case JSCallMode::CALL_THIS_WITH_ARGV:
971         case JSCallMode::DEPRECATED_CALL_THIS_WITH_ARGV:
972         case JSCallMode::CALL_THIS_ARGV_WITH_RETURN:
973             if (isFast_) {
974                 return { glue_, func_ };
975             } else {
976                 return { glue_, ZExtInt32ToInt64(actualNumArgs_), func_, newTarget_ };
977             }
978         case JSCallMode::SUPER_CALL_WITH_ARGV:
979         case JSCallMode::SUPER_CALL_SPREAD_WITH_ARGV:
980             if (isFast_) {
981                 return { glue_, func_ };
982             } else {
983                 return { glue_, ZExtInt32ToInt64(actualNumArgs_), func_};
984             }
985         default:
986             LOG_ECMA(FATAL) << "this branch is unreachable";
987             UNREACHABLE();
988     }
989 }
990 
PrepareAppendArgsForAotStep1()991 std::vector<GateRef> CallStubBuilder::PrepareAppendArgsForAotStep1()
992 {
993     switch (callArgs_.mode) {
994         case JSCallMode::CALL_ARG0:
995         case JSCallMode::DEPRECATED_CALL_ARG0:
996             return {};
997         case JSCallMode::CALL_ARG1:
998         case JSCallMode::DEPRECATED_CALL_ARG1:
999             return { callArgs_.callArgs.arg0 };
1000         case JSCallMode::CALL_ARG2:
1001         case JSCallMode::DEPRECATED_CALL_ARG2:
1002             return {
1003                 callArgs_.callArgs.arg0,
1004                 callArgs_.callArgs.arg1
1005             };
1006         case JSCallMode::CALL_ARG3:
1007         case JSCallMode::DEPRECATED_CALL_ARG3:
1008             return {
1009                 callArgs_.callArgs.arg0,
1010                 callArgs_.callArgs.arg1,
1011                 callArgs_.callArgs.arg2
1012             };
1013         case JSCallMode::CALL_THIS_ARG0:
1014             return { callArgs_.callArgsWithThis.thisValue };
1015         case JSCallMode::CALL_THIS_ARG1:
1016             return {
1017                 callArgs_.callArgsWithThis.thisValue,
1018                 callArgs_.callArgsWithThis.arg0
1019             };
1020         case JSCallMode::CALL_THIS_ARG2:
1021             return {
1022                 callArgs_.callArgsWithThis.thisValue,
1023                 callArgs_.callArgsWithThis.arg0,
1024                 callArgs_.callArgsWithThis.arg1
1025             };
1026         case JSCallMode::CALL_THIS_ARG3:
1027             return {
1028                 callArgs_.callArgsWithThis.thisValue,
1029                 callArgs_.callArgsWithThis.arg0,
1030                 callArgs_.callArgsWithThis.arg1,
1031                 callArgs_.callArgsWithThis.arg2
1032             };
1033         case JSCallMode::CALL_GETTER:
1034             return { callArgs_.callGetterArgs.receiver };
1035         case JSCallMode::CALL_SETTER:
1036             return {
1037                 callArgs_.callSetterArgs.receiver,
1038                 callArgs_.callSetterArgs.value
1039             };
1040         case JSCallMode::CALL_THIS_ARG2_WITH_RETURN:
1041             return {
1042                 callArgs_.callThisArg2WithReturnArgs.thisValue,
1043                 callArgs_.callThisArg2WithReturnArgs.arg0,
1044                 callArgs_.callThisArg2WithReturnArgs.arg1
1045             };
1046         case JSCallMode::CALL_THIS_ARG3_WITH_RETURN:
1047             return {
1048                 callArgs_.callThisArg3WithReturnArgs.argHandle,
1049                 callArgs_.callThisArg3WithReturnArgs.value,
1050                 callArgs_.callThisArg3WithReturnArgs.key,
1051                 callArgs_.callThisArg3WithReturnArgs.thisValue
1052             };
1053         case JSCallMode::CALL_WITH_ARGV:
1054         case JSCallMode::DEPRECATED_CALL_WITH_ARGV:
1055             return { callArgs_.callArgv.argv };
1056         case JSCallMode::CALL_THIS_WITH_ARGV:
1057         case JSCallMode::DEPRECATED_CALL_THIS_WITH_ARGV:
1058             return { callArgs_.callArgvWithThis.thisValue };
1059         case JSCallMode::CALL_CONSTRUCTOR_WITH_ARGV:
1060         case JSCallMode::DEPRECATED_CALL_CONSTRUCTOR_WITH_ARGV:
1061             return { callArgs_.callConstructorArgs.thisObj };
1062         case JSCallMode::CALL_THIS_ARGV_WITH_RETURN:
1063             return { callArgs_.callThisArgvWithReturnArgs.thisValue };
1064         case JSCallMode::SUPER_CALL_WITH_ARGV:
1065         case JSCallMode::SUPER_CALL_SPREAD_WITH_ARGV:
1066             return {};
1067         default:
1068             LOG_ECMA(FATAL) << "this branch is unreachable";
1069             UNREACHABLE();
1070     }
1071 }
1072 
PrepareAppendArgsForAotStep2()1073 std::vector<GateRef> CallStubBuilder::PrepareAppendArgsForAotStep2()
1074 {
1075     switch (callArgs_.mode) {
1076         case JSCallMode::CALL_THIS_WITH_ARGV:
1077         case JSCallMode::DEPRECATED_CALL_THIS_WITH_ARGV:
1078         case JSCallMode::CALL_CONSTRUCTOR_WITH_ARGV:
1079         case JSCallMode::DEPRECATED_CALL_CONSTRUCTOR_WITH_ARGV:
1080         case JSCallMode::CALL_THIS_ARGV_WITH_RETURN:
1081             if (isFast_) {
1082                 return { ZExtInt32ToInt64(actualNumArgs_) };
1083             }
1084             [[fallthrough]];
1085         case JSCallMode::CALL_WITH_ARGV:
1086         case JSCallMode::DEPRECATED_CALL_WITH_ARGV:
1087         case JSCallMode::CALL_ARG0:
1088         case JSCallMode::CALL_ARG1:
1089         case JSCallMode::CALL_ARG2:
1090         case JSCallMode::CALL_ARG3:
1091         case JSCallMode::CALL_THIS_ARG0:
1092         case JSCallMode::CALL_THIS_ARG1:
1093         case JSCallMode::CALL_THIS_ARG2:
1094         case JSCallMode::CALL_THIS_ARG3:
1095         case JSCallMode::DEPRECATED_CALL_ARG0:
1096         case JSCallMode::DEPRECATED_CALL_ARG1:
1097         case JSCallMode::DEPRECATED_CALL_ARG2:
1098         case JSCallMode::DEPRECATED_CALL_ARG3:
1099         case JSCallMode::CALL_GETTER:
1100         case JSCallMode::CALL_SETTER:
1101         case JSCallMode::CALL_THIS_ARG2_WITH_RETURN:
1102         case JSCallMode::CALL_THIS_ARG3_WITH_RETURN:
1103             return {};
1104         case JSCallMode::SUPER_CALL_WITH_ARGV:
1105         case JSCallMode::SUPER_CALL_SPREAD_WITH_ARGV:
1106             if (isFast_) {
1107                 return {
1108                     callArgs_.superCallArgs.thisObj,
1109                     callArgs_.superCallArgs.argc,
1110                     callArgs_.superCallArgs.argv
1111                 };
1112             } else {
1113                 return {
1114                     callArgs_.superCallArgs.newTarget,
1115                     callArgs_.superCallArgs.thisObj,
1116                     callArgs_.superCallArgs.argv
1117                 };
1118             }
1119         default:
1120             LOG_ECMA(FATAL) << "this branch is unreachable";
1121             UNREACHABLE();
1122     }
1123 }
1124 
PrepareAppendArgsForAotStep3(GateRef expectedNum)1125 std::vector<GateRef> CallStubBuilder::PrepareAppendArgsForAotStep3(GateRef expectedNum)
1126 {
1127     std::vector<GateRef> retArgs {};
1128     switch (callArgs_.mode) {
1129         case JSCallMode::CALL_ARG0:
1130         case JSCallMode::CALL_ARG1:
1131         case JSCallMode::CALL_ARG2:
1132         case JSCallMode::CALL_ARG3:
1133         case JSCallMode::CALL_THIS_ARG0:
1134         case JSCallMode::CALL_THIS_ARG1:
1135         case JSCallMode::CALL_THIS_ARG2:
1136         case JSCallMode::CALL_THIS_ARG3:
1137         case JSCallMode::DEPRECATED_CALL_ARG0:
1138         case JSCallMode::DEPRECATED_CALL_ARG1:
1139         case JSCallMode::DEPRECATED_CALL_ARG2:
1140         case JSCallMode::DEPRECATED_CALL_ARG3:
1141         case JSCallMode::CALL_GETTER:
1142         case JSCallMode::CALL_SETTER:
1143         case JSCallMode::CALL_THIS_ARG2_WITH_RETURN:
1144         case JSCallMode::CALL_THIS_ARG3_WITH_RETURN:
1145             return {};
1146         case JSCallMode::CALL_THIS_WITH_ARGV:
1147         case JSCallMode::DEPRECATED_CALL_THIS_WITH_ARGV:
1148             retArgs.push_back(callArgs_.callArgvWithThis.argv);
1149             break;
1150         case JSCallMode::CALL_CONSTRUCTOR_WITH_ARGV:
1151         case JSCallMode::DEPRECATED_CALL_CONSTRUCTOR_WITH_ARGV:
1152             retArgs.push_back(callArgs_.callConstructorArgs.argv);
1153             break;
1154         case JSCallMode::CALL_THIS_ARGV_WITH_RETURN:
1155             retArgs.push_back(callArgs_.callThisArgvWithReturnArgs.argv);
1156             break;
1157         case JSCallMode::CALL_WITH_ARGV:
1158         case JSCallMode::DEPRECATED_CALL_WITH_ARGV:
1159         case JSCallMode::SUPER_CALL_WITH_ARGV:
1160         case JSCallMode::SUPER_CALL_SPREAD_WITH_ARGV:
1161             break;
1162         default:
1163             LOG_ECMA(FATAL) << "this branch is unreachable";
1164             UNREACHABLE();
1165     }
1166 
1167     if (IsFastAotCallWithBridge()) {
1168         retArgs.push_back(expectedNum);
1169     }
1170     return retArgs;
1171 }
1172 
PrepareIdxForAsmInterpreterForBaselineWithBaselineCode()1173 int CallStubBuilder::PrepareIdxForAsmInterpreterForBaselineWithBaselineCode()
1174 {
1175     switch (callArgs_.mode) {
1176         case JSCallMode::CALL_ARG0:
1177         case JSCallMode::DEPRECATED_CALL_ARG0:
1178             return RTSTUB_ID(CallArg0AndCheckToBaselineFromBaseline);
1179         case JSCallMode::CALL_ARG1:
1180         case JSCallMode::DEPRECATED_CALL_ARG1:
1181             return RTSTUB_ID(CallArg1AndCheckToBaselineFromBaseline);
1182         case JSCallMode::CALL_ARG2:
1183         case JSCallMode::DEPRECATED_CALL_ARG2:
1184             return RTSTUB_ID(CallArgs2AndCheckToBaselineFromBaseline);
1185         case JSCallMode::CALL_ARG3:
1186         case JSCallMode::DEPRECATED_CALL_ARG3:
1187             return RTSTUB_ID(CallArgs3AndCheckToBaselineFromBaseline);
1188         case JSCallMode::CALL_THIS_ARG0:
1189             return RTSTUB_ID(CallThisArg0AndCheckToBaselineFromBaseline);
1190         case JSCallMode::CALL_THIS_ARG1:
1191             return RTSTUB_ID(CallThisArg1AndCheckToBaselineFromBaseline);
1192         case JSCallMode::CALL_THIS_ARG2:
1193             return RTSTUB_ID(CallThisArgs2AndCheckToBaselineFromBaseline);
1194         case JSCallMode::CALL_THIS_ARG3:
1195             return RTSTUB_ID(CallThisArgs3AndCheckToBaselineFromBaseline);
1196         case JSCallMode::CALL_WITH_ARGV:
1197         case JSCallMode::DEPRECATED_CALL_WITH_ARGV:
1198             return RTSTUB_ID(CallRangeAndCheckToBaselineFromBaseline);
1199         case JSCallMode::CALL_THIS_WITH_ARGV:
1200         case JSCallMode::DEPRECATED_CALL_THIS_WITH_ARGV:
1201             return RTSTUB_ID(CallThisRangeAndCheckToBaselineFromBaseline);
1202         case JSCallMode::CALL_CONSTRUCTOR_WITH_ARGV:
1203         case JSCallMode::DEPRECATED_CALL_CONSTRUCTOR_WITH_ARGV:
1204             return RTSTUB_ID(CallNewAndCheckToBaselineFromBaseline);
1205         case JSCallMode::SUPER_CALL_WITH_ARGV:
1206         case JSCallMode::SUPER_CALL_SPREAD_WITH_ARGV:
1207             return RTSTUB_ID(SuperCallAndCheckToBaselineFromBaseline);
1208         case JSCallMode::CALL_GETTER:
1209             return RTSTUB_ID(CallGetterToBaseline);
1210         case JSCallMode::CALL_SETTER:
1211             return RTSTUB_ID(CallSetterToBaseline);
1212         case JSCallMode::CALL_THIS_ARG2_WITH_RETURN:
1213             return RTSTUB_ID(CallContainersArgs2ToBaseline);
1214         case JSCallMode::CALL_THIS_ARG3_WITH_RETURN:
1215             return RTSTUB_ID(CallContainersArgs3ToBaseline);
1216         case JSCallMode::CALL_THIS_ARGV_WITH_RETURN:
1217             return RTSTUB_ID(CallReturnWithArgvToBaseline);
1218         default:
1219             LOG_ECMA(FATAL) << "this branch is unreachable";
1220             UNREACHABLE();
1221     }
1222 }
1223 
PrepareIdxForAsmInterpreterForBaselineWithoutBaselineCode()1224 int CallStubBuilder::PrepareIdxForAsmInterpreterForBaselineWithoutBaselineCode()
1225 {
1226     switch (callArgs_.mode) {
1227         case JSCallMode::CALL_ARG0:
1228         case JSCallMode::DEPRECATED_CALL_ARG0:
1229             return RTSTUB_ID(CallArg0AndDispatchFromBaseline);
1230         case JSCallMode::CALL_ARG1:
1231         case JSCallMode::DEPRECATED_CALL_ARG1:
1232             return RTSTUB_ID(CallArg1AndDispatchFromBaseline);
1233         case JSCallMode::CALL_ARG2:
1234         case JSCallMode::DEPRECATED_CALL_ARG2:
1235             return RTSTUB_ID(CallArgs2AndDispatchFromBaseline);
1236         case JSCallMode::CALL_ARG3:
1237         case JSCallMode::DEPRECATED_CALL_ARG3:
1238             return RTSTUB_ID(CallArgs3AndDispatchFromBaseline);
1239         case JSCallMode::CALL_THIS_ARG0:
1240             return RTSTUB_ID(CallThisArg0AndDispatchFromBaseline);
1241         case JSCallMode::CALL_THIS_ARG1:
1242             return RTSTUB_ID(CallThisArg1AndDispatchFromBaseline);
1243         case JSCallMode::CALL_THIS_ARG2:
1244             return RTSTUB_ID(CallThisArgs2AndDispatchFromBaseline);
1245         case JSCallMode::CALL_THIS_ARG3:
1246             return RTSTUB_ID(CallThisArgs3AndDispatchFromBaseline);
1247         case JSCallMode::CALL_WITH_ARGV:
1248         case JSCallMode::DEPRECATED_CALL_WITH_ARGV:
1249             return RTSTUB_ID(CallRangeAndDispatchFromBaseline);
1250         case JSCallMode::CALL_THIS_WITH_ARGV:
1251         case JSCallMode::DEPRECATED_CALL_THIS_WITH_ARGV:
1252             return RTSTUB_ID(CallThisRangeAndDispatchFromBaseline);
1253         case JSCallMode::CALL_CONSTRUCTOR_WITH_ARGV:
1254         case JSCallMode::DEPRECATED_CALL_CONSTRUCTOR_WITH_ARGV:
1255             return RTSTUB_ID(CallNewAndDispatchFromBaseline);
1256         case JSCallMode::SUPER_CALL_WITH_ARGV:
1257         case JSCallMode::SUPER_CALL_SPREAD_WITH_ARGV:
1258             return RTSTUB_ID(SuperCallAndDispatchFromBaseline);
1259         case JSCallMode::CALL_GETTER:
1260             return RTSTUB_ID(CallGetter);
1261         case JSCallMode::CALL_SETTER:
1262             return RTSTUB_ID(CallSetter);
1263         case JSCallMode::CALL_THIS_ARG2_WITH_RETURN:
1264             return RTSTUB_ID(CallContainersArgs2);
1265         case JSCallMode::CALL_THIS_ARG3_WITH_RETURN:
1266             return RTSTUB_ID(CallContainersArgs3);
1267         case JSCallMode::CALL_THIS_ARGV_WITH_RETURN:
1268             return RTSTUB_ID(CallReturnWithArgv);
1269         default:
1270             LOG_ECMA(FATAL) << "this branch is unreachable";
1271             UNREACHABLE();
1272     }
1273 }
1274 
PrepareIdxForAsmInterpreterWithBaselineCode()1275 int CallStubBuilder::PrepareIdxForAsmInterpreterWithBaselineCode()
1276 {
1277     switch (callArgs_.mode) {
1278         case JSCallMode::CALL_ARG0:
1279         case JSCallMode::DEPRECATED_CALL_ARG0:
1280             return RTSTUB_ID(CallArg0AndCheckToBaseline);
1281         case JSCallMode::CALL_ARG1:
1282         case JSCallMode::DEPRECATED_CALL_ARG1:
1283             return RTSTUB_ID(CallArg1AndCheckToBaseline);
1284         case JSCallMode::CALL_ARG2:
1285         case JSCallMode::DEPRECATED_CALL_ARG2:
1286             return RTSTUB_ID(CallArgs2AndCheckToBaseline);
1287         case JSCallMode::CALL_ARG3:
1288         case JSCallMode::DEPRECATED_CALL_ARG3:
1289             return RTSTUB_ID(CallArgs3AndCheckToBaseline);
1290         case JSCallMode::CALL_THIS_ARG0:
1291             return RTSTUB_ID(CallThisArg0AndCheckToBaseline);
1292         case JSCallMode::CALL_THIS_ARG1:
1293             return RTSTUB_ID(CallThisArg1AndCheckToBaseline);
1294         case JSCallMode::CALL_THIS_ARG2:
1295             return RTSTUB_ID(CallThisArgs2AndCheckToBaseline);
1296         case JSCallMode::CALL_THIS_ARG3:
1297             return RTSTUB_ID(CallThisArgs3AndCheckToBaseline);
1298         case JSCallMode::CALL_WITH_ARGV:
1299         case JSCallMode::DEPRECATED_CALL_WITH_ARGV:
1300             return RTSTUB_ID(CallRangeAndCheckToBaseline);
1301         case JSCallMode::CALL_THIS_WITH_ARGV:
1302         case JSCallMode::DEPRECATED_CALL_THIS_WITH_ARGV:
1303             return RTSTUB_ID(CallThisRangeAndCheckToBaseline);
1304         case JSCallMode::CALL_CONSTRUCTOR_WITH_ARGV:
1305         case JSCallMode::DEPRECATED_CALL_CONSTRUCTOR_WITH_ARGV:
1306             return RTSTUB_ID(CallNewAndCheckToBaseline);
1307         case JSCallMode::SUPER_CALL_WITH_ARGV:
1308         case JSCallMode::SUPER_CALL_SPREAD_WITH_ARGV:
1309             return RTSTUB_ID(SuperCallAndCheckToBaseline);
1310         case JSCallMode::CALL_GETTER:
1311             return RTSTUB_ID(CallGetterToBaseline);
1312         case JSCallMode::CALL_SETTER:
1313             return RTSTUB_ID(CallSetterToBaseline);
1314         case JSCallMode::CALL_THIS_ARG2_WITH_RETURN:
1315             return RTSTUB_ID(CallContainersArgs2ToBaseline);
1316         case JSCallMode::CALL_THIS_ARG3_WITH_RETURN:
1317             return RTSTUB_ID(CallContainersArgs3ToBaseline);
1318         case JSCallMode::CALL_THIS_ARGV_WITH_RETURN:
1319             return RTSTUB_ID(CallReturnWithArgvToBaseline);
1320         default:
1321             LOG_ECMA(FATAL) << "this branch is unreachable";
1322             UNREACHABLE();
1323     }
1324 }
1325 
PrepareIdxForAsmInterpreterWithoutBaselineCode()1326 int CallStubBuilder::PrepareIdxForAsmInterpreterWithoutBaselineCode()
1327 {
1328     switch (callArgs_.mode) {
1329         case JSCallMode::CALL_ARG0:
1330         case JSCallMode::DEPRECATED_CALL_ARG0:
1331             return RTSTUB_ID(PushCallArg0AndDispatch);
1332         case JSCallMode::CALL_ARG1:
1333         case JSCallMode::DEPRECATED_CALL_ARG1:
1334             return RTSTUB_ID(PushCallArg1AndDispatch);
1335         case JSCallMode::CALL_ARG2:
1336         case JSCallMode::DEPRECATED_CALL_ARG2:
1337             return RTSTUB_ID(PushCallArgs2AndDispatch);
1338         case JSCallMode::CALL_ARG3:
1339         case JSCallMode::DEPRECATED_CALL_ARG3:
1340             return RTSTUB_ID(PushCallArgs3AndDispatch);
1341         case JSCallMode::CALL_THIS_ARG0:
1342             return RTSTUB_ID(PushCallThisArg0AndDispatch);
1343         case JSCallMode::CALL_THIS_ARG1:
1344             return RTSTUB_ID(PushCallThisArg1AndDispatch);
1345         case JSCallMode::CALL_THIS_ARG2:
1346             return RTSTUB_ID(PushCallThisArgs2AndDispatch);
1347         case JSCallMode::CALL_THIS_ARG3:
1348             return RTSTUB_ID(PushCallThisArgs3AndDispatch);
1349         case JSCallMode::CALL_WITH_ARGV:
1350         case JSCallMode::DEPRECATED_CALL_WITH_ARGV:
1351             return RTSTUB_ID(PushCallRangeAndDispatch);
1352         case JSCallMode::CALL_THIS_WITH_ARGV:
1353         case JSCallMode::DEPRECATED_CALL_THIS_WITH_ARGV:
1354             return RTSTUB_ID(PushCallThisRangeAndDispatch);
1355         case JSCallMode::CALL_CONSTRUCTOR_WITH_ARGV:
1356         case JSCallMode::DEPRECATED_CALL_CONSTRUCTOR_WITH_ARGV:
1357             return RTSTUB_ID(PushCallNewAndDispatch);
1358         case JSCallMode::SUPER_CALL_WITH_ARGV:
1359         case JSCallMode::SUPER_CALL_SPREAD_WITH_ARGV:
1360             return RTSTUB_ID(PushSuperCallAndDispatch);
1361         case JSCallMode::CALL_GETTER:
1362             return RTSTUB_ID(CallGetter);
1363         case JSCallMode::CALL_SETTER:
1364             return RTSTUB_ID(CallSetter);
1365         case JSCallMode::CALL_THIS_ARG2_WITH_RETURN:
1366             return RTSTUB_ID(CallContainersArgs2);
1367         case JSCallMode::CALL_THIS_ARG3_WITH_RETURN:
1368             return RTSTUB_ID(CallContainersArgs3);
1369         case JSCallMode::CALL_THIS_ARGV_WITH_RETURN:
1370             return RTSTUB_ID(CallReturnWithArgv);
1371         default:
1372             LOG_ECMA(FATAL) << "this branch is unreachable";
1373             UNREACHABLE();
1374     }
1375 }
1376 
PrepareArgsForAsmInterpreter()1377 std::vector<GateRef> CallStubBuilder::PrepareArgsForAsmInterpreter()
1378 {
1379     std::vector<GateRef> basicArgs = PrepareBasicArgsForAsmInterpreter();
1380     std::vector<GateRef> appendArgs = PrepareAppendArgsForAsmInterpreter();
1381 
1382     basicArgs.insert(basicArgs.end(), appendArgs.begin(), appendArgs.end());
1383     return basicArgs;
1384 }
1385 
PrepareBasicArgsForAsmInterpreter()1386 std::vector<GateRef> CallStubBuilder::PrepareBasicArgsForAsmInterpreter()
1387 {
1388     switch (callArgs_.mode) {
1389         case JSCallMode::CALL_ARG0:
1390         case JSCallMode::CALL_ARG1:
1391         case JSCallMode::CALL_ARG2:
1392         case JSCallMode::CALL_ARG3:
1393         case JSCallMode::CALL_WITH_ARGV:
1394         case JSCallMode::CALL_THIS_ARG0:
1395         case JSCallMode::CALL_THIS_ARG1:
1396         case JSCallMode::CALL_THIS_ARG2:
1397         case JSCallMode::CALL_THIS_ARG3:
1398         case JSCallMode::CALL_THIS_WITH_ARGV:
1399         case JSCallMode::CALL_CONSTRUCTOR_WITH_ARGV:
1400         case JSCallMode::DEPRECATED_CALL_ARG0:
1401         case JSCallMode::DEPRECATED_CALL_ARG1:
1402         case JSCallMode::DEPRECATED_CALL_ARG2:
1403         case JSCallMode::DEPRECATED_CALL_ARG3:
1404         case JSCallMode::DEPRECATED_CALL_WITH_ARGV:
1405         case JSCallMode::DEPRECATED_CALL_THIS_WITH_ARGV:
1406         case JSCallMode::DEPRECATED_CALL_CONSTRUCTOR_WITH_ARGV:
1407         case JSCallMode::SUPER_CALL_WITH_ARGV:
1408         case JSCallMode::SUPER_CALL_SPREAD_WITH_ARGV:
1409             if (isForBaseline_) {
1410                 return { glue_, baselineBuiltinFp_, func_, method_, callField_ };
1411             } else {
1412                 return { glue_, sp_, func_, method_, callField_ };
1413             }
1414         case JSCallMode::CALL_GETTER:
1415         case JSCallMode::CALL_SETTER:
1416         case JSCallMode::CALL_THIS_ARG2_WITH_RETURN:
1417         case JSCallMode::CALL_THIS_ARG3_WITH_RETURN:
1418         case JSCallMode::CALL_THIS_ARGV_WITH_RETURN:
1419             return { glue_, func_, method_, callField_ };
1420         default:
1421             LOG_ECMA(FATAL) << "this branch is unreachable";
1422             UNREACHABLE();
1423     }
1424 }
1425 
PrepareAppendArgsForAsmInterpreter()1426 std::vector<GateRef> CallStubBuilder::PrepareAppendArgsForAsmInterpreter()
1427 {
1428     switch (callArgs_.mode) {
1429         case JSCallMode::CALL_ARG0:
1430         case JSCallMode::DEPRECATED_CALL_ARG0:
1431             return {};
1432         case JSCallMode::CALL_ARG1:
1433         case JSCallMode::DEPRECATED_CALL_ARG1:
1434             return { callArgs_.callArgs.arg0 };
1435         case JSCallMode::CALL_ARG2:
1436         case JSCallMode::DEPRECATED_CALL_ARG2:
1437             return {
1438                 callArgs_.callArgs.arg0,
1439                 callArgs_.callArgs.arg1
1440             };
1441         case JSCallMode::CALL_ARG3:
1442         case JSCallMode::DEPRECATED_CALL_ARG3:
1443             return {
1444                 callArgs_.callArgs.arg0,
1445                 callArgs_.callArgs.arg1,
1446                 callArgs_.callArgs.arg2
1447             };
1448         case JSCallMode::CALL_THIS_ARG0:
1449             return { callArgs_.callArgsWithThis.thisValue };
1450         case JSCallMode::CALL_THIS_ARG1:
1451             return {
1452                 callArgs_.callArgsWithThis.arg0,
1453                 callArgs_.callArgsWithThis.thisValue
1454             };
1455         case JSCallMode::CALL_THIS_ARG2:
1456             return {
1457                 callArgs_.callArgsWithThis.arg0,
1458                 callArgs_.callArgsWithThis.arg1,
1459                 callArgs_.callArgsWithThis.thisValue
1460             };
1461         case JSCallMode::CALL_THIS_ARG3:
1462             return {
1463                 callArgs_.callArgsWithThis.arg0,
1464                 callArgs_.callArgsWithThis.arg1,
1465                 callArgs_.callArgsWithThis.arg2,
1466                 callArgs_.callArgsWithThis.thisValue
1467             };
1468         case JSCallMode::CALL_WITH_ARGV:
1469         case JSCallMode::DEPRECATED_CALL_WITH_ARGV:
1470             return {
1471                 callArgs_.callArgv.argc,
1472                 callArgs_.callArgv.argv
1473             };
1474         case JSCallMode::CALL_THIS_WITH_ARGV:
1475         case JSCallMode::DEPRECATED_CALL_THIS_WITH_ARGV:
1476             return {
1477                 callArgs_.callArgvWithThis.argc,
1478                 callArgs_.callArgvWithThis.argv,
1479                 callArgs_.callArgvWithThis.thisValue
1480             };
1481         case JSCallMode::CALL_CONSTRUCTOR_WITH_ARGV:
1482         case JSCallMode::DEPRECATED_CALL_CONSTRUCTOR_WITH_ARGV:
1483             return {
1484                 callArgs_.callConstructorArgs.argc,
1485                 callArgs_.callConstructorArgs.argv,
1486                 callArgs_.callConstructorArgs.thisObj
1487             };
1488         case JSCallMode::CALL_GETTER:
1489             return { callArgs_.callGetterArgs.receiver };
1490         case JSCallMode::CALL_SETTER:
1491             return {
1492                 callArgs_.callSetterArgs.value,
1493                 callArgs_.callSetterArgs.receiver
1494             };
1495         case JSCallMode::CALL_THIS_ARG2_WITH_RETURN:
1496             return {
1497                 callArgs_.callThisArg2WithReturnArgs.arg0,
1498                 callArgs_.callThisArg2WithReturnArgs.arg1,
1499                 callArgs_.callThisArg2WithReturnArgs.thisValue
1500             };
1501         case JSCallMode::CALL_THIS_ARG3_WITH_RETURN:
1502             return {
1503                 callArgs_.callThisArg3WithReturnArgs.value,
1504                 callArgs_.callThisArg3WithReturnArgs.key,
1505                 callArgs_.callThisArg3WithReturnArgs.thisValue,
1506                 callArgs_.callThisArg3WithReturnArgs.argHandle
1507             };
1508         case JSCallMode::CALL_THIS_ARGV_WITH_RETURN:
1509             return {
1510                 callArgs_.callThisArgvWithReturnArgs.argc,
1511                 callArgs_.callThisArgvWithReturnArgs.argv,
1512                 callArgs_.callThisArgvWithReturnArgs.thisValue
1513             };
1514         case JSCallMode::SUPER_CALL_WITH_ARGV:
1515         case JSCallMode::SUPER_CALL_SPREAD_WITH_ARGV:
1516             return {
1517                 callArgs_.superCallArgs.argc,
1518                 callArgs_.superCallArgs.argv,
1519                 callArgs_.superCallArgs.thisObj,
1520                 callArgs_.superCallArgs.newTarget
1521             };
1522         default:
1523             LOG_ECMA(FATAL) << "this branch is unreachable";
1524             UNREACHABLE();
1525     }
1526 }
1527 
CallFastBuiltin(Label * notFastBuiltins,Label * exit,GateRef hir)1528 void CallStubBuilder::CallFastBuiltin(Label* notFastBuiltins, Label *exit, GateRef hir)
1529 {
1530     auto env = GetEnvironment();
1531     Label isFastBuiltins(env);
1532     Label supportCall(env);
1533     numArgs_ = ZExtInt32ToPtr(actualNumArgs_);
1534     GateRef isFastBuiltinsMask = Int64(static_cast<uint64_t>(1) << MethodLiteral::IsFastBuiltinBit::START_BIT);
1535     BRANCH(Int64NotEqual(Int64And(callField_, isFastBuiltinsMask), Int64(0)), &isFastBuiltins, notFastBuiltins);
1536     Bind(&isFastBuiltins);
1537     GateRef builtinId = GetBuiltinId(method_);
1538     if (IsCallModeSupportCallBuiltin()) {
1539         BRANCH(Int32GreaterThanOrEqual(builtinId, Int32(kungfu::BuiltinsStubCSigns::BUILTINS_CONSTRUCTOR_STUB_FIRST)),
1540             notFastBuiltins, &supportCall);
1541         Bind(&supportCall);
1542     }
1543     {
1544         GateRef ret;
1545         switch (callArgs_.mode) {
1546             case JSCallMode::CALL_THIS_ARG0:
1547             case JSCallMode::CALL_THIS_ARG1:
1548             case JSCallMode::CALL_THIS_ARG2:
1549             case JSCallMode::CALL_THIS_ARG3:
1550             case JSCallMode::CALL_THIS_ARG2_WITH_RETURN:
1551                 ret = DispatchBuiltins(glue_, builtinId, PrepareArgsForFastBuiltin(), hir);
1552                 break;
1553             case JSCallMode::DEPRECATED_CALL_CONSTRUCTOR_WITH_ARGV:
1554             case JSCallMode::CALL_CONSTRUCTOR_WITH_ARGV:
1555                 ret = DispatchBuiltinsWithArgv(glue_, builtinId, PrepareArgsForFastBuiltin());
1556                 break;
1557             default:
1558                 LOG_ECMA(FATAL) << "this branch is unreachable";
1559                 UNREACHABLE();
1560         }
1561         result_->WriteVariable(ret);
1562         Jump(exit);
1563     }
1564 }
1565 
PrepareBasicArgsForFastBuiltin()1566 std::vector<GateRef> CallStubBuilder::PrepareBasicArgsForFastBuiltin()
1567 {
1568     return { glue_, nativeCode_, func_ };
1569 }
1570 
PrepareAppendArgsForFastBuiltin()1571 std::vector<GateRef> CallStubBuilder::PrepareAppendArgsForFastBuiltin()
1572 {
1573     switch (callArgs_.mode) {
1574         case JSCallMode::CALL_THIS_ARG0:
1575             return { Undefined(),
1576                 callArgs_.callArgsWithThis.thisValue, numArgs_, Undefined(), Undefined(), Undefined()
1577             };
1578         case JSCallMode::CALL_THIS_ARG1:
1579             return { Undefined(),
1580                 callArgs_.callArgsWithThis.thisValue, numArgs_,
1581                 callArgs_.callArgsWithThis.arg0, Undefined(), Undefined()
1582             };
1583         case JSCallMode::CALL_THIS_ARG2:
1584             return { Undefined(),
1585                 callArgs_.callArgsWithThis.thisValue, numArgs_,
1586                 callArgs_.callArgsWithThis.arg0,
1587                 callArgs_.callArgsWithThis.arg1, Undefined()
1588             };
1589         case JSCallMode::CALL_THIS_ARG2_WITH_RETURN:
1590             return { Undefined(),
1591                 callArgs_.callThisArg2WithReturnArgs.thisValue, numArgs_,
1592                 callArgs_.callThisArg2WithReturnArgs.arg0,
1593                 callArgs_.callThisArg2WithReturnArgs.arg1, Undefined()
1594             };
1595         case JSCallMode::CALL_THIS_ARG3:
1596             return { Undefined(),
1597                 callArgs_.callArgsWithThis.thisValue, numArgs_,
1598                 callArgs_.callArgsWithThis.arg0,
1599                 callArgs_.callArgsWithThis.arg1,
1600                 callArgs_.callArgsWithThis.arg2
1601             };
1602         case JSCallMode::DEPRECATED_CALL_CONSTRUCTOR_WITH_ARGV:
1603         case JSCallMode::CALL_CONSTRUCTOR_WITH_ARGV:
1604             return { func_, thisValue_, numArgs_,
1605                 callArgs_.callConstructorArgs.argv
1606             };
1607         default:
1608             LOG_ECMA(FATAL) << "this branch is unreachable";
1609             UNREACHABLE();
1610     }
1611 }
1612 
PrepareArgsForFastBuiltin()1613 std::vector<GateRef> CallStubBuilder::PrepareArgsForFastBuiltin()
1614 {
1615     std::vector<GateRef> basicArgs = PrepareBasicArgsForFastBuiltin();
1616     std::vector<GateRef> appendArgs = PrepareAppendArgsForFastBuiltin();
1617 
1618     basicArgs.insert(basicArgs.end(), appendArgs.begin(), appendArgs.end());
1619     return basicArgs;
1620 }
1621 
IsCallModeSupportPGO() const1622 bool CallStubBuilder::IsCallModeSupportPGO() const
1623 {
1624     switch (callArgs_.mode) {
1625         case JSCallMode::CALL_ARG0:
1626         case JSCallMode::CALL_ARG1:
1627         case JSCallMode::CALL_ARG2:
1628         case JSCallMode::CALL_ARG3:
1629         case JSCallMode::CALL_WITH_ARGV:
1630         case JSCallMode::CALL_THIS_ARG0:
1631         case JSCallMode::CALL_THIS_ARG1:
1632         case JSCallMode::CALL_THIS_ARG2:
1633         case JSCallMode::CALL_THIS_ARG3:
1634         case JSCallMode::CALL_THIS_WITH_ARGV:
1635         case JSCallMode::CALL_CONSTRUCTOR_WITH_ARGV:
1636         case JSCallMode::SUPER_CALL_WITH_ARGV:
1637         case JSCallMode::SUPER_CALL_SPREAD_WITH_ARGV:
1638         case JSCallMode::CALL_GETTER:
1639         case JSCallMode::CALL_SETTER:
1640             return true;
1641         case JSCallMode::DEPRECATED_CALL_ARG0:
1642         case JSCallMode::DEPRECATED_CALL_ARG1:
1643         case JSCallMode::DEPRECATED_CALL_ARG2:
1644         case JSCallMode::DEPRECATED_CALL_ARG3:
1645         case JSCallMode::DEPRECATED_CALL_WITH_ARGV:
1646         case JSCallMode::DEPRECATED_CALL_THIS_WITH_ARGV:
1647         case JSCallMode::DEPRECATED_CALL_CONSTRUCTOR_WITH_ARGV:
1648         case JSCallMode::CALL_ENTRY:
1649         case JSCallMode::CALL_FROM_AOT:
1650         case JSCallMode::CALL_GENERATOR:
1651         case JSCallMode::CALL_THIS_ARG2_WITH_RETURN:
1652         case JSCallMode::CALL_THIS_ARG3_WITH_RETURN:
1653         case JSCallMode::CALL_THIS_ARGV_WITH_RETURN:
1654             return false;
1655         default:
1656             LOG_ECMA(FATAL) << "this branch is unreachable";
1657             UNREACHABLE();
1658     }
1659 }
1660 
IsCallModeSupportCallBuiltin() const1661 bool CallStubBuilder::IsCallModeSupportCallBuiltin() const
1662 {
1663     switch (callArgs_.mode) {
1664         case JSCallMode::CALL_THIS_ARG0:
1665         case JSCallMode::CALL_THIS_ARG1:
1666         case JSCallMode::CALL_THIS_ARG2:
1667         case JSCallMode::CALL_THIS_ARG3:
1668         case JSCallMode::CALL_THIS_ARG2_WITH_RETURN:
1669             return true;
1670         case JSCallMode::CALL_CONSTRUCTOR_WITH_ARGV:
1671         case JSCallMode::DEPRECATED_CALL_CONSTRUCTOR_WITH_ARGV:
1672             return false;
1673         default:
1674             LOG_ECMA(FATAL) << "this branch is unreachable";
1675             UNREACHABLE();
1676     }
1677 }
1678 
CheckResultValueChangedWithReturn(GateRef prevResRef) const1679 bool CallStubBuilder::CheckResultValueChangedWithReturn(GateRef prevResRef) const
1680 {
1681     switch (callArgs_.mode) {
1682         case JSCallMode::CALL_GETTER:
1683         case JSCallMode::CALL_SETTER:
1684         case JSCallMode::CALL_THIS_ARG2_WITH_RETURN:
1685         case JSCallMode::CALL_THIS_ARG3_WITH_RETURN:
1686         case JSCallMode::CALL_THIS_ARGV_WITH_RETURN:
1687             return result_->Value() == prevResRef;
1688         default:
1689             return result_->Value() != prevResRef;
1690     }
1691 }
1692 
IsSlowAotCall() const1693 bool CallStubBuilder::IsSlowAotCall() const
1694 { return !isFast_ && !isBridge_; }
1695 
IsFastAotCall() const1696 bool CallStubBuilder::IsFastAotCall() const
1697 { return isFast_ && !isBridge_; }
1698 
IsSlowAotCallWithBridge() const1699 bool CallStubBuilder::IsSlowAotCallWithBridge() const
1700 { return !isFast_ && isBridge_; }
1701 
IsFastAotCallWithBridge() const1702 bool CallStubBuilder::IsFastAotCallWithBridge() const
1703 { return isFast_ && isBridge_; }
1704 
HandleProfileCall()1705 void CallStubBuilder::HandleProfileCall()
1706 {
1707     if (!callback_.IsEmpty()) {
1708         if (!IsCallModeSupportPGO()) {
1709             return;
1710         }
1711         if (IsCallModeGetterSetter()) {
1712             callback_.ProfileGetterSetterCall(func_);
1713             return;
1714         }
1715         callback_.ProfileCall(func_);
1716     }
1717 }
1718 
HandleProfileNativeCall()1719 void CallStubBuilder::HandleProfileNativeCall()
1720 {
1721     if (!callback_.IsEmpty()) {
1722         if (!IsCallModeSupportPGO()) {
1723             return;
1724         }
1725         if (!IsCallModeGetterSetter()) {
1726             callback_.ProfileNativeCall(func_);
1727         }
1728     }
1729 }
1730 
IsCallModeGetterSetter()1731 bool CallStubBuilder::IsCallModeGetterSetter()
1732 {
1733     switch (callArgs_.mode) {
1734         case JSCallMode::CALL_GETTER:
1735         case JSCallMode::CALL_SETTER:
1736             return true;
1737         default:
1738             return false;
1739     }
1740 }
1741 
1742 } // panda::ecmascript::kungfu
1743