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 
28 namespace panda::ecmascript::kungfu {
29 
VisitGate(GateRef gate)30 GateRef 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 
LowerConvertHoleAsUndefined(GateRef gate)142 void 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 
LowerLoadConstOffset(GateRef gate)162 void 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 
LowerLoadHClassFromConstpool(GateRef gate)172 void 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 
LowerStoreConstOffset(GateRef gate)189 void 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 
LowerHeapObjectCheck(GateRef gate)201 void 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 
LowerTaggedIsHeapObject(GateRef gate)213 void 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 
LowerIsMarkerCellValid(GateRef gate)221 void 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 
LowerIsSpecificObjectType(GateRef gate)229 void 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 
DeleteStateSplit(GateRef gate)268 void 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 
LowerArrayGuardianCheck(GateRef gate)276 void 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 
LowerHClassStableArrayCheck(GateRef gate)288 void 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 
LowerConvert(StateDepend stateDepend, GateRef gate)300 StateDepend 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 
ConvertSpecialHoleIntToTagged(GateRef gate, Label* exit)384 GateRef 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 
ConvertSpecialHoleDoubleToTagged(GateRef gate, Label* exit)407 GateRef 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 
ConvertTaggedNumberToBool(GateRef gate, Label *exit)430 GateRef 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 
ConvertTaggedNumberToInt32(GateRef gate, Label *exit)453 GateRef 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 
ConvertTaggedNumberToFloat64(GateRef gate, Label *exit)470 GateRef 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 
LowerCheckAndConvert(GateRef gate)486 void 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 
LowerCheckFloat64AndConvert(GateRef gate, GateRef frameState, Label *exit)531 void 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 
LowerCheckSpecialHoleAndConvert(GateRef gate, GateRef frameState)542 void 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 
LowerCheckUInt32AndConvert(GateRef gate, GateRef frameState)565 void 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 
LowerCheckTaggedIntAndConvert(GateRef gate, GateRef frameState)574 void 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 
LowerCheckTaggedDoubleAndConvert(GateRef gate, GateRef frameState, Label *exit)590 void 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 
LowerCheckTaggedNumberAndConvert(GateRef gate, GateRef frameState, Label *exit)606 void 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 
LowerCheckSupportAndConvert(GateRef gate, GateRef frameState)624 void 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 
LowerCheckTaggedBoolAndConvert(GateRef gate, GateRef frameState)642 void 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 
LowerCheckNullAndConvert(GateRef gate, GateRef frameState)661 void 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 
LowerUndefinedAndConvert(GateRef gate, GateRef frameState)679 void 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 
ConvertTaggedBooleanToBool(GateRef value)697 GateRef MCRLowering::ConvertTaggedBooleanToBool(GateRef value)
698 {
699     return builder_.TaggedIsTrue(value);
700 }
701 
ConvertBoolToTaggedBoolean(GateRef gate)702 GateRef MCRLowering::ConvertBoolToTaggedBoolean(GateRef gate)
703 {
704     return builder_.BooleanToTaggedBooleanPtr(gate);
705 }
706 
ConvertInt32ToFloat64(GateRef gate)707 GateRef MCRLowering::ConvertInt32ToFloat64(GateRef gate)
708 {
709     return builder_.ChangeInt32ToFloat64(gate);
710 }
711 
ConvertUInt32ToFloat64(GateRef gate)712 GateRef MCRLowering::ConvertUInt32ToFloat64(GateRef gate)
713 {
714     return builder_.ChangeUInt32ToFloat64(gate);
715 }
716 
ConvertInt32ToTaggedInt(GateRef gate)717 GateRef MCRLowering::ConvertInt32ToTaggedInt(GateRef gate)
718 {
719     return builder_.Int32ToTaggedPtr(gate);
720 }
721 
ConvertUInt32ToTaggedNumber(GateRef gate, Label *exit)722 GateRef 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 
ConvertFloat64ToInt32(GateRef gate, Label *exit)739 GateRef MCRLowering::ConvertFloat64ToInt32(GateRef gate, Label *exit)
740 {
741     return builder_.DoubleToInt(gate, exit);
742 }
743 
ConvertFloat64ToBool(GateRef gate)744 GateRef 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 
ConvertFloat64ToTaggedDouble(GateRef gate)752 GateRef MCRLowering::ConvertFloat64ToTaggedDouble(GateRef gate)
753 {
754     return builder_.DoubleToTaggedDoublePtr(gate);
755 }
756 
ConvertTaggedIntToInt32(GateRef gate)757 GateRef MCRLowering::ConvertTaggedIntToInt32(GateRef gate)
758 {
759     return builder_.GetInt32OfTInt(gate);
760 }
761 
ConvertTaggedIntToFloat64(GateRef gate)762 GateRef MCRLowering::ConvertTaggedIntToFloat64(GateRef gate)
763 {
764     return builder_.ChangeInt32ToFloat64(builder_.GetInt32OfTInt(gate));
765 }
766 
ConvertTaggedDoubleToInt32(GateRef gate, Label *exit)767 GateRef MCRLowering::ConvertTaggedDoubleToInt32(GateRef gate, Label *exit)
768 {
769     return builder_.DoubleToInt(builder_.GetDoubleOfTDouble(gate), exit);
770 }
771 
ConvertTaggedDoubleToFloat64(GateRef gate)772 GateRef MCRLowering::ConvertTaggedDoubleToFloat64(GateRef gate)
773 {
774     return builder_.GetDoubleOfTDouble(gate);
775 }
776 
LowerGetGlobalEnv(GateRef gate)777 void 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 
LowerGetGlobalEnvObj(GateRef gate)785 void 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 
LowerGetGlobalEnvObjHClass(GateRef gate)795 void 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 
LowerGetGlobalConstantValue(GateRef gate)807 void 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 
HeapAllocateInSOld(GateRef gate)818 void 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 
LowerInt32CheckRightIsZero(GateRef gate)827 void 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 
LowerRemainderIsNegativeZero(GateRef gate)837 void 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 
LowerFloat64CheckRightIsZero(GateRef gate)853 void 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 
LowerLexVarIsHoleCheck(GateRef gate)863 void 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 
LowerIsUndefinedOrHoleCheck(GateRef gate)873 void 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 
LowerIsNotUndefinedOrHoleCheck(GateRef gate)883 void 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 
LowerIsDataViewCheck(GateRef gate)893 void 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 
LowerValueCheckNegOverflow(GateRef gate)903 void 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 
LowerOverflowCheck(GateRef gate)913 void 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 
LowerInt32UnsignedUpperBoundCheck(GateRef gate)923 void 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 
LowerInt32DivWithCheck(GateRef gate)934 void 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 
LowerStoreMemory(GateRef gate)955 void 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 
InitializeWithSpeicalValue(Label *exit, GateRef object, GateRef glue, GateRef value, GateRef start, GateRef end)965 void 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 
LowerMigrateFromRawValueToHeapValues(GateRef gate)988 void 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 
LowerMigrateFromHeapValueToRawValue(GateRef gate)1074 void 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 
LowerMigrateFromHoleIntToHoleNumber(GateRef gate)1176 void 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 
LowerMigrateFromHoleNumberToHoleInt(GateRef gate)1224 void 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 
LowerHeapObjectIsEcmaObject(GateRef gate)1272 void 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 
LowerIsCallableCheck(GateRef gate)1284 void 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