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