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