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