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