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