• 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/lcr_lowering.h"
16 #include "ecmascript/compiler/bytecodes.h"
17 #include "ecmascript/global_env.h"
18 #include "ecmascript/js_thread.h"
19 #include "ecmascript/js_function.h"
20 
21 namespace panda::ecmascript::kungfu {
Run()22 void LCRLowering::Run()
23 {
24     std::vector<GateRef> gateList;
25     circuit_->GetAllGates(gateList);
26     for (const auto &gate : gateList) {
27         auto op = acc_.GetOpCode(gate);
28         switch (op) {
29             case OpCode::GET_CONSTPOOL:
30                 LowerGetConstPool(gate);
31                 break;
32             case OpCode::STATE_SPLIT:
33                 DeleteStateSplit(gate);
34                 break;
35             case OpCode::ARRAY_GUARDIAN_CHECK:
36                 LowerArrayGuardianCheck(gate);
37                 break;
38             case OpCode::HCLASS_STABLE_ARRAY_CHECK:
39                 LowerHClassStableArrayCheck(gate);
40                 break;
41             case OpCode::HEAP_OBJECT_CHECK:
42                 LowerHeapObjectCheck(gate);
43                 break;
44             case OpCode::LOAD_CONST_OFFSET:
45                 LowerLoadConstOffset(gate);
46                 break;
47             case OpCode::STORE_CONST_OFFSET:
48                 LowerStoreConstOffset(gate);
49                 break;
50             case OpCode::CONVERT_HOLE_AS_UNDEFINED:
51                 LowerConvertHoleAsUndefined(gate);
52                 break;
53             case OpCode::GET_GLOBAL_ENV:
54                 LowerGetGlobalEnv(gate);
55                 break;
56             case OpCode::GET_GLOBAL_ENV_OBJ_HCLASS:
57                 LowerGetGlobalEnvObjHClass(gate);
58                 break;
59             case OpCode::GET_GLOBAL_CONSTANT_VALUE:
60                 LowerGetGlobalConstantValue(gate);
61                 break;
62             case OpCode::HEAP_ALLOC:
63                 LowerHeapAllocate(gate);
64                 break;
65             case OpCode::INT32_CHECK_RIGHT_IS_ZERO:
66                 LowerInt32CheckRightIsZero(gate);
67                 break;
68             case OpCode::FLOAT64_CHECK_RIGHT_IS_ZERO:
69                 LowerFloat64CheckRightIsZero(gate);
70                 break;
71             case OpCode::VALUE_CHECK_NEG_OVERFLOW:
72                 LowerValueCheckNegOverflow(gate);
73                 break;
74             case OpCode::OVERFLOW_CHECK:
75                 LowerOverflowCheck(gate);
76                 break;
77             case OpCode::INT32_UNSIGNED_UPPER_BOUND_CHECK:
78                 LowerInt32UnsignedUpperBoundCheck(gate);
79                 break;
80             case OpCode::INT32_DIV_WITH_CHECK:
81                 LowerInt32DivWithCheck(gate);
82                 break;
83             case OpCode::LEX_VAR_IS_HOLE_CHECK:
84                 LowerLexVarIsHoleCheck(gate);
85                 break;
86             case OpCode::STORE_MEMORY:
87                 LowerStoreMemory(gate);
88                 break;
89             case OpCode::CHECK_AND_CONVERT:
90                 LowerCheckAndConvert(gate);
91                 break;
92             default:
93                 break;
94         }
95     }
96 
97     if (IsLogEnabled()) {
98         LOG_COMPILER(INFO) << " ";
99         LOG_COMPILER(INFO) << "\033[34m" << "================="
100                            << " After LCRLowering "
101                            << "[" << GetMethodName() << "] "
102                            << "=================" << "\033[0m";
103         circuit_->PrintAllGatesWithBytecode();
104         LOG_COMPILER(INFO) << "\033[34m" << "=========================== End ===========================" << "\033[0m";
105     }
106 }
107 
LowerConvertHoleAsUndefined(GateRef gate)108 void LCRLowering::LowerConvertHoleAsUndefined(GateRef gate)
109 {
110     Environment env(gate, circuit_, &builder_);
111 
112     Label returnUndefined(&builder_);
113     Label exit(&builder_);
114     GateRef receiver = acc_.GetValueIn(gate, 0);
115     DEFVAlUE(result, (&builder_), VariableType::JS_ANY(), receiver);
116 
117     builder_.Branch(builder_.TaggedIsHole(*result), &returnUndefined, &exit);
118     builder_.Bind(&returnUndefined);
119     {
120         result = builder_.UndefineConstant();
121         builder_.Jump(&exit);
122     }
123     builder_.Bind(&exit);
124     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result);
125 }
126 
LowerLoadConstOffset(GateRef gate)127 void LCRLowering::LowerLoadConstOffset(GateRef gate)
128 {
129     Environment env(gate, circuit_, &builder_);
130     GateRef receiver = acc_.GetValueIn(gate, 0);
131     GateRef offset = builder_.IntPtr(acc_.GetOffset(gate));
132     VariableType type = VariableType(acc_.GetMachineType(gate), acc_.GetGateType(gate));
133     GateRef result = builder_.Load(type, receiver, offset);
134     acc_.ReplaceGate(gate, Circuit::NullGate(), builder_.GetDepend(), result);
135 }
136 
LowerStoreConstOffset(GateRef gate)137 void LCRLowering::LowerStoreConstOffset(GateRef gate)
138 {
139     Environment env(gate, circuit_, &builder_);
140 
141     GateRef receiver = acc_.GetValueIn(gate, 0);
142     GateRef value = acc_.GetValueIn(gate, 1);
143     GateRef offset = builder_.IntPtr(acc_.GetOffset(gate));
144     VariableType type = VariableType(acc_.GetMachineType(gate), acc_.GetGateType(gate));
145     builder_.Store(type, glue_, receiver, offset, value);
146     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
147 }
148 
LowerHeapObjectCheck(GateRef gate)149 void LCRLowering::LowerHeapObjectCheck(GateRef gate)
150 {
151     Environment env(gate, circuit_, &builder_);
152     GateRef frameState = acc_.GetFrameState(gate);
153     GateRef receiver = acc_.GetValueIn(gate, 0);
154 
155     GateRef heapObjectCheck = builder_.TaggedIsHeapObject(receiver);
156     builder_.DeoptCheck(heapObjectCheck, frameState, DeoptType::NOTHEAPOBJECT);
157 
158     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
159 }
160 
LowerGetConstPool(GateRef gate)161 void LCRLowering::LowerGetConstPool(GateRef gate)
162 {
163     Environment env(gate, circuit_, &builder_);
164     GateRef jsFunc = acc_.GetValueIn(gate, 0); // 0: this object
165     GateRef newGate = builder_.GetConstPoolFromFunction(jsFunc);
166 
167     acc_.UpdateAllUses(gate, newGate);
168 
169     // delete old gate
170     acc_.DeleteGate(gate);
171 }
172 
DeleteStateSplit(GateRef gate)173 void LCRLowering::DeleteStateSplit(GateRef gate)
174 {
175     auto depend = acc_.GetDep(gate);
176     auto frameState = acc_.GetFrameState(gate);
177     acc_.DeleteGateIfNoUse(frameState);
178     acc_.ReplaceGate(gate, Circuit::NullGate(), depend, Circuit::NullGate());
179 }
180 
LowerArrayGuardianCheck(GateRef gate)181 void LCRLowering::LowerArrayGuardianCheck(GateRef gate)
182 {
183     Environment env(gate, circuit_, &builder_);
184 
185     GateRef frameState = acc_.GetFrameState(gate);
186     GateRef guardiansOffset = builder_.IntPtr(JSThread::GlueData::GetStableArrayElementsGuardiansOffset(false));
187     GateRef check = builder_.Load(VariableType::BOOL(), glue_, guardiansOffset);
188     builder_.DeoptCheck(check, frameState, DeoptType::NOTSARRAY);
189 
190     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
191 }
192 
LowerHClassStableArrayCheck(GateRef gate)193 void LCRLowering::LowerHClassStableArrayCheck(GateRef gate)
194 {
195     Environment env(gate, circuit_, &builder_);
196     GateRef frameState = acc_.GetFrameState(gate);
197     GateRef hclass = acc_.GetValueIn(gate, 0);
198 
199     GateRef check = Circuit::NullGate();
200     GateRef stableCheck = builder_.IsIsStableElementsByHClass(hclass);
201     ArrayMetaDataAccessor accessor = acc_.GetArrayMetaDataAccessor(gate);
202     ElementsKind kind = accessor.GetElementsKind();
203     if (accessor.IsLoadElement() && !Elements::IsHole(kind)) {
204         GateRef elementsKindCheck = builder_.Equal(builder_.Int32(static_cast<int32_t>(kind)),
205                                                    builder_.GetElementsKindByHClass(hclass));
206         check = builder_.BoolAnd(stableCheck, elementsKindCheck);
207     } else {
208         check = stableCheck;
209     }
210     builder_.DeoptCheck(check, frameState, DeoptType::NOTSARRAY);
211 
212     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
213 }
214 
LowerConvert(StateDepend stateDepend,GateRef gate)215 StateDepend LCRLowering::LowerConvert(StateDepend stateDepend, GateRef gate)
216 {
217     Environment env(stateDepend.State(), stateDepend.Depend(), {}, circuit_, &builder_);
218     GateRef value = acc_.GetValueIn(gate);
219     ValueType dstType = acc_.GetDstType(gate);
220     GateRef result = Circuit::NullGate();
221     Label exit(&builder_);
222     switch (acc_.GetSrcType(gate)) {
223         case ValueType::BOOL:
224             ASSERT(dstType == ValueType::TAGGED_BOOLEAN);
225             result = ConvertBoolToTaggedBoolean(value);
226             break;
227         case ValueType::INT32:
228             if (dstType == ValueType::TAGGED_INT) {
229                 result = ConvertInt32ToTaggedInt(value);
230             } else if (dstType == ValueType::FLOAT64) {
231                 result = ConvertInt32ToFloat64(value);
232             } else {
233                 ASSERT(dstType == ValueType::BOOL);
234                 result = builder_.NotEqual(value, builder_.Int32(0));
235             }
236             break;
237         case ValueType::UINT32:
238             if (dstType == ValueType::TAGGED_NUMBER) {
239                 result = ConvertUInt32ToTaggedNumber(value, &exit);
240             } else if (dstType == ValueType::FLOAT64) {
241                 result = ConvertUInt32ToFloat64(value);
242             } else {
243                 ASSERT(dstType == ValueType::BOOL);
244                 result = builder_.NotEqual(value,builder_.Int32(0));
245             }
246             break;
247         case ValueType::FLOAT64:
248             if (dstType == ValueType::TAGGED_DOUBLE) {
249                 result = ConvertFloat64ToTaggedDouble(value);
250             } else if (dstType == ValueType::INT32) {
251                 result = ConvertFloat64ToInt32(value, &exit);
252             } else {
253                 ASSERT(dstType == ValueType::BOOL);
254                 result = ConvertFloat64ToBool(value);
255             }
256             break;
257         case ValueType::TAGGED_BOOLEAN:
258             ASSERT((dstType == ValueType::BOOL));
259             result = ConvertTaggedBooleanToBool(value);
260             break;
261         case ValueType::TAGGED_INT:
262             ASSERT((dstType == ValueType::INT32));
263             result = ConvertTaggedIntToInt32(value);
264             break;
265         case ValueType::TAGGED_DOUBLE:
266             ASSERT((dstType == ValueType::FLOAT64));
267             result = ConvertTaggedDoubleToFloat64(value);
268             break;
269         default:
270             LOG_COMPILER(FATAL) << "this branch is unreachable";
271             break;
272     }
273     acc_.ReplaceGate(gate, Circuit::NullGate(), Circuit::NullGate(), result);
274     return builder_.GetStateDepend();
275 }
276 
ConvertTaggedNumberToBool(GateRef gate,Label * exit)277 GateRef LCRLowering::ConvertTaggedNumberToBool(GateRef gate, Label *exit)
278 {
279     DEFVAlUE(result, (&builder_), VariableType::BOOL(), builder_.Boolean(false));
280     Label isInt(&builder_);
281     Label isDouble(&builder_);
282     Label toInt32(&builder_);
283     builder_.Branch(builder_.TaggedIsInt(gate), &isInt, &isDouble);
284     builder_.Bind(&isInt);
285     {
286         GateRef intVal = builder_.GetInt64OfTInt(gate);
287         result = builder_.NotEqual(intVal, builder_.Int64(0));
288     }
289     builder_.Jump(exit);
290     builder_.Bind(&isDouble);
291     {
292         GateRef doubleVal = builder_.GetDoubleOfTDouble(gate);
293         result = ConvertFloat64ToBool(doubleVal);
294     }
295     builder_.Jump(exit);
296     builder_.Bind(exit);
297     return *result;
298 }
299 
ConvertTaggedNumberToInt32(GateRef gate,Label * exit)300 GateRef LCRLowering::ConvertTaggedNumberToInt32(GateRef gate, Label *exit)
301 {
302     DEFVAlUE(result, (&builder_), VariableType::INT32(), builder_.Int32(0));
303     Label isInt(&builder_);
304     Label isDouble(&builder_);
305     Label toInt32(&builder_);
306     builder_.Branch(builder_.TaggedIsInt(gate), &isInt, &isDouble);
307     builder_.Bind(&isInt);
308     result = ConvertTaggedIntToInt32(gate);
309     builder_.Jump(exit);
310     builder_.Bind(&isDouble);
311     result = ConvertFloat64ToInt32(ConvertTaggedDoubleToFloat64(gate), &toInt32);
312     builder_.Jump(exit);
313     builder_.Bind(exit);
314     return *result;
315 }
316 
ConvertTaggedNumberToFloat64(GateRef gate,Label * exit)317 GateRef LCRLowering::ConvertTaggedNumberToFloat64(GateRef gate, Label *exit)
318 {
319     DEFVAlUE(result, (&builder_), VariableType::FLOAT64(), builder_.Double(0));
320     Label isInt(&builder_);
321     Label isDouble(&builder_);
322     builder_.Branch(builder_.TaggedIsInt(gate), &isInt, &isDouble);
323     builder_.Bind(&isInt);
324     result = ConvertInt32ToFloat64(ConvertTaggedIntToInt32(gate));
325     builder_.Jump(exit);
326     builder_.Bind(&isDouble);
327     result = ConvertTaggedDoubleToFloat64(gate);
328     builder_.Jump(exit);
329     builder_.Bind(exit);
330     return *result;
331 }
332 
LowerCheckAndConvert(GateRef gate)333 void LCRLowering::LowerCheckAndConvert(GateRef gate)
334 {
335     Environment env(gate, circuit_, &builder_);
336     GateRef frameState = acc_.GetFrameState(gate);
337     ValueType srcType = acc_.GetSrcType(gate);
338     Label exit(&builder_);
339     switch (srcType) {
340         case ValueType::UINT32:
341             LowerCheckUInt32AndConvert(gate, frameState);
342             break;
343         case ValueType::TAGGED_INT:
344             LowerCheckTaggedIntAndConvert(gate, frameState);
345             break;
346         case ValueType::TAGGED_DOUBLE:
347             LowerCheckTaggedDoubleAndConvert(gate, frameState, &exit);
348             break;
349         case ValueType::TAGGED_BOOLEAN:
350             LowerCheckTaggedBoolAndConvert(gate, frameState);
351             break;
352         case ValueType::TAGGED_NUMBER:
353             LowerCheckTaggedNumberAndConvert(gate, frameState, &exit);
354             break;
355         case ValueType::BOOL:
356             LowerCheckSupportAndConvert(gate, frameState);
357             break;
358         default:
359             UNREACHABLE();
360     }
361 }
362 
LowerCheckUInt32AndConvert(GateRef gate,GateRef frameState)363 void LCRLowering::LowerCheckUInt32AndConvert(GateRef gate, GateRef frameState)
364 {
365     GateRef value = acc_.GetValueIn(gate, 0);
366     GateRef upperBound = builder_.Int32(INT32_MAX);
367     GateRef check = builder_.Int32UnsignedLessThanOrEqual(value, upperBound);
368     builder_.DeoptCheck(check, frameState, DeoptType::INT32OVERFLOW);
369     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), value);
370 }
371 
LowerCheckTaggedIntAndConvert(GateRef gate,GateRef frameState)372 void LCRLowering::LowerCheckTaggedIntAndConvert(GateRef gate, GateRef frameState)
373 {
374     GateRef value = acc_.GetValueIn(gate, 0);
375     GateRef typeCheck = builder_.TaggedIsInt(value);
376     builder_.DeoptCheck(typeCheck, frameState, DeoptType::NOTINT);
377     GateRef result = Circuit::NullGate();
378     ValueType dst = acc_.GetDstType(gate);
379     ASSERT(dst == ValueType::INT32 || dst == ValueType::FLOAT64);
380     if (dst == ValueType::INT32) {
381         result = ConvertTaggedIntToInt32(value);
382     } else {
383         result = ConvertTaggedIntToFloat64(value);
384     }
385     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
386 }
387 
LowerCheckTaggedDoubleAndConvert(GateRef gate,GateRef frameState,Label * exit)388 void LCRLowering::LowerCheckTaggedDoubleAndConvert(GateRef gate, GateRef frameState, Label *exit)
389 {
390     GateRef value = acc_.GetValueIn(gate, 0);
391     GateRef typeCheck = builder_.TaggedIsDouble(value);
392     builder_.DeoptCheck(typeCheck, frameState, DeoptType::NOTDOUBLE);
393     GateRef result = Circuit::NullGate();
394     ValueType dst = acc_.GetDstType(gate);
395     ASSERT(dst == ValueType::INT32 || dst == ValueType::FLOAT64);
396     if (dst == ValueType::INT32) {
397         result = ConvertTaggedDoubleToInt32(value, exit);
398     } else {
399         result = ConvertTaggedDoubleToFloat64(value);
400     }
401     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
402 }
403 
LowerCheckTaggedNumberAndConvert(GateRef gate,GateRef frameState,Label * exit)404 void LCRLowering::LowerCheckTaggedNumberAndConvert(GateRef gate, GateRef frameState, Label *exit)
405 {
406     GateRef value = acc_.GetValueIn(gate, 0);
407     GateRef typeCheck = builder_.TaggedIsNumber(value);
408     builder_.DeoptCheck(typeCheck, frameState, DeoptType::NOTNUMBER);
409     GateRef result = Circuit::NullGate();
410     ValueType dst = acc_.GetDstType(gate);
411     if (dst == ValueType::INT32) {
412         result = ConvertTaggedNumberToInt32(value, exit);
413     } else if (dst == ValueType::FLOAT64) {
414         result = ConvertTaggedNumberToFloat64(value, exit);
415     } else {
416         ASSERT(dst == ValueType::BOOL);
417         result = ConvertTaggedNumberToBool(value, exit);
418     }
419     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
420 }
421 
LowerCheckSupportAndConvert(GateRef gate,GateRef frameState)422 void LCRLowering::LowerCheckSupportAndConvert(GateRef gate, GateRef frameState)
423 {
424     ValueType dstType = acc_.GetDstType(gate);
425     ASSERT(dstType == ValueType::INT32 || dstType == ValueType::FLOAT64);
426     bool support = acc_.IsConvertSupport(gate);
427     GateRef value = acc_.GetValueIn(gate, 0);
428 
429     GateRef result = Circuit::NullGate();
430     if (dstType == ValueType::INT32) {
431         builder_.DeoptCheck(builder_.Boolean(support), frameState, DeoptType::NOTINT);
432         result = builder_.BooleanToInt32(value);
433     } else {
434         builder_.DeoptCheck(builder_.Boolean(support), frameState, DeoptType::NOTDOUBLE);
435         result = builder_.BooleanToFloat64(value);
436     }
437     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
438 }
439 
LowerCheckTaggedBoolAndConvert(GateRef gate,GateRef frameState)440 void LCRLowering::LowerCheckTaggedBoolAndConvert(GateRef gate, GateRef frameState)
441 {
442     GateRef value = acc_.GetValueIn(gate, 0);
443     GateRef typeCheck = builder_.TaggedIsBoolean(value);
444     builder_.DeoptCheck(typeCheck, frameState, DeoptType::NOTBOOL);
445     GateRef result = Circuit::NullGate();
446     ASSERT(acc_.GetDstType(gate) == ValueType::BOOL);
447     result = ConvertTaggedBooleanToBool(value);
448     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
449 }
450 
ConvertTaggedBooleanToBool(GateRef value)451 GateRef LCRLowering::ConvertTaggedBooleanToBool(GateRef value)
452 {
453     return builder_.TaggedIsTrue(value);
454 }
455 
ConvertBoolToTaggedBoolean(GateRef gate)456 GateRef LCRLowering::ConvertBoolToTaggedBoolean(GateRef gate)
457 {
458     return builder_.BooleanToTaggedBooleanPtr(gate);
459 }
460 
ConvertInt32ToFloat64(GateRef gate)461 GateRef LCRLowering::ConvertInt32ToFloat64(GateRef gate)
462 {
463     return builder_.ChangeInt32ToFloat64(gate);
464 }
465 
ConvertUInt32ToFloat64(GateRef gate)466 GateRef LCRLowering::ConvertUInt32ToFloat64(GateRef gate)
467 {
468     return builder_.ChangeUInt32ToFloat64(gate);
469 }
470 
ConvertInt32ToTaggedInt(GateRef gate)471 GateRef LCRLowering::ConvertInt32ToTaggedInt(GateRef gate)
472 {
473     return builder_.Int32ToTaggedPtr(gate);
474 }
475 
ConvertUInt32ToTaggedNumber(GateRef gate,Label * exit)476 GateRef LCRLowering::ConvertUInt32ToTaggedNumber(GateRef gate, Label *exit)
477 {
478     Label isOverFlow(&builder_);
479     Label notOverFlow(&builder_);
480     GateRef upperBound = builder_.Int32(INT32_MAX);
481     DEFVAlUE(taggedVal, (&builder_), VariableType::JS_ANY(), builder_.HoleConstant());
482     builder_.Branch(builder_.Int32UnsignedLessThanOrEqual(gate, upperBound), &notOverFlow, &isOverFlow);
483     builder_.Bind(&notOverFlow);
484     taggedVal = builder_.Int32ToTaggedPtr(gate);
485     builder_.Jump(exit);
486     builder_.Bind(&isOverFlow);
487     taggedVal = builder_.DoubleToTaggedDoublePtr(builder_.ChangeUInt32ToFloat64(gate));
488     builder_.Jump(exit);
489     builder_.Bind(exit);
490     return *taggedVal;
491 }
492 
ConvertFloat64ToInt32(GateRef gate,Label * exit)493 GateRef LCRLowering::ConvertFloat64ToInt32(GateRef gate, Label *exit)
494 {
495     return builder_.DoubleToInt(gate, exit);
496 }
497 
ConvertFloat64ToBool(GateRef gate)498 GateRef LCRLowering::ConvertFloat64ToBool(GateRef gate)
499 {
500     GateRef doubleNotZero = builder_.DoubleNotEqual(gate, builder_.Double(0.0));
501     GateRef doubleNotNAN = builder_.BoolNot(builder_.DoubleIsNAN(gate));
502     return builder_.BoolAnd(doubleNotZero, doubleNotNAN);
503 }
504 
ConvertFloat64ToTaggedDouble(GateRef gate)505 GateRef LCRLowering::ConvertFloat64ToTaggedDouble(GateRef gate)
506 {
507     return builder_.DoubleToTaggedDoublePtr(gate);
508 }
509 
ConvertTaggedIntToInt32(GateRef gate)510 GateRef LCRLowering::ConvertTaggedIntToInt32(GateRef gate)
511 {
512     return builder_.GetInt32OfTInt(gate);
513 }
514 
ConvertTaggedIntToFloat64(GateRef gate)515 GateRef LCRLowering::ConvertTaggedIntToFloat64(GateRef gate)
516 {
517     return builder_.ChangeInt32ToFloat64(builder_.GetInt32OfTInt(gate));
518 }
519 
ConvertTaggedDoubleToInt32(GateRef gate,Label * exit)520 GateRef LCRLowering::ConvertTaggedDoubleToInt32(GateRef gate, Label *exit)
521 {
522     return builder_.DoubleToInt(builder_.GetDoubleOfTDouble(gate), exit);
523 }
524 
ConvertTaggedDoubleToFloat64(GateRef gate)525 GateRef LCRLowering::ConvertTaggedDoubleToFloat64(GateRef gate)
526 {
527     return builder_.GetDoubleOfTDouble(gate);
528 }
529 
LowerGetGlobalEnv(GateRef gate)530 void LCRLowering::LowerGetGlobalEnv(GateRef gate)
531 {
532     Environment env(gate, circuit_, &builder_);
533     GateRef glueGlobalEnvOffset = builder_.IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(false));
534     GateRef glueGlobalEnv = builder_.Load(VariableType::JS_POINTER(), glue_, glueGlobalEnvOffset);
535     acc_.ReplaceGate(gate, Circuit::NullGate(), builder_.GetDepend(), glueGlobalEnv);
536 }
537 
LowerGetGlobalEnvObjHClass(GateRef gate)538 void LCRLowering::LowerGetGlobalEnvObjHClass(GateRef gate)
539 {
540     Environment env(gate, circuit_, &builder_);
541     GateRef globalEnv = acc_.GetValueIn(gate, 0);
542     size_t index = acc_.GetIndex(gate);
543     GateRef offset = builder_.IntPtr(GlobalEnv::HEADER_SIZE + JSTaggedValue::TaggedTypeSize() * index);
544     GateRef object = builder_.Load(VariableType::JS_ANY(), globalEnv, offset);
545     auto hclass = builder_.Load(VariableType::JS_POINTER(), object,
546                                 builder_.IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
547     acc_.ReplaceGate(gate, Circuit::NullGate(), builder_.GetDepend(), hclass);
548 }
549 
LowerGetGlobalConstantValue(GateRef gate)550 void LCRLowering::LowerGetGlobalConstantValue(GateRef gate)
551 {
552     Environment env(gate, circuit_, &builder_);
553     size_t index = acc_.GetIndex(gate);
554     GateRef gConstAddr = builder_.Load(VariableType::JS_POINTER(), glue_,
555         builder_.IntPtr(JSThread::GlueData::GetGlobalConstOffset(false)));
556     GateRef constantIndex = builder_.IntPtr(JSTaggedValue::TaggedTypeSize() * index);
557     GateRef result = builder_.Load(VariableType::JS_POINTER(), gConstAddr, constantIndex);
558     acc_.ReplaceGate(gate, Circuit::NullGate(), builder_.GetDepend(), result);
559 }
560 
LowerHeapAllocate(GateRef gate)561 void LCRLowering::LowerHeapAllocate(GateRef gate)
562 {
563     Environment env(gate, circuit_, &builder_);
564     auto flag = acc_.TryGetValue(gate);
565     switch (flag) {
566         case RegionSpaceFlag::IN_YOUNG_SPACE:
567             HeapAllocateInYoung(gate);
568             break;
569         default:
570             LOG_ECMA(FATAL) << "this branch is unreachable";
571             UNREACHABLE();
572     }
573 }
574 
HeapAllocateInYoung(GateRef gate)575 void LCRLowering::HeapAllocateInYoung(GateRef gate)
576 {
577     Label success(&builder_);
578     Label callRuntime(&builder_);
579     Label exit(&builder_);
580     GateRef size = acc_.GetValueIn(gate, 0);
581     size_t topOffset = JSThread::GlueData::GetNewSpaceAllocationTopAddressOffset(false);
582     size_t endOffset = JSThread::GlueData::GetNewSpaceAllocationEndAddressOffset(false);
583     GateRef topAddress = builder_.Load(VariableType::NATIVE_POINTER(), glue_, builder_.IntPtr(topOffset));
584     GateRef endAddress = builder_.Load(VariableType::NATIVE_POINTER(), glue_, builder_.IntPtr(endOffset));
585     GateRef top = builder_.Load(VariableType::JS_POINTER(), topAddress, builder_.IntPtr(0));
586     GateRef end = builder_.Load(VariableType::JS_POINTER(), endAddress, builder_.IntPtr(0));
587 
588     DEFVAlUE(result, (&builder_), VariableType::JS_ANY(), builder_.HoleConstant());
589     GateRef newTop = builder_.PtrAdd(top, size);
590     builder_.Branch(builder_.IntPtrGreaterThan(newTop, end), &callRuntime, &success);
591     builder_.Bind(&success);
592     {
593         builder_.Store(VariableType::NATIVE_POINTER(), glue_, topAddress, builder_.IntPtr(0), newTop);
594         result = top;
595         builder_.Jump(&exit);
596     }
597     builder_.Bind(&callRuntime);
598     {
599         result = builder_.CallRuntime(glue_, RTSTUB_ID(AllocateInYoung), Gate::InvalidGateRef,
600                                       {builder_.ToTaggedInt(size)}, gate);
601         builder_.Jump(&exit);
602     }
603     builder_.Bind(&exit);
604 
605     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result);
606 }
607 
LowerInt32CheckRightIsZero(GateRef gate)608 void LCRLowering::LowerInt32CheckRightIsZero(GateRef gate)
609 {
610     Environment env(gate, circuit_, &builder_);
611     GateRef frameState = acc_.GetFrameState(gate);
612     GateRef right = acc_.GetValueIn(gate, 0);
613     GateRef rightNotZero = builder_.Int32NotEqual(right, builder_.Int32(0));
614     builder_.DeoptCheck(rightNotZero, frameState, DeoptType::MODZERO);
615     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
616 }
617 
LowerFloat64CheckRightIsZero(GateRef gate)618 void LCRLowering::LowerFloat64CheckRightIsZero(GateRef gate)
619 {
620     Environment env(gate, circuit_, &builder_);
621     GateRef frameState = acc_.GetFrameState(gate);
622     GateRef right = acc_.GetValueIn(gate, 0);
623     GateRef rightNotZero = builder_.DoubleNotEqual(right, builder_.Double(0.0));
624     builder_.DeoptCheck(rightNotZero, frameState, DeoptType::DIVZERO);
625     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
626 }
627 
LowerLexVarIsHoleCheck(GateRef gate)628 void LCRLowering::LowerLexVarIsHoleCheck(GateRef gate)
629 {
630     Environment env(gate, circuit_, &builder_);
631     GateRef frameState = acc_.GetFrameState(gate);
632     GateRef value = acc_.GetValueIn(gate, 0);
633     GateRef valueIsNotHole = builder_.TaggedIsNotHole(value);
634     builder_.DeoptCheck(valueIsNotHole, frameState, DeoptType::LEXVARISHOLE);
635     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
636 }
637 
LowerValueCheckNegOverflow(GateRef gate)638 void LCRLowering::LowerValueCheckNegOverflow(GateRef gate)
639 {
640     Environment env(gate, circuit_, &builder_);
641     GateRef frameState = acc_.GetFrameState(gate);
642     GateRef value = acc_.GetValueIn(gate, 0);
643     GateRef valueNotZero = builder_.NotEqual(value, builder_.Int32(0));
644     builder_.DeoptCheck(valueNotZero, frameState, DeoptType::NOTNEGOV);
645     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
646 }
647 
LowerOverflowCheck(GateRef gate)648 void LCRLowering::LowerOverflowCheck(GateRef gate)
649 {
650     Environment env(gate, circuit_, &builder_);
651     GateRef frameState = acc_.GetFrameState(gate);
652     GateRef result = acc_.GetValueIn(gate, 0);
653     GateRef condition = builder_.BoolNot(builder_.ExtractValue(MachineType::I1, result, builder_.Int32(1)));
654     builder_.DeoptCheck(condition, frameState, DeoptType::NOTINT);
655     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
656 }
657 
LowerInt32UnsignedUpperBoundCheck(GateRef gate)658 void LCRLowering::LowerInt32UnsignedUpperBoundCheck(GateRef gate)
659 {
660     Environment env(gate, circuit_, &builder_);
661     GateRef frameState = acc_.GetFrameState(gate);
662     GateRef value = acc_.GetValueIn(gate, 0);
663     GateRef upperBound = acc_.GetValueIn(gate, 1);
664     GateRef condition = builder_.Int32UnsignedLessThanOrEqual(value, upperBound);
665     builder_.DeoptCheck(condition, frameState, DeoptType::NOTINT);
666     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
667 }
668 
LowerInt32DivWithCheck(GateRef gate)669 void LCRLowering::LowerInt32DivWithCheck(GateRef gate)
670 {
671     Environment env(gate, circuit_, &builder_);
672     GateRef frameState = acc_.GetFrameState(gate);
673     GateRef left = acc_.GetValueIn(gate, 0);
674     GateRef right = acc_.GetValueIn(gate, 1);
675     GateRef result = Circuit::NullGate();
676     GateRef rightGreaterZero = builder_.Int32GreaterThan(right, builder_.Int32(0));
677     GateRef rightLessZero = builder_.Int32LessThan(right, builder_.Int32(0));
678     GateRef leftNotZero = builder_.Int32NotEqual(left, builder_.Int32(0));
679     GateRef condition = builder_.BoolOr(rightGreaterZero, builder_.BoolAnd(rightLessZero, leftNotZero));
680     builder_.DeoptCheck(condition, frameState, DeoptType::DIVZERO);
681     result = builder_.BinaryArithmetic(circuit_->Sdiv(), MachineType::I32, left, right, GateType::NJSValue());
682     GateRef truncated = builder_.BinaryArithmetic(circuit_->Mul(),
683         MachineType::I32, result, right, GateType::NJSValue());
684     GateRef overCheck = builder_.Int32Equal(truncated, left);
685     builder_.DeoptCheck(overCheck, frameState, DeoptType::NOTINT);
686     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
687 }
688 
LowerStoreMemory(GateRef gate)689 void LCRLowering::LowerStoreMemory(GateRef gate)
690 {
691     Environment env(gate, circuit_, &builder_);
692     GateRef receiver = acc_.GetValueIn(gate, 0);
693     GateRef index = acc_.GetValueIn(gate, 1);
694     GateRef value = acc_.GetValueIn(gate, 2);
695     builder_.Store(VariableType::VOID(), glue_, receiver, index, value);
696     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
697 }
698 
InitializeWithSpeicalValue(Label * exit,GateRef object,GateRef glue,GateRef value,GateRef start,GateRef end)699 void LCRLowering::InitializeWithSpeicalValue(Label *exit, GateRef object, GateRef glue,
700                                              GateRef value, GateRef start, GateRef end)
701 {
702     Label begin(&builder_);
703     Label storeValue(&builder_);
704     Label endLoop(&builder_);
705 
706     DEFVAlUE(startOffset, (&builder_), VariableType::INT32(), start);
707     builder_.Jump(&begin);
708     builder_.LoopBegin(&begin);
709     {
710         builder_.Branch(builder_.Int32UnsignedLessThan(*startOffset, end), &storeValue, exit);
711         builder_.Bind(&storeValue);
712         {
713             builder_.Store(VariableType::INT64(), glue, object, builder_.ZExtInt32ToPtr(*startOffset), value);
714             startOffset = builder_.Int32Add(*startOffset, builder_.Int32(JSTaggedValue::TaggedTypeSize()));
715             builder_.Jump(&endLoop);
716         }
717         builder_.Bind(&endLoop);
718         builder_.LoopEnd(&begin);
719     }
720 }
721 }  // namespace panda::ecmascript
722