1 /*
2 * Copyright (c) 2022 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
16 #include "ecmascript/compiler/gate_meta_data.h"
17 #include "ecmascript/compiler/number_gate_info.h"
18 #include "ecmascript/compiler/type.h"
19 #include "ecmascript/compiler/type_mcr_lowering.h"
20 #include "ecmascript/compiler/builtins_lowering.h"
21 #include "ecmascript/compiler/new_object_stub_builder.h"
22 #include "ecmascript/compiler/number_speculative_lowering.h"
23 #include "ecmascript/deoptimizer/deoptimizer.h"
24 #include "ecmascript/js_arraybuffer.h"
25 #include "ecmascript/js_locale.h"
26 #include "ecmascript/js_native_pointer.h"
27
28 namespace panda::ecmascript::kungfu {
29
Run()30 void NumberSpeculativeLowering::Run()
31 {
32 std::vector<GateRef> gateList;
33 acc_.GetAllGates(gateList);
34 for (auto gate : gateList) {
35 auto op = acc_.GetOpCode(gate);
36 switch (op) {
37 case OpCode::RANGE_GUARD: {
38 rangeGuardGates_.push_back(gate);
39 break;
40 }
41 default: {
42 VisitGate(gate);
43 }
44 }
45 }
46 for (auto rangeGuard : rangeGuardGates_) {
47 VisitRangeGuard(rangeGuard);
48 }
49 }
50
VisitGate(GateRef gate)51 void NumberSpeculativeLowering::VisitGate(GateRef gate)
52 {
53 OpCode op = acc_.GetOpCode(gate);
54 switch (op) {
55 case OpCode::TYPED_BINARY_OP: {
56 VisitTypedBinaryOp(gate);
57 break;
58 }
59 case OpCode::TYPED_UNARY_OP: {
60 VisitTypedUnaryOp(gate);
61 break;
62 }
63 case OpCode::TYPED_CONDITION_JUMP: {
64 VisitTypedConditionJump(gate);
65 break;
66 }
67 case OpCode::VALUE_SELECTOR: {
68 VisitPhi(gate);
69 break;
70 }
71 case OpCode::CONSTANT: {
72 VisitConstant(gate);
73 break;
74 }
75 case OpCode::TYPED_CALL_BUILTIN: {
76 VisitCallBuiltins(gate);
77 break;
78 }
79 case OpCode::LOAD_ELEMENT: {
80 VisitLoadElement(gate);
81 break;
82 }
83 case OpCode::INDEX_CHECK: {
84 VisitIndexCheck(gate);
85 break;
86 }
87 case OpCode::LOAD_ARRAY_LENGTH:
88 case OpCode::LOAD_TYPED_ARRAY_LENGTH: {
89 VisitLoadArrayLength(gate);
90 break;
91 }
92 case OpCode::LOAD_PROPERTY: {
93 VisitLoadProperty(gate);
94 break;
95 }
96 default:
97 break;
98 }
99 }
100
VisitTypedBinaryOp(GateRef gate)101 void NumberSpeculativeLowering::VisitTypedBinaryOp(GateRef gate)
102 {
103 Environment env(gate, circuit_, &builder_);
104 if (acc_.HasNumberType(gate)) {
105 VisitNumberBinaryOp(gate);
106 } else {
107 [[maybe_unused]] GateRef left = acc_.GetValueIn(gate, 0);
108 [[maybe_unused]] GateRef right = acc_.GetValueIn(gate, 1);
109 ASSERT(acc_.IsConstantUndefined(left) || acc_.IsConstantUndefined(right));
110 ASSERT(acc_.GetTypedBinaryOp(gate) == TypedBinOp::TYPED_STRICTEQ);
111 VisitUndefinedStrictEq(gate);
112 }
113 }
114
VisitNumberBinaryOp(GateRef gate)115 void NumberSpeculativeLowering::VisitNumberBinaryOp(GateRef gate)
116 {
117 TypedBinOp Op = acc_.GetTypedBinaryOp(gate);
118 switch (Op) {
119 case TypedBinOp::TYPED_ADD: {
120 VisitNumberCalculate<TypedBinOp::TYPED_ADD>(gate);
121 break;
122 }
123 case TypedBinOp::TYPED_SUB: {
124 VisitNumberCalculate<TypedBinOp::TYPED_SUB>(gate);
125 break;
126 }
127 case TypedBinOp::TYPED_MUL: {
128 VisitNumberCalculate<TypedBinOp::TYPED_MUL>(gate);
129 break;
130 }
131 case TypedBinOp::TYPED_LESS: {
132 VisitNumberCompare<TypedBinOp::TYPED_LESS>(gate);
133 break;
134 }
135 case TypedBinOp::TYPED_LESSEQ: {
136 VisitNumberCompare<TypedBinOp::TYPED_LESSEQ>(gate);
137 break;
138 }
139 case TypedBinOp::TYPED_GREATER: {
140 VisitNumberCompare<TypedBinOp::TYPED_GREATER>(gate);
141 break;
142 }
143 case TypedBinOp::TYPED_GREATEREQ: {
144 VisitNumberCompare<TypedBinOp::TYPED_GREATEREQ>(gate);
145 break;
146 }
147 case TypedBinOp::TYPED_EQ: {
148 VisitNumberCompare<TypedBinOp::TYPED_EQ>(gate);
149 break;
150 }
151 case TypedBinOp::TYPED_NOTEQ: {
152 VisitNumberCompare<TypedBinOp::TYPED_NOTEQ>(gate);
153 break;
154 }
155 case TypedBinOp::TYPED_STRICTEQ: {
156 VisitNumberCompare<TypedBinOp::TYPED_STRICTEQ>(gate);
157 break;
158 }
159 case TypedBinOp::TYPED_SHL: {
160 VisitNumberShift<TypedBinOp::TYPED_SHL>(gate);
161 break;
162 }
163 case TypedBinOp::TYPED_SHR: {
164 VisitNumberShift<TypedBinOp::TYPED_SHR>(gate);
165 break;
166 }
167 case TypedBinOp::TYPED_ASHR: {
168 VisitNumberShift<TypedBinOp::TYPED_ASHR>(gate);
169 break;
170 }
171 case TypedBinOp::TYPED_AND: {
172 VisitNumberLogical<TypedBinOp::TYPED_AND>(gate);
173 break;
174 }
175 case TypedBinOp::TYPED_OR: {
176 VisitNumberLogical<TypedBinOp::TYPED_OR>(gate);
177 break;
178 }
179 case TypedBinOp::TYPED_XOR: {
180 VisitNumberLogical<TypedBinOp::TYPED_XOR>(gate);
181 break;
182 }
183 case TypedBinOp::TYPED_DIV: {
184 VisitNumberDiv(gate);
185 break;
186 }
187 case TypedBinOp::TYPED_MOD: {
188 VisitNumberMod<TypedBinOp::TYPED_MOD>(gate);
189 break;
190 }
191 default:
192 break;
193 }
194 }
195
VisitTypedUnaryOp(GateRef gate)196 void NumberSpeculativeLowering::VisitTypedUnaryOp(GateRef gate)
197 {
198 Environment env(gate, circuit_, &builder_);
199 TypedUnOp Op = acc_.GetTypedUnAccessor(gate).GetTypedUnOp();
200 switch (Op) {
201 case TypedUnOp::TYPED_INC: {
202 VisitNumberMonocular<TypedUnOp::TYPED_INC>(gate);
203 return;
204 }
205 case TypedUnOp::TYPED_DEC: {
206 VisitNumberMonocular<TypedUnOp::TYPED_DEC>(gate);
207 return;
208 }
209 case TypedUnOp::TYPED_NEG: {
210 VisitNumberMonocular<TypedUnOp::TYPED_NEG>(gate);
211 return;
212 }
213 case TypedUnOp::TYPED_ISFALSE: {
214 VisitIsTrueOrFalse(gate, false);
215 return;
216 }
217 case TypedUnOp::TYPED_ISTRUE: {
218 VisitIsTrueOrFalse(gate, true);
219 return;
220 }
221 case TypedUnOp::TYPED_NOT: {
222 VisitNumberNot(gate);
223 return;
224 }
225 default:
226 break;
227 }
228 }
229
VisitTypedConditionJump(GateRef gate)230 void NumberSpeculativeLowering::VisitTypedConditionJump(GateRef gate)
231 {
232 Environment env(gate, circuit_, &builder_);
233 GateType type = acc_.GetTypedJumpAccessor(gate).GetTypeValue();
234 if (type.IsBooleanType()) {
235 VisitBooleanJump(gate);
236 } else {
237 UNREACHABLE();
238 }
239 }
240
241 template<TypedBinOp Op>
VisitNumberCalculate(GateRef gate)242 void NumberSpeculativeLowering::VisitNumberCalculate(GateRef gate)
243 {
244 GateRef left = acc_.GetValueIn(gate, 0);
245 GateRef right = acc_.GetValueIn(gate, 1);
246 GateType gateType = acc_.GetGateType(gate);
247 PGOSampleType sampleType = acc_.GetTypedBinaryType(gate);
248 if (sampleType.IsNumber()) {
249 if (sampleType.IsInt()) {
250 gateType = GateType::IntType();
251 } else {
252 gateType = GateType::DoubleType();
253 }
254 }
255 GateRef result = Circuit::NullGate();
256 if (gateType.IsIntType()) {
257 result = CalculateInts<Op>(left, right); // int op int
258 UpdateRange(result, GetRange(gate));
259 acc_.SetMachineType(gate, MachineType::I32);
260 } else {
261 result = CalculateDoubles<Op>(left, right); // float op float
262 acc_.SetMachineType(gate, MachineType::F64);
263 }
264 acc_.SetGateType(gate, GateType::NJSValue());
265 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
266 }
267
268 template<TypedBinOp Op>
VisitNumberCompare(GateRef gate)269 void NumberSpeculativeLowering::VisitNumberCompare(GateRef gate)
270 {
271 GateRef left = acc_.GetValueIn(gate, 0);
272 GateRef right = acc_.GetValueIn(gate, 1);
273 GateType leftType = acc_.GetLeftType(gate);
274 GateType rightType = acc_.GetRightType(gate);
275 PGOSampleType sampleType = acc_.GetTypedBinaryType(gate);
276 if (sampleType.IsNumber()) {
277 if (sampleType.IsInt()) {
278 leftType = GateType::IntType();
279 rightType = GateType::IntType();
280 } else {
281 leftType = GateType::NumberType();
282 rightType = GateType::NumberType();
283 }
284 }
285 GateRef result = Circuit::NullGate();
286 if (leftType.IsIntType() && rightType.IsIntType()) {
287 result = CompareInts<Op>(left, right); // int op int
288 } else {
289 result = CompareDoubles<Op>(left, right); // float op float
290 }
291 acc_.SetMachineType(gate, MachineType::I1);
292 acc_.SetGateType(gate, GateType::NJSValue());
293 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
294 }
295
296 template<TypedBinOp Op>
VisitNumberShift(GateRef gate)297 void NumberSpeculativeLowering::VisitNumberShift(GateRef gate)
298 {
299 GateRef left = acc_.GetValueIn(gate, 0);
300 GateRef right = acc_.GetValueIn(gate, 1);
301 GateRef result = ShiftInts<Op>(left, right); // int op int
302 UpdateRange(result, GetRange(gate));
303 acc_.SetMachineType(gate, MachineType::I32);
304 acc_.SetGateType(gate, GateType::NJSValue());
305 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
306 }
307
308 template<TypedBinOp Op>
VisitNumberLogical(GateRef gate)309 void NumberSpeculativeLowering::VisitNumberLogical(GateRef gate)
310 {
311 GateRef left = acc_.GetValueIn(gate, 0);
312 GateRef right = acc_.GetValueIn(gate, 1);
313 GateRef result = LogicalInts<Op>(left, right); // int op int
314 UpdateRange(result, GetRange(gate));
315 acc_.SetMachineType(gate, MachineType::I32);
316 acc_.SetGateType(gate, GateType::NJSValue());
317 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
318 }
319
VisitNumberDiv(GateRef gate)320 void NumberSpeculativeLowering::VisitNumberDiv(GateRef gate)
321 {
322 GateRef left = acc_.GetValueIn(gate, 0);
323 GateRef right = acc_.GetValueIn(gate, 1);
324 GateType gateType = acc_.GetGateType(gate);
325 PGOSampleType sampleType = acc_.GetTypedBinaryType(gate);
326 if (sampleType.IsNumber()) {
327 if (sampleType.IsInt()) {
328 gateType = GateType::IntType();
329 } else {
330 gateType = GateType::DoubleType();
331 }
332 }
333 GateRef result = Circuit::NullGate();
334 if (gateType.IsIntType()) {
335 result = builder_.Int32DivWithCheck(left, right);
336 acc_.SetMachineType(gate, MachineType::I32);
337 } else {
338 result = builder_.BinaryArithmetic(circuit_->Fdiv(),
339 MachineType::F64, left, right, GateType::NJSValue());
340 acc_.SetMachineType(gate, MachineType::F64);
341 }
342 acc_.SetGateType(gate, GateType::NJSValue());
343 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
344 }
345
346 template<TypedBinOp Op>
VisitNumberMod(GateRef gate)347 void NumberSpeculativeLowering::VisitNumberMod(GateRef gate)
348 {
349 GateRef left = acc_.GetValueIn(gate, 0);
350 GateRef right = acc_.GetValueIn(gate, 1);
351 GateType gateType = acc_.GetGateType(gate);
352 PGOSampleType sampleType = acc_.GetTypedBinaryType(gate);
353 if (sampleType.IsNumber()) {
354 if (sampleType.IsInt()) {
355 gateType = GateType::IntType();
356 } else {
357 gateType = GateType::DoubleType();
358 }
359 }
360 GateRef result = Circuit::NullGate();
361 if (gateType.IsIntType()) {
362 builder_.Int32CheckRightIsZero(right);
363 result = CalculateInts<Op>(left, right);
364 UpdateRange(result, GetRange(gate));
365 acc_.SetMachineType(gate, MachineType::I32);
366 } else {
367 GateRef glue = acc_.GetGlueFromArgList();
368 result = builder_.CallNGCRuntime(glue, RTSTUB_ID(FloatMod),
369 Gate::InvalidGateRef, {left, right}, Circuit::NullGate());
370 acc_.SetMachineType(gate, MachineType::F64);
371 }
372 acc_.SetGateType(gate, GateType::NJSValue());
373 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
374 }
375
376 template<TypedUnOp Op>
VisitNumberMonocular(GateRef gate)377 void NumberSpeculativeLowering::VisitNumberMonocular(GateRef gate)
378 {
379 TypedUnaryAccessor accessor(acc_.TryGetValue(gate));
380 GateType type = accessor.GetTypeValue();
381 ASSERT(type.IsNumberType());
382 GateRef value = acc_.GetValueIn(gate, 0);
383 GateRef result = Circuit::NullGate();
384 if (type.IsIntType()) {
385 if (Op == TypedUnOp::TYPED_NEG) {
386 builder_.ValueCheckNegOverflow(value);
387 }
388 result = MonocularInt<Op>(value);
389 UpdateRange(result, GetRange(gate));
390 acc_.SetMachineType(gate, MachineType::I32);
391 } else {
392 result = MonocularDouble<Op>(value);
393 acc_.SetMachineType(gate, MachineType::F64);
394 }
395 acc_.SetGateType(gate, GateType::NJSValue());
396 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
397 }
398
VisitNumberNot(GateRef gate)399 void NumberSpeculativeLowering::VisitNumberNot(GateRef gate)
400 {
401 ASSERT(TypedUnaryAccessor(acc_.TryGetValue(gate)).GetTypeValue().IsNumberType());
402 GateRef value = acc_.GetValueIn(gate, 0);
403 GateRef result = builder_.Int32Not(value);
404 UpdateRange(result, GetRange(gate));
405 acc_.SetMachineType(gate, MachineType::I32);
406 acc_.SetGateType(gate, GateType::NJSValue());
407 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
408 }
409
VisitIsTrueOrFalse(GateRef gate,bool flag)410 void NumberSpeculativeLowering::VisitIsTrueOrFalse(GateRef gate, bool flag)
411 {
412 GateRef value = acc_.GetValueIn(gate, 0);
413 GateRef result = Circuit::NullGate();
414 if (!flag) {
415 result = builder_.BoolNot(value);
416 } else {
417 result = value;
418 }
419 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
420 }
421
VisitBooleanJump(GateRef gate)422 void NumberSpeculativeLowering::VisitBooleanJump(GateRef gate)
423 {
424 TypedJumpOp jumpOp = acc_.GetTypedJumpAccessor(gate).GetTypedJumpOp();
425 ASSERT((jumpOp == TypedJumpOp::TYPED_JEQZ) || (jumpOp == TypedJumpOp::TYPED_JNEZ));
426 GateRef condition = acc_.GetValueIn(gate, 0);
427 if (jumpOp == TypedJumpOp::TYPED_JEQZ) {
428 condition = builder_.BoolNot(condition);
429 }
430 GateRef ifBranch = builder_.Branch(acc_.GetState(gate), condition);
431 acc_.ReplaceGate(gate, ifBranch, acc_.GetDep(gate), Circuit::NullGate());
432 }
433
VisitUndefinedStrictEq(GateRef gate)434 void NumberSpeculativeLowering::VisitUndefinedStrictEq(GateRef gate)
435 {
436 GateRef left = acc_.GetValueIn(gate, 0);
437 GateRef right = acc_.GetValueIn(gate, 1);
438 GateRef result = builder_.Equal(left, right);
439 acc_.SetMachineType(gate, MachineType::I1);
440 acc_.SetGateType(gate, GateType::NJSValue());
441 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
442 }
443
VisitCallBuiltins(GateRef gate)444 void NumberSpeculativeLowering::VisitCallBuiltins(GateRef gate)
445 {
446 auto valuesIn = acc_.GetNumValueIn(gate);
447 auto idGate = acc_.GetValueIn(gate, valuesIn - 1);
448 auto id = static_cast<BuiltinsStubCSigns::ID>(acc_.GetConstantValue(idGate));
449 if (id != BUILTINS_STUB_ID(SQRT)) {
450 return;
451 }
452
453 BuiltinLowering lowering(circuit_);
454 lowering.LowerTypedSqrt(gate);
455 }
456
VisitConstant(GateRef gate)457 void NumberSpeculativeLowering::VisitConstant(GateRef gate)
458 {
459 TypeInfo output = GetOutputType(gate);
460 switch (output) {
461 case TypeInfo::INT32: {
462 int value = acc_.GetInt32FromConstant(gate);
463 GateRef constGate = GetConstInt32(value);
464 acc_.UpdateAllUses(gate, constGate);
465 break;
466 }
467 case TypeInfo::FLOAT64: {
468 double value = acc_.GetFloat64FromConstant(gate);
469 acc_.UpdateAllUses(gate, builder_.Double(value));
470 break;
471 }
472 default:
473 break;
474 }
475 }
476
VisitPhi(GateRef gate)477 void NumberSpeculativeLowering::VisitPhi(GateRef gate)
478 {
479 TypeInfo output = GetOutputType(gate);
480 switch (output) {
481 case TypeInfo::INT1: {
482 acc_.SetGateType(gate, GateType::NJSValue());
483 acc_.SetMachineType(gate, MachineType::I1);
484 break;
485 }
486 case TypeInfo::INT32: {
487 acc_.SetGateType(gate, GateType::NJSValue());
488 acc_.SetMachineType(gate, MachineType::I32);
489 break;
490 }
491 case TypeInfo::FLOAT64: {
492 acc_.SetGateType(gate, GateType::NJSValue());
493 acc_.SetMachineType(gate, MachineType::F64);
494 break;
495 }
496 default:
497 break;
498 }
499 }
500
VisitIndexCheck(GateRef gate)501 void NumberSpeculativeLowering::VisitIndexCheck(GateRef gate)
502 {
503 acc_.SetGateType(gate, GateType::NJSValue());
504 acc_.SetMachineType(gate, MachineType::I32);
505 }
506
VisitLoadArrayLength(GateRef gate)507 void NumberSpeculativeLowering::VisitLoadArrayLength(GateRef gate)
508 {
509 acc_.SetGateType(gate, GateType::NJSValue());
510 acc_.SetMachineType(gate, MachineType::I32);
511 }
512
VisitLoadElement(GateRef gate)513 void NumberSpeculativeLowering::VisitLoadElement(GateRef gate)
514 {
515 auto op = acc_.GetTypedLoadOp(gate);
516 switch (op) {
517 case TypedLoadOp::INT8ARRAY_LOAD_ELEMENT:
518 case TypedLoadOp::UINT8ARRAY_LOAD_ELEMENT:
519 case TypedLoadOp::UINT8CLAMPEDARRAY_LOAD_ELEMENT:
520 case TypedLoadOp::INT16ARRAY_LOAD_ELEMENT:
521 case TypedLoadOp::UINT16ARRAY_LOAD_ELEMENT:
522 case TypedLoadOp::INT32ARRAY_LOAD_ELEMENT:
523 acc_.SetMachineType(gate, MachineType::I32);
524 break;
525 case TypedLoadOp::FLOAT32ARRAY_LOAD_ELEMENT:
526 case TypedLoadOp::FLOAT64ARRAY_LOAD_ELEMENT:
527 acc_.SetMachineType(gate, MachineType::F64);
528 break;
529 default:
530 break;
531 }
532 acc_.SetGateType(gate, GateType::NJSValue());
533 }
534
VisitLoadProperty(GateRef gate)535 void NumberSpeculativeLowering::VisitLoadProperty(GateRef gate)
536 {
537 TypeInfo output = GetOutputType(gate);
538 if (output == TypeInfo::INT32 || output == TypeInfo::FLOAT64) {
539 Environment env(gate, circuit_, &builder_);
540 ASSERT(acc_.GetNumValueIn(gate) == 2); // 2: receiver, plr
541 GateRef receiver = acc_.GetValueIn(gate, 0);
542 GateRef propertyLookupResult = acc_.GetValueIn(gate, 1);
543 PropertyLookupResult plr(acc_.TryGetValue(propertyLookupResult));
544 ASSERT(plr.IsLocal() || plr.IsFunction());
545
546 // Hole check?
547 GateRef result = Circuit::NullGate();
548 if (output == TypeInfo::FLOAT64) {
549 result = builder_.LoadConstOffset(VariableType::FLOAT64(), receiver, plr.GetOffset());
550 acc_.SetMachineType(gate, MachineType::F64);
551 } else {
552 result = builder_.LoadConstOffset(VariableType::INT32(), receiver, plr.GetOffset());
553 acc_.SetMachineType(gate, MachineType::I32);
554 }
555 acc_.SetGateType(gate, GateType::NJSValue());
556 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
557 }
558 }
559
VisitRangeGuard(GateRef gate)560 void NumberSpeculativeLowering::VisitRangeGuard(GateRef gate)
561 {
562 Environment env(gate, circuit_, &builder_);
563 GateRef inputLength = acc_.GetValueIn(gate, 0);
564 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), inputLength);
565 }
566
567 template<TypedBinOp Op>
CalculateInts(GateRef left,GateRef right)568 GateRef NumberSpeculativeLowering::CalculateInts(GateRef left, GateRef right)
569 {
570 GateRef res = Circuit::NullGate();
571 RangeInfo leftRange = GetRange(left);
572 RangeInfo rightRange = GetRange(right);
573 switch (Op) {
574 case TypedBinOp::TYPED_ADD: {
575 if (!leftRange.MaybeAddOverflowOrUnderflow(rightRange)) {
576 return builder_.Int32Add(left, right, GateType::NJSValue());
577 }
578 res = builder_.AddWithOverflow(left, right);
579 break;
580 }
581 case TypedBinOp::TYPED_SUB: {
582 if (!leftRange.MaybeSubOverflowOrUnderflow(rightRange)) {
583 return builder_.Int32Sub(left, right, GateType::NJSValue());
584 }
585 res = builder_.SubWithOverflow(left, right);
586 break;
587 }
588 case TypedBinOp::TYPED_MUL:
589 res = builder_.MulWithOverflow(left, right);
590 break;
591 case TypedBinOp::TYPED_MOD: {
592 return builder_.BinaryArithmetic(circuit_->Smod(),
593 MachineType::I32, left, right, GateType::NJSValue());
594 break;
595 }
596 default:
597 break;
598 }
599 // DeoptCheckForOverFlow
600 builder_.OverflowCheck(res);
601 return builder_.ExtractValue(MachineType::I32, res, GetConstInt32(0));
602 }
603
604 template<TypedBinOp Op>
CalculateDoubles(GateRef left,GateRef right)605 GateRef NumberSpeculativeLowering::CalculateDoubles(GateRef left, GateRef right)
606 {
607 GateRef res = Circuit::NullGate();
608 switch (Op) {
609 case TypedBinOp::TYPED_ADD:
610 res = builder_.DoubleAdd(left, right, GateType::NJSValue());
611 break;
612 case TypedBinOp::TYPED_SUB:
613 res = builder_.DoubleSub(left, right, GateType::NJSValue());
614 break;
615 case TypedBinOp::TYPED_MUL:
616 res = builder_.DoubleMul(left, right, GateType::NJSValue());
617 break;
618 default:
619 break;
620 }
621 return res;
622 }
623
624 template<TypedBinOp Op>
CompareInts(GateRef left,GateRef right)625 GateRef NumberSpeculativeLowering::CompareInts(GateRef left, GateRef right)
626 {
627 GateRef condition = Circuit::NullGate();
628 switch (Op) {
629 case TypedBinOp::TYPED_LESS:
630 condition = builder_.Int32LessThan(left, right);
631 break;
632 case TypedBinOp::TYPED_LESSEQ:
633 condition = builder_.Int32LessThanOrEqual(left, right);
634 break;
635 case TypedBinOp::TYPED_GREATER:
636 condition = builder_.Int32GreaterThan(left, right);
637 break;
638 case TypedBinOp::TYPED_GREATEREQ:
639 condition = builder_.Int32GreaterThanOrEqual(left, right);
640 break;
641 case TypedBinOp::TYPED_EQ:
642 case TypedBinOp::TYPED_STRICTEQ:
643 condition = builder_.Int32Equal(left, right);
644 break;
645 case TypedBinOp::TYPED_NOTEQ:
646 condition = builder_.Int32NotEqual(left, right);
647 break;
648 default:
649 break;
650 }
651 return condition;
652 }
653
654 template<TypedBinOp Op>
CompareDoubles(GateRef left,GateRef right)655 GateRef NumberSpeculativeLowering::CompareDoubles(GateRef left, GateRef right)
656 {
657 GateRef condition = Circuit::NullGate();
658 switch (Op) {
659 case TypedBinOp::TYPED_LESS:
660 condition = builder_.DoubleLessThan(left, right);
661 break;
662 case TypedBinOp::TYPED_LESSEQ:
663 condition = builder_.DoubleLessThanOrEqual(left, right);
664 break;
665 case TypedBinOp::TYPED_GREATER:
666 condition = builder_.DoubleGreaterThan(left, right);
667 break;
668 case TypedBinOp::TYPED_GREATEREQ:
669 condition = builder_.DoubleGreaterThanOrEqual(left, right);
670 break;
671 case TypedBinOp::TYPED_EQ:
672 condition = builder_.DoubleEqual(left, right);
673 break;
674 case TypedBinOp::TYPED_NOTEQ:
675 condition = builder_.DoubleNotEqual(left, right);
676 break;
677 case TypedBinOp::TYPED_STRICTEQ: {
678 GateRef leftNotNan = builder_.BoolNot(builder_.DoubleIsNAN(left));
679 GateRef rightNotNan = builder_.BoolNot(builder_.DoubleIsNAN(right));
680 GateRef doubleEqual = builder_.DoubleEqual(left, right);
681 condition = builder_.BoolAnd(builder_.BoolAnd(leftNotNan, rightNotNan), doubleEqual);
682 break;
683 }
684 default:
685 break;
686 }
687 return condition;
688 }
689
690 template<TypedBinOp Op>
ShiftInts(GateRef left,GateRef right)691 GateRef NumberSpeculativeLowering::ShiftInts(GateRef left, GateRef right)
692 {
693 GateRef value = Circuit::NullGate();
694 GateRef bitmask = GetConstInt32(0x1f); // 0x1f: bit mask of shift value
695 GateRef shift = builder_.Int32And(right, bitmask, GateType::NJSValue());
696 switch (Op) {
697 case TypedBinOp::TYPED_SHL: {
698 value = builder_.Int32LSL(left, shift, GateType::NJSValue());
699 break;
700 }
701 case TypedBinOp::TYPED_SHR: {
702 value = builder_.Int32LSR(left, shift, GateType::NJSValue());
703 RangeInfo leftRange = GetRange(left);
704 RangeInfo rightRange = GetRange(right);
705 if (!leftRange.MaybeShrOverflow(rightRange)) {
706 return value;
707 }
708 builder_.Int32UnsignedUpperBoundCheck(value, builder_.Int32(INT32_MAX));
709 break;
710 }
711 case TypedBinOp::TYPED_ASHR: {
712 value = builder_.Int32ASR(left, shift, GateType::NJSValue());
713 break;
714 }
715 default:
716 LOG_ECMA(FATAL) << "this branch is unreachable";
717 UNREACHABLE();
718 break;
719 }
720 return value;
721 }
722
723 template<TypedBinOp Op>
LogicalInts(GateRef left,GateRef right)724 GateRef NumberSpeculativeLowering::LogicalInts(GateRef left, GateRef right)
725 {
726 GateRef value = Circuit::NullGate();
727 switch (Op) {
728 case TypedBinOp::TYPED_AND: {
729 value = builder_.Int32And(left, right, GateType::NJSValue());
730 break;
731 }
732 case TypedBinOp::TYPED_OR: {
733 value = builder_.Int32Or(left, right, GateType::NJSValue());
734 break;
735 }
736 case TypedBinOp::TYPED_XOR: {
737 value = builder_.Int32Xor(left, right, GateType::NJSValue());
738 break;
739 }
740 default:
741 LOG_ECMA(FATAL) << "this branch is unreachable";
742 UNREACHABLE();
743 break;
744 }
745 return value;
746 }
747
748 template<TypedUnOp Op>
MonocularInt(GateRef value)749 GateRef NumberSpeculativeLowering::MonocularInt(GateRef value)
750 {
751 GateRef res = Circuit::NullGate();
752 switch (Op) {
753 case TypedUnOp::TYPED_INC:
754 res = CalculateInts<TypedBinOp::TYPED_ADD>(value, GetConstInt32(1));
755 break;
756 case TypedUnOp::TYPED_DEC:
757 res = CalculateInts<TypedBinOp::TYPED_SUB>(value, GetConstInt32(1));
758 break;
759 case TypedUnOp::TYPED_NEG:
760 res = builder_.Int32Sub(GetConstInt32(0), value, GateType::NJSValue());
761 break;
762 default:
763 break;
764 }
765 return res;
766 }
767
768 template<TypedUnOp Op>
MonocularDouble(GateRef value)769 GateRef NumberSpeculativeLowering::MonocularDouble(GateRef value)
770 {
771 GateRef res = Circuit::NullGate();
772 switch (Op) {
773 case TypedUnOp::TYPED_INC:
774 res = builder_.DoubleAdd(value, builder_.Double(1));
775 break;
776 case TypedUnOp::TYPED_DEC:
777 res = builder_.DoubleSub(value, builder_.Double(1));
778 break;
779 case TypedUnOp::TYPED_NEG:
780 res = builder_.DoubleMul(builder_.Double(-1), value);
781 break;
782 default:
783 break;
784 }
785 return res;
786 }
787
UpdateRange(GateRef gate,const RangeInfo & range)788 void NumberSpeculativeLowering::UpdateRange(GateRef gate, const RangeInfo& range)
789 {
790 auto id = acc_.GetId(gate);
791 if (id >= rangeInfos_.size()) {
792 rangeInfos_.resize(id + 1, RangeInfo::ANY());
793 }
794 rangeInfos_[id] = range;
795 }
796
GetRange(GateRef gate) const797 RangeInfo NumberSpeculativeLowering::GetRange(GateRef gate) const
798 {
799 ASSERT(!rangeInfos_[acc_.GetId(gate)].IsNone());
800 return rangeInfos_[acc_.GetId(gate)];
801 }
802
GetConstInt32(int32_t v)803 GateRef NumberSpeculativeLowering::GetConstInt32(int32_t v)
804 {
805 auto val = builder_.Int32(v);
806 UpdateRange(val, RangeInfo(v, v));
807 return val;
808 }
809 } // namespace panda::ecmascript
810