• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
16 #include "ecmascript/compiler/number_speculative_retype.h"
17 #include "ecmascript/compiler/circuit_builder-inl.h"
18 #include "ecmascript/compiler/share_gate_meta_data.h"
19 #include "ecmascript/compiler/number_gate_info.h"
20 #include "ecmascript/compiler/type.h"
21 #include <cstdint>
22 
23 namespace panda::ecmascript::kungfu {
SetOutputType(GateRef gate,GateType gateType)24 GateRef NumberSpeculativeRetype::SetOutputType(GateRef gate, GateType gateType)
25 {
26     TypeInfo type = GetOutputTypeInfo(gate);
27     TypeInfo old = type;
28     if (gateType.IsIntType()) {
29         type = TypeInfo::INT32;
30     } else if (gateType.IsDoubleType()) {
31         type = TypeInfo::FLOAT64;
32     } else if (gateType.IsBooleanType()) {
33         type = TypeInfo::INT1;
34     } else {
35         type = TypeInfo::TAGGED;
36     }
37     SetOutputTypeInfo(gate, type);
38     return old == type ? Circuit::NullGate() : gate;
39 }
40 
SetOutputType(GateRef gate,PGOSampleType pgoType)41 GateRef NumberSpeculativeRetype::SetOutputType(GateRef gate, PGOSampleType pgoType)
42 {
43     TypeInfo type = GetOutputTypeInfo(gate);
44     TypeInfo old = type;
45     if (pgoType.IsInt()) {
46         type = TypeInfo::INT32;
47     } else {
48         type = TypeInfo::FLOAT64;
49     }
50     SetOutputTypeInfo(gate, type);
51     return old == type ? Circuit::NullGate() : gate;
52 }
53 
SetOutputType(GateRef gate,Representation rep)54 GateRef NumberSpeculativeRetype::SetOutputType(GateRef gate, Representation rep)
55 {
56     TypeInfo type = GetOutputTypeInfo(gate);
57     TypeInfo old = type;
58     if (rep == Representation::INT) {
59         type = TypeInfo::INT32;
60     } else if (rep == Representation::DOUBLE) {
61         type = TypeInfo::FLOAT64;
62     } else {
63         type = TypeInfo::TAGGED;
64     }
65     SetOutputTypeInfo(gate, type);
66     return old == type ? Circuit::NullGate() : gate;
67 }
68 
SetOutputType(GateRef gate,TypeInfo type)69 GateRef NumberSpeculativeRetype::SetOutputType(GateRef gate, TypeInfo type)
70 {
71     TypeInfo old = GetOutputTypeInfo(gate);
72     SetOutputTypeInfo(gate, type);
73     return old == type ? Circuit::NullGate() : gate;
74 }
setState(NumberSpeculativeRetype::State state)75 void NumberSpeculativeRetype::setState(NumberSpeculativeRetype::State state)
76 {
77     state_ = state;
78 }
79 
VisitGate(GateRef gate)80 GateRef NumberSpeculativeRetype::VisitGate(GateRef gate)
81 {
82     OpCode op = acc_.GetOpCode(gate);
83     switch (op) {
84         case OpCode::TYPED_BINARY_OP:
85             return VisitTypedBinaryOp(gate);
86         case OpCode::TYPED_UNARY_OP:
87             return VisitTypedUnaryOp(gate);
88         case OpCode::TYPED_CONDITION_JUMP:
89             return VisitTypedConditionJump(gate);
90         case OpCode::RANGE_CHECK_PREDICATE:
91             return VisitRangeCheckPredicate(gate);
92         case OpCode::INDEX_CHECK:
93             return VisitIndexCheck(gate);
94         case OpCode::LOAD_ARRAY_LENGTH:
95         case OpCode::LOAD_TYPED_ARRAY_LENGTH:
96             return VisitLoadArrayLength(gate);
97         case OpCode::LOAD_STRING_LENGTH:
98             return VisitLoadStringLength(gate);
99         case OpCode::LOAD_ELEMENT:
100             return VisitLoadElement(gate);
101         case OpCode::STORE_ELEMENT:
102             return VisitStoreElement(gate);
103         case OpCode::STORE_PROPERTY:
104             return VisitStoreProperty(gate);
105         case OpCode::LOAD_PROPERTY:
106             return VisitLoadProperty(gate);
107         case OpCode::MONO_LOAD_PROPERTY_ON_PROTO:
108             return VisitMonoLoadPropertyOnProto(gate);
109         case OpCode::MONO_CALL_GETTER_ON_PROTO:
110             return VisitMonoCallGetterOnProto(gate);
111         case OpCode::MONO_STORE_PROPERTY:
112         case OpCode::MONO_STORE_PROPERTY_LOOK_UP_PROTO:
113             return VisitMonoStoreProperty(gate);
114         case OpCode::VALUE_SELECTOR:
115             return VisitPhi(gate);
116         case OpCode::CONSTANT:
117             return VisitConstant(gate);
118         case OpCode::TYPED_CALL_BUILTIN:
119             return VisitCallBuiltins(gate);
120         case OpCode::TYPE_CONVERT:
121             return VisitTypeConvert(gate);
122         case OpCode::FRAME_STATE:
123             return VisitFrameState(gate);
124         case OpCode::CALL_GETTER:
125         case OpCode::CALL_SETTER:
126         case OpCode::CONSTRUCT:
127         case OpCode::TYPEDCALL:
128         case OpCode::TYPEDFASTCALL:
129         case OpCode::OBJECT_TYPE_CHECK:
130             return VisitWithConstantValue(gate, PROPERTY_LOOKUP_RESULT_INDEX);
131         case OpCode::LOOP_EXIT_VALUE:
132         case OpCode::RANGE_GUARD:
133             return VisitIntermediateValue(gate);
134         case OpCode::JS_BYTECODE:
135         case OpCode::PRIMITIVE_TYPE_CHECK:
136         case OpCode::STABLE_ARRAY_CHECK:
137         case OpCode::TYPED_ARRAY_CHECK:
138         case OpCode::TYPED_CALLTARGETCHECK_OP:
139         case OpCode::TYPED_CALL_CHECK:
140         case OpCode::HEAP_ALLOC:
141         case OpCode::TYPED_NEW_ALLOCATE_THIS:
142         case OpCode::TYPED_SUPER_ALLOCATE_THIS:
143         case OpCode::GET_SUPER_CONSTRUCTOR:
144         case OpCode::ARG:
145         case OpCode::RETURN:
146         case OpCode::FRAME_ARGS:
147         case OpCode::SAVE_REGISTER:
148         case OpCode::RESTORE_REGISTER:
149         case OpCode::LOAD_CONST_OFFSET:
150         case OpCode::STORE_CONST_OFFSET:
151         case OpCode::LEX_VAR_IS_HOLE_CHECK:
152         case OpCode::TYPE_OF_CHECK:
153         case OpCode::ARRAY_CONSTRUCTOR:
154         case OpCode::OBJECT_CONSTRUCTOR:
155         case OpCode::LD_LOCAL_MODULE_VAR:
156         case OpCode::STORE_MODULE_VAR:
157         case OpCode::STRING_FROM_SINGLE_CHAR_CODE:
158         case OpCode::ORDINARY_HAS_INSTANCE:
159         case OpCode::ECMA_STRING_CHECK:
160             return VisitOthers(gate);
161         default:
162             return Circuit::NullGate();
163     }
164 }
165 
VisitTypedBinaryOp(GateRef gate)166 GateRef NumberSpeculativeRetype::VisitTypedBinaryOp(GateRef gate)
167 {
168     if (acc_.HasStringType(gate)) {
169         return VisitStringBinaryOp(gate);
170     }
171 
172     if (acc_.GetTypedBinaryOp(gate) != TypedBinOp::TYPED_STRICTEQ &&
173         acc_.GetTypedBinaryOp(gate) != TypedBinOp::TYPED_STRICTNOTEQ &&
174         acc_.GetTypedBinaryOp(gate) != TypedBinOp::TYPED_EQ &&
175         acc_.GetTypedBinaryOp(gate) != TypedBinOp::TYPED_NOTEQ) {
176         if (acc_.HasPrimitiveNumberType(gate)) {
177             return VisitNumberBinaryOp(gate);
178         }
179     }
180 
181     return VisitEqualCompareOrNotEqualCompare(gate);
182 }
183 
VisitEqualCompareOrNotEqualCompare(GateRef gate)184 GateRef NumberSpeculativeRetype::VisitEqualCompareOrNotEqualCompare(GateRef gate)
185 {
186     if (acc_.HasNumberType(gate)) {
187         return VisitNumberBinaryOp(gate);
188     } else {
189         return VisitUndefinedEqualCompareOrUndefinedNotEqualCompare(gate);
190     }
191 }
192 
VisitUndefinedEqualCompareOrUndefinedNotEqualCompare(GateRef gate)193 GateRef NumberSpeculativeRetype::VisitUndefinedEqualCompareOrUndefinedNotEqualCompare(GateRef gate)
194 {
195     ASSERT(acc_.GetTypedBinaryOp(gate) == TypedBinOp::TYPED_STRICTEQ ||
196            acc_.GetTypedBinaryOp(gate) == TypedBinOp::TYPED_STRICTNOTEQ ||
197            acc_.GetTypedBinaryOp(gate) == TypedBinOp::TYPED_EQ ||
198            acc_.GetTypedBinaryOp(gate) == TypedBinOp::TYPED_NOTEQ);
199     GateRef left = acc_.GetValueIn(gate, 0);
200     GateRef right = acc_.GetValueIn(gate, 1);
201     ASSERT((acc_.IsUndefinedOrNull(left)) || (acc_.IsUndefinedOrNull(right)));
202     if (IsRetype()) {
203         return SetOutputType(gate, GateType::BooleanType());
204     }
205     if (IsConvert()) {
206         acc_.ReplaceValueIn(gate, ConvertToTagged(left), 0);
207         acc_.ReplaceValueIn(gate, ConvertToTagged(right), 1);
208     }
209     return Circuit::NullGate();
210 }
211 
VisitConstant(GateRef gate)212 GateRef NumberSpeculativeRetype::VisitConstant(GateRef gate)
213 {
214     if (IsRetype()) {
215         if (acc_.GetGateType(gate).IsNJSValueType()) {
216             auto machineType = acc_.GetMachineType(gate);
217             switch (machineType) {
218                 case MachineType::I1:
219                     SetOutputTypeInfo(gate, TypeInfo::INT1);
220                     break;
221                 case MachineType::I32:
222                     SetOutputTypeInfo(gate, TypeInfo::INT32);
223                     break;
224                 case MachineType::F64:
225                     SetOutputTypeInfo(gate, TypeInfo::FLOAT64);
226                     break;
227                 default:
228                     SetOutputTypeInfo(gate, TypeInfo::NONE);
229                     break;
230             }
231         } else {
232             return SetOutputType(gate, GateType::AnyType());
233         }
234     }
235     return Circuit::NullGate();
236 }
237 
VisitIntermediateValue(GateRef gate)238 GateRef NumberSpeculativeRetype::VisitIntermediateValue(GateRef gate)
239 {
240     GateRef value = acc_.GetValueIn(gate, 0);
241     TypeInfo valueInfo = GetOutputTypeInfo(value);
242     if (IsRetype()) {
243         TypeInfo oldType = GetOutputTypeInfo(gate);
244         SetOutputTypeInfo(gate, valueInfo);
245         return oldType == valueInfo ? Circuit::NullGate() : gate;
246     }
247     return Circuit::NullGate();
248 }
249 
VisitStringBinaryOp(GateRef gate)250 GateRef NumberSpeculativeRetype::VisitStringBinaryOp(GateRef gate)
251 {
252     TypedBinOp op = acc_.GetTypedBinaryOp(gate);
253     switch (op) {
254         case TypedBinOp::TYPED_EQ:
255             return VisitStringCompare(gate);
256         case TypedBinOp::TYPED_ADD:
257             return VisitStringAdd(gate);
258         default:
259             return Circuit::NullGate();
260     }
261 }
262 
VisitStringCompare(GateRef gate)263 GateRef NumberSpeculativeRetype::VisitStringCompare(GateRef gate)
264 {
265     if (IsRetype()) {
266         return SetOutputType(gate, GateType::BooleanType());
267     }
268 
269     Environment env(gate, circuit_, &builder_);
270     GateRef left = acc_.GetValueIn(gate, 0);
271     GateRef right = acc_.GetValueIn(gate, 1);
272     TypeInfo leftInfo = GetOutputTypeInfo(left);
273     TypeInfo rightInfo = GetOutputTypeInfo(right);
274     if (leftInfo == TypeInfo::CHAR && rightInfo == TypeInfo::CHAR) {
275         return Circuit::NullGate();
276     }
277     if (leftInfo == TypeInfo::CHAR) {
278         GateRef rep = builder_.ConvertCharToEcmaString(left);
279         acc_.ReplaceValueIn(gate, rep, 0);
280     }
281     if (rightInfo == TypeInfo::CHAR) {
282         GateRef rep =  builder_.ConvertCharToEcmaString(right);
283         acc_.ReplaceValueIn(gate, rep, 1);
284     }
285     return Circuit::NullGate();
286 }
287 
VisitStringAdd(GateRef gate)288 GateRef NumberSpeculativeRetype::VisitStringAdd(GateRef gate)
289 {
290     if (IsRetype()) {
291         return SetOutputType(gate, GateType::StringType());
292     }
293     if (IsConvert()) {
294         Environment env(gate, circuit_, &builder_);
295         size_t valueNum = acc_.GetNumValueIn(gate);
296         for (size_t i = 0; i < valueNum; ++i) {
297             GateRef input = acc_.GetValueIn(gate, i);
298             TypeInfo inputInfo = GetOutputTypeInfo(input);
299             if (inputInfo == TypeInfo::CHAR) {
300                 GateRef glue = acc_.GetGlueFromArgList();
301                 input = builder_.CallStub(glue, gate, CommonStubCSigns::CreateStringBySingleCharCode, { glue, input });
302             }
303             acc_.ReplaceValueIn(gate, input, i);
304         }
305     }
306     return Circuit::NullGate();
307 }
308 
GetOuputForPhi(GateRef gate,bool ignoreConstant)309 TypeInfo NumberSpeculativeRetype::GetOuputForPhi(GateRef gate, bool ignoreConstant)
310 {
311     size_t valueNum = acc_.GetNumValueIn(gate);
312     bool hasConstantInput = false;
313     TypeInfo tempType = TypeInfo::NONE;
314     for (size_t i = 0; i < valueNum; ++i) {
315         GateRef input = acc_.GetValueIn(gate, i);
316         TypeInfo inputInfo = GetOutputTypeInfo(input);
317         if (inputInfo == TypeInfo::NONE) {
318             continue;
319         }
320         if (ignoreConstant && acc_.IsConstantNumber(input)) {
321             hasConstantInput = true;
322             continue;
323         }
324         // use less general input as phi output
325         if (tempType == TypeInfo::NONE) {
326             tempType = inputInfo;
327         } else if (tempType != inputInfo) {
328             tempType = TypeInfo::TAGGED;
329             break;
330         }
331     }
332 
333     if (hasConstantInput && ignoreConstant && tempType == TypeInfo::NONE) {
334         return GetOuputForPhi(gate, false);
335     }
336     return tempType;
337 }
338 
VisitPhi(GateRef gate)339 GateRef NumberSpeculativeRetype::VisitPhi(GateRef gate)
340 {
341     if (IsRetype()) {
342         auto tempType = GetOuputForPhi(gate, true);
343         TypeInfo typeInfo = GetOutputTypeInfo(gate);
344         if (typeInfo != tempType) {
345             SetOutputTypeInfo(gate, tempType);
346             return gate;
347         }
348         return Circuit::NullGate();
349     }
350     ASSERT(IsConvert());
351     size_t valueNum = acc_.GetNumValueIn(gate);
352     auto merge = acc_.GetState(gate);
353     auto dependSelector = acc_.GetDependSelectorFromMerge(merge);
354     TypeInfo output = GetOutputTypeInfo(gate);
355     for (size_t i = 0; i < valueNum; ++i) {
356         GateRef input = acc_.GetValueIn(gate, i);
357         if (output == TypeInfo::TAGGED || output == TypeInfo::NONE) {
358             input = ConvertToTagged(input);
359         } else {
360             auto state = acc_.GetState(merge, i);
361             auto depend = acc_.GetDep(dependSelector, i);
362             Environment env(state, depend, {}, circuit_, &builder_);
363             input = ConvertTaggedToNJSValue(input, output);
364             acc_.ReplaceStateIn(merge, builder_.GetState(), i);
365             acc_.ReplaceDependIn(dependSelector, builder_.GetDepend(), i);
366         }
367         acc_.ReplaceValueIn(gate, input, i);
368     }
369     return Circuit::NullGate();
370 }
371 
ConvertTaggedToNJSValue(GateRef gate,TypeInfo output)372 GateRef NumberSpeculativeRetype::ConvertTaggedToNJSValue(GateRef gate, TypeInfo output)
373 {
374     TypeInfo curOutput = GetOutputTypeInfo(gate);
375     if (curOutput != TypeInfo::TAGGED) {
376         return gate;
377     }
378     switch (output) {
379         case TypeInfo::INT1:
380             return CheckAndConvertToBool(gate, GateType::BooleanType());
381         case TypeInfo::INT32:
382             return CheckAndConvertToInt32(gate, GateType::NumberType());
383         case TypeInfo::FLOAT64:
384             return CheckAndConvertToFloat64(gate, GateType::NumberType());
385         default:
386             LOG_COMPILER(FATAL) << "this branch is unreachable";
387             UNREACHABLE();
388             return Circuit::NullGate();
389     }
390 }
391 
VisitNumberBinaryOp(GateRef gate)392 GateRef NumberSpeculativeRetype::VisitNumberBinaryOp(GateRef gate)
393 {
394     TypedBinOp op = acc_.GetTypedBinaryOp(gate);
395     switch (op) {
396         case TypedBinOp::TYPED_ADD:
397         case TypedBinOp::TYPED_SUB:
398         case TypedBinOp::TYPED_MUL:
399         case TypedBinOp::TYPED_DIV: {
400             return VisitNumberCalculate(gate);
401         }
402         case TypedBinOp::TYPED_LESS:
403         case TypedBinOp::TYPED_LESSEQ:
404         case TypedBinOp::TYPED_GREATER:
405         case TypedBinOp::TYPED_GREATEREQ:
406         case TypedBinOp::TYPED_EQ:
407         case TypedBinOp::TYPED_NOTEQ:
408         case TypedBinOp::TYPED_STRICTEQ:
409         case TypedBinOp::TYPED_STRICTNOTEQ: {
410             return VisitNumberCompare(gate);
411         }
412         case TypedBinOp::TYPED_SHL:
413         case TypedBinOp::TYPED_SHR:
414         case TypedBinOp::TYPED_ASHR:
415         case TypedBinOp::TYPED_AND:
416         case TypedBinOp::TYPED_OR:
417         case TypedBinOp::TYPED_XOR: {
418             return VisitNumberShiftAndLogical(gate);
419         }
420         case TypedBinOp::TYPED_MOD: {
421             return VisitNumberMod(gate);
422         }
423         default:
424             return VisitNumberRelated(gate);
425     }
426 }
427 
VisitTypedUnaryOp(GateRef gate)428 GateRef NumberSpeculativeRetype::VisitTypedUnaryOp(GateRef gate)
429 {
430     Environment env(gate, circuit_, &builder_);
431     TypedUnOp Op = acc_.GetTypedUnAccessor(gate).GetTypedUnOp();
432     switch (Op) {
433         case TypedUnOp::TYPED_INC:
434         case TypedUnOp::TYPED_DEC:
435         case TypedUnOp::TYPED_NEG:
436             return VisitNumberMonocular(gate);
437         case TypedUnOp::TYPED_NOT:
438             return VisitNumberNot(gate);
439         case TypedUnOp::TYPED_ISFALSE:
440         case TypedUnOp::TYPED_ISTRUE:
441             return VisitIsTrueOrFalse(gate);
442         default:
443             return VisitNumberRelated(gate);
444     }
445 }
446 
VisitTypedConditionJump(GateRef gate)447 GateRef NumberSpeculativeRetype::VisitTypedConditionJump(GateRef gate)
448 {
449     Environment env(gate, circuit_, &builder_);
450     TypedUnaryAccessor accessor(acc_.TryGetValue(gate));
451     auto type = accessor.GetTypeValue();
452     if (type.IsBooleanType()) {
453         return VisitBooleanJump(gate);
454     } else {
455         UNREACHABLE();
456         return Circuit::NullGate();
457     }
458 }
459 
VisitNumberCalculate(GateRef gate)460 GateRef NumberSpeculativeRetype::VisitNumberCalculate(GateRef gate)
461 {
462     if (IsRetype()) {
463         const PGOSampleType *sampleType = acc_.GetTypedBinaryType(gate).GetPGOSampleType();
464         if (sampleType->IsNumber()) {
465             return SetOutputType(gate, *sampleType);
466         } else {
467             GateType gateType = acc_.GetGateType(gate);
468             GateType resType = gateType.IsIntType() ? GateType::IntType() : GateType::DoubleType();
469             return SetOutputType(gate, resType);
470         }
471     } else if (IsConvert()) {
472         Environment env(gate, circuit_, &builder_);
473         ConvertForBinaryOp(gate);
474     }
475     return Circuit::NullGate();
476 }
477 
VisitNumberCompare(GateRef gate)478 GateRef NumberSpeculativeRetype::VisitNumberCompare(GateRef gate)
479 {
480     if (IsRetype()) {
481         return SetOutputType(gate, GateType::BooleanType());
482     }
483     if (IsConvert()) {
484         Environment env(gate, circuit_, &builder_);
485         ConvertForCompareOp(gate);
486     }
487     return Circuit::NullGate();
488 }
489 
VisitNumberShiftAndLogical(GateRef gate)490 GateRef NumberSpeculativeRetype::VisitNumberShiftAndLogical(GateRef gate)
491 {
492     if (IsRetype()) {
493         return SetOutputType(gate, GateType::IntType());
494     }
495     if (IsConvert()) {
496         Environment env(gate, circuit_, &builder_);
497         GateType leftType = acc_.GetLeftType(gate);
498         GateType rightType = acc_.GetRightType(gate);
499         const PGOSampleType *sampleType = acc_.GetTypedBinaryType(gate).GetPGOSampleType();
500         if (sampleType->IsNumber()) {
501             if (sampleType->IsInt()) {
502                 leftType = GateType::IntType();
503                 rightType = GateType::IntType();
504             } else {
505                 leftType = GateType::NumberType();
506                 rightType = GateType::NumberType();
507             }
508         }
509         ConvertForShiftAndLogicalOperator(gate, leftType, rightType);
510     }
511     return Circuit::NullGate();
512 }
513 
VisitNumberMonocular(GateRef gate)514 GateRef NumberSpeculativeRetype::VisitNumberMonocular(GateRef gate)
515 {
516     TypedUnaryAccessor accessor(acc_.TryGetValue(gate));
517     GateType type = accessor.GetTypeValue();
518     ASSERT(type.IsPrimitiveNumberType());
519     if (type.IsIntType()) {
520         return VisitIntMonocular(gate);
521     } else {
522         return VisitDoubleMonocular(gate);
523     }
524 }
525 
VisitIntMonocular(GateRef gate)526 GateRef NumberSpeculativeRetype::VisitIntMonocular(GateRef gate)
527 {
528     if (IsRetype()) {
529         return SetOutputType(gate, GateType::IntType());
530     }
531 
532     if (IsConvert()) {
533         GateRef value = acc_.GetValueIn(gate, 0);
534         acc_.ReplaceValueIn(gate, CheckAndConvertToInt32(value, GateType::IntType()), 0);
535         acc_.ReplaceStateIn(gate, builder_.GetState());
536         acc_.ReplaceDependIn(gate, builder_.GetDepend());
537     }
538     return Circuit::NullGate();
539 }
540 
VisitDoubleMonocular(GateRef gate)541 GateRef NumberSpeculativeRetype::VisitDoubleMonocular(GateRef gate)
542 {
543     if (IsRetype()) {
544         return SetOutputType(gate, GateType::DoubleType());
545     }
546 
547     if (IsConvert()) {
548         TypedUnaryAccessor accessor(acc_.TryGetValue(gate));
549         GateRef value = acc_.GetValueIn(gate, 0);
550         acc_.ReplaceValueIn(gate, CheckAndConvertToFloat64(value, accessor.GetTypeValue()), 0);
551         acc_.ReplaceStateIn(gate, builder_.GetState());
552         acc_.ReplaceDependIn(gate, builder_.GetDepend());
553     }
554     return Circuit::NullGate();
555 }
556 
VisitIsTrueOrFalse(GateRef gate)557 GateRef NumberSpeculativeRetype::VisitIsTrueOrFalse(GateRef gate)
558 {
559     TypedUnaryAccessor accessor(acc_.TryGetValue(gate));
560     GateType valueType = accessor.GetTypeValue();
561     ASSERT(valueType.IsPrimitiveNumberType());
562     if (IsRetype()) {
563         return SetOutputType(gate, GateType::BooleanType());
564     }
565     if (IsConvert()) {
566         Environment env(gate, circuit_, &builder_);
567         GateRef value = acc_.GetValueIn(gate, 0);
568         auto input = CheckAndConvertToBool(value, valueType);
569         ResizeAndSetTypeInfo(input, TypeInfo::INT1);
570         acc_.ReplaceValueIn(gate, input, 0);
571         acc_.ReplaceStateIn(gate, builder_.GetState());
572         acc_.ReplaceDependIn(gate, builder_.GetDepend());
573     }
574     return Circuit::NullGate();
575 }
576 
VisitNumberNot(GateRef gate)577 GateRef NumberSpeculativeRetype::VisitNumberNot(GateRef gate)
578 {
579     TypedUnaryAccessor accessor(acc_.TryGetValue(gate));
580     GateType valueType = accessor.GetTypeValue();
581     ASSERT(valueType.IsPrimitiveNumberType());
582     if (IsRetype()) {
583         return SetOutputType(gate, GateType::IntType());
584     }
585     if (IsConvert()) {
586         Environment env(gate, circuit_, &builder_);
587         GateRef value = acc_.GetValueIn(gate, 0);
588         acc_.ReplaceValueIn(gate,
589             CheckAndConvertToInt32(value, valueType, ConvertSupport::ENABLE, OpType::SHIFT_AND_LOGICAL), 0);
590         acc_.ReplaceStateIn(gate, builder_.GetState());
591         acc_.ReplaceDependIn(gate, builder_.GetDepend());
592     }
593     return Circuit::NullGate();
594 }
595 
VisitBooleanJump(GateRef gate)596 GateRef NumberSpeculativeRetype::VisitBooleanJump(GateRef gate)
597 {
598     if (IsRetype()) {
599         return SetOutputType(gate, GateType::AnyType());
600     }
601     if (IsConvert()) {
602         Environment env(gate, circuit_, &builder_);
603         GateRef value = acc_.GetValueIn(gate, 0);
604         GateRef input = Circuit::NullGate();
605         if (GetOutputTypeInfo(value) == TypeInfo::TAGGED) {
606             // use TaggedIsTrue
607             input = builder_.ConvertTaggedBooleanToBool(value);
608         } else {
609             input = CheckAndConvertToBool(value, GateType::BooleanType());
610         }
611         ResizeAndSetTypeInfo(input, TypeInfo::INT1);
612         acc_.ReplaceValueIn(gate, input, 0);
613         acc_.ReplaceStateIn(gate, builder_.GetState());
614         acc_.ReplaceDependIn(gate, builder_.GetDepend());
615     }
616     return Circuit::NullGate();
617 }
618 
VisitNumberRelated(GateRef gate)619 GateRef NumberSpeculativeRetype::VisitNumberRelated(GateRef gate)
620 {
621     if (IsRetype()) {
622         return SetOutputType(gate, GateType::NumberType());
623     }
624     if (IsConvert()) {
625         Environment env(gate, circuit_, &builder_);
626         size_t valueNum = acc_.GetNumValueIn(gate);
627         for (size_t i = 0; i < valueNum; ++i) {
628             GateRef input = acc_.GetValueIn(gate, i);
629             GateType inputType = acc_.GetGateType(input);
630             if (inputType.IsNumberType() || inputType.IsBooleanType()) {
631                 acc_.ReplaceValueIn(gate, CheckAndConvertToTagged(input, inputType), i);
632             }
633         }
634         acc_.ReplaceStateIn(gate, builder_.GetState());
635         acc_.ReplaceDependIn(gate, builder_.GetDepend());
636     }
637     return Circuit::NullGate();
638 }
639 
VisitCallBuiltins(GateRef gate)640 GateRef NumberSpeculativeRetype::VisitCallBuiltins(GateRef gate)
641 {
642     auto valuesIn = acc_.GetNumValueIn(gate);
643     auto idGate = acc_.GetValueIn(gate, valuesIn - 1);
644     auto id = static_cast<BuiltinsStubCSigns::ID>(acc_.GetConstantValue(idGate));
645     if (id != BUILTINS_STUB_ID(SQRT)) {
646         return VisitOthers(gate);
647     }
648 
649     if (IsRetype()) {
650         // Sqrt output is double
651         return SetOutputType(gate, GateType::DoubleType());
652     }
653     if (IsConvert()) {
654         Environment env(gate, circuit_, &builder_);
655         acc_.ReplaceValueIn(gate, ConvertToTagged(idGate), valuesIn - 1);
656         for (size_t i = 0; i < valuesIn - 1; ++i) {
657             GateRef input = acc_.GetValueIn(gate, i);
658             acc_.ReplaceValueIn(gate, CheckAndConvertToFloat64(input, GateType::NumberType()), i);
659         }
660         acc_.ReplaceStateIn(gate, builder_.GetState());
661         acc_.ReplaceDependIn(gate, builder_.GetDepend());
662     }
663     return Circuit::NullGate();
664 }
665 
VisitFrameState(GateRef gate)666 GateRef NumberSpeculativeRetype::VisitFrameState(GateRef gate)
667 {
668     if (IsRetype()) {
669         return SetOutputType(gate, GateType::AnyType());
670     }
671     return Circuit::NullGate();
672 }
673 
VisitOthers(GateRef gate)674 GateRef NumberSpeculativeRetype::VisitOthers(GateRef gate)
675 {
676     if (IsRetype()) {
677         return SetOutputType(gate, GateType::AnyType());
678     }
679     if (IsConvert()) {
680         size_t valueNum = acc_.GetNumValueIn(gate);
681         for (size_t i = 0; i < valueNum; ++i) {
682             GateRef input = acc_.GetValueIn(gate, i);
683             acc_.ReplaceValueIn(gate, ConvertToTagged(input), i);
684         }
685     }
686     return Circuit::NullGate();
687 }
688 
VisitWithConstantValue(GateRef gate,size_t ignoreIndex)689 GateRef NumberSpeculativeRetype::VisitWithConstantValue(GateRef gate, size_t ignoreIndex)
690 {
691     if (IsRetype()) {
692         return SetOutputType(gate, GateType::AnyType());
693     }
694     if (IsConvert()) {
695         size_t valueNum = acc_.GetNumValueIn(gate);
696         for (size_t i = 0; i < valueNum; ++i) {
697             if (i == ignoreIndex) {
698                 continue;
699             }
700             GateRef input = acc_.GetValueIn(gate, i);
701             acc_.ReplaceValueIn(gate, ConvertToTagged(input), i);
702         }
703     }
704     return Circuit::NullGate();
705 }
706 
CheckAndConvertToBool(GateRef gate,GateType gateType)707 GateRef NumberSpeculativeRetype::CheckAndConvertToBool(GateRef gate, GateType gateType)
708 {
709     TypeInfo output = GetOutputTypeInfo(gate);
710     switch (output) {
711         case TypeInfo::INT1:
712             return gate;
713         case TypeInfo::INT32:
714             return builder_.ConvertInt32ToBool(gate);
715         case TypeInfo::UINT32:
716             return builder_.ConvertUInt32ToBool(gate);
717         case TypeInfo::FLOAT64:
718             return builder_.ConvertFloat64ToBool(gate);
719         case TypeInfo::NONE:
720         case TypeInfo::TAGGED: {
721             if (gateType.IsBooleanType()) {
722                 return builder_.CheckTaggedBooleanAndConvertToBool(gate);
723             } else if (gateType.IsUndefinedType()) {
724                 return builder_.CheckUndefinedAndConvertToBool(gate);
725             } else if (gateType.IsNullType()) {
726                 return builder_.CheckNullAndConvertToBool(gate);
727             } else {
728                 ASSERT(gateType.IsNumberType());
729                 return builder_.CheckTaggedNumberAndConvertToBool(gate);
730             }
731         }
732         default: {
733             UNREACHABLE();
734             return Circuit::NullGate();
735         }
736     }
737 }
738 
ConvertForBinaryOp(GateRef gate)739 void NumberSpeculativeRetype::ConvertForBinaryOp(GateRef gate)
740 {
741     const PGOSampleType *sampleType = acc_.GetTypedBinaryType(gate).GetPGOSampleType();
742     if (sampleType->IsNumber()) {
743         if (sampleType->IsInt()) {
744             GateType leftType = GateType::IntType();
745             GateType rightType = GateType::IntType();
746             ConvertForIntOperator(gate, leftType, rightType);
747         } else {
748             GateType leftType = GateType::NumberType();
749             GateType rightType = GateType::NumberType();
750             if (sampleType->IsIntOverFlow()) {
751                 leftType = GateType::IntType();
752                 rightType = GateType::IntType();
753             } else if (sampleType->IsDouble()) {
754                 leftType = GateType::DoubleType();
755                 rightType = GateType::DoubleType();
756             }
757             ConvertForDoubleOperator(gate, leftType, rightType);
758         }
759     } else {
760         GateType gateType = acc_.GetGateType(gate);
761         GateType leftType = acc_.GetLeftType(gate);
762         GateType rightType = acc_.GetRightType(gate);
763         if (gateType.IsIntType()) {
764             ConvertForIntOperator(gate, leftType, rightType);
765         } else {
766             ConvertForDoubleOperator(gate, leftType, rightType);
767         }
768     }
769 }
770 
ConvertForCompareOp(GateRef gate)771 void NumberSpeculativeRetype::ConvertForCompareOp(GateRef gate)
772 {
773     const PGOSampleType *sampleType = acc_.GetTypedBinaryType(gate).GetPGOSampleType();
774     if (sampleType->IsNumber()) {
775         if (sampleType->IsInt()) {
776             GateType leftType = GateType::IntType();
777             GateType rightType = GateType::IntType();
778             ConvertForIntOperator(gate, leftType, rightType);
779         } else {
780             GateType leftType = GateType::NumberType();
781             GateType rightType = GateType::NumberType();
782             ConvertForDoubleOperator(gate, leftType, rightType);
783         }
784     } else {
785         GateType leftType = acc_.GetLeftType(gate);
786         GateType rightType = acc_.GetRightType(gate);
787         if (leftType.IsIntType() && rightType.IsIntType()) {
788             ConvertForIntOperator(gate, leftType, rightType);
789         } else {
790             ConvertForDoubleOperator(gate, leftType, rightType);
791         }
792     }
793 }
794 
ConvertForIntOperator(GateRef gate,GateType leftType,GateType rightType)795 void NumberSpeculativeRetype::ConvertForIntOperator(GateRef gate, GateType leftType, GateType rightType)
796 {
797     GateRef left = acc_.GetValueIn(gate, 0);
798     GateRef right = acc_.GetValueIn(gate, 1);
799 
800     acc_.ReplaceValueIn(gate, CheckAndConvertToInt32(left, leftType), 0);
801     acc_.ReplaceValueIn(gate, CheckAndConvertToInt32(right, rightType), 1);
802 
803     acc_.ReplaceStateIn(gate, builder_.GetState());
804     acc_.ReplaceDependIn(gate, builder_.GetDepend());
805 }
806 
ConvertForShiftAndLogicalOperator(GateRef gate,GateType leftType,GateType rightType)807 void NumberSpeculativeRetype::ConvertForShiftAndLogicalOperator(GateRef gate, GateType leftType, GateType rightType)
808 {
809     GateRef left = acc_.GetValueIn(gate, 0);
810     GateRef right = acc_.GetValueIn(gate, 1);
811     GateRef cLeft = CheckAndConvertToInt32(left, leftType, ConvertSupport::ENABLE, OpType::SHIFT_AND_LOGICAL);
812     GateRef cRight = CheckAndConvertToInt32(right, rightType, ConvertSupport::ENABLE, OpType::SHIFT_AND_LOGICAL);
813 
814     acc_.ReplaceValueIn(gate, cLeft, 0);
815     acc_.ReplaceValueIn(gate, cRight, 1);
816 
817     acc_.ReplaceStateIn(gate, builder_.GetState());
818     acc_.ReplaceDependIn(gate, builder_.GetDepend());
819 }
820 
ConvertForDoubleOperator(GateRef gate,GateType leftType,GateType rightType)821 void NumberSpeculativeRetype::ConvertForDoubleOperator(GateRef gate, GateType leftType, GateType rightType)
822 {
823     GateRef left = acc_.GetValueIn(gate, 0);
824     GateRef right = acc_.GetValueIn(gate, 1);
825 
826     acc_.ReplaceValueIn(gate, CheckAndConvertToFloat64(left, leftType), 0);
827     acc_.ReplaceValueIn(gate, CheckAndConvertToFloat64(right, rightType), 1);
828 
829     acc_.ReplaceStateIn(gate, builder_.GetState());
830     acc_.ReplaceDependIn(gate, builder_.GetDepend());
831 }
832 
TryConvertConstant(GateRef gate,bool needInt32)833 GateRef NumberSpeculativeRetype::TryConvertConstant(GateRef gate, bool needInt32)
834 {
835     if (acc_.GetOpCode(gate) != OpCode::CONSTANT) {
836         return Circuit::NullGate();
837     }
838 
839     if (acc_.GetGateType(gate).IsNJSValueType()) {
840         MachineType mType = acc_.GetMachineType(gate);
841         if (mType == MachineType::I32) {
842             int32_t rawValue = acc_.GetInt32FromConstant(gate);
843             double value = static_cast<double>(rawValue);
844             return needInt32 ? builder_.Int32(rawValue) : builder_.Double(value);
845         } else if (mType == MachineType::F64 && !needInt32) {
846             double rawValue = acc_.GetFloat64FromConstant(gate);
847             return builder_.Double(rawValue);
848         } else {
849             return Circuit::NullGate();
850         }
851     }
852 
853     JSTaggedValue value(acc_.GetConstantValue(gate));
854     if (value.IsInt()) {
855         int32_t rawValue = value.GetInt();
856         double doubleValue = static_cast<double>(rawValue);
857         return needInt32 ? builder_.Int32(rawValue) : builder_.Double(doubleValue);
858     } else if (value.IsDouble() && !needInt32) {
859         double rawValue = value.GetDouble();
860         return builder_.Double(rawValue);
861     }
862     return Circuit::NullGate();
863 }
864 
CheckAndConvertToInt32(GateRef gate,GateType gateType,ConvertSupport support,OpType type)865 GateRef NumberSpeculativeRetype::CheckAndConvertToInt32(GateRef gate, GateType gateType, ConvertSupport support,
866                                                         OpType type)
867 {
868     auto result = TryConvertConstant(gate, true);
869     if (result != Circuit::NullGate()) {
870         acc_.DeleteGateIfNoUse(gate);
871         ResizeAndSetTypeInfo(result, TypeInfo::INT32);
872         return result;
873     }
874     TypeInfo output = GetOutputTypeInfo(gate);
875     switch (output) {
876         case TypeInfo::INT1:
877             result = builder_.ConvertBoolToInt32(gate, support);
878             break;
879         case TypeInfo::CHAR:
880         case TypeInfo::INT32:
881             return gate;
882         case TypeInfo::UINT32: {
883             if (type != OpType::SHIFT_AND_LOGICAL) {
884                 result = builder_.CheckUInt32AndConvertToInt32(gate);
885             } else {
886                 result = gate;
887             }
888             break;
889         }
890         case TypeInfo::FLOAT64:
891             result = builder_.ConvertFloat64ToInt32(gate);
892             break;
893         case TypeInfo::NONE:
894         case TypeInfo::TAGGED: {
895             if (gateType.IsIntType()) {
896                 result = builder_.CheckTaggedIntAndConvertToInt32(gate);
897             } else if (gateType.IsDoubleType()) {
898                 result = builder_.CheckTaggedDoubleAndConvertToInt32(gate);
899             } else if (gateType.IsNullType()) {
900                 result = builder_.CheckNullAndConvertToInt32(gate);
901             } else if (gateType.IsBooleanType()) {
902                 result = builder_.CheckTaggedBooleanAndConvertToInt32(gate);
903             } else if (gateType.IsUndefinedType()) {
904                 if (type == OpType::SHIFT_AND_LOGICAL) {
905                     result = builder_.CheckUndefinedAndConvertToInt32(gate);
906                 } else {
907                     LOG_ECMA(FATAL) << "undefined cannot convert to int type";
908                 }
909             } else {
910                 ASSERT(gateType.IsNumberType());
911                 result = builder_.CheckTaggedNumberAndConvertToInt32(gate);
912             }
913             break;
914         }
915         default: {
916             LOG_ECMA(FATAL) << "this branch is unreachable";
917             UNREACHABLE();
918             return Circuit::NullGate();
919         }
920     }
921     ResizeAndSetTypeInfo(result, TypeInfo::INT32);
922     return result;
923 }
924 
CheckAndConvertToFloat64(GateRef gate,GateType gateType,ConvertSupport support)925 GateRef NumberSpeculativeRetype::CheckAndConvertToFloat64(GateRef gate, GateType gateType, ConvertSupport support)
926 {
927     auto result = TryConvertConstant(gate, false);
928     if (result != Circuit::NullGate()) {
929         acc_.DeleteGateIfNoUse(gate);
930         ResizeAndSetTypeInfo(result, TypeInfo::FLOAT64);
931         return result;
932     }
933     TypeInfo output = GetOutputTypeInfo(gate);
934     switch (output) {
935         case TypeInfo::INT1:
936             result = builder_.ConvertBoolToFloat64(gate, support);
937             break;
938         case TypeInfo::INT32:
939             result = builder_.ConvertInt32ToFloat64(gate);
940             break;
941         case TypeInfo::UINT32:
942             result = builder_.ConvertUInt32ToFloat64(gate);
943             break;
944         case TypeInfo::FLOAT64:
945             return gate;
946         case TypeInfo::NONE:
947         case TypeInfo::TAGGED: {
948             if (gateType.IsIntType()) {
949                 result = builder_.CheckTaggedIntAndConvertToFloat64(gate);
950             } else if (gateType.IsDoubleType()) {
951                 result = builder_.CheckTaggedDoubleAndConvertToFloat64(gate);
952             } else if (gateType.IsNullType()) {
953                 result = builder_.CheckNullAndConvertToFloat64(gate);
954             } else if (gateType.IsBooleanType()) {
955                 result = builder_.CheckTaggedBooleanAndConvertToFloat64(gate);
956             } else if (gateType.IsUndefinedType()) {
957                 result = builder_.CheckUndefinedAndConvertToFloat64(gate);
958             } else {
959                 ASSERT(gateType.IsNumberType());
960                 result = builder_.CheckTaggedNumberAndConvertToFloat64(gate);
961             }
962             break;
963         }
964         default: {
965             LOG_ECMA(FATAL) << "this branch is unreachable";
966             UNREACHABLE();
967             return Circuit::NullGate();
968         }
969     }
970     ResizeAndSetTypeInfo(result, TypeInfo::FLOAT64);
971     return result;
972 }
973 
CheckAndConvertToTagged(GateRef gate,GateType gateType)974 GateRef NumberSpeculativeRetype::CheckAndConvertToTagged(GateRef gate, GateType gateType)
975 {
976     TypeInfo output = GetOutputTypeInfo(gate);
977     switch (output) {
978         case TypeInfo::INT1:
979             return builder_.ConvertBoolToTaggedBoolean(gate);
980         case TypeInfo::INT32:
981             return builder_.ConvertInt32ToTaggedInt(gate);
982         case TypeInfo::UINT32:
983             return builder_.ConvertUInt32ToTaggedNumber(gate);
984         case TypeInfo::FLOAT64:
985             return builder_.ConvertFloat64ToTaggedDouble(gate);
986         case TypeInfo::NONE:
987         case TypeInfo::TAGGED: {
988             ASSERT(gateType.IsNumberType() || gateType.IsBooleanType());
989             builder_.TryPrimitiveTypeCheck(gateType, gate);
990             return gate;
991         }
992         default:
993             LOG_ECMA(FATAL) << "this branch is unreachable";
994             UNREACHABLE();
995             return Circuit::NullGate();
996     }
997 }
998 
ConvertToTagged(GateRef gate)999 GateRef NumberSpeculativeRetype::ConvertToTagged(GateRef gate)
1000 {
1001     TypeInfo output = GetOutputTypeInfo(gate);
1002     switch (output) {
1003         case TypeInfo::INT1:
1004             return builder_.ConvertBoolToTaggedBoolean(gate);
1005         case TypeInfo::INT32:
1006             return builder_.ConvertInt32ToTaggedInt(gate);
1007         case TypeInfo::UINT32:
1008             return builder_.ConvertUInt32ToTaggedNumber(gate);
1009         case TypeInfo::FLOAT64:
1010             return builder_.ConvertFloat64ToTaggedDouble(gate);
1011         case TypeInfo::CHAR:
1012             return builder_.ConvertCharToEcmaString(gate);
1013         case TypeInfo::NONE:
1014         case TypeInfo::TAGGED: {
1015             return gate;
1016         }
1017         default:
1018             LOG_ECMA(FATAL) << "this branch is unreachable";
1019             UNREACHABLE();
1020             return Circuit::NullGate();
1021     }
1022 }
1023 
VisitRangeCheckPredicate(GateRef gate)1024 GateRef NumberSpeculativeRetype::VisitRangeCheckPredicate(GateRef gate)
1025 {
1026     if (IsRetype()) {
1027         return SetOutputType(gate, GateType::IntType());
1028     }
1029 
1030     if (IsConvert()) {
1031         Environment env(gate, circuit_, &builder_);
1032         GateRef value0 = acc_.GetValueIn(gate, 0);
1033         GateRef value1 = acc_.GetValueIn(gate, 1);
1034         GateType value0Type = acc_.GetGateType(value0);
1035         GateType value1Type = acc_.GetGateType(value1);
1036         acc_.ReplaceValueIn(gate, CheckAndConvertToInt32(value0, value0Type), 0);
1037         acc_.ReplaceValueIn(gate, CheckAndConvertToInt32(value1, value1Type), 1);
1038 
1039         acc_.ReplaceStateIn(gate, builder_.GetState());
1040         acc_.ReplaceDependIn(gate, builder_.GetDepend());
1041     }
1042 
1043     return Circuit::NullGate();
1044 }
1045 
VisitIndexCheck(GateRef gate)1046 GateRef NumberSpeculativeRetype::VisitIndexCheck(GateRef gate)
1047 {
1048     if (IsRetype()) {
1049         return SetOutputType(gate, GateType::IntType());
1050     }
1051 
1052     if (IsConvert()) {
1053         Environment env(gate, circuit_, &builder_);
1054         GateRef receiver = acc_.GetValueIn(gate, 0);
1055         GateRef index = acc_.GetValueIn(gate, 1);
1056         GateType receiverType = acc_.GetGateType(receiver);
1057         GateType indexType = acc_.GetGateType(index);
1058         acc_.ReplaceValueIn(gate, CheckAndConvertToInt32(receiver, receiverType), 0);
1059         acc_.ReplaceValueIn(gate, CheckAndConvertToInt32(index, indexType), 1);
1060 
1061         acc_.ReplaceStateIn(gate, builder_.GetState());
1062         acc_.ReplaceDependIn(gate, builder_.GetDepend());
1063     }
1064 
1065     return Circuit::NullGate();
1066 }
1067 
VisitLoadArrayLength(GateRef gate)1068 GateRef NumberSpeculativeRetype::VisitLoadArrayLength(GateRef gate)
1069 {
1070     if (IsRetype()) {
1071         return SetOutputType(gate, GateType::IntType());
1072     }
1073 
1074     return Circuit::NullGate();
1075 }
1076 
VisitLoadStringLength(GateRef gate)1077 GateRef NumberSpeculativeRetype::VisitLoadStringLength(GateRef gate)
1078 {
1079     if (IsRetype()) {
1080         return SetOutputType(gate, GateType::IntType());
1081     }
1082 
1083     return Circuit::NullGate();
1084 }
1085 
VisitLoadElement(GateRef gate)1086 GateRef NumberSpeculativeRetype::VisitLoadElement(GateRef gate)
1087 {
1088     if (IsRetype()) {
1089         auto op = acc_.GetTypedLoadOp(gate);
1090         switch (op) {
1091             case TypedLoadOp::INT8ARRAY_LOAD_ELEMENT:
1092             case TypedLoadOp::UINT8ARRAY_LOAD_ELEMENT:
1093             case TypedLoadOp::UINT8CLAMPEDARRAY_LOAD_ELEMENT:
1094             case TypedLoadOp::INT16ARRAY_LOAD_ELEMENT:
1095             case TypedLoadOp::UINT16ARRAY_LOAD_ELEMENT:
1096             case TypedLoadOp::INT32ARRAY_LOAD_ELEMENT:
1097                 return SetOutputType(gate, GateType::IntType());
1098             case TypedLoadOp::UINT32ARRAY_LOAD_ELEMENT:
1099                 return SetOutputType(gate, TypeInfo::UINT32);
1100             case TypedLoadOp::FLOAT32ARRAY_LOAD_ELEMENT:
1101             case TypedLoadOp::FLOAT64ARRAY_LOAD_ELEMENT:
1102                 return SetOutputType(gate, GateType::DoubleType());
1103             case TypedLoadOp::STRING_LOAD_ELEMENT:
1104                 return SetOutputType(gate, TypeInfo::CHAR);
1105             default:
1106                 return SetOutputType(gate, GateType::AnyType());
1107         }
1108     }
1109 
1110     if (IsConvert()) {
1111         Environment env(gate, circuit_, &builder_);
1112         GateRef index = acc_.GetValueIn(gate, 1);
1113         GateType indexType = acc_.GetGateType(index);
1114         acc_.ReplaceValueIn(gate, CheckAndConvertToInt32(index, indexType), 1);
1115         acc_.ReplaceStateIn(gate, builder_.GetState());
1116         acc_.ReplaceDependIn(gate, builder_.GetDepend());
1117     }
1118 
1119     return Circuit::NullGate();
1120 }
1121 
VisitStoreElement(GateRef gate)1122 GateRef NumberSpeculativeRetype::VisitStoreElement(GateRef gate)
1123 {
1124     if (IsRetype()) {
1125         return SetOutputType(gate, GateType::AnyType());
1126     }
1127 
1128     if (IsConvert()) {
1129         Environment env(gate, circuit_, &builder_);
1130         GateRef index = acc_.GetValueIn(gate, 1);
1131         GateType indexType = acc_.GetGateType(index);
1132         GateRef value = acc_.GetValueIn(gate, 2);
1133         acc_.ReplaceValueIn(gate, CheckAndConvertToInt32(index, indexType), 1);
1134         auto op = acc_.GetTypedStoreOp(gate);
1135         switch (op) {
1136             case TypedStoreOp::INT8ARRAY_STORE_ELEMENT:
1137             case TypedStoreOp::UINT8ARRAY_STORE_ELEMENT:
1138             case TypedStoreOp::UINT8CLAMPEDARRAY_STORE_ELEMENT:
1139             case TypedStoreOp::INT16ARRAY_STORE_ELEMENT:
1140             case TypedStoreOp::UINT16ARRAY_STORE_ELEMENT:
1141             case TypedStoreOp::INT32ARRAY_STORE_ELEMENT:
1142             case TypedStoreOp::UINT32ARRAY_STORE_ELEMENT:
1143                 acc_.ReplaceValueIn(gate, CheckAndConvertToInt32(value, GateType::NumberType()), 2);   // 2: value idx
1144                 break;
1145             case TypedStoreOp::FLOAT32ARRAY_STORE_ELEMENT:
1146             case TypedStoreOp::FLOAT64ARRAY_STORE_ELEMENT:
1147                 acc_.ReplaceValueIn(gate, CheckAndConvertToFloat64(value, GateType::NumberType()), 2);  // 2: value idx
1148                 break;
1149             default:
1150                 acc_.ReplaceValueIn(gate, ConvertToTagged(value), 2);   // 2: value idx
1151                 break;
1152         }
1153         acc_.ReplaceStateIn(gate, builder_.GetState());
1154         acc_.ReplaceDependIn(gate, builder_.GetDepend());
1155     }
1156 
1157     return Circuit::NullGate();
1158 }
1159 
VisitStoreProperty(GateRef gate)1160 GateRef NumberSpeculativeRetype::VisitStoreProperty(GateRef gate)
1161 {
1162     if (IsRetype()) {
1163         return SetOutputType(gate, GateType::AnyType());
1164     }
1165     ASSERT(IsConvert());
1166     GateRef value = acc_.GetValueIn(gate, 2); // 2: value
1167 
1168     Environment env(gate, circuit_, &builder_);
1169     GateRef propertyLookupResult = acc_.GetValueIn(gate, 1);
1170     PropertyLookupResult plr(acc_.TryGetValue(propertyLookupResult));
1171     if (plr.GetRepresentation() == Representation::DOUBLE) {
1172         acc_.SetMetaData(gate, circuit_->StorePropertyNoBarrier());
1173         acc_.ReplaceValueIn(
1174             gate, CheckAndConvertToFloat64(value, GateType::NumberType(), ConvertSupport::DISABLE), 2); // 2: value
1175     } else if (plr.GetRepresentation() == Representation::INT) {
1176         acc_.SetMetaData(gate, circuit_->StorePropertyNoBarrier());
1177         acc_.ReplaceValueIn(
1178             gate, CheckAndConvertToInt32(value, GateType::IntType(), ConvertSupport::DISABLE), 2); // 2: value
1179     } else {
1180         TypeInfo valueType = GetOutputTypeInfo(value);
1181         if (valueType == TypeInfo::INT1 || valueType == TypeInfo::INT32 || valueType == TypeInfo::FLOAT64) {
1182             acc_.SetMetaData(gate, circuit_->StorePropertyNoBarrier());
1183         }
1184         acc_.ReplaceValueIn(gate, ConvertToTagged(value), 2); // 2: value
1185     }
1186 
1187     GateRef receiver = acc_.GetValueIn(gate, 0); // receiver
1188     acc_.ReplaceValueIn(gate, ConvertToTagged(receiver), 0);
1189     acc_.ReplaceStateIn(gate, builder_.GetState());
1190     acc_.ReplaceDependIn(gate, builder_.GetDepend());
1191     return Circuit::NullGate();
1192 }
1193 
VisitLoadProperty(GateRef gate)1194 GateRef NumberSpeculativeRetype::VisitLoadProperty(GateRef gate)
1195 {
1196     if (IsRetype()) {
1197         GateRef propertyLookupResult = acc_.GetValueIn(gate, 1);
1198         PropertyLookupResult plr(acc_.TryGetValue(propertyLookupResult));
1199         return SetOutputType(gate, plr.GetRepresentation());
1200     }
1201 
1202     ASSERT(IsConvert());
1203 
1204     return VisitWithConstantValue(gate, PROPERTY_LOOKUP_RESULT_INDEX); // ignoreIndex
1205 }
1206 
VisitTypeConvert(GateRef gate)1207 GateRef NumberSpeculativeRetype::VisitTypeConvert(GateRef gate)
1208 {
1209     GateRef input = acc_.GetValueIn(gate, 0);
1210     TypeInfo inputInfo = GetOutputTypeInfo(input);
1211     if (IsRetype()) {
1212         if (inputInfo == TypeInfo::TAGGED) {
1213             if (acc_.IsConstantNumber(input)) {
1214                 return Circuit::NullGate();
1215             }
1216             GateType gateType = acc_.GetGateType(gate);
1217             ASSERT(gateType.IsNumberType());
1218             GateType resType = gateType.IsIntType() ? GateType::IntType() : GateType::DoubleType();
1219             return SetOutputType(gate, resType);
1220         }
1221         TypeInfo oldType = GetOutputTypeInfo(gate);
1222         SetOutputTypeInfo(gate, inputInfo);
1223         return oldType == inputInfo ? Circuit::NullGate() : gate;
1224     }
1225     ASSERT(IsConvert());
1226     ASSERT(inputInfo != TypeInfo::INT1 && inputInfo != TypeInfo::NONE);
1227     Environment env(gate, circuit_, &builder_);
1228     if (inputInfo == TypeInfo::TAGGED && !acc_.IsConstantNumber(input)) {
1229         GateType gateType = acc_.GetGateType(gate);
1230         ASSERT(gateType.IsNumberType());
1231         if (gateType.IsIntType()) {
1232             input = CheckAndConvertToInt32(input, GateType::IntType());
1233             ResizeAndSetTypeInfo(input, TypeInfo::INT32);
1234         } else {
1235             input = CheckAndConvertToFloat64(input, acc_.GetGateType(input));
1236             ResizeAndSetTypeInfo(input, TypeInfo::FLOAT64);
1237         }
1238     }
1239     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), input);
1240     return Circuit::NullGate();
1241 }
1242 
VisitNumberMod(GateRef gate)1243 GateRef NumberSpeculativeRetype::VisitNumberMod(GateRef gate)
1244 {
1245     if (IsRetype()) {
1246         const PGOSampleType *sampleType = acc_.GetTypedBinaryType(gate).GetPGOSampleType();
1247         if (sampleType->IsNumber()) {
1248             return SetOutputType(gate, *sampleType);
1249         } else {
1250             GateType gateType = acc_.GetGateType(gate);
1251             GateType resType = gateType.IsIntType() ? GateType::IntType() : GateType::DoubleType();
1252             return SetOutputType(gate, resType);
1253         }
1254     } else if (IsConvert()) {
1255         Environment env(gate, circuit_, &builder_);
1256         ConvertForBinaryOp(gate);
1257     }
1258 
1259     return Circuit::NullGate();
1260 }
1261 
VisitMonoLoadPropertyOnProto(GateRef gate)1262 GateRef NumberSpeculativeRetype::VisitMonoLoadPropertyOnProto(GateRef gate)
1263 {
1264     if (IsRetype()) {
1265         GateRef propertyLookupResult = acc_.GetValueIn(gate, 1);
1266         PropertyLookupResult plr(acc_.TryGetValue(propertyLookupResult));
1267         return SetOutputType(gate, plr.GetRepresentation());
1268     }
1269 
1270     ASSERT(IsConvert());
1271     size_t valueNum = acc_.GetNumValueIn(gate);
1272     for (size_t i = 0; i < valueNum; ++i) {
1273         if (i == PROPERTY_LOOKUP_RESULT_INDEX || i == HCLASS_INDEX) {
1274             continue;
1275         }
1276         GateRef input = acc_.GetValueIn(gate, i);
1277         acc_.ReplaceValueIn(gate, ConvertToTagged(input), i);
1278     }
1279 
1280     return Circuit::NullGate();
1281 }
1282 
VisitMonoCallGetterOnProto(GateRef gate)1283 GateRef NumberSpeculativeRetype::VisitMonoCallGetterOnProto(GateRef gate)
1284 {
1285     if (IsRetype()) {
1286         return SetOutputType(gate, GateType::AnyType());
1287     }
1288     if (IsConvert()) {
1289         size_t valueNum = acc_.GetNumValueIn(gate);
1290         for (size_t i = 0; i < valueNum; ++i) {
1291             if (i == PROPERTY_LOOKUP_RESULT_INDEX || i == HCLASS_INDEX) {
1292                 continue;
1293             }
1294             GateRef input = acc_.GetValueIn(gate, i);
1295             acc_.ReplaceValueIn(gate, ConvertToTagged(input), i);
1296         }
1297     }
1298     return Circuit::NullGate();
1299 }
1300 
VisitMonoStoreProperty(GateRef gate)1301 GateRef NumberSpeculativeRetype::VisitMonoStoreProperty(GateRef gate)
1302 {
1303     if (IsRetype()) {
1304         return SetOutputType(gate, GateType::AnyType());
1305     }
1306     ASSERT(IsConvert());
1307 
1308     GateRef value = acc_.GetValueIn(gate, 4); // 4: value
1309 
1310     Environment env(gate, circuit_, &builder_);
1311     GateRef propertyLookupResult = acc_.GetValueIn(gate, 1);
1312     PropertyLookupResult plr(acc_.TryGetValue(propertyLookupResult));
1313     if (plr.IsAccessor()) {
1314         size_t valueNum = acc_.GetNumValueIn(gate);
1315         for (size_t i = 0; i < valueNum; ++i) {
1316             if (i == PROPERTY_LOOKUP_RESULT_INDEX || i == HCLASS_INDEX) {
1317                 continue;
1318             }
1319             GateRef input = acc_.GetValueIn(gate, i);
1320             acc_.ReplaceValueIn(gate, ConvertToTagged(input), i);
1321         }
1322         return Circuit::NullGate();
1323     }
1324 
1325     if (plr.GetRepresentation() == Representation::DOUBLE) {
1326         acc_.SetStoreNoBarrier(gate, true);
1327         acc_.ReplaceValueIn(
1328             gate, CheckAndConvertToFloat64(value, GateType::NumberType(), ConvertSupport::DISABLE), 4); // 4: value
1329     } else if (plr.GetRepresentation() == Representation::INT) {
1330         acc_.SetStoreNoBarrier(gate, true);
1331         acc_.ReplaceValueIn(
1332             gate, CheckAndConvertToInt32(value, GateType::IntType(), ConvertSupport::DISABLE), 4); // 4: value
1333     } else {
1334         TypeInfo valueType = GetOutputTypeInfo(value);
1335         if (valueType == TypeInfo::INT1 || valueType == TypeInfo::INT32 || valueType == TypeInfo::FLOAT64) {
1336             acc_.SetStoreNoBarrier(gate, true);
1337         }
1338         acc_.ReplaceValueIn(gate, ConvertToTagged(value), 4); // 4: value
1339     }
1340 
1341     GateRef receiver = acc_.GetValueIn(gate, 0); // receiver
1342     acc_.ReplaceValueIn(gate, ConvertToTagged(receiver), 0);
1343     acc_.ReplaceStateIn(gate, builder_.GetState());
1344     acc_.ReplaceDependIn(gate, builder_.GetDepend());
1345     return Circuit::NullGate();
1346 }
1347 
VisitGate(GateRef gate)1348 GateRef NumberSpeculativeRetypeManager::VisitGate(GateRef gate)
1349 {
1350     retype_->setState(state_);
1351     return retype_->VisitGate(gate);
1352 }
1353 
1354 }  // namespace panda::ecmascript::kungfu
1355