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