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 ¬FastCall);
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(¬FastCall);
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, ¬FastCall);
257 builder.Bind(&fastCall);
258 {
259 Label notBridge(&builder);
260 Label bridge(&builder);
261 BRANCH_CIR(builder.Int64Equal(expectedNum, actualArgc), ¬Bridge, &bridge);
262 builder.Bind(¬Bridge);
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(¬FastCall);
272 BRANCH_CIR(IsAotCall(builder, superFunc), &aotCall, ¬AotCall);
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), ¬Bridge, &bridge);
279 builder.Bind(¬Bridge);
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(¬AotCall);
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, ¬CallConstructor);
332 builder.Bind(¬CallConstructor);
333 }
334 GateRef method = builder.GetMethodFromFunction(glue, func);
335 BRANCH_CIR(builder.JudgeAotAndFastCall(func,
336 CircuitBuilder::JudgeMethodType::HAS_AOT_FASTCALL), &fastCall, ¬FastCall);
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(¬FastCall);
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, ¬JSFunction);
537 Bind(&isJSFunction);
538 {
539 JSCallNativeInner(exit, true);
540 }
541 Bind(¬JSFunction);
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(¬FastBuiltins, exit, hir_);
572 Bind(¬FastBuiltins);
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