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