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