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