• 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/bytecodes.h"
17 #include "ecmascript/compiler/share_gate_meta_data.h"
18 #include "ecmascript/global_env.h"
19 #include "ecmascript/jspandafile/program_object.h"
20 #include "ecmascript/js_thread.h"
21 #include "ecmascript/js_function.h"
22 #include "ecmascript/message_string.h"
23 #include "ecmascript/compiler/argument_accessor.h"
24 
25 namespace panda::ecmascript::kungfu {
26 
VisitGate(GateRef gate)27 GateRef MCRLowering::VisitGate(GateRef gate)
28 {
29     auto op = acc_.GetOpCode(gate);
30     switch (op) {
31         case OpCode::GET_CONSTPOOL:
32             LowerGetConstPool(gate);
33             break;
34         case OpCode::STATE_SPLIT:
35             DeleteStateSplit(gate);
36             break;
37         case OpCode::ARRAY_GUARDIAN_CHECK:
38             LowerArrayGuardianCheck(gate);
39             break;
40         case OpCode::HCLASS_STABLE_ARRAY_CHECK:
41             LowerHClassStableArrayCheck(gate);
42             break;
43         case OpCode::HEAP_OBJECT_CHECK:
44             LowerHeapObjectCheck(gate);
45             break;
46         case OpCode::LOAD_CONST_OFFSET:
47             LowerLoadConstOffset(gate);
48             break;
49         case OpCode::LOAD_HCLASS_FROM_CONSTPOOL:
50             LowerLoadHClassFromConstpool(gate);
51             break;
52         case OpCode::STORE_CONST_OFFSET:
53             LowerStoreConstOffset(gate);
54             break;
55         case OpCode::CONVERT_HOLE_AS_UNDEFINED:
56             LowerConvertHoleAsUndefined(gate);
57             break;
58         case OpCode::GET_GLOBAL_ENV:
59             LowerGetGlobalEnv(gate);
60             break;
61         case OpCode::GET_GLOBAL_ENV_OBJ:
62             LowerGetGlobalEnvObj(gate);
63             break;
64         case OpCode::GET_GLOBAL_ENV_OBJ_HCLASS:
65             LowerGetGlobalEnvObjHClass(gate);
66             break;
67         case OpCode::GET_GLOBAL_CONSTANT_VALUE:
68             LowerGetGlobalConstantValue(gate);
69             break;
70         case OpCode::HEAP_ALLOC:
71             LowerHeapAllocate(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::STORE_MEMORY:
98             LowerStoreMemory(gate);
99             break;
100         case OpCode::CHECK_AND_CONVERT:
101             LowerCheckAndConvert(gate);
102             break;
103         case OpCode::TAGGED_IS_HEAP_OBJECT:
104             LowerTaggedIsHeapObject(gate);
105             break;
106         case OpCode::IS_MARKER_CELL_VALID:
107             LowerIsMarkerCellValid(gate);
108             break;
109         case OpCode::IS_SPECIFIC_OBJECT_TYPE:
110             LowerIsSpecificObjectType(gate);
111             break;
112         default:
113             break;
114     }
115     return Circuit::NullGate();
116 }
117 
LowerConvertHoleAsUndefined(GateRef gate)118 void MCRLowering::LowerConvertHoleAsUndefined(GateRef gate)
119 {
120     Environment env(gate, circuit_, &builder_);
121 
122     Label returnUndefined(&builder_);
123     Label exit(&builder_);
124     GateRef receiver = acc_.GetValueIn(gate, 0);
125     DEFVALUE(result, (&builder_), VariableType::JS_ANY(), receiver);
126 
127     builder_.Branch(builder_.TaggedIsHole(*result), &returnUndefined, &exit, 1, BranchWeight::DEOPT_WEIGHT);
128     builder_.Bind(&returnUndefined);
129     {
130         result = builder_.UndefineConstant();
131         builder_.Jump(&exit);
132     }
133     builder_.Bind(&exit);
134     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result);
135 }
136 
LowerLoadConstOffset(GateRef gate)137 void MCRLowering::LowerLoadConstOffset(GateRef gate)
138 {
139     Environment env(gate, circuit_, &builder_);
140     GateRef receiver = acc_.GetValueIn(gate, 0);
141     GateRef offset = builder_.IntPtr(acc_.GetOffset(gate));
142     VariableType type = VariableType(acc_.GetMachineType(gate), acc_.GetGateType(gate));
143     GateRef result = builder_.Load(type, receiver, offset, acc_.GetMemoryOrder(gate));
144     acc_.ReplaceGate(gate, Circuit::NullGate(), builder_.GetDepend(), result);
145 }
146 
LowerLoadHClassFromConstpool(GateRef gate)147 void MCRLowering::LowerLoadHClassFromConstpool(GateRef gate)
148 {
149     Environment env(gate, circuit_, &builder_);
150     GateRef constpool = acc_.GetValueIn(gate, 0);
151     uint32_t index = acc_.GetIndex(gate);
152     GateRef constPoolSize = builder_.GetLengthOfTaggedArray(constpool);
153     GateRef valVecIndex = builder_.Int32Sub(constPoolSize, builder_.Int32(ConstantPool::AOT_HCLASS_INFO_INDEX));
154     GateRef valVec = builder_.GetValueFromTaggedArray(constpool, valVecIndex);
155     GateRef hclass = builder_.GetValueFromTaggedArray(valVec, builder_.Int32(index));
156     acc_.ReplaceGate(gate, Circuit::NullGate(), builder_.GetDepend(), hclass);
157 }
158 
LowerStoreConstOffset(GateRef gate)159 void MCRLowering::LowerStoreConstOffset(GateRef gate)
160 {
161     Environment env(gate, circuit_, &builder_);
162 
163     GateRef receiver = acc_.GetValueIn(gate, 0);
164     GateRef value = acc_.GetValueIn(gate, 1);
165     GateRef offset = builder_.IntPtr(acc_.GetOffset(gate));
166     VariableType type = VariableType(acc_.GetMachineType(gate), acc_.GetGateType(gate));
167     builder_.Store(type, glue_, receiver, offset, value, acc_.GetMemoryOrder(gate));
168     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
169 }
170 
LowerHeapObjectCheck(GateRef gate)171 void MCRLowering::LowerHeapObjectCheck(GateRef gate)
172 {
173     Environment env(gate, circuit_, &builder_);
174     GateRef frameState = acc_.GetFrameState(gate);
175     GateRef receiver = acc_.GetValueIn(gate, 0);
176 
177     GateRef heapObjectCheck = builder_.TaggedIsHeapObject(receiver);
178     builder_.DeoptCheck(heapObjectCheck, frameState, DeoptType::NOTHEAPOBJECT1);
179 
180     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
181 }
182 
LowerTaggedIsHeapObject(GateRef gate)183 void MCRLowering::LowerTaggedIsHeapObject(GateRef gate)
184 {
185     Environment env(gate, circuit_, &builder_);
186     GateRef receiver = acc_.GetValueIn(gate, 0);
187     GateRef result = builder_.TaggedIsHeapObject(receiver);
188     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
189 }
190 
LowerIsMarkerCellValid(GateRef gate)191 void MCRLowering::LowerIsMarkerCellValid(GateRef gate)
192 {
193     Environment env(gate, circuit_, &builder_);
194     GateRef cell = acc_.GetValueIn(gate, 0);
195     GateRef result = builder_.IsMarkerCellValid(cell);
196     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
197 }
198 
LowerIsSpecificObjectType(GateRef gate)199 void MCRLowering::LowerIsSpecificObjectType(GateRef gate)
200 {
201     Environment env(gate, circuit_, &builder_);
202     JSType expectType = static_cast<JSType>(acc_.GetJSType(gate));
203     GateRef obj = acc_.GetValueIn(gate, 0);
204     GateRef result;
205     switch (expectType) {
206         case JSType::JS_MAP: {
207             result = builder_.TaggedObjectIsJSMap(obj);
208             break;
209         }
210         case JSType::JS_SET: {
211             result = builder_.TaggedObjectIsJSSet(obj);
212             break;
213         }
214         case JSType::JS_ARRAY: {
215             result = builder_.TaggedObjectIsJSArray(obj);
216             break;
217         }
218         case JSType::STRING_FIRST: {
219             result = builder_.TaggedObjectIsString(obj);
220             break;
221         }
222         case JSType::JS_TYPED_ARRAY_FIRST: {
223             result = builder_.TaggedObjectIsTypedArray(obj);
224             break;
225         }
226         default: {
227             LOG_COMPILER(FATAL) << "this branch is unreachable";
228             UNREACHABLE();
229         }
230     }
231     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
232 }
233 
LowerGetConstPool(GateRef gate)234 void MCRLowering::LowerGetConstPool(GateRef gate)
235 {
236     Environment env(gate, circuit_, &builder_);
237     GateRef jsFunc = acc_.GetValueIn(gate, 0); // 0: this object
238     GateRef newGate = builder_.GetConstPoolFromFunction(jsFunc);
239 
240     acc_.UpdateAllUses(gate, newGate);
241 
242     // delete old gate
243     acc_.DeleteGate(gate);
244 }
245 
DeleteStateSplit(GateRef gate)246 void MCRLowering::DeleteStateSplit(GateRef gate)
247 {
248     auto depend = acc_.GetDep(gate);
249     auto frameState = acc_.GetFrameState(gate);
250     acc_.DeleteGateIfNoUse(frameState);
251     acc_.ReplaceGate(gate, Circuit::NullGate(), depend, Circuit::NullGate());
252 }
253 
LowerArrayGuardianCheck(GateRef gate)254 void MCRLowering::LowerArrayGuardianCheck(GateRef gate)
255 {
256     Environment env(gate, circuit_, &builder_);
257 
258     GateRef frameState = acc_.GetFrameState(gate);
259     GateRef guardiansOffset = builder_.IntPtr(JSThread::GlueData::GetStableArrayElementsGuardiansOffset(false));
260     GateRef check = builder_.Load(VariableType::BOOL(), glue_, guardiansOffset);
261     builder_.DeoptCheck(check, frameState, DeoptType::NOTSARRAY1);
262 
263     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
264 }
265 
LowerHClassStableArrayCheck(GateRef gate)266 void MCRLowering::LowerHClassStableArrayCheck(GateRef gate)
267 {
268     Environment env(gate, circuit_, &builder_);
269     GateRef frameState = acc_.GetFrameState(gate);
270     GateRef hclass = acc_.GetValueIn(gate, 0);
271 
272     GateRef check = Circuit::NullGate();
273     GateRef stableCheck = builder_.IsStableElements(hclass);
274     ArrayMetaDataAccessor accessor = acc_.GetArrayMetaDataAccessor(gate);
275     ElementsKind kind = accessor.GetElementsKind();
276     if (accessor.IsLoadElement() && !Elements::IsHole(kind)) {
277         if (Elements::IsComplex(kind)) {
278             GateRef elementsKindCheck = builder_.Int32GreaterThanOrEqual(builder_.Int32(static_cast<int32_t>(kind)),
279                                                                          builder_.GetElementsKindByHClass(hclass));
280             check = builder_.BoolAnd(stableCheck, elementsKindCheck);
281         } else {
282             GateRef elementsKindCheck = builder_.Equal(builder_.Int32(static_cast<int32_t>(kind)),
283                                                        builder_.GetElementsKindByHClass(hclass));
284             check = builder_.BoolAnd(stableCheck, elementsKindCheck);
285         }
286     } else {
287         check = stableCheck;
288     }
289     builder_.DeoptCheck(check, frameState, DeoptType::NOTSARRAY2);
290 
291     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
292 }
293 
LowerConvert(StateDepend stateDepend,GateRef gate)294 StateDepend MCRLowering::LowerConvert(StateDepend stateDepend, GateRef gate)
295 {
296     Environment env(stateDepend.State(), stateDepend.Depend(), {}, circuit_, &builder_);
297     GateRef value = acc_.GetValueIn(gate);
298     ValueType dstType = acc_.GetDstType(gate);
299     GateRef result = Circuit::NullGate();
300     Label exit(&builder_);
301     switch (acc_.GetSrcType(gate)) {
302         case ValueType::BOOL:
303             ASSERT(dstType == ValueType::TAGGED_BOOLEAN);
304             result = ConvertBoolToTaggedBoolean(value);
305             break;
306         case ValueType::INT32:
307             if (dstType == ValueType::TAGGED_INT) {
308                 result = ConvertInt32ToTaggedInt(value);
309             } else if (dstType == ValueType::FLOAT64) {
310                 result = ConvertInt32ToFloat64(value);
311             } else {
312                 ASSERT(dstType == ValueType::BOOL);
313                 result = builder_.NotEqual(value, builder_.Int32(0));
314             }
315             break;
316         case ValueType::UINT32:
317             if (dstType == ValueType::TAGGED_NUMBER) {
318                 result = ConvertUInt32ToTaggedNumber(value, &exit);
319             } else if (dstType == ValueType::FLOAT64) {
320                 result = ConvertUInt32ToFloat64(value);
321             } else {
322                 ASSERT(dstType == ValueType::BOOL);
323                 result = builder_.NotEqual(value, builder_.Int32(0));
324             }
325             break;
326         case ValueType::FLOAT64:
327             if (dstType == ValueType::TAGGED_DOUBLE) {
328                 result = ConvertFloat64ToTaggedDouble(value);
329             } else if (dstType == ValueType::INT32) {
330                 result = ConvertFloat64ToInt32(value, &exit);
331             } else {
332                 ASSERT(dstType == ValueType::BOOL);
333                 result = ConvertFloat64ToBool(value);
334             }
335             break;
336         case ValueType::TAGGED_BOOLEAN:
337             ASSERT((dstType == ValueType::BOOL));
338             result = ConvertTaggedBooleanToBool(value);
339             break;
340         case ValueType::TAGGED_INT:
341             ASSERT((dstType == ValueType::INT32));
342             result = ConvertTaggedIntToInt32(value);
343             break;
344         case ValueType::TAGGED_DOUBLE:
345             ASSERT((dstType == ValueType::FLOAT64));
346             result = ConvertTaggedDoubleToFloat64(value);
347             break;
348         case ValueType::CHAR: {
349             ASSERT((dstType == ValueType::ECMA_STRING));
350             GateRef glue = acc_.GetGlueFromArgList();
351             result = builder_.CallStub(glue, gate, CommonStubCSigns::CreateStringBySingleCharCode, { glue, value });
352             break;
353         }
354         default:
355             LOG_COMPILER(FATAL) << "this branch is unreachable";
356             break;
357     }
358     acc_.ReplaceGate(gate, Circuit::NullGate(), Circuit::NullGate(), result);
359     return builder_.GetStateDepend();
360 }
361 
ConvertTaggedNumberToBool(GateRef gate,Label * exit)362 GateRef MCRLowering::ConvertTaggedNumberToBool(GateRef gate, Label *exit)
363 {
364     DEFVALUE(result, (&builder_), VariableType::BOOL(), builder_.Boolean(false));
365     Label isInt(&builder_);
366     Label isDouble(&builder_);
367     Label toInt32(&builder_);
368     builder_.Branch(builder_.TaggedIsInt(gate), &isInt, &isDouble);
369     builder_.Bind(&isInt);
370     {
371         GateRef intVal = builder_.GetInt64OfTInt(gate);
372         result = builder_.NotEqual(intVal, builder_.Int64(0));
373     }
374     builder_.Jump(exit);
375     builder_.Bind(&isDouble);
376     {
377         GateRef doubleVal = builder_.GetDoubleOfTDouble(gate);
378         result = ConvertFloat64ToBool(doubleVal);
379     }
380     builder_.Jump(exit);
381     builder_.Bind(exit);
382     return *result;
383 }
384 
ConvertTaggedNumberToInt32(GateRef gate,Label * exit)385 GateRef MCRLowering::ConvertTaggedNumberToInt32(GateRef gate, Label *exit)
386 {
387     DEFVALUE(result, (&builder_), VariableType::INT32(), builder_.Int32(0));
388     Label isInt(&builder_);
389     Label isDouble(&builder_);
390     Label toInt32(&builder_);
391     builder_.Branch(builder_.TaggedIsInt(gate), &isInt, &isDouble);
392     builder_.Bind(&isInt);
393     result = ConvertTaggedIntToInt32(gate);
394     builder_.Jump(exit);
395     builder_.Bind(&isDouble);
396     result = ConvertFloat64ToInt32(ConvertTaggedDoubleToFloat64(gate), &toInt32);
397     builder_.Jump(exit);
398     builder_.Bind(exit);
399     return *result;
400 }
401 
ConvertTaggedNumberToFloat64(GateRef gate,Label * exit)402 GateRef MCRLowering::ConvertTaggedNumberToFloat64(GateRef gate, Label *exit)
403 {
404     DEFVALUE(result, (&builder_), VariableType::FLOAT64(), builder_.Double(0));
405     Label isInt(&builder_);
406     Label isDouble(&builder_);
407     builder_.Branch(builder_.TaggedIsInt(gate), &isInt, &isDouble);
408     builder_.Bind(&isInt);
409     result = ConvertInt32ToFloat64(ConvertTaggedIntToInt32(gate));
410     builder_.Jump(exit);
411     builder_.Bind(&isDouble);
412     result = ConvertTaggedDoubleToFloat64(gate);
413     builder_.Jump(exit);
414     builder_.Bind(exit);
415     return *result;
416 }
417 
LowerCheckAndConvert(GateRef gate)418 void MCRLowering::LowerCheckAndConvert(GateRef gate)
419 {
420     Environment env(gate, circuit_, &builder_);
421     GateRef frameState = acc_.GetFrameState(gate);
422     ValueType srcType = acc_.GetSrcType(gate);
423     Label exit(&builder_);
424     switch (srcType) {
425         case ValueType::UINT32:
426             LowerCheckUInt32AndConvert(gate, frameState);
427             break;
428         case ValueType::TAGGED_INT:
429             LowerCheckTaggedIntAndConvert(gate, frameState);
430             break;
431         case ValueType::TAGGED_DOUBLE:
432             LowerCheckTaggedDoubleAndConvert(gate, frameState, &exit);
433             break;
434         case ValueType::TAGGED_BOOLEAN:
435             LowerCheckTaggedBoolAndConvert(gate, frameState);
436             break;
437         case ValueType::TAGGED_NUMBER:
438             LowerCheckTaggedNumberAndConvert(gate, frameState, &exit);
439             break;
440         case ValueType::BOOL:
441             LowerCheckSupportAndConvert(gate, frameState);
442             break;
443         case ValueType::TAGGED_NULL:
444             LowerCheckNullAndConvert(gate, frameState);
445             break;
446         case ValueType::UNDEFINED:
447             LowerUndefinedAndConvert(gate, frameState);
448             break;
449         default:
450             UNREACHABLE();
451     }
452 }
453 
LowerCheckUInt32AndConvert(GateRef gate,GateRef frameState)454 void MCRLowering::LowerCheckUInt32AndConvert(GateRef gate, GateRef frameState)
455 {
456     GateRef value = acc_.GetValueIn(gate, 0);
457     GateRef upperBound = builder_.Int32(INT32_MAX);
458     GateRef check = builder_.Int32UnsignedLessThanOrEqual(value, upperBound);
459     builder_.DeoptCheck(check, frameState, DeoptType::INT32OVERFLOW1);
460     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), value);
461 }
462 
LowerCheckTaggedIntAndConvert(GateRef gate,GateRef frameState)463 void MCRLowering::LowerCheckTaggedIntAndConvert(GateRef gate, GateRef frameState)
464 {
465     GateRef value = acc_.GetValueIn(gate, 0);
466     GateRef typeCheck = builder_.TaggedIsInt(value);
467     builder_.DeoptCheck(typeCheck, frameState, DeoptType::NOTINT1);
468     GateRef result = Circuit::NullGate();
469     ValueType dst = acc_.GetDstType(gate);
470     ASSERT(dst == ValueType::INT32 || dst == ValueType::FLOAT64);
471     if (dst == ValueType::INT32) {
472         result = ConvertTaggedIntToInt32(value);
473     } else {
474         result = ConvertTaggedIntToFloat64(value);
475     }
476     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
477 }
478 
LowerCheckTaggedDoubleAndConvert(GateRef gate,GateRef frameState,Label * exit)479 void MCRLowering::LowerCheckTaggedDoubleAndConvert(GateRef gate, GateRef frameState, Label *exit)
480 {
481     GateRef value = acc_.GetValueIn(gate, 0);
482     GateRef typeCheck = builder_.TaggedIsDouble(value);
483     builder_.DeoptCheck(typeCheck, frameState, DeoptType::NOTDOUBLE1);
484     GateRef result = Circuit::NullGate();
485     ValueType dst = acc_.GetDstType(gate);
486     ASSERT(dst == ValueType::INT32 || dst == ValueType::FLOAT64);
487     if (dst == ValueType::INT32) {
488         result = ConvertTaggedDoubleToInt32(value, exit);
489     } else {
490         result = ConvertTaggedDoubleToFloat64(value);
491     }
492     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
493 }
494 
LowerCheckTaggedNumberAndConvert(GateRef gate,GateRef frameState,Label * exit)495 void MCRLowering::LowerCheckTaggedNumberAndConvert(GateRef gate, GateRef frameState, Label *exit)
496 {
497     GateRef value = acc_.GetValueIn(gate, 0);
498     GateRef typeCheck = builder_.TaggedIsNumber(value);
499     builder_.DeoptCheck(typeCheck, frameState, DeoptType::NOTNUMBER1);
500     GateRef result = Circuit::NullGate();
501     ValueType dst = acc_.GetDstType(gate);
502     if (dst == ValueType::INT32) {
503         result = ConvertTaggedNumberToInt32(value, exit);
504     } else if (dst == ValueType::FLOAT64) {
505         result = ConvertTaggedNumberToFloat64(value, exit);
506     } else {
507         ASSERT(dst == ValueType::BOOL);
508         result = ConvertTaggedNumberToBool(value, exit);
509     }
510     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
511 }
512 
LowerCheckSupportAndConvert(GateRef gate,GateRef frameState)513 void MCRLowering::LowerCheckSupportAndConvert(GateRef gate, GateRef frameState)
514 {
515     ValueType dstType = acc_.GetDstType(gate);
516     ASSERT(dstType == ValueType::INT32 || dstType == ValueType::FLOAT64);
517     bool support = acc_.IsConvertSupport(gate);
518     GateRef value = acc_.GetValueIn(gate, 0);
519 
520     GateRef result = Circuit::NullGate();
521     if (dstType == ValueType::INT32) {
522         builder_.DeoptCheck(builder_.Boolean(support), frameState, DeoptType::NOTINT2);
523         result = builder_.BooleanToInt32(value);
524     } else {
525         builder_.DeoptCheck(builder_.Boolean(support), frameState, DeoptType::NOTDOUBLE2);
526         result = builder_.BooleanToFloat64(value);
527     }
528     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
529 }
530 
LowerCheckTaggedBoolAndConvert(GateRef gate,GateRef frameState)531 void MCRLowering::LowerCheckTaggedBoolAndConvert(GateRef gate, GateRef frameState)
532 {
533     GateRef value = acc_.GetValueIn(gate, 0);
534     GateRef typeCheck = builder_.TaggedIsBoolean(value);
535     builder_.DeoptCheck(typeCheck, frameState, DeoptType::NOTBOOL1);
536     GateRef result = Circuit::NullGate();
537     GateRef boolValue = ConvertTaggedBooleanToBool(value);
538     if (acc_.GetDstType(gate) == ValueType::BOOL) {
539         result = boolValue;
540     } else if (acc_.GetDstType(gate) == ValueType::INT32) {
541         result = builder_.ZExtInt1ToInt32(boolValue);
542     } else if (acc_.GetDstType(gate) == ValueType::FLOAT64) {
543         result = builder_.BooleanToFloat64(boolValue);
544     } else {
545         UNREACHABLE();
546     }
547     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
548 }
549 
LowerCheckNullAndConvert(GateRef gate,GateRef frameState)550 void MCRLowering::LowerCheckNullAndConvert(GateRef gate, GateRef frameState)
551 {
552     GateRef value = acc_.GetValueIn(gate, 0);
553     GateRef typeCheck = builder_.TaggedIsNull(value);
554     builder_.DeoptCheck(typeCheck, frameState, DeoptType::NOTNULL1);
555     GateRef result = Circuit::NullGate();
556     if (acc_.GetDstType(gate) == ValueType::INT32) {
557         result = builder_.Int32(0);
558     } else if (acc_.GetDstType(gate) == ValueType::FLOAT64) {
559         result = builder_.Double(0);
560     } else if (acc_.GetDstType(gate) == ValueType::BOOL) {
561         result = builder_.False();
562     } else {
563         UNREACHABLE();
564     }
565     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
566 }
567 
LowerUndefinedAndConvert(GateRef gate,GateRef frameState)568 void MCRLowering::LowerUndefinedAndConvert(GateRef gate, GateRef frameState)
569 {
570     GateRef value = acc_.GetValueIn(gate, 0);
571     GateRef typeCheck = builder_.TaggedIsUndefined(value);
572     builder_.DeoptCheck(typeCheck, frameState, DeoptType::NOTNULL2);
573     GateRef result = Circuit::NullGate();
574     if (acc_.GetDstType(gate) == ValueType::FLOAT64) {
575         result = builder_.NanValue();
576     } else if (acc_.GetDstType(gate) == ValueType::BOOL) {
577         result = builder_.False();
578     } else if (acc_.GetDstType(gate) == ValueType::INT32) {
579         result = builder_.Int32(0);
580     } else {
581         UNREACHABLE();
582     }
583     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
584 }
585 
ConvertTaggedBooleanToBool(GateRef value)586 GateRef MCRLowering::ConvertTaggedBooleanToBool(GateRef value)
587 {
588     return builder_.TaggedIsTrue(value);
589 }
590 
ConvertBoolToTaggedBoolean(GateRef gate)591 GateRef MCRLowering::ConvertBoolToTaggedBoolean(GateRef gate)
592 {
593     return builder_.BooleanToTaggedBooleanPtr(gate);
594 }
595 
ConvertInt32ToFloat64(GateRef gate)596 GateRef MCRLowering::ConvertInt32ToFloat64(GateRef gate)
597 {
598     return builder_.ChangeInt32ToFloat64(gate);
599 }
600 
ConvertUInt32ToFloat64(GateRef gate)601 GateRef MCRLowering::ConvertUInt32ToFloat64(GateRef gate)
602 {
603     return builder_.ChangeUInt32ToFloat64(gate);
604 }
605 
ConvertInt32ToTaggedInt(GateRef gate)606 GateRef MCRLowering::ConvertInt32ToTaggedInt(GateRef gate)
607 {
608     return builder_.Int32ToTaggedPtr(gate);
609 }
610 
ConvertUInt32ToTaggedNumber(GateRef gate,Label * exit)611 GateRef MCRLowering::ConvertUInt32ToTaggedNumber(GateRef gate, Label *exit)
612 {
613     Label isOverFlow(&builder_);
614     Label notOverFlow(&builder_);
615     GateRef upperBound = builder_.Int32(INT32_MAX);
616     DEFVALUE(taggedVal, (&builder_), VariableType::JS_ANY(), builder_.HoleConstant());
617     builder_.Branch(builder_.Int32UnsignedLessThanOrEqual(gate, upperBound), &notOverFlow, &isOverFlow);
618     builder_.Bind(&notOverFlow);
619     taggedVal = builder_.Int32ToTaggedPtr(gate);
620     builder_.Jump(exit);
621     builder_.Bind(&isOverFlow);
622     taggedVal = builder_.DoubleToTaggedDoublePtr(builder_.ChangeUInt32ToFloat64(gate));
623     builder_.Jump(exit);
624     builder_.Bind(exit);
625     return *taggedVal;
626 }
627 
ConvertFloat64ToInt32(GateRef gate,Label * exit)628 GateRef MCRLowering::ConvertFloat64ToInt32(GateRef gate, Label *exit)
629 {
630     return builder_.DoubleToInt(gate, exit);
631 }
632 
ConvertFloat64ToBool(GateRef gate)633 GateRef MCRLowering::ConvertFloat64ToBool(GateRef gate)
634 {
635     GateRef doubleNotZero = builder_.DoubleNotEqual(gate, builder_.Double(0.0));
636     GateRef doubleNotNAN = builder_.BoolNot(builder_.DoubleIsNAN(gate));
637     return builder_.BoolAnd(doubleNotZero, doubleNotNAN);
638 }
639 
ConvertFloat64ToTaggedDouble(GateRef gate)640 GateRef MCRLowering::ConvertFloat64ToTaggedDouble(GateRef gate)
641 {
642     return builder_.DoubleToTaggedDoublePtr(gate);
643 }
644 
ConvertTaggedIntToInt32(GateRef gate)645 GateRef MCRLowering::ConvertTaggedIntToInt32(GateRef gate)
646 {
647     return builder_.GetInt32OfTInt(gate);
648 }
649 
ConvertTaggedIntToFloat64(GateRef gate)650 GateRef MCRLowering::ConvertTaggedIntToFloat64(GateRef gate)
651 {
652     return builder_.ChangeInt32ToFloat64(builder_.GetInt32OfTInt(gate));
653 }
654 
ConvertTaggedDoubleToInt32(GateRef gate,Label * exit)655 GateRef MCRLowering::ConvertTaggedDoubleToInt32(GateRef gate, Label *exit)
656 {
657     return builder_.DoubleToInt(builder_.GetDoubleOfTDouble(gate), exit);
658 }
659 
ConvertTaggedDoubleToFloat64(GateRef gate)660 GateRef MCRLowering::ConvertTaggedDoubleToFloat64(GateRef gate)
661 {
662     return builder_.GetDoubleOfTDouble(gate);
663 }
664 
LowerGetGlobalEnv(GateRef gate)665 void MCRLowering::LowerGetGlobalEnv(GateRef gate)
666 {
667     Environment env(gate, circuit_, &builder_);
668     GateRef glueGlobalEnvOffset = builder_.IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(false));
669     GateRef glueGlobalEnv = builder_.Load(VariableType::JS_POINTER(), glue_, glueGlobalEnvOffset);
670     acc_.ReplaceGate(gate, Circuit::NullGate(), builder_.GetDepend(), glueGlobalEnv);
671 }
672 
LowerGetGlobalEnvObj(GateRef gate)673 void MCRLowering::LowerGetGlobalEnvObj(GateRef gate)
674 {
675     Environment env(gate, circuit_, &builder_);
676     GateRef globalEnv = acc_.GetValueIn(gate, 0);
677     size_t index = acc_.GetIndex(gate);
678     GateRef offset = builder_.IntPtr(GlobalEnv::HEADER_SIZE + JSTaggedValue::TaggedTypeSize() * index);
679     GateRef object = builder_.Load(VariableType::JS_ANY(), globalEnv, offset);
680     acc_.ReplaceGate(gate, Circuit::NullGate(), builder_.GetDepend(), object);
681 }
682 
LowerGetGlobalEnvObjHClass(GateRef gate)683 void MCRLowering::LowerGetGlobalEnvObjHClass(GateRef gate)
684 {
685     Environment env(gate, circuit_, &builder_);
686     GateRef globalEnv = acc_.GetValueIn(gate, 0);
687     size_t index = acc_.GetIndex(gate);
688     GateRef offset = builder_.IntPtr(GlobalEnv::HEADER_SIZE + JSTaggedValue::TaggedTypeSize() * index);
689     GateRef object = builder_.Load(VariableType::JS_ANY(), globalEnv, offset);
690     auto hclass = builder_.Load(VariableType::JS_POINTER(), object,
691                                 builder_.IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
692     acc_.ReplaceGate(gate, Circuit::NullGate(), builder_.GetDepend(), hclass);
693 }
694 
LowerGetGlobalConstantValue(GateRef gate)695 void MCRLowering::LowerGetGlobalConstantValue(GateRef gate)
696 {
697     Environment env(gate, circuit_, &builder_);
698     size_t index = acc_.GetIndex(gate);
699     GateRef gConstAddr = builder_.Load(VariableType::JS_POINTER(), glue_,
700         builder_.IntPtr(JSThread::GlueData::GetGlobalConstOffset(false)));
701     GateRef constantIndex = builder_.IntPtr(JSTaggedValue::TaggedTypeSize() * index);
702     GateRef result = builder_.Load(VariableType::JS_POINTER(), gConstAddr, constantIndex);
703     acc_.ReplaceGate(gate, Circuit::NullGate(), builder_.GetDepend(), result);
704 }
705 
LowerHeapAllocate(GateRef gate)706 void MCRLowering::LowerHeapAllocate(GateRef gate)
707 {
708     Environment env(gate, circuit_, &builder_);
709     auto flag = acc_.TryGetValue(gate);
710     switch (flag) {
711         case RegionSpaceFlag::IN_YOUNG_SPACE:
712             HeapAllocateInYoung(gate);
713             break;
714         default:
715             LOG_ECMA(FATAL) << "this branch is unreachable";
716             UNREACHABLE();
717     }
718 }
719 
HeapAllocateInYoung(GateRef gate)720 void MCRLowering::HeapAllocateInYoung(GateRef gate)
721 {
722     Label exit(&builder_);
723     GateRef size = acc_.GetValueIn(gate, 0);
724     DEFVALUE(result, (&builder_), VariableType::JS_ANY(), builder_.HoleConstant());
725 #ifndef ARK_ASAN_ON
726     Label success(&builder_);
727     Label callRuntime(&builder_);
728     size_t topOffset = JSThread::GlueData::GetNewSpaceAllocationTopAddressOffset(false);
729     size_t endOffset = JSThread::GlueData::GetNewSpaceAllocationEndAddressOffset(false);
730     GateRef topAddress = builder_.Load(VariableType::NATIVE_POINTER(), glue_, builder_.IntPtr(topOffset));
731     GateRef endAddress = builder_.Load(VariableType::NATIVE_POINTER(), glue_, builder_.IntPtr(endOffset));
732     GateRef top = builder_.Load(VariableType::JS_POINTER(), topAddress, builder_.IntPtr(0));
733     GateRef end = builder_.Load(VariableType::JS_POINTER(), endAddress, builder_.IntPtr(0));
734 
735     GateRef newTop = builder_.PtrAdd(top, size);
736     builder_.Branch(builder_.IntPtrGreaterThan(newTop, end), &callRuntime, &success);
737     builder_.Bind(&success);
738     {
739         builder_.Store(VariableType::NATIVE_POINTER(), glue_, topAddress, builder_.IntPtr(0), newTop);
740         result = top;
741         builder_.Jump(&exit);
742     }
743     builder_.Bind(&callRuntime);
744 #endif
745     {
746         result = builder_.CallRuntime(glue_, RTSTUB_ID(AllocateInYoung), Gate::InvalidGateRef,
747                                       {builder_.ToTaggedInt(size)}, gate);
748         builder_.Jump(&exit);
749     }
750     builder_.Bind(&exit);
751 
752     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result);
753 }
754 
LowerInt32CheckRightIsZero(GateRef gate)755 void MCRLowering::LowerInt32CheckRightIsZero(GateRef gate)
756 {
757     Environment env(gate, circuit_, &builder_);
758     GateRef frameState = acc_.GetFrameState(gate);
759     GateRef right = acc_.GetValueIn(gate, 0);
760     GateRef rightNotZero = builder_.Int32NotEqual(right, builder_.Int32(0));
761     builder_.DeoptCheck(rightNotZero, frameState, DeoptType::MODZERO1);
762     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
763 }
764 
LowerRemainderIsNegativeZero(GateRef gate)765 void MCRLowering::LowerRemainderIsNegativeZero(GateRef gate)
766 {
767     Environment env(gate, circuit_, &builder_);
768     GateRef frameState = acc_.GetFrameState(gate);
769     GateRef left = acc_.GetValueIn(gate, 0);
770     GateRef right = acc_.GetValueIn(gate, 1);
771     GateRef leftIsNegative = builder_.Int32LessThan(left, builder_.Int32(0));
772     GateRef remainder =
773         builder_.BinaryArithmetic(circuit_->Smod(), MachineType::I32, left, right, GateType::NJSValue());
774     GateRef remainderEqualZero = builder_.Int32Equal(remainder, builder_.Int32(0));
775     GateRef remainderIsNotNegative = builder_.BoolNot(builder_.BoolAnd(leftIsNegative, remainderEqualZero));
776     builder_.DeoptCheck(remainderIsNotNegative, frameState, DeoptType::REMAINDERISNEGATIVEZERO);
777     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
778 }
779 
LowerFloat64CheckRightIsZero(GateRef gate)780 void MCRLowering::LowerFloat64CheckRightIsZero(GateRef gate)
781 {
782     Environment env(gate, circuit_, &builder_);
783     GateRef frameState = acc_.GetFrameState(gate);
784     GateRef right = acc_.GetValueIn(gate, 0);
785     GateRef rightNotZero = builder_.DoubleNotEqual(right, builder_.Double(0.0));
786     builder_.DeoptCheck(rightNotZero, frameState, DeoptType::DIVZERO1);
787     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
788 }
789 
LowerLexVarIsHoleCheck(GateRef gate)790 void MCRLowering::LowerLexVarIsHoleCheck(GateRef gate)
791 {
792     Environment env(gate, circuit_, &builder_);
793     GateRef frameState = acc_.GetFrameState(gate);
794     GateRef value = acc_.GetValueIn(gate, 0);
795     GateRef valueIsNotHole = builder_.TaggedIsNotHole(value);
796     builder_.DeoptCheck(valueIsNotHole, frameState, DeoptType::LEXVARISHOLE1);
797     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
798 }
799 
LowerValueCheckNegOverflow(GateRef gate)800 void MCRLowering::LowerValueCheckNegOverflow(GateRef gate)
801 {
802     Environment env(gate, circuit_, &builder_);
803     GateRef frameState = acc_.GetFrameState(gate);
804     GateRef value = acc_.GetValueIn(gate, 0);
805     GateRef valueNotZero = builder_.NotEqual(value, builder_.Int32(0));
806     builder_.DeoptCheck(valueNotZero, frameState, DeoptType::NOTNEGOV1);
807     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
808 }
809 
LowerOverflowCheck(GateRef gate)810 void MCRLowering::LowerOverflowCheck(GateRef gate)
811 {
812     Environment env(gate, circuit_, &builder_);
813     GateRef frameState = acc_.GetFrameState(gate);
814     GateRef result = acc_.GetValueIn(gate, 0);
815     GateRef condition = builder_.BoolNot(builder_.ExtractValue(MachineType::I1, result, builder_.Int32(1)));
816     builder_.DeoptCheck(condition, frameState, DeoptType::NOTINT3);
817     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
818 }
819 
LowerInt32UnsignedUpperBoundCheck(GateRef gate)820 void MCRLowering::LowerInt32UnsignedUpperBoundCheck(GateRef gate)
821 {
822     Environment env(gate, circuit_, &builder_);
823     GateRef frameState = acc_.GetFrameState(gate);
824     GateRef value = acc_.GetValueIn(gate, 0);
825     GateRef upperBound = acc_.GetValueIn(gate, 1);
826     GateRef condition = builder_.Int32UnsignedLessThanOrEqual(value, upperBound);
827     builder_.DeoptCheck(condition, frameState, DeoptType::NOTINT4);
828     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
829 }
830 
LowerInt32DivWithCheck(GateRef gate)831 void MCRLowering::LowerInt32DivWithCheck(GateRef gate)
832 {
833     Environment env(gate, circuit_, &builder_);
834     GateRef frameState = acc_.GetFrameState(gate);
835     GateRef left = acc_.GetValueIn(gate, 0);
836     GateRef right = acc_.GetValueIn(gate, 1);
837     GateRef result = Circuit::NullGate();
838     GateRef rightGreaterZero = builder_.Int32GreaterThan(right, builder_.Int32(0));
839     GateRef rightLessZero = builder_.Int32LessThan(right, builder_.Int32(0));
840     GateRef leftNotZero = builder_.Int32NotEqual(left, builder_.Int32(0));
841     GateRef condition = builder_.BoolOr(rightGreaterZero, builder_.BoolAnd(rightLessZero, leftNotZero));
842     builder_.DeoptCheck(condition, frameState, DeoptType::DIVZERO2);
843     result = builder_.BinaryArithmetic(circuit_->Sdiv(), MachineType::I32, left, right, GateType::NJSValue());
844     GateRef truncated = builder_.BinaryArithmetic(circuit_->Mul(),
845         MachineType::I32, result, right, GateType::NJSValue());
846     GateRef overCheck = builder_.Int32Equal(truncated, left);
847     builder_.DeoptCheck(overCheck, frameState, DeoptType::NOTINT5);
848     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
849 }
850 
LowerStoreMemory(GateRef gate)851 void MCRLowering::LowerStoreMemory(GateRef gate)
852 {
853     Environment env(gate, circuit_, &builder_);
854     GateRef receiver = acc_.GetValueIn(gate, 0);
855     GateRef index = acc_.GetValueIn(gate, 1);
856     GateRef value = acc_.GetValueIn(gate, 2);
857     builder_.Store(VariableType::VOID(), glue_, receiver, index, value);
858     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
859 }
860 
InitializeWithSpeicalValue(Label * exit,GateRef object,GateRef glue,GateRef value,GateRef start,GateRef end)861 void MCRLowering::InitializeWithSpeicalValue(Label *exit, GateRef object, GateRef glue,
862                                              GateRef value, GateRef start, GateRef end)
863 {
864     Label begin(&builder_);
865     Label storeValue(&builder_);
866     Label endLoop(&builder_);
867 
868     DEFVALUE(startOffset, (&builder_), VariableType::INT32(), start);
869     builder_.Jump(&begin);
870     builder_.LoopBegin(&begin);
871     {
872         builder_.Branch(builder_.Int32UnsignedLessThan(*startOffset, end), &storeValue, exit);
873         builder_.Bind(&storeValue);
874         {
875             builder_.Store(VariableType::INT64(), glue, object, builder_.ZExtInt32ToPtr(*startOffset), value);
876             startOffset = builder_.Int32Add(*startOffset, builder_.Int32(JSTaggedValue::TaggedTypeSize()));
877             builder_.Jump(&endLoop);
878         }
879         builder_.Bind(&endLoop);
880         builder_.LoopEnd(&begin);
881     }
882 }
883 }  // namespace panda::ecmascript
884