1/*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15#include "ecmascript/compiler/mcr_lowering.h"
16#include "ecmascript/compiler/argument_accessor.h"
17#include "ecmascript/compiler/bytecodes.h"
18#include "ecmascript/compiler/share_gate_meta_data.h"
19#include "ecmascript/compiler/share_opcodes.h"
20#include "ecmascript/compiler/pgo_type/pgo_type_manager.h"
21#include "ecmascript/global_env.h"
22#include "ecmascript/js_function.h"
23#include "ecmascript/js_hclass.h"
24#include "ecmascript/js_thread.h"
25#include "ecmascript/jspandafile/program_object.h"
26#include "ecmascript/message_string.h"
27
28namespace panda::ecmascript::kungfu {
29
30GateRef MCRLowering::VisitGate(GateRef gate)
31{
32    auto op = acc_.GetOpCode(gate);
33    switch (op) {
34        case OpCode::STATE_SPLIT:
35            DeleteStateSplit(gate);
36            break;
37        case OpCode::ARRAY_GUARDIAN_CHECK:
38            LowerArrayGuardianCheck(gate);
39            break;
40        case OpCode::HCLASS_STABLE_ARRAY_CHECK:
41            LowerHClassStableArrayCheck(gate);
42            break;
43        case OpCode::HEAP_OBJECT_CHECK:
44            LowerHeapObjectCheck(gate);
45            break;
46        case OpCode::LOAD_CONST_OFFSET:
47            LowerLoadConstOffset(gate);
48            break;
49        case OpCode::LOAD_HCLASS_FROM_CONSTPOOL:
50            LowerLoadHClassFromConstpool(gate);
51            break;
52        case OpCode::STORE_CONST_OFFSET:
53            LowerStoreConstOffset(gate);
54            break;
55        case OpCode::CONVERT_HOLE_AS_UNDEFINED:
56            LowerConvertHoleAsUndefined(gate);
57            break;
58        case OpCode::GET_GLOBAL_ENV:
59            LowerGetGlobalEnv(gate);
60            break;
61        case OpCode::GET_GLOBAL_ENV_OBJ:
62            LowerGetGlobalEnvObj(gate);
63            break;
64        case OpCode::GET_GLOBAL_ENV_OBJ_HCLASS:
65            LowerGetGlobalEnvObjHClass(gate);
66            break;
67        case OpCode::GET_GLOBAL_CONSTANT_VALUE:
68            LowerGetGlobalConstantValue(gate);
69            break;
70        case OpCode::INT32_CHECK_RIGHT_IS_ZERO:
71            LowerInt32CheckRightIsZero(gate);
72            break;
73        case OpCode::REMAINDER_IS_NEGATIVE_ZERO:
74            LowerRemainderIsNegativeZero(gate);
75            break;
76        case OpCode::FLOAT64_CHECK_RIGHT_IS_ZERO:
77            LowerFloat64CheckRightIsZero(gate);
78            break;
79        case OpCode::VALUE_CHECK_NEG_OVERFLOW:
80            LowerValueCheckNegOverflow(gate);
81            break;
82        case OpCode::OVERFLOW_CHECK:
83            LowerOverflowCheck(gate);
84            break;
85        case OpCode::INT32_UNSIGNED_UPPER_BOUND_CHECK:
86            LowerInt32UnsignedUpperBoundCheck(gate);
87            break;
88        case OpCode::INT32_DIV_WITH_CHECK:
89            LowerInt32DivWithCheck(gate);
90            break;
91        case OpCode::LEX_VAR_IS_HOLE_CHECK:
92            LowerLexVarIsHoleCheck(gate);
93            break;
94        case OpCode::IS_UNDEFINED_OR_HOLE_CHECK:
95            LowerIsUndefinedOrHoleCheck(gate);
96            break;
97        case OpCode::IS_NOT_UNDEFINED_OR_HOLE_CHECK:
98            LowerIsNotUndefinedOrHoleCheck(gate);
99            break;
100        case OpCode::IS_DATA_VIEW_CHECK:
101            LowerIsDataViewCheck(gate);
102            break;
103        case OpCode::STORE_MEMORY:
104            LowerStoreMemory(gate);
105            break;
106        case OpCode::CHECK_AND_CONVERT:
107            LowerCheckAndConvert(gate);
108            break;
109        case OpCode::TAGGED_IS_HEAP_OBJECT:
110            LowerTaggedIsHeapObject(gate);
111            break;
112        case OpCode::IS_MARKER_CELL_VALID:
113            LowerIsMarkerCellValid(gate);
114            break;
115        case OpCode::IS_SPECIFIC_OBJECT_TYPE:
116            LowerIsSpecificObjectType(gate);
117            break;
118        case OpCode::MIGRATE_FROM_HEAPVALUE_TO_RAWVALUE:
119            LowerMigrateFromHeapValueToRawValue(gate);
120            break;
121        case OpCode::MIGRATE_FROM_RAWVALUE_TO_HEAPVALUES:
122            LowerMigrateFromRawValueToHeapValues(gate);
123            break;
124        case OpCode::MIGRATE_FROM_HOLEINT_TO_HOLENUMBER:
125            LowerMigrateFromHoleIntToHoleNumber(gate);
126            break;
127        case OpCode::MIGRATE_FROM_HOLENUMBER_TO_HOLEINT:
128            LowerMigrateFromHoleNumberToHoleInt(gate);
129            break;
130        case OpCode::HEAP_OBJECT_IS_ECMA_OBJECT:
131            LowerHeapObjectIsEcmaObject(gate);
132            break;
133        case OpCode::IS_CALLABLE_CHECK:
134            LowerIsCallableCheck(gate);
135            break;
136        default:
137            break;
138    }
139    return Circuit::NullGate();
140}
141
142void MCRLowering::LowerConvertHoleAsUndefined(GateRef gate)
143{
144    Environment env(gate, circuit_, &builder_);
145
146    Label returnUndefined(&builder_);
147    Label exit(&builder_);
148    GateRef receiver = acc_.GetValueIn(gate, 0);
149    DEFVALUE(result, (&builder_), VariableType::JS_ANY(), receiver);
150
151    builder_.Branch(builder_.TaggedIsHole(*result), &returnUndefined, &exit, 1, BranchWeight::DEOPT_WEIGHT,
152                    "holeCheck");
153    builder_.Bind(&returnUndefined);
154    {
155        result = builder_.UndefineConstant();
156        builder_.Jump(&exit);
157    }
158    builder_.Bind(&exit);
159    acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result);
160}
161
162void MCRLowering::LowerLoadConstOffset(GateRef gate)
163{
164    Environment env(gate, circuit_, &builder_);
165    GateRef receiver = acc_.GetValueIn(gate, 0);
166    GateRef offset = builder_.IntPtr(acc_.GetOffset(gate));
167    VariableType type = VariableType(acc_.GetMachineType(gate), acc_.GetGateType(gate));
168    GateRef result = builder_.Load(type, receiver, offset, acc_.GetMemoryAttribute(gate));
169    acc_.ReplaceGate(gate, Circuit::NullGate(), builder_.GetDepend(), result);
170}
171
172void MCRLowering::LowerLoadHClassFromConstpool(GateRef gate)
173{
174    Environment env(gate, circuit_, &builder_);
175    GateRef constpool = acc_.GetValueIn(gate, 0);
176    uint32_t index = acc_.GetIndex(gate);
177    if (!env_->IsJitCompiler()) {
178        GateRef constPoolSize = builder_.GetLengthOfTaggedArray(constpool);
179        GateRef valVecIndex = builder_.Int32Sub(constPoolSize, builder_.Int32(ConstantPool::AOT_HCLASS_INFO_INDEX));
180        GateRef valVec = builder_.GetValueFromTaggedArray(constpool, valVecIndex);
181        GateRef hclass = builder_.GetValueFromTaggedArray(valVec, builder_.Int32(index));
182        acc_.ReplaceGate(gate, Circuit::NullGate(), builder_.GetDepend(), hclass);
183    } else {
184        JSTaggedValue hclass = env_->GetPTManager()->QueryHClassByIndexForJIT(index);
185        acc_.ReplaceGate(gate, Circuit::NullGate(), builder_.GetDepend(), builder_.TaggedValueConstant(hclass));
186    }
187}
188
189void MCRLowering::LowerStoreConstOffset(GateRef gate)
190{
191    Environment env(gate, circuit_, &builder_);
192
193    GateRef receiver = acc_.GetValueIn(gate, 0);
194    GateRef value = acc_.GetValueIn(gate, 1);
195    GateRef offset = builder_.IntPtr(acc_.GetOffset(gate));
196    VariableType type = VariableType(acc_.GetMachineType(gate), acc_.GetGateType(gate));
197    builder_.Store(type, glue_, receiver, offset, value, acc_.GetMemoryAttribute(gate));
198    acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
199}
200
201void MCRLowering::LowerHeapObjectCheck(GateRef gate)
202{
203    Environment env(gate, circuit_, &builder_);
204    GateRef frameState = acc_.GetFrameState(gate);
205    GateRef receiver = acc_.GetValueIn(gate, 0);
206
207    GateRef heapObjectCheck = builder_.TaggedIsHeapObject(receiver);
208    builder_.DeoptCheck(heapObjectCheck, frameState, DeoptType::NOTHEAPOBJECT1);
209
210    acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
211}
212
213void MCRLowering::LowerTaggedIsHeapObject(GateRef gate)
214{
215    Environment env(gate, circuit_, &builder_);
216    GateRef receiver = acc_.GetValueIn(gate, 0);
217    GateRef result = builder_.TaggedIsHeapObject(receiver);
218    acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
219}
220
221void MCRLowering::LowerIsMarkerCellValid(GateRef gate)
222{
223    Environment env(gate, circuit_, &builder_);
224    GateRef cell = acc_.GetValueIn(gate, 0);
225    GateRef result = builder_.IsMarkerCellValid(cell);
226    acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
227}
228
229void MCRLowering::LowerIsSpecificObjectType(GateRef gate)
230{
231    Environment env(gate, circuit_, &builder_);
232    JSType expectType = static_cast<JSType>(acc_.GetJSType(gate));
233    GateRef obj = acc_.GetValueIn(gate, 0);
234    GateRef result;
235    switch (expectType) {
236        case JSType::JS_MAP: {
237            result = builder_.TaggedObjectIsJSMap(obj);
238            break;
239        }
240        case JSType::JS_SET: {
241            result = builder_.TaggedObjectIsJSSet(obj);
242            break;
243        }
244        case JSType::JS_DATE: {
245            result = builder_.TaggedObjectIsJSDate(obj);
246            break;
247        }
248        case JSType::JS_ARRAY: {
249            result = builder_.TaggedObjectIsJSArray(obj);
250            break;
251        }
252        case JSType::STRING_FIRST: {
253            result = builder_.TaggedObjectIsString(obj);
254            break;
255        }
256        case JSType::JS_TYPED_ARRAY_FIRST: {
257            result = builder_.TaggedObjectIsTypedArray(obj);
258            break;
259        }
260        default: {
261            LOG_COMPILER(FATAL) << "this branch is unreachable";
262            UNREACHABLE();
263        }
264    }
265    acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
266}
267
268void MCRLowering::DeleteStateSplit(GateRef gate)
269{
270    auto depend = acc_.GetDep(gate);
271    auto frameState = acc_.GetFrameState(gate);
272    acc_.DeleteGateIfNoUse(frameState);
273    acc_.ReplaceGate(gate, Circuit::NullGate(), depend, Circuit::NullGate());
274}
275
276void MCRLowering::LowerArrayGuardianCheck(GateRef gate)
277{
278    Environment env(gate, circuit_, &builder_);
279
280    GateRef frameState = acc_.GetFrameState(gate);
281    GateRef guardiansOffset = builder_.IntPtr(JSThread::GlueData::GetStableArrayElementsGuardiansOffset(false));
282    GateRef check = builder_.Load(VariableType::BOOL(), glue_, guardiansOffset);
283    builder_.DeoptCheck(check, frameState, DeoptType::NOTSARRAY1);
284
285    acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
286}
287
288void MCRLowering::LowerHClassStableArrayCheck(GateRef gate)
289{
290    Environment env(gate, circuit_, &builder_);
291    GateRef frameState = acc_.GetFrameState(gate);
292    GateRef hclass = acc_.GetValueIn(gate, 0);
293
294    GateRef check = builder_.IsStableElements(hclass);
295    builder_.DeoptCheck(check, frameState, DeoptType::NOTSARRAY2);
296
297    acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
298}
299
300StateDepend MCRLowering::LowerConvert(StateDepend stateDepend, GateRef gate)
301{
302    Environment env(stateDepend.State(), stateDepend.Depend(), {}, circuit_, &builder_);
303    GateRef value = acc_.GetValueIn(gate);
304    ValueType dstType = acc_.GetDstType(gate);
305    GateRef result = Circuit::NullGate();
306    Label exit(&builder_);
307    switch (acc_.GetSrcType(gate)) {
308        case ValueType::BOOL:
309            ASSERT(dstType == ValueType::TAGGED_BOOLEAN);
310            result = ConvertBoolToTaggedBoolean(value);
311            break;
312        case ValueType::INT32:
313            if (dstType == ValueType::TAGGED_INT) {
314                result = ConvertInt32ToTaggedInt(value);
315            } else if (dstType == ValueType::FLOAT64) {
316                result = ConvertInt32ToFloat64(value);
317            } else {
318                ASSERT(dstType == ValueType::BOOL);
319                result = builder_.NotEqual(value, builder_.Int32(0));
320            }
321            break;
322        case ValueType::UINT32:
323            if (dstType == ValueType::TAGGED_NUMBER) {
324                result = ConvertUInt32ToTaggedNumber(value, &exit);
325            } else if (dstType == ValueType::FLOAT64) {
326                result = ConvertUInt32ToFloat64(value);
327            } else {
328                ASSERT(dstType == ValueType::BOOL);
329                result = builder_.NotEqual(value, builder_.Int32(0));
330            }
331            break;
332        case ValueType::FLOAT64:
333            if (dstType == ValueType::TAGGED_DOUBLE) {
334                result = ConvertFloat64ToTaggedDouble(value);
335            } else if (dstType == ValueType::INT32) {
336                result = ConvertFloat64ToInt32(value, &exit);
337            } else {
338                ASSERT(dstType == ValueType::BOOL);
339                result = ConvertFloat64ToBool(value);
340            }
341            break;
342        case ValueType::TAGGED_BOOLEAN:
343            ASSERT((dstType == ValueType::BOOL));
344            result = ConvertTaggedBooleanToBool(value);
345            break;
346        case ValueType::TAGGED_INT:
347            ASSERT((dstType == ValueType::INT32));
348            result = ConvertTaggedIntToInt32(value);
349            break;
350        case ValueType::TAGGED_DOUBLE:
351            ASSERT((dstType == ValueType::FLOAT64));
352            result = ConvertTaggedDoubleToFloat64(value);
353            break;
354        case ValueType::CHAR: {
355            GateRef glue = acc_.GetGlueFromArgList();
356            if (dstType == ValueType::ECMA_STRING) {
357                result = builder_.CallStub(glue, gate, CommonStubCSigns::CreateStringBySingleCharCode, { glue, value });
358            } else if (dstType == ValueType::INT32) {
359                result = builder_.CallStub(glue, gate, CommonStubCSigns::ConvertCharToInt32, { glue, value });
360            } else {
361                ASSERT((dstType == ValueType::FLOAT64));
362                result = builder_.CallStub(glue, gate, CommonStubCSigns::ConvertCharToDouble, { glue, value });
363            }
364            break;
365        }
366        case ValueType::HOLE_INT:
367            if (dstType == ValueType::TAGGED_INT) {
368                result = ConvertSpecialHoleIntToTagged(value, &exit);
369            }
370            break;
371        case ValueType::HOLE_DOUBLE:
372            if (dstType == ValueType::TAGGED_DOUBLE) {
373                result = ConvertSpecialHoleDoubleToTagged(value, &exit);
374            }
375            break;
376        default:
377            LOG_COMPILER(FATAL) << "this branch is unreachable";
378            break;
379    }
380    acc_.ReplaceGate(gate, Circuit::NullGate(), Circuit::NullGate(), result);
381    return builder_.GetStateDepend();
382}
383
384GateRef MCRLowering::ConvertSpecialHoleIntToTagged(GateRef gate, Label* exit)
385{
386    Label returnUndefined(&builder_);
387    Label returnTaggedInt(&builder_);
388    DEFVALUE(result, (&builder_), VariableType::JS_ANY(), builder_.HoleConstant());
389
390    builder_.Branch(builder_.IsSpecialHole(gate), &returnUndefined, &returnTaggedInt, 1, BranchWeight::DEOPT_WEIGHT,
391                    "specialHoleCheck");
392    builder_.Bind(&returnUndefined);
393    {
394        result = builder_.UndefineConstant();
395        builder_.Jump(exit);
396    }
397    builder_.Bind(&returnTaggedInt);
398    {
399        GateRef rawInt = builder_.TruncInt64ToInt32(gate);
400        result = ConvertInt32ToTaggedInt(rawInt);
401        builder_.Jump(exit);
402    }
403    builder_.Bind(exit);
404    return *result;
405}
406
407GateRef MCRLowering::ConvertSpecialHoleDoubleToTagged(GateRef gate, Label* exit)
408{
409    Label returnUndefined(&builder_);
410    Label returnTaggedDouble(&builder_);
411    DEFVALUE(result, (&builder_), VariableType::JS_ANY(), builder_.HoleConstant());
412
413    builder_.Branch(builder_.IsSpecialHole(gate), &returnUndefined, &returnTaggedDouble, 1, BranchWeight::DEOPT_WEIGHT,
414                    "specialHoleCheck");
415    builder_.Bind(&returnUndefined);
416    {
417        result = builder_.UndefineConstant();
418        builder_.Jump(exit);
419    }
420    builder_.Bind(&returnTaggedDouble);
421    {
422        GateRef rawDouble = builder_.CastInt64ToFloat64(gate);
423        result = ConvertFloat64ToTaggedDouble(rawDouble);
424        builder_.Jump(exit);
425    }
426    builder_.Bind(exit);
427    return *result;
428}
429
430GateRef MCRLowering::ConvertTaggedNumberToBool(GateRef gate, Label *exit)
431{
432    DEFVALUE(result, (&builder_), VariableType::BOOL(), builder_.Boolean(false));
433    Label isInt(&builder_);
434    Label isDouble(&builder_);
435    Label toInt32(&builder_);
436    BRANCH_CIR(builder_.TaggedIsInt(gate), &isInt, &isDouble);
437    builder_.Bind(&isInt);
438    {
439        GateRef intVal = builder_.GetInt64OfTInt(gate);
440        result = builder_.NotEqual(intVal, builder_.Int64(0));
441    }
442    builder_.Jump(exit);
443    builder_.Bind(&isDouble);
444    {
445        GateRef doubleVal = builder_.GetDoubleOfTDouble(gate);
446        result = ConvertFloat64ToBool(doubleVal);
447    }
448    builder_.Jump(exit);
449    builder_.Bind(exit);
450    return *result;
451}
452
453GateRef MCRLowering::ConvertTaggedNumberToInt32(GateRef gate, Label *exit)
454{
455    DEFVALUE(result, (&builder_), VariableType::INT32(), builder_.Int32(0));
456    Label isInt(&builder_);
457    Label isDouble(&builder_);
458    Label toInt32(&builder_);
459    BRANCH_CIR(builder_.TaggedIsInt(gate), &isInt, &isDouble);
460    builder_.Bind(&isInt);
461    result = ConvertTaggedIntToInt32(gate);
462    builder_.Jump(exit);
463    builder_.Bind(&isDouble);
464    result = ConvertFloat64ToInt32(ConvertTaggedDoubleToFloat64(gate), &toInt32);
465    builder_.Jump(exit);
466    builder_.Bind(exit);
467    return *result;
468}
469
470GateRef MCRLowering::ConvertTaggedNumberToFloat64(GateRef gate, Label *exit)
471{
472    DEFVALUE(result, (&builder_), VariableType::FLOAT64(), builder_.Double(0));
473    Label isInt(&builder_);
474    Label isDouble(&builder_);
475    BRANCH_CIR(builder_.TaggedIsInt(gate), &isInt, &isDouble);
476    builder_.Bind(&isInt);
477    result = ConvertInt32ToFloat64(ConvertTaggedIntToInt32(gate));
478    builder_.Jump(exit);
479    builder_.Bind(&isDouble);
480    result = ConvertTaggedDoubleToFloat64(gate);
481    builder_.Jump(exit);
482    builder_.Bind(exit);
483    return *result;
484}
485
486void MCRLowering::LowerCheckAndConvert(GateRef gate)
487{
488    Environment env(gate, circuit_, &builder_);
489    GateRef frameState = acc_.GetFrameState(gate);
490    ValueType srcType = acc_.GetSrcType(gate);
491    Label exit(&builder_);
492    switch (srcType) {
493        case ValueType::UINT32:
494            LowerCheckUInt32AndConvert(gate, frameState);
495            break;
496        case ValueType::TAGGED_INT:
497            LowerCheckTaggedIntAndConvert(gate, frameState);
498            break;
499        case ValueType::TAGGED_DOUBLE:
500            LowerCheckTaggedDoubleAndConvert(gate, frameState, &exit);
501            break;
502        case ValueType::TAGGED_BOOLEAN:
503            LowerCheckTaggedBoolAndConvert(gate, frameState);
504            break;
505        case ValueType::TAGGED_NUMBER:
506            LowerCheckTaggedNumberAndConvert(gate, frameState, &exit);
507            break;
508        case ValueType::BOOL:
509            LowerCheckSupportAndConvert(gate, frameState);
510            break;
511        case ValueType::TAGGED_NULL:
512            LowerCheckNullAndConvert(gate, frameState);
513            break;
514        case ValueType::UNDEFINED:
515            LowerUndefinedAndConvert(gate, frameState);
516            break;
517        case ValueType::HOLE_INT:
518            LowerCheckSpecialHoleAndConvert(gate, frameState);
519            break;
520        case ValueType::HOLE_DOUBLE:
521            LowerCheckSpecialHoleAndConvert(gate, frameState);
522            break;
523        case ValueType::FLOAT64:
524            LowerCheckFloat64AndConvert(gate, frameState, &exit);
525            break;
526        default:
527            UNREACHABLE();
528    }
529}
530
531void MCRLowering::LowerCheckFloat64AndConvert(GateRef gate, GateRef frameState, Label *exit)
532{
533    GateRef value = acc_.GetValueIn(gate, 0);
534
535    GateRef result = ConvertFloat64ToInt32(value, exit);
536    GateRef check = builder_.DoubleEqual(builder_.ChangeInt32ToFloat64(result), value);
537    builder_.DeoptCheck(check, frameState, DeoptType::INT32OVERFLOW1);
538
539    acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
540}
541
542void MCRLowering::LowerCheckSpecialHoleAndConvert(GateRef gate, GateRef frameState)
543{
544    GateRef value = acc_.GetValueIn(gate, 0);
545    GateRef typeCheck = builder_.IsNotSpecialHole(value);
546    builder_.DeoptCheck(typeCheck, frameState, DeoptType::CANNOTSTORESPECAILHOLE);
547    GateRef result = Circuit::NullGate();
548    ValueType dst = acc_.GetDstType(gate);
549    if (dst == ValueType::INT32) {
550        result = builder_.TruncInt64ToInt32(value);
551    } else if (dst == ValueType::FLOAT64) {
552        result = builder_.CastInt64ToFloat64(value);
553    } else if (dst == ValueType::TAGGED_INT) {
554        GateRef rawInt = builder_.TruncInt64ToInt32(gate);
555        result = ConvertInt32ToTaggedInt(rawInt);
556    } else if (dst == ValueType::TAGGED_DOUBLE) {
557        GateRef rawDouble = builder_.CastInt64ToFloat64(value);
558        result = ConvertFloat64ToTaggedDouble(rawDouble);
559    } else {
560        UNREACHABLE();
561    }
562    acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
563}
564
565void MCRLowering::LowerCheckUInt32AndConvert(GateRef gate, GateRef frameState)
566{
567    GateRef value = acc_.GetValueIn(gate, 0);
568    GateRef upperBound = builder_.Int32(INT32_MAX);
569    GateRef check = builder_.Int32UnsignedLessThanOrEqual(value, upperBound);
570    builder_.DeoptCheck(check, frameState, DeoptType::INT32OVERFLOW1);
571    acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), value);
572}
573
574void MCRLowering::LowerCheckTaggedIntAndConvert(GateRef gate, GateRef frameState)
575{
576    GateRef value = acc_.GetValueIn(gate, 0);
577    GateRef typeCheck = builder_.TaggedIsInt(value);
578    builder_.DeoptCheck(typeCheck, frameState, DeoptType::NOTINT1);
579    GateRef result = Circuit::NullGate();
580    ValueType dst = acc_.GetDstType(gate);
581    ASSERT(dst == ValueType::INT32 || dst == ValueType::FLOAT64);
582    if (dst == ValueType::INT32) {
583        result = ConvertTaggedIntToInt32(value);
584    } else {
585        result = ConvertTaggedIntToFloat64(value);
586    }
587    acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
588}
589
590void MCRLowering::LowerCheckTaggedDoubleAndConvert(GateRef gate, GateRef frameState, Label *exit)
591{
592    GateRef value = acc_.GetValueIn(gate, 0);
593    GateRef typeCheck = builder_.TaggedIsDouble(value);
594    builder_.DeoptCheck(typeCheck, frameState, DeoptType::NOTDOUBLE1);
595    GateRef result = Circuit::NullGate();
596    ValueType dst = acc_.GetDstType(gate);
597    ASSERT(dst == ValueType::INT32 || dst == ValueType::FLOAT64);
598    if (dst == ValueType::INT32) {
599        result = ConvertTaggedDoubleToInt32(value, exit);
600    } else {
601        result = ConvertTaggedDoubleToFloat64(value);
602    }
603    acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
604}
605
606void MCRLowering::LowerCheckTaggedNumberAndConvert(GateRef gate, GateRef frameState, Label *exit)
607{
608    GateRef value = acc_.GetValueIn(gate, 0);
609    GateRef typeCheck = builder_.TaggedIsNumber(value);
610    builder_.DeoptCheck(typeCheck, frameState, DeoptType::NOTNUMBER1);
611    GateRef result = Circuit::NullGate();
612    ValueType dst = acc_.GetDstType(gate);
613    if (dst == ValueType::INT32) {
614        result = ConvertTaggedNumberToInt32(value, exit);
615    } else if (dst == ValueType::FLOAT64) {
616        result = ConvertTaggedNumberToFloat64(value, exit);
617    } else {
618        ASSERT(dst == ValueType::BOOL);
619        result = ConvertTaggedNumberToBool(value, exit);
620    }
621    acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
622}
623
624void MCRLowering::LowerCheckSupportAndConvert(GateRef gate, GateRef frameState)
625{
626    ValueType dstType = acc_.GetDstType(gate);
627    ASSERT(dstType == ValueType::INT32 || dstType == ValueType::FLOAT64);
628    bool support = acc_.IsConvertSupport(gate);
629    GateRef value = acc_.GetValueIn(gate, 0);
630
631    GateRef result = Circuit::NullGate();
632    if (dstType == ValueType::INT32) {
633        builder_.DeoptCheck(builder_.Boolean(support), frameState, DeoptType::NOTINT2);
634        result = builder_.BooleanToInt32(value);
635    } else {
636        builder_.DeoptCheck(builder_.Boolean(support), frameState, DeoptType::NOTDOUBLE2);
637        result = builder_.BooleanToFloat64(value);
638    }
639    acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
640}
641
642void MCRLowering::LowerCheckTaggedBoolAndConvert(GateRef gate, GateRef frameState)
643{
644    GateRef value = acc_.GetValueIn(gate, 0);
645    GateRef typeCheck = builder_.TaggedIsBoolean(value);
646    builder_.DeoptCheck(typeCheck, frameState, DeoptType::NOTBOOL1);
647    GateRef result = Circuit::NullGate();
648    GateRef boolValue = ConvertTaggedBooleanToBool(value);
649    if (acc_.GetDstType(gate) == ValueType::BOOL) {
650        result = boolValue;
651    } else if (acc_.GetDstType(gate) == ValueType::INT32) {
652        result = builder_.ZExtInt1ToInt32(boolValue);
653    } else if (acc_.GetDstType(gate) == ValueType::FLOAT64) {
654        result = builder_.BooleanToFloat64(boolValue);
655    } else {
656        UNREACHABLE();
657    }
658    acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
659}
660
661void MCRLowering::LowerCheckNullAndConvert(GateRef gate, GateRef frameState)
662{
663    GateRef value = acc_.GetValueIn(gate, 0);
664    GateRef typeCheck = builder_.TaggedIsNull(value);
665    builder_.DeoptCheck(typeCheck, frameState, DeoptType::NOTNULL1);
666    GateRef result = Circuit::NullGate();
667    if (acc_.GetDstType(gate) == ValueType::INT32) {
668        result = builder_.Int32(0);
669    } else if (acc_.GetDstType(gate) == ValueType::FLOAT64) {
670        result = builder_.Double(0);
671    } else if (acc_.GetDstType(gate) == ValueType::BOOL) {
672        result = builder_.False();
673    } else {
674        UNREACHABLE();
675    }
676    acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
677}
678
679void MCRLowering::LowerUndefinedAndConvert(GateRef gate, GateRef frameState)
680{
681    GateRef value = acc_.GetValueIn(gate, 0);
682    GateRef typeCheck = builder_.TaggedIsUndefined(value);
683    builder_.DeoptCheck(typeCheck, frameState, DeoptType::NOTNULL2);
684    GateRef result = Circuit::NullGate();
685    if (acc_.GetDstType(gate) == ValueType::FLOAT64) {
686        result = builder_.NanValue();
687    } else if (acc_.GetDstType(gate) == ValueType::BOOL) {
688        result = builder_.False();
689    } else if (acc_.GetDstType(gate) == ValueType::INT32) {
690        result = builder_.Int32(0);
691    } else {
692        UNREACHABLE();
693    }
694    acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
695}
696
697GateRef MCRLowering::ConvertTaggedBooleanToBool(GateRef value)
698{
699    return builder_.TaggedIsTrue(value);
700}
701
702GateRef MCRLowering::ConvertBoolToTaggedBoolean(GateRef gate)
703{
704    return builder_.BooleanToTaggedBooleanPtr(gate);
705}
706
707GateRef MCRLowering::ConvertInt32ToFloat64(GateRef gate)
708{
709    return builder_.ChangeInt32ToFloat64(gate);
710}
711
712GateRef MCRLowering::ConvertUInt32ToFloat64(GateRef gate)
713{
714    return builder_.ChangeUInt32ToFloat64(gate);
715}
716
717GateRef MCRLowering::ConvertInt32ToTaggedInt(GateRef gate)
718{
719    return builder_.Int32ToTaggedPtr(gate);
720}
721
722GateRef MCRLowering::ConvertUInt32ToTaggedNumber(GateRef gate, Label *exit)
723{
724    Label isOverFlow(&builder_);
725    Label notOverFlow(&builder_);
726    GateRef upperBound = builder_.Int32(INT32_MAX);
727    DEFVALUE(taggedVal, (&builder_), VariableType::JS_ANY(), builder_.HoleConstant());
728    BRANCH_CIR(builder_.Int32UnsignedLessThanOrEqual(gate, upperBound), &notOverFlow, &isOverFlow);
729    builder_.Bind(&notOverFlow);
730    taggedVal = builder_.Int32ToTaggedPtr(gate);
731    builder_.Jump(exit);
732    builder_.Bind(&isOverFlow);
733    taggedVal = builder_.DoubleToTaggedDoublePtr(builder_.ChangeUInt32ToFloat64(gate));
734    builder_.Jump(exit);
735    builder_.Bind(exit);
736    return *taggedVal;
737}
738
739GateRef MCRLowering::ConvertFloat64ToInt32(GateRef gate, Label *exit)
740{
741    return builder_.DoubleToInt(gate, exit);
742}
743
744GateRef MCRLowering::ConvertFloat64ToBool(GateRef gate)
745{
746    return LogicAndBuilder(builder_.GetCurrentEnvironment())
747        .And(builder_.DoubleNotEqual(gate, builder_.Double(0.0)))
748        .And(builder_.BoolNot(builder_.DoubleIsNAN(gate)))
749        .Done();
750}
751
752GateRef MCRLowering::ConvertFloat64ToTaggedDouble(GateRef gate)
753{
754    return builder_.DoubleToTaggedDoublePtr(gate);
755}
756
757GateRef MCRLowering::ConvertTaggedIntToInt32(GateRef gate)
758{
759    return builder_.GetInt32OfTInt(gate);
760}
761
762GateRef MCRLowering::ConvertTaggedIntToFloat64(GateRef gate)
763{
764    return builder_.ChangeInt32ToFloat64(builder_.GetInt32OfTInt(gate));
765}
766
767GateRef MCRLowering::ConvertTaggedDoubleToInt32(GateRef gate, Label *exit)
768{
769    return builder_.DoubleToInt(builder_.GetDoubleOfTDouble(gate), exit);
770}
771
772GateRef MCRLowering::ConvertTaggedDoubleToFloat64(GateRef gate)
773{
774    return builder_.GetDoubleOfTDouble(gate);
775}
776
777void MCRLowering::LowerGetGlobalEnv(GateRef gate)
778{
779    Environment env(gate, circuit_, &builder_);
780    GateRef glueGlobalEnvOffset = builder_.IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(false));
781    GateRef glueGlobalEnv = builder_.Load(VariableType::JS_POINTER(), glue_, glueGlobalEnvOffset);
782    acc_.ReplaceGate(gate, Circuit::NullGate(), builder_.GetDepend(), glueGlobalEnv);
783}
784
785void MCRLowering::LowerGetGlobalEnvObj(GateRef gate)
786{
787    Environment env(gate, circuit_, &builder_);
788    GateRef globalEnv = acc_.GetValueIn(gate, 0);
789    size_t index = acc_.GetIndex(gate);
790    GateRef offset = builder_.IntPtr(GlobalEnv::HEADER_SIZE + JSTaggedValue::TaggedTypeSize() * index);
791    GateRef object = builder_.Load(VariableType::JS_ANY(), globalEnv, offset);
792    acc_.ReplaceGate(gate, Circuit::NullGate(), builder_.GetDepend(), object);
793}
794
795void MCRLowering::LowerGetGlobalEnvObjHClass(GateRef gate)
796{
797    Environment env(gate, circuit_, &builder_);
798    GateRef globalEnv = acc_.GetValueIn(gate, 0);
799    size_t index = acc_.GetIndex(gate);
800    GateRef offset = builder_.IntPtr(GlobalEnv::HEADER_SIZE + JSTaggedValue::TaggedTypeSize() * index);
801    GateRef object = builder_.Load(VariableType::JS_ANY(), globalEnv, offset);
802    auto hclass = builder_.Load(VariableType::JS_POINTER(), object,
803                                builder_.IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
804    acc_.ReplaceGate(gate, Circuit::NullGate(), builder_.GetDepend(), hclass);
805}
806
807void MCRLowering::LowerGetGlobalConstantValue(GateRef gate)
808{
809    Environment env(gate, circuit_, &builder_);
810    size_t index = acc_.GetIndex(gate);
811    GateRef gConstAddr = builder_.Load(VariableType::JS_POINTER(), glue_,
812        builder_.IntPtr(JSThread::GlueData::GetGlobalConstOffset(false)));
813    GateRef constantIndex = builder_.IntPtr(JSTaggedValue::TaggedTypeSize() * index);
814    GateRef result = builder_.Load(VariableType::JS_POINTER(), gConstAddr, constantIndex);
815    acc_.ReplaceGate(gate, Circuit::NullGate(), builder_.GetDepend(), result);
816}
817
818void MCRLowering::HeapAllocateInSOld(GateRef gate)
819{
820    GateRef size = acc_.GetValueIn(gate, 0);
821    GateRef ret = builder_.CallRuntime(glue_, RTSTUB_ID(AllocateInSOld), Gate::InvalidGateRef,
822                                       {builder_.ToTaggedInt(size)}, gate);
823
824    acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), ret);
825}
826
827void MCRLowering::LowerInt32CheckRightIsZero(GateRef gate)
828{
829    Environment env(gate, circuit_, &builder_);
830    GateRef frameState = acc_.GetFrameState(gate);
831    GateRef right = acc_.GetValueIn(gate, 0);
832    GateRef rightNotZero = builder_.Int32NotEqual(right, builder_.Int32(0));
833    builder_.DeoptCheck(rightNotZero, frameState, DeoptType::MODZERO1);
834    acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
835}
836
837void MCRLowering::LowerRemainderIsNegativeZero(GateRef gate)
838{
839    Environment env(gate, circuit_, &builder_);
840    GateRef frameState = acc_.GetFrameState(gate);
841    GateRef left = acc_.GetValueIn(gate, 0);
842    GateRef right = acc_.GetValueIn(gate, 1);
843    GateRef remainderIsNegative = LogicAndBuilder(&env)
844        .And(builder_.Int32LessThan(left, builder_.Int32(0)))
845        .And(builder_.Int32Equal(builder_.Int32(0),
846            builder_.BinaryArithmetic(circuit_->Smod(), MachineType::I32, left, right, GateType::NJSValue())))
847        .Done();
848    GateRef remainderIsNotNegative = builder_.BoolNot(remainderIsNegative);
849    builder_.DeoptCheck(remainderIsNotNegative, frameState, DeoptType::REMAINDERISNEGATIVEZERO);
850    acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
851}
852
853void MCRLowering::LowerFloat64CheckRightIsZero(GateRef gate)
854{
855    Environment env(gate, circuit_, &builder_);
856    GateRef frameState = acc_.GetFrameState(gate);
857    GateRef right = acc_.GetValueIn(gate, 0);
858    GateRef rightNotZero = builder_.DoubleNotEqual(right, builder_.Double(0.0));
859    builder_.DeoptCheck(rightNotZero, frameState, DeoptType::DIVZERO1);
860    acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
861}
862
863void MCRLowering::LowerLexVarIsHoleCheck(GateRef gate)
864{
865    Environment env(gate, circuit_, &builder_);
866    GateRef frameState = acc_.GetFrameState(gate);
867    GateRef value = acc_.GetValueIn(gate, 0);
868    GateRef valueIsNotHole = builder_.TaggedIsNotHole(value);
869    builder_.DeoptCheck(valueIsNotHole, frameState, DeoptType::LEXVARISHOLE1);
870    acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
871}
872
873void MCRLowering::LowerIsUndefinedOrHoleCheck(GateRef gate)
874{
875    Environment env(gate, circuit_, &builder_);
876    GateRef frameState = acc_.GetFrameState(gate);
877    GateRef value = acc_.GetValueIn(gate, 0);
878    GateRef isNotUndefinedorHole = builder_.BoolNot(builder_.TaggedIsUndefinedOrHole(value));
879    builder_.DeoptCheck(isNotUndefinedorHole, frameState, DeoptType::ISUNDEFINEDORHOLE);
880    acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
881}
882
883void MCRLowering::LowerIsNotUndefinedOrHoleCheck(GateRef gate)
884{
885    Environment env(gate, circuit_, &builder_);
886    GateRef frameState = acc_.GetFrameState(gate);
887    GateRef value = acc_.GetValueIn(gate, 0);
888    GateRef isUndefinedorHole = builder_.TaggedIsUndefinedOrHole(value);
889    builder_.DeoptCheck(isUndefinedorHole, frameState, DeoptType::ISNOTUNDEFINEDORHOLE);
890    acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
891}
892
893void MCRLowering::LowerIsDataViewCheck(GateRef gate)
894{
895    Environment env(gate, circuit_, &builder_);
896    GateRef frameState = acc_.GetFrameState(gate);
897    GateRef obj = acc_.GetValueIn(gate, 0);
898    GateRef isDataView = builder_.CheckJSType(obj, JSType::JS_DATA_VIEW);
899    builder_.DeoptCheck(isDataView, frameState, DeoptType::ISNOTDATAVIEW);
900    acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
901}
902
903void MCRLowering::LowerValueCheckNegOverflow(GateRef gate)
904{
905    Environment env(gate, circuit_, &builder_);
906    GateRef frameState = acc_.GetFrameState(gate);
907    GateRef value = acc_.GetValueIn(gate, 0);
908    GateRef valueNotZero = builder_.NotEqual(value, builder_.Int32(0));
909    builder_.DeoptCheck(valueNotZero, frameState, DeoptType::NOTNEGOV1);
910    acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
911}
912
913void MCRLowering::LowerOverflowCheck(GateRef gate)
914{
915    Environment env(gate, circuit_, &builder_);
916    GateRef frameState = acc_.GetFrameState(gate);
917    GateRef result = acc_.GetValueIn(gate, 0);
918    GateRef condition = builder_.BoolNot(builder_.ExtractValue(MachineType::I1, result, builder_.Int32(1)));
919    builder_.DeoptCheck(condition, frameState, DeoptType::NOTINT3);
920    acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
921}
922
923void MCRLowering::LowerInt32UnsignedUpperBoundCheck(GateRef gate)
924{
925    Environment env(gate, circuit_, &builder_);
926    GateRef frameState = acc_.GetFrameState(gate);
927    GateRef value = acc_.GetValueIn(gate, 0);
928    GateRef upperBound = acc_.GetValueIn(gate, 1);
929    GateRef condition = builder_.Int32UnsignedLessThanOrEqual(value, upperBound);
930    builder_.DeoptCheck(condition, frameState, DeoptType::NOTINT4);
931    acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
932}
933
934void MCRLowering::LowerInt32DivWithCheck(GateRef gate)
935{
936    Environment env(gate, circuit_, &builder_);
937    GateRef frameState = acc_.GetFrameState(gate);
938    GateRef left = acc_.GetValueIn(gate, 0);
939    GateRef right = acc_.GetValueIn(gate, 1);
940    GateRef result = Circuit::NullGate();
941    GateRef condition = LogicOrBuilder(&env)
942        .Or(builder_.Int32GreaterThan(right, builder_.Int32(0)))
943        .Or(builder_.BitAnd(builder_.Int32LessThan(right, builder_.Int32(0)),
944                            builder_.Int32NotEqual(left, builder_.Int32(0))))
945        .Done();
946    builder_.DeoptCheck(condition, frameState, DeoptType::DIVZERO2);
947    result = builder_.BinaryArithmetic(circuit_->Sdiv(), MachineType::I32, left, right, GateType::NJSValue());
948    GateRef truncated = builder_.BinaryArithmetic(circuit_->Mul(),
949        MachineType::I32, result, right, GateType::NJSValue());
950    GateRef overCheck = builder_.Int32Equal(truncated, left);
951    builder_.DeoptCheck(overCheck, frameState, DeoptType::NOTINT5);
952    acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
953}
954
955void MCRLowering::LowerStoreMemory(GateRef gate)
956{
957    Environment env(gate, circuit_, &builder_);
958    GateRef receiver = acc_.GetValueIn(gate, 0);
959    GateRef index = acc_.GetValueIn(gate, 1);
960    GateRef value = acc_.GetValueIn(gate, 2);
961    builder_.Store(VariableType::VOID(), glue_, receiver, index, value);
962    acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
963}
964
965void MCRLowering::InitializeWithSpeicalValue(Label *exit, GateRef object, GateRef glue,
966                                             GateRef value, GateRef start, GateRef end)
967{
968    Label begin(&builder_);
969    Label storeValue(&builder_);
970    Label endLoop(&builder_);
971
972    DEFVALUE(startOffset, (&builder_), VariableType::INT32(), start);
973    builder_.Jump(&begin);
974    builder_.LoopBegin(&begin);
975    {
976        BRANCH_CIR(builder_.Int32UnsignedLessThan(*startOffset, end), &storeValue, exit);
977        builder_.Bind(&storeValue);
978        {
979            builder_.Store(VariableType::INT64(), glue, object, builder_.ZExtInt32ToPtr(*startOffset), value);
980            startOffset = builder_.Int32Add(*startOffset, builder_.Int32(JSTaggedValue::TaggedTypeSize()));
981            builder_.Jump(&endLoop);
982        }
983        builder_.Bind(&endLoop);
984        builder_.LoopEnd(&begin);
985    }
986}
987
988void MCRLowering::LowerMigrateFromRawValueToHeapValues(GateRef gate)
989{
990    Environment env(gate, circuit_, &builder_);
991    DEFVALUE(newElements, (&builder_), VariableType::JS_ANY(), builder_.Undefined());
992    Label exit(&builder_);
993    GateRef object = acc_.GetValueIn(gate, 0);
994    GateRef needCOW = acc_.GetValueIn(gate, 1);
995    GateRef isIntKind = acc_.GetValueIn(gate, 2);
996    GateRef elements = builder_.GetElementsArray(object);
997    GateRef length = builder_.GetLengthOfTaggedArray(elements);
998    Label createCOW(&builder_);
999    Label createNormal(&builder_);
1000    Label finishElementsInit(&builder_);
1001    BRANCH_CIR(needCOW, &createCOW, &createNormal);
1002    builder_.Bind(&createCOW);
1003    {
1004        newElements = builder_.CallRuntime(glue_, RTSTUB_ID(NewCOWTaggedArray), acc_.GetDep(gate),
1005                                           { builder_.Int32ToTaggedPtr(length) }, gate);
1006        builder_.Jump(&finishElementsInit);
1007    }
1008    builder_.Bind(&createNormal);
1009    {
1010        newElements = builder_.CallRuntime(glue_, RTSTUB_ID(NewTaggedArray), acc_.GetDep(gate),
1011                                           { builder_.Int32ToTaggedPtr(length) }, gate);
1012        builder_.Jump(&finishElementsInit);
1013    }
1014    builder_.Bind(&finishElementsInit);
1015
1016    DEFVALUE(index, (&builder_), VariableType::INT32(), builder_.Int32(0));
1017    Label loopHead(&builder_);
1018    Label loopEnd(&builder_);
1019    Label afterLoop(&builder_);
1020    Label storeValue(&builder_);
1021    builder_.Jump(&loopHead);
1022    builder_.LoopBegin(&loopHead);
1023    {
1024        Label storeHole(&builder_);
1025        Label storeNormalValue(&builder_);
1026        Label finishStore(&builder_);
1027        BRANCH_CIR(builder_.Int32UnsignedLessThan(*index, length), &storeValue, &afterLoop);
1028        builder_.Bind(&storeValue);
1029        {
1030            Label rawValueIsInt(&builder_);
1031            Label rawValueIsNumber(&builder_);
1032            GateRef value = builder_.GetValueFromJSArrayWithElementsKind(VariableType::INT64(), elements, *index);
1033            BRANCH_CIR(builder_.IsSpecialHole(value), &storeHole, &storeNormalValue);
1034            builder_.Bind(&storeHole);
1035            {
1036                builder_.SetValueToTaggedArray(VariableType::JS_ANY(), glue_, *newElements, *index, builder_.Hole());
1037                builder_.Jump(&finishStore);
1038            }
1039            builder_.Bind(&storeNormalValue);
1040            {
1041                BRANCH_CIR(isIntKind, &rawValueIsInt, &rawValueIsNumber);
1042                builder_.Bind(&rawValueIsInt);
1043                {
1044                    GateRef convertedInt = builder_.ToTaggedIntPtr(value);
1045                    builder_.SetValueToTaggedArray(VariableType::JS_ANY(), glue_, *newElements, *index, convertedInt);
1046                    builder_.Jump(&finishStore);
1047                }
1048                builder_.Bind(&rawValueIsNumber);
1049                {
1050                    GateRef tmpDouble = builder_.CastInt64ToFloat64(value);
1051                    GateRef convertedDouble = builder_.DoubleToTaggedDoublePtr(tmpDouble);
1052                    builder_.SetValueToTaggedArray(VariableType::JS_ANY(), glue_, *newElements,
1053                                                   *index, convertedDouble);
1054                    builder_.Jump(&finishStore);
1055                }
1056            }
1057            builder_.Bind(&finishStore);
1058            {
1059                index = builder_.Int32Add(*index, builder_.Int32(1));
1060                builder_.Jump(&loopEnd);
1061            }
1062        }
1063    }
1064    builder_.Bind(&loopEnd);
1065    builder_.LoopEnd(&loopHead);
1066    builder_.Bind(&afterLoop);
1067    {
1068        builder_.Jump(&exit);
1069    }
1070    builder_.Bind(&exit);
1071    acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *newElements);
1072}
1073
1074void MCRLowering::LowerMigrateFromHeapValueToRawValue(GateRef gate)
1075{
1076    Environment env(gate, circuit_, &builder_);
1077    DEFVALUE(newElements, (&builder_), VariableType::JS_ANY(), builder_.Undefined());
1078    Label exit(&builder_);
1079    GateRef object = acc_.GetValueIn(gate, 0);
1080    GateRef needCOW = acc_.GetValueIn(gate, 1);
1081    GateRef isIntKind = acc_.GetValueIn(gate, 2);
1082
1083    GateRef elements = builder_.GetElementsArray(object);
1084    GateRef length = builder_.GetLengthOfTaggedArray(elements);
1085    Label createCOW(&builder_);
1086    Label createNormal(&builder_);
1087    Label finishElementsInit(&builder_);
1088    BRANCH_CIR(needCOW, &createCOW, &createNormal);
1089    builder_.Bind(&createCOW);
1090    {
1091        newElements = builder_.CallRuntime(glue_, RTSTUB_ID(NewCOWMutantTaggedArray), acc_.GetDep(gate),
1092                                           { builder_.Int32ToTaggedPtr(length) }, gate);
1093        builder_.Jump(&finishElementsInit);
1094    }
1095    builder_.Bind(&createNormal);
1096    {
1097        newElements = builder_.CallRuntime(glue_, RTSTUB_ID(NewMutantTaggedArray), acc_.GetDep(gate),
1098                                           { builder_.Int32ToTaggedPtr(length) }, gate);
1099        builder_.Jump(&finishElementsInit);
1100    }
1101    builder_.Bind(&finishElementsInit);
1102
1103    DEFVALUE(index, (&builder_), VariableType::INT32(), builder_.Int32(0));
1104    Label loopHead(&builder_);
1105    Label loopEnd(&builder_);
1106    Label afterLoop(&builder_);
1107    Label storeValue(&builder_);
1108    builder_.Jump(&loopHead);
1109    builder_.LoopBegin(&loopHead);
1110    {
1111        Label storeSpecialHole(&builder_);
1112        Label storeNormalValue(&builder_);
1113        Label finishStore(&builder_);
1114        BRANCH_CIR(builder_.Int32UnsignedLessThan(*index, length), &storeValue, &afterLoop);
1115        builder_.Bind(&storeValue);
1116        {
1117            Label convertToInt(&builder_);
1118            Label convertToDouble(&builder_);
1119            GateRef value = builder_.GetValueFromTaggedArray(elements, *index);
1120            BRANCH_CIR(builder_.TaggedIsHole(value), &storeSpecialHole, &storeNormalValue);
1121            builder_.Bind(&storeSpecialHole);
1122            {
1123                builder_.SetValueToTaggedArray(VariableType::INT64(), glue_, *newElements,
1124                                               *index, builder_.SpecialHoleConstant());
1125                builder_.Jump(&finishStore);
1126            }
1127            builder_.Bind(&storeNormalValue);
1128            {
1129                Label valueIsInt(&builder_);
1130                Label valueIsDouble(&builder_);
1131                BRANCH_CIR(isIntKind, &convertToInt, &convertToDouble);
1132                builder_.Bind(&convertToInt);
1133                {
1134                    GateRef convertedInt = builder_.GetInt64OfTInt(value);
1135                    builder_.SetValueToTaggedArray(VariableType::INT64(), glue_, *newElements, *index, convertedInt);
1136                    builder_.Jump(&finishStore);
1137                }
1138                builder_.Bind(&convertToDouble);
1139                {
1140                    BRANCH_CIR(builder_.TaggedIsInt(value), &valueIsInt, &valueIsDouble);
1141                    builder_.Bind(&valueIsInt);
1142                    {
1143                        GateRef convertedDoubleFromTInt = builder_.CastDoubleToInt64(builder_.GetDoubleOfTInt(value));
1144                        builder_.SetValueToTaggedArray(VariableType::INT64(), glue_, *newElements, *index,
1145                                                       convertedDoubleFromTInt);
1146                        builder_.Jump(&finishStore);
1147                    }
1148                    builder_.Bind(&valueIsDouble);
1149                    {
1150                        GateRef doubleValue = builder_.GetDoubleOfTDouble(value);
1151                        GateRef convertedDoubleFromTDouble = builder_.CastDoubleToInt64(doubleValue);
1152                        builder_.SetValueToTaggedArray(VariableType::INT64(), glue_, *newElements, *index,
1153                                                       convertedDoubleFromTDouble);
1154                        builder_.Jump(&finishStore);
1155                    }
1156                }
1157            }
1158            builder_.Bind(&finishStore);
1159            {
1160                index = builder_.Int32Add(*index, builder_.Int32(1));
1161                builder_.Jump(&loopEnd);
1162            }
1163        }
1164    }
1165    builder_.Bind(&loopEnd);
1166    builder_.LoopEnd(&loopHead);
1167    builder_.Bind(&afterLoop);
1168    {
1169        builder_.Jump(&exit);
1170    }
1171
1172    builder_.Bind(&exit);
1173    acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *newElements);
1174}
1175
1176void MCRLowering::LowerMigrateFromHoleIntToHoleNumber(GateRef gate)
1177{
1178    Environment env(gate, circuit_, &builder_);
1179    GateRef object = acc_.GetValueIn(gate, 0);
1180    Label exit(&builder_);
1181    GateRef elements = builder_.GetElementsArray(object);
1182    GateRef length = builder_.GetLengthOfTaggedArray(elements);
1183    DEFVALUE(index, (&builder_), VariableType::INT32(), builder_.Int32(0));
1184    Label loopHead(&builder_);
1185    Label loopEnd(&builder_);
1186    Label afterLoop(&builder_);
1187    Label storeValue(&builder_);
1188    builder_.Jump(&loopHead);
1189    builder_.LoopBegin(&loopHead);
1190    {
1191        Label storeNormalValue(&builder_);
1192        Label finishStore(&builder_);
1193        BRANCH_CIR(builder_.Int32UnsignedLessThan(*index, length), &storeValue, &afterLoop);
1194        builder_.Bind(&storeValue);
1195        {
1196            GateRef value = builder_.GetValueFromTaggedArray(VariableType::INT64(), elements, *index);
1197            BRANCH_CIR(builder_.IsSpecialHole(value), &finishStore, &storeNormalValue);
1198            builder_.Bind(&storeNormalValue);
1199            {
1200                GateRef intVal = builder_.TruncInt64ToInt32(value);
1201                GateRef convertedValue = builder_.CastDoubleToInt64(builder_.ChangeInt32ToFloat64(intVal));
1202                builder_.SetValueToTaggedArray(VariableType::INT64(), glue_, elements, *index,
1203                                               convertedValue);
1204                builder_.Jump(&finishStore);
1205            }
1206            builder_.Bind(&finishStore);
1207            {
1208                index = builder_.Int32Add(*index, builder_.Int32(1));
1209                builder_.Jump(&loopEnd);
1210            }
1211        }
1212    }
1213    builder_.Bind(&loopEnd);
1214    builder_.LoopEnd(&loopHead);
1215    builder_.Bind(&afterLoop);
1216    {
1217        builder_.Jump(&exit);
1218    }
1219
1220    builder_.Bind(&exit);
1221    acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
1222}
1223
1224void MCRLowering::LowerMigrateFromHoleNumberToHoleInt(GateRef gate)
1225{
1226    Environment env(gate, circuit_, &builder_);
1227    GateRef object = acc_.GetValueIn(gate, 0);
1228    Label exit(&builder_);
1229    GateRef elements = builder_.GetElementsArray(object);
1230    GateRef length = builder_.GetLengthOfTaggedArray(elements);
1231    DEFVALUE(index, (&builder_), VariableType::INT32(), builder_.Int32(0));
1232    Label loopHead(&builder_);
1233    Label loopEnd(&builder_);
1234    Label afterLoop(&builder_);
1235    Label storeValue(&builder_);
1236    builder_.Jump(&loopHead);
1237    builder_.LoopBegin(&loopHead);
1238    {
1239        Label storeNormalValue(&builder_);
1240        Label finishStore(&builder_);
1241        BRANCH_CIR(builder_.Int32UnsignedLessThan(*index, length), &storeValue, &afterLoop);
1242        builder_.Bind(&storeValue);
1243        {
1244            GateRef value = builder_.GetValueFromTaggedArray(VariableType::INT64(), elements, *index);
1245            BRANCH_CIR(builder_.IsSpecialHole(value), &finishStore, &storeNormalValue);
1246            builder_.Bind(&storeNormalValue);
1247            {
1248                GateRef doubleVal = builder_.CastInt64ToFloat64(value);
1249                GateRef convertedValue = builder_.SExtInt32ToInt64(builder_.ChangeFloat64ToInt32(doubleVal));
1250                builder_.SetValueToTaggedArray(VariableType::INT64(), glue_, elements, *index,
1251                                               convertedValue);
1252                builder_.Jump(&finishStore);
1253            }
1254            builder_.Bind(&finishStore);
1255            {
1256                index = builder_.Int32Add(*index, builder_.Int32(1));
1257                builder_.Jump(&loopEnd);
1258            }
1259        }
1260    }
1261    builder_.Bind(&loopEnd);
1262    builder_.LoopEnd(&loopHead);
1263    builder_.Bind(&afterLoop);
1264    {
1265        builder_.Jump(&exit);
1266    }
1267
1268    builder_.Bind(&exit);
1269    acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
1270}
1271
1272void MCRLowering::LowerHeapObjectIsEcmaObject(GateRef gate)
1273{
1274    Environment env(gate, circuit_, &builder_);
1275    GateRef frameState = acc_.GetFrameState(gate);
1276    GateRef value = acc_.GetValueIn(gate, 0);
1277
1278    GateRef isEcmaObject = builder_.TaggedObjectIsEcmaObject(value);
1279    builder_.DeoptCheck(isEcmaObject, frameState, DeoptType::NOT_ECMA_OBJECT);
1280
1281    acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
1282}
1283
1284void MCRLowering::LowerIsCallableCheck(GateRef gate)
1285{
1286    Environment env(gate, circuit_, &builder_);
1287    GateRef func = acc_.GetValueIn(gate, 0);
1288    GateRef frameState = acc_.GetFrameState(gate);
1289    GateRef isCallable = LogicAndBuilder(&env).And(builder_.TaggedIsHeapObject(func))
1290        .And(builder_.IsCallable(func)).Done();
1291    builder_.DeoptCheck(isCallable, frameState, DeoptType::NOTCALLABLE);
1292    acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
1293}
1294}  // namespace panda::ecmascript
1295