• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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