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