1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include "ecmascript/compiler/native_inline_lowering.h"
16 #include "ecmascript/builtins/builtins_number.h"
17 #include "ecmascript/builtins/builtins_string.h"
18 #include "ecmascript/base/number_helper.h"
19 #include "ecmascript/compiler/circuit.h"
20 #include "ecmascript/compiler/circuit_builder-inl.h"
21 #include "ecmascript/compiler/circuit_builder_helper.h"
22 #include "ecmascript/compiler/share_gate_meta_data.h"
23 #include "ecmascript/js_dataview.h"
24 #include "ecmascript/compiler/circuit.h"
25 #include "ecmascript/compiler/new_object_stub_builder.h"
26 #include "ecmascript/global_env.h"
27 #include "ecmascript/js_iterator.h"
28 #include "ecmascript/js_thread.h"
29 #include "ecmascript/message_string.h"
30
31 namespace panda::ecmascript::kungfu {
32
GetCallInfo(GateRef gate)33 std::optional<std::pair<size_t, bool>> NativeInlineLowering::GetCallInfo(GateRef gate)
34 {
35 EcmaOpcode ecmaOpcode = acc_.GetByteCodeOpcode(gate);
36 switch (ecmaOpcode) {
37 case EcmaOpcode::CALLARG0_IMM8:
38 return {{0U, false}};
39 case EcmaOpcode::CALLTHIS0_IMM8_V8:
40 return {{0U, true}};
41 case EcmaOpcode::CALLARG1_IMM8_V8:
42 return {{1U, false}};
43 case EcmaOpcode::CALLTHIS1_IMM8_V8_V8:
44 return {{1U, true}};
45 case EcmaOpcode::CALLARGS2_IMM8_V8_V8:
46 return {{2U, false}};
47 case EcmaOpcode::CALLTHIS2_IMM8_V8_V8_V8:
48 return {{2U, true}};
49 case EcmaOpcode::CALLARGS3_IMM8_V8_V8_V8:
50 return {{3U, false}};
51 case EcmaOpcode::CALLTHIS3_IMM8_V8_V8_V8_V8:
52 return {{3U, true}};
53 case EcmaOpcode::CALLRANGE_IMM8_IMM8_V8: {
54 CallRangeTypeInfoAccessor tia(compilationEnv_, circuit_, gate);
55 return {{tia.GetArgc(), false}};
56 }
57 case EcmaOpcode::CALLTHISRANGE_IMM8_IMM8_V8: {
58 CallThisRangeTypeInfoAccessor tia(compilationEnv_, circuit_, gate);
59 return {{tia.GetArgc(), true}};
60 }
61 default:
62 return std::nullopt;
63 }
64 }
65
RunNativeInlineLowering()66 void NativeInlineLowering::RunNativeInlineLowering()
67 {
68 std::vector<GateRef> gateList;
69 circuit_->GetAllGates(gateList);
70 for (const auto &gate : gateList) {
71 auto op = acc_.GetOpCode(gate);
72 if (op != OpCode::JS_BYTECODE) {
73 continue;
74 }
75 auto optCallInfo = GetCallInfo(gate);
76 if (!optCallInfo) {
77 continue;
78 }
79 auto [argc, skipThis] = optCallInfo.value();
80 CallTypeInfoAccessor ctia(compilationEnv_, circuit_, gate);
81 BuiltinsStubCSigns::ID id = ctia.TryGetPGOBuiltinMethodId();
82 if (IS_INVALID_ID(id) && id != BuiltinsStubCSigns::ID::BigIntConstructor) {
83 continue;
84 }
85 switch (id) {
86 case BuiltinsStubCSigns::ID::StringFromCharCode:
87 TryInlineStringFromCharCode(gate, argc, skipThis);
88 break;
89 case BuiltinsStubCSigns::ID::StringSubstring:
90 TryInlineStringSubstring(gate, argc, skipThis);
91 break;
92 case BuiltinsStubCSigns::ID::StringSubStr:
93 TryInlineStringSubStr(gate, argc, skipThis);
94 break;
95 case BuiltinsStubCSigns::ID::StringSlice:
96 TryInlineStringSlice(gate, argc, skipThis);
97 break;
98 case BuiltinsStubCSigns::ID::NumberIsFinite:
99 TryInlineNumberIsFinite(gate, argc, skipThis);
100 break;
101 case BuiltinsStubCSigns::ID::NumberIsInteger:
102 TryInlineNumberIsInteger(gate, argc, skipThis);
103 break;
104 case BuiltinsStubCSigns::ID::NumberIsNaN:
105 TryInlineNumberIsNaN(gate, argc, skipThis);
106 break;
107 case BuiltinsStubCSigns::ID::NumberParseFloat:
108 TryInlineNumberParseFloat(gate, argc, skipThis);
109 break;
110 case BuiltinsStubCSigns::ID::NumberParseInt:
111 TryInlineNumberParseInt(gate, argc, skipThis);
112 break;
113 case BuiltinsStubCSigns::ID::NumberIsSafeInteger:
114 TryInlineNumberIsSafeInteger(gate, argc, skipThis);
115 break;
116 case BuiltinsStubCSigns::ID::TypedArrayEntries:
117 TryInlineTypedArrayIteratorBuiltin(gate, id, circuit_->TypedArrayEntries(), skipThis);
118 break;
119 case BuiltinsStubCSigns::ID::TypedArrayKeys:
120 TryInlineTypedArrayIteratorBuiltin(gate, id, circuit_->TypedArrayKeys(), skipThis);
121 break;
122 case BuiltinsStubCSigns::ID::TypedArrayValues:
123 TryInlineTypedArrayIteratorBuiltin(gate, id, circuit_->TypedArrayValues(), skipThis);
124 break;
125 case BuiltinsStubCSigns::ID::ArrayValues:
126 TryInlineArrayIterator(gate, id, skipThis);
127 break;
128 case BuiltinsStubCSigns::ID::ArrayKeys:
129 TryInlineArrayIterator(gate, id, skipThis);
130 break;
131 case BuiltinsStubCSigns::ID::ArrayEntries:
132 TryInlineArrayIterator(gate, id, skipThis);
133 break;
134 case BuiltinsStubCSigns::ID::MathAcos:
135 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathAcos(), skipThis);
136 break;
137 case BuiltinsStubCSigns::ID::MathAcosh:
138 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathAcosh(), skipThis);
139 break;
140 case BuiltinsStubCSigns::ID::MathAsin:
141 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathAsin(), skipThis);
142 break;
143 case BuiltinsStubCSigns::ID::MathAsinh:
144 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathAsinh(), skipThis);
145 break;
146 case BuiltinsStubCSigns::ID::MathAtan:
147 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathAtan(), skipThis);
148 break;
149 case BuiltinsStubCSigns::ID::MathAtan2:
150 TryInlineMathBinaryBuiltin(gate, argc, id, circuit_->MathAtan2(), skipThis);
151 break;
152 case BuiltinsStubCSigns::ID::MathAtanh:
153 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathAtanh(), skipThis);
154 break;
155 case BuiltinsStubCSigns::ID::MathCos:
156 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathCos(), skipThis);
157 break;
158 case BuiltinsStubCSigns::ID::MathCosh:
159 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathCosh(), skipThis);
160 break;
161 case BuiltinsStubCSigns::ID::MathSign:
162 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathSign(), skipThis);
163 break;
164 case BuiltinsStubCSigns::ID::MathSin:
165 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathSin(), skipThis);
166 break;
167 case BuiltinsStubCSigns::ID::MathSinh:
168 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathSinh(), skipThis);
169 break;
170 case BuiltinsStubCSigns::ID::MathSqrt:
171 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathSqrt(), skipThis);
172 break;
173 case BuiltinsStubCSigns::ID::MathTan:
174 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathTan(), skipThis);
175 break;
176 case BuiltinsStubCSigns::ID::MathTanh:
177 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathTanh(), skipThis);
178 break;
179 case BuiltinsStubCSigns::ID::MathTrunc:
180 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathTrunc(), skipThis);
181 break;
182 case BuiltinsStubCSigns::ID::MathAbs:
183 TryInlineMathAbsBuiltin(gate, argc, skipThis);
184 break;
185 case BuiltinsStubCSigns::ID::MathLog:
186 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathLog(), skipThis);
187 break;
188 case BuiltinsStubCSigns::ID::MathLog2:
189 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathLog2(), skipThis);
190 break;
191 case BuiltinsStubCSigns::ID::MathLog10:
192 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathLog10(), skipThis);
193 break;
194 case BuiltinsStubCSigns::ID::MathLog1p:
195 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathLog1p(), skipThis);
196 break;
197 case BuiltinsStubCSigns::ID::MathExp:
198 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathExp(), skipThis);
199 break;
200 case BuiltinsStubCSigns::ID::MathExpm1:
201 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathExpm1(), skipThis);
202 break;
203 case BuiltinsStubCSigns::ID::MathClz32:
204 TryInlineMathClz32Builtin(gate, argc, skipThis);
205 break;
206 case BuiltinsStubCSigns::ID::MathPow:
207 TryInlineMathBinaryBuiltin(gate, argc, id, circuit_->MathPow(), skipThis);
208 break;
209 case BuiltinsStubCSigns::ID::MathCbrt:
210 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathCbrt(), skipThis);
211 break;
212 case BuiltinsStubCSigns::ID::MathImul:
213 TryInlineMathImulBuiltin(gate, argc, id, circuit_->MathImul(), skipThis);
214 break;
215 case BuiltinsStubCSigns::ID::GlobalIsFinite:
216 TryInlineGlobalFiniteBuiltin(gate, argc, id, circuit_->GlobalIsFinite(), skipThis);
217 break;
218 case BuiltinsStubCSigns::ID::GlobalIsNan:
219 TryInlineGlobalNanBuiltin(gate, argc, id, circuit_->GlobalIsNan(), skipThis);
220 break;
221 case BuiltinsStubCSigns::ID::DateGetTime:
222 TryInlineDateGetTime(gate, argc, skipThis);
223 break;
224 case BuiltinsStubCSigns::ID::MathMin:
225 TryInlineMathMinMaxBuiltin(gate, argc, id, circuit_->MathMin(), base::POSITIVE_INFINITY, skipThis);
226 break;
227 case BuiltinsStubCSigns::ID::MathMax:
228 TryInlineMathMinMaxBuiltin(gate, argc, id, circuit_->MathMax(), -base::POSITIVE_INFINITY, skipThis);
229 break;
230 case BuiltinsStubCSigns::ID::MathRound:
231 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathRound(), skipThis);
232 break;
233 case BuiltinsStubCSigns::ID::MathFRound:
234 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathFRound(), skipThis);
235 break;
236 case BuiltinsStubCSigns::ID::MathCeil:
237 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathCeil(), skipThis);
238 break;
239 case BuiltinsStubCSigns::ID::MathFloor:
240 TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathFloor(), skipThis);
241 break;
242 case BuiltinsStubCSigns::ID::ArrayBufferIsView:
243 TryInlineArrayBufferIsView(gate, argc, id, skipThis);
244 break;
245 case BuiltinsStubCSigns::ID::DataViewGetFloat32:
246 case BuiltinsStubCSigns::ID::DataViewGetFloat64:
247 case BuiltinsStubCSigns::ID::DataViewGetInt8:
248 case BuiltinsStubCSigns::ID::DataViewGetInt16:
249 case BuiltinsStubCSigns::ID::DataViewGetInt32:
250 case BuiltinsStubCSigns::ID::DataViewGetUint16:
251 case BuiltinsStubCSigns::ID::DataViewGetUint32:
252 case BuiltinsStubCSigns::ID::DataViewGetUint8:
253 TryInlineDataViewGet(gate, argc, id, skipThis);
254 break;
255 case BuiltinsStubCSigns::ID::DataViewSetFloat32:
256 case BuiltinsStubCSigns::ID::DataViewSetFloat64:
257 case BuiltinsStubCSigns::ID::DataViewSetInt8:
258 case BuiltinsStubCSigns::ID::DataViewSetInt16:
259 case BuiltinsStubCSigns::ID::DataViewSetInt32:
260 case BuiltinsStubCSigns::ID::DataViewSetUint8:
261 case BuiltinsStubCSigns::ID::DataViewSetUint16:
262 case BuiltinsStubCSigns::ID::DataViewSetUint32:
263 TryInlineDataViewSet(gate, argc, id, skipThis);
264 break;
265 case BuiltinsStubCSigns::ID::BigIntAsIntN:
266 case BuiltinsStubCSigns::ID::BigIntAsUintN:
267 TryInlineBigIntAsIntN(gate, argc, id, skipThis);
268 break;
269 case BuiltinsStubCSigns::ID::MapGet:
270 InlineStubBuiltin(gate, 1U, argc, id, circuit_->MapGet(), skipThis);
271 break;
272 case BuiltinsStubCSigns::ID::MapHas:
273 InlineStubBuiltin(gate, 1U, argc, id, circuit_->MapHas(), skipThis);
274 break;
275 case BuiltinsStubCSigns::ID::MapKeys:
276 InlineStubBuiltin(gate, 0U, argc, id, circuit_->MapKeys(), skipThis);
277 break;
278 case BuiltinsStubCSigns::ID::MapValues:
279 InlineStubBuiltin(gate, 0U, argc, id, circuit_->MapValues(), skipThis);
280 break;
281 case BuiltinsStubCSigns::ID::MapEntries:
282 InlineStubBuiltin(gate, 0U, argc, id, circuit_->MapEntries(), skipThis);
283 break;
284 case BuiltinsStubCSigns::ID::SetHas:
285 InlineStubBuiltin(gate, 1U, argc, id, circuit_->SetHas(), skipThis);
286 break;
287 case BuiltinsStubCSigns::ID::SetAdd:
288 InlineStubBuiltin(gate, 1U, argc, id, circuit_->SetAdd(), skipThis);
289 break;
290 case BuiltinsStubCSigns::ID::DateNow:
291 TryInlineWhitoutParamBuiltin(gate, argc, id, circuit_->DateNow(), skipThis);
292 break;
293 case BuiltinsStubCSigns::ID::MapDelete:
294 InlineStubBuiltin(gate, 1U, argc, id, circuit_->MapDelete(), skipThis);
295 break;
296 case BuiltinsStubCSigns::ID::SetDelete:
297 InlineStubBuiltin(gate, 1U, argc, id, circuit_->SetDelete(), skipThis);
298 break;
299 case BuiltinsStubCSigns::ID::SetValues:
300 InlineStubBuiltin(gate, 0U, argc, id, circuit_->SetValues(), skipThis);
301 break;
302 case BuiltinsStubCSigns::ID::SetEntries:
303 InlineStubBuiltin(gate, 0U, argc, id, circuit_->SetEntries(), skipThis);
304 break;
305 case BuiltinsStubCSigns::ID::BigIntConstructor:
306 TryInlineBigIntConstructor(gate, argc, skipThis);
307 break;
308 case BuiltinsStubCSigns::ID::MapClear:
309 InlineStubBuiltin(gate, 0U, argc, id, circuit_->MapClear(), skipThis);
310 break;
311 case BuiltinsStubCSigns::ID::SetClear:
312 InlineStubBuiltin(gate, 0U, argc, id, circuit_->SetClear(), skipThis);
313 break;
314 case BuiltinsStubCSigns::ID::ArraySort:
315 TryInlineArraySort(gate, argc, id, skipThis);
316 break;
317 case BuiltinsStubCSigns::ID::ObjectIs:
318 TryInlineObjectIs(gate, argc, id, skipThis);
319 break;
320 case BuiltinsStubCSigns::ID::ObjectGetPrototypeOf:
321 TryInlineObjectGetPrototypeOf(gate, argc, id, skipThis);
322 break;
323 case BuiltinsStubCSigns::ID::ObjectGetProto:
324 TryInlineObjectGetProto(gate, argc, id, skipThis);
325 break;
326 case BuiltinsStubCSigns::ID::ObjectCreate:
327 TryInlineObjectCreate(gate, argc, id, skipThis);
328 break;
329 case BuiltinsStubCSigns::ID::ObjectIsPrototypeOf:
330 TryInlineObjectIsPrototypeOf(gate, argc, id, skipThis);
331 break;
332 case BuiltinsStubCSigns::ID::ObjectHasOwnProperty:
333 TryInlineObjectHasOwnProperty(gate, argc, id, skipThis);
334 break;
335 case BuiltinsStubCSigns::ID::ReflectGetPrototypeOf:
336 TryInlineReflectGetPrototypeOf(gate, argc, id, skipThis);
337 break;
338 case BuiltinsStubCSigns::ID::ReflectGet:
339 TryInlineReflectGet(gate, argc, id, skipThis);
340 break;
341 case BuiltinsStubCSigns::ID::ReflectHas:
342 TryInlineReflectHas(gate, argc, id, skipThis);
343 break;
344 case BuiltinsStubCSigns::ID::ReflectConstruct:
345 TryInlineReflectConstruct(gate, argc, id, skipThis);
346 break;
347 case BuiltinsStubCSigns::ID::ReflectApply:
348 TryInlineReflectApply(gate, argc, id, skipThis);
349 break;
350 case BuiltinsStubCSigns::ID::FunctionPrototypeHasInstance:
351 TryInlineFunctionPrototypeHasInstance(gate, argc, id, skipThis);
352 break;
353 case BuiltinsStubCSigns::ID::ArrayIndexOf:
354 TryInlineIndexOfIncludes(gate, argc, id, skipThis);
355 break;
356 case BuiltinsStubCSigns::ID::ArrayIncludes:
357 TryInlineIndexOfIncludes(gate, argc, id, skipThis);
358 break;
359 case BuiltinsStubCSigns::ID::ArrayForEach:
360 TryInlineArrayForEach(gate, argc, id, skipThis);
361 break;
362 case BuiltinsStubCSigns::ID::ArrayFind:
363 TryInlineArrayFindOrFindIndex(gate, argc, id, skipThis);
364 break;
365 case BuiltinsStubCSigns::ID::ArrayFindIndex:
366 TryInlineArrayFindOrFindIndex(gate, argc, id, skipThis);
367 break;
368 case BuiltinsStubCSigns::ID::ArrayFilter:
369 TryInlineArrayFilter(gate, argc, id, skipThis);
370 break;
371 case BuiltinsStubCSigns::ID::ArrayMap:
372 TryInlineArrayMap(gate, argc, id, skipThis);
373 break;
374 case BuiltinsStubCSigns::ID::ArraySome:
375 TryInlineArraySome(gate, argc, id, skipThis);
376 break;
377 case BuiltinsStubCSigns::ID::ArrayEvery:
378 TryInlineArrayEvery(gate, argc, id, skipThis);
379 break;
380 case BuiltinsStubCSigns::ID::ArrayPop:
381 TryInlineArrayPop(gate, argc, id, skipThis);
382 break;
383 case BuiltinsStubCSigns::ID::ArraySlice:
384 TryInlineArraySlice(gate, argc, id, skipThis);
385 break;
386 default:
387 break;
388 }
389 }
390
391 if (EnableLog()) {
392 LOG_COMPILER(INFO) << " ";
393 LOG_COMPILER(INFO) << "\033[34m" << "================="
394 << " After Native Inline Lowering "
395 << "[" << GetMethodName() << "] "
396 << "=================" << "\033[0m";
397 circuit_->PrintAllGatesWithBytecode();
398 LOG_COMPILER(INFO) << "\033[34m" << "=========================== End ===========================" << "\033[0m";
399 }
400 }
401
AddTraceLogs(GateRef gate,BuiltinsStubCSigns::ID id)402 void NativeInlineLowering::AddTraceLogs(GateRef gate, BuiltinsStubCSigns::ID id)
403 {
404 size_t index = RTSTUB_ID(AotInlineBuiltinTrace);
405
406 GateRef frameState = acc_.GetFrameState(gate);
407 GateRef frameArgs = acc_.GetValueIn(frameState);
408 GateRef callerFunc = acc_.GetValueIn(frameArgs, 0);
409 std::vector<GateRef> args{callerFunc, builder_.Int32(id)};
410
411 builder_.CallRuntime(glue_, index, Gate::InvalidGateRef, args, gate);
412 }
413
TryInlineStringFromCharCode(GateRef gate,size_t argc,bool skipThis)414 void NativeInlineLowering::TryInlineStringFromCharCode(GateRef gate, size_t argc, bool skipThis)
415 {
416 if (!skipThis) {
417 return;
418 }
419 if (argc != 1) {
420 return;
421 }
422 CallThis1TypeInfoAccessor tacc(compilationEnv_, circuit_, gate);
423 Environment env(gate, circuit_, &builder_);
424 if (!Uncheck()) {
425 builder_.CallTargetCheck(gate, tacc.GetFunc(),
426 builder_.IntPtr(static_cast<int64_t>(BuiltinsStubCSigns::ID::StringFromCharCode)),
427 {tacc.GetArg0()});
428 }
429
430 if (EnableTrace()) {
431 AddTraceLogs(gate, BuiltinsStubCSigns::ID::StringFromCharCode);
432 }
433
434 GateRef ret = builder_.StringFromSingleCharCode(tacc.GetArg0());
435 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), ret);
436 }
437
TryInlineStringSubstring(GateRef gate,size_t argc,bool skipThis)438 void NativeInlineLowering::TryInlineStringSubstring(GateRef gate, size_t argc, bool skipThis)
439 {
440 if (!skipThis) {
441 return;
442 }
443 if (argc != 1 && argc != 2) { // only optimize one or two parameters scene
444 return;
445 }
446 Environment env(gate, circuit_, &builder_);
447 GateRef ret = Circuit::NullGate();
448 if (argc == 1) {
449 CallThis1TypeInfoAccessor tacc(compilationEnv_, circuit_, gate);
450 GateRef thisValue = acc_.GetValueIn(gate, 0);
451 GateRef startTag = tacc.GetArg0();
452 GateRef endTag = builder_.GetLengthFromString(thisValue);
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 ret = builder_.StringSubstring(thisValue, startTag, endTag);
462 } else {
463 GateRef thisValue = acc_.GetValueIn(gate, 0);
464 GateRef startTag = acc_.GetValueIn(gate, 1);
465 GateRef endTag = acc_.GetValueIn(gate, 2);
466 GateRef func = acc_.GetValueIn(gate, 3);
467 if (!Uncheck()) {
468 builder_.CallTargetCheck(gate, func,
469 builder_.IntPtr(static_cast<int64_t>(BuiltinsStubCSigns::ID::StringSubstring)));
470 builder_.EcmaStringCheck(thisValue);
471 auto param_check = LogicAndBuilder(&env).And(builder_.TaggedIsNumber(startTag))
472 .And(builder_.TaggedIsNumber(endTag)).Done();
473 builder_.DeoptCheck(param_check, acc_.GetFrameState(gate), DeoptType::BUILTIN_INLINING_TYPE_GUARD);
474 }
475 ret = builder_.StringSubstring(thisValue, startTag, endTag);
476 }
477 acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret);
478 }
479
TryInlineStringSubStr(GateRef gate,size_t argc,bool skipThis)480 void NativeInlineLowering::TryInlineStringSubStr(GateRef gate, size_t argc, bool skipThis)
481 {
482 if (!skipThis) {
483 return;
484 }
485 if (argc != 1 && argc != 2) { // only optimize one or two parameters scene
486 return;
487 }
488 Environment env(gate, circuit_, &builder_);
489 GateRef ret = Circuit::NullGate();
490 if (argc == 1) {
491 CallThis1TypeInfoAccessor tacc(compilationEnv_, circuit_, gate);
492 GateRef thisValue = acc_.GetValueIn(gate, 0);
493 GateRef intStart = tacc.GetArg0();
494 GateRef lengthTag = builder_.Int32(INT_MAX);
495 if (!Uncheck()) {
496 builder_.CallTargetCheck(gate, tacc.GetFunc(),
497 builder_.IntPtr(static_cast<int64_t>(BuiltinsStubCSigns::ID::StringSubStr)),
498 {tacc.GetArg0()});
499 builder_.EcmaStringCheck(thisValue);
500 auto param_check = builder_.TaggedIsNumber(intStart);
501 builder_.DeoptCheck(param_check, acc_.GetFrameState(gate), DeoptType::BUILTIN_INLINING_TYPE_GUARD);
502 }
503 ret = builder_.StringSubStr(thisValue, intStart, lengthTag);
504 } else {
505 GateRef thisValue = acc_.GetValueIn(gate, 0);
506 GateRef intStart = acc_.GetValueIn(gate, 1);
507 GateRef lengthTag = acc_.GetValueIn(gate, 2);
508 GateRef func = acc_.GetValueIn(gate, 3); //acc
509 if (!Uncheck()) {
510 builder_.CallTargetCheck(gate, func,
511 builder_.IntPtr(static_cast<int64_t>(BuiltinsStubCSigns::ID::StringSubStr)));
512 builder_.EcmaStringCheck(thisValue);
513 auto param_check = LogicAndBuilder(&env).And(builder_.TaggedIsNumber(intStart))
514 .And(builder_.TaggedIsNumber(lengthTag)).Done();
515 builder_.DeoptCheck(param_check, acc_.GetFrameState(gate), DeoptType::BUILTIN_INLINING_TYPE_GUARD);
516 }
517 ret = builder_.StringSubStr(thisValue, intStart, lengthTag);
518 }
519 acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret);
520 }
521
TryInlineStringSlice(GateRef gate,size_t argc,bool skipThis)522 void NativeInlineLowering::TryInlineStringSlice(GateRef gate, size_t argc, bool skipThis)
523 {
524 if (!skipThis) {
525 return;
526 }
527 if (argc != 1 && argc != 2) { // only optimize one or two parameters scene
528 return;
529 }
530 Environment env(gate, circuit_, &builder_);
531 GateRef ret = Circuit::NullGate();
532 if (argc == 1) {
533 CallThis1TypeInfoAccessor tacc(compilationEnv_, circuit_, gate);
534 GateRef thisValue = acc_.GetValueIn(gate, 0);
535 GateRef startTag = tacc.GetArg0();
536 GateRef endTag = builder_.GetLengthFromString(thisValue);
537 if (!Uncheck()) {
538 builder_.CallTargetCheck(gate, tacc.GetFunc(),
539 builder_.IntPtr(static_cast<int64_t>(BuiltinsStubCSigns::ID::StringSlice)),
540 {tacc.GetArg0()});
541 builder_.EcmaStringCheck(thisValue);
542 auto param_check = builder_.TaggedIsNumber(startTag);
543 builder_.DeoptCheck(param_check, acc_.GetFrameState(gate), DeoptType::BUILTIN_INLINING_TYPE_GUARD);
544 }
545 ret = builder_.StringSlice(thisValue, startTag, endTag);
546 } else {
547 GateRef thisValue = acc_.GetValueIn(gate, 0);
548 GateRef startTag = acc_.GetValueIn(gate, 1);
549 GateRef endTag = acc_.GetValueIn(gate, 2);
550 GateRef func = acc_.GetValueIn(gate, 3);
551 if (!Uncheck()) {
552 builder_.CallTargetCheck(gate, func,
553 builder_.IntPtr(static_cast<int64_t>(BuiltinsStubCSigns::ID::StringSlice)));
554 builder_.EcmaStringCheck(thisValue);
555 auto param_check = LogicAndBuilder(&env).And(builder_.TaggedIsNumber(startTag))
556 .And(builder_.TaggedIsNumber(endTag)).Done();
557 builder_.DeoptCheck(param_check, acc_.GetFrameState(gate), DeoptType::BUILTIN_INLINING_TYPE_GUARD);
558 }
559 ret = builder_.StringSlice(thisValue, startTag, endTag);
560 }
561 acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret);
562 }
563
TryInlineNumberIsFinite(GateRef gate,size_t argc,bool skipThis)564 void NativeInlineLowering::TryInlineNumberIsFinite(GateRef gate, size_t argc, bool skipThis)
565 {
566 if (!skipThis) {
567 return;
568 }
569 if (argc != 1) {
570 return;
571 }
572 CallThis1TypeInfoAccessor tacc(compilationEnv_, circuit_, gate);
573 Environment env(gate, circuit_, &builder_);
574 if (!Uncheck()) {
575 builder_.CallTargetCheck(gate, tacc.GetFunc(),
576 builder_.IntPtr(static_cast<int64_t>(BuiltinsStubCSigns::ID::NumberIsFinite)));
577 }
578 GateRef ret = builder_.NumberIsFinite(tacc.GetArg0());
579 acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret);
580 }
581
TryInlineNumberIsInteger(GateRef gate,size_t argc,bool skipThis)582 void NativeInlineLowering::TryInlineNumberIsInteger(GateRef gate, size_t argc, bool skipThis)
583 {
584 if (!skipThis) {
585 return;
586 }
587 if (argc != 1) {
588 return;
589 }
590 CallThis1TypeInfoAccessor tacc(compilationEnv_, circuit_, gate);
591 Environment env(gate, circuit_, &builder_);
592 auto id = BuiltinsStubCSigns::ID::NumberIsInteger;
593 if (!Uncheck()) {
594 builder_.CallTargetCheck(gate, tacc.GetFunc(),
595 builder_.IntPtr(static_cast<int64_t>(id)));
596 }
597 if (EnableTrace()) {
598 AddTraceLogs(gate, id);
599 }
600 GateRef ret = builder_.NumberIsInteger(tacc.GetArg0());
601 acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret);
602 }
603
TryInlineNumberIsNaN(GateRef gate,size_t argc,bool skipThis)604 void NativeInlineLowering::TryInlineNumberIsNaN(GateRef gate, size_t argc, bool skipThis)
605 {
606 if (!skipThis) {
607 return;
608 }
609 if (argc != 1) {
610 return;
611 }
612 CallThis1TypeInfoAccessor tacc(compilationEnv_, circuit_, gate);
613 Environment env(gate, circuit_, &builder_);
614 if (!Uncheck()) {
615 builder_.CallTargetCheck(gate, tacc.GetFunc(),
616 builder_.IntPtr(static_cast<int64_t>(BuiltinsStubCSigns::ID::NumberIsNaN)));
617 }
618 GateRef ret = builder_.NumberIsNaN(tacc.GetArg0());
619 acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret);
620 }
621
TryInlineNumberParseFloat(GateRef gate,size_t argc,bool skipThis)622 void NativeInlineLowering::TryInlineNumberParseFloat(GateRef gate, size_t argc, bool skipThis)
623 {
624 auto firstParam = skipThis ? 1 : 0;
625 auto func = acc_.GetValueIn(gate, argc + firstParam);
626 auto arg = acc_.GetValueIn(gate, firstParam);
627
628 Environment env(gate, circuit_, &builder_);
629 auto id = BuiltinsStubCSigns::ID::NumberParseFloat;
630 if (!Uncheck()) {
631 builder_.CallTargetCheck(gate, func, builder_.IntPtr(static_cast<int64_t>(id)));
632 }
633 if (EnableTrace()) {
634 AddTraceLogs(gate, id);
635 }
636 GateRef ret = builder_.NumberParseFloat(arg, acc_.GetFrameState(gate));
637 acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret);
638 }
639
TryInlineNumberParseInt(GateRef gate,size_t argc,bool skipThis)640 void NativeInlineLowering::TryInlineNumberParseInt(GateRef gate, size_t argc, bool skipThis)
641 {
642 auto firstParam = skipThis ? 1 : 0;
643 auto func = acc_.GetValueIn(gate, argc + firstParam);
644 auto arg = acc_.GetValueIn(gate, firstParam);
645 auto radix = builder_.Undefined();
646 if (argc > 1) {
647 radix = acc_.GetValueIn(gate, firstParam + 1);
648 }
649
650 Environment env(gate, circuit_, &builder_);
651 auto id = BuiltinsStubCSigns::ID::NumberParseInt;
652 if (!Uncheck()) {
653 builder_.CallTargetCheck(gate, func, builder_.IntPtr(static_cast<int64_t>(id)));
654 }
655 if (EnableTrace()) {
656 AddTraceLogs(gate, id);
657 }
658 GateRef ret = builder_.NumberParseInt(arg, radix);
659 acc_.ReplaceHirAndDeleteIfException(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_.ReplaceHirAndDeleteIfException(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 acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), 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 acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), 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_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), builder_.NanValue());
747 return;
748 }
749 GateRef ret = builder_.BuildControlDependOp(op, {acc_.GetValueIn(gate, firstParam)});
750 acc_.ReplaceHirAndDeleteIfException(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_.ReplaceHirAndDeleteIfException(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_.ReplaceHirAndDeleteIfException(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_.ReplaceHirAndDeleteIfException(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_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), builder_.Int32(defaultValue));
807 return;
808 }
809 GateRef ret = builder_.BuildControlDependOp(circuit_->MathClz32(), {acc_.GetValueIn(gate, firstParam)});
810 acc_.ReplaceHirAndDeleteIfException(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_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), builder_.Boolean(false));
827 return;
828 }
829 GateRef ret = builder_.BuildControlDependOp(op, {acc_.GetValueIn(gate, firstParam)});
830 acc_.ReplaceHirAndDeleteIfException(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_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), builder_.Boolean(true));
847 return;
848 }
849 GateRef ret = builder_.BuildControlDependOp(op, {acc_.GetValueIn(gate, firstParam)});
850 acc_.ReplaceHirAndDeleteIfException(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_.ReplaceHirAndDeleteIfException(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_.ReplaceHirAndDeleteIfException(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_.ReplaceHirAndDeleteIfException(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_.ReplaceHirAndDeleteIfException(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_.ReplaceHirAndDeleteIfException(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_.ReplaceHirAndDeleteIfException(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_.ReplaceHirAndDeleteIfException(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_.ReplaceHirAndDeleteIfException(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_.ReplaceHirAndDeleteIfException(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_.ReplaceHirAndDeleteIfException(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_.ReplaceHirAndDeleteIfException(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_);
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_.ReplaceHirAndDeleteIfException(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(), { target, key });
1285 ReplaceGateWithPendingException(gate, ret);
1286 }
1287
TryInlineReflectHas(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)1288 void NativeInlineLowering::TryInlineReflectHas(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis)
1289 {
1290 Environment env(gate, circuit_, &builder_);
1291 if (argc != 2) { // 2: target and key
1292 return;
1293 }
1294
1295 size_t firstParam = skipThis ? 1 : 0;
1296 if (!Uncheck()) {
1297 builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam),
1298 builder_.IntPtr(static_cast<int64_t>(id)));
1299 }
1300
1301 if (EnableTrace()) {
1302 AddTraceLogs(gate, id);
1303 }
1304
1305 GateRef target = acc_.GetValueIn(gate, firstParam);
1306 GateRef key = acc_.GetValueIn(gate, firstParam + 1);
1307 GateRef ret = builder_.BuildControlDependOp(circuit_->ReflectHas(), { target, key });
1308 ReplaceGateWithPendingException(gate, ret);
1309 }
1310
TryInlineReflectConstruct(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)1311 void NativeInlineLowering::TryInlineReflectConstruct(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id,
1312 bool skipThis)
1313 {
1314 Environment env(gate, circuit_, &builder_);
1315 if (argc != 2) { // 2: optimize newtarget equal target
1316 return;
1317 }
1318
1319 size_t firstParam = skipThis ? 1 : 0;
1320 GateRef target = acc_.GetValueIn(gate, firstParam);
1321 GateRef argumentsList = acc_.GetValueIn(gate, firstParam + 1);
1322
1323 OpCode op = acc_.GetOpCode(argumentsList);
1324 if (op != OpCode::JS_BYTECODE) {
1325 return;
1326 }
1327
1328 EcmaOpcode ecmaOpcode = acc_.GetByteCodeOpcode(argumentsList);
1329 // optimize empty array literal argumentsList
1330 if ((ecmaOpcode != EcmaOpcode::CREATEEMPTYARRAY_IMM8) && (ecmaOpcode != EcmaOpcode::CREATEEMPTYARRAY_IMM16)) {
1331 return;
1332 }
1333
1334 if (!Uncheck()) {
1335 builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam),
1336 builder_.IntPtr(static_cast<int64_t>(id)));
1337 }
1338
1339 if (EnableTrace()) {
1340 AddTraceLogs(gate, id);
1341 }
1342
1343 GateRef ret = builder_.BuildControlDependOp(circuit_->ReflectConstruct(), { target });
1344 ReplaceGateWithPendingException(gate, ret);
1345 }
1346
TryInlineReflectApply(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)1347 void NativeInlineLowering::TryInlineReflectApply(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id,
1348 bool skipThis)
1349 {
1350 Environment env(gate, circuit_, &builder_);
1351 if (argc != 3) { // 3: target key and argumentsList
1352 return;
1353 }
1354
1355 size_t firstParam = skipThis ? 1 : 0;
1356 GateRef target = acc_.GetValueIn(gate, firstParam);
1357 GateRef thisValue = acc_.GetValueIn(gate, firstParam + 1);
1358 GateRef argumentsList = acc_.GetValueIn(gate, firstParam + 2);
1359
1360 if (!Uncheck()) {
1361 builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + firstParam),
1362 builder_.IntPtr(static_cast<int64_t>(id)));
1363 }
1364
1365 if (EnableTrace()) {
1366 AddTraceLogs(gate, id);
1367 }
1368
1369 GateRef ret = builder_.BuildControlDependOp(circuit_->ReflectApply(), { target, thisValue, argumentsList });
1370 ReplaceGateWithPendingException(gate, ret);
1371 }
1372
TryInlineFunctionPrototypeApply(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)1373 void NativeInlineLowering::TryInlineFunctionPrototypeApply(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id,
1374 bool skipThis)
1375 {
1376 Environment env(gate, circuit_, &builder_);
1377 if (!skipThis || argc == 0) {
1378 return;
1379 }
1380
1381 if (!Uncheck()) {
1382 builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + 1), builder_.IntPtr(static_cast<int64_t>(id)));
1383 }
1384
1385 if (EnableTrace()) {
1386 AddTraceLogs(gate, id);
1387 }
1388
1389 GateRef thisFunc = acc_.GetValueIn(gate, 0);
1390 GateRef thisArg = acc_.GetValueIn(gate, 1);
1391 GateRef argArray = (argc == 2) ? (acc_.GetValueIn(gate, 2)) : (builder_.UndefineConstant());
1392 GateRef ret = builder_.BuildControlDependOp(circuit_->FunctionPrototypeApply(), { thisFunc, thisArg, argArray });
1393 ReplaceGateWithPendingException(gate, ret);
1394 }
1395
TryInlineFunctionPrototypeBind(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)1396 void NativeInlineLowering::TryInlineFunctionPrototypeBind(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id,
1397 bool skipThis)
1398 {
1399 Environment env(gate, circuit_, &builder_);
1400 if (!skipThis || argc != 1) {
1401 return;
1402 }
1403
1404 if (!Uncheck()) {
1405 builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, 2), builder_.IntPtr(static_cast<int64_t>(id))); // 2: func
1406 }
1407
1408 if (EnableTrace()) {
1409 AddTraceLogs(gate, id);
1410 }
1411
1412 GateRef target = acc_.GetValueIn(gate, 0);
1413 GateRef thisArg = acc_.GetValueIn(gate, 1);
1414 GateRef ret = builder_.BuildControlDependOp(circuit_->FunctionPrototypeBind(), { target, thisArg });
1415 ReplaceGateWithPendingException(gate, ret);
1416 }
1417
TryInlineFunctionPrototypeCall(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)1418 void NativeInlineLowering::TryInlineFunctionPrototypeCall(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id,
1419 bool skipThis)
1420 {
1421 Environment env(gate, circuit_, &builder_);
1422 if (!skipThis || argc == 0) {
1423 return;
1424 }
1425
1426 if (!Uncheck()) {
1427 builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + 1), builder_.IntPtr(static_cast<int64_t>(id)));
1428 }
1429
1430 if (EnableTrace()) {
1431 AddTraceLogs(gate, id);
1432 }
1433
1434 std::vector<GateRef> args(argc + 1); // 1: thisFunc
1435 for (size_t i = 0; i <= argc; ++i) {
1436 args[i] = acc_.GetValueIn(gate, i);
1437 }
1438 GateRef ret = builder_.BuildControlDependOp(circuit_->FunctionPrototypeCall(argc + 1), args);
1439 ReplaceGateWithPendingException(gate, ret);
1440 }
1441
TryInlineFunctionPrototypeHasInstance(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)1442 void NativeInlineLowering::TryInlineFunctionPrototypeHasInstance(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id,
1443 bool skipThis)
1444 {
1445 Environment env(gate, circuit_, &builder_);
1446 if (!skipThis || argc != 1) {
1447 return;
1448 }
1449
1450 if (!Uncheck()) {
1451 builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, 2), builder_.IntPtr(static_cast<int64_t>(id))); // 2: func
1452 }
1453
1454 if (EnableTrace()) {
1455 AddTraceLogs(gate, id);
1456 }
1457
1458 GateRef function = acc_.GetValueIn(gate, 0);
1459 GateRef value = acc_.GetValueIn(gate, 1);
1460 GateRef ret = builder_.OrdinaryHasInstance(value, function);
1461 ReplaceGateWithPendingException(gate, ret);
1462 }
1463
TryInlineIndexOfIncludes(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)1464 void NativeInlineLowering::TryInlineIndexOfIncludes(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis)
1465 {
1466 if (!skipThis) {
1467 return;
1468 }
1469 if (argc == 0) {
1470 return;
1471 }
1472 Environment env(gate, circuit_, &builder_);
1473 GateRef thisArray = acc_.GetValueIn(gate, 0);
1474 GateRef targetElement = acc_.GetValueIn(gate, 1);
1475 ElementsKind kind = acc_.TryGetArrayElementsKind(thisArray);
1476 if (!Uncheck()) {
1477 builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + 1), builder_.IntPtr(static_cast<int64_t>(id)));
1478 }
1479 builder_.BuiltinPrototypeHClassCheck(thisArray, BuiltinTypeId::ARRAY, kind, false);
1480 builder_.StableArrayCheck(thisArray, kind, ArrayMetaDataAccessor::Mode::LOAD_ELEMENT);
1481 GateRef ret = Circuit::NullGate();
1482 GateRef callID = builder_.Int32(static_cast<int32_t>(id));
1483 GateRef arrayKind = builder_.Int32(static_cast<int32_t>(kind));
1484 if (argc == 1) {
1485 ret = builder_.ArrayIncludesIndexOf(thisArray, builder_.Int32(0), targetElement, callID, arrayKind);
1486 } else {
1487 GateRef fromIndexHandler = acc_.GetValueIn(gate, 2);
1488 builder_.DeoptCheck(builder_.TaggedIsInt(fromIndexHandler), acc_.GetFrameState(gate), DeoptType::INDEXNOTINT);
1489 GateRef fromIndex = builder_.TaggedGetInt(fromIndexHandler);
1490 ret = builder_.ArrayIncludesIndexOf(thisArray, fromIndex, targetElement, callID, arrayKind);
1491 }
1492 if (EnableTrace()) {
1493 AddTraceLogs(gate, id);
1494 }
1495 acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret);
1496 }
1497
TryInlineArrayIterator(GateRef gate,BuiltinsStubCSigns::ID id,bool skipThis)1498 void NativeInlineLowering::TryInlineArrayIterator(GateRef gate, BuiltinsStubCSigns::ID id, bool skipThis)
1499 {
1500 if (!skipThis) {
1501 return;
1502 }
1503 CallThis0TypeInfoAccessor tacc(compilationEnv_, circuit_, gate);
1504 Environment env(gate, circuit_, &builder_);
1505
1506 if (!Uncheck()) {
1507 builder_.CallTargetCheck(gate, tacc.GetFunc(), builder_.IntPtr(static_cast<int64_t>(id)), {tacc.GetThisObj()});
1508 }
1509 GateRef thisObj = acc_.GetValueIn(gate, 0);
1510 builder_.EcmaObjectCheck(thisObj);
1511 if (EnableTrace()) {
1512 AddTraceLogs(gate, id);
1513 }
1514 GateRef CallIDRef = builder_.Int32(static_cast<int32_t>(id));
1515 GateRef ret = builder_.ArrayIteratorBuiltin(thisObj, CallIDRef);
1516 acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret);
1517 }
1518
TryInlineArrayForEach(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)1519 void NativeInlineLowering::TryInlineArrayForEach(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis)
1520 {
1521 if (argc == 0) { // 0: Must have a callBackFn
1522 return;
1523 }
1524 if (!skipThis) {
1525 return;
1526 }
1527 Environment env(gate, circuit_, &builder_);
1528 auto pcOffset = acc_.TryGetPcOffset(gate);
1529 GateRef ret = Circuit::NullGate();
1530 GateRef thisValue = acc_.GetValueIn(gate, 0);
1531 ElementsKind kind = acc_.TryGetArrayElementsKind(thisValue);
1532 if (Elements::IsHole(kind)) {
1533 return;
1534 }
1535 if (!Uncheck()) {
1536 builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + 1), builder_.IntPtr(static_cast<int64_t>(id)));
1537 }
1538 builder_.BuiltinPrototypeHClassCheck(thisValue, BuiltinTypeId::ARRAY, kind, false);
1539 builder_.StableArrayCheck(thisValue, kind, ArrayMetaDataAccessor::Mode::LOAD_ELEMENT);
1540 GateRef callBackFn = acc_.GetValueIn(gate, 1);
1541 builder_.IsCallableCheck(callBackFn);
1542 if (EnableTrace()) {
1543 AddTraceLogs(gate, id);
1544 }
1545 if (argc == 1) {
1546 ret = builder_.ArrayForEach(thisValue, callBackFn, builder_.UndefineConstant(), pcOffset);
1547 } else {
1548 ret = builder_.ArrayForEach(thisValue, callBackFn, acc_.GetValueIn(gate, 2), pcOffset); // 2:provide using This
1549 }
1550 acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret);
1551 }
1552
TryInlineArrayFindOrFindIndex(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)1553 void NativeInlineLowering::TryInlineArrayFindOrFindIndex(GateRef gate,
1554 size_t argc,
1555 BuiltinsStubCSigns::ID id,
1556 bool skipThis)
1557 {
1558 if (argc == 0) { // 0: Must have a callBackFn
1559 return;
1560 }
1561 if (!skipThis) {
1562 return;
1563 }
1564 Environment env(gate, circuit_, &builder_);
1565 GateRef thisValue = acc_.GetValueIn(gate, 0);
1566 ElementsKind kind = acc_.TryGetArrayElementsKind(thisValue);
1567 if (Elements::IsHole(kind)) {
1568 return;
1569 }
1570 if (!Uncheck()) {
1571 builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + 1), builder_.IntPtr(static_cast<int64_t>(id)));
1572 }
1573 uint32_t pcOffset = acc_.TryGetPcOffset(gate);
1574 GateRef ret = Circuit::NullGate();
1575
1576 builder_.BuiltinPrototypeHClassCheck(thisValue, BuiltinTypeId::ARRAY, kind, false);
1577 builder_.StableArrayCheck(thisValue, kind, ArrayMetaDataAccessor::Mode::LOAD_ELEMENT);
1578 GateRef callBackFn = acc_.GetValueIn(gate, 1);
1579 builder_.IsCallableCheck(callBackFn);
1580 if (EnableTrace()) {
1581 AddTraceLogs(gate, id);
1582 }
1583 GateRef callIDRef = builder_.Int32(static_cast<int32_t>(id));
1584
1585 if (argc == 1) {
1586 ret = builder_.ArrayFindOrFindIndex(thisValue, callBackFn, builder_.UndefineConstant(), callIDRef, pcOffset);
1587 } else {
1588 ret = builder_.ArrayFindOrFindIndex(
1589 thisValue, callBackFn, acc_.GetValueIn(gate, 2), callIDRef, pcOffset); // 2:provide using This
1590 }
1591 acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret);
1592 }
1593
TryInlineArrayFilter(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)1594 void NativeInlineLowering::TryInlineArrayFilter(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis)
1595 {
1596 if (argc == 0) {
1597 return;
1598 }
1599 if (!skipThis) {
1600 return;
1601 }
1602 Environment env(gate, circuit_, &builder_);
1603 GateRef thisValue = acc_.GetValueIn(gate, 0);
1604 ElementsKind kind = acc_.TryGetArrayElementsKind(thisValue);
1605 if (Elements::IsHole(kind)) {
1606 return;
1607 }
1608 if (!Uncheck()) {
1609 builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + 1), builder_.IntPtr(static_cast<int64_t>(id)));
1610 }
1611 builder_.BuiltinPrototypeHClassCheck(thisValue, BuiltinTypeId::ARRAY, kind, false);
1612 builder_.StableArrayCheck(thisValue, kind, ArrayMetaDataAccessor::Mode::LOAD_ELEMENT);
1613 GateRef callBackFn = acc_.GetValueIn(gate, 1);
1614 builder_.IsCallableCheck(callBackFn);
1615 if (EnableTrace()) {
1616 AddTraceLogs(gate, id);
1617 }
1618 uint32_t pcOffset = acc_.TryGetPcOffset(gate);
1619 GateRef frameState = acc_.GetFrameState(gate);
1620 GateRef ret = Circuit::NullGate();
1621 if (argc == 1) {
1622 ret = builder_.ArrayFilter(thisValue, callBackFn, builder_.UndefineConstant(), frameState, pcOffset);
1623 } else {
1624 ret = builder_.ArrayFilter(
1625 thisValue, callBackFn, acc_.GetValueIn(gate, 2), frameState, pcOffset); //2: provide usingThis
1626 }
1627 acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret);
1628 }
1629
TryInlineArrayMap(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)1630 void NativeInlineLowering::TryInlineArrayMap(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis)
1631 {
1632 if (argc == 0) {
1633 return;
1634 }
1635 if (!skipThis) {
1636 return;
1637 }
1638 Environment env(gate, circuit_, &builder_);
1639 GateRef thisValue = acc_.GetValueIn(gate, 0);
1640 ElementsKind kind = acc_.TryGetArrayElementsKind(thisValue);
1641 if (Elements::IsHole(kind)) {
1642 return;
1643 }
1644 if (!Uncheck()) {
1645 builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + 1), builder_.IntPtr(static_cast<int64_t>(id)));
1646 }
1647 builder_.BuiltinPrototypeHClassCheck(thisValue, BuiltinTypeId::ARRAY, kind, false);
1648 builder_.StableArrayCheck(thisValue, kind, ArrayMetaDataAccessor::Mode::LOAD_ELEMENT);
1649 GateRef callBackFn = acc_.GetValueIn(gate, 1);
1650 builder_.IsCallableCheck(callBackFn);
1651 if (EnableTrace()) {
1652 AddTraceLogs(gate, id);
1653 }
1654 uint32_t pcOffset = acc_.TryGetPcOffset(gate);
1655 GateRef frameState = acc_.GetFrameState(gate);
1656 GateRef ret = Circuit::NullGate();
1657 if (argc == 1) {
1658 ret = builder_.ArrayMap(thisValue, callBackFn, builder_.UndefineConstant(), frameState, pcOffset);
1659 } else {
1660 ret = builder_.ArrayMap(
1661 thisValue, callBackFn, acc_.GetValueIn(gate, 2), frameState, pcOffset); //2: provide usingThis
1662 }
1663 acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret);
1664 }
1665
TryInlineArraySome(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)1666 void NativeInlineLowering::TryInlineArraySome(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis)
1667 {
1668 if (argc == 0) {
1669 return;
1670 }
1671 if (!skipThis) {
1672 return;
1673 }
1674 Environment env(gate, circuit_, &builder_);
1675 GateRef thisValue = acc_.GetValueIn(gate, 0);
1676 ElementsKind kind = acc_.TryGetArrayElementsKind(thisValue);
1677 if (Elements::IsHole(kind)) {
1678 return;
1679 }
1680 if (!Uncheck()) {
1681 builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + 1), builder_.IntPtr(static_cast<int64_t>(id)));
1682 }
1683 builder_.BuiltinPrototypeHClassCheck(thisValue, BuiltinTypeId::ARRAY, kind, false);
1684 builder_.StableArrayCheck(thisValue, kind, ArrayMetaDataAccessor::Mode::LOAD_ELEMENT);
1685 GateRef callBackFn = acc_.GetValueIn(gate, 1);
1686 builder_.IsCallableCheck(callBackFn);
1687 if (EnableTrace()) {
1688 AddTraceLogs(gate, id);
1689 }
1690 uint32_t pcOffset = acc_.TryGetPcOffset(gate);
1691 GateRef ret = Circuit::NullGate();
1692 if (argc == 1) {
1693 ret = builder_.ArraySome(thisValue, callBackFn, builder_.UndefineConstant(), pcOffset);
1694 } else {
1695 ret = builder_.ArraySome(thisValue, callBackFn, acc_.GetValueIn(gate, 2), pcOffset); //2: provide usingThis
1696 }
1697 acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret);
1698 }
1699
TryInlineArrayEvery(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)1700 void NativeInlineLowering::TryInlineArrayEvery(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis)
1701 {
1702 if (argc == 0) {
1703 return;
1704 }
1705 if (!skipThis) {
1706 return;
1707 }
1708 Environment env(gate, circuit_, &builder_);
1709 GateRef thisValue = acc_.GetValueIn(gate, 0);
1710 ElementsKind kind = acc_.TryGetArrayElementsKind(thisValue);
1711 if (Elements::IsHole(kind)) {
1712 return;
1713 }
1714 if (!Uncheck()) {
1715 builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + 1), builder_.IntPtr(static_cast<int64_t>(id)));
1716 }
1717 builder_.BuiltinPrototypeHClassCheck(thisValue, BuiltinTypeId::ARRAY, kind, false);
1718 builder_.StableArrayCheck(thisValue, kind, ArrayMetaDataAccessor::Mode::LOAD_ELEMENT);
1719 GateRef callBackFn = acc_.GetValueIn(gate, 1);
1720 builder_.IsCallableCheck(callBackFn);
1721 if (EnableTrace()) {
1722 AddTraceLogs(gate, id);
1723 }
1724 uint32_t pcOffset = acc_.TryGetPcOffset(gate);
1725 GateRef ret = Circuit::NullGate();
1726 if (argc == 1) {
1727 ret = builder_.ArrayEvery(thisValue, callBackFn, builder_.UndefineConstant(), pcOffset);
1728 } else {
1729 ret = builder_.ArrayEvery(thisValue, callBackFn, acc_.GetValueIn(gate, 2), pcOffset); //2: provide usingThis
1730 }
1731 acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret);
1732 }
1733
TryInlineArrayPop(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)1734 void NativeInlineLowering::TryInlineArrayPop(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis)
1735 {
1736 if (!skipThis) {
1737 return;
1738 }
1739 Environment env(gate, circuit_, &builder_);
1740 if (!Uncheck()) {
1741 builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + 1), builder_.IntPtr(static_cast<int64_t>(id)));
1742 }
1743 GateRef thisValue = acc_.GetValueIn(gate, 0);
1744 ElementsKind kind = acc_.TryGetArrayElementsKind(thisValue);
1745 builder_.BuiltinPrototypeHClassCheck(thisValue, BuiltinTypeId::ARRAY, kind, false);
1746 builder_.StableArrayCheck(thisValue, kind, ArrayMetaDataAccessor::Mode::LOAD_ELEMENT);
1747 if (EnableTrace()) {
1748 AddTraceLogs(gate, id);
1749 }
1750 GateRef ret = builder_.ArrayPop(thisValue, acc_.GetFrameState(gate));
1751 acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret);
1752 }
1753
TryInlineArraySlice(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)1754 void NativeInlineLowering::TryInlineArraySlice(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis)
1755 {
1756 if (!skipThis) {
1757 return;
1758 }
1759 Environment env(gate, circuit_, &builder_);
1760 GateRef thisValue = acc_.GetValueIn(gate, 0);
1761 ElementsKind kind = acc_.TryGetArrayElementsKind(thisValue);
1762 builder_.BuiltinPrototypeHClassCheck(thisValue, BuiltinTypeId::ARRAY, kind, false);
1763 builder_.StableArrayCheck(thisValue, kind, ArrayMetaDataAccessor::Mode::LOAD_ELEMENT);
1764 GateRef frameState = acc_.GetFrameState(gate);
1765 if (!Uncheck()) {
1766 builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + 1), builder_.IntPtr(static_cast<int64_t>(id)));
1767 }
1768 GateRef ret = Circuit::NullGate();
1769 if (argc == 0) {
1770 ret = builder_.ArraySlice(thisValue, builder_.UndefineConstant(), builder_.UndefineConstant(), frameState);
1771 } else if (argc == 1) {
1772 GateRef startIndex = acc_.GetValueIn(gate, 1);
1773 builder_.DeoptCheck(builder_.TaggedIsInt(startIndex), acc_.GetFrameState(gate), DeoptType::INDEXNOTINT);
1774 ret = builder_.ArraySlice(thisValue, startIndex, builder_.UndefineConstant(), frameState);
1775 } else {
1776 GateRef startIndex = acc_.GetValueIn(gate, 1);
1777 GateRef endIndex = acc_.GetValueIn(gate, 2);
1778 builder_.DeoptCheck(builder_.TaggedIsInt(startIndex), acc_.GetFrameState(gate), DeoptType::INDEXNOTINT);
1779 builder_.DeoptCheck(builder_.TaggedIsInt(endIndex), acc_.GetFrameState(gate), DeoptType::INDEXNOTINT);
1780 ret = builder_.ArraySlice(thisValue, startIndex, endIndex, frameState);
1781 }
1782 if (EnableTrace()) {
1783 AddTraceLogs(gate, id);
1784 }
1785 acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret);
1786 }
1787
TryInlineArraySort(GateRef gate,size_t argc,BuiltinsStubCSigns::ID id,bool skipThis)1788 void NativeInlineLowering::TryInlineArraySort(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis)
1789 {
1790 if (!skipThis) {
1791 return;
1792 }
1793 if (argc > 1) {
1794 return;
1795 }
1796 Environment env(gate, circuit_, &builder_);
1797 if (argc == 1) {
1798 GateRef callBackFn = acc_.GetValueIn(gate, 1);
1799 auto fnType = acc_.GetGateType(callBackFn);
1800 if (!fnType.IsUndefinedType()) {
1801 return;
1802 }
1803 }
1804 GateRef thisValue = acc_.GetValueIn(gate, 0);
1805 ElementsKind kind = acc_.TryGetArrayElementsKind(thisValue);
1806 if (Elements::IsHole(kind)) {
1807 return;
1808 }
1809 if (!Uncheck()) {
1810 builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + 1), builder_.IntPtr(static_cast<int64_t>(id)));
1811 }
1812 GateRef ret = Circuit::NullGate();
1813
1814 builder_.BuiltinPrototypeHClassCheck(thisValue, BuiltinTypeId::ARRAY, kind, false);
1815 builder_.StableArrayCheck(thisValue, kind, ArrayMetaDataAccessor::Mode::LOAD_ELEMENT);
1816 ret = builder_.ArraySort(thisValue, builder_.UndefineConstant());
1817 acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret);
1818 }
1819
1820 } // namespace panda::ecmascript
1821