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