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