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