• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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 #include "ecmascript/compiler/native_inline_lowering.h"
16 #include "ecmascript/compiler/builtins/builtins_array_stub_builder.h"
17 #include "ecmascript/compiler/builtins/builtins_call_signature.h"
18 #include "ecmascript/global_env.h"
19 
20 namespace panda::ecmascript::kungfu {
21 
GetCallInfo(GateRef gate)22 std::optional<std::pair<size_t, bool>> NativeInlineLowering::GetCallInfo(GateRef gate)
23 {
24     EcmaOpcode ecmaOpcode = acc_.GetByteCodeOpcode(gate);
25     switch (ecmaOpcode) {
26         case EcmaOpcode::CALLARG0_IMM8:
27             return {{0U, false}};
28         case EcmaOpcode::CALLTHIS0_IMM8_V8:
29             return {{0U, true}};
30         case EcmaOpcode::CALLARG1_IMM8_V8:
31             return {{1U, false}};
32         case EcmaOpcode::CALLTHIS1_IMM8_V8_V8:
33             return {{1U, true}};
34         case EcmaOpcode::CALLARGS2_IMM8_V8_V8:
35             return {{2U, false}};
36         case EcmaOpcode::CALLTHIS2_IMM8_V8_V8_V8:
37             return {{2U, true}};
38         case EcmaOpcode::CALLARGS3_IMM8_V8_V8_V8:
39             return {{3U, false}};
40         case EcmaOpcode::CALLTHIS3_IMM8_V8_V8_V8_V8:
41             return {{3U, true}};
42         case EcmaOpcode::CALLRANGE_IMM8_IMM8_V8: {
43             CallRangeTypeInfoAccessor tia(compilationEnv_, circuit_, gate);
44             return {{tia.GetArgc(), false}};
45         }
46         case EcmaOpcode::CALLTHISRANGE_IMM8_IMM8_V8: {
47             CallThisRangeTypeInfoAccessor tia(compilationEnv_, circuit_, gate);
48             return {{tia.GetArgc(), true}};
49         }
50         default:
51             return std::nullopt;
52     }
53 }
54 
RunNativeInlineLowering()55 void NativeInlineLowering::RunNativeInlineLowering()
56 {
57     std::vector<GateRef> gateList;
58     circuit_->GetAllGates(gateList);
59     for (const auto &gate : gateList) {
60         auto op = acc_.GetOpCode(gate);
61         if (op != OpCode::JS_BYTECODE) {
62             continue;
63         }
64         auto optCallInfo = GetCallInfo(gate);
65         if (!optCallInfo) {
66             continue;
67         }
68         auto [argc, skipThis] = optCallInfo.value();
69         CallTypeInfoAccessor ctia(compilationEnv_, circuit_, gate);
70         BuiltinsStubCSigns::ID id = ctia.TryGetPGOBuiltinMethodId();
71         if (IS_INVALID_ID(id) && id != BuiltinsStubCSigns::ID::BigIntConstructor) {
72             continue;
73         }
74         switch (id) {
75             case BuiltinsStubCSigns::ID::StringFromCharCode:
76                 TryInlineStringFromCharCode(gate, argc, skipThis);
77                 break;
78             case BuiltinsStubCSigns::ID::StringCharCodeAt:
79                 TryInlineStringCharCodeAt(gate, argc, skipThis);
80                 break;
81             case BuiltinsStubCSigns::ID::StringSubstring:
82                 TryInlineStringSubstring(gate, argc, skipThis);
83                 break;
84             case BuiltinsStubCSigns::ID::StringSubStr:
85                 TryInlineStringSubStr(gate, argc, skipThis);
86                 break;
87             case BuiltinsStubCSigns::ID::StringSlice:
88                 TryInlineStringSlice(gate, argc, skipThis);
89                 break;
90             case BuiltinsStubCSigns::ID::NumberIsFinite:
91                 TryInlineNumberIsFinite(gate, argc, skipThis);
92                 break;
93             case BuiltinsStubCSigns::ID::NumberIsInteger:
94                 TryInlineNumberIsInteger(gate, argc, skipThis);
95                 break;
96             case BuiltinsStubCSigns::ID::NumberIsNaN:
97                 TryInlineNumberIsNaN(gate, argc, skipThis);
98                 break;
99             case BuiltinsStubCSigns::ID::NumberParseFloat:
100                 TryInlineNumberParseFloat(gate, argc, skipThis);
101                 break;
102             case BuiltinsStubCSigns::ID::NumberParseInt:
103                 TryInlineNumberParseInt(gate, argc, skipThis);
104                 break;
105             case BuiltinsStubCSigns::ID::NumberIsSafeInteger:
106                 TryInlineNumberIsSafeInteger(gate, argc, skipThis);
107                 break;
108             case BuiltinsStubCSigns::ID::TypedArrayEntries:
109                 TryInlineTypedArrayIteratorBuiltin(gate, id, circuit_->TypedArrayEntries(), skipThis);
110                 break;
111             case BuiltinsStubCSigns::ID::TypedArrayKeys:
112                 TryInlineTypedArrayIteratorBuiltin(gate, id, circuit_->TypedArrayKeys(), skipThis);
113                 break;
114             case BuiltinsStubCSigns::ID::TypedArrayValues:
115                 TryInlineTypedArrayIteratorBuiltin(gate, id, circuit_->TypedArrayValues(), skipThis);
116                 break;
117             case BuiltinsStubCSigns::ID::ArrayValues:
118                 TryInlineArrayIterator(gate, id, skipThis);
119                 break;
120             case BuiltinsStubCSigns::ID::ArrayKeys:
121                 TryInlineArrayIterator(gate, id, skipThis);
122                 break;
123             case BuiltinsStubCSigns::ID::ArrayEntries:
124                 TryInlineArrayIterator(gate, id, skipThis);
125                 break;
126             case BuiltinsStubCSigns::ID::MathAcos:
127                 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathAcos(), skipThis);
128                 break;
129             case BuiltinsStubCSigns::ID::MathAcosh:
130                 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathAcosh(), skipThis);
131                 break;
132             case BuiltinsStubCSigns::ID::MathAsin:
133                 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathAsin(), skipThis);
134                 break;
135             case BuiltinsStubCSigns::ID::MathAsinh:
136                 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathAsinh(), skipThis);
137                 break;
138             case BuiltinsStubCSigns::ID::MathAtan:
139                 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathAtan(), skipThis);
140                 break;
141             case BuiltinsStubCSigns::ID::MathAtan2:
142                 TryInlineMathBinaryBuiltin(gate, argc, id, circuit_->MathAtan2(), skipThis);
143                 break;
144             case BuiltinsStubCSigns::ID::MathAtanh:
145                 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathAtanh(), skipThis);
146                 break;
147             case BuiltinsStubCSigns::ID::MathCos:
148                 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathCos(), skipThis);
149                 break;
150             case BuiltinsStubCSigns::ID::MathCosh:
151                 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathCosh(), skipThis);
152                 break;
153             case BuiltinsStubCSigns::ID::MathSign:
154                 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathSign(), skipThis);
155                 break;
156             case BuiltinsStubCSigns::ID::MathSin:
157                 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathSin(), skipThis);
158                 break;
159             case BuiltinsStubCSigns::ID::MathSinh:
160                 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathSinh(), skipThis);
161                 break;
162             case BuiltinsStubCSigns::ID::MathSqrt:
163                 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathSqrt(), skipThis);
164                 break;
165             case BuiltinsStubCSigns::ID::MathTan:
166                 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathTan(), skipThis);
167                 break;
168             case BuiltinsStubCSigns::ID::MathTanh:
169                 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathTanh(), skipThis);
170                 break;
171             case BuiltinsStubCSigns::ID::MathTrunc:
172                 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathTrunc(), skipThis);
173                 break;
174             case BuiltinsStubCSigns::ID::MathAbs:
175                 TryInlineMathAbsBuiltin(gate, argc, skipThis);
176                 break;
177             case BuiltinsStubCSigns::ID::MathLog:
178                 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathLog(), skipThis);
179                 break;
180             case BuiltinsStubCSigns::ID::MathLog2:
181                 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathLog2(), skipThis);
182                 break;
183             case BuiltinsStubCSigns::ID::MathLog10:
184                 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathLog10(), skipThis);
185                 break;
186             case BuiltinsStubCSigns::ID::MathLog1p:
187                 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathLog1p(), skipThis);
188                 break;
189             case BuiltinsStubCSigns::ID::MathExp:
190                 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathExp(), skipThis);
191                 break;
192             case BuiltinsStubCSigns::ID::MathExpm1:
193                 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathExpm1(), skipThis);
194                 break;
195             case BuiltinsStubCSigns::ID::MathClz32:
196                 TryInlineMathClz32Builtin(gate, argc, skipThis);
197                 break;
198             case BuiltinsStubCSigns::ID::MathPow:
199                 TryInlineMathBinaryBuiltin(gate, argc, id, circuit_->MathPow(), skipThis);
200                 break;
201             case BuiltinsStubCSigns::ID::MathCbrt:
202                 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathCbrt(), skipThis);
203                 break;
204             case BuiltinsStubCSigns::ID::MathImul:
205                 TryInlineMathImulBuiltin(gate, argc, id, circuit_->MathImul(), skipThis);
206                 break;
207             case BuiltinsStubCSigns::ID::GlobalIsFinite:
208                 TryInlineGlobalFiniteBuiltin(gate, argc, id, circuit_->GlobalIsFinite(), skipThis);
209                 break;
210             case BuiltinsStubCSigns::ID::GlobalIsNan:
211                 TryInlineGlobalNanBuiltin(gate, argc, id, circuit_->GlobalIsNan(), skipThis);
212                 break;
213             case BuiltinsStubCSigns::ID::DateGetTime:
214                 TryInlineDateGetTime(gate, argc, skipThis);
215                 break;
216             case BuiltinsStubCSigns::ID::MathMin:
217                 TryInlineMathMinMaxBuiltin(gate, argc, id, circuit_->MathMin(), base::POSITIVE_INFINITY, skipThis);
218                 break;
219             case BuiltinsStubCSigns::ID::MathMax:
220                 TryInlineMathMinMaxBuiltin(gate, argc, id, circuit_->MathMax(), -base::POSITIVE_INFINITY, skipThis);
221                 break;
222             case BuiltinsStubCSigns::ID::MathRound:
223                 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathRound(), skipThis);
224                 break;
225             case BuiltinsStubCSigns::ID::MathFRound:
226                 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathFRound(), skipThis);
227                 break;
228             case BuiltinsStubCSigns::ID::MathCeil:
229                 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathCeil(), skipThis);
230                 break;
231             case BuiltinsStubCSigns::ID::MathFloor:
232                 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathFloor(), skipThis);
233                 break;
234             case BuiltinsStubCSigns::ID::ArrayBufferIsView:
235                 TryInlineArrayBufferIsView(gate, argc, id, skipThis);
236                 break;
237             case BuiltinsStubCSigns::ID::DataViewGetFloat32:
238             case BuiltinsStubCSigns::ID::DataViewGetFloat64:
239             case BuiltinsStubCSigns::ID::DataViewGetInt8:
240             case BuiltinsStubCSigns::ID::DataViewGetInt16:
241             case BuiltinsStubCSigns::ID::DataViewGetInt32:
242             case BuiltinsStubCSigns::ID::DataViewGetUint16:
243             case BuiltinsStubCSigns::ID::DataViewGetUint32:
244             case BuiltinsStubCSigns::ID::DataViewGetUint8:
245                 TryInlineDataViewGet(gate, argc, id, skipThis);
246                 break;
247             case BuiltinsStubCSigns::ID::DataViewSetFloat32:
248             case BuiltinsStubCSigns::ID::DataViewSetFloat64:
249             case BuiltinsStubCSigns::ID::DataViewSetInt8:
250             case BuiltinsStubCSigns::ID::DataViewSetInt16:
251             case BuiltinsStubCSigns::ID::DataViewSetInt32:
252             case BuiltinsStubCSigns::ID::DataViewSetUint8:
253             case BuiltinsStubCSigns::ID::DataViewSetUint16:
254             case BuiltinsStubCSigns::ID::DataViewSetUint32:
255                 TryInlineDataViewSet(gate, argc, id, skipThis);
256                 break;
257             case BuiltinsStubCSigns::ID::BigIntAsIntN:
258             case BuiltinsStubCSigns::ID::BigIntAsUintN:
259                 TryInlineBigIntAsIntN(gate, argc, id, skipThis);
260                 break;
261             case BuiltinsStubCSigns::ID::MapGet:
262                 InlineStubBuiltin(gate, 1U, argc, id, circuit_->MapGet(), skipThis);
263                 break;
264             case BuiltinsStubCSigns::ID::MapHas:
265                 InlineStubBuiltin(gate, 1U, argc, id, circuit_->MapHas(), skipThis);
266                 break;
267             case BuiltinsStubCSigns::ID::SetHas:
268                 InlineStubBuiltin(gate, 1U, argc, id, circuit_->SetHas(), skipThis);
269                 break;
270             case BuiltinsStubCSigns::ID::SetAdd:
271                 InlineStubBuiltin(gate, 1U, argc, id, circuit_->SetAdd(), skipThis);
272                 break;
273             case BuiltinsStubCSigns::ID::DateNow:
274                 TryInlineWhitoutParamBuiltin(gate, argc, id, circuit_->DateNow(), skipThis);
275                 break;
276             case BuiltinsStubCSigns::ID::MapDelete:
277                 InlineStubBuiltin(gate, 1U, argc, id, circuit_->MapDelete(), skipThis);
278                 break;
279             case BuiltinsStubCSigns::ID::SetDelete:
280                 InlineStubBuiltin(gate, 1U, argc, id, circuit_->SetDelete(), skipThis);
281                 break;
282             case BuiltinsStubCSigns::ID::BigIntConstructor:
283                 TryInlineBigIntConstructor(gate, argc, skipThis);
284                 break;
285             case BuiltinsStubCSigns::ID::ArraySort:
286                 TryInlineArraySort(gate, argc, id, skipThis);
287                 break;
288             case BuiltinsStubCSigns::ID::ObjectIs:
289                 TryInlineObjectIs(gate, argc, id, skipThis);
290                 break;
291             case BuiltinsStubCSigns::ID::ObjectGetPrototypeOf:
292                 TryInlineObjectGetPrototypeOf(gate, argc, id, skipThis);
293                 break;
294             case BuiltinsStubCSigns::ID::ObjectGetProto:
295                 TryInlineObjectGetProto(gate, argc, id, skipThis);
296                 break;
297             case BuiltinsStubCSigns::ID::ObjectCreate:
298                 TryInlineObjectCreate(gate, argc, id, skipThis);
299                 break;
300             case BuiltinsStubCSigns::ID::ObjectIsPrototypeOf:
301                 TryInlineObjectIsPrototypeOf(gate, argc, id, skipThis);
302                 break;
303             case BuiltinsStubCSigns::ID::ObjectHasOwnProperty:
304                 TryInlineObjectHasOwnProperty(gate, argc, id, skipThis);
305                 break;
306             case BuiltinsStubCSigns::ID::ReflectGetPrototypeOf:
307                 TryInlineReflectGetPrototypeOf(gate, argc, id, skipThis);
308                 break;
309             case BuiltinsStubCSigns::ID::ReflectGet:
310                 TryInlineReflectGet(gate, argc, id, skipThis);
311                 break;
312             case BuiltinsStubCSigns::ID::ReflectHas:
313                 TryInlineReflectHas(gate, argc, id, skipThis);
314                 break;
315             case BuiltinsStubCSigns::ID::ReflectConstruct:
316                 TryInlineReflectConstruct(gate, argc, id, skipThis);
317                 break;
318             case BuiltinsStubCSigns::ID::ReflectApply:
319                 TryInlineReflectApply(gate, argc, id, skipThis);
320                 break;
321             case BuiltinsStubCSigns::ID::FunctionPrototypeHasInstance:
322                 TryInlineFunctionPrototypeHasInstance(gate, argc, id, skipThis);
323                 break;
324             case BuiltinsStubCSigns::ID::ArrayIndexOf:
325             case BuiltinsStubCSigns::ID::ArrayLastIndexOf:
326             case BuiltinsStubCSigns::ID::ArrayIncludes:
327                 TryInlineIndexOfIncludes(gate, argc, id, skipThis);
328                 break;
329             case BuiltinsStubCSigns::ID::ArrayForEach:
330                 TryInlineArrayForEach(gate, argc, id, skipThis);
331                 break;
332             case BuiltinsStubCSigns::ID::ArrayFind:
333                 TryInlineArrayFindOrFindIndex(gate, argc, id, skipThis);
334                 break;
335             case BuiltinsStubCSigns::ID::ArrayFindIndex:
336                 TryInlineArrayFindOrFindIndex(gate, argc, id, skipThis);
337                 break;
338             case BuiltinsStubCSigns::ID::ArrayFilter:
339                 TryInlineArrayFilter(gate, argc, id, skipThis);
340                 break;
341             case BuiltinsStubCSigns::ID::ArrayMap:
342                 TryInlineArrayMap(gate, argc, id, skipThis);
343                 break;
344             case BuiltinsStubCSigns::ID::ArraySome:
345                 TryInlineArraySome(gate, argc, id, skipThis);
346                 break;
347             case BuiltinsStubCSigns::ID::ArrayEvery:
348                 TryInlineArrayEvery(gate, argc, id, skipThis);
349                 break;
350             case BuiltinsStubCSigns::ID::ArrayPop:
351                 TryInlineArrayPop(gate, argc, id, skipThis);
352                 break;
353             case BuiltinsStubCSigns::ID::ArrayPush:
354                 TryInlineArrayPush(gate, argc, id, skipThis);
355                 break;
356             case BuiltinsStubCSigns::ID::ArraySlice:
357                 // disable slice inline because builtin call is faster than inline implementation.
358                 // and the elementsKind in inline implementation is missed.
359                 TryInlineArraySlice(gate, argc, id, false);
360                 break;
361             default:
362                 break;
363         }
364     }
365 
366     if (EnableLog()) {
367         LOG_COMPILER(INFO) << " ";
368         LOG_COMPILER(INFO) << "\033[34m" << "================="
369                            << " After Native Inline Lowering "
370                            << "[" << GetMethodName() << "] "
371                            << "=================" << "\033[0m";
372         circuit_->PrintAllGatesWithBytecode();
373         LOG_COMPILER(INFO) << "\033[34m" << "=========================== End ===========================" << "\033[0m";
374     }
375 }
376 
AddTraceLogs(GateRef gate,BuiltinsStubCSigns::ID id)377 void NativeInlineLowering::AddTraceLogs(GateRef gate, BuiltinsStubCSigns::ID id)
378 {
379     size_t index = RTSTUB_ID(AotInlineBuiltinTrace);
380 
381     GateRef frameState = acc_.GetFrameState(gate);
382     GateRef frameArgs = acc_.GetValueIn(frameState);
383     GateRef callerFunc = acc_.GetValueIn(frameArgs, 0);
384     std::vector<GateRef> args{callerFunc, builder_.Int32(id)};
385 
386     builder_.CallRuntime(glue_, index, Gate::InvalidGateRef, args, gate);
387 }
388 
TryInlineStringFromCharCode(GateRef gate,size_t argc,bool skipThis)389 void NativeInlineLowering::TryInlineStringFromCharCode(GateRef gate, size_t argc, bool skipThis)
390 {
391     if (!skipThis) {
392         return;
393     }
394     if (argc != 1) {
395         return;
396     }
397     CallThis1TypeInfoAccessor tacc(compilationEnv_, circuit_, gate);
398     Environment env(gate, circuit_, &builder_);
399     if (!Uncheck()) {
400         builder_.CallTargetCheck(gate, tacc.GetFunc(),
401                                  builder_.IntPtr(static_cast<int64_t>(BuiltinsStubCSigns::ID::StringFromCharCode)),
402                                  {tacc.GetArg0()});
403     }
404 
405     if (EnableTrace()) {
406         AddTraceLogs(gate, BuiltinsStubCSigns::ID::StringFromCharCode);
407     }
408 
409     GateRef ret = builder_.StringFromSingleCharCode(tacc.GetArg0());
410     ReplaceGateWithPendingException(gate, ret);
411 }
412 
TryInlineStringCharCodeAt(GateRef gate,size_t argc,bool skipThis)413 void NativeInlineLowering::TryInlineStringCharCodeAt(GateRef gate, size_t argc, bool skipThis)
414 {
415     // only inline number input, string input will be deoptimized
416     if (!skipThis) {
417         return;
418     }
419 
420     GateRef thisValue = acc_.GetValueIn(gate, 0);
421     GateRef posTag = (argc == 0) ? (builder_.Int32(0)) : (acc_.GetValueIn(gate, 1));
422     GateRef func = acc_.GetValueIn(gate, argc + 1);
423     Environment env(gate, circuit_, &builder_);
424     if (!Uncheck()) {
425         builder_.CallTargetCheck(gate, func,
426                                  builder_.IntPtr(static_cast<int64_t>(BuiltinsStubCSigns::ID::StringCharCodeAt)),
427                                  {thisValue});
428         builder_.EcmaStringCheck(thisValue);
429     }
430 
431     if (EnableTrace()) {
432         AddTraceLogs(gate, BuiltinsStubCSigns::ID::StringCharCodeAt);
433     }
434 
435     GateRef ret = builder_.StringCharCodeAt(thisValue, posTag);
436     acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret);
437 }
438 
TryInlineStringSubstring(GateRef gate,size_t argc,bool skipThis)439 void NativeInlineLowering::TryInlineStringSubstring(GateRef gate, size_t argc, bool skipThis)
440 {
441     if (!skipThis) {
442         return;
443     }
444     if (argc != 1 && argc != 2) { // only optimize one or two parameters scene
445         return;
446     }
447     Environment env(gate, circuit_, &builder_);
448     GateRef ret = Circuit::NullGate();
449     if (argc == 1) {
450         CallThis1TypeInfoAccessor tacc(compilationEnv_, circuit_, gate);
451         GateRef thisValue = acc_.GetValueIn(gate, 0);
452         GateRef startTag = tacc.GetArg0();
453         if (!Uncheck()) {
454             builder_.CallTargetCheck(gate, tacc.GetFunc(),
455                                      builder_.IntPtr(static_cast<int64_t>(BuiltinsStubCSigns::ID::StringSubstring)),
456                                      {tacc.GetArg0()});
457             builder_.EcmaStringCheck(thisValue);
458             auto param_check = builder_.TaggedIsNumber(startTag);
459             builder_.DeoptCheck(param_check, acc_.GetFrameState(gate), DeoptType::BUILTIN_INLINING_TYPE_GUARD);
460         }
461         std::vector<GateRef> args {thisValue, startTag};
462         ret = builder_.StringSubstring(args);
463     } else {
464         GateRef thisValue = acc_.GetValueIn(gate, 0);
465         GateRef startTag = acc_.GetValueIn(gate, 1);
466         GateRef endTag = acc_.GetValueIn(gate, 2);
467         GateRef func = acc_.GetValueIn(gate, 3);
468         if (!Uncheck()) {
469             builder_.CallTargetCheck(gate, func,
470                                      builder_.IntPtr(static_cast<int64_t>(BuiltinsStubCSigns::ID::StringSubstring)));
471             builder_.EcmaStringCheck(thisValue);
472             auto param_check = LogicAndBuilder(&env).And(builder_.TaggedIsNumber(startTag))
473                 .And(builder_.TaggedIsNumber(endTag)).Done();
474             builder_.DeoptCheck(param_check, acc_.GetFrameState(gate), DeoptType::BUILTIN_INLINING_TYPE_GUARD);
475         }
476         std::vector<GateRef> args {thisValue, startTag, endTag};
477         ret = builder_.StringSubstring(args);
478     }
479     acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret);
480 }
481 
TryInlineStringSubStr(GateRef gate,size_t argc,bool skipThis)482 void NativeInlineLowering::TryInlineStringSubStr(GateRef gate, size_t argc, bool skipThis)
483 {
484     if (!skipThis) {
485         return;
486     }
487     if (argc != 1 && argc != 2) { // only optimize one or two parameters scene
488         return;
489     }
490     Environment env(gate, circuit_, &builder_);
491     GateRef ret = Circuit::NullGate();
492     if (argc == 1) {
493         CallThis1TypeInfoAccessor tacc(compilationEnv_, circuit_, gate);
494         GateRef thisValue = acc_.GetValueIn(gate, 0);
495         GateRef intStart = tacc.GetArg0();
496         GateRef lengthTag = builder_.Int32(INT_MAX);
497         if (!Uncheck()) {
498             builder_.CallTargetCheck(gate, tacc.GetFunc(),
499                                      builder_.IntPtr(static_cast<int64_t>(BuiltinsStubCSigns::ID::StringSubStr)),
500                                      {tacc.GetArg0()});
501             builder_.EcmaStringCheck(thisValue);
502             auto param_check = builder_.TaggedIsNumber(intStart);
503             builder_.DeoptCheck(param_check, acc_.GetFrameState(gate), DeoptType::BUILTIN_INLINING_TYPE_GUARD);
504         }
505         ret = builder_.StringSubStr(thisValue, intStart, lengthTag);
506     } else {
507         GateRef thisValue = acc_.GetValueIn(gate, 0);
508         GateRef intStart = acc_.GetValueIn(gate, 1);
509         GateRef lengthTag = acc_.GetValueIn(gate, 2);
510         GateRef func = acc_.GetValueIn(gate, 3);  //acc
511         if (!Uncheck()) {
512             builder_.CallTargetCheck(gate, func,
513                                      builder_.IntPtr(static_cast<int64_t>(BuiltinsStubCSigns::ID::StringSubStr)));
514             builder_.EcmaStringCheck(thisValue);
515             auto param_check = LogicAndBuilder(&env).And(builder_.TaggedIsNumber(intStart))
516                 .And(builder_.TaggedIsNumber(lengthTag)).Done();
517             builder_.DeoptCheck(param_check, acc_.GetFrameState(gate), DeoptType::BUILTIN_INLINING_TYPE_GUARD);
518         }
519         ret = builder_.StringSubStr(thisValue, intStart, lengthTag);
520     }
521     acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret);
522 }
523 
TryInlineStringSlice(GateRef gate,size_t argc,bool skipThis)524 void NativeInlineLowering::TryInlineStringSlice(GateRef gate, size_t argc, bool skipThis)
525 {
526     if (!skipThis) {
527         return;
528     }
529     if (argc != 1 && argc != 2) { // only optimize one or two parameters scene
530         return;
531     }
532     Environment env(gate, circuit_, &builder_);
533     GateRef ret = Circuit::NullGate();
534     if (argc == 1) {
535         CallThis1TypeInfoAccessor tacc(compilationEnv_, circuit_, gate);
536         GateRef thisValue = acc_.GetValueIn(gate, 0);
537         GateRef startTag = tacc.GetArg0();
538         if (!Uncheck()) {
539             builder_.CallTargetCheck(gate, tacc.GetFunc(),
540                                      builder_.IntPtr(static_cast<int64_t>(BuiltinsStubCSigns::ID::StringSlice)),
541                                      {tacc.GetArg0()});
542             builder_.EcmaStringCheck(thisValue);
543             auto param_check = builder_.TaggedIsNumber(startTag);
544             builder_.DeoptCheck(param_check, acc_.GetFrameState(gate), DeoptType::BUILTIN_INLINING_TYPE_GUARD);
545         }
546         std::vector<GateRef> args {thisValue, startTag};
547         ret = builder_.StringSlice(args);
548     } else {
549         GateRef thisValue = acc_.GetValueIn(gate, 0);
550         GateRef startTag = acc_.GetValueIn(gate, 1);
551         GateRef endTag = acc_.GetValueIn(gate, 2);
552         GateRef func = acc_.GetValueIn(gate, 3);
553         if (!Uncheck()) {
554             builder_.CallTargetCheck(gate, func,
555                                      builder_.IntPtr(static_cast<int64_t>(BuiltinsStubCSigns::ID::StringSlice)));
556             builder_.EcmaStringCheck(thisValue);
557             auto param_check = LogicAndBuilder(&env).And(builder_.TaggedIsNumber(startTag))
558                 .And(builder_.TaggedIsNumber(endTag)).Done();
559             builder_.DeoptCheck(param_check, acc_.GetFrameState(gate), DeoptType::BUILTIN_INLINING_TYPE_GUARD);
560         }
561         std::vector<GateRef> args {thisValue, startTag, endTag};
562         ret = builder_.StringSlice(args);
563     }
564     acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret);
565 }
566 
TryInlineNumberIsFinite(GateRef gate,size_t argc,bool skipThis)567 void NativeInlineLowering::TryInlineNumberIsFinite(GateRef gate, size_t argc, bool skipThis)
568 {
569     if (!skipThis) {
570         return;
571     }
572     if (argc != 1) {
573         return;
574     }
575     CallThis1TypeInfoAccessor tacc(compilationEnv_, circuit_, gate);
576     Environment env(gate, circuit_, &builder_);
577     if (!Uncheck()) {
578         builder_.CallTargetCheck(gate, tacc.GetFunc(),
579                                  builder_.IntPtr(static_cast<int64_t>(BuiltinsStubCSigns::ID::NumberIsFinite)));
580     }
581     GateRef ret = builder_.NumberIsFinite(tacc.GetArg0());
582     acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret);
583 }
584 
TryInlineNumberIsInteger(GateRef gate,size_t argc,bool skipThis)585 void NativeInlineLowering::TryInlineNumberIsInteger(GateRef gate, size_t argc, bool skipThis)
586 {
587     if (!skipThis) {
588         return;
589     }
590     if (argc != 1) {
591         return;
592     }
593     CallThis1TypeInfoAccessor tacc(compilationEnv_, circuit_, gate);
594     Environment env(gate, circuit_, &builder_);
595     auto id = BuiltinsStubCSigns::ID::NumberIsInteger;
596     if (!Uncheck()) {
597         builder_.CallTargetCheck(gate, tacc.GetFunc(),
598                                  builder_.IntPtr(static_cast<int64_t>(id)));
599     }
600     if (EnableTrace()) {
601         AddTraceLogs(gate, id);
602     }
603     GateRef ret = builder_.NumberIsInteger(tacc.GetArg0());
604     acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret);
605 }
606 
TryInlineNumberIsNaN(GateRef gate,size_t argc,bool skipThis)607 void NativeInlineLowering::TryInlineNumberIsNaN(GateRef gate, size_t argc, bool skipThis)
608 {
609     if (!skipThis) {
610         return;
611     }
612     if (argc != 1) {
613         return;
614     }
615     CallThis1TypeInfoAccessor tacc(compilationEnv_, circuit_, gate);
616     Environment env(gate, circuit_, &builder_);
617     if (!Uncheck()) {
618         builder_.CallTargetCheck(gate, tacc.GetFunc(),
619                                  builder_.IntPtr(static_cast<int64_t>(BuiltinsStubCSigns::ID::NumberIsNaN)));
620     }
621     GateRef ret = builder_.NumberIsNaN(tacc.GetArg0());
622     acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret);
623 }
624 
TryInlineNumberParseFloat(GateRef gate,size_t argc,bool skipThis)625 void NativeInlineLowering::TryInlineNumberParseFloat(GateRef gate, size_t argc, bool skipThis)
626 {
627     auto firstParam = skipThis ? 1 : 0;
628     auto func = acc_.GetValueIn(gate, argc + firstParam);
629     auto arg = acc_.GetValueIn(gate, firstParam);
630 
631     Environment env(gate, circuit_, &builder_);
632     auto id = BuiltinsStubCSigns::ID::NumberParseFloat;
633     if (!Uncheck()) {
634         builder_.CallTargetCheck(gate, func, builder_.IntPtr(static_cast<int64_t>(id)));
635     }
636     if (EnableTrace()) {
637         AddTraceLogs(gate, id);
638     }
639     GateRef ret = builder_.NumberParseFloat(arg, acc_.GetFrameState(gate));
640     acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret);
641 }
642 
TryInlineNumberParseInt(GateRef gate,size_t argc,bool skipThis)643 void NativeInlineLowering::TryInlineNumberParseInt(GateRef gate, size_t argc, bool skipThis)
644 {
645     auto firstParam = skipThis ? 1 : 0;
646     auto func = acc_.GetValueIn(gate, argc + firstParam);
647     auto arg = acc_.GetValueIn(gate, firstParam);
648     auto radix = builder_.Undefined();
649     if (argc > 1) {
650         radix = acc_.GetValueIn(gate, firstParam + 1);
651     }
652 
653     Environment env(gate, circuit_, &builder_);
654     auto id = BuiltinsStubCSigns::ID::NumberParseInt;
655     if (!Uncheck()) {
656         builder_.CallTargetCheck(gate, func, builder_.IntPtr(static_cast<int64_t>(id)));
657     }
658     if (EnableTrace()) {
659         AddTraceLogs(gate, id);
660     }
661     // this may return exception
662     GateRef ret = builder_.NumberParseInt(arg, radix);
663     acc_.ReplaceGate(gate, builder_.GetStateDepend(), ret);
664 }
665 
TryInlineNumberIsSafeInteger(GateRef gate,size_t argc,bool skipThis)666 void NativeInlineLowering::TryInlineNumberIsSafeInteger(GateRef gate, size_t argc, bool skipThis)
667 {
668     if (!skipThis) {
669         return;
670     }
671     if (argc != 1) {
672         return;
673     }
674     CallThis1TypeInfoAccessor tacc(compilationEnv_, circuit_, gate);
675     Environment env(gate, circuit_, &builder_);
676     auto id = BuiltinsStubCSigns::ID::NumberIsSafeInteger;
677     if (!Uncheck()) {
678         builder_.CallTargetCheck(gate, tacc.GetFunc(),
679                                  builder_.IntPtr(static_cast<int64_t>(id)));
680     }
681     if (EnableTrace()) {
682         AddTraceLogs(gate, id);
683     }
684     GateRef ret = builder_.NumberIsSafeInteger(tacc.GetArg0());
685     acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret);
686 }
687 
TryInlineBigIntAsIntN(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)688 void NativeInlineLowering::TryInlineBigIntAsIntN(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id,
689                                                  bool skipThis)
690 {
691     Environment env(gate, circuit_, &builder_);
692     bool firstParam = skipThis ? 1 : 0;
693     if (argc < 2U) {
694         return;
695     }
696     if (!Uncheck()) {
697         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam),
698                                  builder_.IntPtr(static_cast<int64_t>(id)));
699     }
700     if (EnableTrace()) {
701         AddTraceLogs(gate, id);
702     }
703     GateRef bits = acc_.GetValueIn(gate, firstParam);
704     GateRef bigint = acc_.GetValueIn(gate, firstParam + 1);
705     GateRef frameState = acc_.GetFrameState(gate);
706     bool isUnsigned = (id == BuiltinsStubCSigns::ID::BigIntAsUintN);
707     const auto* op = isUnsigned ? circuit_->BigIntAsUintN() : circuit_->BigIntAsIntN();
708     GateRef ret = builder_.BuildBigIntAsIntN(op, {bits, bigint, frameState});
709     ReplaceGateWithPendingException(gate, ret);
710 }
711 
TryInlineTypedArrayIteratorBuiltin(GateRef gate,BuiltinsStubCSigns::ID id,const GateMetaData * op,bool skipThis)712 void NativeInlineLowering::TryInlineTypedArrayIteratorBuiltin(GateRef gate,
713                                                               BuiltinsStubCSigns::ID id,
714                                                               const GateMetaData* op, bool skipThis)
715 {
716     if (!skipThis) {
717         return;
718     }
719 
720     CallThis0TypeInfoAccessor tacc(compilationEnv_, circuit_, gate);
721     Environment env(gate, circuit_, &builder_);
722 
723     if (!Uncheck()) {
724         builder_.CallTargetCheck(gate, tacc.GetFunc(), builder_.IntPtr(static_cast<int64_t>(id)), {tacc.GetThisObj()});
725     }
726 
727     if (EnableTrace()) {
728         AddTraceLogs(gate, id);
729     }
730 
731     GateRef ret = builder_.BuildTypedArrayIterator(acc_.GetValueIn(gate, 0), op);
732     ReplaceGateWithPendingException(gate, ret);
733 }
734 
TryInlineMathUnaryBuiltin(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,const GateMetaData * op,bool skipThis)735 void NativeInlineLowering::TryInlineMathUnaryBuiltin(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id,
736                                                      const GateMetaData* op, bool skipThis)
737 {
738     Environment env(gate, circuit_, &builder_);
739     bool firstParam = skipThis ? 1 : 0;
740     if (!Uncheck()) {
741         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam),
742                                  builder_.IntPtr(static_cast<int64_t>(id)));
743     }
744 
745     if (EnableTrace()) {
746         AddTraceLogs(gate, id);
747     }
748 
749     if (argc == 0) {
750         acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), builder_.NanValue());
751         return;
752     }
753     GateRef ret = builder_.BuildControlDependOp(op, {acc_.GetValueIn(gate, firstParam)});
754     acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret);
755 }
756 
TryInlineWhitoutParamBuiltin(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,const GateMetaData * op,bool skipThis)757 void NativeInlineLowering::TryInlineWhitoutParamBuiltin(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id,
758                                                         const GateMetaData* op, bool skipThis)
759 {
760     Environment env(gate, circuit_, &builder_);
761     bool firstParam = skipThis ? 1 : 0;
762     if (!Uncheck()) {
763         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam),
764                                  builder_.IntPtr(static_cast<int64_t>(id)));
765     }
766 
767     if (EnableTrace()) {
768         AddTraceLogs(gate, id);
769     }
770 
771     GateRef ret = builder_.BuildControlDependOp(op, {});
772     acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret);
773 }
774 
TryInlineMathAbsBuiltin(GateRef gate,size_t argc,bool skipThis)775 void NativeInlineLowering::TryInlineMathAbsBuiltin(GateRef gate, size_t argc, bool skipThis)
776 {
777     Environment env(gate, circuit_, &builder_);
778     bool firstParam = skipThis ? 1 : 0;
779     if (!Uncheck()) {
780         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam),
781                                  builder_.IntPtr(static_cast<int64_t>(BuiltinsStubCSigns::ID::MathAbs)));
782     }
783 
784     if (EnableTrace()) {
785         AddTraceLogs(gate, BuiltinsStubCSigns::ID::MathAbs);
786     }
787 
788     if (argc == 0) {
789         acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), builder_.NanValue());
790         return;
791     }
792     GateRef ret = builder_.BuildControlDependOp(circuit_->MathAbs(), {acc_.GetValueIn(gate, firstParam)},
793                                                 {acc_.GetFrameState(gate)});
794     acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret);
795 }
796 
TryInlineMathClz32Builtin(GateRef gate,size_t argc,bool skipThis)797 void NativeInlineLowering::TryInlineMathClz32Builtin(GateRef gate, size_t argc, bool skipThis)
798 {
799     Environment env(gate, circuit_, &builder_);
800     bool firstParam = skipThis ? 1 : 0;
801     if (!Uncheck()) {
802         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam),
803                                  builder_.IntPtr(static_cast<int64_t>(BuiltinsStubCSigns::ID::MathClz32)));
804     }
805     if (EnableTrace()) {
806         AddTraceLogs(gate, BuiltinsStubCSigns::ID::MathClz32);
807     }
808     if (argc == 0) {
809         const int32_t defaultValue = 32;
810         acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), builder_.Int32(defaultValue));
811         return;
812     }
813     GateRef ret = builder_.BuildControlDependOp(circuit_->MathClz32(), {acc_.GetValueIn(gate, firstParam)});
814     acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret);
815 }
816 
TryInlineGlobalFiniteBuiltin(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,const GateMetaData * op,bool skipThis)817 void NativeInlineLowering::TryInlineGlobalFiniteBuiltin(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id,
818                                                         const GateMetaData* op, bool skipThis)
819 {
820     Environment env(gate, circuit_, &builder_);
821     bool firstParam = skipThis ? 1 : 0;
822     if (!Uncheck()) {
823         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam),
824                                  builder_.IntPtr(static_cast<int64_t>(id)));
825     }
826     if (EnableTrace()) {
827         AddTraceLogs(gate, id);
828     }
829     if (argc == 0) {
830         acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), builder_.Boolean(false));
831         return;
832     }
833     GateRef ret = builder_.BuildControlDependOp(op, {acc_.GetValueIn(gate, firstParam)});
834     acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret);
835 }
836 
TryInlineGlobalNanBuiltin(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,const GateMetaData * op,bool skipThis)837 void NativeInlineLowering::TryInlineGlobalNanBuiltin(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id,
838                                                      const GateMetaData* op, bool skipThis)
839 {
840     Environment env(gate, circuit_, &builder_);
841     bool firstParam = skipThis ? 1 : 0;
842     if (!Uncheck()) {
843         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam),
844                                  builder_.IntPtr(static_cast<int64_t>(id)));
845     }
846     if (EnableTrace()) {
847         AddTraceLogs(gate, id);
848     }
849     if (argc == 0) {
850         acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), builder_.Boolean(true));
851         return;
852     }
853     GateRef ret = builder_.BuildControlDependOp(op, {acc_.GetValueIn(gate, firstParam)});
854     acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret);
855 }
856 
TryInlineMathImulBuiltin(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,const GateMetaData * op,bool skipThis)857 void NativeInlineLowering::TryInlineMathImulBuiltin(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id,
858                                                     const GateMetaData* op, bool skipThis)
859 {
860     Environment env(gate, circuit_, &builder_);
861     bool firstParam = skipThis ? 1 : 0;
862     if (!Uncheck()) {
863         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam),
864                                  builder_.IntPtr(static_cast<int64_t>(id)));
865     }
866     if (EnableTrace()) {
867         AddTraceLogs(gate, id);
868     }
869     if (argc < 2U) {
870         acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), builder_.Int32(0));
871         return;
872     }
873     GateRef ret = builder_.BuildControlDependOp(op, {acc_.GetValueIn(gate, firstParam),
874                                               acc_.GetValueIn(gate, firstParam + 1)});
875     acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret);
876     return;
877 }
878 
TryInlineMathBinaryBuiltin(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,const GateMetaData * op,bool skipThis)879 void NativeInlineLowering::TryInlineMathBinaryBuiltin(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id,
880                                                       const GateMetaData* op, bool skipThis)
881 {
882     Environment env(gate, circuit_, &builder_);
883     bool firstParam = skipThis ? 1 : 0;
884     if (!Uncheck()) {
885         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam),
886                                  builder_.IntPtr(static_cast<int64_t>(id)));
887     }
888     if (EnableTrace()) {
889         AddTraceLogs(gate, id);
890     }
891     if (argc < 2U) {
892         acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), builder_.NanValue());
893         return;
894     }
895     GateRef ret = builder_.BuildControlDependOp(op, {acc_.GetValueIn(gate, firstParam),
896                                               acc_.GetValueIn(gate, firstParam + 1)});
897     acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret);
898     return;
899 }
900 
TryInlineMathMinMaxBuiltin(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,const GateMetaData * op,double defaultValue,bool skipThis)901 void NativeInlineLowering::TryInlineMathMinMaxBuiltin(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id,
902                                                       const GateMetaData* op, double defaultValue, bool skipThis)
903 {
904     Environment env(gate, circuit_, &builder_);
905     bool firstParam = skipThis ? 1 : 0;
906     if (!Uncheck()) {
907         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam),
908                                  builder_.IntPtr(static_cast<int64_t>(id)));
909     }
910     if (EnableTrace()) {
911         AddTraceLogs(gate, id);
912     }
913     if (argc == 0) {
914         acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), builder_.Double(defaultValue));
915         return;
916     }
917     GateRef ret = acc_.GetValueIn(gate, firstParam);
918     if (argc == 1) {
919         builder_.TypeOfCheck(ret, ParamType::NumberType());
920         acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret);
921         return;
922     }
923     for (size_t i = 1; i < argc; i++) {
924         auto param = acc_.GetValueIn(gate, i + firstParam);
925         ret = builder_.BuildControlDependOp(op, {ret, param});
926     }
927     acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret);
928 }
929 
TryInlineArrayBufferIsView(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)930 void NativeInlineLowering::TryInlineArrayBufferIsView(GateRef gate,
931                                                       size_t argc,
932                                                       BuiltinsStubCSigns::ID id,
933                                                       bool skipThis)
934 {
935     if (!skipThis) {
936         return;
937     }
938     if (argc != 1) {
939         return;
940     }
941     CallThis1TypeInfoAccessor tacc(compilationEnv_, circuit_, gate);
942     Environment env(gate, circuit_, &builder_);
943     if (!Uncheck()) {
944         builder_.CallTargetCheck(gate, tacc.GetFunc(), builder_.IntPtr(static_cast<int64_t>(id)), {tacc.GetArg0()});
945     }
946     GateRef arg0 = tacc.GetArg0();
947     GateRef ret = builder_.ArrayBufferIsView(arg0);
948     acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret);
949 }
950 
TryInlineDataViewGet(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)951 void NativeInlineLowering::TryInlineDataViewGet(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis)
952 {
953     if (!skipThis) {
954         return;
955     }
956     if (argc != 1 && argc != 2) { // number of args must be 1/2
957         return;
958     }
959     Environment env(gate, circuit_, &builder_);
960     if (!Uncheck()) {
961         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + 1), builder_.IntPtr(static_cast<int64_t>(id)));
962     }
963     GateRef thisObj = acc_.GetValueIn(gate, 0); // 0: this
964     builder_.EcmaObjectCheck(thisObj);
965     builder_.IsDataViewCheck(thisObj);
966     GateRef dataViewCallID = builder_.Int32(id);
967     GateRef index = acc_.GetValueIn(gate, 1); // 1: index of dataView
968     GateRef ret = Circuit::NullGate();
969     GateRef frameState = acc_.GetFrameState(gate);
970     builder_.DeoptCheck(builder_.TaggedIsInt(index), frameState, DeoptType::INDEXNOTINT);
971     GateRef indexInt = builder_.TaggedGetInt(index);
972     if (argc == 1) { // if not provide isLittleEndian, default use big endian
973         ret = builder_.DataViewGet(thisObj, indexInt, dataViewCallID, builder_.False(), frameState);
974     } else if (argc == 2) { // 2: provide isLittleEndian
975         GateRef isLittleEndian = acc_.GetValueIn(gate, 2); // 2: is little endian mode
976         ret = builder_.DataViewGet(thisObj, indexInt, dataViewCallID, isLittleEndian, frameState);
977     }
978     if (EnableTrace()) {
979         AddTraceLogs(gate, id);
980     }
981     acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret);
982 }
983 
TryInlineDataViewSet(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)984 void NativeInlineLowering::TryInlineDataViewSet(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis)
985 {
986     if (!skipThis) {
987         return;
988     }
989     if (argc != 1 && argc != 2 && argc != 3) { // number of args must be 1/2/3
990         return;
991     }
992     Environment env(gate, circuit_, &builder_);
993     if (!Uncheck()) {
994         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + 1), builder_.IntPtr(static_cast<int64_t>(id)));
995     }
996     GateRef thisObj = acc_.GetValueIn(gate, 0); // 0: this
997     builder_.EcmaObjectCheck(thisObj);
998     builder_.IsDataViewCheck(thisObj);
999     GateRef dataViewCallID = builder_.Int32(id);
1000     GateRef index = acc_.GetValueIn(gate, 1); // 1: index
1001     GateRef frameState = acc_.GetFrameState(gate);
1002     builder_.DeoptCheck(builder_.TaggedIsInt(index), frameState, DeoptType::INDEXNOTINT);
1003     GateRef indexInt = builder_.TaggedGetInt(index);
1004     GateRef ret = Circuit::NullGate();
1005     if (argc == 1) { // arg counts is 1
1006         ret = builder_.DataViewSet(
1007             thisObj, indexInt, builder_.Double(base::NAN_VALUE), dataViewCallID, builder_.False(), frameState);
1008     } else if (argc == 2) { // arg counts is 2
1009         GateRef value = acc_.GetValueIn(gate, 2); // 2: value
1010         ret = builder_.DataViewSet(thisObj, indexInt, value, dataViewCallID, builder_.False(), frameState);
1011     } else if (argc == 3) { // arg counts is 3
1012         GateRef value = acc_.GetValueIn(gate, 2); // 2: value
1013         GateRef isLittleEndian = acc_.GetValueIn(gate, 3); // 3: is little endian mode
1014         ret = builder_.DataViewSet(thisObj, indexInt, value, dataViewCallID, isLittleEndian, frameState);
1015     }
1016     if (EnableTrace()) {
1017         AddTraceLogs(gate, id);
1018     }
1019     acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret);
1020 }
1021 
InlineStubBuiltin(GateRef gate,size_t builtinArgc,size_t realArgc,BuiltinsStubCSigns::ID id,const GateMetaData * op,bool skipThis)1022 void NativeInlineLowering::InlineStubBuiltin(GateRef gate, size_t builtinArgc, size_t realArgc,
1023     BuiltinsStubCSigns::ID id, const GateMetaData* op, bool skipThis)
1024 {
1025     if (!skipThis) {
1026         return;
1027     }
1028     Environment env(gate, circuit_, &builder_);
1029     if (!Uncheck()) {
1030         GateRef obj = acc_.GetValueIn(gate, 0);
1031         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, realArgc + 1U),
1032                                  builder_.IntPtr(static_cast<int64_t>(id)), {obj});
1033     }
1034     if (EnableTrace()) {
1035         AddTraceLogs(gate, id);
1036     }
1037 
1038     std::vector<GateRef> args {};
1039     for (size_t i = 0; i <= builtinArgc; i++) {
1040         args.push_back(i <= realArgc ? acc_.GetValueIn(gate, i) : builder_.Undefined());
1041     }
1042     GateRef ret = builder_.BuildControlDependOp(op, args);
1043     acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret);
1044 }
1045 
ReplaceGateWithPendingException(GateRef hirGate,GateRef value)1046 void NativeInlineLowering::ReplaceGateWithPendingException(GateRef hirGate, GateRef value)
1047 {
1048     GateRef state = builder_.GetState();
1049     // copy depend-wire of hirGate to value
1050     GateRef depend = builder_.GetDepend();
1051     // exception condition
1052     GateRef condition = builder_.HasPendingException(glue_);
1053     auto ifBranch = builder_.Branch(state, condition, 1, BranchWeight::DEOPT_WEIGHT, "checkException");
1054 
1055     GateRef ifTrue = builder_.IfTrue(ifBranch);
1056     GateRef ifFalse = builder_.IfFalse(ifBranch);
1057     GateRef eDepend = builder_.DependRelay(ifTrue, depend);
1058     GateRef sDepend = builder_.DependRelay(ifFalse, depend);
1059     StateDepend success(ifFalse, sDepend);
1060     StateDepend exception(ifTrue, eDepend);
1061     acc_.ReplaceHirWithIfBranch(hirGate, success, exception, value);
1062 }
1063 
TryInlineBigIntConstructor(GateRef gate,size_t argc,bool skipThis)1064 void NativeInlineLowering::TryInlineBigIntConstructor(GateRef gate, size_t argc, bool skipThis)
1065 {
1066     Environment env(gate, circuit_, &builder_);
1067     bool firstParam = skipThis ? 1 : 0;
1068     auto id = BuiltinsStubCSigns::ID::BigIntConstructor;
1069     if (!Uncheck()) {
1070         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam),
1071                                  builder_.IntPtr(static_cast<int64_t>(id)));
1072     }
1073     if (EnableTrace()) {
1074         AddTraceLogs(gate, id);
1075     }
1076 
1077     auto param = builder_.Undefined();
1078     if (argc > 0) {
1079         param = acc_.GetValueIn(gate, firstParam);
1080     }
1081 
1082     GateRef ret = builder_.BuildControlDependOp(circuit_->BigIntConstructor(), {param});
1083     ReplaceGateWithPendingException(gate, ret);
1084     return;
1085 }
1086 
TryInlineDateGetTime(GateRef gate,size_t argc,bool skipThis)1087 void NativeInlineLowering::TryInlineDateGetTime(GateRef gate, size_t argc, bool skipThis)
1088 {
1089     // Always shout be "this", we can't inline this function without instance of object
1090     if (!skipThis) {
1091         return;
1092     }
1093     Environment env(gate, circuit_, &builder_);
1094     // We are sure, that "this" is passed to this function, so always need to do +1
1095     bool firstParam = 1;
1096     if (!Uncheck()) {
1097         GateRef obj = acc_.GetValueIn(gate, 0);
1098         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam),
1099                                  builder_.IntPtr(static_cast<int64_t>(BuiltinsStubCSigns::ID::DateGetTime)), {obj});
1100     }
1101     if (EnableTrace()) {
1102         AddTraceLogs(gate, BuiltinsStubCSigns::ID::DateGetTime);
1103     }
1104     // Take object using "this"
1105     GateRef obj = acc_.GetValueIn(gate, 0);
1106     GateRef ret = builder_.BuildControlDependOp(circuit_->DateGetTime(), {obj});
1107     acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret);
1108 }
1109 
TryInlineObjectIs(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)1110 void NativeInlineLowering::TryInlineObjectIs(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis)
1111 {
1112     Environment env(gate, circuit_, &builder_);
1113     if (argc != 2) {  // 2: left and right
1114         return;
1115     }
1116 
1117     size_t firstParam = skipThis ? 1 : 0;
1118     if (!Uncheck()) {
1119         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam),
1120                                  builder_.IntPtr(static_cast<int64_t>(id)));
1121     }
1122 
1123     if (EnableTrace()) {
1124         AddTraceLogs(gate, id);
1125     }
1126 
1127     GateRef left = acc_.GetValueIn(gate, firstParam);
1128     GateRef right = acc_.GetValueIn(gate, firstParam + 1);
1129     GateRef ret = builder_.BuildControlDependOp(circuit_->ObjectIs(), { left, right });
1130     ReplaceGateWithPendingException(gate, ret);
1131 }
1132 
TryInlineObjectGetPrototypeOf(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)1133 void NativeInlineLowering::TryInlineObjectGetPrototypeOf(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id,
1134                                                          bool skipThis)
1135 {
1136     Environment env(gate, circuit_, &builder_);
1137     if (argc != 1) {
1138         return;
1139     }
1140 
1141     size_t firstParam = skipThis ? 1 : 0;
1142     if (!Uncheck()) {
1143         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam),
1144                                  builder_.IntPtr(static_cast<int64_t>(id)));
1145     }
1146 
1147     if (EnableTrace()) {
1148         AddTraceLogs(gate, id);
1149     }
1150 
1151     GateRef value = acc_.GetValueIn(gate, firstParam);
1152     GateRef ret = builder_.BuildControlDependOp(circuit_->ObjectGetPrototypeOf(), { value });
1153     ReplaceGateWithPendingException(gate, ret);
1154 }
1155 
TryInlineObjectGetProto(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)1156 void NativeInlineLowering::TryInlineObjectGetProto(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis)
1157 {
1158     if (!skipThis || argc != 0) {
1159         return;
1160     }
1161 
1162     Environment env(gate, circuit_, &builder_);
1163     if (!Uncheck()) {
1164         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, 1), builder_.IntPtr(static_cast<int64_t>(id)));  // 1: func
1165     }
1166 
1167     if (EnableTrace()) {
1168         AddTraceLogs(gate, id);
1169     }
1170 
1171     GateRef thisValue = acc_.GetValueIn(gate, 0);
1172     GateRef ret = builder_.BuildControlDependOp(circuit_->ObjectGetPrototypeOf(), { thisValue });
1173     ReplaceGateWithPendingException(gate, ret);
1174 }
1175 
TryInlineObjectCreate(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)1176 void NativeInlineLowering::TryInlineObjectCreate(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis)
1177 {
1178     Environment env(gate, circuit_, &builder_);
1179     if (argc != 1) {
1180         return;
1181     }
1182 
1183     size_t firstParam = skipThis ? 1 : 0;
1184     if (!Uncheck()) {
1185         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam),
1186                                  builder_.IntPtr(static_cast<int64_t>(id)));
1187     }
1188 
1189     if (EnableTrace()) {
1190         AddTraceLogs(gate, id);
1191     }
1192 
1193     GateRef proto = acc_.GetValueIn(gate, firstParam);
1194     GateRef ret = builder_.BuildControlDependOp(circuit_->ObjectCreate(), { proto });
1195     ReplaceGateWithPendingException(gate, ret);
1196 }
1197 
TryInlineObjectIsPrototypeOf(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)1198 void NativeInlineLowering::TryInlineObjectIsPrototypeOf(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id,
1199                                                         bool skipThis)
1200 {
1201     if (!skipThis || argc != 1) {
1202         return;
1203     }
1204 
1205     Environment env(gate, circuit_, &builder_);
1206     if (!Uncheck()) {
1207         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, 2), builder_.IntPtr(static_cast<int64_t>(id)));  // 2: func
1208     }
1209 
1210     if (EnableTrace()) {
1211         AddTraceLogs(gate, id);
1212     }
1213 
1214     GateRef thisValue = acc_.GetValueIn(gate, 0);
1215     GateRef value = acc_.GetValueIn(gate, 1);
1216     GateRef ret = builder_.BuildControlDependOp(circuit_->ObjectIsPrototypeOf(), {thisValue, value});
1217     ReplaceGateWithPendingException(gate, ret);
1218 }
1219 
TryInlineObjectHasOwnProperty(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)1220 void NativeInlineLowering::TryInlineObjectHasOwnProperty(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id,
1221                                                          bool skipThis)
1222 {
1223     if (!skipThis || argc != 1) {
1224         return;
1225     }
1226 
1227     Environment env(gate, circuit_, &builder_);
1228     if (!Uncheck()) {
1229         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, 2), builder_.IntPtr(static_cast<int64_t>(id)));  // 2: func
1230     }
1231 
1232     if (EnableTrace()) {
1233         AddTraceLogs(gate, id);
1234     }
1235 
1236     GateRef thisValue = acc_.GetValueIn(gate, 0);
1237     GateRef key = acc_.GetValueIn(gate, 1);
1238     GateRef ret = builder_.BuildControlDependOp(circuit_->ObjectHasOwnProperty(), { thisValue, key });
1239     ReplaceGateWithPendingException(gate, ret);
1240 }
1241 
TryInlineReflectGetPrototypeOf(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)1242 void NativeInlineLowering::TryInlineReflectGetPrototypeOf(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id,
1243                                                           bool skipThis)
1244 {
1245     Environment env(gate, circuit_, &builder_);
1246     if (argc != 1) {
1247         return;
1248     }
1249 
1250     size_t firstParam = skipThis ? 1 : 0;
1251     if (!Uncheck()) {
1252         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam),
1253                                  builder_.IntPtr(static_cast<int64_t>(id)));
1254     }
1255 
1256     if (EnableTrace()) {
1257         AddTraceLogs(gate, id);
1258     }
1259 
1260     GateRef value = acc_.GetValueIn(gate, firstParam);
1261     GateRef ret = builder_.BuildControlDependOp(circuit_->ReflectGetPrototypeOf(), { value });
1262     ReplaceGateWithPendingException(gate, ret);
1263 }
1264 
TryInlineReflectGet(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)1265 void NativeInlineLowering::TryInlineReflectGet(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis)
1266 {
1267     Environment env(gate, circuit_, &builder_);
1268     if (argc != 2) {  // 2: target and key, do not handle receiver argument scene
1269         return;
1270     }
1271 
1272     size_t firstParam = skipThis ? 1 : 0;
1273     GateRef key = acc_.GetValueIn(gate, firstParam + 1);
1274     if (!TypeInfoAccessor::IsTrustedStringType(compilationEnv_, circuit_, chunk_, acc_, key)) {
1275         return;
1276     }
1277 
1278     if (!Uncheck()) {
1279         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam),
1280                                  builder_.IntPtr(static_cast<int64_t>(id)));
1281     }
1282 
1283     if (EnableTrace()) {
1284         AddTraceLogs(gate, id);
1285     }
1286 
1287     GateRef target = acc_.GetValueIn(gate, firstParam);
1288     GateRef ret = builder_.BuildControlDependOp(circuit_->ReflectGet(), { target, key });
1289     ReplaceGateWithPendingException(gate, ret);
1290 }
1291 
TryInlineReflectHas(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)1292 void NativeInlineLowering::TryInlineReflectHas(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis)
1293 {
1294     Environment env(gate, circuit_, &builder_);
1295     if (argc != 2) {  // 2: target and key
1296         return;
1297     }
1298 
1299     size_t firstParam = skipThis ? 1 : 0;
1300     if (!Uncheck()) {
1301         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam),
1302                                  builder_.IntPtr(static_cast<int64_t>(id)));
1303     }
1304 
1305     if (EnableTrace()) {
1306         AddTraceLogs(gate, id);
1307     }
1308 
1309     GateRef target = acc_.GetValueIn(gate, firstParam);
1310     GateRef key = acc_.GetValueIn(gate, firstParam + 1);
1311     GateRef ret = builder_.BuildControlDependOp(circuit_->ReflectHas(), { target, key });
1312     ReplaceGateWithPendingException(gate, ret);
1313 }
1314 
TryInlineReflectConstruct(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)1315 void NativeInlineLowering::TryInlineReflectConstruct(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id,
1316                                                      bool skipThis)
1317 {
1318     Environment env(gate, circuit_, &builder_);
1319     if (argc != 2) {  // 2: optimize newtarget equal target
1320         return;
1321     }
1322 
1323     size_t firstParam = skipThis ? 1 : 0;
1324     GateRef target = acc_.GetValueIn(gate, firstParam);
1325     GateRef argumentsList = acc_.GetValueIn(gate, firstParam + 1);
1326 
1327     OpCode op = acc_.GetOpCode(argumentsList);
1328     if (op != OpCode::JS_BYTECODE) {
1329         return;
1330     }
1331 
1332     EcmaOpcode ecmaOpcode = acc_.GetByteCodeOpcode(argumentsList);
1333     // optimize empty array literal argumentsList
1334     if ((ecmaOpcode != EcmaOpcode::CREATEEMPTYARRAY_IMM8) && (ecmaOpcode != EcmaOpcode::CREATEEMPTYARRAY_IMM16)) {
1335         return;
1336     }
1337 
1338     if (!Uncheck()) {
1339         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam),
1340                                  builder_.IntPtr(static_cast<int64_t>(id)));
1341     }
1342 
1343     if (EnableTrace()) {
1344         AddTraceLogs(gate, id);
1345     }
1346 
1347     GateRef ret = builder_.BuildControlDependOp(circuit_->ReflectConstruct(), { target });
1348     ReplaceGateWithPendingException(gate, ret);
1349 }
1350 
TryInlineReflectApply(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)1351 void NativeInlineLowering::TryInlineReflectApply(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id,
1352                                                  bool skipThis)
1353 {
1354     Environment env(gate, circuit_, &builder_);
1355     if (argc != 3) {  // 3: target key and  argumentsList
1356         return;
1357     }
1358 
1359     size_t firstParam = skipThis ? 1 : 0;
1360     GateRef target = acc_.GetValueIn(gate, firstParam);
1361     GateRef thisValue = acc_.GetValueIn(gate, firstParam + 1);
1362     GateRef argumentsList = acc_.GetValueIn(gate, firstParam + 2);
1363 
1364     if (!Uncheck()) {
1365         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam),
1366                                  builder_.IntPtr(static_cast<int64_t>(id)));
1367     }
1368 
1369     if (EnableTrace()) {
1370         AddTraceLogs(gate, id);
1371     }
1372 
1373     GateRef ret = builder_.BuildControlDependOp(circuit_->ReflectApply(), { target, thisValue, argumentsList });
1374     ReplaceGateWithPendingException(gate, ret);
1375 }
1376 
TryInlineFunctionPrototypeApply(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)1377 void NativeInlineLowering::TryInlineFunctionPrototypeApply(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id,
1378                                                            bool skipThis)
1379 {
1380     Environment env(gate, circuit_, &builder_);
1381     if (!skipThis || argc == 0) {
1382         return;
1383     }
1384 
1385     if (!Uncheck()) {
1386         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + 1), builder_.IntPtr(static_cast<int64_t>(id)));
1387     }
1388 
1389     if (EnableTrace()) {
1390         AddTraceLogs(gate, id);
1391     }
1392 
1393     GateRef thisFunc = acc_.GetValueIn(gate, 0);
1394     GateRef thisArg = acc_.GetValueIn(gate, 1);
1395     GateRef argArray = (argc == 2) ? (acc_.GetValueIn(gate, 2)) : (builder_.UndefineConstant());
1396     GateRef ret = builder_.BuildControlDependOp(circuit_->FunctionPrototypeApply(), { thisFunc, thisArg, argArray });
1397     ReplaceGateWithPendingException(gate, ret);
1398 }
1399 
TryInlineFunctionPrototypeBind(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)1400 void NativeInlineLowering::TryInlineFunctionPrototypeBind(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id,
1401                                                           bool skipThis)
1402 {
1403     Environment env(gate, circuit_, &builder_);
1404     if (!skipThis || argc != 1) {
1405         return;
1406     }
1407 
1408     if (!Uncheck()) {
1409         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, 2), builder_.IntPtr(static_cast<int64_t>(id)));  // 2: func
1410     }
1411 
1412     if (EnableTrace()) {
1413         AddTraceLogs(gate, id);
1414     }
1415 
1416     GateRef target = acc_.GetValueIn(gate, 0);
1417     GateRef thisArg = acc_.GetValueIn(gate, 1);
1418     GateRef ret = builder_.BuildControlDependOp(circuit_->FunctionPrototypeBind(), { target, thisArg });
1419     ReplaceGateWithPendingException(gate, ret);
1420 }
1421 
TryInlineFunctionPrototypeCall(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)1422 void NativeInlineLowering::TryInlineFunctionPrototypeCall(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id,
1423                                                           bool skipThis)
1424 {
1425     Environment env(gate, circuit_, &builder_);
1426     if (!skipThis || argc == 0) {
1427         return;
1428     }
1429 
1430     if (!Uncheck()) {
1431         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + 1), builder_.IntPtr(static_cast<int64_t>(id)));
1432     }
1433 
1434     if (EnableTrace()) {
1435         AddTraceLogs(gate, id);
1436     }
1437 
1438     std::vector<GateRef> args(argc + 1);  // 1: thisFunc
1439     for (size_t i = 0; i <= argc; ++i) {
1440         args[i] = acc_.GetValueIn(gate, i);
1441     }
1442     GateRef ret = builder_.BuildControlDependOp(circuit_->FunctionPrototypeCall(argc + 1), args);
1443     ReplaceGateWithPendingException(gate, ret);
1444 }
1445 
TryInlineFunctionPrototypeHasInstance(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)1446 void NativeInlineLowering::TryInlineFunctionPrototypeHasInstance(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id,
1447                                                                  bool skipThis)
1448 {
1449     Environment env(gate, circuit_, &builder_);
1450     if (!skipThis || argc != 1) {
1451         return;
1452     }
1453 
1454     if (!Uncheck()) {
1455         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, 2), builder_.IntPtr(static_cast<int64_t>(id)));  // 2: func
1456     }
1457 
1458     if (EnableTrace()) {
1459         AddTraceLogs(gate, id);
1460     }
1461 
1462     GateRef function = acc_.GetValueIn(gate, 0);
1463     GateRef value = acc_.GetValueIn(gate, 1);
1464     GateRef ret = builder_.OrdinaryHasInstance(value, function);
1465     ReplaceGateWithPendingException(gate, ret);
1466 }
1467 
1468 // indexOf, lastIndexOf, includes
TryInlineIndexOfIncludes(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)1469 void NativeInlineLowering::TryInlineIndexOfIncludes(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis)
1470 {
1471     if (!skipThis) {
1472         return;
1473     }
1474     if (argc == 0) {
1475         return;
1476     }
1477     Environment env(gate, circuit_, &builder_);
1478     GateRef thisArray = acc_.GetValueIn(gate, 0);
1479     GateRef targetElement = acc_.GetValueIn(gate, 1);
1480     ElementsKind kind = acc_.TryGetArrayElementsKind(thisArray);
1481     if (!Uncheck()) {
1482         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + 1), builder_.IntPtr(static_cast<int64_t>(id)));
1483     }
1484     builder_.BuiltinPrototypeHClassCheck(thisArray, BuiltinTypeId::ARRAY, kind, false);
1485     builder_.StableArrayCheck(thisArray, kind, ArrayMetaDataAccessor::Mode::CALL_BUILTIN_METHOD);
1486     builder_.ElementsKindCheck(thisArray, kind, ArrayMetaDataAccessor::Mode::CALL_BUILTIN_METHOD);
1487     GateRef ret = Circuit::NullGate();
1488     GateRef elements = builder_.GetElementsArray(thisArray);
1489     GateRef thisLen = builder_.GetLengthOfJSArray(thisArray);
1490     GateRef callID = builder_.Int32(static_cast<int32_t>(id));
1491     GateRef arrayKind = builder_.Int32(Elements::ToUint(kind));
1492     if (argc == 1) {
1493         GateRef defaultFromIndex = (id == BuiltinsStubCSigns::ID::ArrayLastIndexOf)
1494             ? builder_.Int64Sub(builder_.ZExtInt32ToInt64(thisLen), builder_.Int64(1))
1495             : builder_.Int64(0);
1496         ret = builder_.ArrayIncludesIndexOf(elements, targetElement, defaultFromIndex, thisLen, callID, arrayKind);
1497     } else {
1498         GateRef fromIndexHandler = acc_.GetValueIn(gate, 2);
1499         builder_.DeoptCheck(builder_.TaggedIsNumber(fromIndexHandler), acc_.GetFrameState(gate),
1500                             DeoptType::INDEXNOTINT);
1501         GateRef fromIndex = BuiltinsArrayStubBuilder(&env).MakeFromIndex(
1502             fromIndexHandler, thisLen,
1503             (id == BuiltinsStubCSigns::ID::ArrayLastIndexOf));
1504         ret = builder_.ArrayIncludesIndexOf(elements, targetElement, fromIndex, thisLen, callID, arrayKind);
1505     }
1506     if (EnableTrace()) {
1507         AddTraceLogs(gate, id);
1508     }
1509     acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret);
1510 }
1511 
TryInlineArrayIterator(GateRef gate,BuiltinsStubCSigns::ID id,bool skipThis)1512 void NativeInlineLowering::TryInlineArrayIterator(GateRef gate, BuiltinsStubCSigns::ID id, bool skipThis)
1513 {
1514     if (!skipThis) {
1515         return;
1516     }
1517     CallThis0TypeInfoAccessor tacc(compilationEnv_, circuit_, gate);
1518     Environment env(gate, circuit_, &builder_);
1519 
1520     if (!Uncheck()) {
1521         builder_.CallTargetCheck(gate, tacc.GetFunc(), builder_.IntPtr(static_cast<int64_t>(id)), {tacc.GetThisObj()});
1522     }
1523     GateRef thisObj = acc_.GetValueIn(gate, 0);
1524     builder_.EcmaObjectCheck(thisObj);
1525     if (EnableTrace()) {
1526         AddTraceLogs(gate, id);
1527     }
1528     GateRef CallIDRef = builder_.Int32(static_cast<int32_t>(id));
1529     GateRef ret = builder_.ArrayIteratorBuiltin(thisObj, CallIDRef);
1530     acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret);
1531 }
1532 
TryInlineArrayForEach(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)1533 void NativeInlineLowering::TryInlineArrayForEach(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis)
1534 {
1535     if (argc == 0) { // 0: Must have a callBackFn
1536         return;
1537     }
1538     if (!skipThis) {
1539         return;
1540     }
1541     Environment env(gate, circuit_, &builder_);
1542     auto pcOffset = acc_.TryGetPcOffset(gate);
1543     GateRef ret = Circuit::NullGate();
1544     GateRef thisValue = acc_.GetValueIn(gate, 0);
1545     ElementsKind kind = acc_.TryGetArrayElementsKind(thisValue);
1546     if (Elements::IsHole(kind)) {
1547         return;
1548     }
1549     if (!Uncheck()) {
1550         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + 1), builder_.IntPtr(static_cast<int64_t>(id)));
1551     }
1552     builder_.BuiltinPrototypeHClassCheck(thisValue, BuiltinTypeId::ARRAY, kind, false);
1553     builder_.StableArrayCheck(thisValue, kind, ArrayMetaDataAccessor::Mode::CALL_BUILTIN_METHOD);
1554     builder_.ElementsKindCheck(thisValue, kind, ArrayMetaDataAccessor::Mode::CALL_BUILTIN_METHOD);
1555     GateRef callBackFn = acc_.GetValueIn(gate, 1);
1556     builder_.IsCallableCheck(callBackFn);
1557     if (EnableTrace()) {
1558         AddTraceLogs(gate, id);
1559     }
1560     if (argc == 1) {
1561         ret = builder_.ArrayForEach(thisValue, callBackFn, builder_.UndefineConstant(), pcOffset);
1562     } else {
1563         ret = builder_.ArrayForEach(thisValue, callBackFn, acc_.GetValueIn(gate, 2), pcOffset); // 2:provide using This
1564     }
1565     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), ret);
1566 }
1567 
TryInlineArrayFindOrFindIndex(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)1568 void NativeInlineLowering::TryInlineArrayFindOrFindIndex(GateRef gate,
1569                                                          size_t argc,
1570                                                          BuiltinsStubCSigns::ID id,
1571                                                          bool skipThis)
1572 {
1573     if (argc == 0) { // 0: Must have a callBackFn
1574         return;
1575     }
1576     if (!skipThis) {
1577         return;
1578     }
1579     Environment env(gate, circuit_, &builder_);
1580     GateRef thisValue = acc_.GetValueIn(gate, 0);
1581     ElementsKind kind = acc_.TryGetArrayElementsKind(thisValue);
1582     if (Elements::IsHole(kind)) {
1583         return;
1584     }
1585     if (!Uncheck()) {
1586         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + 1), builder_.IntPtr(static_cast<int64_t>(id)));
1587     }
1588     uint32_t pcOffset = acc_.TryGetPcOffset(gate);
1589     GateRef ret = Circuit::NullGate();
1590 
1591     builder_.BuiltinPrototypeHClassCheck(thisValue, BuiltinTypeId::ARRAY, kind, false);
1592     builder_.StableArrayCheck(thisValue, kind, ArrayMetaDataAccessor::Mode::CALL_BUILTIN_METHOD);
1593     builder_.ElementsKindCheck(thisValue, kind, ArrayMetaDataAccessor::Mode::CALL_BUILTIN_METHOD);
1594     GateRef callBackFn = acc_.GetValueIn(gate, 1);
1595     builder_.IsCallableCheck(callBackFn);
1596     if (EnableTrace()) {
1597         AddTraceLogs(gate, id);
1598     }
1599     GateRef callIDRef = builder_.Int32(static_cast<int32_t>(id));
1600 
1601     if (argc == 1) {
1602         ret = builder_.ArrayFindOrFindIndex(thisValue, callBackFn, builder_.UndefineConstant(), callIDRef, pcOffset);
1603     } else {
1604         ret = builder_.ArrayFindOrFindIndex(
1605             thisValue, callBackFn, acc_.GetValueIn(gate, 2), callIDRef, pcOffset); // 2:provide using This
1606     }
1607     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), ret);
1608 }
1609 
TryInlineArrayFilter(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)1610 void NativeInlineLowering::TryInlineArrayFilter(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis)
1611 {
1612     if (argc == 0) {
1613         return;
1614     }
1615     if (!skipThis) {
1616         return;
1617     }
1618     Environment env(gate, circuit_, &builder_);
1619     GateRef thisValue = acc_.GetValueIn(gate, 0);
1620     ElementsKind kind = acc_.TryGetArrayElementsKind(thisValue);
1621     if (Elements::IsHole(kind)) {
1622         return;
1623     }
1624     if (!Uncheck()) {
1625         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + 1), builder_.IntPtr(static_cast<int64_t>(id)));
1626     }
1627     builder_.BuiltinPrototypeHClassCheck(thisValue, BuiltinTypeId::ARRAY, kind, false);
1628     builder_.StableArrayCheck(thisValue, kind, ArrayMetaDataAccessor::Mode::CALL_BUILTIN_METHOD);
1629     builder_.ElementsKindCheck(thisValue, kind, ArrayMetaDataAccessor::Mode::CALL_BUILTIN_METHOD);
1630     GateRef callBackFn = acc_.GetValueIn(gate, 1);
1631     builder_.IsCallableCheck(callBackFn);
1632     if (EnableTrace()) {
1633         AddTraceLogs(gate, id);
1634     }
1635     uint32_t pcOffset = acc_.TryGetPcOffset(gate);
1636     GateRef frameState = acc_.GetFrameState(gate);
1637     GateRef ret = Circuit::NullGate();
1638     if (argc == 1) {
1639         ret = builder_.ArrayFilter(thisValue, callBackFn, builder_.UndefineConstant(), frameState, pcOffset);
1640     } else {
1641         ret = builder_.ArrayFilter(
1642             thisValue, callBackFn, acc_.GetValueIn(gate, 2), frameState, pcOffset); // 2: provide usingThis
1643     }
1644     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), ret);
1645 }
1646 
TryInlineArrayMap(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)1647 void NativeInlineLowering::TryInlineArrayMap(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis)
1648 {
1649     if (argc == 0) {
1650         return;
1651     }
1652     if (!skipThis) {
1653         return;
1654     }
1655     Environment env(gate, circuit_, &builder_);
1656     GateRef thisValue = acc_.GetValueIn(gate, 0);
1657     ElementsKind kind = acc_.TryGetArrayElementsKind(thisValue);
1658     if (Elements::IsHole(kind)) {
1659         return;
1660     }
1661     if (!Uncheck()) {
1662         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + 1), builder_.IntPtr(static_cast<int64_t>(id)));
1663     }
1664     builder_.BuiltinPrototypeHClassCheck(thisValue, BuiltinTypeId::ARRAY, kind, false);
1665     builder_.StableArrayCheck(thisValue, kind, ArrayMetaDataAccessor::Mode::CALL_BUILTIN_METHOD);
1666     builder_.ElementsKindCheck(thisValue, kind, ArrayMetaDataAccessor::Mode::CALL_BUILTIN_METHOD);
1667     GateRef callBackFn = acc_.GetValueIn(gate, 1);
1668     builder_.IsCallableCheck(callBackFn);
1669     if (EnableTrace()) {
1670         AddTraceLogs(gate, id);
1671     }
1672     uint32_t pcOffset = acc_.TryGetPcOffset(gate);
1673     GateRef frameState = acc_.GetFrameState(gate);
1674     GateRef ret = Circuit::NullGate();
1675     if (argc == 1) {
1676         ret = builder_.ArrayMap(thisValue, callBackFn, builder_.UndefineConstant(), frameState, pcOffset);
1677     } else {
1678         ret = builder_.ArrayMap(
1679             thisValue, callBackFn, acc_.GetValueIn(gate, 2), frameState, pcOffset); //2: provide usingThis
1680     }
1681     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), ret);
1682 }
1683 
TryInlineArraySome(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)1684 void NativeInlineLowering::TryInlineArraySome(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis)
1685 {
1686     if (argc == 0) {
1687         return;
1688     }
1689     if (!skipThis) {
1690         return;
1691     }
1692     Environment env(gate, circuit_, &builder_);
1693     GateRef thisValue = acc_.GetValueIn(gate, 0);
1694     ElementsKind kind = acc_.TryGetArrayElementsKind(thisValue);
1695     if (Elements::IsHole(kind)) {
1696         return;
1697     }
1698     if (!Uncheck()) {
1699         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + 1), builder_.IntPtr(static_cast<int64_t>(id)));
1700     }
1701     builder_.BuiltinPrototypeHClassCheck(thisValue, BuiltinTypeId::ARRAY, kind, false);
1702     builder_.StableArrayCheck(thisValue, kind, ArrayMetaDataAccessor::Mode::CALL_BUILTIN_METHOD);
1703     builder_.ElementsKindCheck(thisValue, kind, ArrayMetaDataAccessor::Mode::CALL_BUILTIN_METHOD);
1704     GateRef callBackFn = acc_.GetValueIn(gate, 1);
1705     builder_.IsCallableCheck(callBackFn);
1706     if (EnableTrace()) {
1707         AddTraceLogs(gate, id);
1708     }
1709     uint32_t pcOffset = acc_.TryGetPcOffset(gate);
1710     GateRef ret = Circuit::NullGate();
1711     if (argc == 1) {
1712         ret = builder_.ArraySome(thisValue, callBackFn, builder_.UndefineConstant(), pcOffset);
1713     } else {
1714         ret = builder_.ArraySome(thisValue, callBackFn, acc_.GetValueIn(gate, 2), pcOffset); //2: provide usingThis
1715     }
1716     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), ret);
1717 }
1718 
TryInlineArrayEvery(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)1719 void NativeInlineLowering::TryInlineArrayEvery(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis)
1720 {
1721     if (argc == 0) {
1722         return;
1723     }
1724     if (!skipThis) {
1725         return;
1726     }
1727     Environment env(gate, circuit_, &builder_);
1728     GateRef thisValue = acc_.GetValueIn(gate, 0);
1729     ElementsKind kind = acc_.TryGetArrayElementsKind(thisValue);
1730     if (Elements::IsHole(kind)) {
1731         return;
1732     }
1733     if (!Uncheck()) {
1734         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + 1), builder_.IntPtr(static_cast<int64_t>(id)));
1735     }
1736     builder_.BuiltinPrototypeHClassCheck(thisValue, BuiltinTypeId::ARRAY, kind, false);
1737     builder_.StableArrayCheck(thisValue, kind, ArrayMetaDataAccessor::Mode::CALL_BUILTIN_METHOD);
1738     builder_.ElementsKindCheck(thisValue, kind, ArrayMetaDataAccessor::Mode::CALL_BUILTIN_METHOD);
1739     GateRef callBackFn = acc_.GetValueIn(gate, 1);
1740     builder_.IsCallableCheck(callBackFn);
1741     if (EnableTrace()) {
1742         AddTraceLogs(gate, id);
1743     }
1744     uint32_t pcOffset = acc_.TryGetPcOffset(gate);
1745     GateRef ret = Circuit::NullGate();
1746     if (argc == 1) {
1747         ret = builder_.ArrayEvery(thisValue, callBackFn, builder_.UndefineConstant(), pcOffset);
1748     } else {
1749         ret = builder_.ArrayEvery(thisValue, callBackFn, acc_.GetValueIn(gate, 2), pcOffset); //2: provide usingThis
1750     }
1751     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), ret);
1752 }
1753 
TryInlineArrayPop(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)1754 void NativeInlineLowering::TryInlineArrayPop(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis)
1755 {
1756     if (!skipThis) {
1757         return;
1758     }
1759     Environment env(gate, circuit_, &builder_);
1760     if (!Uncheck()) {
1761         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + 1), builder_.IntPtr(static_cast<int64_t>(id)));
1762     }
1763     GateRef thisValue = acc_.GetValueIn(gate, 0);
1764     ElementsKind kind = acc_.TryGetArrayElementsKind(thisValue);
1765     builder_.BuiltinPrototypeHClassCheck(thisValue, BuiltinTypeId::ARRAY, kind, false);
1766     builder_.StableArrayCheck(thisValue, kind, ArrayMetaDataAccessor::Mode::CALL_BUILTIN_METHOD);
1767     builder_.ElementsKindCheck(thisValue, kind, ArrayMetaDataAccessor::Mode::CALL_BUILTIN_METHOD);
1768     if (EnableTrace()) {
1769         AddTraceLogs(gate, id);
1770     }
1771     GateRef ret = builder_.ArrayPop(thisValue, acc_.GetFrameState(gate));
1772     ReplaceGateWithPendingException(gate, ret);
1773 }
1774 
TryInlineArrayPush(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)1775 void NativeInlineLowering::TryInlineArrayPush(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis)
1776 {
1777     // To ensure that the Inline code is as small as possible,
1778     // FastPath only processes the case when the number of elements to push equals 1
1779     // and mutantArray is not enabled.
1780     if (!skipThis || argc != 1 || enableMutantArray_) {
1781         return;
1782     }
1783     Environment env(gate, circuit_, &builder_);
1784     if (!Uncheck()) {
1785         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + 1), builder_.IntPtr(static_cast<int64_t>(id)));
1786     }
1787     GateRef thisValue = acc_.GetValueIn(gate, 0);
1788     ElementsKind kind = acc_.TryGetArrayElementsKind(thisValue);
1789     if (EnableTrace()) {
1790         AddTraceLogs(gate, id);
1791     }
1792     builder_.StableArrayCheck(thisValue, kind, ArrayMetaDataAccessor::Mode::CALL_BUILTIN_METHOD);
1793     builder_.BuiltinPrototypeHClassCheck(thisValue, BuiltinTypeId::ARRAY, kind, false);
1794     GateRef ret = builder_.ArrayPush(thisValue, acc_.GetValueIn(gate, 1));
1795     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), ret);
1796 }
1797 
1798 
TryInlineArraySlice(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)1799 void NativeInlineLowering::TryInlineArraySlice(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis)
1800 {
1801     if (!skipThis) {
1802         return;
1803     }
1804     Environment env(gate, circuit_, &builder_);
1805     GateRef thisValue = acc_.GetValueIn(gate, 0);
1806     ElementsKind kind = acc_.TryGetArrayElementsKind(thisValue);
1807     builder_.BuiltinPrototypeHClassCheck(thisValue, BuiltinTypeId::ARRAY, kind, false);
1808     builder_.StableArrayCheck(thisValue, kind, ArrayMetaDataAccessor::Mode::CALL_BUILTIN_METHOD);
1809     builder_.ElementsKindCheck(thisValue, kind, ArrayMetaDataAccessor::Mode::CALL_BUILTIN_METHOD);
1810     GateRef frameState = acc_.GetFrameState(gate);
1811     if (!Uncheck()) {
1812         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + 1), builder_.IntPtr(static_cast<int64_t>(id)));
1813     }
1814     GateRef ret = Circuit::NullGate();
1815     if (argc == 0) {
1816         ret = builder_.ArraySlice(thisValue, builder_.UndefineConstant(), builder_.UndefineConstant(), frameState);
1817     } else if (argc == 1) {
1818         GateRef startIndex = acc_.GetValueIn(gate, 1);
1819         builder_.DeoptCheck(builder_.TaggedIsInt(startIndex), acc_.GetFrameState(gate), DeoptType::INDEXNOTINT);
1820         ret = builder_.ArraySlice(thisValue, startIndex, builder_.UndefineConstant(), frameState);
1821     } else {
1822         GateRef startIndex = acc_.GetValueIn(gate, 1);
1823         GateRef endIndex = acc_.GetValueIn(gate, 2);
1824         builder_.DeoptCheck(builder_.TaggedIsInt(startIndex), acc_.GetFrameState(gate), DeoptType::INDEXNOTINT);
1825         builder_.DeoptCheck(builder_.TaggedIsInt(endIndex), acc_.GetFrameState(gate), DeoptType::INDEXNOTINT);
1826         ret = builder_.ArraySlice(thisValue, startIndex, endIndex, frameState);
1827     }
1828     if (EnableTrace()) {
1829         AddTraceLogs(gate, id);
1830     }
1831     acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret);
1832 }
1833 
TryInlineArraySort(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)1834 void NativeInlineLowering::TryInlineArraySort(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis)
1835 {
1836     if (!skipThis) {
1837         return;
1838     }
1839     if (argc > 1) {
1840         return;
1841     }
1842     Environment env(gate, circuit_, &builder_);
1843     if (argc == 1) {
1844         GateRef callBackFn = acc_.GetValueIn(gate, 1);
1845         auto fnType = acc_.GetGateType(callBackFn);
1846         if (!fnType.IsUndefinedType()) {
1847             return;
1848         }
1849     }
1850     GateRef thisValue = acc_.GetValueIn(gate, 0);
1851     ElementsKind kind = acc_.TryGetArrayElementsKind(thisValue);
1852     if (Elements::IsHole(kind)) {
1853         return;
1854     }
1855     if (!Uncheck()) {
1856         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + 1), builder_.IntPtr(static_cast<int64_t>(id)));
1857     }
1858     GateRef ret = Circuit::NullGate();
1859 
1860     builder_.BuiltinPrototypeHClassCheck(thisValue, BuiltinTypeId::ARRAY, kind, false);
1861     builder_.StableArrayCheck(thisValue, kind, ArrayMetaDataAccessor::Mode::CALL_BUILTIN_METHOD);
1862     builder_.ElementsKindCheck(thisValue, kind, ArrayMetaDataAccessor::Mode::CALL_BUILTIN_METHOD);
1863     ret = builder_.ArraySort(thisValue, builder_.UndefineConstant());
1864     acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret);
1865 }
1866 
1867 }  // namespace panda::ecmascript
1868