• 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                 TryInlineArraySlice(gate, argc, id, skipThis);
358                 break;
359             default:
360                 break;
361         }
362     }
363 
364     if (EnableLog()) {
365         LOG_COMPILER(INFO) << " ";
366         LOG_COMPILER(INFO) << "\033[34m" << "================="
367                            << " After Native Inline Lowering "
368                            << "[" << GetMethodName() << "] "
369                            << "=================" << "\033[0m";
370         circuit_->PrintAllGatesWithBytecode();
371         LOG_COMPILER(INFO) << "\033[34m" << "=========================== End ===========================" << "\033[0m";
372     }
373 }
374 
AddTraceLogs(GateRef gate,BuiltinsStubCSigns::ID id)375 void NativeInlineLowering::AddTraceLogs(GateRef gate, BuiltinsStubCSigns::ID id)
376 {
377     size_t index = RTSTUB_ID(AotInlineBuiltinTrace);
378 
379     GateRef frameState = acc_.GetFrameState(gate);
380     GateRef frameArgs = acc_.GetValueIn(frameState);
381     GateRef callerFunc = acc_.GetValueIn(frameArgs, 0);
382     std::vector<GateRef> args{callerFunc, builder_.Int32(id)};
383 
384     builder_.CallRuntime(glue_, index, Gate::InvalidGateRef, args, gate);
385 }
386 
TryInlineStringFromCharCode(GateRef gate,size_t argc,bool skipThis)387 void NativeInlineLowering::TryInlineStringFromCharCode(GateRef gate, size_t argc, bool skipThis)
388 {
389     if (!skipThis) {
390         return;
391     }
392     if (argc != 1) {
393         return;
394     }
395     CallThis1TypeInfoAccessor tacc(compilationEnv_, circuit_, gate);
396     Environment env(gate, circuit_, &builder_);
397     if (!Uncheck()) {
398         builder_.CallTargetCheck(gate, tacc.GetFunc(),
399                                  builder_.IntPtr(static_cast<int64_t>(BuiltinsStubCSigns::ID::StringFromCharCode)),
400                                  {tacc.GetArg0()});
401     }
402 
403     if (EnableTrace()) {
404         AddTraceLogs(gate, BuiltinsStubCSigns::ID::StringFromCharCode);
405     }
406 
407     GateRef ret = builder_.StringFromSingleCharCode(tacc.GetArg0());
408     ReplaceGateWithPendingException(gate, ret);
409 }
410 
TryInlineStringCharCodeAt(GateRef gate,size_t argc,bool skipThis)411 void NativeInlineLowering::TryInlineStringCharCodeAt(GateRef gate, size_t argc, bool skipThis)
412 {
413     // only inline number input, string input will be deoptimized
414     if (!skipThis) {
415         return;
416     }
417 
418     GateRef thisValue = acc_.GetValueIn(gate, 0);
419     GateRef posTag = (argc == 0) ? (builder_.Int32(0)) : (acc_.GetValueIn(gate, 1));
420     GateRef func = acc_.GetValueIn(gate, argc + 1);
421     Environment env(gate, circuit_, &builder_);
422     if (!Uncheck()) {
423         builder_.CallTargetCheck(gate, func,
424                                  builder_.IntPtr(static_cast<int64_t>(BuiltinsStubCSigns::ID::StringCharCodeAt)),
425                                  {thisValue});
426         builder_.EcmaStringCheck(thisValue);
427     }
428 
429     if (EnableTrace()) {
430         AddTraceLogs(gate, BuiltinsStubCSigns::ID::StringCharCodeAt);
431     }
432 
433     GateRef ret = builder_.StringCharCodeAt(thisValue, posTag);
434     acc_.ReplaceHirAndReplaceDeadIfException(gate, builder_.GetStateDepend(), ret);
435 }
436 
TryInlineStringSubstring(GateRef gate,size_t argc,bool skipThis)437 void NativeInlineLowering::TryInlineStringSubstring(GateRef gate, size_t argc, bool skipThis)
438 {
439     if (!skipThis) {
440         return;
441     }
442     if (argc != 1 && argc != 2) { // only optimize one or two parameters scene
443         return;
444     }
445     Environment env(gate, circuit_, &builder_);
446     GateRef ret = Circuit::NullGate();
447     if (argc == 1) {
448         CallThis1TypeInfoAccessor tacc(compilationEnv_, circuit_, gate);
449         GateRef thisValue = acc_.GetValueIn(gate, 0);
450         GateRef startTag = tacc.GetArg0();
451         GateRef endTag = builder_.GetLengthFromString(thisValue);
452         if (!Uncheck()) {
453             builder_.CallTargetCheck(gate, tacc.GetFunc(),
454                                      builder_.IntPtr(static_cast<int64_t>(BuiltinsStubCSigns::ID::StringSubstring)),
455                                      {tacc.GetArg0()});
456             builder_.EcmaStringCheck(thisValue);
457             auto param_check = builder_.TaggedIsNumber(startTag);
458             builder_.DeoptCheck(param_check, acc_.GetFrameState(gate), DeoptType::BUILTIN_INLINING_TYPE_GUARD);
459         }
460         ret = builder_.StringSubstring(thisValue, startTag, endTag);
461     } else {
462         GateRef thisValue = acc_.GetValueIn(gate, 0);
463         GateRef startTag = acc_.GetValueIn(gate, 1);
464         GateRef endTag = acc_.GetValueIn(gate, 2);
465         GateRef func = acc_.GetValueIn(gate, 3);
466         if (!Uncheck()) {
467             builder_.CallTargetCheck(gate, func,
468                                      builder_.IntPtr(static_cast<int64_t>(BuiltinsStubCSigns::ID::StringSubstring)));
469             builder_.EcmaStringCheck(thisValue);
470             auto param_check = LogicAndBuilder(&env).And(builder_.TaggedIsNumber(startTag))
471                 .And(builder_.TaggedIsNumber(endTag)).Done();
472             builder_.DeoptCheck(param_check, acc_.GetFrameState(gate), DeoptType::BUILTIN_INLINING_TYPE_GUARD);
473         }
474         ret = builder_.StringSubstring(thisValue, startTag, endTag);
475     }
476     acc_.ReplaceHirAndReplaceDeadIfException(gate, builder_.GetStateDepend(), ret);
477 }
478 
TryInlineStringSubStr(GateRef gate,size_t argc,bool skipThis)479 void NativeInlineLowering::TryInlineStringSubStr(GateRef gate, size_t argc, bool skipThis)
480 {
481     if (!skipThis) {
482         return;
483     }
484     if (argc != 1 && argc != 2) { // only optimize one or two parameters scene
485         return;
486     }
487     Environment env(gate, circuit_, &builder_);
488     GateRef ret = Circuit::NullGate();
489     if (argc == 1) {
490         CallThis1TypeInfoAccessor tacc(compilationEnv_, circuit_, gate);
491         GateRef thisValue = acc_.GetValueIn(gate, 0);
492         GateRef intStart = tacc.GetArg0();
493         GateRef lengthTag = builder_.Int32(INT_MAX);
494         if (!Uncheck()) {
495             builder_.CallTargetCheck(gate, tacc.GetFunc(),
496                                      builder_.IntPtr(static_cast<int64_t>(BuiltinsStubCSigns::ID::StringSubStr)),
497                                      {tacc.GetArg0()});
498             builder_.EcmaStringCheck(thisValue);
499             auto param_check = builder_.TaggedIsNumber(intStart);
500             builder_.DeoptCheck(param_check, acc_.GetFrameState(gate), DeoptType::BUILTIN_INLINING_TYPE_GUARD);
501         }
502         ret = builder_.StringSubStr(thisValue, intStart, lengthTag);
503     } else {
504         GateRef thisValue = acc_.GetValueIn(gate, 0);
505         GateRef intStart = acc_.GetValueIn(gate, 1);
506         GateRef lengthTag = acc_.GetValueIn(gate, 2);
507         GateRef func = acc_.GetValueIn(gate, 3);  //acc
508         if (!Uncheck()) {
509             builder_.CallTargetCheck(gate, func,
510                                      builder_.IntPtr(static_cast<int64_t>(BuiltinsStubCSigns::ID::StringSubStr)));
511             builder_.EcmaStringCheck(thisValue);
512             auto param_check = LogicAndBuilder(&env).And(builder_.TaggedIsNumber(intStart))
513                 .And(builder_.TaggedIsNumber(lengthTag)).Done();
514             builder_.DeoptCheck(param_check, acc_.GetFrameState(gate), DeoptType::BUILTIN_INLINING_TYPE_GUARD);
515         }
516         ret = builder_.StringSubStr(thisValue, intStart, lengthTag);
517     }
518     acc_.ReplaceHirAndReplaceDeadIfException(gate, builder_.GetStateDepend(), ret);
519 }
520 
TryInlineStringSlice(GateRef gate,size_t argc,bool skipThis)521 void NativeInlineLowering::TryInlineStringSlice(GateRef gate, size_t argc, bool skipThis)
522 {
523     if (!skipThis) {
524         return;
525     }
526     if (argc != 1 && argc != 2) { // only optimize one or two parameters scene
527         return;
528     }
529     Environment env(gate, circuit_, &builder_);
530     GateRef ret = Circuit::NullGate();
531     if (argc == 1) {
532         CallThis1TypeInfoAccessor tacc(compilationEnv_, circuit_, gate);
533         GateRef thisValue = acc_.GetValueIn(gate, 0);
534         GateRef startTag = tacc.GetArg0();
535         GateRef endTag = builder_.GetLengthFromString(thisValue);
536         if (!Uncheck()) {
537             builder_.CallTargetCheck(gate, tacc.GetFunc(),
538                                      builder_.IntPtr(static_cast<int64_t>(BuiltinsStubCSigns::ID::StringSlice)),
539                                      {tacc.GetArg0()});
540             builder_.EcmaStringCheck(thisValue);
541             auto param_check = builder_.TaggedIsNumber(startTag);
542             builder_.DeoptCheck(param_check, acc_.GetFrameState(gate), DeoptType::BUILTIN_INLINING_TYPE_GUARD);
543         }
544         ret = builder_.StringSlice(thisValue, startTag, endTag);
545     } else {
546         GateRef thisValue = acc_.GetValueIn(gate, 0);
547         GateRef startTag = acc_.GetValueIn(gate, 1);
548         GateRef endTag = acc_.GetValueIn(gate, 2);
549         GateRef func = acc_.GetValueIn(gate, 3);
550         if (!Uncheck()) {
551             builder_.CallTargetCheck(gate, func,
552                                      builder_.IntPtr(static_cast<int64_t>(BuiltinsStubCSigns::ID::StringSlice)));
553             builder_.EcmaStringCheck(thisValue);
554             auto param_check = LogicAndBuilder(&env).And(builder_.TaggedIsNumber(startTag))
555                 .And(builder_.TaggedIsNumber(endTag)).Done();
556             builder_.DeoptCheck(param_check, acc_.GetFrameState(gate), DeoptType::BUILTIN_INLINING_TYPE_GUARD);
557         }
558         ret = builder_.StringSlice(thisValue, startTag, endTag);
559     }
560     acc_.ReplaceHirAndReplaceDeadIfException(gate, builder_.GetStateDepend(), ret);
561 }
562 
TryInlineNumberIsFinite(GateRef gate,size_t argc,bool skipThis)563 void NativeInlineLowering::TryInlineNumberIsFinite(GateRef gate, size_t argc, bool skipThis)
564 {
565     if (!skipThis) {
566         return;
567     }
568     if (argc != 1) {
569         return;
570     }
571     CallThis1TypeInfoAccessor tacc(compilationEnv_, circuit_, gate);
572     Environment env(gate, circuit_, &builder_);
573     if (!Uncheck()) {
574         builder_.CallTargetCheck(gate, tacc.GetFunc(),
575                                  builder_.IntPtr(static_cast<int64_t>(BuiltinsStubCSigns::ID::NumberIsFinite)));
576     }
577     GateRef ret = builder_.NumberIsFinite(tacc.GetArg0());
578     acc_.ReplaceHirAndReplaceDeadIfException(gate, builder_.GetStateDepend(), ret);
579 }
580 
TryInlineNumberIsInteger(GateRef gate,size_t argc,bool skipThis)581 void NativeInlineLowering::TryInlineNumberIsInteger(GateRef gate, size_t argc, bool skipThis)
582 {
583     if (!skipThis) {
584         return;
585     }
586     if (argc != 1) {
587         return;
588     }
589     CallThis1TypeInfoAccessor tacc(compilationEnv_, circuit_, gate);
590     Environment env(gate, circuit_, &builder_);
591     auto id = BuiltinsStubCSigns::ID::NumberIsInteger;
592     if (!Uncheck()) {
593         builder_.CallTargetCheck(gate, tacc.GetFunc(),
594                                  builder_.IntPtr(static_cast<int64_t>(id)));
595     }
596     if (EnableTrace()) {
597         AddTraceLogs(gate, id);
598     }
599     GateRef ret = builder_.NumberIsInteger(tacc.GetArg0());
600     acc_.ReplaceHirAndReplaceDeadIfException(gate, builder_.GetStateDepend(), ret);
601 }
602 
TryInlineNumberIsNaN(GateRef gate,size_t argc,bool skipThis)603 void NativeInlineLowering::TryInlineNumberIsNaN(GateRef gate, size_t argc, bool skipThis)
604 {
605     if (!skipThis) {
606         return;
607     }
608     if (argc != 1) {
609         return;
610     }
611     CallThis1TypeInfoAccessor tacc(compilationEnv_, circuit_, gate);
612     Environment env(gate, circuit_, &builder_);
613     if (!Uncheck()) {
614         builder_.CallTargetCheck(gate, tacc.GetFunc(),
615                                  builder_.IntPtr(static_cast<int64_t>(BuiltinsStubCSigns::ID::NumberIsNaN)));
616     }
617     GateRef ret = builder_.NumberIsNaN(tacc.GetArg0());
618     acc_.ReplaceHirAndReplaceDeadIfException(gate, builder_.GetStateDepend(), ret);
619 }
620 
TryInlineNumberParseFloat(GateRef gate,size_t argc,bool skipThis)621 void NativeInlineLowering::TryInlineNumberParseFloat(GateRef gate, size_t argc, bool skipThis)
622 {
623     auto firstParam = skipThis ? 1 : 0;
624     auto func = acc_.GetValueIn(gate, argc + firstParam);
625     auto arg = acc_.GetValueIn(gate, firstParam);
626 
627     Environment env(gate, circuit_, &builder_);
628     auto id = BuiltinsStubCSigns::ID::NumberParseFloat;
629     if (!Uncheck()) {
630         builder_.CallTargetCheck(gate, func, builder_.IntPtr(static_cast<int64_t>(id)));
631     }
632     if (EnableTrace()) {
633         AddTraceLogs(gate, id);
634     }
635     GateRef ret = builder_.NumberParseFloat(arg, acc_.GetFrameState(gate));
636     acc_.ReplaceHirAndReplaceDeadIfException(gate, builder_.GetStateDepend(), ret);
637 }
638 
TryInlineNumberParseInt(GateRef gate,size_t argc,bool skipThis)639 void NativeInlineLowering::TryInlineNumberParseInt(GateRef gate, size_t argc, bool skipThis)
640 {
641     auto firstParam = skipThis ? 1 : 0;
642     auto func = acc_.GetValueIn(gate, argc + firstParam);
643     auto arg = acc_.GetValueIn(gate, firstParam);
644     auto radix = builder_.Undefined();
645     if (argc > 1) {
646         radix = acc_.GetValueIn(gate, firstParam + 1);
647     }
648 
649     Environment env(gate, circuit_, &builder_);
650     auto id = BuiltinsStubCSigns::ID::NumberParseInt;
651     if (!Uncheck()) {
652         builder_.CallTargetCheck(gate, func, builder_.IntPtr(static_cast<int64_t>(id)));
653     }
654     if (EnableTrace()) {
655         AddTraceLogs(gate, id);
656     }
657     // this may return exception
658     GateRef ret = builder_.NumberParseInt(arg, radix);
659     acc_.ReplaceGate(gate, builder_.GetStateDepend(), ret);
660 }
661 
TryInlineNumberIsSafeInteger(GateRef gate,size_t argc,bool skipThis)662 void NativeInlineLowering::TryInlineNumberIsSafeInteger(GateRef gate, size_t argc, bool skipThis)
663 {
664     if (!skipThis) {
665         return;
666     }
667     if (argc != 1) {
668         return;
669     }
670     CallThis1TypeInfoAccessor tacc(compilationEnv_, circuit_, gate);
671     Environment env(gate, circuit_, &builder_);
672     auto id = BuiltinsStubCSigns::ID::NumberIsSafeInteger;
673     if (!Uncheck()) {
674         builder_.CallTargetCheck(gate, tacc.GetFunc(),
675                                  builder_.IntPtr(static_cast<int64_t>(id)));
676     }
677     if (EnableTrace()) {
678         AddTraceLogs(gate, id);
679     }
680     GateRef ret = builder_.NumberIsSafeInteger(tacc.GetArg0());
681     acc_.ReplaceHirAndReplaceDeadIfException(gate, builder_.GetStateDepend(), ret);
682 }
683 
TryInlineBigIntAsIntN(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)684 void NativeInlineLowering::TryInlineBigIntAsIntN(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id,
685                                                  bool skipThis)
686 {
687     Environment env(gate, circuit_, &builder_);
688     bool firstParam = skipThis ? 1 : 0;
689     if (argc < 2U) {
690         return;
691     }
692     if (!Uncheck()) {
693         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam),
694                                  builder_.IntPtr(static_cast<int64_t>(id)));
695     }
696     if (EnableTrace()) {
697         AddTraceLogs(gate, id);
698     }
699     GateRef bits = acc_.GetValueIn(gate, firstParam);
700     GateRef bigint = acc_.GetValueIn(gate, firstParam + 1);
701     GateRef frameState = acc_.GetFrameState(gate);
702     bool isUnsigned = (id == BuiltinsStubCSigns::ID::BigIntAsUintN);
703     const auto* op = isUnsigned ? circuit_->BigIntAsUintN() : circuit_->BigIntAsIntN();
704     GateRef ret = builder_.BuildBigIntAsIntN(op, {bits, bigint, frameState});
705     ReplaceGateWithPendingException(gate, ret);
706 }
707 
TryInlineTypedArrayIteratorBuiltin(GateRef gate,BuiltinsStubCSigns::ID id,const GateMetaData * op,bool skipThis)708 void NativeInlineLowering::TryInlineTypedArrayIteratorBuiltin(GateRef gate,
709                                                               BuiltinsStubCSigns::ID id,
710                                                               const GateMetaData* op, bool skipThis)
711 {
712     if (!skipThis) {
713         return;
714     }
715 
716     CallThis0TypeInfoAccessor tacc(compilationEnv_, circuit_, gate);
717     Environment env(gate, circuit_, &builder_);
718 
719     if (!Uncheck()) {
720         builder_.CallTargetCheck(gate, tacc.GetFunc(), builder_.IntPtr(static_cast<int64_t>(id)), {tacc.GetThisObj()});
721     }
722 
723     if (EnableTrace()) {
724         AddTraceLogs(gate, id);
725     }
726 
727     GateRef ret = builder_.BuildTypedArrayIterator(acc_.GetValueIn(gate, 0), op);
728     ReplaceGateWithPendingException(gate, ret);
729 }
730 
TryInlineMathUnaryBuiltin(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,const GateMetaData * op,bool skipThis)731 void NativeInlineLowering::TryInlineMathUnaryBuiltin(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id,
732                                                      const GateMetaData* op, bool skipThis)
733 {
734     Environment env(gate, circuit_, &builder_);
735     bool firstParam = skipThis ? 1 : 0;
736     if (!Uncheck()) {
737         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam),
738                                  builder_.IntPtr(static_cast<int64_t>(id)));
739     }
740 
741     if (EnableTrace()) {
742         AddTraceLogs(gate, id);
743     }
744 
745     if (argc == 0) {
746         acc_.ReplaceHirAndReplaceDeadIfException(gate, builder_.GetStateDepend(), builder_.NanValue());
747         return;
748     }
749     GateRef ret = builder_.BuildControlDependOp(op, {acc_.GetValueIn(gate, firstParam)});
750     acc_.ReplaceHirAndReplaceDeadIfException(gate, builder_.GetStateDepend(), ret);
751 }
752 
TryInlineWhitoutParamBuiltin(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,const GateMetaData * op,bool skipThis)753 void NativeInlineLowering::TryInlineWhitoutParamBuiltin(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id,
754                                                         const GateMetaData* op, bool skipThis)
755 {
756     Environment env(gate, circuit_, &builder_);
757     bool firstParam = skipThis ? 1 : 0;
758     if (!Uncheck()) {
759         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam),
760                                  builder_.IntPtr(static_cast<int64_t>(id)));
761     }
762 
763     if (EnableTrace()) {
764         AddTraceLogs(gate, id);
765     }
766 
767     GateRef ret = builder_.BuildControlDependOp(op, {});
768     acc_.ReplaceHirAndReplaceDeadIfException(gate, builder_.GetStateDepend(), ret);
769 }
770 
TryInlineMathAbsBuiltin(GateRef gate,size_t argc,bool skipThis)771 void NativeInlineLowering::TryInlineMathAbsBuiltin(GateRef gate, size_t argc, bool skipThis)
772 {
773     Environment env(gate, circuit_, &builder_);
774     bool firstParam = skipThis ? 1 : 0;
775     if (!Uncheck()) {
776         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam),
777                                  builder_.IntPtr(static_cast<int64_t>(BuiltinsStubCSigns::ID::MathAbs)));
778     }
779 
780     if (EnableTrace()) {
781         AddTraceLogs(gate, BuiltinsStubCSigns::ID::MathAbs);
782     }
783 
784     if (argc == 0) {
785         acc_.ReplaceHirAndReplaceDeadIfException(gate, builder_.GetStateDepend(), builder_.NanValue());
786         return;
787     }
788     GateRef ret = builder_.BuildControlDependOp(circuit_->MathAbs(), {acc_.GetValueIn(gate, firstParam)},
789                                                 {acc_.GetFrameState(gate)});
790     acc_.ReplaceHirAndReplaceDeadIfException(gate, builder_.GetStateDepend(), ret);
791 }
792 
TryInlineMathClz32Builtin(GateRef gate,size_t argc,bool skipThis)793 void NativeInlineLowering::TryInlineMathClz32Builtin(GateRef gate, size_t argc, bool skipThis)
794 {
795     Environment env(gate, circuit_, &builder_);
796     bool firstParam = skipThis ? 1 : 0;
797     if (!Uncheck()) {
798         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam),
799                                  builder_.IntPtr(static_cast<int64_t>(BuiltinsStubCSigns::ID::MathClz32)));
800     }
801     if (EnableTrace()) {
802         AddTraceLogs(gate, BuiltinsStubCSigns::ID::MathClz32);
803     }
804     if (argc == 0) {
805         const int32_t defaultValue = 32;
806         acc_.ReplaceHirAndReplaceDeadIfException(gate, builder_.GetStateDepend(), builder_.Int32(defaultValue));
807         return;
808     }
809     GateRef ret = builder_.BuildControlDependOp(circuit_->MathClz32(), {acc_.GetValueIn(gate, firstParam)});
810     acc_.ReplaceHirAndReplaceDeadIfException(gate, builder_.GetStateDepend(), ret);
811 }
812 
TryInlineGlobalFiniteBuiltin(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,const GateMetaData * op,bool skipThis)813 void NativeInlineLowering::TryInlineGlobalFiniteBuiltin(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id,
814                                                         const GateMetaData* op, bool skipThis)
815 {
816     Environment env(gate, circuit_, &builder_);
817     bool firstParam = skipThis ? 1 : 0;
818     if (!Uncheck()) {
819         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam),
820                                  builder_.IntPtr(static_cast<int64_t>(id)));
821     }
822     if (EnableTrace()) {
823         AddTraceLogs(gate, id);
824     }
825     if (argc == 0) {
826         acc_.ReplaceHirAndReplaceDeadIfException(gate, builder_.GetStateDepend(), builder_.Boolean(false));
827         return;
828     }
829     GateRef ret = builder_.BuildControlDependOp(op, {acc_.GetValueIn(gate, firstParam)});
830     acc_.ReplaceHirAndReplaceDeadIfException(gate, builder_.GetStateDepend(), ret);
831 }
832 
TryInlineGlobalNanBuiltin(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,const GateMetaData * op,bool skipThis)833 void NativeInlineLowering::TryInlineGlobalNanBuiltin(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id,
834                                                      const GateMetaData* op, bool skipThis)
835 {
836     Environment env(gate, circuit_, &builder_);
837     bool firstParam = skipThis ? 1 : 0;
838     if (!Uncheck()) {
839         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam),
840                                  builder_.IntPtr(static_cast<int64_t>(id)));
841     }
842     if (EnableTrace()) {
843         AddTraceLogs(gate, id);
844     }
845     if (argc == 0) {
846         acc_.ReplaceHirAndReplaceDeadIfException(gate, builder_.GetStateDepend(), builder_.Boolean(true));
847         return;
848     }
849     GateRef ret = builder_.BuildControlDependOp(op, {acc_.GetValueIn(gate, firstParam)});
850     acc_.ReplaceHirAndReplaceDeadIfException(gate, builder_.GetStateDepend(), ret);
851 }
852 
TryInlineMathImulBuiltin(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,const GateMetaData * op,bool skipThis)853 void NativeInlineLowering::TryInlineMathImulBuiltin(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id,
854                                                     const GateMetaData* op, bool skipThis)
855 {
856     Environment env(gate, circuit_, &builder_);
857     bool firstParam = skipThis ? 1 : 0;
858     if (!Uncheck()) {
859         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam),
860                                  builder_.IntPtr(static_cast<int64_t>(id)));
861     }
862     if (EnableTrace()) {
863         AddTraceLogs(gate, id);
864     }
865     if (argc < 2U) {
866         acc_.ReplaceHirAndReplaceDeadIfException(gate, builder_.GetStateDepend(), builder_.Int32(0));
867         return;
868     }
869     GateRef ret = builder_.BuildControlDependOp(op, {acc_.GetValueIn(gate, firstParam),
870                                               acc_.GetValueIn(gate, firstParam + 1)});
871     acc_.ReplaceHirAndReplaceDeadIfException(gate, builder_.GetStateDepend(), ret);
872     return;
873 }
874 
TryInlineMathBinaryBuiltin(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,const GateMetaData * op,bool skipThis)875 void NativeInlineLowering::TryInlineMathBinaryBuiltin(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id,
876                                                       const GateMetaData* op, bool skipThis)
877 {
878     Environment env(gate, circuit_, &builder_);
879     bool firstParam = skipThis ? 1 : 0;
880     if (!Uncheck()) {
881         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam),
882                                  builder_.IntPtr(static_cast<int64_t>(id)));
883     }
884     if (EnableTrace()) {
885         AddTraceLogs(gate, id);
886     }
887     if (argc < 2U) {
888         acc_.ReplaceHirAndReplaceDeadIfException(gate, builder_.GetStateDepend(), builder_.NanValue());
889         return;
890     }
891     GateRef ret = builder_.BuildControlDependOp(op, {acc_.GetValueIn(gate, firstParam),
892                                               acc_.GetValueIn(gate, firstParam + 1)});
893     acc_.ReplaceHirAndReplaceDeadIfException(gate, builder_.GetStateDepend(), ret);
894     return;
895 }
896 
TryInlineMathMinMaxBuiltin(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,const GateMetaData * op,double defaultValue,bool skipThis)897 void NativeInlineLowering::TryInlineMathMinMaxBuiltin(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id,
898                                                       const GateMetaData* op, double defaultValue, bool skipThis)
899 {
900     Environment env(gate, circuit_, &builder_);
901     bool firstParam = skipThis ? 1 : 0;
902     if (!Uncheck()) {
903         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam),
904                                  builder_.IntPtr(static_cast<int64_t>(id)));
905     }
906     if (EnableTrace()) {
907         AddTraceLogs(gate, id);
908     }
909     if (argc == 0) {
910         acc_.ReplaceHirAndReplaceDeadIfException(gate, builder_.GetStateDepend(), builder_.Double(defaultValue));
911         return;
912     }
913     GateRef ret = acc_.GetValueIn(gate, firstParam);
914     if (argc == 1) {
915         builder_.TypeOfCheck(ret, ParamType::NumberType());
916         acc_.ReplaceHirAndReplaceDeadIfException(gate, builder_.GetStateDepend(), ret);
917         return;
918     }
919     for (size_t i = 1; i < argc; i++) {
920         auto param = acc_.GetValueIn(gate, i + firstParam);
921         ret = builder_.BuildControlDependOp(op, {ret, param});
922     }
923     acc_.ReplaceHirAndReplaceDeadIfException(gate, builder_.GetStateDepend(), ret);
924 }
925 
TryInlineArrayBufferIsView(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)926 void NativeInlineLowering::TryInlineArrayBufferIsView(GateRef gate,
927                                                       size_t argc,
928                                                       BuiltinsStubCSigns::ID id,
929                                                       bool skipThis)
930 {
931     if (!skipThis) {
932         return;
933     }
934     if (argc != 1) {
935         return;
936     }
937     CallThis1TypeInfoAccessor tacc(compilationEnv_, circuit_, gate);
938     Environment env(gate, circuit_, &builder_);
939     if (!Uncheck()) {
940         builder_.CallTargetCheck(gate, tacc.GetFunc(), builder_.IntPtr(static_cast<int64_t>(id)), {tacc.GetArg0()});
941     }
942     GateRef arg0 = tacc.GetArg0();
943     GateRef ret = builder_.ArrayBufferIsView(arg0);
944     acc_.ReplaceHirAndReplaceDeadIfException(gate, builder_.GetStateDepend(), ret);
945 }
946 
TryInlineDataViewGet(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)947 void NativeInlineLowering::TryInlineDataViewGet(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis)
948 {
949     if (!skipThis) {
950         return;
951     }
952     if (argc != 1 && argc != 2) { // number of args must be 1/2
953         return;
954     }
955     Environment env(gate, circuit_, &builder_);
956     if (!Uncheck()) {
957         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + 1), builder_.IntPtr(static_cast<int64_t>(id)));
958     }
959     GateRef thisObj = acc_.GetValueIn(gate, 0); // 0: this
960     builder_.EcmaObjectCheck(thisObj);
961     builder_.IsDataViewCheck(thisObj);
962     GateRef dataViewCallID = builder_.Int32(id);
963     GateRef index = acc_.GetValueIn(gate, 1); // 1: index of dataView
964     GateRef ret = Circuit::NullGate();
965     GateRef frameState = acc_.GetFrameState(gate);
966     builder_.DeoptCheck(builder_.TaggedIsInt(index), frameState, DeoptType::INDEXNOTINT);
967     GateRef indexInt = builder_.TaggedGetInt(index);
968     if (argc == 1) { // if not provide isLittleEndian, default use big endian
969         ret = builder_.DataViewGet(thisObj, indexInt, dataViewCallID, builder_.False(), frameState);
970     } else if (argc == 2) { // 2: provide isLittleEndian
971         GateRef isLittleEndian = acc_.GetValueIn(gate, 2); // 2: is little endian mode
972         ret = builder_.DataViewGet(thisObj, indexInt, dataViewCallID, isLittleEndian, frameState);
973     }
974     if (EnableTrace()) {
975         AddTraceLogs(gate, id);
976     }
977     acc_.ReplaceHirAndReplaceDeadIfException(gate, builder_.GetStateDepend(), ret);
978 }
979 
TryInlineDataViewSet(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)980 void NativeInlineLowering::TryInlineDataViewSet(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis)
981 {
982     if (!skipThis) {
983         return;
984     }
985     if (argc != 1 && argc != 2 && argc != 3) { // number of args must be 1/2/3
986         return;
987     }
988     Environment env(gate, circuit_, &builder_);
989     if (!Uncheck()) {
990         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + 1), builder_.IntPtr(static_cast<int64_t>(id)));
991     }
992     GateRef thisObj = acc_.GetValueIn(gate, 0); // 0: this
993     builder_.EcmaObjectCheck(thisObj);
994     builder_.IsDataViewCheck(thisObj);
995     GateRef dataViewCallID = builder_.Int32(id);
996     GateRef index = acc_.GetValueIn(gate, 1); // 1: index
997     GateRef frameState = acc_.GetFrameState(gate);
998     builder_.DeoptCheck(builder_.TaggedIsInt(index), frameState, DeoptType::INDEXNOTINT);
999     GateRef indexInt = builder_.TaggedGetInt(index);
1000     GateRef ret = Circuit::NullGate();
1001     if (argc == 1) { // arg counts is 1
1002         ret = builder_.DataViewSet(
1003             thisObj, indexInt, builder_.Double(base::NAN_VALUE), dataViewCallID, builder_.False(), frameState);
1004     } else if (argc == 2) { // arg counts is 2
1005         GateRef value = acc_.GetValueIn(gate, 2); // 2: value
1006         ret = builder_.DataViewSet(thisObj, indexInt, value, dataViewCallID, builder_.False(), frameState);
1007     } else if (argc == 3) { // arg counts is 3
1008         GateRef value = acc_.GetValueIn(gate, 2); // 2: value
1009         GateRef isLittleEndian = acc_.GetValueIn(gate, 3); // 3: is little endian mode
1010         ret = builder_.DataViewSet(thisObj, indexInt, value, dataViewCallID, isLittleEndian, frameState);
1011     }
1012     if (EnableTrace()) {
1013         AddTraceLogs(gate, id);
1014     }
1015     acc_.ReplaceHirAndReplaceDeadIfException(gate, builder_.GetStateDepend(), ret);
1016 }
1017 
InlineStubBuiltin(GateRef gate,size_t builtinArgc,size_t realArgc,BuiltinsStubCSigns::ID id,const GateMetaData * op,bool skipThis)1018 void NativeInlineLowering::InlineStubBuiltin(GateRef gate, size_t builtinArgc, size_t realArgc,
1019     BuiltinsStubCSigns::ID id, const GateMetaData* op, bool skipThis)
1020 {
1021     if (!skipThis) {
1022         return;
1023     }
1024     Environment env(gate, circuit_, &builder_);
1025     if (!Uncheck()) {
1026         GateRef obj = acc_.GetValueIn(gate, 0);
1027         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, realArgc + 1U),
1028                                  builder_.IntPtr(static_cast<int64_t>(id)), {obj});
1029     }
1030     if (EnableTrace()) {
1031         AddTraceLogs(gate, id);
1032     }
1033 
1034     std::vector<GateRef> args {};
1035     for (size_t i = 0; i <= builtinArgc; i++) {
1036         args.push_back(i <= realArgc ? acc_.GetValueIn(gate, i) : builder_.Undefined());
1037     }
1038     GateRef ret = builder_.BuildControlDependOp(op, args);
1039     acc_.ReplaceHirAndReplaceDeadIfException(gate, builder_.GetStateDepend(), ret);
1040 }
1041 
ReplaceGateWithPendingException(GateRef hirGate,GateRef value)1042 void NativeInlineLowering::ReplaceGateWithPendingException(GateRef hirGate, GateRef value)
1043 {
1044     GateRef state = builder_.GetState();
1045     // copy depend-wire of hirGate to value
1046     GateRef depend = builder_.GetDepend();
1047     // exception condition
1048     GateRef condition = builder_.HasPendingException(glue_, compilationEnv_);
1049     auto ifBranch = builder_.Branch(state, condition, 1, BranchWeight::DEOPT_WEIGHT, "checkException");
1050 
1051     GateRef ifTrue = builder_.IfTrue(ifBranch);
1052     GateRef ifFalse = builder_.IfFalse(ifBranch);
1053     GateRef eDepend = builder_.DependRelay(ifTrue, depend);
1054     GateRef sDepend = builder_.DependRelay(ifFalse, depend);
1055     StateDepend success(ifFalse, sDepend);
1056     StateDepend exception(ifTrue, eDepend);
1057     acc_.ReplaceHirWithIfBranch(hirGate, success, exception, value);
1058 }
1059 
TryInlineBigIntConstructor(GateRef gate,size_t argc,bool skipThis)1060 void NativeInlineLowering::TryInlineBigIntConstructor(GateRef gate, size_t argc, bool skipThis)
1061 {
1062     Environment env(gate, circuit_, &builder_);
1063     bool firstParam = skipThis ? 1 : 0;
1064     auto id = BuiltinsStubCSigns::ID::BigIntConstructor;
1065     if (!Uncheck()) {
1066         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam),
1067                                  builder_.IntPtr(static_cast<int64_t>(id)));
1068     }
1069     if (EnableTrace()) {
1070         AddTraceLogs(gate, id);
1071     }
1072 
1073     auto param = builder_.Undefined();
1074     if (argc > 0) {
1075         param = acc_.GetValueIn(gate, firstParam);
1076     }
1077 
1078     GateRef ret = builder_.BuildControlDependOp(circuit_->BigIntConstructor(), {param});
1079     ReplaceGateWithPendingException(gate, ret);
1080     return;
1081 }
1082 
TryInlineDateGetTime(GateRef gate,size_t argc,bool skipThis)1083 void NativeInlineLowering::TryInlineDateGetTime(GateRef gate, size_t argc, bool skipThis)
1084 {
1085     // Always shout be "this", we can't inline this function without instance of object
1086     if (!skipThis) {
1087         return;
1088     }
1089     Environment env(gate, circuit_, &builder_);
1090     // We are sure, that "this" is passed to this function, so always need to do +1
1091     bool firstParam = 1;
1092     if (!Uncheck()) {
1093         GateRef obj = acc_.GetValueIn(gate, 0);
1094         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam),
1095                                  builder_.IntPtr(static_cast<int64_t>(BuiltinsStubCSigns::ID::DateGetTime)), {obj});
1096     }
1097     if (EnableTrace()) {
1098         AddTraceLogs(gate, BuiltinsStubCSigns::ID::DateGetTime);
1099     }
1100     // Take object using "this"
1101     GateRef obj = acc_.GetValueIn(gate, 0);
1102     GateRef ret = builder_.BuildControlDependOp(circuit_->DateGetTime(), {obj});
1103     acc_.ReplaceHirAndReplaceDeadIfException(gate, builder_.GetStateDepend(), ret);
1104 }
1105 
TryInlineObjectIs(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)1106 void NativeInlineLowering::TryInlineObjectIs(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis)
1107 {
1108     Environment env(gate, circuit_, &builder_);
1109     if (argc != 2) {  // 2: left and right
1110         return;
1111     }
1112 
1113     size_t firstParam = skipThis ? 1 : 0;
1114     if (!Uncheck()) {
1115         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam),
1116                                  builder_.IntPtr(static_cast<int64_t>(id)));
1117     }
1118 
1119     if (EnableTrace()) {
1120         AddTraceLogs(gate, id);
1121     }
1122 
1123     GateRef left = acc_.GetValueIn(gate, firstParam);
1124     GateRef right = acc_.GetValueIn(gate, firstParam + 1);
1125     GateRef ret = builder_.BuildControlDependOp(circuit_->ObjectIs(), { left, right });
1126     ReplaceGateWithPendingException(gate, ret);
1127 }
1128 
TryInlineObjectGetPrototypeOf(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)1129 void NativeInlineLowering::TryInlineObjectGetPrototypeOf(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id,
1130                                                          bool skipThis)
1131 {
1132     Environment env(gate, circuit_, &builder_);
1133     if (argc != 1) {
1134         return;
1135     }
1136 
1137     size_t firstParam = skipThis ? 1 : 0;
1138     if (!Uncheck()) {
1139         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam),
1140                                  builder_.IntPtr(static_cast<int64_t>(id)));
1141     }
1142 
1143     if (EnableTrace()) {
1144         AddTraceLogs(gate, id);
1145     }
1146 
1147     GateRef value = acc_.GetValueIn(gate, firstParam);
1148     GateRef ret = builder_.BuildControlDependOp(circuit_->ObjectGetPrototypeOf(), { value });
1149     ReplaceGateWithPendingException(gate, ret);
1150 }
1151 
TryInlineObjectGetProto(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)1152 void NativeInlineLowering::TryInlineObjectGetProto(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis)
1153 {
1154     if (!skipThis || argc != 0) {
1155         return;
1156     }
1157 
1158     Environment env(gate, circuit_, &builder_);
1159     if (!Uncheck()) {
1160         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, 1), builder_.IntPtr(static_cast<int64_t>(id)));  // 1: func
1161     }
1162 
1163     if (EnableTrace()) {
1164         AddTraceLogs(gate, id);
1165     }
1166 
1167     GateRef thisValue = acc_.GetValueIn(gate, 0);
1168     GateRef ret = builder_.BuildControlDependOp(circuit_->ObjectGetPrototypeOf(), { thisValue });
1169     ReplaceGateWithPendingException(gate, ret);
1170 }
1171 
TryInlineObjectCreate(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)1172 void NativeInlineLowering::TryInlineObjectCreate(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis)
1173 {
1174     Environment env(gate, circuit_, &builder_);
1175     if (argc != 1) {
1176         return;
1177     }
1178 
1179     size_t firstParam = skipThis ? 1 : 0;
1180     if (!Uncheck()) {
1181         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam),
1182                                  builder_.IntPtr(static_cast<int64_t>(id)));
1183     }
1184 
1185     if (EnableTrace()) {
1186         AddTraceLogs(gate, id);
1187     }
1188 
1189     GateRef proto = acc_.GetValueIn(gate, firstParam);
1190     GateRef ret = builder_.BuildControlDependOp(circuit_->ObjectCreate(), { proto });
1191     ReplaceGateWithPendingException(gate, ret);
1192 }
1193 
TryInlineObjectIsPrototypeOf(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)1194 void NativeInlineLowering::TryInlineObjectIsPrototypeOf(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id,
1195                                                         bool skipThis)
1196 {
1197     if (!skipThis || argc != 1) {
1198         return;
1199     }
1200 
1201     Environment env(gate, circuit_, &builder_);
1202     if (!Uncheck()) {
1203         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, 2), builder_.IntPtr(static_cast<int64_t>(id)));  // 2: func
1204     }
1205 
1206     if (EnableTrace()) {
1207         AddTraceLogs(gate, id);
1208     }
1209 
1210     GateRef thisValue = acc_.GetValueIn(gate, 0);
1211     GateRef value = acc_.GetValueIn(gate, 1);
1212     GateRef ret = builder_.BuildControlDependOp(circuit_->ObjectIsPrototypeOf(), {thisValue, value});
1213     ReplaceGateWithPendingException(gate, ret);
1214 }
1215 
TryInlineObjectHasOwnProperty(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)1216 void NativeInlineLowering::TryInlineObjectHasOwnProperty(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id,
1217                                                          bool skipThis)
1218 {
1219     if (!skipThis || argc != 1) {
1220         return;
1221     }
1222 
1223     Environment env(gate, circuit_, &builder_);
1224     if (!Uncheck()) {
1225         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, 2), builder_.IntPtr(static_cast<int64_t>(id)));  // 2: func
1226     }
1227 
1228     if (EnableTrace()) {
1229         AddTraceLogs(gate, id);
1230     }
1231 
1232     GateRef thisValue = acc_.GetValueIn(gate, 0);
1233     GateRef key = acc_.GetValueIn(gate, 1);
1234     GateRef ret = builder_.BuildControlDependOp(circuit_->ObjectHasOwnProperty(), { thisValue, key });
1235     ReplaceGateWithPendingException(gate, ret);
1236 }
1237 
TryInlineReflectGetPrototypeOf(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)1238 void NativeInlineLowering::TryInlineReflectGetPrototypeOf(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id,
1239                                                           bool skipThis)
1240 {
1241     Environment env(gate, circuit_, &builder_);
1242     if (argc != 1) {
1243         return;
1244     }
1245 
1246     size_t firstParam = skipThis ? 1 : 0;
1247     if (!Uncheck()) {
1248         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam),
1249                                  builder_.IntPtr(static_cast<int64_t>(id)));
1250     }
1251 
1252     if (EnableTrace()) {
1253         AddTraceLogs(gate, id);
1254     }
1255 
1256     GateRef value = acc_.GetValueIn(gate, firstParam);
1257     GateRef ret = builder_.BuildControlDependOp(circuit_->ReflectGetPrototypeOf(), { value });
1258     ReplaceGateWithPendingException(gate, ret);
1259 }
1260 
TryInlineReflectGet(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)1261 void NativeInlineLowering::TryInlineReflectGet(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis)
1262 {
1263     Environment env(gate, circuit_, &builder_);
1264     if (argc != 2) {  // 2: target and key, do not handle receiver argument scene
1265         return;
1266     }
1267 
1268     size_t firstParam = skipThis ? 1 : 0;
1269     GateRef key = acc_.GetValueIn(gate, firstParam + 1);
1270     if (!TypeInfoAccessor::IsTrustedStringType(compilationEnv_, circuit_, chunk_, acc_, key)) {
1271         return;
1272     }
1273 
1274     if (!Uncheck()) {
1275         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam),
1276                                  builder_.IntPtr(static_cast<int64_t>(id)));
1277     }
1278 
1279     if (EnableTrace()) {
1280         AddTraceLogs(gate, id);
1281     }
1282 
1283     GateRef target = acc_.GetValueIn(gate, firstParam);
1284     GateRef ret = builder_.BuildControlDependOp(circuit_->ReflectGet(),
1285         { target, key }, { acc_.GetFrameState(gate) });
1286     ReplaceGateWithPendingException(gate, ret);
1287 }
1288 
TryInlineReflectHas(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)1289 void NativeInlineLowering::TryInlineReflectHas(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis)
1290 {
1291     Environment env(gate, circuit_, &builder_);
1292     if (argc != 2) {  // 2: target and key
1293         return;
1294     }
1295 
1296     size_t firstParam = skipThis ? 1 : 0;
1297     if (!Uncheck()) {
1298         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam),
1299                                  builder_.IntPtr(static_cast<int64_t>(id)));
1300     }
1301 
1302     if (EnableTrace()) {
1303         AddTraceLogs(gate, id);
1304     }
1305 
1306     GateRef target = acc_.GetValueIn(gate, firstParam);
1307     GateRef key = acc_.GetValueIn(gate, firstParam + 1);
1308     GateRef ret = builder_.BuildControlDependOp(circuit_->ReflectHas(), { target, key });
1309     ReplaceGateWithPendingException(gate, ret);
1310 }
1311 
TryInlineReflectConstruct(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)1312 void NativeInlineLowering::TryInlineReflectConstruct(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id,
1313                                                      bool skipThis)
1314 {
1315     Environment env(gate, circuit_, &builder_);
1316     if (argc != 2) {  // 2: optimize newtarget equal target
1317         return;
1318     }
1319 
1320     size_t firstParam = skipThis ? 1 : 0;
1321     GateRef target = acc_.GetValueIn(gate, firstParam);
1322     GateRef argumentsList = acc_.GetValueIn(gate, firstParam + 1);
1323 
1324     OpCode op = acc_.GetOpCode(argumentsList);
1325     if (op != OpCode::JS_BYTECODE) {
1326         return;
1327     }
1328 
1329     EcmaOpcode ecmaOpcode = acc_.GetByteCodeOpcode(argumentsList);
1330     // optimize empty array literal argumentsList
1331     if ((ecmaOpcode != EcmaOpcode::CREATEEMPTYARRAY_IMM8) && (ecmaOpcode != EcmaOpcode::CREATEEMPTYARRAY_IMM16)) {
1332         return;
1333     }
1334 
1335     if (!Uncheck()) {
1336         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam),
1337                                  builder_.IntPtr(static_cast<int64_t>(id)));
1338     }
1339 
1340     if (EnableTrace()) {
1341         AddTraceLogs(gate, id);
1342     }
1343 
1344     GateRef ret = builder_.BuildControlDependOp(circuit_->ReflectConstruct(),
1345         { target }, { acc_.GetFrameState(gate) });
1346     ReplaceGateWithPendingException(gate, ret);
1347 }
1348 
TryInlineReflectApply(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)1349 void NativeInlineLowering::TryInlineReflectApply(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id,
1350                                                  bool skipThis)
1351 {
1352     Environment env(gate, circuit_, &builder_);
1353     if (argc != 3) {  // 3: target key and  argumentsList
1354         return;
1355     }
1356 
1357     size_t firstParam = skipThis ? 1 : 0;
1358     GateRef target = acc_.GetValueIn(gate, firstParam);
1359     GateRef thisValue = acc_.GetValueIn(gate, firstParam + 1);
1360     GateRef argumentsList = acc_.GetValueIn(gate, firstParam + 2);
1361 
1362     if (!Uncheck()) {
1363         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam),
1364                                  builder_.IntPtr(static_cast<int64_t>(id)));
1365     }
1366 
1367     if (EnableTrace()) {
1368         AddTraceLogs(gate, id);
1369     }
1370 
1371     GateRef ret = builder_.BuildControlDependOp(circuit_->ReflectApply(),
1372         { target, thisValue, argumentsList }, { acc_.GetFrameState(gate) });
1373     ReplaceGateWithPendingException(gate, ret);
1374 }
1375 
TryInlineFunctionPrototypeApply(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)1376 void NativeInlineLowering::TryInlineFunctionPrototypeApply(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id,
1377                                                            bool skipThis)
1378 {
1379     Environment env(gate, circuit_, &builder_);
1380     if (!skipThis || argc == 0) {
1381         return;
1382     }
1383 
1384     if (!Uncheck()) {
1385         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + 1), builder_.IntPtr(static_cast<int64_t>(id)));
1386     }
1387 
1388     if (EnableTrace()) {
1389         AddTraceLogs(gate, id);
1390     }
1391 
1392     GateRef thisFunc = acc_.GetValueIn(gate, 0);
1393     GateRef thisArg = acc_.GetValueIn(gate, 1);
1394     GateRef argArray = (argc == 2) ? (acc_.GetValueIn(gate, 2)) : (builder_.UndefineConstant());
1395     GateRef ret = builder_.BuildControlDependOp(circuit_->FunctionPrototypeApply(), { thisFunc, thisArg, argArray });
1396     ReplaceGateWithPendingException(gate, ret);
1397 }
1398 
TryInlineFunctionPrototypeBind(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)1399 void NativeInlineLowering::TryInlineFunctionPrototypeBind(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id,
1400                                                           bool skipThis)
1401 {
1402     Environment env(gate, circuit_, &builder_);
1403     if (!skipThis || argc != 1) {
1404         return;
1405     }
1406 
1407     if (!Uncheck()) {
1408         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, 2), builder_.IntPtr(static_cast<int64_t>(id)));  // 2: func
1409     }
1410 
1411     if (EnableTrace()) {
1412         AddTraceLogs(gate, id);
1413     }
1414 
1415     GateRef target = acc_.GetValueIn(gate, 0);
1416     GateRef thisArg = acc_.GetValueIn(gate, 1);
1417     GateRef ret = builder_.BuildControlDependOp(circuit_->FunctionPrototypeBind(), { target, thisArg });
1418     ReplaceGateWithPendingException(gate, ret);
1419 }
1420 
TryInlineFunctionPrototypeCall(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)1421 void NativeInlineLowering::TryInlineFunctionPrototypeCall(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id,
1422                                                           bool skipThis)
1423 {
1424     Environment env(gate, circuit_, &builder_);
1425     if (!skipThis || argc == 0) {
1426         return;
1427     }
1428 
1429     if (!Uncheck()) {
1430         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + 1), builder_.IntPtr(static_cast<int64_t>(id)));
1431     }
1432 
1433     if (EnableTrace()) {
1434         AddTraceLogs(gate, id);
1435     }
1436 
1437     std::vector<GateRef> args(argc + 1);  // 1: thisFunc
1438     for (size_t i = 0; i <= argc; ++i) {
1439         args[i] = acc_.GetValueIn(gate, i);
1440     }
1441     GateRef ret = builder_.BuildControlDependOp(circuit_->FunctionPrototypeCall(argc + 1), args);
1442     ReplaceGateWithPendingException(gate, ret);
1443 }
1444 
TryInlineFunctionPrototypeHasInstance(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)1445 void NativeInlineLowering::TryInlineFunctionPrototypeHasInstance(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id,
1446                                                                  bool skipThis)
1447 {
1448     Environment env(gate, circuit_, &builder_);
1449     if (!skipThis || argc != 1) {
1450         return;
1451     }
1452 
1453     if (!Uncheck()) {
1454         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, 2), builder_.IntPtr(static_cast<int64_t>(id)));  // 2: func
1455     }
1456 
1457     if (EnableTrace()) {
1458         AddTraceLogs(gate, id);
1459     }
1460 
1461     GateRef function = acc_.GetValueIn(gate, 0);
1462     GateRef value = acc_.GetValueIn(gate, 1);
1463     GateRef ret = builder_.OrdinaryHasInstance(value, function);
1464     ReplaceGateWithPendingException(gate, ret);
1465 }
1466 
1467 // indexOf, lastIndexOf, includes
TryInlineIndexOfIncludes(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)1468 void NativeInlineLowering::TryInlineIndexOfIncludes(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis)
1469 {
1470     if (!skipThis) {
1471         return;
1472     }
1473     if (argc == 0) {
1474         return;
1475     }
1476     Environment env(gate, circuit_, &builder_);
1477     GateRef thisArray = acc_.GetValueIn(gate, 0);
1478     GateRef targetElement = acc_.GetValueIn(gate, 1);
1479     ElementsKind kind = acc_.TryGetArrayElementsKind(thisArray);
1480     if (!Uncheck()) {
1481         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + 1), builder_.IntPtr(static_cast<int64_t>(id)));
1482     }
1483     builder_.BuiltinPrototypeHClassCheck(thisArray, BuiltinTypeId::ARRAY, kind, false);
1484     builder_.StableArrayCheck(thisArray, kind, ArrayMetaDataAccessor::Mode::CALL_BUILTIN_METHOD);
1485     builder_.ElementsKindCheck(thisArray, kind, ArrayMetaDataAccessor::Mode::CALL_BUILTIN_METHOD);
1486     GateRef ret = Circuit::NullGate();
1487     GateRef elements = builder_.GetElementsArray(glue_, thisArray);
1488     GateRef thisLen = builder_.GetLengthOfJSArray(thisArray);
1489     GateRef callID = builder_.Int32(static_cast<int32_t>(id));
1490     GateRef arrayKind = builder_.Int32(Elements::ToUint(kind));
1491     if (argc == 1) {
1492         GateRef defaultFromIndex = (id == BuiltinsStubCSigns::ID::ArrayLastIndexOf)
1493             ? builder_.Int64Sub(builder_.ZExtInt32ToInt64(thisLen), builder_.Int64(1))
1494             : builder_.Int64(0);
1495         ret = builder_.ArrayIncludesIndexOf(elements, targetElement, defaultFromIndex, thisLen, callID, arrayKind);
1496     } else {
1497         GateRef fromIndexHandler = acc_.GetValueIn(gate, 2);
1498         builder_.DeoptCheck(builder_.TaggedIsNumber(fromIndexHandler), acc_.GetFrameState(gate),
1499                             DeoptType::INDEXNOTINT);
1500         GateRef fromIndex =
1501             BuiltinsArrayStubBuilder(&env, circuit_->GetGlobalEnvCache())
1502                 .MakeFromIndex(fromIndexHandler, thisLen, (id == BuiltinsStubCSigns::ID::ArrayLastIndexOf));
1503         ret = builder_.ArrayIncludesIndexOf(elements, targetElement, fromIndex, thisLen, callID, arrayKind);
1504     }
1505     if (EnableTrace()) {
1506         AddTraceLogs(gate, id);
1507     }
1508     acc_.ReplaceHirAndReplaceDeadIfException(gate, builder_.GetStateDepend(), ret);
1509 }
1510 
TryInlineArrayIterator(GateRef gate,BuiltinsStubCSigns::ID id,bool skipThis)1511 void NativeInlineLowering::TryInlineArrayIterator(GateRef gate, BuiltinsStubCSigns::ID id, bool skipThis)
1512 {
1513     if (!skipThis) {
1514         return;
1515     }
1516     CallThis0TypeInfoAccessor tacc(compilationEnv_, circuit_, gate);
1517     Environment env(gate, circuit_, &builder_);
1518 
1519     if (!Uncheck()) {
1520         builder_.CallTargetCheck(gate, tacc.GetFunc(), builder_.IntPtr(static_cast<int64_t>(id)), {tacc.GetThisObj()});
1521     }
1522     GateRef thisObj = acc_.GetValueIn(gate, 0);
1523     builder_.EcmaObjectCheck(thisObj);
1524     if (EnableTrace()) {
1525         AddTraceLogs(gate, id);
1526     }
1527     GateRef CallIDRef = builder_.Int32(static_cast<int32_t>(id));
1528     GateRef ret = builder_.ArrayIteratorBuiltin(thisObj, CallIDRef);
1529     acc_.ReplaceHirAndReplaceDeadIfException(gate, builder_.GetStateDepend(), ret);
1530 }
1531 
TryInlineArrayForEach(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)1532 void NativeInlineLowering::TryInlineArrayForEach(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis)
1533 {
1534     if (argc == 0) { // 0: Must have a callBackFn
1535         return;
1536     }
1537     if (!skipThis) {
1538         return;
1539     }
1540     Environment env(gate, circuit_, &builder_);
1541     auto pcOffset = acc_.TryGetPcOffset(gate);
1542     GateRef frameState = acc_.GetFrameState(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(), frameState, pcOffset);
1562     } else {
1563         ret = builder_.ArrayForEach(thisValue, callBackFn,
1564             acc_.GetValueIn(gate, 2), frameState, pcOffset); // 2 : provide using This
1565     }
1566     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), ret);
1567 }
1568 
TryInlineArrayFindOrFindIndex(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)1569 void NativeInlineLowering::TryInlineArrayFindOrFindIndex(GateRef gate,
1570                                                          size_t argc,
1571                                                          BuiltinsStubCSigns::ID id,
1572                                                          bool skipThis)
1573 {
1574     if (argc == 0) { // 0: Must have a callBackFn
1575         return;
1576     }
1577     if (!skipThis) {
1578         return;
1579     }
1580     Environment env(gate, circuit_, &builder_);
1581     GateRef thisValue = acc_.GetValueIn(gate, 0);
1582     ElementsKind kind = acc_.TryGetArrayElementsKind(thisValue);
1583     if (Elements::IsHole(kind)) {
1584         return;
1585     }
1586     if (!Uncheck()) {
1587         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + 1), builder_.IntPtr(static_cast<int64_t>(id)));
1588     }
1589     GateRef frameState = acc_.GetFrameState(gate);
1590     uint32_t pcOffset = acc_.TryGetPcOffset(gate);
1591     GateRef ret = Circuit::NullGate();
1592 
1593     builder_.BuiltinPrototypeHClassCheck(thisValue, BuiltinTypeId::ARRAY, kind, false);
1594     builder_.StableArrayCheck(thisValue, kind, ArrayMetaDataAccessor::Mode::CALL_BUILTIN_METHOD);
1595     builder_.ElementsKindCheck(thisValue, kind, ArrayMetaDataAccessor::Mode::CALL_BUILTIN_METHOD);
1596     GateRef callBackFn = acc_.GetValueIn(gate, 1);
1597     builder_.IsCallableCheck(callBackFn);
1598     if (EnableTrace()) {
1599         AddTraceLogs(gate, id);
1600     }
1601     GateRef callIDRef = builder_.Int32(static_cast<int32_t>(id));
1602 
1603     if (argc == 1) {
1604         ret = builder_.ArrayFindOrFindIndex(thisValue, callBackFn,
1605             builder_.UndefineConstant(), callIDRef, frameState, pcOffset);
1606     } else {
1607         ret = builder_.ArrayFindOrFindIndex(
1608             thisValue, callBackFn, acc_.GetValueIn(gate, 2), callIDRef, frameState, pcOffset); // 2:provide using This
1609     }
1610     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), ret);
1611 }
1612 
TryInlineArrayFilter(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)1613 void NativeInlineLowering::TryInlineArrayFilter(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis)
1614 {
1615     if (argc == 0) {
1616         return;
1617     }
1618     if (!skipThis) {
1619         return;
1620     }
1621     Environment env(gate, circuit_, &builder_);
1622     GateRef thisValue = acc_.GetValueIn(gate, 0);
1623     ElementsKind kind = acc_.TryGetArrayElementsKind(thisValue);
1624     if (Elements::IsHole(kind)) {
1625         return;
1626     }
1627     if (!Uncheck()) {
1628         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + 1), builder_.IntPtr(static_cast<int64_t>(id)));
1629     }
1630     builder_.BuiltinPrototypeHClassCheck(thisValue, BuiltinTypeId::ARRAY, kind, false);
1631     builder_.StableArrayCheck(thisValue, kind, ArrayMetaDataAccessor::Mode::CALL_BUILTIN_METHOD);
1632     builder_.ElementsKindCheck(thisValue, kind, ArrayMetaDataAccessor::Mode::CALL_BUILTIN_METHOD);
1633     GateRef callBackFn = acc_.GetValueIn(gate, 1);
1634     builder_.IsCallableCheck(callBackFn);
1635     if (EnableTrace()) {
1636         AddTraceLogs(gate, id);
1637     }
1638     uint32_t pcOffset = acc_.TryGetPcOffset(gate);
1639     GateRef frameState = acc_.GetFrameState(gate);
1640     GateRef ret = Circuit::NullGate();
1641     if (argc == 1) {
1642         ret = builder_.ArrayFilter(thisValue, callBackFn, builder_.UndefineConstant(), frameState, pcOffset);
1643     } else {
1644         ret = builder_.ArrayFilter(
1645             thisValue, callBackFn, acc_.GetValueIn(gate, 2), frameState, pcOffset); // 2: provide usingThis
1646     }
1647     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), ret);
1648 }
1649 
TryInlineArrayMap(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)1650 void NativeInlineLowering::TryInlineArrayMap(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis)
1651 {
1652     if (argc == 0) {
1653         return;
1654     }
1655     if (!skipThis) {
1656         return;
1657     }
1658     Environment env(gate, circuit_, &builder_);
1659     GateRef thisValue = acc_.GetValueIn(gate, 0);
1660     ElementsKind kind = acc_.TryGetArrayElementsKind(thisValue);
1661     if (Elements::IsHole(kind)) {
1662         return;
1663     }
1664     if (!Uncheck()) {
1665         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + 1), builder_.IntPtr(static_cast<int64_t>(id)));
1666     }
1667     builder_.BuiltinPrototypeHClassCheck(thisValue, BuiltinTypeId::ARRAY, kind, false);
1668     builder_.StableArrayCheck(thisValue, kind, ArrayMetaDataAccessor::Mode::CALL_BUILTIN_METHOD);
1669     builder_.ElementsKindCheck(thisValue, kind, ArrayMetaDataAccessor::Mode::CALL_BUILTIN_METHOD);
1670     GateRef callBackFn = acc_.GetValueIn(gate, 1);
1671     builder_.IsCallableCheck(callBackFn);
1672     if (EnableTrace()) {
1673         AddTraceLogs(gate, id);
1674     }
1675     uint32_t pcOffset = acc_.TryGetPcOffset(gate);
1676     GateRef frameState = acc_.GetFrameState(gate);
1677     GateRef ret = Circuit::NullGate();
1678     if (argc == 1) {
1679         ret = builder_.ArrayMap(thisValue, callBackFn, builder_.UndefineConstant(), frameState, pcOffset);
1680     } else {
1681         ret = builder_.ArrayMap(
1682             thisValue, callBackFn, acc_.GetValueIn(gate, 2), frameState, pcOffset); //2: provide usingThis
1683     }
1684     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), ret);
1685 }
1686 
TryInlineArraySome(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)1687 void NativeInlineLowering::TryInlineArraySome(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis)
1688 {
1689     if (argc == 0) {
1690         return;
1691     }
1692     if (!skipThis) {
1693         return;
1694     }
1695     Environment env(gate, circuit_, &builder_);
1696     GateRef thisValue = acc_.GetValueIn(gate, 0);
1697     ElementsKind kind = acc_.TryGetArrayElementsKind(thisValue);
1698     if (Elements::IsHole(kind)) {
1699         return;
1700     }
1701     if (!Uncheck()) {
1702         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + 1), builder_.IntPtr(static_cast<int64_t>(id)));
1703     }
1704     builder_.BuiltinPrototypeHClassCheck(thisValue, BuiltinTypeId::ARRAY, kind, false);
1705     builder_.StableArrayCheck(thisValue, kind, ArrayMetaDataAccessor::Mode::CALL_BUILTIN_METHOD);
1706     builder_.ElementsKindCheck(thisValue, kind, ArrayMetaDataAccessor::Mode::CALL_BUILTIN_METHOD);
1707     GateRef callBackFn = acc_.GetValueIn(gate, 1);
1708     builder_.IsCallableCheck(callBackFn);
1709     if (EnableTrace()) {
1710         AddTraceLogs(gate, id);
1711     }
1712     GateRef frameState = acc_.GetFrameState(gate);
1713     uint32_t pcOffset = acc_.TryGetPcOffset(gate);
1714     GateRef ret = Circuit::NullGate();
1715     if (argc == 1) {
1716         ret = builder_.ArraySome(thisValue, callBackFn, builder_.UndefineConstant(), frameState, pcOffset);
1717     } else {
1718         ret = builder_.ArraySome(thisValue, callBackFn,
1719             acc_.GetValueIn(gate, 2), frameState, pcOffset); // 2: provide usingThis
1720     }
1721     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), ret);
1722 }
1723 
TryInlineArrayEvery(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)1724 void NativeInlineLowering::TryInlineArrayEvery(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis)
1725 {
1726     if (argc == 0) {
1727         return;
1728     }
1729     if (!skipThis) {
1730         return;
1731     }
1732     Environment env(gate, circuit_, &builder_);
1733     GateRef thisValue = acc_.GetValueIn(gate, 0);
1734     ElementsKind kind = acc_.TryGetArrayElementsKind(thisValue);
1735     if (Elements::IsHole(kind)) {
1736         return;
1737     }
1738     if (!Uncheck()) {
1739         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + 1), builder_.IntPtr(static_cast<int64_t>(id)));
1740     }
1741     builder_.BuiltinPrototypeHClassCheck(thisValue, BuiltinTypeId::ARRAY, kind, false);
1742     builder_.StableArrayCheck(thisValue, kind, ArrayMetaDataAccessor::Mode::CALL_BUILTIN_METHOD);
1743     builder_.ElementsKindCheck(thisValue, kind, ArrayMetaDataAccessor::Mode::CALL_BUILTIN_METHOD);
1744     GateRef callBackFn = acc_.GetValueIn(gate, 1);
1745     builder_.IsCallableCheck(callBackFn);
1746     if (EnableTrace()) {
1747         AddTraceLogs(gate, id);
1748     }
1749     GateRef frameState = acc_.GetFrameState(gate);
1750     uint32_t pcOffset = acc_.TryGetPcOffset(gate);
1751     GateRef ret = Circuit::NullGate();
1752     if (argc == 1) {
1753         ret = builder_.ArrayEvery(thisValue, callBackFn, builder_.UndefineConstant(), frameState, pcOffset);
1754     } else {
1755         ret = builder_.ArrayEvery(thisValue, callBackFn,
1756             acc_.GetValueIn(gate, 2), frameState, pcOffset); // 2: provide usingThis
1757     }
1758     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), ret);
1759 }
1760 
TryInlineArrayPop(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)1761 void NativeInlineLowering::TryInlineArrayPop(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis)
1762 {
1763     if (!skipThis) {
1764         return;
1765     }
1766     Environment env(gate, circuit_, &builder_);
1767     if (!Uncheck()) {
1768         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + 1), builder_.IntPtr(static_cast<int64_t>(id)));
1769     }
1770     GateRef thisValue = acc_.GetValueIn(gate, 0);
1771     ElementsKind kind = acc_.TryGetArrayElementsKind(thisValue);
1772     builder_.BuiltinPrototypeHClassCheck(thisValue, BuiltinTypeId::ARRAY, kind, false);
1773     builder_.StableArrayCheck(thisValue, kind, ArrayMetaDataAccessor::Mode::CALL_BUILTIN_METHOD);
1774     builder_.ElementsKindCheck(thisValue, kind, ArrayMetaDataAccessor::Mode::CALL_BUILTIN_METHOD);
1775     if (EnableTrace()) {
1776         AddTraceLogs(gate, id);
1777     }
1778     GateRef ret = builder_.ArrayPop(thisValue, acc_.GetFrameState(gate));
1779     ReplaceGateWithPendingException(gate, ret);
1780 }
1781 
TryInlineArrayPush(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)1782 void NativeInlineLowering::TryInlineArrayPush(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis)
1783 {
1784     // To ensure that the Inline code is as small as possible,
1785     // FastPath only processes the case when the number of elements to push equals 1
1786     // and mutantArray is not enabled.
1787     if (!skipThis || argc != 1 || enableMutantArray_) {
1788         return;
1789     }
1790     Environment env(gate, circuit_, &builder_);
1791     if (!Uncheck()) {
1792         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + 1), builder_.IntPtr(static_cast<int64_t>(id)));
1793     }
1794     GateRef thisValue = acc_.GetValueIn(gate, 0);
1795     ElementsKind kind = acc_.TryGetArrayElementsKind(thisValue);
1796     if (EnableTrace()) {
1797         AddTraceLogs(gate, id);
1798     }
1799     builder_.StableArrayCheck(thisValue, kind, ArrayMetaDataAccessor::Mode::CALL_BUILTIN_METHOD);
1800     builder_.BuiltinPrototypeHClassCheck(thisValue, BuiltinTypeId::ARRAY, kind, false);
1801     GateRef ret = builder_.ArrayPush(thisValue, acc_.GetValueIn(gate, 1));
1802     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), ret);
1803 }
1804 
1805 
TryInlineArraySlice(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)1806 void NativeInlineLowering::TryInlineArraySlice(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis)
1807 {
1808     if (!skipThis) {
1809         return;
1810     }
1811     Environment env(gate, circuit_, &builder_);
1812     GateRef thisValue = acc_.GetValueIn(gate, 0);
1813     ElementsKind kind = acc_.TryGetArrayElementsKind(thisValue);
1814     builder_.BuiltinPrototypeHClassCheck(thisValue, BuiltinTypeId::ARRAY, kind, false);
1815     builder_.StableArrayCheck(thisValue, kind, ArrayMetaDataAccessor::Mode::CALL_BUILTIN_METHOD);
1816     builder_.ElementsKindCheck(thisValue, kind, ArrayMetaDataAccessor::Mode::CALL_BUILTIN_METHOD);
1817     GateRef frameState = acc_.GetFrameState(gate);
1818     if (!Uncheck()) {
1819         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + 1), builder_.IntPtr(static_cast<int64_t>(id)));
1820     }
1821     GateRef ret = Circuit::NullGate();
1822     if (argc == 0) {
1823         ret = builder_.ArraySlice(thisValue, builder_.UndefineConstant(), builder_.UndefineConstant(), frameState);
1824     } else if (argc == 1) {
1825         GateRef startIndex = acc_.GetValueIn(gate, 1);
1826         builder_.DeoptCheck(builder_.TaggedIsInt(startIndex), acc_.GetFrameState(gate), DeoptType::INDEXNOTINT);
1827         ret = builder_.ArraySlice(thisValue, startIndex, builder_.UndefineConstant(), frameState);
1828     } else {
1829         GateRef startIndex = acc_.GetValueIn(gate, 1);
1830         GateRef endIndex = acc_.GetValueIn(gate, 2);
1831         builder_.DeoptCheck(builder_.TaggedIsInt(startIndex), acc_.GetFrameState(gate), DeoptType::INDEXNOTINT);
1832         builder_.DeoptCheck(builder_.TaggedIsInt(endIndex), acc_.GetFrameState(gate), DeoptType::INDEXNOTINT);
1833         ret = builder_.ArraySlice(thisValue, startIndex, endIndex, frameState);
1834     }
1835     if (EnableTrace()) {
1836         AddTraceLogs(gate, id);
1837     }
1838     acc_.ReplaceHirAndReplaceDeadIfException(gate, builder_.GetStateDepend(), ret);
1839 }
1840 
TryInlineArraySort(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)1841 void NativeInlineLowering::TryInlineArraySort(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis)
1842 {
1843     if (!skipThis) {
1844         return;
1845     }
1846     if (argc > 1) {
1847         return;
1848     }
1849     Environment env(gate, circuit_, &builder_);
1850     if (argc == 1) {
1851         GateRef callBackFn = acc_.GetValueIn(gate, 1);
1852         auto fnType = acc_.GetGateType(callBackFn);
1853         if (!fnType.IsUndefinedType()) {
1854             return;
1855         }
1856     }
1857     GateRef thisValue = acc_.GetValueIn(gate, 0);
1858     ElementsKind kind = acc_.TryGetArrayElementsKind(thisValue);
1859     if (Elements::IsHole(kind)) {
1860         return;
1861     }
1862     if (!Uncheck()) {
1863         builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + 1), builder_.IntPtr(static_cast<int64_t>(id)));
1864     }
1865     GateRef ret = Circuit::NullGate();
1866 
1867     builder_.BuiltinPrototypeHClassCheck(thisValue, BuiltinTypeId::ARRAY, kind, false);
1868     builder_.StableArrayCheck(thisValue, kind, ArrayMetaDataAccessor::Mode::CALL_BUILTIN_METHOD);
1869     builder_.ElementsKindCheck(thisValue, kind, ArrayMetaDataAccessor::Mode::CALL_BUILTIN_METHOD);
1870     ret = builder_.ArraySort(thisValue, builder_.UndefineConstant());
1871     acc_.ReplaceHirAndReplaceDeadIfException(gate, builder_.GetStateDepend(), ret);
1872 }
1873 
1874 }  // namespace panda::ecmascript
1875