• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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/typed_native_inline_lowering.h"
16 #include "ecmascript/compiler/builtins/builtins_array_stub_builder.h"
17 #include "ecmascript/compiler/builtins/builtins_object_stub_builder.h"
18 #include "ecmascript/compiler/circuit_arg_indices.h"
19 #include "ecmascript/compiler/new_object_stub_builder.h"
20 #include "ecmascript/compiler/type_info_accessors.h"
21 #include "ecmascript/global_env.h"
22 #include "ecmascript/interpreter/interpreter-inl.h"
23 #include "ecmascript/jit/jit.h"
24 #include "ecmascript/js_array_iterator.h"
25 #include "ecmascript/js_date.h"
26 #include "ecmascript/js_primitive_ref.h"
27 
28 namespace panda::ecmascript::kungfu {
VisitGate(GateRef gate)29 GateRef TypedNativeInlineLowering::VisitGate(GateRef gate)
30 {
31     auto op = acc_.GetOpCode(gate);
32     switch (op) {
33         case OpCode::MATH_COS:
34             LowerGeneralUnaryMath(gate, RTSTUB_ID(FloatCos));
35             break;
36         case OpCode::MATH_COSH:
37             LowerGeneralUnaryMath(gate, RTSTUB_ID(FloatCosh));
38             break;
39         case OpCode::MATH_SIN:
40             LowerGeneralUnaryMath(gate, RTSTUB_ID(FloatSin));
41             break;
42         case OpCode::MATH_LOG:
43             LowerGeneralUnaryMath(gate, RTSTUB_ID(FloatLog));
44             break;
45         case OpCode::MATH_LOG2:
46             LowerGeneralUnaryMath(gate, RTSTUB_ID(FloatLog2));
47             break;
48         case OpCode::MATH_LOG10:
49             LowerGeneralUnaryMath(gate, RTSTUB_ID(FloatLog10));
50             break;
51         case OpCode::MATH_LOG1P:
52             LowerGeneralUnaryMath(gate, RTSTUB_ID(FloatLog1p));
53             break;
54         case OpCode::MATH_EXP:
55             LowerMathExp(gate);
56             break;
57         case OpCode::MATH_EXPM1:
58             LowerGeneralUnaryMath(gate, RTSTUB_ID(FloatExpm1));
59             break;
60         case OpCode::MATH_SINH:
61             LowerGeneralUnaryMath(gate, RTSTUB_ID(FloatSinh));
62             break;
63         case OpCode::MATH_ASINH:
64             LowerGeneralUnaryMath(gate, RTSTUB_ID(FloatAsinh));
65             break;
66         case OpCode::MATH_TAN:
67             LowerGeneralUnaryMath(gate, RTSTUB_ID(FloatTan));
68             break;
69         case OpCode::MATH_ATAN:
70             LowerGeneralUnaryMath(gate, RTSTUB_ID(FloatAtan));
71             break;
72         case OpCode::MATH_TANH:
73             LowerGeneralUnaryMath(gate, RTSTUB_ID(FloatTanh));
74             break;
75         case OpCode::MATH_ACOS:
76             LowerGeneralUnaryMath(gate, RTSTUB_ID(FloatAcos));
77             break;
78         case OpCode::MATH_ASIN:
79             LowerGeneralUnaryMath(gate, RTSTUB_ID(FloatAsin));
80             break;
81         case OpCode::MATH_ATANH:
82             LowerGeneralUnaryMath(gate, RTSTUB_ID(FloatAtanh));
83             break;
84         case OpCode::MATH_ACOSH:
85             LowerGeneralUnaryMath(gate, RTSTUB_ID(FloatAcosh));
86             break;
87         case OpCode::MATH_ATAN2:
88             LowerMathAtan2(gate);
89             break;
90         case OpCode::MATH_ABS:
91             LowerAbs(gate);
92             break;
93         case OpCode::MATH_ABS_INT32:
94             LowerIntAbs(gate);
95             break;
96         case OpCode::MATH_ABS_DOUBLE:
97             LowerDoubleAbs(gate);
98             break;
99         case OpCode::MATH_TRUNC:
100             LowerTrunc(gate);
101             break;
102         case OpCode::MATH_POW:
103             LowerMathPow(gate);
104             break;
105         case OpCode::MATH_CBRT:
106             LowerGeneralUnaryMath(gate, RTSTUB_ID(FloatCbrt));
107             break;
108         case OpCode::MATH_SIGN:
109             LowerMathSignInt(gate);
110             break;
111         case OpCode::MATH_SIGN_TAGGED:
112             LowerMathSignTagged(gate);
113             break;
114         case OpCode::MATH_MIN:
115             LowerMinMax<false>(gate);
116             break;
117         case OpCode::MATH_MAX:
118             LowerMinMax<true>(gate);
119             break;
120         case OpCode::MATH_MIN_INT32:
121             LowerIntMinMax<false>(gate);
122             break;
123         case OpCode::MATH_MAX_INT32:
124             LowerIntMinMax<true>(gate);
125             break;
126         case OpCode::MATH_MIN_DOUBLE:
127             LowerDoubleMinMax<false>(gate);
128             break;
129         case OpCode::MATH_MAX_DOUBLE:
130             LowerDoubleMinMax<true>(gate);
131             break;
132         case OpCode::MATH_CLZ32_DOUBLE:
133             LowerClz32Float64(gate);
134             break;
135         case OpCode::MATH_CLZ32_INT32:
136             LowerClz32Int32(gate);
137             break;
138         case OpCode::MATH_SQRT:
139             LowerMathSqrt(gate);
140             break;
141         case OpCode::MATH_ROUND:
142             LowerTaggedRounding(gate);
143             break;
144         case OpCode::MATH_ROUND_DOUBLE:
145         case OpCode::MATH_FROUND:
146             LowerDoubleRounding(gate);
147             break;
148         case OpCode::MATH_CEIL:
149             LowerMathCeilFloor<true>(gate);
150             break;
151         case OpCode::MATH_FLOOR:
152             LowerMathCeilFloor<false>(gate);
153             break;
154         case OpCode::MATH_IMUL:
155             LowerMathImul(gate);
156             break;
157         case OpCode::NEW_NUMBER:
158             LowerNewNumber(gate);
159             break;
160         case OpCode::GLOBAL_IS_FINITE:
161             LowerGlobalIsFinite(gate);
162             break;
163         case OpCode::GLOBAL_IS_NAN:
164             LowerGlobalIsNan(gate);
165             break;
166         case OpCode::DATA_VIEW_GET:
167             LowerDataViewProtoFunc(gate, DataViewProtoFunc::GET);
168             break;
169         case OpCode::DATA_VIEW_SET:
170             LowerDataViewProtoFunc(gate, DataViewProtoFunc::SET);
171             break;
172         case OpCode::ARRAY_BUFFER_IS_VIEW:
173             LowerArrayBufferIsView(gate);
174             break;
175         case OpCode::BIGINT_ASINTN:
176             LowerBigIntAsIntN<false>(gate);
177             break;
178         case OpCode::BIGINT_ASUINTN:
179             LowerBigIntAsIntN<true>(gate);
180             break;
181         case OpCode::NUMBER_IS_FINITE:
182             LowerNumberIsFinite(gate);
183             break;
184         case OpCode::NUMBER_IS_INTEGER:
185         case OpCode::NUMBER_IS_SAFEINTEGER:
186             LowerNumberIsInteger(gate, op);
187             break;
188         case OpCode::NUMBER_IS_NAN:
189             LowerNumberIsNaN(gate);
190             break;
191         case OpCode::NUMBER_PARSE_FLOAT:
192             LowerNumberParseFloat(gate);
193             break;
194         case OpCode::NUMBER_PARSE_INT:
195             LowerNumberParseInt(gate);
196             break;
197         case OpCode::MAP_GET:
198             LowerToCommonStub(gate, CommonStubCSigns::JSMapGet);
199             break;
200         case OpCode::DATE_GET_TIME:
201             LowerDateGetTime(gate);
202             break;
203         case OpCode::MAP_HAS:
204             LowerToCommonStub(gate, CommonStubCSigns::JSMapHas);
205             break;
206         case OpCode::MAP_KEYS:
207             LowerToCommonStub(gate, CommonStubCSigns::JSMapKeys);
208             break;
209         case OpCode::MAP_VALUES:
210             LowerToCommonStub(gate, CommonStubCSigns::JSMapValues);
211             break;
212         case OpCode::MAP_ENTRIES:
213             LowerToCommonStub(gate, CommonStubCSigns::CreateJSMapIterator);
214             break;
215         case OpCode::SET_HAS:
216             LowerToCommonStub(gate, CommonStubCSigns::JSSetHas);
217             break;
218         case OpCode::SET_ADD:
219             LowerToCommonStub(gate, CommonStubCSigns::JSSetAdd);
220             break;
221         case OpCode::DATE_NOW:
222             LowerGeneralWithoutArgs(gate, RTSTUB_ID(CallDateNow));
223             break;
224         case OpCode::TYPED_ARRAY_ENTRIES:
225             LowerTypedArrayIterator(gate, CommonStubCSigns::CreateJSTypedArrayEntries,
226                                     IterationKind::KEY_AND_VALUE);
227             break;
228         case OpCode::TYPED_ARRAY_KEYS:
229             LowerTypedArrayIterator(gate, CommonStubCSigns::CreateJSTypedArrayKeys,
230                                     IterationKind::KEY);
231             break;
232         case OpCode::TYPED_ARRAY_VALUES:
233             LowerTypedArrayIterator(gate, CommonStubCSigns::CreateJSTypedArrayValues,
234                                     IterationKind::VALUE);
235             break;
236         case OpCode::MAP_DELETE:
237             LowerToCommonStub(gate, CommonStubCSigns::JSMapDelete);
238             break;
239         case OpCode::SET_DELETE:
240             LowerToCommonStub(gate, CommonStubCSigns::JSSetDelete);
241             break;
242         case OpCode::SET_VALUES:
243             LowerToCommonStub(gate, CommonStubCSigns::CreateJSSetIterator);
244             break;
245         case OpCode::SET_ENTRIES:
246             LowerToCommonStub(gate, CommonStubCSigns::JSSetEntries);
247             break;
248         case OpCode::BIGINT_CONSTRUCTOR:
249             LowerBigIntConstructor(gate);
250             break;
251         case OpCode::BIGINT_CONSTRUCTOR_INT32:
252             LowerBigIntConstructorInt32<true>(gate);
253             break;
254         case OpCode::BIGINT_CONSTRUCTOR_UINT32:
255             LowerBigIntConstructorInt32<false>(gate);
256             break;
257         case OpCode::STRING_CHAR_CODE_AT:
258             LowerStringCharCodeAt(gate);
259             break;
260         case OpCode::STRING_SUB_STRING:
261             LowerStringSubstring(gate);
262             break;
263         case OpCode::STRING_SUB_STR:
264             LowerStringSubStr(gate);
265             break;
266         case OpCode::STRING_SLICE:
267             LowerStringSlice(gate);
268             break;
269         case OpCode::OBJECT_IS:
270             LowerObjectIs(gate);
271             break;
272         case OpCode::OBJECT_GET_PROTOTYPE_OF:
273             LowerObjectGetPrototypeOf(gate);
274             break;
275         case OpCode::OBJECT_CREATE:
276             LowerObjectCreate(gate);
277             break;
278         case OpCode::OBJECT_IS_PROTOTYPE_OF:
279             LowerObjectIsPrototypeOf(gate);
280             break;
281         case OpCode::OBJECT_HAS_OWN_PROPERTY:
282             LowerObjectHasOwnProperty(gate);
283             break;
284         case OpCode::REFLECT_GET_PROTOTYPE_OF:
285             LowerReflectGetPrototypeOf(gate);
286             break;
287         case OpCode::REFLECT_GET:
288             LowerReflectGet(gate);
289             break;
290         case OpCode::REFLECT_HAS:
291             LowerReflectHas(gate);
292             break;
293         case OpCode::REFLECT_CONSTRUCT:
294             LowerReflectConstruct(gate);
295             break;
296         case OpCode::REFLECT_APPLY:
297             LowerReflectApply(gate);
298             break;
299         case OpCode::FUNCTION_PROTOTYPE_APPLY:
300             LowerFunctionPrototypeApply(gate);
301             break;
302         case OpCode::FUNCTION_PROTOTYPE_BIND:
303             LowerFunctionPrototypeBind(gate);
304             break;
305         case OpCode::FUNCTION_PROTOTYPE_CALL:
306             LowerFunctionPrototypeCall(gate);
307             break;
308         case OpCode::ARRAY_INCLUDES_INDEXOF:
309             LowerArrayIncludesIndexOf(gate);
310             break;
311         case OpCode::ARRAY_ITERATOR_BUILTIN:
312             LowerArrayIteratorBuiltin(gate);
313             break;
314         case OpCode::ARRAY_FOR_EACH:
315             LowerArrayForEach(gate);
316             break;
317         case OpCode::ARRAY_FIND_OR_FINDINDEX:
318             LowerArrayFindOrFindIndex(gate);
319             break;
320         case OpCode::ARRAY_FILTER:
321             LowerArrayFilter(gate);
322             break;
323         case OpCode::ARRAY_MAP:
324             LowerArrayMap(gate);
325             break;
326         case OpCode::ARRAY_SOME:
327             LowerArraySome(gate);
328             break;
329         case OpCode::ARRAY_EVERY:
330             LowerArrayEvery(gate);
331             break;
332         case OpCode::ARRAY_POP:
333             LowerArrayPop(gate);
334             break;
335         case OpCode::ARRAY_PUSH:
336             LowerArrayPush(gate);
337             break;
338         case OpCode::ARRAY_SLICE:
339             LowerArraySlice(gate);
340             break;
341         case OpCode::ARRAY_SORT:
342             LowerArraySort(gate);
343             break;
344         default:
345             break;
346     }
347     return Circuit::NullGate();
348 }
349 
350 template <bool IS_CEIL>
LowerMathCeilFloor(GateRef gate)351 void TypedNativeInlineLowering::LowerMathCeilFloor(GateRef gate)
352 {
353     if (builder_.GetCompilationConfig()->IsAArch64()) {
354         LowerMathCeilFloorWithIntrinsic<IS_CEIL>(gate);
355     } else {
356         LowerMathCeilFloorWithRuntimeCall<IS_CEIL>(gate);
357     }
358 }
359 
360 template <bool IS_CEIL>
LowerMathCeilFloorWithIntrinsic(GateRef gate)361 void TypedNativeInlineLowering::LowerMathCeilFloorWithIntrinsic(GateRef gate)
362 {
363     Environment env(gate, circuit_, &builder_);
364     DEFVALUE(result, (&builder_), VariableType::FLOAT64(), builder_.NanValue());
365     GateRef arg = acc_.GetValueIn(gate, 0);
366 
367     if constexpr (IS_CEIL) {
368         result = builder_.DoubleCeil(arg);
369     } else {
370         result = builder_.DoubleFloor(arg);
371     }
372     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result);
373 }
374 
375 template <bool IS_CEIL>
LowerMathCeilFloorWithRuntimeCall(GateRef gate)376 void TypedNativeInlineLowering::LowerMathCeilFloorWithRuntimeCall(GateRef gate)
377 {
378     Environment env(gate, circuit_, &builder_);
379     DEFVALUE(result, (&builder_), VariableType::FLOAT64(), builder_.NanValue());
380     GateRef arg = acc_.GetValueIn(gate, 0);
381     GateRef glue = acc_.GetGlueFromArgList();
382 
383     if constexpr (IS_CEIL) {
384         result = builder_.CallNGCRuntime(glue, RTSTUB_ID(FloatCeil), Gate::InvalidGateRef, {arg}, gate);
385     } else {
386         result = builder_.CallNGCRuntime(glue, RTSTUB_ID(FloatFloor), Gate::InvalidGateRef, {arg}, gate);
387     }
388     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result);
389 }
390 
AllocateArrayIterator(GateRef glue,GateRef self,GateRef iteratorHClass,IterationKind iterationKind)391 GateRef TypedNativeInlineLowering::AllocateArrayIterator(GateRef glue,
392                                                          GateRef self,
393                                                          GateRef iteratorHClass,
394                                                          IterationKind iterationKind)
395 {
396     GateRef emptyArray = builder_.GetGlobalConstantValue(ConstantIndex::EMPTY_ARRAY_OBJECT_INDEX);
397     GateRef kind = builder_.Int32(static_cast<int32_t>(iterationKind));
398 
399     builder_.StartAllocate();
400 
401     GateRef iterator = builder_.HeapAlloc(glue, builder_.IntPtr(JSArrayIterator::SIZE),
402         GateType::TaggedValue(), RegionSpaceFlag::IN_YOUNG_SPACE);
403 
404     builder_.StoreConstOffset(VariableType::JS_POINTER(), iterator, TaggedObject::HCLASS_OFFSET,
405                               iteratorHClass, MemoryAttribute::NeedBarrierAndAtomic());
406     builder_.StoreConstOffset(VariableType::INT64(), iterator, JSObject::HASH_OFFSET,
407         builder_.Int64(JSTaggedValue(0).GetRawData()));
408     builder_.StoreConstOffset(VariableType::INT64(), iterator, JSObject::PROPERTIES_OFFSET, emptyArray);
409     builder_.StoreConstOffset(VariableType::INT64(), iterator, JSObject::ELEMENTS_OFFSET, emptyArray);
410 
411     builder_.StoreConstOffset(VariableType::JS_ANY(), iterator, JSArrayIterator::ITERATED_ARRAY_OFFSET, self);
412     builder_.StoreConstOffset(VariableType::INT32(), iterator, JSArrayIterator::NEXT_INDEX_OFFSET, builder_.Int32(0));
413     builder_.StoreConstOffset(VariableType::INT32(), iterator, JSArrayIterator::BIT_FIELD_OFFSET, kind);
414 
415     GateRef result = builder_.FinishAllocate(iterator);
416     builder_.SubCfgExit();
417 
418     return result;
419 }
420 
LowerTypedArrayIterator(GateRef gate,CommonStubCSigns::ID index,IterationKind iterationKind)421 void TypedNativeInlineLowering::LowerTypedArrayIterator(GateRef gate, CommonStubCSigns::ID index,
422                                                         IterationKind iterationKind)
423 {
424     Environment env(gate, circuit_, &builder_);
425 
426     GateRef glue = acc_.GetGlueFromArgList();
427     GateRef self = acc_.GetValueIn(gate, 0);
428 
429     DEFVALUE(result, (&builder_), VariableType::JS_ANY(), builder_.Undefined());
430 
431     Label selfExistsLabel(&env);
432     Label isHeapObjectLabel(&env);
433     Label isTypedArrayLabel(&env);
434     Label selfValidLabel(&env);
435     Label selfInvalidLabel(&env);
436     Label exit(&env);
437 
438     GateRef selfExists = builder_.TaggedIsNotUndefinedAndNullAndHole(self);
439     BRANCH_CIR(selfExists, &selfExistsLabel, &selfInvalidLabel);
440     builder_.Bind(&selfExistsLabel);
441 
442     GateRef isHeapObject = builder_.TaggedIsHeapObject(self);
443     BRANCH_CIR(isHeapObject, &isHeapObjectLabel, &selfInvalidLabel);
444     builder_.Bind(&isHeapObjectLabel);
445 
446     GateRef isTypedArray = builder_.IsTypedArray(self);
447     BRANCH_CIR(isTypedArray, &isTypedArrayLabel, &selfInvalidLabel);
448     builder_.Bind(&isTypedArrayLabel);
449 
450     GateRef hasNoConstructor = builder_.BoolNot(builder_.HasConstructor(self));
451     BRANCH_CIR(hasNoConstructor, &selfValidLabel, &selfInvalidLabel);
452     builder_.Bind(&selfValidLabel);
453     {
454         GateRef glueGlobalEnvOffset = builder_.IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env.Is32Bit()));
455         GateRef glueGlobalEnv = builder_.Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset);
456         GateRef prototype = builder_.GetGlobalEnvValue(VariableType::JS_POINTER(), glueGlobalEnv,
457                                                        GlobalEnv::ARRAY_ITERATOR_PROTOTYPE_INDEX);
458 
459         GateRef iteratorHClass = builder_.GetGlobalConstantValue(ConstantIndex::JS_ARRAY_ITERATOR_CLASS_INDEX);
460         GateRef offset = builder_.IntPtr(JSHClass::PROTOTYPE_OFFSET);
461         builder_.Store(VariableType::JS_POINTER(), glue, iteratorHClass, offset, prototype);
462 
463         result = AllocateArrayIterator(glue, self, iteratorHClass, iterationKind);
464         builder_.Jump(&exit);
465     }
466 
467     builder_.Bind(&selfInvalidLabel);
468     {
469         result = builder_.CallStub(glue, gate, index, { glue, self });
470         builder_.Jump(&exit);
471     }
472     builder_.Bind(&exit);
473     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result);
474 }
475 
LowerGlobalDoubleIsFinite(GateRef value)476 GateRef TypedNativeInlineLowering::LowerGlobalDoubleIsFinite(GateRef value)
477 {
478     // set the sign bit to 0 by shift left then right.
479     auto temp = builder_.Int64LSL(builder_.CastDoubleToInt64(value), builder_.Int64(1));
480     auto res = builder_.Int64LSR(temp, builder_.Int64(1));
481     auto abs = builder_.CastInt64ToFloat64(res);
482     auto result = builder_.DoubleLessThan(abs, builder_.Double(base::POSITIVE_INFINITY));
483     return result;
484 }
485 
LowerGlobalTNumberIsFinite(GateRef value)486 GateRef TypedNativeInlineLowering::LowerGlobalTNumberIsFinite(GateRef value)
487 {
488     ASSERT(!acc_.GetGateType(value).IsNJSValueType());
489     DEFVALUE(result, (&builder_), VariableType::BOOL(), builder_.Boolean(true));
490 
491     Label isInt(&builder_);
492     Label notInt(&builder_);
493     Label exit(&builder_);
494     builder_.Branch(builder_.TaggedIsInt(value), &isInt, &notInt);
495     builder_.Bind(&isInt);
496     {
497         result = builder_.Boolean(true);
498         builder_.Jump(&exit);
499     }
500     builder_.Bind(&notInt);
501     {
502         result = LowerGlobalDoubleIsFinite(value);
503         builder_.Jump(&exit);
504     }
505     builder_.Bind(&exit);
506     return *result;
507 }
508 
LowerGlobalIsFinite(GateRef gate)509 void TypedNativeInlineLowering::LowerGlobalIsFinite(GateRef gate)
510 {
511     GateRef value = acc_.GetValueIn(gate, 0);
512     Environment env(gate, circuit_, &builder_);
513     GateRef result = LowerGlobalDoubleIsFinite(value);
514 
515     acc_.ReplaceGate(gate, builder_.GetStateDepend(), result);
516 }
517 
LowerGlobalTNumberIsNan(GateRef value)518 GateRef TypedNativeInlineLowering::LowerGlobalTNumberIsNan(GateRef value)
519 {
520     ASSERT(!acc_.GetGateType(value).IsNJSValueType());
521     DEFVALUE(result, (&builder_), VariableType::BOOL(), builder_.Boolean(false));
522 
523     Label isInt(&builder_);
524     Label notInt(&builder_);
525     Label exit(&builder_);
526     builder_.Branch(builder_.TaggedIsInt(value), &isInt, &notInt);
527     builder_.Bind(&isInt);
528     {
529         result = builder_.Boolean(false);
530         builder_.Jump(&exit);
531     }
532     builder_.Bind(&notInt);
533     {
534         result = builder_.DoubleIsNAN(value);
535         builder_.Jump(&exit);
536     }
537     builder_.Bind(&exit);
538     return *result;
539 }
540 
LowerGlobalIsNan(GateRef gate)541 void TypedNativeInlineLowering::LowerGlobalIsNan(GateRef gate)
542 {
543     GateRef value = acc_.GetValueIn(gate, 0);
544     Environment env(gate, circuit_, &builder_);
545     GateRef result = builder_.DoubleIsNAN(value);
546 
547     acc_.ReplaceGate(gate, builder_.GetStateDepend(), result);
548 }
549 
LowerMathPow(GateRef gate)550 void TypedNativeInlineLowering::LowerMathPow(GateRef gate)
551 {
552     Environment env(gate, circuit_, &builder_);
553     GateRef base = acc_.GetValueIn(gate, 0);
554     GateRef exp = acc_.GetValueIn(gate, 1);
555     Label exit(&builder_);
556     Label notNan(&builder_);
557 
558     auto nanValue = builder_.NanValue();
559     DEFVALUE(result, (&builder_), VariableType::FLOAT64(), nanValue);
560 
561     const double doubleOne = 1.0;
562     // Base is 1.0, exponent is inf => NaN
563     // Exponent is not finit, if is NaN or is Inf
564     GateRef resultIsNan = LogicOrBuilder(&env)
565         .Or(builder_.DoubleIsNAN(exp))
566         .Or(LogicAndBuilder(&env)
567             .And(builder_.DoubleEqual(builder_.FAbs(base), builder_.Double(doubleOne)))
568             .And(builder_.DoubleIsINF(exp))
569             .Done())
570         .Done();
571 
572     BRANCH_CIR(resultIsNan, &exit, &notNan);
573     builder_.Bind(&notNan);
574     {
575         GateRef glue = acc_.GetGlueFromArgList();
576         result = builder_.CallNGCRuntime(glue, RTSTUB_ID(FloatPow), Gate::InvalidGateRef, {base, exp}, gate);
577         builder_.Jump(&exit);
578     }
579 
580     builder_.Bind(&exit);
581     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result);
582 }
583 
LowerMathExp(GateRef gate)584 void TypedNativeInlineLowering::LowerMathExp(GateRef gate)
585 {
586 #ifdef SUPPORT_LLVM_INTRINSICS_WITH_CALLS
587     Environment env(gate, circuit_, &builder_);
588     constexpr double one = 1.0;
589     GateRef base = builder_.Double(std::exp(one));
590     GateRef power = acc_.GetValueIn(gate, 0U);
591 
592     GateRef exp = builder_.DoubleExp(base, power);
593     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), exp);
594 #else
595     LowerGeneralUnaryMath(gate, RTSTUB_ID(FloatExp));
596 #endif
597 }
598 
LowerMathImul(GateRef gate)599 void TypedNativeInlineLowering::LowerMathImul(GateRef gate)
600 {
601     Environment env(gate, circuit_, &builder_);
602     GateRef val1 = acc_.GetValueIn(gate, 0);
603     GateRef val2 = acc_.GetValueIn(gate, 1);
604     ASSERT(acc_.GetGateType(val1).IsNJSValueType() && acc_.GetGateType(val2).IsNJSValueType());
605 
606     GateRef result = builder_.Int32Mul(val1, val2);
607     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
608 }
609 
LowerGeneralUnaryMath(GateRef gate,RuntimeStubCSigns::ID stubId)610 void TypedNativeInlineLowering::LowerGeneralUnaryMath(GateRef gate, RuntimeStubCSigns::ID stubId)
611 {
612     Environment env(gate, circuit_, &builder_);
613     GateRef value = acc_.GetValueIn(gate, 0);
614     GateRef glue = acc_.GetGlueFromArgList();
615     GateRef result = builder_.CallNGCRuntime(glue, stubId, Gate::InvalidGateRef, {value}, gate);
616     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
617 }
618 
LowerMathAtan2(GateRef gate)619 void TypedNativeInlineLowering::LowerMathAtan2(GateRef gate)
620 {
621     Environment env(gate, circuit_, &builder_);
622     GateRef y = acc_.GetValueIn(gate, 0);
623     GateRef x = acc_.GetValueIn(gate, 1);
624     GateRef glue = acc_.GetGlueFromArgList();
625     GateRef result = builder_.CallNGCRuntime(glue, RTSTUB_ID(FloatAtan2), Gate::InvalidGateRef, {y, x}, gate);
626     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
627 }
628 
629 //  Int abs : The internal representation of an integer is inverse code,
630 //  The absolute value of a negative number can be found by inverting it by adding one.
BuildIntAbs(GateRef value)631 GateRef TypedNativeInlineLowering::BuildIntAbs(GateRef value)
632 {
633     ASSERT(acc_.GetMachineType(value) == MachineType::I32);
634     if (isLiteCG_) {
635         auto temp = builder_.Int32ASR(value, builder_.Int32(JSTaggedValue::INT_SIGN_BIT_OFFSET));
636         auto res = builder_.Int32Xor(value, temp);
637         return builder_.Int32Sub(res, temp);
638     }
639     return builder_.Abs(value);
640 }
641 
642 //  Float abs : A floating-point number is composed of mantissa and exponent.
643 //  The length of mantissa will affect the precision of the number, and its sign will determine the sign of the number.
644 //  The absolute value of a floating-point number can be found by setting mantissa sign bit to 0.
BuildDoubleAbs(GateRef value)645 GateRef TypedNativeInlineLowering::BuildDoubleAbs(GateRef value)
646 {
647     ASSERT(acc_.GetMachineType(value) == MachineType::F64);
648     if (isLiteCG_) {
649         // set the sign bit to 0 by shift left then right.
650         auto temp = builder_.Int64LSL(builder_.CastDoubleToInt64(value), builder_.Int64(1));
651         auto res = builder_.Int64LSR(temp, builder_.Int64(1));
652         return builder_.CastInt64ToFloat64(res);
653     }
654     return builder_.FAbs(value);
655 }
656 
BuildTNumberAbs(GateRef param)657 GateRef TypedNativeInlineLowering::BuildTNumberAbs(GateRef param)
658 {
659     ASSERT(!acc_.GetGateType(param).IsNJSValueType());
660     Label entry(&builder_);
661     builder_.SubCfgEntry(&entry);
662     DEFVALUE(result, (&builder_), VariableType::JS_ANY(), builder_.HoleConstant());
663     Label exit(&builder_);
664     Label isInt(&builder_);
665     Label notInt(&builder_);
666     Label isIntMin(&builder_);
667     Label isResultInt(&builder_);
668     Label intExit(&builder_);
669     BRANCH_CIR(builder_.TaggedIsInt(param), &isInt, &notInt);
670     builder_.Bind(&isInt);
671     {
672         auto value = builder_.GetInt32OfTInt(param);
673         BRANCH_CIR(builder_.Equal(value, builder_.Int32(INT32_MIN)), &isIntMin, &isResultInt);
674         builder_.Bind(&isResultInt);
675         {
676             result = builder_.Int32ToTaggedPtr(BuildIntAbs(value));
677             builder_.Jump(&intExit);
678         }
679         builder_.Bind(&isIntMin);
680         {
681             result = builder_.DoubleToTaggedDoublePtr(builder_.Double(-static_cast<double>(INT_MIN)));
682             builder_.Jump(&intExit);
683         }
684         // Aot compiler fails without jump to intermediate label
685         builder_.Bind(&intExit);
686         builder_.Jump(&exit);
687     }
688     builder_.Bind(&notInt);
689     {
690         auto value = builder_.GetDoubleOfTDouble(param);
691         result = builder_.DoubleToTaggedDoublePtr(BuildDoubleAbs(value));
692         builder_.Jump(&exit);
693     }
694     builder_.Bind(&exit);
695     GateRef res = *result;
696     builder_.SubCfgExit();
697     return res;
698 }
699 
LowerAbs(GateRef gate)700 void TypedNativeInlineLowering::LowerAbs(GateRef gate)
701 {
702     GateRef value = acc_.GetValueIn(gate, 0);
703     Environment env(gate, circuit_, &builder_);
704     GateRef res = BuildTNumberAbs(value);
705     acc_.ReplaceGate(gate, builder_.GetStateDepend(), res);
706 }
707 
BuildRounding(GateRef gate,GateRef value,OpCode op)708 GateRef TypedNativeInlineLowering::BuildRounding(GateRef gate, GateRef value, OpCode op)
709 {
710     if (op == OpCode::MATH_ROUND || op == OpCode::MATH_ROUND_DOUBLE) {
711         Label entry(&builder_);
712         builder_.SubCfgEntry(&entry);
713         const double diff = 0.5;
714         GateRef diffValue = builder_.Double(diff);
715         const double zero = 0.0;
716         Label subOne(&builder_);
717         Label exit(&builder_);
718         Label retCeil(&builder_);
719         Label nonZero(&builder_);
720         DEFVALUE(result, (&builder_), VariableType::FLOAT64(), builder_.Double(zero));
721         // 0 <= x < 0.5, return 0
722         GateRef returnZero = builder_.BitAnd(builder_.DoubleLessThan(value, diffValue),
723             builder_.DoubleGreaterThan(value, builder_.Double(zero)));
724         BRANCH_CIR(returnZero, &exit, &nonZero);
725         builder_.Bind(&nonZero);
726         {
727             GateRef rounded;
728             if (builder_.GetCompilationConfig()->IsAArch64() && !isLiteCG_) {
729                 rounded = builder_.DoubleCeil(value);
730             } else {
731                 GateRef glue = acc_.GetGlueFromArgList();
732                 rounded = builder_.CallNGCRuntime(glue, RTSTUB_ID(FloatCeil), Gate::InvalidGateRef, {value}, gate);
733             }
734             // if ceil(x) - x > 0.5, return ceil(x) - 1
735             // else return ceil(x)
736             BRANCH_CIR(builder_.DoubleGreaterThan(builder_.DoubleSub(rounded, value), diffValue),
737                 &subOne, &retCeil);
738             builder_.Bind(&subOne);
739             {
740                 result = builder_.DoubleSub(rounded, builder_.Double(1U));
741                 builder_.Jump(&exit);
742             }
743             builder_.Bind(&retCeil);
744             result = rounded;
745             builder_.Jump(&exit);
746         }
747         builder_.Bind(&exit);
748         GateRef res = *result;
749         builder_.SubCfgExit();
750         return res;
751     } else if (op == OpCode::MATH_FROUND) {
752         return builder_.ExtFloat32ToDouble(builder_.TruncDoubleToFloat32(value));
753     } else {
754         UNREACHABLE();
755     }
756 }
757 
LowerTaggedRounding(GateRef gate)758 void TypedNativeInlineLowering::LowerTaggedRounding(GateRef gate)
759 {
760     Environment env(gate, circuit_, &builder_);
761 
762     DEFVALUE(result, (&builder_), VariableType::FLOAT64(), builder_.NanValue());
763 
764     GateRef in = acc_.GetValueIn(gate, 0);
765     Label isInt(&builder_);
766     Label isDouble(&builder_);
767     Label exit(&builder_);
768 
769     builder_.Branch(builder_.TaggedIsInt(in), &isInt, &isDouble);
770     builder_.Bind(&isInt);
771     {
772         result = builder_.GetDoubleOfTInt(in);
773         builder_.Jump(&exit);
774     }
775     builder_.Bind(&isDouble);
776     {
777         GateRef value = builder_.GetDoubleOfTDouble(in);
778         result = BuildRounding(gate, value, acc_.GetOpCode(gate));
779         builder_.Jump(&exit);
780     }
781 
782     builder_.Bind(&exit);
783     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result);
784 }
785 
LowerDoubleRounding(GateRef gate)786 void TypedNativeInlineLowering::LowerDoubleRounding(GateRef gate)
787 {
788     Environment env(gate, circuit_, &builder_);
789     GateRef value = acc_.GetValueIn(gate, 0);
790     GateRef res = BuildRounding(gate, value, acc_.GetOpCode(gate));
791     acc_.ReplaceGate(gate, builder_.GetStateDepend(), res);
792 }
793 
LowerIntAbs(GateRef gate)794 void TypedNativeInlineLowering::LowerIntAbs(GateRef gate)
795 {
796     Environment env(gate, circuit_, &builder_);
797     GateRef value = acc_.GetValueIn(gate, 0);
798     auto frameState = FindFrameState(gate);
799     builder_.DeoptCheck(builder_.NotEqual(value, builder_.Int32(INT32_MIN)), frameState, DeoptType::NOTINT3);
800     GateRef res = BuildIntAbs(value);
801     acc_.ReplaceGate(gate, builder_.GetStateDepend(), res);
802 }
803 
LowerDoubleAbs(GateRef gate)804 void TypedNativeInlineLowering::LowerDoubleAbs(GateRef gate)
805 {
806     GateRef value = acc_.GetValueIn(gate, 0);
807     Environment env(gate, circuit_, &builder_);
808     GateRef res = BuildDoubleAbs(value);
809     acc_.ReplaceGate(gate, builder_.GetStateDepend(), res);
810 }
811 
812 // for min select in1 if int1 < int2, in2 otherwise
813 template<bool IS_MAX>
BuildIntMinMax(GateRef int1,GateRef int2,GateRef in1,GateRef in2)814 GateRef TypedNativeInlineLowering::BuildIntMinMax(GateRef int1, GateRef int2, GateRef in1, GateRef in2)
815 {
816     Label entry(&builder_);
817     builder_.SubCfgEntry(&entry);
818     // int or tagged
819     VariableType type {acc_.GetMachineType(in1), acc_.GetGateType(in1)};
820     DEFVALUE(result, (&builder_), type, (IS_MAX ? in1 : in2));
821     Label left(&builder_);
822     Label exit(&builder_);
823     builder_.Branch(builder_.Int32LessThan(int1, int2), &left, &exit);
824     builder_.Bind(&left);
825     {
826         result = IS_MAX ? in2 : in1;
827         builder_.Jump(&exit);
828     }
829     builder_.Bind(&exit);
830     GateRef res = *result;
831     builder_.SubCfgExit();
832     return res;
833 }
834 
835 template<bool IS_MAX>
BuildIntMinMax(GateRef in1,GateRef in2)836 GateRef TypedNativeInlineLowering::BuildIntMinMax(GateRef in1, GateRef in2)
837 {
838     ASSERT(acc_.GetMachineType(in1) == MachineType::I32);
839     ASSERT(acc_.GetMachineType(in2) == MachineType::I32);
840     if (isLiteCG_) {
841         return BuildIntMinMax<IS_MAX>(in1, in2, in1, in2);
842     }
843     return IS_MAX ? builder_.Int32Max(in1, in2) : builder_.Int32Min(in1, in2);
844 }
845 
846 /* for min select:
847  * NaN if double1 or double2 is NaN
848  * in1 if double1 and double2 are equal and in1 is negative zero
849  * in1 if double1 < double2, in2 otherwise */
850 template<bool IS_MAX>
BuildDoubleMinMax(GateRef double1,GateRef double2,GateRef in1,GateRef in2)851 GateRef TypedNativeInlineLowering::BuildDoubleMinMax(GateRef double1, GateRef double2, GateRef in1, GateRef in2)
852 {
853     Label entry(&builder_);
854     builder_.SubCfgEntry(&entry);
855     GateRef nanValue = builder_.NanValue();
856     if (in1 != double1) { // case when in1 and in2 are tagged
857         nanValue = builder_.DoubleToTaggedDoublePtr(nanValue);
858     }
859     // double or tagged
860     VariableType type {acc_.GetMachineType(in1), acc_.GetGateType(in1)};
861     DEFVALUE(result, (&builder_), type, nanValue);
862     Label left(&builder_);
863     Label rightOrZeroOrNan(&builder_);
864     Label right(&builder_);
865     Label exit(&builder_);
866     Label equal(&builder_);
867     Label equalOrNan(&builder_);
868     builder_.Branch(builder_.DoubleLessThan(double1, double2), &left, &rightOrZeroOrNan);
869     builder_.Bind(&rightOrZeroOrNan);
870     {
871         builder_.Branch(builder_.DoubleGreaterThan(double1, double2), &right, &equalOrNan);
872         builder_.Bind(&equalOrNan);
873         {
874             builder_.Branch(builder_.DoubleEqual(double1, double2), &equal, &exit);
875             builder_.Bind(&equal);
876             {
877                 // Whether to return in1 or in2 matters only in case of 0, -0
878                 const double negZero = -0.0;
879                 GateRef negZeroValue = builder_.CastDoubleToInt64(builder_.Double(negZero));
880                 builder_.Branch(builder_.Equal(builder_.CastDoubleToInt64(double1), negZeroValue), &left, &right);
881             }
882         }
883         builder_.Bind(&right);
884         {
885             result = IS_MAX ? in1 : in2;
886             builder_.Jump(&exit);
887         }
888     }
889     builder_.Bind(&left);
890     {
891         result = IS_MAX ? in2 : in1;
892         builder_.Jump(&exit);
893     }
894     builder_.Bind(&exit);
895     GateRef res = *result;
896     builder_.SubCfgExit();
897     return res;
898 }
899 
900 template<bool IS_MAX>
BuildDoubleMinMax(GateRef in1,GateRef in2)901 GateRef TypedNativeInlineLowering::BuildDoubleMinMax(GateRef in1, GateRef in2)
902 {
903     ASSERT(acc_.GetMachineType(in1) == MachineType::F64);
904     ASSERT(acc_.GetMachineType(in2) == MachineType::F64);
905     if (!isLiteCG_ && builder_.GetCompilationConfig()->IsAArch64()) {
906         return IS_MAX ? builder_.DoubleMax(in1, in2) : builder_.DoubleMin(in1, in2);
907     }
908     return BuildDoubleMinMax<IS_MAX>(in1, in2, in1, in2);
909 }
910 
911 template<bool IS_MAX>
LowerTNumberMinMax(GateRef gate)912 void TypedNativeInlineLowering::LowerTNumberMinMax(GateRef gate)
913 {
914     Environment env(gate, circuit_, &builder_);
915     GateRef in1 = acc_.GetValueIn(gate, 0);
916     GateRef in2 = acc_.GetValueIn(gate, 1);
917     GateRef nanValue = builder_.DoubleToTaggedDoublePtr(builder_.NanValue());
918     DEFVALUE(result, (&builder_), VariableType::JS_ANY(), nanValue);
919     DEFVALUE(double1, (&builder_), VariableType::FLOAT64(), builder_.Double(0));
920     DEFVALUE(double2, (&builder_), VariableType::FLOAT64(), builder_.Double(0));
921 
922     Label isInt1(&builder_);
923     Label isInt2(&builder_);
924     Label isDouble1(&builder_);
925     Label isDouble2(&builder_);
926     Label doubleExit(&builder_);
927     Label exit(&builder_);
928     builder_.Branch(builder_.TaggedIsInt(in1), &isInt1, &isDouble1);
929     {
930         builder_.Bind(&isInt1);
931         GateRef int1 = builder_.GetInt32OfTInt(in1);
932         builder_.Branch(builder_.TaggedIsInt(in2), &isInt2, &isDouble2);
933         {
934             builder_.Bind(&isInt2);
935             GateRef int2 = builder_.GetInt32OfTInt(in2);
936             result = BuildIntMinMax<IS_MAX>(int1, int2, in1, in2);
937             builder_.Jump(&exit);
938         }
939         builder_.Bind(&isDouble2);
940         double1 = builder_.ChangeInt32ToFloat64(int1);
941         double2 = builder_.GetDoubleOfTDouble(in2);
942         builder_.Jump(&doubleExit);
943     }
944     {
945         builder_.Bind(&isDouble1);
946         double1 = builder_.GetDoubleOfTDouble(in1);
947         double2 = builder_.GetDoubleOfTNumber(in2);
948         builder_.Jump(&doubleExit);
949     }
950     builder_.Bind(&doubleExit);
951     result = BuildDoubleMinMax<IS_MAX>(*double1, *double2, in1, in2);
952     builder_.Jump(&exit);
953 
954     builder_.Bind(&exit);
955     acc_.ReplaceGate(gate, builder_.GetStateDepend(), *result);
956 }
957 
958 template<bool IS_MAX>
LowerMathMinMaxWithIntrinsic(GateRef gate)959 void TypedNativeInlineLowering::LowerMathMinMaxWithIntrinsic(GateRef gate)
960 {
961     Environment env(gate, circuit_, &builder_);
962     GateRef in1 = acc_.GetValueIn(gate, 0);
963     GateRef in2 = acc_.GetValueIn(gate, 1);
964     GateRef nanValue = builder_.DoubleToTaggedDoublePtr(builder_.NanValue());
965     DEFVALUE(result, (&builder_), VariableType::JS_ANY(), nanValue);
966 
967     Label intRes(&builder_);
968     Label doubleRes(&builder_);
969     Label exit(&builder_);
970 
971     BRANCH_CIR(LogicAndBuilder(&env).And(builder_.TaggedIsInt(in1)).And(builder_.TaggedIsInt(in2)).Done(),
972         &intRes, &doubleRes);
973     builder_.Bind(&intRes);
974     {
975         GateRef int1 = builder_.GetInt32OfTInt(in1);
976         GateRef int2 = builder_.GetInt32OfTInt(in2);
977         GateRef intRet = BuildIntMinMax<IS_MAX>(int1, int2);
978         result = builder_.Int32ToTaggedPtr(intRet);
979         builder_.Jump(&exit);
980     }
981     builder_.Bind(&doubleRes);
982     {
983         GateRef double1 = builder_.GetDoubleOfTNumber(in1);
984         GateRef double2 = builder_.GetDoubleOfTNumber(in2);
985         // LLVM supports lowering of `minimum/maximum` intrinsics on X86 only since version 17
986         // see https://github.com/llvm/llvm-project/commit/a82d27a9a6853c96f857ba0f514a78cd03bc5c35
987         if (builder_.GetCompilationConfig()->IsAArch64()) {
988             GateRef doubleRet = IS_MAX ? builder_.DoubleMax(double1, double2) : builder_.DoubleMin(double1, double2);
989             result = builder_.DoubleToTaggedDoublePtr(doubleRet);
990         } else {
991             result = BuildDoubleMinMax<IS_MAX>(double1, double2, in1, in2);
992         }
993         builder_.Jump(&exit);
994     }
995     builder_.Bind(&exit);
996     acc_.ReplaceGate(gate, builder_.GetStateDepend(), *result);
997 }
998 
999 template<bool IS_MAX>
LowerMinMax(GateRef gate)1000 void TypedNativeInlineLowering::LowerMinMax(GateRef gate)
1001 {
1002     if (isLiteCG_) {
1003         LowerTNumberMinMax<IS_MAX>(gate);
1004     } else {
1005         LowerMathMinMaxWithIntrinsic<IS_MAX>(gate);
1006     }
1007 }
1008 
1009 template<bool IS_MAX>
LowerIntMinMax(GateRef gate)1010 void TypedNativeInlineLowering::LowerIntMinMax(GateRef gate)
1011 {
1012     GateRef in1 = acc_.GetValueIn(gate, 0);
1013     GateRef in2 = acc_.GetValueIn(gate, 1);
1014     Environment env(gate, circuit_, &builder_);
1015     GateRef res = BuildIntMinMax<IS_MAX>(in1, in2);
1016     acc_.ReplaceGate(gate, builder_.GetStateDepend(), res);
1017 }
1018 
1019 template<bool IS_MAX>
LowerDoubleMinMax(GateRef gate)1020 void TypedNativeInlineLowering::LowerDoubleMinMax(GateRef gate)
1021 {
1022     GateRef in1 = acc_.GetValueIn(gate, 0);
1023     GateRef in2 = acc_.GetValueIn(gate, 1);
1024     Environment env(gate, circuit_, &builder_);
1025     GateRef res = BuildDoubleMinMax<IS_MAX>(in1, in2);
1026     acc_.ReplaceGate(gate, builder_.GetStateDepend(), res);
1027 }
1028 
FindFrameState(GateRef gate)1029 GateRef TypedNativeInlineLowering::FindFrameState(GateRef gate)
1030 {
1031     while (!acc_.HasFrameState(gate)) {
1032         ASSERT(acc_.GetDependCount(gate) > 0);
1033         gate = acc_.GetDep(gate);
1034     }
1035     return acc_.GetFrameState(gate);
1036 }
1037 
LowerClz32Float64(GateRef gate)1038 void TypedNativeInlineLowering::LowerClz32Float64(GateRef gate)
1039 {
1040     Environment env(gate, circuit_, &builder_);
1041     Label exit(&builder_);
1042     Label isFinit(&builder_);
1043 
1044     GateRef param = acc_.GetValueIn(gate, 0);
1045     const int32_t defaultReturnValue = 32;
1046     DEFVALUE(result, (&builder_), VariableType::INT32(), builder_.Int32(defaultReturnValue));
1047 
1048     // NaN, Inf, -Inf after ToUint32 equal 0, so we in advance know result: Clz32(0) = 32
1049     builder_.Branch(builder_.DoubleIsNanOrInf(param), &exit, &isFinit);
1050     builder_.Bind(&isFinit);
1051     {
1052         auto truncedValue = builder_.TruncInt64ToInt32(builder_.TruncFloatToInt64(param));
1053         result = builder_.CountLeadingZeroes32(truncedValue);
1054         builder_.Jump(&exit);
1055     }
1056 
1057     builder_.Bind(&exit);
1058     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result);
1059 }
1060 
LowerClz32Int32(GateRef gate)1061 void TypedNativeInlineLowering::LowerClz32Int32(GateRef gate)
1062 {
1063     Environment env(gate, circuit_, &builder_);
1064     GateRef param = acc_.GetValueIn(gate, 0);
1065     GateRef result = builder_.CountLeadingZeroes32(param);
1066     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
1067 }
1068 
1069 //  Int trunc(x) : return x
1070 //  Float trunc(x) : return the integer part removing all fractional digits
LowerTrunc(GateRef gate)1071 void TypedNativeInlineLowering::LowerTrunc(GateRef gate)
1072 {
1073     Environment env(gate, circuit_, &builder_);
1074     GateRef param = acc_.GetValueIn(gate, 0);
1075     DEFVALUE(result, (&builder_), VariableType::FLOAT64(), builder_.NanValue());
1076 
1077     Label isInt(&builder_);
1078     Label notInt(&builder_);
1079     Label isDouble(&builder_);
1080     Label exit(&builder_);
1081 
1082     BRANCH_CIR(builder_.TaggedIsInt(param), &isInt, &notInt);
1083     builder_.Bind(&isInt);
1084     {
1085         result = builder_.ChangeInt32ToFloat64(builder_.GetInt32OfTInt(param));
1086         builder_.Jump(&exit);
1087     }
1088     builder_.Bind(&notInt);
1089     {
1090         BRANCH_CIR(builder_.TaggedIsDouble(param), &isDouble, &exit);
1091         builder_.Bind(&isDouble);
1092         {
1093             GateRef input = builder_.GetDoubleOfTDouble(param);
1094             result = builder_.DoubleTrunc(gate, input);
1095             builder_.Jump(&exit);
1096         }
1097     }
1098     builder_.Bind(&exit);
1099     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result);
1100 }
1101 
LowerMathSqrt(GateRef gate)1102 void TypedNativeInlineLowering::LowerMathSqrt(GateRef gate)
1103 {
1104     Environment env(gate, circuit_, &builder_);
1105     builder_.SetEnvironment(&env);
1106     GateRef param = acc_.GetValueIn(gate, 0);
1107     // 20.2.2.32
1108     // If value is NAN or negative, include -NaN and -Infinity but not -0.0, the result is NaN
1109     // Assembly instruction support NAN and negative
1110     auto ret = builder_.Sqrt(param);
1111     acc_.SetMachineType(ret, MachineType::F64);
1112     acc_.SetGateType(ret, GateType::NJSValue());
1113     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), ret);
1114 }
1115 
1116 
AllocateNewNumber(const CompilationEnv * compilationEnv,CircuitBuilder * builder,GateAccessor acc,GateRef protoOrHclass,GateRef result)1117 GateRef AllocateNewNumber(const CompilationEnv *compilationEnv, CircuitBuilder *builder, GateAccessor acc,
1118                           GateRef protoOrHclass, GateRef result)
1119 {
1120     Jit::JitLockHolder lock(compilationEnv, "AllocateNewNumber");
1121     JSHandle<JSFunction> numberFunctionCT(compilationEnv->GetGlobalEnv()->GetNumberFunction());
1122     JSTaggedValue protoOrHClassCT = numberFunctionCT->GetProtoOrHClass();
1123     JSHClass *numberHClassCT = JSHClass::Cast(protoOrHClassCT.GetTaggedObject());
1124     size_t objectSize = numberHClassCT->GetObjectSize();
1125 
1126     GateRef size = builder->IntPtr(objectSize);
1127 
1128     GateRef emptyArray = builder->GetGlobalConstantValue(ConstantIndex::EMPTY_ARRAY_OBJECT_INDEX);
1129     builder->StartAllocate();
1130     GateRef object = builder->HeapAlloc(acc.GetGlueFromArgList(), size, GateType::TaggedValue(),
1131                                         RegionSpaceFlag::IN_YOUNG_SPACE);
1132     // Initialization:
1133     builder->StoreConstOffset(VariableType::JS_POINTER(), object, JSObject::HCLASS_OFFSET, protoOrHclass,
1134                               MemoryAttribute::NeedBarrierAndAtomic());
1135     builder->StoreConstOffset(VariableType::INT64(), object, JSObject::HASH_OFFSET,
1136                               builder->Int64(JSTaggedValue(0).GetRawData()));
1137     builder->StoreConstOffset(VariableType::JS_POINTER(), object, JSObject::PROPERTIES_OFFSET, emptyArray,
1138                               MemoryAttribute::NoBarrier());
1139     builder->StoreConstOffset(VariableType::JS_POINTER(), object, JSObject::ELEMENTS_OFFSET, emptyArray,
1140                               MemoryAttribute::NoBarrier());
1141     builder->StoreConstOffset(VariableType::JS_ANY(), object, JSPrimitiveRef::VALUE_OFFSET, result);
1142     auto offset = JSPrimitiveRef::VALUE_OFFSET + JSTaggedValue::TaggedTypeSize();
1143     // Initialize inlined properties:
1144     for (; offset < objectSize; offset += JSTaggedValue::TaggedTypeSize()) {
1145         builder->StoreConstOffset(VariableType::INT64(), object, offset, builder->Undefined());
1146     }
1147     return builder->FinishAllocate(object);
1148 }
1149 
LowerNewNumber(GateRef gate)1150 void TypedNativeInlineLowering::LowerNewNumber(GateRef gate)
1151 {
1152     Environment env(gate, circuit_, &builder_);
1153 
1154     GateRef numberFunction = acc_.GetValueIn(gate, 0);
1155     GateRef param = acc_.GetValueIn(gate, 1);
1156 
1157     GateRef globalEnvNumberFunction = builder_.GetGlobalEnvValue(VariableType::JS_ANY(), builder_.GetGlobalEnv(),
1158                                                                  GlobalEnv::NUMBER_FUNCTION_INDEX);
1159     auto builtinIsNumber = builder_.Equal(numberFunction, globalEnvNumberFunction);
1160     builder_.DeoptCheck(builtinIsNumber, FindFrameState(gate), DeoptType::NEWBUILTINCTORFAIL1);
1161 
1162     DEFVALUE(result, (&builder_), VariableType::JS_ANY(),
1163              builder_.ToTaggedIntPtr(builder_.SExtInt32ToInt64(builder_.Int32(0))));
1164     Label exit(&env);
1165     Label isNumber(&env);
1166     Label notNumber(&env);
1167     BRANCH_CIR(builder_.TaggedIsNumber(param), &isNumber, &notNumber);
1168     builder_.Bind(&isNumber);
1169     {
1170         result = param;
1171         builder_.Jump(&exit);
1172     }
1173     builder_.Bind(&notNumber);
1174     {
1175         builder_.DeoptCheck(builder_.TaggedIsString(param), FindFrameState(gate), DeoptType::NOTSTRING1);
1176         auto isIntString = builder_.IsIntegerString(param);
1177         builder_.DeoptCheck(isIntString, FindFrameState(gate), DeoptType::NOTINT1);
1178         result = builder_.ToTaggedIntPtr(builder_.SExtInt32ToInt64(builder_.GetRawHashFromString(param)));
1179         builder_.Jump(&exit);
1180     }
1181     builder_.Bind(&exit);
1182 
1183     auto protoOrHclass = builder_.LoadConstOffset(VariableType::JS_POINTER(), numberFunction,
1184                                                   JSFunction::PROTO_OR_DYNCLASS_OFFSET);
1185 
1186     GateRef ret = AllocateNewNumber(compilationEnv_, &builder_, acc_, protoOrHclass, *result);
1187 
1188     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), ret);
1189 }
1190 
LowerArrayBufferIsView(GateRef gate)1191 void TypedNativeInlineLowering::LowerArrayBufferIsView(GateRef gate)
1192 {
1193     Environment env(gate, circuit_, &builder_);
1194 
1195     GateRef arg = acc_.GetValueIn(gate, 0);
1196     DEFVALUE(result, (&builder_), VariableType::JS_ANY(), builder_.TaggedFalse());
1197     Label exit(&builder_);
1198     Label isDataViewOrTypedArray(&builder_);
1199     Label returnTaggedTrue(&builder_);
1200     BRANCH_CIR(builder_.IsEcmaObject(arg), &isDataViewOrTypedArray, &exit);
1201     builder_.Bind(&isDataViewOrTypedArray);
1202     {
1203         BRANCH_CIR(LogicOrBuilder(&env).Or(builder_.CheckJSType(arg, JSType::JS_DATA_VIEW))
1204             .Or(builder_.TaggedObjectIsTypedArray(arg)).Done(),
1205             &returnTaggedTrue, &exit);
1206     }
1207     builder_.Bind(&returnTaggedTrue);
1208     {
1209         result = builder_.TaggedTrue();
1210         builder_.Jump(&exit);
1211     }
1212     builder_.Bind(&exit);
1213     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result);
1214 }
1215 
1216 template <bool IS_UNSIGNED>
LowerBigIntAsIntN(GateRef gate)1217 void TypedNativeInlineLowering::LowerBigIntAsIntN(GateRef gate)
1218 {
1219     Environment env(gate, circuit_, &builder_);
1220     Label hasException(&builder_);
1221     Label exit(&builder_);
1222     Label returnBigInt(&builder_);
1223     Label notZeroBigInt(&builder_);
1224     Label commonCase(&builder_);
1225 #if BIGINT_CONSTRUCTOR_IMPLEMENTED // NOTE: add fastpath after BigInt constructor implementing
1226     Label zeroBits(&builder_);
1227     Label notZeroBits(&builder_);
1228 #endif // BIGINT_CONSTRUCTOR_IMPLEMENTED
1229 
1230     GateRef glue = acc_.GetGlueFromArgList();
1231     GateRef bits = acc_.GetValueIn(gate, 0);
1232     GateRef bigint = acc_.GetValueIn(gate, 1);
1233     GateRef frameState = acc_.GetValueIn(gate, 2);
1234     GateRef bitness = builder_.GetDoubleOfTDouble(bits);
1235     DEFVALUE(result, (&builder_), VariableType::JS_ANY(), builder_.Undefined());
1236 
1237     // Deoptimization if bitness is negative or more than safe number
1238     GateRef safeNumber = builder_.Double(SAFE_NUMBER);
1239     GateRef positiveCheck = builder_.DoubleGreaterThanOrEqual(bitness, builder_.Double(0));
1240     GateRef safeCheck = builder_.DoubleLessThanOrEqual(bitness, safeNumber);
1241     builder_.DeoptCheck(positiveCheck, frameState, DeoptType::RANGE_ERROR);
1242     builder_.DeoptCheck(safeCheck, frameState, DeoptType::RANGE_ERROR);
1243     builder_.DeoptCheck(builder_.TaggedIsBigInt(bigint), frameState, DeoptType::NOT_BIG_INT);
1244 
1245     // Return bigint(0), if bits == 0
1246 #if BIGINT_CONSTRUCTOR_IMPLEMENTED // NOTE: add fastpath after BigInt constructor implementing
1247     BRANCH_CIR(builder_.DoubleEqual(bitness, builder_.Double(0)), &zeroBits, &notZeroBits);
1248     builder_.Bind(&zeroBits);
1249     {
1250         result = builder_.BigIntConstructor(0);
1251         builder_.Jump(&exit);
1252     }
1253     builder_.Bind(&notZeroBits);
1254 #endif // BIGINT_CONSTRUCTOR_IMPLEMENTED
1255 
1256     // Return bigint, if bigint == 0
1257     GateRef isZeroBigInt = LogicAndBuilder(&env)
1258         .And(builder_.Int32Equal(builder_.Load(VariableType::INT32(), bigint, builder_.IntPtr(BigInt::LENGTH_OFFSET)),
1259                                  builder_.Int32(1)))
1260         .And(builder_.Int32Equal(builder_.Load(VariableType::INT32(), bigint, builder_.IntPtr(BigInt::DATA_OFFSET)),
1261                                  builder_.Int32(0)))
1262         .Done();
1263     BRANCH_CIR(isZeroBigInt, &returnBigInt, &notZeroBigInt);
1264 
1265     // Return bigint, if bits >= max_value
1266     builder_.Bind(&notZeroBigInt);
1267     GateRef maxLengthBits = builder_.Double(static_cast<double>(BigInt::kMaxLengthBits));
1268     BRANCH_CIR(builder_.DoubleGreaterThanOrEqual(bitness, maxLengthBits), &returnBigInt, &commonCase);
1269     builder_.Bind(&returnBigInt);
1270     {
1271         result = bigint;
1272         builder_.Jump(&exit);
1273     }
1274 
1275     // Common case
1276     builder_.Bind(&commonCase);
1277     if constexpr (IS_UNSIGNED) {
1278         result = builder_.CallRuntime(glue, RTSTUB_ID(CallBigIntAsUintN), Gate::InvalidGateRef,
1279                                       {bits, bigint}, gate);
1280     } else {
1281         result = builder_.CallRuntime(glue, RTSTUB_ID(CallBigIntAsIntN), Gate::InvalidGateRef,
1282                                       {bits, bigint}, gate);
1283     }
1284     BRANCH_CIR(builder_.HasPendingException(glue), &hasException, &exit);
1285     builder_.Bind(&hasException);
1286     {
1287         result = builder_.ExceptionConstant();
1288         builder_.Jump(&exit);
1289     }
1290     builder_.Bind(&exit);
1291     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result);
1292 }
1293 
LowerDataViewProtoFunc(GateRef gate,DataViewProtoFunc func)1294 void TypedNativeInlineLowering::LowerDataViewProtoFunc(GateRef gate, DataViewProtoFunc func)
1295 {
1296     Environment env(gate, circuit_, &builder_);
1297 
1298     Label isNotDetachedBuffer(&builder_);
1299     Label isNotByteArray(&builder_);
1300     Label getPointFromByteArray(&builder_);
1301     Label getPointFromNotByteArray(&builder_);
1302     Label getValueFromBuffer(&builder_);
1303     Label bufferByteLengthIsZero(&builder_);
1304     Label bufferByteLengthIsNotZero(&builder_);
1305     GateRef thisobj = acc_.GetValueIn(gate, 0);
1306     GateRef requestIndex = acc_.GetValueIn(gate, 1); // 1: requestIndex
1307     GateRef builtinId = Circuit::NullGate();
1308     GateRef isLittleEndian = Circuit::NullGate();
1309     GateRef frameState = Circuit::NullGate();
1310     ASSERT(func == DataViewProtoFunc::GET || func == DataViewProtoFunc::SET);
1311     if (func == DataViewProtoFunc::GET) {
1312         builtinId = acc_.GetValueIn(gate, 2); // 2: builtinId
1313         isLittleEndian = acc_.GetValueIn(gate, 3); // 3: isLittleEndian
1314         frameState = acc_.GetValueIn(gate, 4); // 4: frameState
1315     } else if (func == DataViewProtoFunc::SET) {
1316         builtinId = acc_.GetValueIn(gate, 3); // 3: builtinId
1317         isLittleEndian = acc_.GetValueIn(gate, 4); // 4: isLittleEndian
1318         frameState = acc_.GetValueIn(gate, 5); // 5: frameState
1319     } else {
1320         UNREACHABLE();
1321     }
1322 
1323     GateRef resultfinal = Circuit::NullGate();
1324 
1325     DEFVALUE(dataPointer, (&builder_), VariableType::NATIVE_POINTER(), builder_.IntPtr(0));
1326 
1327     builder_.DeoptCheck(
1328         builder_.Int32GreaterThanOrEqual(requestIndex, builder_.Int32(0)), frameState, DeoptType::INDEXLESSZERO);
1329     GateRef viewedArrayBufferOffset = builder_.IntPtr(JSDataView::VIEW_ARRAY_BUFFER_OFFSET);
1330     GateRef buffer = builder_.Load(VariableType::JS_ANY(), thisobj, viewedArrayBufferOffset);
1331     BRANCH_CIR(builder_.CheckJSType(buffer, JSType::BYTE_ARRAY), &isNotDetachedBuffer, &isNotByteArray);
1332     builder_.Bind(&isNotByteArray);
1333     {
1334         GateRef dataOffset = builder_.IntPtr(JSArrayBuffer::DATA_OFFSET);
1335         GateRef dataSlot = builder_.Load(VariableType::JS_ANY(), buffer, dataOffset);
1336         builder_.DeoptCheck(builder_.TaggedIsNotNull(dataSlot), frameState, DeoptType::ARRAYBUFFERISDETACHED);
1337         builder_.Jump(&isNotDetachedBuffer);
1338     }
1339     builder_.Bind(&isNotDetachedBuffer);
1340     GateRef sizeOffset = builder_.IntPtr(JSDataView::BYTE_LENGTH_OFFSET);
1341     GateRef size = builder_.ZExtInt32ToInt64(builder_.Load(VariableType::INT32(), thisobj, sizeOffset));
1342     GateRef elementSize = BuiltinIdToSize(builtinId);
1343     GateRef totalSize = builder_.Int64Add(builder_.ZExtInt32ToInt64(requestIndex), elementSize);
1344 
1345     builder_.DeoptCheck(
1346         builder_.Int64UnsignedGreaterThanOrEqual(size, totalSize), frameState, DeoptType::TOTALSIZEOVERFLOW);
1347     GateRef byteOffset = builder_.IntPtr(JSDataView::BYTE_OFFSET_OFFSET);
1348     GateRef offset = builder_.Load(VariableType::INT32(), thisobj, byteOffset);
1349     GateRef bufferIndex = builder_.Int32Add(requestIndex, offset);
1350     BRANCH_CIR(builder_.CheckJSType(buffer, JSType::BYTE_ARRAY), &getPointFromByteArray, &getPointFromNotByteArray);
1351     builder_.Bind(&getPointFromByteArray);
1352     {
1353         dataPointer = builder_.Load(VariableType::NATIVE_POINTER(), buffer, builder_.IntPtr(ByteArray::DATA_OFFSET));
1354         builder_.Jump(&getValueFromBuffer);
1355     }
1356     builder_.Bind(&getPointFromNotByteArray);
1357     {
1358         GateRef arrayBufferByteLengthOffset = builder_.IntPtr(JSArrayBuffer::BYTE_LENGTH_OFFSET);
1359         GateRef arrayBufferByteLength = builder_.Load(VariableType::INT32(), buffer, arrayBufferByteLengthOffset);
1360         BRANCH_CIR(builder_.Int32Equal(arrayBufferByteLength, builder_.Int32(0)),
1361                    &bufferByteLengthIsZero,
1362                    &bufferByteLengthIsNotZero);
1363         builder_.Bind(&bufferByteLengthIsZero);
1364         {
1365             dataPointer = builder_.IntPtr(0);
1366             builder_.Jump(&getValueFromBuffer);
1367         }
1368         builder_.Bind(&bufferByteLengthIsNotZero);
1369         {
1370             GateRef bufferDataOffset = builder_.IntPtr(JSArrayBuffer::DATA_OFFSET);
1371             GateRef data = builder_.Load(VariableType::JS_ANY(), buffer, bufferDataOffset);
1372             GateRef externalPointerOffset = builder_.IntPtr(JSNativePointer::POINTER_OFFSET);
1373             GateRef externalPointer = builder_.Load(VariableType::NATIVE_POINTER(), data, externalPointerOffset);
1374             dataPointer = externalPointer;
1375             builder_.Jump(&getValueFromBuffer);
1376         }
1377     }
1378     builder_.Bind(&getValueFromBuffer);
1379     ASSERT(func == DataViewProtoFunc::GET || func == DataViewProtoFunc::SET);
1380     if (func == DataViewProtoFunc::GET) {
1381         resultfinal = GetValueFromBuffer(bufferIndex, *dataPointer, isLittleEndian, builtinId);
1382     } else if (func == DataViewProtoFunc::SET) {
1383         GateRef value = acc_.GetValueIn(gate, 2); // 2: value
1384         resultfinal =
1385             SetValueInBuffer(bufferIndex, value, *dataPointer, isLittleEndian, builtinId, acc_.GetGlueFromArgList());
1386     } else {
1387         UNREACHABLE();
1388     }
1389 
1390     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), resultfinal);
1391 }
1392 
BuiltinIdToSize(GateRef ID)1393 GateRef TypedNativeInlineLowering::BuiltinIdToSize(GateRef ID)
1394 {
1395     auto builtinsID = static_cast<BuiltinsStubCSigns::ID>(acc_.GetConstantValue(ID));
1396     switch (builtinsID) {
1397         case BuiltinsStubCSigns::ID::DataViewGetInt8:
1398         case BuiltinsStubCSigns::ID::DataViewGetUint8:
1399         case BuiltinsStubCSigns::ID::DataViewSetUint8:
1400         case BuiltinsStubCSigns::ID::DataViewSetInt8:
1401             return builder_.Int64(ElmentSize::BITS_8);
1402         case BuiltinsStubCSigns::ID::DataViewGetInt16:
1403         case BuiltinsStubCSigns::ID::DataViewGetUint16:
1404         case BuiltinsStubCSigns::ID::DataViewSetInt16:
1405         case BuiltinsStubCSigns::ID::DataViewSetUint16:
1406             return builder_.Int64(ElmentSize::BITS_16);
1407         case BuiltinsStubCSigns::ID::DataViewGetUint32:
1408         case BuiltinsStubCSigns::ID::DataViewGetInt32:
1409         case BuiltinsStubCSigns::ID::DataViewGetFloat32:
1410         case BuiltinsStubCSigns::ID::DataViewSetUint32:
1411         case BuiltinsStubCSigns::ID::DataViewSetInt32:
1412         case BuiltinsStubCSigns::ID::DataViewSetFloat32:
1413             return builder_.Int64(ElmentSize::BITS_32);
1414         case BuiltinsStubCSigns::ID::DataViewGetFloat64:
1415         case BuiltinsStubCSigns::ID::DataViewSetFloat64:
1416             return builder_.Int64(ElmentSize::BITS_64);
1417         default:
1418             UNREACHABLE();
1419     }
1420 }
GetValueFromBuffer(GateRef bufferIndex,GateRef dataPointer,GateRef isLittleEndian,GateRef ID)1421 GateRef TypedNativeInlineLowering::GetValueFromBuffer(GateRef bufferIndex,
1422                                                       GateRef dataPointer,
1423                                                       GateRef isLittleEndian,
1424                                                       GateRef ID)
1425 {
1426     Label entry(&builder_);
1427     builder_.SubCfgEntry(&entry);
1428     Label exit(&builder_);
1429     Label littleEndian(&builder_);
1430     Label bigEndian(&builder_);
1431     Label passResult(&builder_);
1432     GateRef finalResult = builder_.NullConstant();
1433     BuiltinsStubCSigns::ID builtinsID = static_cast<BuiltinsStubCSigns::ID>(acc_.GetConstantValue(ID));
1434     switch (builtinsID) {
1435         case BuiltinsStubCSigns::ID::DataViewGetUint8: {
1436             GateRef uint8Res = builder_.Load(VariableType::INT8(), dataPointer, builder_.ZExtInt32ToPtr(bufferIndex));
1437             finalResult = builder_.ZExtInt8ToInt32(uint8Res);
1438             builder_.Jump(&exit);
1439             break;
1440         }
1441         case BuiltinsStubCSigns::ID::DataViewGetInt8: {
1442             GateRef int8res = builder_.Load(VariableType::INT8(), dataPointer, builder_.ZExtInt32ToPtr(bufferIndex));
1443             finalResult = builder_.SExtInt8ToInt32(int8res);
1444             builder_.Jump(&exit);
1445             break;
1446         }
1447         case BuiltinsStubCSigns::ID::DataViewGetUint16: {
1448             DEFVALUE(tempRes, (&builder_), VariableType::INT32(), builder_.Int32(0));
1449             GateRef uint16Res = builder_.Load(VariableType::INT16(), dataPointer, builder_.ZExtInt32ToPtr(bufferIndex));
1450             BRANCH_CIR(builder_.BoolNot(isLittleEndian), &bigEndian, &littleEndian);
1451             builder_.Bind(&littleEndian);
1452             {
1453                 tempRes = builder_.ZExtInt16ToInt32(uint16Res);
1454                 builder_.Jump(&passResult);
1455             }
1456             builder_.Bind(&bigEndian);
1457             {
1458                 GateRef bigEndianInt16 = builder_.Int16ToBigEndianInt16(uint16Res);
1459                 tempRes = builder_.ZExtInt16ToInt32(bigEndianInt16);
1460                 builder_.Jump(&passResult);
1461             }
1462             builder_.Bind(&passResult);
1463             {
1464                 finalResult = *tempRes;
1465                 builder_.Jump(&exit);
1466             }
1467             break;
1468         }
1469         case BuiltinsStubCSigns::ID::DataViewGetInt16: {
1470             DEFVALUE(tempRes, (&builder_), VariableType::INT32(), builder_.Int32(0));
1471             GateRef int16Res = builder_.Load(VariableType::INT16(), dataPointer, builder_.ZExtInt32ToPtr(bufferIndex));
1472             BRANCH_CIR(builder_.BoolNot(isLittleEndian), &bigEndian, &littleEndian);
1473             builder_.Bind(&littleEndian);
1474             {
1475                 tempRes = builder_.SExtInt16ToInt32(int16Res);
1476                 builder_.Jump(&passResult);
1477             }
1478             builder_.Bind(&bigEndian);
1479             {
1480                 tempRes = builder_.SExtInt16ToInt32(builder_.Int16ToBigEndianInt16(int16Res));
1481                 builder_.Jump(&passResult);
1482             }
1483             builder_.Bind(&passResult);
1484             {
1485                 finalResult = *tempRes;
1486                 builder_.Jump(&exit);
1487             }
1488             break;
1489         }
1490         case BuiltinsStubCSigns::ID::DataViewGetUint32: {
1491             DEFVALUE(tempRes, (&builder_), VariableType::INT32(), builder_.Int32(0));
1492             GateRef uint32Res = builder_.Load(VariableType::INT32(), dataPointer, builder_.ZExtInt32ToPtr(bufferIndex));
1493             BRANCH_CIR(builder_.BoolNot(isLittleEndian), &bigEndian, &littleEndian);
1494             builder_.Bind(&littleEndian);
1495             {
1496                 tempRes = uint32Res;
1497                 builder_.Jump(&passResult);
1498             }
1499             builder_.Bind(&bigEndian);
1500             {
1501                 tempRes = builder_.Int32ToBigEndianInt32(uint32Res);
1502                 builder_.Jump(&passResult);
1503             }
1504             builder_.Bind(&passResult);
1505             {
1506                 finalResult = *tempRes;
1507                 builder_.Jump(&exit);
1508             }
1509             break;
1510         }
1511         case BuiltinsStubCSigns::ID::DataViewGetInt32: {
1512             DEFVALUE(tempRes, (&builder_), VariableType::INT32(), builder_.Int32(0));
1513             GateRef int32Res = builder_.Load(VariableType::INT32(), dataPointer, builder_.ZExtInt32ToPtr(bufferIndex));
1514             BRANCH_CIR(builder_.BoolNot(isLittleEndian), &bigEndian, &littleEndian);
1515             builder_.Bind(&littleEndian);
1516             {
1517                 tempRes = int32Res;
1518                 builder_.Jump(&passResult);
1519             }
1520             builder_.Bind(&bigEndian);
1521             {
1522                 tempRes = builder_.Int32ToBigEndianInt32(int32Res);
1523                 builder_.Jump(&passResult);
1524             }
1525             builder_.Bind(&passResult);
1526             {
1527                 finalResult = *tempRes;
1528                 builder_.Jump(&exit);
1529             }
1530             break;
1531         }
1532         case BuiltinsStubCSigns::ID::DataViewGetFloat32: {
1533             DEFVALUE(tempRes, (&builder_), VariableType::FLOAT64(), builder_.Double(base::NAN_VALUE));
1534             Label notNaN(&builder_);
1535             GateRef int32Res = builder_.Load(VariableType::INT32(), dataPointer, builder_.ZExtInt32ToPtr(bufferIndex));
1536             BRANCH_CIR(builder_.BoolNot(isLittleEndian), &bigEndian, &littleEndian);
1537             builder_.Bind(&littleEndian);
1538             {
1539                 GateRef float32Res = builder_.CastInt32ToFloat32(int32Res);
1540                 tempRes = builder_.ExtFloat32ToDouble(float32Res);
1541                 builder_.Jump(&passResult);
1542             }
1543             builder_.Bind(&bigEndian);
1544             {
1545                 GateRef originFloat32Res = builder_.CastInt32ToFloat32(int32Res);
1546                 GateRef originDoubleRes = builder_.ExtFloat32ToDouble(originFloat32Res);
1547                 BRANCH_CIR(builder_.DoubleIsNAN(originDoubleRes), &passResult, &notNaN);
1548                 builder_.Bind(&notNaN);
1549                 {
1550                     GateRef bigEndianInt32Res = builder_.Int32ToBigEndianInt32(int32Res);
1551                     GateRef float32Res = builder_.CastInt32ToFloat32(bigEndianInt32Res);
1552                     tempRes = builder_.ExtFloat32ToDouble(float32Res);
1553                     builder_.Jump(&passResult);
1554                 }
1555             }
1556             builder_.Bind(&passResult);
1557             {
1558                 finalResult = *tempRes;
1559                 builder_.Jump(&exit);
1560             }
1561             break;
1562         }
1563         case BuiltinsStubCSigns::ID::DataViewGetFloat64: {
1564             GateRef float64Res =
1565                 builder_.Load(VariableType::FLOAT64(), dataPointer, builder_.ZExtInt32ToPtr(bufferIndex));
1566             DEFVALUE(tempRes, (&builder_), VariableType::FLOAT64(), builder_.NanValue());
1567             Label NaNandNotImpure(&builder_);
1568             Label ifLittleEndian(&builder_);
1569             GateRef resIsImpure = builder_.DoubleIsImpureNaN(float64Res);
1570             GateRef canPassResult = LogicAndBuilder(builder_.GetCurrentEnvironment())
1571                 .And(builder_.BoolNot(resIsImpure)).And(builder_.DoubleIsNAN(float64Res)).Done();
1572             BRANCH_CIR(canPassResult, &passResult, &ifLittleEndian);
1573             builder_.Bind(&ifLittleEndian);
1574             {
1575                 BRANCH_CIR(builder_.BoolNot(isLittleEndian), &bigEndian, &littleEndian);
1576                 builder_.Bind(&bigEndian);
1577                 {
1578                     GateRef int64Res = builder_.CastDoubleToInt64(float64Res);
1579                     GateRef bigEndianInt64Res = builder_.Int64ToBigEndianInt64(int64Res);
1580                     GateRef bigEndianDoubleRes = builder_.CastInt64ToFloat64(bigEndianInt64Res);
1581                     Label bigEndianResNotImpure(&builder_);
1582                     BRANCH_CIR(builder_.DoubleIsImpureNaN(bigEndianDoubleRes), &passResult, &bigEndianResNotImpure);
1583                     builder_.Bind(&bigEndianResNotImpure);
1584                     {
1585                         tempRes = bigEndianDoubleRes;
1586                         builder_.Jump(&passResult);
1587                     }
1588                 }
1589                 builder_.Bind(&littleEndian);
1590                 {
1591                     Label resNotImpure(&builder_);
1592                     BRANCH_CIR(resIsImpure, &passResult, &resNotImpure);
1593                     builder_.Bind(&resNotImpure);
1594                     {
1595                         tempRes = float64Res;
1596                         builder_.Jump(&passResult);
1597                     }
1598                 }
1599             }
1600             builder_.Bind(&passResult);
1601             {
1602                 finalResult = *tempRes;
1603                 builder_.Jump(&exit);
1604             }
1605             break;
1606         }
1607         default:
1608             UNREACHABLE();
1609     }
1610     builder_.Bind(&exit);
1611     builder_.SubCfgExit();
1612     return finalResult;
1613 }
1614 
SetValueInBuffer(GateRef bufferIndex,GateRef value,GateRef dataPointer,GateRef isLittleEndian,GateRef ID,GateRef glue)1615 GateRef TypedNativeInlineLowering::SetValueInBuffer(
1616     GateRef bufferIndex, GateRef value, GateRef dataPointer, GateRef isLittleEndian, GateRef ID, GateRef glue)
1617 {
1618     Label entry(&builder_);
1619     builder_.SubCfgEntry(&entry);
1620     Label exit(&builder_);
1621 
1622     Label littleEndian(&builder_);
1623     Label bigEndian(&builder_);
1624     Label passResult(&builder_);
1625     GateRef offset = builder_.ZExtInt32ToPtr(bufferIndex);
1626     Label startStore(&builder_);
1627     Label getInt64Value(&builder_);
1628     DEFVALUE(int64Value, (&builder_), VariableType::INT64(), builder_.Int64(0));
1629     BRANCH_CIR(builder_.DoubleIsNanOrInf(value), &startStore, &getInt64Value);
1630     builder_.Bind(&getInt64Value);
1631     {
1632         int64Value = builder_.TruncFloatToInt64(value);
1633         builder_.Jump(&startStore);
1634     }
1635     builder_.Bind(&startStore);
1636     BuiltinsStubCSigns::ID builtinsID = static_cast<BuiltinsStubCSigns::ID>(acc_.GetConstantValue(ID));
1637 
1638     switch (builtinsID) {
1639         case BuiltinsStubCSigns::ID::DataViewSetUint8:
1640         case BuiltinsStubCSigns::ID::DataViewSetInt8: {
1641             GateRef int32Value = builder_.TruncInt64ToInt32(*int64Value);
1642             builder_.Store(VariableType::INT8(), glue, dataPointer, offset, builder_.TruncInt32ToInt8(int32Value));
1643             builder_.Jump(&exit);
1644             break;
1645         }
1646         case BuiltinsStubCSigns::ID::DataViewSetUint16:
1647         case BuiltinsStubCSigns::ID::DataViewSetInt16: {
1648             BRANCH_CIR(isLittleEndian, &littleEndian, &bigEndian);
1649             builder_.Bind(&littleEndian);
1650             {
1651                 builder_.Store(
1652                     VariableType::INT16(), glue, dataPointer, offset, builder_.TruncInt64ToInt16(*int64Value));
1653                 builder_.Jump(&exit);
1654             }
1655             builder_.Bind(&bigEndian);
1656             {
1657                 GateRef int16Value = builder_.TruncInt64ToInt16(*int64Value);
1658                 GateRef bigEndianInt16 = builder_.Int16ToBigEndianInt16(int16Value);
1659                 builder_.Store(VariableType::INT16(), glue, dataPointer, offset, bigEndianInt16);
1660                 builder_.Jump(&exit);
1661             }
1662             break;
1663         }
1664         case BuiltinsStubCSigns::ID::DataViewSetFloat32: {
1665             Label isNaN(&builder_);
1666             Label notNaN(&builder_);
1667             GateRef float32Value = builder_.TruncDoubleToFloat32(value);
1668             BRANCH_CIR(builder_.DoubleIsNAN(value), &isNaN, &notNaN);
1669             builder_.Bind(&isNaN);
1670             {
1671                 builder_.Store(VariableType::FLOAT32(), glue, dataPointer, offset, float32Value);
1672                 builder_.Jump(&exit);
1673             }
1674             builder_.Bind(&notNaN);
1675             {
1676                 BRANCH_CIR(isLittleEndian, &littleEndian, &bigEndian);
1677                 builder_.Bind(&littleEndian);
1678                 {
1679                     builder_.Store(VariableType::FLOAT32(), glue, dataPointer, offset, float32Value);
1680                     builder_.Jump(&exit);
1681                 }
1682                 builder_.Bind(&bigEndian);
1683                 {
1684                     GateRef int32Value = builder_.CastFloat32ToInt32(float32Value);
1685                     GateRef bigEndianInt32Value = builder_.Int32ToBigEndianInt32(int32Value);
1686                     GateRef bigEndianFloat32Value = builder_.CastInt32ToFloat32(bigEndianInt32Value);
1687                     builder_.Store(VariableType::FLOAT32(), glue, dataPointer, offset, bigEndianFloat32Value);
1688                     builder_.Jump(&exit);
1689                 }
1690             }
1691             break;
1692         }
1693         case BuiltinsStubCSigns::ID::DataViewSetInt32:
1694         case BuiltinsStubCSigns::ID::DataViewSetUint32: {
1695             BRANCH_CIR(isLittleEndian, &littleEndian, &bigEndian);
1696             builder_.Bind(&littleEndian);
1697             {
1698                 builder_.Store(
1699                     VariableType::INT32(), glue, dataPointer, offset, builder_.TruncInt64ToInt32(*int64Value));
1700                 builder_.Jump(&exit);
1701             }
1702             builder_.Bind(&bigEndian);
1703             {
1704                 GateRef int32Value = builder_.TruncInt64ToInt32(*int64Value);
1705                 GateRef bigEndianInt32 = builder_.Int32ToBigEndianInt32(int32Value);
1706                 builder_.Store(VariableType::INT32(), glue, dataPointer, offset, bigEndianInt32);
1707                 builder_.Jump(&exit);
1708             }
1709             break;
1710         }
1711         case BuiltinsStubCSigns::ID::DataViewSetFloat64: {
1712             Label isNaN(&builder_);
1713             Label notNaN(&builder_);
1714             BRANCH_CIR(builder_.DoubleIsNAN(value), &isNaN, &notNaN);
1715             {
1716                 builder_.Bind(&isNaN);
1717                 {
1718                     builder_.Store(VariableType::FLOAT64(), glue, dataPointer, offset, value);
1719                     builder_.Jump(&exit);
1720                 }
1721                 builder_.Bind(&notNaN);
1722                 {
1723                     BRANCH_CIR(isLittleEndian, &littleEndian, &bigEndian);
1724                     builder_.Bind(&littleEndian);
1725                     {
1726                         builder_.Store(VariableType::FLOAT64(), glue, dataPointer, offset, value);
1727                         builder_.Jump(&exit);
1728                     }
1729                     builder_.Bind(&bigEndian);
1730                     {
1731                         GateRef int64bitsValue = builder_.CastDoubleToInt64(value);
1732                         GateRef bigEndianInt64Value = builder_.Int64ToBigEndianInt64(int64bitsValue);
1733                         GateRef float64Value = builder_.CastInt64ToFloat64(bigEndianInt64Value);
1734                         builder_.Store(VariableType::FLOAT64(), glue, dataPointer, offset, float64Value);
1735                         builder_.Jump(&exit);
1736                     }
1737                 }
1738             }
1739             break;
1740         }
1741         default:
1742             UNREACHABLE();
1743     }
1744     builder_.Bind(&exit);
1745     builder_.SubCfgExit();
1746     return builder_.UndefineConstant();
1747 }
1748 
BuildMathSignDouble(Variable * resVarPtr,CircuitBuilder * builder,GateRef param,std::vector<Label> * labelsForFloatCase)1749 static void BuildMathSignDouble(Variable *resVarPtr, CircuitBuilder *builder, GateRef param,
1750                                 std::vector<Label> *labelsForFloatCase)
1751 {
1752     auto &taggedRes = *resVarPtr;
1753     auto &labelsForFloatCaseRef = *labelsForFloatCase;
1754     auto labelsIdx = 0;
1755     Label *isNan = &labelsForFloatCaseRef.at(labelsIdx++);
1756     Label *notNan = &labelsForFloatCaseRef.at(labelsIdx++);
1757     Label *exitNan = &labelsForFloatCaseRef.at(labelsIdx++);
1758 
1759     auto value = builder->GetDoubleOfTDouble(param);
1760     builder->Branch(builder->DoubleIsNAN(value), isNan, notNan);
1761     builder->Bind(isNan);
1762     {
1763         taggedRes = builder->DoubleToTaggedDoublePtr(builder->NanValue());
1764         builder->Jump(exitNan);
1765     }
1766     builder->Bind(notNan);
1767     {
1768         Label *isZero = &labelsForFloatCaseRef.at(labelsIdx++);
1769         Label *notZero = &labelsForFloatCaseRef.at(labelsIdx++);
1770         Label *exitZero = &labelsForFloatCaseRef.at(labelsIdx++);
1771 
1772         builder->Branch(builder->DoubleEqual(value, builder->Double(0)), isZero, notZero);
1773         builder->Bind(isZero);
1774         {
1775             taggedRes = param;
1776             builder->Jump(exitZero);
1777         }
1778         builder->Bind(notZero);
1779         {
1780             Label *isNegative = &labelsForFloatCaseRef.at(labelsIdx++);
1781             Label *notNegative = &labelsForFloatCaseRef.at(labelsIdx++);
1782             Label *exitNegative = &labelsForFloatCaseRef.at(labelsIdx);
1783 
1784             builder->Branch(builder->DoubleLessThan(value, builder->Double(0)), isNegative, notNegative);
1785             builder->Bind(isNegative);
1786             {
1787                 taggedRes = builder->Int32ToTaggedPtr(builder->Int32(-1));
1788                 builder->Jump(exitNegative);
1789             }
1790             builder->Bind(notNegative);
1791             {
1792                 taggedRes = builder->Int32ToTaggedPtr(builder->Int32(1));
1793                 builder->Jump(exitNegative);
1794             }
1795             builder->Bind(exitNegative);
1796             builder->Jump(exitZero);
1797         }
1798         builder->Bind(exitZero);
1799         builder->Jump(exitNan);
1800     }
1801     builder->Bind(exitNan);
1802 }
1803 
BuildMathSignInt(CircuitBuilder * builder,GateRef input)1804 static GateRef BuildMathSignInt(CircuitBuilder *builder, GateRef input)
1805 {
1806     auto nz = builder->BooleanToInt32(builder->Int32NotEqual(input, builder->Int32(0)));
1807     auto valueShifted = builder->Int32ASR(input, builder->Int32(JSTaggedValue::INT_SIGN_BIT_OFFSET));
1808     return builder->Int32Or(valueShifted, nz);
1809 }
1810 
LowerMathSignInt(GateRef gate)1811 void TypedNativeInlineLowering::LowerMathSignInt(GateRef gate)
1812 {
1813     Environment env(gate, circuit_, &builder_);
1814     GateRef param = acc_.GetValueIn(gate, 0);
1815 
1816     auto res = BuildMathSignInt(&builder_, param);
1817 
1818     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), res);
1819 }
1820 
LowerMathSignTagged(GateRef gate)1821 void TypedNativeInlineLowering::LowerMathSignTagged(GateRef gate)
1822 {
1823     Environment env(gate, circuit_, &builder_);
1824     Label exit(&builder_);
1825     GateRef param = acc_.GetValueIn(gate, 0);
1826     DEFVALUE(taggedRes, (&builder_), VariableType::JS_ANY(), builder_.HoleConstant());
1827 
1828     std::vector<Label> labelsForFloatCase;
1829     constexpr auto FLOAT_CASE_LABELS_COUNT = 9;
1830     labelsForFloatCase.reserve(FLOAT_CASE_LABELS_COUNT);
1831     for (auto i = 0; i < FLOAT_CASE_LABELS_COUNT; i++) {
1832         labelsForFloatCase.emplace_back(&builder_);
1833     }
1834 
1835     Label isInt(&builder_);
1836     Label notInt(&builder_);
1837     builder_.Branch(builder_.TaggedIsInt(param), &isInt, &notInt);
1838     builder_.Bind(&isInt);
1839     {
1840         auto value = builder_.GetInt32OfTInt(param);
1841 
1842         auto res = BuildMathSignInt(&builder_, value);
1843 
1844         taggedRes = builder_.Int32ToTaggedPtr(res);
1845         builder_.Jump(&exit);
1846     }
1847     builder_.Bind(&notInt);
1848     {
1849         BuildMathSignDouble(&taggedRes, &builder_, param, &labelsForFloatCase);
1850         builder_.Jump(&exit);
1851     }
1852     builder_.Bind(&exit);
1853     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *taggedRes);
1854 }
1855 
BuildDoubleIsFinite(GateRef value)1856 GateRef TypedNativeInlineLowering::BuildDoubleIsFinite(GateRef value)
1857 {
1858     GateRef diff = builder_.DoubleSub(value, value);
1859     return builder_.DoubleEqual(diff, diff);
1860 }
1861 
LowerNumberIsFinite(GateRef gate)1862 void TypedNativeInlineLowering::LowerNumberIsFinite(GateRef gate)
1863 {
1864     GateRef value = acc_.GetValueIn(gate, 0);
1865     Environment env(gate, circuit_, &builder_);
1866     GateRef result = BuildDoubleIsFinite(value);
1867 
1868     acc_.ReplaceGate(gate, builder_.GetStateDepend(), result);
1869 }
1870 
BuildTaggedIsInteger(GateRef gate,GateRef value,bool safe)1871 GateRef TypedNativeInlineLowering::BuildTaggedIsInteger(GateRef gate, GateRef value, bool safe)
1872 {
1873     Label exit(&builder_);
1874     Label entry(&builder_);
1875     builder_.SubCfgEntry(&entry);
1876     DEFVALUE(result, (&builder_), VariableType::BOOL(), builder_.False());
1877     Label isInt(&builder_);
1878     Label notIsInt(&builder_);
1879     BRANCH_CIR(builder_.TaggedIsInt(value), &isInt, &notIsInt);
1880     builder_.Bind(&isInt);
1881     {
1882         result = builder_.True();
1883         builder_.Jump(&exit);
1884     }
1885     builder_.Bind(&notIsInt);
1886 
1887     Label isFinite(&builder_);
1888     GateRef doubleVal = builder_.GetDoubleOfTDouble(value);
1889     BRANCH_CIR(BuildDoubleIsFinite(doubleVal), &isFinite, &exit);
1890     builder_.Bind(&isFinite);
1891     {
1892         GateRef doubleTrunc = builder_.DoubleTrunc(gate, doubleVal);
1893         result = builder_.Equal(doubleVal, doubleTrunc);
1894         if (safe) {
1895             GateRef resultVal = *result;
1896             result = LogicAndBuilder(builder_.GetCurrentEnvironment())
1897                 .And(resultVal)
1898                 .And(builder_.DoubleLessThanOrEqual(builder_.FAbs(doubleTrunc),
1899                                                     builder_.Double(base::MAX_SAFE_INTEGER)))
1900                 .Done();
1901         }
1902         builder_.Jump(&exit);
1903     }
1904 
1905     builder_.Bind(&exit);
1906     GateRef res = *result;
1907     builder_.SubCfgExit();
1908     return res;
1909 }
1910 
LowerNumberIsInteger(GateRef gate,OpCode op)1911 void TypedNativeInlineLowering::LowerNumberIsInteger(GateRef gate, OpCode op)
1912 {
1913     ASSERT(op == OpCode::NUMBER_IS_INTEGER || op == OpCode::NUMBER_IS_SAFEINTEGER);
1914     GateRef value = acc_.GetValueIn(gate, 0);
1915     Environment env(gate, circuit_, &builder_);
1916     GateRef result = BuildTaggedIsInteger(gate, value, op == OpCode::NUMBER_IS_SAFEINTEGER);
1917 
1918     acc_.ReplaceGate(gate, builder_.GetStateDepend(), result);
1919 }
1920 
LowerNumberIsNaN(GateRef gate)1921 void TypedNativeInlineLowering::LowerNumberIsNaN(GateRef gate)
1922 {
1923     GateRef value = acc_.GetValueIn(gate, 0);
1924     Environment env(gate, circuit_, &builder_);
1925     GateRef result = builder_.DoubleIsNAN(value);
1926 
1927     acc_.ReplaceGate(gate, builder_.GetStateDepend(), result);
1928 }
1929 
LowerNumberParseInt(GateRef gate)1930 void TypedNativeInlineLowering::LowerNumberParseInt(GateRef gate)
1931 {
1932     Environment env(gate, circuit_, &builder_);
1933 
1934     Label exit(&builder_);
1935     Label slowPath(&builder_);
1936     Label msgIsString(&builder_);
1937     Label radixIsSpecial(&builder_);
1938     Label radixIsSpecialInt(&builder_);
1939 
1940     DEFVALUE(result, (&builder_), VariableType::JS_ANY(), builder_.Undefined());
1941     DEFVALUE(radix, (&builder_), VariableType::INT32(), builder_.Int32(0));
1942     GateRef msg = acc_.GetValueIn(gate, 0);
1943     GateRef arg2 = acc_.GetValueIn(gate, 1);
1944 
1945     builder_.Branch(builder_.TaggedIsString(msg), &msgIsString, &slowPath);
1946 
1947     builder_.Bind(&msgIsString);
1948     {
1949         builder_.Branch(builder_.TaggedIsUndefined(arg2), &radixIsSpecialInt, &radixIsSpecial);
1950         builder_.Bind(&radixIsSpecial);
1951         {
1952             Label radixIsInt(&builder_);
1953             builder_.Branch(builder_.TaggedIsInt(arg2), &radixIsInt, &slowPath);
1954             builder_.Bind(&radixIsInt);
1955             {
1956                 radix = builder_.GetInt32OfTInt(arg2);
1957                 builder_.Jump(&radixIsSpecialInt);
1958             }
1959         }
1960         builder_.Bind(&radixIsSpecialInt);
1961         {
1962             GateRef glue = acc_.GetGlueFromArgList();
1963             result = builder_.CallNGCRuntime(glue, RTSTUB_ID(StringToNumber), Gate::InvalidGateRef,
1964                 { msg, *radix }, gate);
1965             builder_.Jump(&exit);
1966         }
1967     }
1968     builder_.Bind(&slowPath);
1969     {
1970         GateRef glue = acc_.GetGlueFromArgList();
1971         // this may return exception
1972         result = builder_.CallRuntime(glue, RTSTUB_ID(ParseInt), Gate::InvalidGateRef, {msg, arg2}, gate);
1973         builder_.Jump(&exit);
1974     }
1975 
1976     builder_.Bind(&exit);
1977     ReplaceGateWithPendingException(
1978         gate, acc_.GetGlueFromArgList(), builder_.GetState(), builder_.GetDepend(), *result);
1979 }
1980 
LowerNumberParseFloat(GateRef gate)1981 void TypedNativeInlineLowering::LowerNumberParseFloat(GateRef gate)
1982 {
1983     Environment env(gate, circuit_, &builder_);
1984 
1985     DEFVALUE(result, (&builder_), VariableType::FLOAT64(), builder_.HoleConstant());
1986     Label slowPath(&builder_);
1987     Label exit(&builder_);
1988 
1989     Label definedMsg(&builder_);
1990     Label undefinedMsg(&builder_);
1991     GateRef msg = acc_.GetValueIn(gate, 0);
1992     builder_.Branch(builder_.BoolNot(builder_.TaggedIsUndefined(msg)), &definedMsg, &undefinedMsg);
1993     builder_.Bind(&definedMsg);
1994     {
1995         auto frameState = acc_.GetFrameState(gate);
1996         builder_.DeoptCheck(builder_.TaggedIsString(msg), frameState, DeoptType::NOTSTRING1);
1997         Label isIntegerStr(&builder_);
1998         Label notIntegerStr(&builder_);
1999         Label exitIntegerStr(&builder_);
2000         builder_.Branch(builder_.IsIntegerString(msg), &isIntegerStr, &notIntegerStr);
2001         builder_.Bind(&isIntegerStr);
2002         {
2003             result = builder_.ChangeInt32ToFloat64(builder_.GetRawHashFromString(msg));
2004             builder_.Jump(&exitIntegerStr);
2005         }
2006         builder_.Bind(&notIntegerStr);
2007         {
2008             GateRef glue = acc_.GetGlueFromArgList();
2009             auto taggedDouble = builder_.CallNGCRuntime(glue, RTSTUB_ID(NumberHelperStringToDouble),
2010                                                         Gate::InvalidGateRef, { msg }, gate);
2011             result = builder_.GetDoubleOfTDouble(taggedDouble);
2012             builder_.Jump(&exitIntegerStr);
2013         }
2014         builder_.Bind(&exitIntegerStr);
2015         builder_.Jump(&exit);
2016     }
2017     builder_.Bind(&undefinedMsg);
2018     {
2019         result = builder_.Double(base::NAN_VALUE);
2020         builder_.Jump(&exit);
2021     }
2022     builder_.Bind(&exit);
2023     acc_.ReplaceGate(gate, builder_.GetStateDepend(), *result);
2024 }
2025 
LowerToCommonStub(GateRef gate,CommonStubCSigns::ID id)2026 void TypedNativeInlineLowering::LowerToCommonStub(GateRef gate, CommonStubCSigns::ID id)
2027 {
2028     Environment env(gate, circuit_, &builder_);
2029     GateRef glue = acc_.GetGlueFromArgList();
2030     std::vector<GateRef> args {glue};
2031     size_t numIn = acc_.GetNumValueIn(gate);
2032     for (size_t idx = 0; idx < numIn; idx++) {
2033         args.emplace_back(acc_.GetValueIn(gate, idx));
2034     }
2035     GateRef ret = builder_.CallStub(glue, gate, id, args);
2036     acc_.ReplaceGate(gate, builder_.GetStateDepend(), ret);
2037 }
2038 
LowerDateGetTime(GateRef gate)2039 void TypedNativeInlineLowering::LowerDateGetTime(GateRef gate)
2040 {
2041     Environment env(gate, circuit_, &builder_);
2042     GateRef obj = acc_.GetValueIn(gate, 0);
2043     GateRef dateValueOffset = builder_.IntPtr(JSDate::TIME_VALUE_OFFSET);
2044     GateRef result = builder_.Load(VariableType::JS_ANY(), obj, dateValueOffset);
2045     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
2046 }
2047 
LowerGeneralWithoutArgs(GateRef gate,RuntimeStubCSigns::ID stubId)2048 void TypedNativeInlineLowering::LowerGeneralWithoutArgs(GateRef gate, RuntimeStubCSigns::ID stubId)
2049 {
2050     Environment env(gate, circuit_, &builder_);
2051     GateRef glue = acc_.GetGlueFromArgList();
2052     GateRef result = builder_.CallNGCRuntime(glue, stubId, Gate::InvalidGateRef, {glue}, gate);
2053     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
2054 }
2055 
LowerBigIntConstructor(GateRef gate)2056 void TypedNativeInlineLowering::LowerBigIntConstructor(GateRef gate)
2057 {
2058     Environment env(gate, circuit_, &builder_);
2059     Label hasException(&builder_);
2060     Label exit(&builder_);
2061     GateRef value = acc_.GetValueIn(gate, 0);
2062     GateRef glue = acc_.GetGlueFromArgList();
2063     auto result = builder_.CallRuntime(glue, RTSTUB_ID(BigIntConstructor), Gate::InvalidGateRef, {value}, gate);
2064     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
2065 }
2066 
2067 template <bool IS_SIGNED>
LowerBigIntConstructorInt32(GateRef gate)2068 void TypedNativeInlineLowering::LowerBigIntConstructorInt32(GateRef gate)
2069 {
2070     Environment env(gate, circuit_, &builder_);
2071     GateRef value = acc_.GetValueIn(gate, 0);
2072     size_t length = 1;
2073     size_t size = AlignUp(BigInt::ComputeSize(length), static_cast<size_t>(MemAlignment::MEM_ALIGN_OBJECT));
2074     GateRef sizeGate = builder_.IntPtr(size);
2075     GateRef hclass = builder_.GetGlobalConstantValue(ConstantIndex::BIGINT_CLASS_INDEX);
2076     GateRef sign = builder_.Int32(0);
2077     if constexpr (IS_SIGNED) {
2078         sign = builder_.Int32LSR(value, builder_.Int32(JSTaggedValue::INT_SIGN_BIT_OFFSET));
2079         auto temp = builder_.Int32ASR(value, builder_.Int32(JSTaggedValue::INT_SIGN_BIT_OFFSET));
2080         value = builder_.Int32Sub(builder_.Int32Xor(value, temp), temp);
2081     }
2082 
2083     // looks like code from StartAllocate to FinishAllocate must be linear
2084     builder_.StartAllocate();
2085     GateRef object = builder_.HeapAlloc(acc_.GetGlueFromArgList(), sizeGate, GateType::TaggedValue(),
2086                                         RegionSpaceFlag::IN_SHARED_NON_MOVABLE);
2087     // initialization
2088     builder_.StoreConstOffset(VariableType::JS_POINTER(), object, JSObject::HCLASS_OFFSET, hclass,
2089                               MemoryAttribute::NeedBarrierAndAtomic());
2090     builder_.StoreConstOffset(VariableType::INT32(), object, BigInt::LENGTH_OFFSET, builder_.Int32(length));
2091     builder_.StoreConstOffset(VariableType::INT32(), object, BigInt::BIT_FIELD_OFFSET, sign);
2092     builder_.StoreConstOffset(VariableType::INT32(), object, BigInt::DATA_OFFSET, value);
2093     GateRef ret = builder_.FinishAllocate(object);
2094 
2095     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), ret);
2096 }
2097 
BuildTaggedPointerOverflowInt32(GateRef value)2098 GateRef TypedNativeInlineLowering::BuildTaggedPointerOverflowInt32(GateRef value)
2099 {
2100     GateRef intValue = builder_.ChangeFloat64ToInt32(
2101         builder_.CastInt64ToFloat64(builder_.ChangeTaggedPointerToInt64(value)));
2102     return builder_.BitOr(builder_.Int32LessThanOrEqual(intValue, builder_.Int32(INT32_MIN)),
2103                           builder_.Int32GreaterThanOrEqual(intValue, builder_.Int32(INT32_MAX)));
2104 }
2105 
LowerStringCharCodeAt(GateRef gate)2106 void TypedNativeInlineLowering::LowerStringCharCodeAt(GateRef gate)
2107 {
2108     Environment env(gate, circuit_, &builder_);
2109 
2110     GateRef thisValue = acc_.GetValueIn(gate, 0); // 0: first argument
2111     GateRef pos = acc_.GetValueIn(gate, 1); // 1: second argument
2112     GateRef glue = acc_.GetGlueFromArgList();
2113     DEFVALUE(result, (&builder_), VariableType::JS_ANY(), builder_.Undefined());
2114     Label posIsValid(&builder_);
2115     Label posNotValid(&builder_);
2116     Label exit(&builder_);
2117 
2118     GateRef strLen = builder_.GetLengthFromString(thisValue);
2119     BRANCH_CIR(builder_.Int32UnsignedLessThan(pos, strLen), &posIsValid, &posNotValid);
2120     builder_.Bind(&posIsValid);
2121     {
2122         BuiltinsStringStubBuilder stringBuilder(builder_.GetCurrentEnvironment());
2123         result = stringBuilder.FastStringCharCodeAt(glue, thisValue, pos);
2124         builder_.Jump(&exit);
2125     }
2126     builder_.Bind(&posNotValid);
2127     {
2128         result = builder_.DoubleToTaggedDoublePtr(builder_.Double(base::NAN_VALUE));
2129         builder_.Jump(&exit);
2130     }
2131     builder_.Bind(&exit);
2132     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result);
2133 }
2134 
LowerStringSubstring(GateRef gate)2135 void TypedNativeInlineLowering::LowerStringSubstring(GateRef gate)
2136 {
2137     Environment env(gate, circuit_, &builder_);
2138 
2139     GateRef thisValue = acc_.GetValueIn(gate, 0); // 0: the first parameter
2140     GateRef startTag = acc_.GetValueIn(gate, 1); // 1: the second parameter
2141     auto argc = acc_.GetNumValueIn(gate);
2142     GateRef endTag;
2143     if (argc < 3) { // 3: the 2nd parameter of substring is optional
2144         endTag = builder_.GetLengthFromString(thisValue);
2145     } else {
2146         endTag = acc_.GetValueIn(gate, 2); // 2: the third parameter
2147     }
2148     GateRef glue = acc_.GetGlueFromArgList();
2149     DEFVALUE(result, (&builder_), VariableType::JS_POINTER(), builder_.Int32ToTaggedPtr(builder_.Int32(-1)));
2150     DEFVALUE(start, (&builder_), VariableType::INT32(), builder_.Int32(0));
2151     DEFVALUE(end, (&builder_), VariableType::INT32(), builder_.Int32(0));
2152     DEFVALUE(from, (&builder_), VariableType::INT32(), builder_.Int32(0));
2153     DEFVALUE(to, (&builder_), VariableType::INT32(), builder_.Int32(0));
2154     Label next(&builder_);
2155     Label countStart(&builder_);
2156     Label startTagIsInt(&builder_);
2157     Label startTagNotInt(&builder_);
2158     Label endTagIsInt(&builder_);
2159     Label endTagNotInt(&builder_);
2160     GateRef length = builder_.GetLengthFromString(thisValue);
2161 
2162     if (acc_.GetMachineType(startTag) == MachineType::I64) {
2163         BRANCH_CIR(builder_.TaggedIsInt(startTag), &startTagIsInt, &startTagNotInt);
2164         builder_.Bind(&startTagIsInt);
2165         start = builder_.GetInt32OfTInt(startTag);
2166         builder_.Jump(&next);
2167         builder_.Bind(&startTagNotInt);
2168         {
2169             start = builder_.SaturateTruncDoubleToInt32(glue, builder_.GetDoubleOfTDouble(startTag));
2170             builder_.Jump(&next);
2171         }
2172     } else {
2173         start = NumberToInt32(startTag);
2174         builder_.Jump(&next);
2175     }
2176     builder_.Bind(&next);
2177     {
2178         if (acc_.GetMachineType(endTag) == MachineType::I64) {
2179             BRANCH_CIR(builder_.TaggedIsInt(endTag), &endTagIsInt, &endTagNotInt);
2180             builder_.Bind(&endTagIsInt);
2181             end = builder_.GetInt32OfTInt(endTag);
2182             builder_.Jump(&countStart);
2183             builder_.Bind(&endTagNotInt);
2184             {
2185                 end = builder_.SaturateTruncDoubleToInt32(glue, builder_.GetDoubleOfTDouble(endTag));
2186                 builder_.Jump(&countStart);
2187             }
2188         } else {
2189             end = NumberToInt32(endTag);
2190             builder_.Jump(&countStart);
2191         }
2192     }
2193     builder_.Bind(&countStart);
2194     GateRef zero = builder_.Int32(0);
2195     GateRef finalStart = BuildIntMinMax<false>(BuildIntMinMax<true>(*start, zero), length);
2196     GateRef finalEnd = BuildIntMinMax<false>(BuildIntMinMax<true>(*end, zero), length);
2197     from = BuildIntMinMax<false>(finalStart, finalEnd);
2198     to = BuildIntMinMax<true>(finalStart, finalEnd);
2199     const CallSignature *cs = BuiltinsStubCSigns::Get(BuiltinsStubCSigns::ID::StringSubstring);
2200     BuiltinsStringStubBuilder stringBuilder(const_cast<CallSignature *>(cs), &env);
2201     GateRef len = builder_.Int32Sub(*to, *from);
2202     result = stringBuilder.GetSubString(glue, thisValue, *from, len);
2203     acc_.ReplaceGate(gate, builder_.GetStateDepend(), *result);
2204 }
2205 
LowerStringSubStr(GateRef gate)2206 void TypedNativeInlineLowering::LowerStringSubStr(GateRef gate)
2207 {
2208     Environment env(gate, circuit_, &builder_);
2209 
2210     GateRef thisValue = acc_.GetValueIn(gate, 0); // 0: the first parameter
2211     GateRef intStart = acc_.GetValueIn(gate, 1); // 1: the second parameter
2212     GateRef lengthTag = acc_.GetValueIn(gate, 2); // 2: the third parameter
2213     GateRef glue = acc_.GetGlueFromArgList();
2214     DEFVALUE(result, (&builder_), VariableType::JS_POINTER(), builder_.Undefined());
2215     DEFVALUE(start, (&builder_), VariableType::INT32(), builder_.Int32(0));
2216     DEFVALUE(end, (&builder_), VariableType::INT32(), builder_.Int32(0));
2217     DEFVALUE(resultLength, (&builder_), VariableType::INT32(), builder_.Int32(0));
2218     Label exit(&builder_);
2219     Label next(&builder_);
2220     Label intStartIsInt(&builder_);
2221     Label intStartNotInt(&builder_);
2222     Label lengthTagIsInt(&builder_);
2223     Label lengthTagNotInt(&builder_);
2224     Label startLessZero(&builder_);
2225     Label countStart(&builder_);
2226     Label countResultLength(&builder_);
2227     Label countResult(&builder_);
2228     GateRef length = builder_.GetLengthFromString(thisValue);
2229 
2230     if (acc_.GetMachineType(intStart) == MachineType::I64) {
2231         BRANCH_CIR(builder_.TaggedIsInt(intStart), &intStartIsInt, &intStartNotInt);
2232         builder_.Bind(&intStartIsInt);
2233         start = builder_.GetInt32OfTInt(intStart);
2234         builder_.Jump(&next);
2235         builder_.Bind(&intStartNotInt);
2236         {
2237             start = builder_.SaturateTruncDoubleToInt32(glue, builder_.GetDoubleOfTDouble(intStart));
2238             builder_.Jump(&next);
2239         }
2240     } else {
2241         start = NumberToInt32(intStart);
2242         builder_.Jump(&next);
2243     }
2244     builder_.Bind(&next);
2245     {
2246         if (acc_.GetMachineType(lengthTag) == MachineType::I64) {
2247             BRANCH_CIR(builder_.TaggedIsInt(lengthTag), &lengthTagIsInt, &lengthTagNotInt);
2248             builder_.Bind(&lengthTagIsInt);
2249             end = builder_.GetInt32OfTInt(lengthTag);
2250             builder_.Jump(&countStart);
2251             builder_.Bind(&lengthTagNotInt);
2252             {
2253                 end = builder_.SaturateTruncDoubleToInt32(glue, builder_.GetDoubleOfTDouble(lengthTag));
2254                 builder_.Jump(&countStart);
2255             }
2256         } else {
2257             end = NumberToInt32(lengthTag);
2258             builder_.Jump(&countStart);
2259         }
2260     }
2261     builder_.Bind(&countStart);
2262     GateRef zero = builder_.Int32(0);
2263     BRANCH_CIR(builder_.Int32LessThan(*start, zero), &startLessZero, &countResultLength);
2264     builder_.Bind(&startLessZero);
2265     {
2266         GateRef tempStart = *start;
2267         start = BuildIntMinMax<true>(builder_.Int32Add(length, tempStart), zero);
2268         builder_.Jump(&countResultLength);
2269     }
2270     builder_.Bind(&countResultLength);
2271     {
2272         resultLength = BuildIntMinMax<false>(BuildIntMinMax<true>(*end, zero), builder_.Int32Sub(length, *start));
2273         builder_.Jump(&countResult);
2274     }
2275     builder_.Bind(&countResult);
2276     {
2277         Label resLenLessOrEqualZero(&builder_);
2278         Label resLenNotLessOrEqualZero(&builder_);
2279         builder_.Branch(builder_.Int32LessThanOrEqual(*resultLength, zero),
2280             &resLenLessOrEqualZero, &resLenNotLessOrEqualZero);
2281         builder_.Bind(&resLenLessOrEqualZero);
2282         {
2283             result = builder_.GetGlobalConstantValue(ConstantIndex::EMPTY_STRING_OBJECT_INDEX);
2284             builder_.Jump(&exit);
2285         }
2286         builder_.Bind(&resLenNotLessOrEqualZero);
2287         {
2288             const CallSignature *cs = BuiltinsStubCSigns::Get(BuiltinsStubCSigns::ID::StringSubStr);
2289             BuiltinsStringStubBuilder stringBuilder(const_cast<CallSignature *>(cs), &env);
2290             result = stringBuilder.GetFastSubString(glue, thisValue, *start, *resultLength);
2291             builder_.Jump(&exit);
2292         }
2293     }
2294     builder_.Bind(&exit);
2295     acc_.ReplaceGate(gate, builder_.GetStateDepend(), *result);
2296 }
2297 
LowerStringSlice(GateRef gate)2298 void TypedNativeInlineLowering::LowerStringSlice(GateRef gate)
2299 {
2300     Environment env(gate, circuit_, &builder_);
2301 
2302     GateRef thisValue = acc_.GetValueIn(gate, 0); // 0: the first parameter
2303     GateRef startTag = acc_.GetValueIn(gate, 1); // 1: the second parameter
2304     auto argc = acc_.GetNumValueIn(gate);
2305     GateRef endTag;
2306     if (argc < 3) { // 3: the 2nd parameter of slice is optional
2307         endTag = builder_.GetLengthFromString(thisValue);
2308     } else {
2309         endTag = acc_.GetValueIn(gate, 2); // 2: the third parameter
2310     }
2311     GateRef glue = acc_.GetGlueFromArgList();
2312     DEFVALUE(result, (&builder_), VariableType::JS_POINTER(), builder_.Undefined());
2313     DEFVALUE(start, (&builder_), VariableType::INT32(), builder_.Int32(0));
2314     DEFVALUE(end, (&builder_), VariableType::INT32(), builder_.Int32(0));
2315     DEFVALUE(from, (&builder_), VariableType::INT32(), builder_.Int32(0));
2316     DEFVALUE(to, (&builder_), VariableType::INT32(), builder_.Int32(0));
2317     Label exit(&builder_);
2318     Label next(&builder_);
2319     Label startTagIsInt(&builder_);
2320     Label startTagNotInt(&builder_);
2321     Label endTagIsInt(&builder_);
2322     Label endTagNotInt(&builder_);
2323     Label countStart(&builder_);
2324     Label countRes(&builder_);
2325     Label getTo(&builder_);
2326     Label startLessThanZero(&builder_);
2327     Label startNotLessThanZero(&builder_);
2328     GateRef length = builder_.GetLengthFromString(thisValue);
2329 
2330     if (acc_.GetMachineType(startTag) == MachineType::I64) {
2331         BRANCH_CIR(builder_.TaggedIsInt(startTag), &startTagIsInt, &startTagNotInt);
2332         builder_.Bind(&startTagIsInt);
2333         start = builder_.GetInt32OfTInt(startTag);
2334         builder_.Jump(&next);
2335         builder_.Bind(&startTagNotInt);
2336         {
2337             start = builder_.SaturateTruncDoubleToInt32(glue, builder_.GetDoubleOfTDouble(startTag));
2338             builder_.Jump(&next);
2339         }
2340     } else {
2341         start = NumberToInt32(startTag);
2342         builder_.Jump(&next);
2343     }
2344     builder_.Bind(&next);
2345     {
2346         if (acc_.GetMachineType(endTag) == MachineType::I64) {
2347             BRANCH_CIR(builder_.TaggedIsInt(endTag), &endTagIsInt, &endTagNotInt);
2348             builder_.Bind(&endTagIsInt);
2349             end = builder_.GetInt32OfTInt(endTag);
2350             builder_.Jump(&countStart);
2351             builder_.Bind(&endTagNotInt);
2352             end = builder_.SaturateTruncDoubleToInt32(glue, builder_.GetDoubleOfTDouble(endTag));
2353             builder_.Jump(&countStart);
2354         } else {
2355             end = NumberToInt32(endTag);
2356             builder_.Jump(&countStart);
2357         }
2358     }
2359     builder_.Bind(&countStart);
2360     GateRef zero = builder_.Int32(0);
2361     BRANCH_CIR(builder_.Int32LessThan(*start, zero), &startLessThanZero, &startNotLessThanZero);
2362     builder_.Bind(&startLessThanZero);
2363     {
2364         from = BuildIntMinMax<true>(builder_.Int32Add(length, *start), zero);
2365         builder_.Jump(&getTo);
2366     }
2367     builder_.Bind(&startNotLessThanZero);
2368     {
2369         from = BuildIntMinMax<false>(length, *start);
2370         builder_.Jump(&getTo);
2371     }
2372     builder_.Bind(&getTo);
2373     {
2374         Label endLessThanZero(&builder_);
2375         Label endNotLessThanZero(&builder_);
2376         BRANCH_CIR(builder_.Int32LessThan(*end, zero), &endLessThanZero, &endNotLessThanZero);
2377         builder_.Bind(&endLessThanZero);
2378         {
2379             to = BuildIntMinMax<true>(builder_.Int32Add(length, *end), zero);
2380             builder_.Jump(&countRes);
2381         }
2382         builder_.Bind(&endNotLessThanZero);
2383         {
2384             to = BuildIntMinMax<false>(length, *end);
2385             builder_.Jump(&countRes);
2386         }
2387         builder_.Bind(&countRes);
2388         {
2389             Label fromLessThanTo(&builder_);
2390             Label fromNotLessThanTo(&builder_);
2391             BRANCH_CIR(builder_.Int32LessThan(*from, *to), &fromLessThanTo, &fromNotLessThanTo);
2392             builder_.Bind(&fromLessThanTo);
2393             {
2394                 const CallSignature *cs = BuiltinsStubCSigns::Get(BuiltinsStubCSigns::ID::StringSlice);
2395                 BuiltinsStringStubBuilder stringBuilder(const_cast<CallSignature *>(cs), &env);
2396                 GateRef len = builder_.Int32Sub(*to, *from);
2397                 result = stringBuilder.GetSubString(glue, thisValue, *from, len);
2398                 builder_.Jump(&exit);
2399             }
2400             builder_.Bind(&fromNotLessThanTo);
2401             {
2402                 result = builder_.GetGlobalConstantValue(ConstantIndex::EMPTY_STRING_OBJECT_INDEX);
2403                 builder_.Jump(&exit);
2404             }
2405         }
2406     }
2407     builder_.Bind(&exit);
2408     acc_.ReplaceGate(gate, builder_.GetStateDepend(), *result);
2409 }
2410 
NumberToInt32(GateRef gate)2411 GateRef TypedNativeInlineLowering::NumberToInt32(GateRef gate)
2412 {
2413     auto machineType = acc_.GetMachineType(gate);
2414     switch (machineType) {
2415         case MachineType::I32:
2416             return gate;
2417         case MachineType::F64:
2418             if (isLiteCG_) {
2419                 return builder_.ChangeFloat64ToInt32(gate);
2420             } else {
2421                 GateRef glue = acc_.GetGlueFromArgList();
2422                 return builder_.SaturateTruncDoubleToInt32(glue, gate);
2423             }
2424         case MachineType::I1:
2425             return builder_.ZExtInt1ToInt32(gate);
2426         default:
2427             LOG_COMPILER(ERROR) << "Not Number Type";
2428             break;
2429     }
2430     return Circuit::NullGate();
2431 }
2432 
LowerObjectIs(GateRef gate)2433 void TypedNativeInlineLowering::LowerObjectIs(GateRef gate)
2434 {
2435     Environment env(gate, circuit_, &builder_);
2436     GateRef left = acc_.GetValueIn(gate, 0);
2437     GateRef right = acc_.GetValueIn(gate, 1);
2438     GateRef result = Circuit::NullGate();
2439 
2440     if (left == right) {
2441         result = builder_.TaggedTrue();
2442     } else if (TypeInfoAccessor::IsTrustedNotSameType(compilationEnv_, circuit_, chunk_, acc_, left, right)) {
2443         result = builder_.TaggedFalse();
2444     } else {
2445         GateRef glue = acc_.GetGlueFromArgList();
2446         GateRef boolRet = builder_.CallStub(glue, gate, CommonStubCSigns::SameValue, { glue, left, right});
2447         result = builder_.BooleanToTaggedBooleanPtr(boolRet);
2448     }
2449 
2450     acc_.ReplaceGate(gate, builder_.GetStateDepend(), result);
2451 }
2452 
LowerObjectGetPrototypeOf(GateRef gate)2453 void TypedNativeInlineLowering::LowerObjectGetPrototypeOf(GateRef gate)
2454 {
2455     Environment env(gate, circuit_, &builder_);
2456     GateRef glue = acc_.GetGlueFromArgList();
2457     GateRef value = acc_.GetValueIn(gate, 0);
2458     GateRef result = Circuit::NullGate();
2459 
2460     // fast handle some primitive types
2461     if (TypeInfoAccessor::IsTrustedBooleanOrNumberOrStringType(compilationEnv_, circuit_, chunk_, acc_, value)) {
2462         GateRef glueGlobalEnvOffset = builder_.IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env.Is32Bit()));
2463         GateRef glueGlobalEnv = builder_.Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset);
2464         size_t index = -1;
2465         if (TypeInfoAccessor::IsTrustedBooleanType(acc_, value)) {
2466             index = GlobalEnv::BOOLEAN_PROTOTYPE_INDEX;
2467         } else if (TypeInfoAccessor::IsTrustedNumberType(acc_, value)) {
2468             index = GlobalEnv::NUMBER_PROTOTYPE_INDEX;
2469         } else {
2470             ASSERT(TypeInfoAccessor::IsTrustedStringType(compilationEnv_, circuit_, chunk_, acc_, value));
2471             index = GlobalEnv::STRING_PROTOTYPE_INDEX;
2472         }
2473         result = builder_.GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, index);
2474     } else {
2475         GateRef object = builder_.ToObject(glue, value);
2476         result = builder_.GetPrototype(glue, object);
2477     }
2478 
2479     acc_.ReplaceGate(gate, builder_.GetStateDepend(), result);
2480 }
2481 
LowerObjectCreate(GateRef gate)2482 void TypedNativeInlineLowering::LowerObjectCreate(GateRef gate)
2483 {
2484     Environment env(gate, circuit_, &builder_);
2485     GateRef glue = acc_.GetGlueFromArgList();
2486     GateRef proto = acc_.GetValueIn(gate, 0);
2487     DEFVALUE(result, (&builder_), VariableType::JS_ANY(), builder_.Undefined());
2488 
2489     Label exception(&builder_);
2490     Label create(&builder_);
2491     Label exit(&builder_);
2492     GateRef protoCheck = LogicAndBuilder(&env)
2493         .And(builder_.BoolNot(builder_.IsEcmaObject(proto)))
2494         .And(builder_.BoolNot(builder_.TaggedIsNull(proto)))
2495         .Done();
2496     protoCheck = LogicOrBuilder(&env).Or(protoCheck).Or(builder_.TaggedIsSharedObj(proto)).Done();
2497     BRANCH_CIR(protoCheck,  &exception, &create);
2498     builder_.Bind(&exception);
2499     {
2500         GateRef taggedId = builder_.Int32(GET_MESSAGE_STRING_ID(CanNotConvertNotValidObject));
2501         builder_.CallRuntime(glue, RTSTUB_ID(ThrowTypeError), Gate::InvalidGateRef,
2502                              { builder_.Int32ToTaggedInt(taggedId) }, gate);
2503         result = builder_.ExceptionConstant();
2504         builder_.Jump(&exit);
2505     }
2506     builder_.Bind(&create);
2507     {
2508         result = builder_.OrdinaryNewJSObjectCreate(glue, proto);
2509         builder_.Jump(&exit);
2510     }
2511     builder_.Bind(&exit);
2512     acc_.ReplaceGate(gate, builder_.GetStateDepend(), *result);
2513 }
2514 
LowerObjectIsPrototypeOf(GateRef gate)2515 void TypedNativeInlineLowering::LowerObjectIsPrototypeOf(GateRef gate)
2516 {
2517     Environment env(gate, circuit_, &builder_);
2518     GateRef glue = acc_.GetGlueFromArgList();
2519     GateRef thisValue = acc_.GetValueIn(gate, 0);
2520     GateRef value = acc_.GetValueIn(gate, 1);
2521     DEFVALUE(result, (&builder_), VariableType::JS_ANY(), builder_.TaggedFalse());
2522 
2523     // 1. If Type(V) is not Object, return false.
2524     Label ecmaObject(&builder_);
2525     Label returnFalse(&builder_);
2526     Label returnException(&builder_);
2527     Label exit(&builder_);
2528     BRANCH_CIR(builder_.IsEcmaObject(value), &ecmaObject, &returnFalse);
2529     builder_.Bind(&ecmaObject);
2530     {
2531         // 2. Let O be ? ToObject(this value).
2532         GateRef obj = builder_.ToObject(glue, thisValue);
2533         Label noPendingException(&builder_);
2534         BRANCH_CIR(builder_.HasPendingException(glue), &returnException, &noPendingException);
2535         builder_.Bind(&noPendingException);
2536         {
2537             // 3. Repeat,
2538             //    a. Set V to ? V.[[GetPrototypeOf]]().
2539             //    b. If V is null, return false.
2540             //    c. If SameValue(O, V) is true, return true.
2541             DEFVALUE(proto, (&builder_), VariableType::JS_ANY(), value);
2542             Label loopHead(&builder_);
2543             Label loopEnd(&builder_);
2544             Label loopExit(&builder_);
2545             Label compare(&builder_);
2546             builder_.Jump(&loopHead);
2547             builder_.LoopBegin(&loopHead);
2548             {
2549                 BRANCH_CIR(builder_.TaggedIsNotNull(*proto), &compare, &loopExit);
2550                 builder_.Bind(&compare);
2551                 {
2552                     proto = builder_.GetPrototype(glue, *proto);
2553                     Label noPendingException1(&builder_);
2554                     BRANCH_CIR(builder_.HasPendingException(glue), &returnException, &noPendingException1);
2555                     builder_.Bind(&noPendingException1);
2556                     {
2557                         Label sameValue(&builder_);
2558                         GateRef same = builder_.CallStub(glue, gate, CommonStubCSigns::SameValue,
2559                                                          { glue, obj, *proto });
2560                         BRANCH_CIR(same, &sameValue, &loopEnd);
2561                         builder_.Bind(&sameValue);
2562                         {
2563                             result = builder_.TaggedTrue();
2564                             builder_.Jump(&exit);
2565                         }
2566                     }
2567                 }
2568             }
2569             builder_.Bind(&loopEnd);
2570             builder_.LoopEnd(&loopHead);
2571             builder_.Bind(&loopExit);
2572             {
2573                 builder_.Jump(&exit);
2574             }
2575         }
2576     }
2577     builder_.Bind(&returnFalse);
2578     {
2579         result = builder_.TaggedFalse();
2580         builder_.Jump(&exit);
2581     }
2582     builder_.Bind(&returnException);
2583     {
2584         result = builder_.ExceptionConstant();
2585         builder_.Jump(&exit);
2586     }
2587     builder_.Bind(&exit);
2588     acc_.ReplaceGate(gate, builder_.GetStateDepend(), *result);
2589 }
2590 
LowerObjectHasOwnProperty(GateRef gate)2591 void TypedNativeInlineLowering::LowerObjectHasOwnProperty(GateRef gate)
2592 {
2593     Environment env(gate, circuit_, &builder_);
2594     GateRef glue = acc_.GetGlueFromArgList();
2595     GateRef thisValue = acc_.GetValueIn(gate, 0);
2596     GateRef key = acc_.GetValueIn(gate, 1);
2597     DEFVALUE(result, (&builder_), VariableType::JS_ANY(), builder_.TaggedFalse());
2598     Label callRuntime(&builder_);
2599     Label exit(&builder_);
2600     BuiltinsObjectStubBuilder objectStubBuilder(&env, glue);
2601     objectStubBuilder.HasOwnProperty(&result, &exit, &callRuntime, thisValue, key, gate);
2602     builder_.Bind(&callRuntime);
2603     {
2604         result = builder_.CallRuntime(glue, RTSTUB_ID(ObjectPrototypeHasOwnProperty), Gate::InvalidGateRef,
2605                                       { thisValue, key }, gate);
2606         builder_.Jump(&exit);
2607     }
2608     builder_.Bind(&exit);
2609     acc_.ReplaceGate(gate, builder_.GetStateDepend(), *result);
2610 }
2611 
LowerReflectGetPrototypeOf(GateRef gate)2612 void TypedNativeInlineLowering::LowerReflectGetPrototypeOf(GateRef gate)
2613 {
2614     Environment env(gate, circuit_, &builder_);
2615     GateRef glue = acc_.GetGlueFromArgList();
2616     GateRef value = acc_.GetValueIn(gate, 0);
2617     GateRef result = builder_.GetPrototype(glue, value);  // Do not ToObject
2618     acc_.ReplaceGate(gate, builder_.GetStateDepend(), result);
2619 }
2620 
LowerReflectGet(GateRef gate)2621 void TypedNativeInlineLowering::LowerReflectGet(GateRef gate)
2622 {
2623     Environment env(gate, circuit_, &builder_);
2624     GateRef glue = acc_.GetGlueFromArgList();
2625     GateRef target = acc_.GetValueIn(gate, 0);
2626     GateRef key = acc_.GetValueIn(gate, 1);  // key is trusted string
2627     Label isEcmaObject(&builder_);
2628     Label notEcmaObject(&builder_);
2629     Label exit(&builder_);
2630     DEFVALUE(result, (&builder_), VariableType::JS_ANY(), builder_.Undefined());
2631     // 1. If Type(target) is not Object, throw a TypeError exception.
2632     BRANCH_CIR(builder_.IsEcmaObject(target), &isEcmaObject, &notEcmaObject);
2633     builder_.Bind(&isEcmaObject);
2634     {
2635         result = builder_.CallStub(glue, gate, CommonStubCSigns::DeprecatedGetPropertyByName,  // no ic
2636                                    { glue, target, key });
2637         builder_.Jump(&exit);
2638     }
2639     builder_.Bind(&notEcmaObject);
2640     {
2641         GateRef taggedId = builder_.Int32(GET_MESSAGE_STRING_ID(TargetTypeNotObject));
2642         builder_.CallRuntime(glue, RTSTUB_ID(ThrowTypeError), Gate::InvalidGateRef,
2643                              { builder_.Int32ToTaggedInt(taggedId) }, gate);
2644         result = builder_.ExceptionConstant();
2645         builder_.Jump(&exit);
2646     }
2647     builder_.Bind(&exit);
2648     acc_.ReplaceGate(gate, builder_.GetStateDepend(), *result);
2649 }
2650 
LowerReflectHas(GateRef gate)2651 void TypedNativeInlineLowering::LowerReflectHas(GateRef gate)
2652 {
2653     Environment env(gate, circuit_, &builder_);
2654     GateRef glue = acc_.GetGlueFromArgList();
2655     GateRef target = acc_.GetValueIn(gate, 0);
2656     GateRef key = acc_.GetValueIn(gate, 1);
2657     DEFVALUE(result, (&builder_), VariableType::JS_ANY(), builder_.TaggedFalse());
2658     Label afterHasOwn(&builder_);
2659     Label callRuntime(&builder_);
2660     Label exit(&builder_);
2661     BuiltinsObjectStubBuilder objectStubBuilder(&env, glue);
2662     objectStubBuilder.HasOwnProperty(&result, &afterHasOwn, &callRuntime, target, key, gate);
2663     builder_.Bind(&afterHasOwn);
2664     {
2665         BRANCH_CIR(builder_.TaggedIsTrue(*result), &exit, &callRuntime);
2666     }
2667     builder_.Bind(&callRuntime);
2668     {
2669         result = builder_.CallRuntime(glue, RTSTUB_ID(ReflectHas), Gate::InvalidGateRef, { target, key }, gate);
2670         builder_.Jump(&exit);
2671     }
2672     builder_.Bind(&exit);
2673     acc_.ReplaceGate(gate, builder_.GetStateDepend(), *result);
2674 }
2675 
LowerReflectConstruct(GateRef gate)2676 void TypedNativeInlineLowering::LowerReflectConstruct(GateRef gate)
2677 {
2678     Environment env(gate, circuit_, &builder_);
2679     GateRef glue = acc_.GetGlueFromArgList();
2680     GateRef target = acc_.GetValueIn(gate, 0);
2681     GateRef thisObj = builder_.CallStub(glue, gate, CommonStubCSigns::NewThisObjectChecked, { glue, target });
2682     Label callCtor(&builder_);
2683     Label callRuntime(&builder_);
2684     Label exit(&builder_);
2685     DEFVALUE(result, (&builder_), VariableType::JS_ANY(), builder_.UndefineConstant());
2686     BRANCH_CIR(builder_.TaggedIsHole(thisObj), &callRuntime, &callCtor);
2687     builder_.Bind(&callCtor);
2688     {
2689         std::vector<GateRef> args { glue, builder_.Int64(NUM_MANDATORY_JSFUNC_ARGS), builder_.IntPtr(0),
2690                                     target, target, thisObj };
2691         result = builder_.Construct(gate, args);
2692         builder_.Jump(&exit);
2693     }
2694     builder_.Bind(&callRuntime);
2695     {
2696         result = builder_.CallRuntime(glue, RTSTUB_ID(ReflectConstruct), Gate::InvalidGateRef, { target }, gate);
2697         builder_.Jump(&exit);
2698     }
2699     builder_.Bind(&exit);
2700     acc_.ReplaceGate(gate, builder_.GetStateDepend(), *result);
2701 }
2702 
LowerReflectApply(GateRef gate)2703 void TypedNativeInlineLowering::LowerReflectApply(GateRef gate)
2704 {
2705     Environment env(gate, circuit_, &builder_);
2706     GateRef glue = acc_.GetGlueFromArgList();
2707     GateRef target = acc_.GetValueIn(gate, 0);
2708     GateRef thisValue = acc_.GetValueIn(gate, 1);
2709     GateRef argumentsList = acc_.GetValueIn(gate, 2);
2710     GateRef result = builder_.CallRuntime(glue, RTSTUB_ID(ReflectApply), Gate::InvalidGateRef,
2711                                           { target, thisValue, argumentsList }, gate);
2712     acc_.ReplaceGate(gate, builder_.GetStateDepend(), result);
2713 }
2714 
LowerFunctionPrototypeApply(GateRef gate)2715 void TypedNativeInlineLowering::LowerFunctionPrototypeApply(GateRef gate)
2716 {
2717     Environment env(gate, circuit_, &builder_);
2718     GateRef glue = acc_.GetGlueFromArgList();
2719     GateRef thisFunc = acc_.GetValueIn(gate, 0);
2720     GateRef thisArg = acc_.GetValueIn(gate, 1);
2721     GateRef argArray = acc_.GetValueIn(gate, 2);
2722     GateRef result = builder_.CallRuntime(glue, RTSTUB_ID(FunctionPrototypeApply), Gate::InvalidGateRef,
2723                                           { thisFunc, thisArg, argArray }, gate);
2724     acc_.ReplaceGate(gate, builder_.GetStateDepend(), result);
2725 }
2726 
LowerFunctionPrototypeBind(GateRef gate)2727 void TypedNativeInlineLowering::LowerFunctionPrototypeBind(GateRef gate)
2728 {
2729     Environment env(gate, circuit_, &builder_);
2730     GateRef glue = acc_.GetGlueFromArgList();
2731     GateRef target = acc_.GetValueIn(gate, 0);
2732     GateRef thisArg = acc_.GetValueIn(gate, 1);
2733     GateRef result = builder_.CallRuntime(glue, RTSTUB_ID(FunctionPrototypeBind), Gate::InvalidGateRef,
2734                                           { target, thisArg }, gate);
2735     acc_.ReplaceGate(gate, builder_.GetStateDepend(), result);
2736 }
2737 
LowerFunctionPrototypeCall(GateRef gate)2738 void TypedNativeInlineLowering::LowerFunctionPrototypeCall(GateRef gate)
2739 {
2740     Environment env(gate, circuit_, &builder_);
2741     GateRef glue = acc_.GetGlueFromArgList();
2742     std::vector<GateRef> args = acc_.GetValueIns(gate);
2743     GateRef result = builder_.CallRuntime(glue, RTSTUB_ID(FunctionPrototypeCall), Gate::InvalidGateRef, args, gate);
2744     acc_.ReplaceGate(gate, builder_.GetStateDepend(), result);
2745 }
2746 
LowerArrayIncludesIndexOf(GateRef gate)2747 void TypedNativeInlineLowering::LowerArrayIncludesIndexOf(GateRef gate)
2748 {
2749     Environment env(gate, circuit_, &builder_);
2750     Label exit(&builder_);
2751     BuiltinsArrayStubBuilder stubBuilder(&env);
2752 
2753     using Indices = CircuitArgIndices::ArrayIncludesIndexOf;
2754     GateRef elements = acc_.GetValueIn(gate, Indices::ELEMENTS);
2755     GateRef target = acc_.GetValueIn(gate, Indices::TARGET);
2756     GateRef fromIndex = acc_.GetValueIn(gate, Indices::FROM_INDEX);
2757     GateRef len = acc_.GetValueIn(gate, Indices::LENGTH);
2758     GateRef callIDRef = acc_.GetValueIn(gate, Indices::CALL_ID);
2759     GateRef kindRef = acc_.GetValueIn(gate, Indices::ARRAY_KIND);
2760 
2761     ElementsKind kind = static_cast<ElementsKind>(acc_.GetConstantValue(kindRef));
2762     BuiltinsStubCSigns::ID callID = static_cast<BuiltinsStubCSigns::ID>(acc_.GetConstantValue(callIDRef));
2763     auto options = stubBuilder.MakeIndexOfOptions(callID, false);
2764     Variable res = stubBuilder.MakeResultVariableDefaultNotFound(options);
2765 
2766     Label arrayIsNotEmpty(&builder_);
2767     Label searchRangeIsNotEmpty(&builder_);
2768     BRANCH_CIR_UNLIKELY(builder_.Int32Equal(builder_.Int32(0), len), &exit, &arrayIsNotEmpty);
2769     builder_.Bind(&arrayIsNotEmpty);
2770     if (options.reversedOrder) {
2771         BRANCH_CIR_UNLIKELY(builder_.Int64LessThan(fromIndex, builder_.Int64(0)), &exit, &searchRangeIsNotEmpty);
2772     } else {
2773         GateRef exitCond = builder_.Int64GreaterThanOrEqual(fromIndex, builder_.ZExtInt32ToInt64(len));
2774         BRANCH_CIR_UNLIKELY(exitCond, &exit, &searchRangeIsNotEmpty)
2775     }
2776 
2777     builder_.Bind(&searchRangeIsNotEmpty);
2778     // todo: Branches for mutant tagged array (with raw int32 or raw double values)?
2779     Label undefinedBranch(&builder_);
2780     Label targetIsNotUndefined(&builder_);
2781     BRANCH_CIR_UNLIKELY(builder_.TaggedIsUndefined(target), &undefinedBranch, &targetIsNotUndefined);
2782     builder_.Bind(&undefinedBranch);
2783     res = stubBuilder.IndexOfTaggedUndefined(elements, fromIndex, len, options);
2784     builder_.Jump(&exit);
2785 
2786     builder_.Bind(&targetIsNotUndefined);
2787     GateRef glue = acc_.GetGlueFromArgList();
2788     switch (kind) {
2789         case ElementsKind::INT:
2790         case ElementsKind::HOLE_INT:
2791             res = stubBuilder.IndexOfTaggedIntElements(elements, target, fromIndex, len, options);
2792             break;
2793         case ElementsKind::NUMBER:
2794         case ElementsKind::HOLE_NUMBER:
2795             res = stubBuilder.IndexOfTaggedNumber(elements, target, fromIndex, len, options, false);
2796             break;
2797         case ElementsKind::STRING:
2798             using StringElementsCondition = BuiltinsArrayStubBuilder::StringElementsCondition;
2799             res = stubBuilder.IndexOfStringElements(glue, elements, target, fromIndex, len, options,
2800                 StringElementsCondition::MUST_BE_STRING);
2801             break;
2802         case ElementsKind::HOLE_STRING:
2803             res = stubBuilder.IndexOfStringElements(glue, elements, target, fromIndex, len, options,
2804                 StringElementsCondition::MAY_BE_HOLE);
2805             break;
2806         case ElementsKind::OBJECT:
2807         case ElementsKind::HOLE_OBJECT:
2808             res = stubBuilder.IndexOfBigIntOrObjectElements(glue, elements, target, fromIndex, len, options);
2809             break;
2810         default:
2811             res = stubBuilder.IndexOfGeneric(glue, elements, target, fromIndex, len, options);
2812             break;
2813     }
2814     builder_.Jump(&exit);
2815 
2816     builder_.Bind(&exit);
2817     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *res);
2818 }
2819 
LowerArrayIteratorBuiltin(GateRef gate)2820 void TypedNativeInlineLowering::LowerArrayIteratorBuiltin(GateRef gate)
2821 {
2822     Environment env(gate, circuit_, &builder_);
2823     GateRef thisArray = acc_.GetValueIn(gate, 0);
2824     GateRef callIDRef = acc_.GetValueIn(gate, 1);
2825     BuiltinsStubCSigns::ID callID = static_cast<BuiltinsStubCSigns::ID>(acc_.GetConstantValue(callIDRef));
2826     IterationKind iterationKind = GetArrayIterKindFromBuilin(callID);
2827 
2828     GateRef glue = acc_.GetGlueFromArgList();
2829     GateRef glueGlobalEnvOffset = builder_.IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env.Is32Bit()));
2830     GateRef glueGlobalEnv = builder_.Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset);
2831     GateRef prototype = builder_.GetGlobalEnvValue(
2832         VariableType::JS_POINTER(), glueGlobalEnv, GlobalEnv::ARRAY_ITERATOR_PROTOTYPE_INDEX);
2833 
2834     GateRef iteratorHClass = builder_.GetGlobalConstantValue(ConstantIndex::JS_ARRAY_ITERATOR_CLASS_INDEX);
2835     GateRef offset = builder_.IntPtr(JSHClass::PROTOTYPE_OFFSET);
2836     builder_.Store(VariableType::JS_POINTER(), glue, iteratorHClass, offset, prototype);
2837 
2838     GateRef result = AllocateArrayIterator(glue, thisArray, iteratorHClass, iterationKind);
2839     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
2840 }
2841 
GetArrayIterKindFromBuilin(BuiltinsStubCSigns::ID callID)2842 IterationKind TypedNativeInlineLowering::GetArrayIterKindFromBuilin(BuiltinsStubCSigns::ID callID)
2843 {
2844     switch (callID) {
2845         case BuiltinsStubCSigns::ID::ArrayEntries:
2846             return IterationKind::KEY_AND_VALUE;
2847         case BuiltinsStubCSigns::ID::ArrayKeys:
2848             return IterationKind::KEY;
2849         case BuiltinsStubCSigns::ID::ArrayValues:
2850             return IterationKind::VALUE;
2851         default:
2852             UNREACHABLE();
2853     }
2854 }
2855 
ReplaceGateWithPendingException(GateRef gate,GateRef glue,GateRef state,GateRef depend,GateRef value)2856 void TypedNativeInlineLowering::ReplaceGateWithPendingException(
2857     GateRef gate, GateRef glue, GateRef state, GateRef depend, GateRef value)
2858 {
2859     GateRef condition = builder_.HasPendingException(glue);
2860     auto ifBranch = builder_.Branch(state, condition, 1, BranchWeight::DEOPT_WEIGHT, "checkException");
2861     GateRef ifTrue = builder_.IfTrue(ifBranch);
2862     GateRef ifFalse = builder_.IfFalse(ifBranch);
2863     GateRef eDepend = builder_.DependRelay(ifTrue, depend);
2864     GateRef sDepend = builder_.DependRelay(ifFalse, depend);
2865     StateDepend success(ifFalse, sDepend);
2866     StateDepend exception(ifTrue, eDepend);
2867     acc_.ReplaceHirWithIfBranch(gate, success, exception, value);
2868 }
2869 
LowerArrayForEach(GateRef gate)2870 void TypedNativeInlineLowering::LowerArrayForEach(GateRef gate)
2871 {
2872     Environment env(gate, circuit_, &builder_);
2873     GateRef thisValue = acc_.GetValueIn(gate, 0);
2874     GateRef callBackFn = acc_.GetValueIn(gate, 1);
2875     GateRef usingThis = acc_.GetValueIn(gate, 2);
2876     GateRef glue = acc_.GetGlueFromArgList();
2877     GateRef length = builder_.GetLengthOfJSArray(thisValue);
2878     Label loopHead(&builder_);
2879     Label loopEnd(&builder_);
2880     Label exit(&builder_);
2881     Label noPendingException(&builder_);
2882     Label merge(&builder_);
2883     DEFVALUE(i, (&builder_), VariableType::INT32(), builder_.Int32(0));
2884     DEFVALUE(propKey, (&builder_), VariableType::JS_ANY(), builder_.ToTaggedIntPtr(builder_.SExtInt32ToInt64(*i)));
2885     DEFVALUE(value, (&builder_), VariableType::JS_ANY(), builder_.Hole());
2886     BRANCH_CIR(builder_.Int32LessThan(*i, length), &loopHead, &exit);
2887     builder_.LoopBegin(&loopHead);
2888     {
2889         GateRef element = builder_.LoadConstOffset(VariableType::JS_POINTER(), thisValue, JSObject::ELEMENTS_OFFSET);
2890         value = builder_.GetValueFromTaggedArray(element, *i);
2891         GateRef nativeCall = builder_.CallInternal(gate,
2892                                                    {glue,
2893                                                     builder_.Int64(6),
2894                                                     builder_.IntPtr(0),
2895                                                     callBackFn,
2896                                                     builder_.Undefined(),
2897                                                     usingThis,
2898                                                     *value,
2899                                                     *propKey,
2900                                                     thisValue},
2901                                                    acc_.TryGetPcOffset(gate));
2902         builder_.SetDepend(nativeCall);
2903         BRANCH_CIR(builder_.HasPendingException(glue), &exit, &noPendingException);
2904         builder_.Bind(&noPendingException);
2905         {
2906             i = builder_.Int32Add(*i, builder_.Int32(1));
2907             propKey = builder_.ToTaggedIntPtr(builder_.SExtInt32ToInt64(*i));
2908             BRANCH_CIR(builder_.Int32LessThan(*i, length), &loopEnd, &exit);
2909         }
2910     }
2911     builder_.Bind(&loopEnd);
2912     builder_.LoopEnd(&loopHead);
2913 
2914     builder_.Bind(&exit);
2915     ReplaceGateWithPendingException(gate, glue, builder_.GetState(), builder_.GetDepend(), builder_.UndefineConstant());
2916 }
2917 
LowerArrayFindOrFindIndex(GateRef gate)2918 void TypedNativeInlineLowering::LowerArrayFindOrFindIndex(GateRef gate)
2919 {
2920     Environment env(gate, circuit_, &builder_);
2921     BuiltinsArrayStubBuilder arrayBuilder(&env);
2922     GateRef thisValue = acc_.GetValueIn(gate, 0);
2923     GateRef callBackFn = acc_.GetValueIn(gate, 1);
2924     GateRef usingThis = acc_.GetValueIn(gate, 2);
2925     GateRef builtinFunc = acc_.GetValueIn(gate, 3);
2926     auto builtinsID = static_cast<BuiltinsStubCSigns::ID>(acc_.GetConstantValue(builtinFunc));
2927     GateRef glue = acc_.GetGlueFromArgList();
2928     GateRef length = builder_.GetLengthOfJSArray(thisValue);
2929     Label loopHead(&builder_);
2930     Label loopEnd(&builder_);
2931     Label exit(&builder_);
2932     Label noFindElement(&builder_);
2933     Label findElement(&builder_);
2934     Label returnNotFind(&builder_);
2935     Label returnFind(&builder_);
2936     Label quit(&builder_);
2937     Label noPendingException(&builder_);
2938     DEFVALUE(i, (&builder_), VariableType::INT32(), builder_.Int32(0));
2939     DEFVALUE(value, (&builder_), VariableType::JS_ANY(), builder_.Hole());
2940     DEFVALUE(res, (&builder_), VariableType::INT32(), builder_.Int32(-1));
2941     DEFVALUE(findRes, (&builder_), VariableType::JS_ANY(), builder_.UndefineConstant());
2942     BRANCH_CIR(builder_.Int32LessThan(*i, length), &loopHead, &exit);
2943     builder_.LoopBegin(&loopHead);
2944     {
2945         GateRef element = builder_.LoadConstOffset(VariableType::JS_POINTER(), thisValue, JSObject::ELEMENTS_OFFSET);
2946         value = builder_.GetValueFromTaggedArray(element, *i);
2947         GateRef nativeCall = builder_.CallInternal(gate,
2948                                                    {glue,
2949                                                     builder_.Int64(6),
2950                                                     builder_.IntPtr(0),
2951                                                     callBackFn,
2952                                                     builder_.Undefined(),
2953                                                     usingThis,
2954                                                     *value,
2955                                                     builder_.Int32ToTaggedPtr(*i),
2956                                                     thisValue},
2957                                                    acc_.TryGetPcOffset(gate));
2958         builder_.SetDepend(nativeCall);
2959         BRANCH_CIR(builder_.HasPendingException(glue), &exit, &noPendingException);
2960         builder_.Bind(&noPendingException);
2961         {
2962             BRANCH_CIR(builder_.TaggedIsTrue(builder_.FastToBoolean(nativeCall)), &findElement, &noFindElement);
2963             builder_.Bind(&noFindElement);
2964             {
2965                 i = builder_.Int32Add(*i, builder_.Int32(1));
2966                 BRANCH_CIR(builder_.Int32LessThan(*i, length), &loopEnd, &exit);
2967             }
2968         }
2969     }
2970     builder_.Bind(&loopEnd);
2971     builder_.LoopEnd(&loopHead);
2972 
2973     builder_.Bind(&findElement);
2974     {
2975         res = *i;
2976         findRes = *value;
2977         builder_.Jump(&exit);
2978     }
2979     builder_.Bind(&exit);
2980     if (builtinsID == BuiltinsStubCSigns::ID::ArrayFind) {
2981         ReplaceGateWithPendingException(gate, glue, builder_.GetState(), builder_.GetDepend(), *findRes);
2982     } else {
2983         ReplaceGateWithPendingException(gate, glue, builder_.GetState(), builder_.GetDepend(), *res);
2984     }
2985 }
2986 
LowerArrayFilter(GateRef gate)2987 void TypedNativeInlineLowering::LowerArrayFilter(GateRef gate)
2988 {
2989     Environment env(gate, circuit_, &builder_);
2990     BuiltinsArrayStubBuilder builtinsArrayStubBuilder(&env);
2991     auto pcOffset = acc_.TryGetPcOffset(gate);
2992     GateRef thisValue = acc_.GetValueIn(gate, 0);
2993     GateRef callBackFn = acc_.GetValueIn(gate, 1);
2994     GateRef usingThis = acc_.GetValueIn(gate, 2);
2995     GateRef frameState = acc_.GetValueIn(gate, 3);
2996     GateRef length = builder_.SExtInt32ToInt64(builder_.GetLengthOfJSArray(thisValue));
2997     GateRef glue = acc_.GetGlueFromArgList();
2998     GateRef lengthOffset = builder_.IntPtr(JSArray::LENGTH_OFFSET);
2999 
3000     Label lengthIsZero(&builder_);
3001     Label lengthNotZero(&builder_);
3002     Label notHole(&builder_);
3003     Label loopHead(&builder_);
3004     Label loopEnd(&builder_);
3005     Label afterLoop(&builder_);
3006     Label returnTrue(&builder_);
3007     Label exit(&builder_);
3008     Label needTrim(&builder_);
3009     Label quit(&builder_);
3010     Label noPendingException(&builder_);
3011     DEFVALUE(result, (&builder_), VariableType::JS_ANY(), builder_.Undefined());
3012     DEFVALUE(i, (&builder_), VariableType::INT64(), builder_.Int64(0));
3013     DEFVALUE(toIndex, (&builder_), VariableType::INT64(), builder_.Int64(0));
3014     DEFVALUE(propKey, (&builder_), VariableType::JS_ANY(), builder_.ToTaggedIntPtr(*i));
3015     DEFVALUE(kValue, (&builder_), VariableType::JS_ANY(), builder_.Hole());
3016     BRANCH_CIR(builder_.Int64Equal(length, builder_.Int64(0)), &lengthIsZero, &lengthNotZero)
3017     builder_.Bind(&lengthIsZero);
3018     {
3019         NewObjectStubBuilder newBuilder(&env);
3020         result = newBuilder.CreateEmptyArray(glue);
3021         builder_.Jump(&quit);
3022     }
3023     builder_.Bind(&lengthNotZero);
3024     builder_.DeoptCheck(builder_.Int64LessThanOrEqual(length, builder_.Int64(JSObject::MAX_GAP)),
3025                         frameState,
3026                         DeoptType::ARRAYLENGTHOVERMAX);
3027     GateRef newArray = builtinsArrayStubBuilder.NewArray(glue, length);
3028     GateRef newArrayEles = builder_.GetElementsArray(newArray);
3029     builder_.Jump(&loopHead);
3030     builder_.LoopBegin(&loopHead);
3031     {
3032         kValue = builtinsArrayStubBuilder.GetTaggedValueWithElementsKind(glue, thisValue, *i);
3033         GateRef callJs = builder_.CallInternal(gate,
3034                                                {glue,
3035                                                 builder_.Int64(6),
3036                                                 builder_.IntPtr(0),
3037                                                 callBackFn,
3038                                                 builder_.Undefined(),
3039                                                 usingThis,
3040                                                 *kValue,
3041                                                 *propKey,
3042                                                 thisValue},
3043                                                pcOffset);
3044         builder_.SetDepend(callJs);
3045         BRANCH_CIR(builder_.HasPendingException(glue), &quit, &noPendingException);
3046         builder_.Bind(&noPendingException);
3047         {
3048             BRANCH_CIR(builder_.TaggedIsTrue(builder_.FastToBoolean(callJs)), &returnTrue, &afterLoop);
3049             builder_.Bind(&returnTrue);
3050             {
3051                 builtinsArrayStubBuilder.SetValueWithElementsKind(
3052                     glue,
3053                     newArray,
3054                     *kValue,
3055                     *toIndex,
3056                     builder_.Boolean(true),
3057                     builder_.Int32(Elements::ToUint(ElementsKind::NONE)));
3058                 toIndex = builder_.Int64Add(*toIndex, builder_.Int64(1));
3059                 builder_.Jump(&afterLoop);
3060             }
3061         }
3062         builder_.Bind(&afterLoop);
3063         {
3064             i = builder_.Int64Add(*i, builder_.Int64(1));
3065             propKey = builder_.ToTaggedIntPtr(*i);
3066             BRANCH_CIR(builder_.Int64LessThan(*i, length), &loopEnd, &exit);
3067         }
3068     }
3069     builder_.Bind(&loopEnd);
3070     builder_.LoopEnd(&loopHead);
3071 
3072     builder_.Bind(&exit);
3073     result = newArray;
3074 
3075     BRANCH_CIR(builder_.Int64LessThan(*toIndex, length), &needTrim, &quit);
3076     builder_.Bind(&needTrim);
3077     {
3078         GateRef trim = builder_.CallNGCRuntime(
3079             glue, RTSTUB_ID(ArrayTrim), Gate::InvalidGateRef, {glue, newArrayEles, *toIndex}, Circuit::NullGate());
3080         builder_.SetDepend(trim);
3081         builder_.Store(VariableType::INT32(), glue, newArray, lengthOffset, builder_.TruncInt64ToInt32(*toIndex));
3082         builder_.Jump(&quit);
3083     }
3084     builder_.Bind(&quit);
3085     ReplaceGateWithPendingException(gate, glue, builder_.GetState(), builder_.GetDepend(), *result);
3086 }
3087 
LowerArrayMap(GateRef gate)3088 void TypedNativeInlineLowering::LowerArrayMap(GateRef gate)
3089 {
3090     Environment env(gate, circuit_, &builder_);
3091     BuiltinsArrayStubBuilder builtinsArrayStubBuilder(&env);
3092     auto pcOffset = acc_.TryGetPcOffset(gate);
3093     GateRef thisValue = acc_.GetValueIn(gate, 0);
3094     GateRef callBackFn = acc_.GetValueIn(gate, 1);
3095     GateRef usingThis = acc_.GetValueIn(gate, 2);
3096     GateRef frameState = acc_.GetValueIn(gate, 3);
3097     GateRef length = builder_.SExtInt32ToInt64(builder_.GetLengthOfJSArray(thisValue));
3098     GateRef glue = acc_.GetGlueFromArgList();
3099 
3100     Label lengthIsZero(&builder_);
3101     Label lengthNotZero(&builder_);
3102     Label notHole(&builder_);
3103     Label loopHead(&builder_);
3104     Label loopEnd(&builder_);
3105     Label returnTrue(&builder_);
3106     Label exit(&builder_);
3107     Label needTrim(&builder_);
3108     Label finish(&builder_);
3109     Label noPendingException(&builder_);
3110     DEFVALUE(result, (&builder_), VariableType::JS_ANY(), builder_.Undefined());
3111     DEFVALUE(i, (&builder_), VariableType::INT64(), builder_.Int64(0));
3112     DEFVALUE(toIndex, (&builder_), VariableType::INT64(), builder_.Int64(0));
3113     DEFVALUE(propKey, (&builder_), VariableType::JS_ANY(), builder_.ToTaggedIntPtr(*i));
3114     DEFVALUE(kValue, (&builder_), VariableType::JS_ANY(), builder_.Hole());
3115     BRANCH_CIR(builder_.Int64Equal(length, builder_.Int64(0)), &lengthIsZero, &lengthNotZero)
3116     builder_.Bind(&lengthIsZero);
3117     {
3118         NewObjectStubBuilder newBuilder(&env);
3119         result = newBuilder.CreateEmptyArray(glue);
3120         builder_.Jump(&exit);
3121     }
3122     builder_.Bind(&lengthNotZero);
3123     builder_.DeoptCheck(builder_.Int64LessThanOrEqual(length, builder_.Int64(JSObject::MAX_GAP)),
3124                         frameState,
3125                         DeoptType::ARRAYLENGTHOVERMAX);
3126     GateRef newArray = builtinsArrayStubBuilder.NewArray(glue, length);
3127     builder_.Jump(&loopHead);
3128     builder_.LoopBegin(&loopHead);
3129     {
3130         kValue = builtinsArrayStubBuilder.GetTaggedValueWithElementsKind(glue, thisValue, *i);
3131         GateRef callJs = builder_.CallInternal(gate,
3132                                                {glue,
3133                                                 builder_.Int64(6),
3134                                                 builder_.IntPtr(0),
3135                                                 callBackFn,
3136                                                 builder_.Undefined(),
3137                                                 usingThis,
3138                                                 *kValue,
3139                                                 *propKey,
3140                                                 thisValue},
3141                                                pcOffset);
3142         builder_.SetDepend(callJs);
3143         BRANCH_CIR(builder_.HasPendingException(glue), &exit, &noPendingException);
3144         builder_.Bind(&noPendingException);
3145         {
3146             builtinsArrayStubBuilder.SetValueWithElementsKind(
3147                 glue,
3148                 newArray,
3149                 callJs,
3150                 *toIndex,
3151                 builder_.Boolean(true),
3152                 builder_.Int32(Elements::ToUint(ElementsKind::NONE)));
3153             toIndex = builder_.Int64Add(*toIndex, builder_.Int64(1));
3154 
3155             i = builder_.Int64Add(*i, builder_.Int64(1));
3156             propKey = builder_.ToTaggedIntPtr(*i);
3157             BRANCH_CIR(builder_.Int64LessThan(*i, length), &loopEnd, &finish);
3158         }
3159     }
3160     builder_.Bind(&loopEnd);
3161     builder_.LoopEnd(&loopHead);
3162 
3163     builder_.Bind(&finish);
3164     {
3165         result = newArray;
3166         builder_.Jump(&exit);
3167     }
3168     builder_.Bind(&exit);
3169     ReplaceGateWithPendingException(gate, glue, builder_.GetState(), builder_.GetDepend(), *result);
3170 }
3171 
LowerArraySome(GateRef gate)3172 void TypedNativeInlineLowering::LowerArraySome(GateRef gate)
3173 {
3174     Environment env(gate, circuit_, &builder_);
3175     BuiltinsArrayStubBuilder builtinsArrayStubBuilder(&env);
3176     auto pcOffset = acc_.TryGetPcOffset(gate);
3177     GateRef thisValue = acc_.GetValueIn(gate, 0);
3178     GateRef callBackFn = acc_.GetValueIn(gate, 1);
3179     GateRef usingThis = acc_.GetValueIn(gate, 2);
3180     GateRef length = builder_.SExtInt32ToInt64(builder_.GetLengthOfJSArray(thisValue));
3181     GateRef glue = acc_.GetGlueFromArgList();
3182 
3183     Label lengthIsZero(&builder_);
3184     Label lengthNotZero(&builder_);
3185     Label notHole(&builder_);
3186     Label loopHead(&builder_);
3187     Label loopEnd(&builder_);
3188     Label afterLoop(&builder_);
3189     Label exit(&builder_);
3190     Label findElement(&builder_);
3191     Label noPendingException(&builder_);
3192     DEFVALUE(result, (&builder_), VariableType::JS_ANY(), builder_.TaggedFalse());
3193     DEFVALUE(i, (&builder_), VariableType::INT64(), builder_.Int64(0));
3194     DEFVALUE(propKey, (&builder_), VariableType::JS_ANY(), builder_.ToTaggedIntPtr(*i));
3195     DEFVALUE(kValue, (&builder_), VariableType::JS_ANY(), builder_.Hole());
3196     BRANCH_CIR(builder_.Int64Equal(length, builder_.Int64(0)), &lengthIsZero, &lengthNotZero)
3197     builder_.Bind(&lengthIsZero);
3198     {
3199         builder_.Jump(&exit);
3200     }
3201     builder_.Bind(&lengthNotZero);
3202     builder_.Jump(&loopHead);
3203     builder_.LoopBegin(&loopHead);
3204     kValue = builtinsArrayStubBuilder.GetTaggedValueWithElementsKind(glue, thisValue, *i);
3205     {
3206         GateRef callJs = builder_.CallInternal(gate,
3207                                                {glue,
3208                                                 builder_.Int64(6),
3209                                                 builder_.IntPtr(0),
3210                                                 callBackFn,
3211                                                 builder_.Undefined(),
3212                                                 usingThis,
3213                                                 *kValue,
3214                                                 *propKey,
3215                                                 thisValue},
3216                                                pcOffset);
3217         builder_.SetDepend(callJs);
3218         BRANCH_CIR(builder_.HasPendingException(glue), &exit, &noPendingException);
3219         builder_.Bind(&noPendingException);
3220         {
3221             BRANCH_CIR(builder_.TaggedIsTrue(builder_.FastToBoolean(callJs)), &findElement, &afterLoop);
3222             builder_.Bind(&afterLoop);
3223             {
3224                 i = builder_.Int64Add(*i, builder_.Int64(1));
3225                 propKey = builder_.ToTaggedIntPtr(*i);
3226                 BRANCH_CIR(builder_.Int64LessThan(*i, length), &loopEnd, &exit);
3227             }
3228         }
3229     }
3230     builder_.Bind(&loopEnd);
3231     builder_.LoopEnd(&loopHead);
3232 
3233     builder_.Bind(&findElement);
3234     {
3235         result = builder_.TaggedTrue();
3236         builder_.Jump(&exit);
3237     }
3238     builder_.Bind(&exit);
3239     ReplaceGateWithPendingException(gate, glue, builder_.GetState(), builder_.GetDepend(), *result);
3240 }
3241 
LowerArrayEvery(GateRef gate)3242 void TypedNativeInlineLowering::LowerArrayEvery(GateRef gate)
3243 {
3244     Environment env(gate, circuit_, &builder_);
3245     BuiltinsArrayStubBuilder builtinsArrayStubBuilder(&env);
3246     auto pcOffset = acc_.TryGetPcOffset(gate);
3247     GateRef thisValue = acc_.GetValueIn(gate, 0);
3248     GateRef callBackFn = acc_.GetValueIn(gate, 1);
3249     GateRef usingThis = acc_.GetValueIn(gate, 2);
3250     GateRef length = builder_.SExtInt32ToInt64(builder_.GetLengthOfJSArray(thisValue));
3251     GateRef glue = acc_.GetGlueFromArgList();
3252 
3253     Label lengthIsZero(&builder_);
3254     Label lengthNotZero(&builder_);
3255     Label notHole(&builder_);
3256     Label loopHead(&builder_);
3257     Label loopEnd(&builder_);
3258     Label afterLoop(&builder_);
3259     Label exit(&builder_);
3260     Label callResultNotTrue(&builder_);
3261     Label noPendingException(&builder_);
3262     DEFVALUE(result, (&builder_), VariableType::JS_ANY(), builder_.TaggedTrue());
3263     DEFVALUE(i, (&builder_), VariableType::INT64(), builder_.Int64(0));
3264     DEFVALUE(propKey, (&builder_), VariableType::JS_ANY(), builder_.ToTaggedIntPtr(*i));
3265     DEFVALUE(kValue, (&builder_), VariableType::JS_ANY(), builder_.Hole());
3266     BRANCH_CIR(builder_.Int64Equal(length, builder_.Int64(0)), &lengthIsZero, &lengthNotZero)
3267     builder_.Bind(&lengthIsZero);
3268     {
3269         builder_.Jump(&exit);
3270     }
3271     builder_.Bind(&lengthNotZero);
3272     builder_.Jump(&loopHead);
3273     builder_.LoopBegin(&loopHead);
3274     kValue = builtinsArrayStubBuilder.GetTaggedValueWithElementsKind(glue, thisValue, *i);
3275     {
3276         GateRef callJs = builder_.CallInternal(gate,
3277                                                {glue,
3278                                                 builder_.Int64(6),
3279                                                 builder_.IntPtr(0),
3280                                                 callBackFn,
3281                                                 builder_.Undefined(),
3282                                                 usingThis,
3283                                                 *kValue,
3284                                                 *propKey,
3285                                                 thisValue},
3286                                                pcOffset);
3287         builder_.SetDepend(callJs);
3288         BRANCH_CIR(builder_.HasPendingException(glue), &exit, &noPendingException);
3289         builder_.Bind(&noPendingException);
3290         {
3291             BRANCH_CIR(builder_.TaggedIsFalse(builder_.FastToBoolean(callJs)), &callResultNotTrue, &afterLoop);
3292             builder_.Bind(&afterLoop);
3293             {
3294                 i = builder_.Int64Add(*i, builder_.Int64(1));
3295                 propKey = builder_.ToTaggedIntPtr(*i);
3296                 BRANCH_CIR(builder_.Int64LessThan(*i, length), &loopEnd, &exit);
3297             }
3298         }
3299     }
3300     builder_.Bind(&loopEnd);
3301     builder_.LoopEnd(&loopHead);
3302 
3303     builder_.Bind(&callResultNotTrue);
3304     {
3305         result = builder_.TaggedFalse();
3306         builder_.Jump(&exit);
3307     }
3308     builder_.Bind(&exit);
3309     ReplaceGateWithPendingException(gate, glue, builder_.GetState(), builder_.GetDepend(), *result);
3310 }
3311 
LowerArrayPop(GateRef gate)3312 void TypedNativeInlineLowering::LowerArrayPop(GateRef gate)
3313 {
3314     Environment env(gate, circuit_, &builder_);
3315     Label arraylengthNotZero(&builder_);
3316     Label exit(&builder_);
3317     Label isCOWArray(&builder_);
3318     Label getElements(&builder_);
3319     Label indexLessCapacity(&builder_);
3320     Label slowGetElement(&builder_);
3321     Label setArrayLength(&builder_);
3322     Label checkTrim(&builder_);
3323     Label needTrim(&builder_);
3324     Label noTrim(&builder_);
3325     Label isHole(&builder_);
3326     GateRef thisValue = acc_.GetValueIn(gate, 0);
3327     GateRef glue = acc_.GetGlueFromArgList();
3328     builder_.DeoptCheck(
3329         builder_.IsStableArrayLengthWriteable(thisValue), acc_.GetValueIn(gate, 1), DeoptType::ARRAYLENGTHNOTWRITABLE);
3330     GateRef arrayLength = builder_.GetLengthOfJSArray(thisValue);
3331     DEFVALUE(ret, (&builder_), VariableType::JS_ANY(), builder_.UndefineConstant());
3332     BRANCH_CIR(builder_.Int32Equal(arrayLength, builder_.Int32(0)), &exit, &arraylengthNotZero);
3333     builder_.Bind(&arraylengthNotZero);
3334     {
3335         BRANCH_CIR(builder_.IsJsCOWArray(thisValue), &isCOWArray, &getElements);
3336         builder_.Bind(&isCOWArray);
3337         {
3338             builder_.CallRuntime(glue, RTSTUB_ID(CheckAndCopyArray), builder_.GetDepend(), {thisValue}, glue);
3339             builder_.Jump(&getElements);
3340         }
3341     }
3342     builder_.Bind(&getElements);
3343     {
3344         GateRef elements = builder_.GetElementsArray(thisValue);
3345         GateRef capacity = builder_.GetLengthOfTaggedArray(elements);
3346         GateRef index = builder_.Int32Sub(arrayLength, builder_.Int32(1));
3347         BRANCH_CIR(builder_.Int32LessThan(index, capacity), &indexLessCapacity, &setArrayLength);
3348         builder_.Bind(&indexLessCapacity);
3349         {
3350             GateRef result = builder_.GetValueFromTaggedArray(elements, index);
3351             BRANCH_CIR(builder_.TaggedIsHole(result), &slowGetElement, &checkTrim);
3352             builder_.Bind(&checkTrim);
3353             {
3354                 ret = result;
3355                 GateRef unused = builder_.Int32Sub(capacity, index);
3356                 BRANCH_CIR(
3357                     builder_.Int32GreaterThan(unused, builder_.Int32(TaggedArray::MAX_END_UNUSED)), &needTrim, &noTrim);
3358             }
3359             builder_.Bind(&slowGetElement);
3360             {
3361                 Label hasException(&builder_);
3362                 Label notHasException(&builder_);
3363                 GateRef element = builder_.CallStub(glue, gate, CommonStubCSigns::GetPropertyByIndex,
3364                                                     { glue, thisValue, index });
3365                 BRANCH_CIR(builder_.HasPendingException(glue), &hasException, &notHasException);
3366                 builder_.Bind(&hasException);
3367                 {
3368                     ret = builder_.ExceptionConstant();
3369                     builder_.Jump(&exit);
3370                 }
3371                 builder_.Bind(&notHasException);
3372                 {
3373                     ret = element;
3374                     builder_.Jump(&setArrayLength);
3375                 }
3376             }
3377         }
3378         builder_.Bind(&needTrim);
3379         {
3380             builder_.CallNGCRuntime(glue,
3381                                     RTSTUB_ID(ArrayTrim),
3382                                     builder_.GetDepend(),
3383                                     {glue, elements, builder_.ZExtInt32ToInt64(index)},
3384                                     Circuit::NullGate());
3385             builder_.Jump(&setArrayLength);
3386         }
3387         builder_.Bind(&noTrim);
3388         {
3389             builder_.SetValueToTaggedArray(VariableType::JS_ANY(), glue, elements, index, builder_.HoleConstant());
3390             builder_.Jump(&setArrayLength);
3391         }
3392         builder_.Bind(&setArrayLength);
3393         {
3394             GateRef lengthOffset = builder_.IntPtr(JSArray::LENGTH_OFFSET);
3395             builder_.Store(VariableType::INT32(), glue, thisValue, lengthOffset, index);
3396             builder_.Jump(&exit);
3397         }
3398     }
3399     builder_.Bind(&exit);
3400     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *ret);
3401 }
3402 
LowerArrayPush(GateRef gate)3403 void TypedNativeInlineLowering::LowerArrayPush(GateRef gate)
3404 {
3405     Environment env(gate, circuit_, &builder_);
3406     Label grow(&builder_);
3407     Label setValue(&builder_);
3408     Label setLength(&builder_);
3409     Label exit(&builder_);
3410     BuiltinsArrayStubBuilder arrayBuilder(&env);
3411     GateRef thisValue = acc_.GetValueIn(gate, 0);
3412     GateRef value = acc_.GetValueIn(gate, 1);
3413     GateRef oldLength = builder_.GetLengthOfJSArray(thisValue);
3414     GateRef glue = acc_.GetGlueFromArgList();
3415     DEFVALUE(ret, (&builder_), VariableType::JS_ANY(), builder_.Int32ToTaggedPtr(thisValue));
3416     DEFVALUE(elements, (&builder_), VariableType::JS_ANY(), builder_.UndefineConstant());
3417     GateRef newLength = builder_.Int32Add(oldLength, builder_.Int32(1));
3418     elements = builder_.GetElementsArray(thisValue);
3419     GateRef capacity = builder_.GetLengthOfTaggedArray(*elements);
3420     BRANCH_CIR(builder_.Int32GreaterThan(newLength, capacity), &grow, &setValue);
3421     builder_.Bind(&grow);
3422     {
3423         elements = builder_.CallStub(glue, gate, CommonStubCSigns::GrowElementsCapacity, {glue, thisValue, newLength});
3424         builder_.Jump(&setValue);
3425     }
3426     builder_.Bind(&setValue);
3427     {
3428         arrayBuilder.FastSetValueWithElementsKind(glue, thisValue, *elements, value, oldLength, ElementsKind::NONE,
3429                                                   true);
3430         builder_.Jump(&setLength);
3431     }
3432     builder_.Bind(&setLength);
3433     {
3434         arrayBuilder.SetArrayLength(glue, thisValue, newLength);
3435         ret = arrayBuilder.IntToTaggedPtr(newLength);
3436         builder_.Jump(&exit);
3437     }
3438     builder_.Bind(&exit);
3439     ReplaceGateWithPendingException(gate, glue, builder_.GetState(), builder_.GetDepend(), *ret);
3440 }
3441 
LowerArraySlice(GateRef gate)3442 void TypedNativeInlineLowering::LowerArraySlice(GateRef gate)
3443 {
3444     Environment env(gate, circuit_, &builder_);
3445     Label exit(&builder_);
3446     Label checkIndexDone(&builder_);
3447     Label sliceCountIsZero(&builder_);
3448     Label sliceCountIsNotZero(&builder_);
3449     Label inThisEles(&builder_);
3450     Label outThisEles(&builder_);
3451 
3452     Label indexInRange(&builder_);
3453     Label setElementToNewArray(&builder_);
3454 
3455     GateRef thisArray = acc_.GetValueIn(gate, 0);
3456     GateRef startHandler = acc_.GetValueIn(gate, 1);
3457     GateRef endHandler = acc_.GetValueIn(gate, 2);
3458     GateRef frameState = acc_.GetValueIn(gate, 3);
3459     GateRef length = builder_.GetLengthOfJSArray(thisArray);
3460     GateRef glue = acc_.GetGlueFromArgList();
3461     DEFVALUE(start, (&builder_), VariableType::INT32(), builder_.Int32(0));
3462     DEFVALUE(end, (&builder_), VariableType::INT32(), length);
3463     DEFVALUE(res, (&builder_), VariableType::JS_ANY(), builder_.UndefineConstant());
3464 
3465     CheckAndCalcuSliceIndex(length, startHandler, endHandler, &exit, &checkIndexDone, &res, &start, &end);
3466     builder_.Bind(&checkIndexDone);
3467     GateRef sliceCount = builder_.Int32Sub(*end, *start);
3468     builder_.Branch(builder_.Int32Equal(sliceCount, builder_.Int32(0)), &sliceCountIsZero, &sliceCountIsNotZero);
3469     builder_.Bind(&sliceCountIsZero);
3470     {
3471         NewObjectStubBuilder newObject(&env);
3472         res = newObject.CreateEmptyArray(glue);
3473         builder_.Jump(&exit);
3474     }
3475     builder_.Bind(&sliceCountIsNotZero);
3476     builder_.DeoptCheck(builder_.Int32LessThanOrEqual(sliceCount, builder_.Int32(JSObject::MAX_GAP)),
3477                         frameState,
3478                         DeoptType::ARRAYLENGTHOVERMAX);
3479     BuiltinsArrayStubBuilder arrayBuilder(&env);
3480     GateRef newArray = arrayBuilder.NewArray(glue, sliceCount);
3481     GateRef newArrayElements = builder_.GetElementsArray(newArray);
3482     GateRef thisElements = builder_.GetElementsArray(thisArray);
3483     GateRef thisElementsLen = builder_.GetLengthOfTaggedArray(thisElements);
3484     BRANCH_CIR(
3485         builder_.Int32GreaterThan(thisElementsLen, builder_.Int32Add(*start, sliceCount)), &inThisEles, &outThisEles);
3486     builder_.Bind(&inThisEles);
3487     {
3488         Label loopHead(&builder_);
3489         Label loopEnd(&builder_);
3490         Label copyElement(&builder_);
3491         Label loopExit(&builder_);
3492         Label afterLoop(&builder_);
3493         DEFVALUE(i, (&builder_), VariableType::INT32(), builder_.Int32(0));
3494         builder_.Jump(&loopHead);
3495         builder_.LoopBegin(&loopHead);
3496         {
3497             BRANCH_CIR(builder_.Int32LessThan(*i, sliceCount), &copyElement, &loopExit);
3498             builder_.Bind(&copyElement);
3499             {
3500                 GateRef copyPosition = builder_.Int32Add(*start, *i);
3501                 GateRef ele = builder_.GetValueFromTaggedArray(thisElements, copyPosition);
3502                 builder_.SetValueToTaggedArray(VariableType::JS_ANY(), glue, newArrayElements, *i, ele);
3503                 builder_.Jump(&afterLoop);
3504             }
3505         }
3506         builder_.Bind(&afterLoop);
3507         {
3508             i = builder_.Int32Add(*i, builder_.Int32(1));
3509             builder_.Jump(&loopEnd);
3510         }
3511         builder_.Bind(&loopEnd);
3512         builder_.LoopEnd(&loopHead);
3513         builder_.Bind(&loopExit);
3514         {
3515             res = newArray;
3516             builder_.Jump(&exit);
3517         }
3518     }
3519     builder_.Bind(&outThisEles);
3520     {
3521         Label loopHead(&builder_);
3522         Label loopEnd(&builder_);
3523         Label copyElement(&builder_);
3524         Label loopExit(&builder_);
3525         Label afterLoop(&builder_);
3526         DEFVALUE(i, (&builder_), VariableType::INT32(), builder_.Int32(0));
3527         builder_.Jump(&loopHead);
3528         builder_.LoopBegin(&loopHead);
3529         {
3530             BRANCH_CIR(builder_.Int32LessThan(*i, sliceCount), &copyElement, &loopExit);
3531             builder_.Bind(&copyElement);
3532             {
3533                 GateRef copyPosition = builder_.Int32Add(*i, *start);
3534                 DEFVALUE(element, (&builder_), VariableType::JS_ANY(), builder_.HoleConstant());
3535                 BRANCH_CIR(
3536                     builder_.Int32GreaterThan(thisElementsLen, copyPosition), &indexInRange, &setElementToNewArray);
3537                 builder_.Bind(&indexInRange);
3538                 {
3539                     element = builder_.GetValueFromTaggedArray(thisElements, copyPosition);
3540                     builder_.Jump(&setElementToNewArray);
3541                 }
3542                 builder_.Bind(&setElementToNewArray);
3543                 {
3544                     builder_.SetValueToTaggedArray(VariableType::JS_ANY(), glue, newArrayElements, *i, *element);
3545                     builder_.Jump(&afterLoop);
3546                 }
3547             }
3548             builder_.Bind(&afterLoop);
3549             {
3550                 i = builder_.Int32Add(*i, builder_.Int32(1));
3551                 builder_.Jump(&loopEnd);
3552             }
3553             builder_.Bind(&loopEnd);
3554             builder_.LoopEnd(&loopHead);
3555             builder_.Bind(&loopExit);
3556             {
3557                 res = newArray;
3558                 builder_.Jump(&exit);
3559             }
3560         }
3561     }
3562     builder_.Bind(&exit);
3563     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *res);
3564 }
3565 
CheckAndCalcuSliceIndex(GateRef length,GateRef startHandler,GateRef endHandler,Label * exit,Label * checkIndexDone,Variable * res,Variable * start,Variable * end)3566 void TypedNativeInlineLowering::CheckAndCalcuSliceIndex(GateRef length,
3567                                                         GateRef startHandler,
3568                                                         GateRef endHandler,
3569                                                         Label* exit,
3570                                                         Label* checkIndexDone,
3571                                                         Variable* res,
3572                                                         Variable* start,
3573                                                         Variable* end)
3574 {
3575     Label startUseZero(&builder_);
3576     Label startNotUndef(&builder_);
3577     Label returnEmptyArray(&builder_);
3578     Label startGreaterOrEqualZero(&builder_);
3579     Label startLessZero(&builder_);
3580     Label startLessLength(&builder_);
3581     Label startCheckDone(&builder_);
3582     Label startCalcu(&builder_);
3583     Label endUseLength(&builder_);
3584     Label endNotUndef(&builder_);
3585     Label endLessZero(&builder_);
3586     Label endGreaterZero(&builder_);
3587     Label endUseMixed(&builder_);
3588     Label endUseZero(&builder_);
3589     Label checkEndLessStart(&builder_);
3590     Label endUseHandler(&builder_);
3591     BRANCH_CIR(builder_.TaggedIsUndefined(startHandler), &startUseZero, &startNotUndef);
3592     builder_.Bind(&startNotUndef);
3593     {
3594         GateRef tempStart = builder_.GetInt32OfTInt(startHandler);
3595         BRANCH_CIR(builder_.Int32LessThan(tempStart, builder_.Int32(0)), &startLessZero, &startGreaterOrEqualZero);
3596         builder_.Bind(&startGreaterOrEqualZero);
3597         {
3598             BRANCH_CIR(builder_.Int32GreaterThanOrEqual(tempStart, length), &returnEmptyArray, &startLessLength);
3599             builder_.Bind(&startLessLength);
3600             {
3601                 start->WriteVariable(tempStart);
3602                 builder_.Jump(&startCheckDone);
3603             }
3604         }
3605         builder_.Bind(&startLessZero);
3606         {
3607             GateRef negativeLength = builder_.Int32Sub(builder_.Int32(0), length);
3608             BRANCH_CIR(builder_.Int32LessThan(tempStart, negativeLength), &startUseZero, &startCalcu);
3609             builder_.Bind(&startCalcu);
3610             {
3611                 start->WriteVariable(builder_.Int32Add(tempStart, length));
3612                 builder_.Jump(&startCheckDone);
3613             }
3614         }
3615         builder_.Bind(&startUseZero);
3616         {
3617             start->WriteVariable(builder_.Int32(0));
3618             builder_.Jump(&startCheckDone);
3619         }
3620     }
3621     builder_.Bind(&startCheckDone);
3622     {
3623         BRANCH_CIR(builder_.TaggedIsUndefined(endHandler), &endUseLength, &endNotUndef);
3624         builder_.Bind(&endNotUndef);
3625         {
3626             GateRef tempEnd = builder_.GetInt32OfTInt(endHandler);
3627             BRANCH_CIR(builder_.Int32LessThan(tempEnd, builder_.Int32(0)), &endLessZero, &endGreaterZero);
3628             builder_.Bind(&endLessZero);
3629             {
3630                 GateRef endMixed = builder_.Int32Add(tempEnd, length);
3631                 BRANCH_CIR(builder_.Int32LessThan(endMixed, builder_.Int32(0)), &endUseZero, &endUseMixed);
3632                 builder_.Bind(&endUseMixed);
3633                 {
3634                     end->WriteVariable(endMixed);
3635                     builder_.Jump(&checkEndLessStart);
3636                 }
3637                 builder_.Bind(&endUseZero);
3638                 {
3639                     end->WriteVariable(builder_.Int32(0));
3640                     builder_.Jump(&checkEndLessStart);
3641                 }
3642             }
3643             builder_.Bind(&endGreaterZero);
3644             {
3645                 BRANCH_CIR(builder_.Int32GreaterThanOrEqual(tempEnd, length), &endUseLength, &endUseHandler);
3646                 builder_.Bind(&endUseHandler);
3647                 {
3648                     end->WriteVariable(tempEnd);
3649                     builder_.Jump(&checkEndLessStart);
3650                 }
3651             }
3652         }
3653         builder_.Bind(&endUseLength);
3654         {
3655             end->WriteVariable(length);
3656             builder_.Jump(&checkEndLessStart);
3657         }
3658         builder_.Bind(&checkEndLessStart);
3659         {
3660             BRANCH_CIR(builder_.Int32GreaterThan(start->ReadVariable(), end->ReadVariable()),
3661                        &returnEmptyArray,
3662                        checkIndexDone);
3663         }
3664     }
3665     builder_.Bind(&returnEmptyArray);
3666     {
3667         NewObjectStubBuilder newBuilder(builder_.GetCurrentEnvironment());
3668         res->WriteVariable(newBuilder.CreateEmptyArray(acc_.GetGlueFromArgList()));
3669         builder_.Jump(exit);
3670     }
3671 }
3672 
LowerArraySort(GateRef gate)3673 void TypedNativeInlineLowering::LowerArraySort(GateRef gate)
3674 {
3675     Environment env(gate, circuit_, &builder_);
3676     GateRef glue = acc_.GetGlueFromArgList();
3677     GateRef thisValue = acc_.GetValueIn(gate, 0);
3678     GateRef callBackFn = acc_.GetValueIn(gate, 1);
3679     BuiltinsArrayStubBuilder arrayStubBuilder(&env);
3680     DEFVALUE(result, (&builder_), VariableType::JS_ANY(), builder_.Undefined());
3681     Label slowPath(&env);
3682     Label exit(&env);
3683     arrayStubBuilder.SortAfterArgs(glue, thisValue, callBackFn, &result, &exit, &slowPath, gate);
3684     builder_.Bind(&slowPath);
3685     {
3686         result.WriteVariable(builder_.CallRuntime(glue, RTSTUB_ID(ArraySort),
3687                                                   Gate::InvalidGateRef, { thisValue }, gate));
3688         builder_.Jump(&exit);
3689     }
3690     builder_.Bind(&exit);
3691     acc_.ReplaceGate(gate, builder_.GetStateDepend(), *result);
3692 }
3693 }
3694