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), ¬OverFlow, &isOverFlow);
483 builder_.Bind(¬OverFlow);
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