• 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 
18 #include "ecmascript/compiler/circuit_arg_indices.h"
19 #include "ecmascript/compiler/circuit_builder-inl.h"
20 
21 namespace panda::ecmascript::kungfu {
SetOutputType(GateRef gate,GateType gateType)22 GateRef NumberSpeculativeRetype::SetOutputType(GateRef gate, GateType gateType)
23 {
24     TypeInfo type = GetOutputTypeInfo(gate);
25     TypeInfo old = type;
26     if (gateType.IsIntType()) {
27         type = TypeInfo::INT32;
28     } else if (gateType.IsDoubleType()) {
29         type = TypeInfo::FLOAT64;
30     } else if (gateType.IsBooleanType()) {
31         type = TypeInfo::INT1;
32     } else {
33         type = TypeInfo::TAGGED;
34     }
35     SetOutputTypeInfo(gate, type);
36     return old == type ? Circuit::NullGate() : gate;
37 }
38 
SetOutputType(GateRef gate,ParamType paramType)39 GateRef NumberSpeculativeRetype::SetOutputType(GateRef gate, ParamType paramType)
40 {
41     TypeInfo type = GetOutputTypeInfo(gate);
42     TypeInfo old = type;
43     if (paramType.IsIntType()) {
44         type = TypeInfo::INT32;
45     } else if (paramType.IsNumberType()) {
46         type = TypeInfo::FLOAT64;
47     } else if (paramType.IsDoubleType()) {
48         type = TypeInfo::FLOAT64;
49     } else if (paramType.IsIntOverflowType()) {
50         type = TypeInfo::FLOAT64;
51     } else if (paramType.IsBooleanType()) {
52         type = TypeInfo::INT1;
53     } else {
54         type = TypeInfo::TAGGED;
55     }
56     SetOutputTypeInfo(gate, type);
57     return old == type ? Circuit::NullGate() : gate;
58 }
59 
SetOutputType(GateRef gate,Representation rep)60 GateRef NumberSpeculativeRetype::SetOutputType(GateRef gate, Representation rep)
61 {
62     TypeInfo type = GetOutputTypeInfo(gate);
63     TypeInfo old = type;
64     if (rep == Representation::INT) {
65         type = TypeInfo::INT32;
66     } else if (rep == Representation::DOUBLE) {
67         type = TypeInfo::FLOAT64;
68     } else {
69         type = TypeInfo::TAGGED;
70     }
71     SetOutputTypeInfo(gate, type);
72     return old == type ? Circuit::NullGate() : gate;
73 }
74 
SetOutputType(GateRef gate,TypeInfo type)75 GateRef NumberSpeculativeRetype::SetOutputType(GateRef gate, TypeInfo type)
76 {
77     TypeInfo old = GetOutputTypeInfo(gate);
78     SetOutputTypeInfo(gate, type);
79     return old == type ? Circuit::NullGate() : gate;
80 }
81 
GetNumberTypeInfo(GateRef gate)82 TypeInfo NumberSpeculativeRetype::GetNumberTypeInfo(GateRef gate)
83 {
84     TypeInfo typeInfo = GetOutputTypeInfo(gate);
85     switch (typeInfo) {
86         case TypeInfo::INT1:
87         case TypeInfo::INT32:
88         case TypeInfo::HOLE_INT:
89             return TypeInfo::INT32;
90         case TypeInfo::UINT32:
91         case TypeInfo::FLOAT64:
92         case TypeInfo::HOLE_DOUBLE:
93             return TypeInfo::FLOAT64;
94         case TypeInfo::NONE:
95         case TypeInfo::TAGGED: {
96             GateType gateType = acc_.GetGateType(gate);
97             if (gateType.IsIntType() || gateType.IsBooleanType()) {
98                 return TypeInfo::INT32;
99             } else if (gateType.IsDoubleType()) {
100                 return TypeInfo::FLOAT64;
101             } else {
102                 return TypeInfo::TAGGED;
103             }
104         }
105         case TypeInfo::CHAR:
106             return TypeInfo::TAGGED;
107     }
108     UNREACHABLE();
109 }
110 
GetCommonTypeInfo(TypeInfo left,TypeInfo right)111 static TypeInfo GetCommonTypeInfo(TypeInfo left, TypeInfo right)
112 {
113     if (left == TypeInfo::TAGGED || right == TypeInfo::TAGGED) {
114         return TypeInfo::TAGGED;
115     }
116     ASSERT(left == TypeInfo::INT32 || left == TypeInfo::FLOAT64);
117     ASSERT(right == TypeInfo::INT32 || right == TypeInfo::FLOAT64);
118     if (left == right) {
119         return left;
120     }
121     return TypeInfo::FLOAT64;
122 }
123 
setState(NumberSpeculativeRetype::State state)124 void NumberSpeculativeRetype::setState(NumberSpeculativeRetype::State state)
125 {
126     state_ = state;
127 }
128 
ConvertMonoAccessorValueIn(GateRef gate)129 void NumberSpeculativeRetype::ConvertMonoAccessorValueIn(GateRef gate)
130 {
131     size_t valueNum = acc_.GetNumValueIn(gate);
132     for (size_t i = 0; i < valueNum; ++i) {
133         if (i == PROPERTY_LOOKUP_RESULT_INDEX || i == HCLASS_INDEX) {
134             continue;
135         }
136         GateRef input = acc_.GetValueIn(gate, i);
137         acc_.ReplaceValueIn(gate, ConvertToTagged(input), i);
138     }
139 }
140 
VisitGate(GateRef gate)141 GateRef NumberSpeculativeRetype::VisitGate(GateRef gate)
142 {
143     OpCode op = acc_.GetOpCode(gate);
144     switch (op) {
145         case OpCode::TYPED_BINARY_OP:
146             return VisitTypedBinaryOp(gate);
147         case OpCode::TYPED_UNARY_OP:
148             return VisitTypedUnaryOp(gate);
149         case OpCode::TYPED_CONDITION_JUMP:
150             return VisitTypedConditionJump(gate);
151         case OpCode::RANGE_CHECK_PREDICATE:
152             return VisitRangeCheckPredicate(gate);
153         case OpCode::INDEX_CHECK:
154             return VisitIndexCheck(gate);
155         case OpCode::LOAD_ARRAY_LENGTH:
156         case OpCode::LOAD_TYPED_ARRAY_LENGTH:
157             return VisitLoadArrayLength(gate);
158         case OpCode::LOAD_STRING_LENGTH:
159             return VisitLoadStringLength(gate);
160         case OpCode::LOAD_MAP_SIZE:
161             return VisitLoadMapSize(gate);
162         case OpCode::LOAD_ELEMENT:
163             return VisitLoadElement(gate);
164         case OpCode::STORE_ELEMENT:
165             return VisitStoreElement(gate);
166         case OpCode::STORE_PROPERTY:
167             return VisitStoreProperty(gate);
168         case OpCode::LOAD_PROPERTY:
169             return VisitLoadProperty(gate);
170         case OpCode::MONO_LOAD_PROPERTY_ON_PROTO:
171             return VisitMonoLoadPropertyOnProto(gate);
172         case OpCode::MONO_CALL_GETTER_ON_PROTO:
173             return VisitMonoCallGetterOnProto(gate);
174         case OpCode::MONO_STORE_PROPERTY:
175         case OpCode::MONO_STORE_PROPERTY_LOOK_UP_PROTO:
176             return VisitMonoStoreProperty(gate);
177         case OpCode::VALUE_SELECTOR:
178             return VisitPhi(gate);
179         case OpCode::CONSTANT:
180             return VisitConstant(gate);
181         case OpCode::TYPE_CONVERT:
182             return VisitTypeConvert(gate);
183         case OpCode::FRAME_STATE:
184             return VisitFrameState(gate);
185         case OpCode::CALL_GETTER:
186         case OpCode::CALL_SETTER:
187         case OpCode::CONSTRUCT:
188         case OpCode::CALL_NEW:
189         case OpCode::TYPEDCALL:
190         case OpCode::TYPEDFASTCALL:
191         case OpCode::OBJECT_TYPE_CHECK:
192         case OpCode::CALLINTERNAL:
193             return VisitWithConstantValue(gate, PROPERTY_LOOKUP_RESULT_INDEX);
194         case OpCode::LOOP_EXIT_VALUE:
195         case OpCode::RANGE_GUARD:
196             return VisitIntermediateValue(gate);
197         case OpCode::NUMBER_TO_STRING:
198             return VisitNumberToString(gate);
199         case OpCode::ARRAY_FIND_OR_FINDINDEX:
200             return VisitArrayFindOrFindIndex(gate);
201         case OpCode::MATH_LOG:
202         case OpCode::MATH_LOG2:
203         case OpCode::MATH_LOG10:
204         case OpCode::MATH_LOG1P:
205         case OpCode::MATH_EXP:
206         case OpCode::MATH_EXPM1:
207         case OpCode::MATH_ACOS:
208         case OpCode::MATH_ACOSH:
209         case OpCode::MATH_ASIN:
210         case OpCode::MATH_ASINH:
211         case OpCode::MATH_ATAN:
212         case OpCode::MATH_ATAN2:
213         case OpCode::MATH_ATANH:
214         case OpCode::MATH_COS:
215         case OpCode::MATH_COSH:
216         case OpCode::MATH_SIN:
217         case OpCode::MATH_SINH:
218         case OpCode::MATH_SQRT:
219         case OpCode::MATH_TAN:
220         case OpCode::MATH_TANH:
221         case OpCode::MATH_POW:
222         case OpCode::MATH_CBRT:
223         case OpCode::MATH_FROUND:
224         case OpCode::MATH_CEIL:
225         case OpCode::MATH_FLOOR:
226             return VisitMathDoubleParamsBuiltin(gate);
227         case OpCode::MATH_CLZ32:
228             return VisitClz32Builtin(gate);
229         case OpCode::MATH_ABS:
230         case OpCode::MATH_MIN:
231         case OpCode::MATH_MAX:
232         case OpCode::MATH_SIGN:
233         case OpCode::MATH_ROUND:
234             return VisitMathTaggedNumberParamsBuiltin(gate);
235         case OpCode::MATH_TRUNC:
236             return VisitMathTrunc(gate);
237         case OpCode::GLOBAL_IS_FINITE:
238         case OpCode::NUMBER_IS_FINITE:
239             return VisitNumberOrGlobalBuiltin<false>(gate);
240         case OpCode::GLOBAL_IS_NAN:
241         case OpCode::NUMBER_IS_NAN:
242             return VisitNumberOrGlobalBuiltin<true>(gate);
243         case OpCode::NUMBER_IS_INTEGER:
244         case OpCode::NUMBER_IS_SAFEINTEGER:
245             return VisitNumberIsInteger(gate);
246         case OpCode::NUMBER_PARSE_FLOAT:
247             return VisitNumberParseFloat(gate);
248         case OpCode::MATH_IMUL:
249             return VisitMathImul(gate);
250         case OpCode::DATA_VIEW_GET:
251             return VisitDataViewGet(gate);
252         case OpCode::DATA_VIEW_SET:
253             return VisitDataViewSet(gate);
254         case OpCode::DATE_GET_TIME:
255             return VisitDateGetTime(gate);
256         case OpCode::BIGINT_ASINTN:
257         case OpCode::BIGINT_ASUINTN:
258             return VisitBigIntAsIntN(gate);
259         case OpCode::MAP_HAS:
260         case OpCode::SET_HAS:
261         case OpCode::MAP_DELETE:
262         case OpCode::SET_DELETE:
263             return VisitOthers(gate, GateType::BooleanType());
264         case OpCode::DATE_NOW:
265             return VisitDateNow(gate);
266         case OpCode::BIGINT_CONSTRUCTOR:
267             return VisitBigIntConstructor(gate);
268         case OpCode::CREATE_ARRAY_WITH_BUFFER:
269         case OpCode::TYPED_CREATE_OBJ_WITH_BUFFER:
270         case OpCode::ARRAY_ITERATOR_BUILTIN:
271         case OpCode::MAP_KEYS:
272         case OpCode::MAP_VALUES:
273         case OpCode::MAP_ENTRIES:
274         case OpCode::SET_ENTRIES:
275         case OpCode::SET_VALUES:
276             return VisitOthersWithoutConvert(gate);
277         case OpCode::STRING_SUB_STR:
278         case OpCode::STRING_SUB_STRING:
279         case OpCode::STRING_SLICE:
280             return VisitString(gate);
281         case OpCode::ARRAY_INCLUDES_INDEXOF:
282             return VisitArrayIncludesIndexOf(gate);
283         case OpCode::STRING_CHAR_CODE_AT:
284             return VisitStringCharCodeAt(gate);
285         case OpCode::NUMBER_PARSE_INT:
286         case OpCode::JS_BYTECODE:
287         case OpCode::RUNTIME_CALL:
288         case OpCode::PRIMITIVE_TYPE_CHECK:
289         case OpCode::STABLE_ARRAY_CHECK:
290         case OpCode::TYPED_ARRAY_CHECK:
291         case OpCode::TYPED_CALLTARGETCHECK_OP:
292         case OpCode::TYPED_CALL_CHECK:
293         case OpCode::HEAP_ALLOC:
294         case OpCode::TYPED_SUPER_ALLOCATE_THIS:
295         case OpCode::GET_SUPER_CONSTRUCTOR:
296         case OpCode::ARG:
297         case OpCode::INITVREG:
298         case OpCode::RETURN:
299         case OpCode::FRAME_ARGS:
300         case OpCode::SAVE_REGISTER:
301         case OpCode::RESTORE_REGISTER:
302         case OpCode::LOAD_CONST_OFFSET:
303         case OpCode::STORE_CONST_OFFSET:
304         case OpCode::LEX_VAR_IS_HOLE_CHECK:
305         case OpCode::TYPE_OF_CHECK:
306         case OpCode::TYPE_OF:
307         case OpCode::ARRAY_CONSTRUCTOR:
308         case OpCode::FLOAT32_ARRAY_CONSTRUCTOR:
309         case OpCode::OBJECT_CONSTRUCTOR:
310         case OpCode::BOOLEAN_CONSTRUCTOR:
311         case OpCode::LD_LOCAL_MODULE_VAR:
312         case OpCode::STORE_MODULE_VAR:
313         case OpCode::STRING_FROM_SINGLE_CHAR_CODE:
314         case OpCode::ORDINARY_HAS_INSTANCE:
315         case OpCode::ECMA_STRING_CHECK:
316         case OpCode::INTERN_STRING_CHECK:
317         case OpCode::CREATE_ARGUMENTS:
318         case OpCode::TAGGED_TO_INT64:
319         case OpCode::TYPED_CALL_BUILTIN:
320         case OpCode::TYPED_CALL_BUILTIN_SIDE_EFFECT:
321         case OpCode::CALL_PRIVATE_GETTER:
322         case OpCode::CALL_PRIVATE_SETTER:
323         case OpCode::MAP_GET:
324         case OpCode::NEW_NUMBER:
325         case OpCode::TYPED_ARRAY_ENTRIES:
326         case OpCode::TYPED_ARRAY_KEYS:
327         case OpCode::TYPED_ARRAY_VALUES:
328         case OpCode::SET_ADD:
329         case OpCode::LOAD_BUILTIN_OBJECT:
330         case OpCode::CREATE_ARRAY:
331         case OpCode::OBJECT_IS:
332         case OpCode::OBJECT_GET_PROTOTYPE_OF:
333         case OpCode::OBJECT_CREATE:
334         case OpCode::OBJECT_IS_PROTOTYPE_OF:
335         case OpCode::OBJECT_HAS_OWN_PROPERTY:
336         case OpCode::REFLECT_GET_PROTOTYPE_OF:
337         case OpCode::REFLECT_GET:
338         case OpCode::REFLECT_HAS:
339         case OpCode::REFLECT_CONSTRUCT:
340         case OpCode::REFLECT_APPLY:
341         case OpCode::FUNCTION_PROTOTYPE_APPLY:
342         case OpCode::FUNCTION_PROTOTYPE_BIND:
343         case OpCode::FUNCTION_PROTOTYPE_CALL:
344         case OpCode::BUILTIN_PROTOTYPE_HCLASS_CHECK:
345         case OpCode::FLATTEN_TREE_STRING_CHECK:
346         case OpCode::ARRAY_POP:
347         case OpCode::ARRAY_PUSH:
348         case OpCode::ARRAY_SOME:
349         case OpCode::ARRAY_EVERY:
350         case OpCode::ARRAY_FOR_EACH:
351         case OpCode::HEAP_OBJECT_CHECK:
352         case OpCode::ARRAY_FILTER:
353         case OpCode::ARRAY_MAP:
354         case OpCode::ARRAY_SLICE:
355         case OpCode::ARRAY_BUFFER_IS_VIEW:
356         case OpCode::ARRAY_SORT:
357         case OpCode::FINISH_ALLOCATE:
358         case OpCode::IS_CALLABLE_CHECK:
359         case OpCode::IS_UNDEFINED_OR_HOLE_CHECK:
360         case OpCode::IS_NOT_UNDEFINED_OR_HOLE_CHECK:
361         case OpCode::ECMA_OBJECT_CHECK:
362         case OpCode::GET_EXCEPTION:
363         case OpCode::MATH_HCLASS_CONSISTENCY_CHECK:
364             return VisitOthers(gate);
365         case OpCode::CALL:
366         case OpCode::BYTECODE_CALL:
367         case OpCode::DEBUGGER_BYTECODE_CALL:
368         case OpCode::BUILTINS_CALL_WITH_ARGV:
369         case OpCode::BUILTINS_CALL:
370         case OpCode::RUNTIME_CALL_WITH_ARGV:
371         case OpCode::BASELINE_CALL:
372         case OpCode::ASM_CALL_BARRIER:
373         case OpCode::CALL_OPTIMIZED:
374         case OpCode::FAST_CALL_OPTIMIZED:
375             UNREACHABLE();
376         default:
377             return Circuit::NullGate();
378     }
379 }
380 
VisitTypedBinaryOp(GateRef gate)381 GateRef NumberSpeculativeRetype::VisitTypedBinaryOp(GateRef gate)
382 {
383     if (acc_.HasStringType(gate)) {
384         return VisitStringBinaryOp(gate);
385     }
386 
387     if (acc_.GetTypedBinaryOp(gate) != TypedBinOp::TYPED_STRICTEQ &&
388         acc_.GetTypedBinaryOp(gate) != TypedBinOp::TYPED_STRICTNOTEQ &&
389         acc_.GetTypedBinaryOp(gate) != TypedBinOp::TYPED_EQ &&
390         acc_.GetTypedBinaryOp(gate) != TypedBinOp::TYPED_NOTEQ) {
391         if (acc_.HasNumberType(gate)) {
392             return VisitNumberBinaryOp(gate);
393         }
394     }
395 
396     return VisitEqualCompareOrNotEqualCompare(gate);
397 }
398 
VisitArrayFindOrFindIndex(GateRef gate)399 GateRef NumberSpeculativeRetype::VisitArrayFindOrFindIndex(GateRef gate)
400 {
401     constexpr size_t BUILTINS_FUNC_ID_INDEX = 3;
402     ASSERT(acc_.GetOpCode(gate) == OpCode::ARRAY_FIND_OR_FINDINDEX);
403     ASSERT(acc_.GetNumValueIn(gate) > BUILTINS_FUNC_ID_INDEX);
404     if (IsRetype()) {
405         GateRef builtinFunc = acc_.GetValueIn(gate, BUILTINS_FUNC_ID_INDEX);
406         auto builtinsID = static_cast<BuiltinsStubCSigns::ID>(acc_.GetConstantValue(builtinFunc));
407         if (builtinsID == BuiltinsStubCSigns::ID::ArrayFind) {
408             return SetOutputType(gate, GateType::AnyType());
409         } else {
410             return SetOutputType(gate, GateType::IntType());
411         }
412     }
413 
414     return VisitWithConstantValue(gate, BUILTINS_FUNC_ID_INDEX); // ignoreIndex
415 }
416 
VisitEqualCompareOrNotEqualCompare(GateRef gate)417 GateRef NumberSpeculativeRetype::VisitEqualCompareOrNotEqualCompare(GateRef gate)
418 {
419     if (acc_.HasNumberType(gate)) {
420         return VisitNumberBinaryOp(gate);
421     } else {
422         return VisitUndefinedEqualCompareOrUndefinedNotEqualCompare(gate);
423     }
424 }
425 
VisitUndefinedEqualCompareOrUndefinedNotEqualCompare(GateRef gate)426 GateRef NumberSpeculativeRetype::VisitUndefinedEqualCompareOrUndefinedNotEqualCompare(GateRef gate)
427 {
428     ASSERT(acc_.GetTypedBinaryOp(gate) == TypedBinOp::TYPED_STRICTEQ ||
429            acc_.GetTypedBinaryOp(gate) == TypedBinOp::TYPED_STRICTNOTEQ ||
430            acc_.GetTypedBinaryOp(gate) == TypedBinOp::TYPED_EQ ||
431            acc_.GetTypedBinaryOp(gate) == TypedBinOp::TYPED_NOTEQ);
432     GateRef left = acc_.GetValueIn(gate, 0);
433     GateRef right = acc_.GetValueIn(gate, 1);
434     ASSERT((acc_.IsUndefinedOrNullOrHole(left)) || (acc_.IsUndefinedOrNullOrHole(right)));
435     if (IsRetype()) {
436         return SetOutputType(gate, GateType::BooleanType());
437     }
438     if (IsConvert()) {
439         acc_.ReplaceValueIn(gate, ConvertToTagged(left), 0);
440         acc_.ReplaceValueIn(gate, ConvertToTagged(right), 1);
441     }
442     return Circuit::NullGate();
443 }
444 
VisitConstant(GateRef gate)445 GateRef NumberSpeculativeRetype::VisitConstant(GateRef gate)
446 {
447     if (IsRetype()) {
448         if (acc_.GetGateType(gate).IsNJSValueType()) {
449             auto machineType = acc_.GetMachineType(gate);
450             switch (machineType) {
451                 case MachineType::I1:
452                     SetOutputTypeInfo(gate, TypeInfo::INT1);
453                     break;
454                 case MachineType::I32:
455                     SetOutputTypeInfo(gate, TypeInfo::INT32);
456                     break;
457                 case MachineType::F64:
458                     SetOutputTypeInfo(gate, TypeInfo::FLOAT64);
459                     break;
460                 default:
461                     SetOutputTypeInfo(gate, TypeInfo::NONE);
462                     break;
463             }
464         } else {
465             return SetOutputType(gate, GateType::AnyType());
466         }
467     }
468     return Circuit::NullGate();
469 }
470 
VisitIntermediateValue(GateRef gate)471 GateRef NumberSpeculativeRetype::VisitIntermediateValue(GateRef gate)
472 {
473     GateRef value = acc_.GetValueIn(gate, 0);
474     TypeInfo valueInfo = GetOutputTypeInfo(value);
475     if (IsRetype()) {
476         TypeInfo oldType = GetOutputTypeInfo(gate);
477         SetOutputTypeInfo(gate, valueInfo);
478         return oldType == valueInfo ? Circuit::NullGate() : gate;
479     }
480     return Circuit::NullGate();
481 }
482 
VisitNumberToString(GateRef gate)483 GateRef NumberSpeculativeRetype::VisitNumberToString(GateRef gate)
484 {
485     if (IsRetype()) {
486         return SetOutputType(gate, GateType::StringType());
487     }
488     if (IsConvert()) {
489         size_t valueNum = acc_.GetNumValueIn(gate);
490         for (size_t i = 0; i < valueNum; ++i) {
491             GateRef input = acc_.GetValueIn(gate, i);
492             acc_.ReplaceValueIn(gate, ConvertToTagged(input), i);
493         }
494     }
495     return Circuit::NullGate();
496 }
497 
VisitStringBinaryOp(GateRef gate)498 GateRef NumberSpeculativeRetype::VisitStringBinaryOp(GateRef gate)
499 {
500     TypedBinOp op = acc_.GetTypedBinaryOp(gate);
501     switch (op) {
502         case TypedBinOp::TYPED_EQ:
503         case TypedBinOp::TYPED_STRICTEQ:
504         case TypedBinOp::TYPED_STRICTNOTEQ:
505             return VisitStringCompare(gate);
506         case TypedBinOp::TYPED_ADD:
507             return VisitStringAdd(gate);
508         default:
509             return Circuit::NullGate();
510     }
511 }
512 
VisitStringCompare(GateRef gate)513 GateRef NumberSpeculativeRetype::VisitStringCompare(GateRef gate)
514 {
515     if (IsRetype()) {
516         return SetOutputType(gate, GateType::BooleanType());
517     }
518 
519     Environment env(gate, circuit_, &builder_);
520     GateRef left = acc_.GetValueIn(gate, 0);
521     GateRef right = acc_.GetValueIn(gate, 1);
522     TypeInfo leftInfo = GetOutputTypeInfo(left);
523     TypeInfo rightInfo = GetOutputTypeInfo(right);
524     if (leftInfo == TypeInfo::CHAR && rightInfo == TypeInfo::CHAR) {
525         return Circuit::NullGate();
526     }
527     if (leftInfo == TypeInfo::CHAR) {
528         GateRef rep = builder_.ConvertCharToEcmaString(left);
529         acc_.ReplaceValueIn(gate, rep, 0);
530     }
531     if (rightInfo == TypeInfo::CHAR) {
532         GateRef rep =  builder_.ConvertCharToEcmaString(right);
533         acc_.ReplaceValueIn(gate, rep, 1);
534     }
535     return Circuit::NullGate();
536 }
537 
VisitStringAdd(GateRef gate)538 GateRef NumberSpeculativeRetype::VisitStringAdd(GateRef gate)
539 {
540     if (IsRetype()) {
541         return SetOutputType(gate, GateType::StringType());
542     }
543     if (IsConvert()) {
544         Environment env(gate, circuit_, &builder_);
545         size_t valueNum = acc_.GetNumValueIn(gate);
546         for (size_t i = 0; i < valueNum; ++i) {
547             GateRef input = acc_.GetValueIn(gate, i);
548             TypeInfo inputInfo = GetOutputTypeInfo(input);
549             if (inputInfo == TypeInfo::CHAR) {
550                 input = builder_.ConvertCharToEcmaString(input);
551             }
552             acc_.ReplaceValueIn(gate, input, i);
553         }
554     }
555     return Circuit::NullGate();
556 }
557 
GetOutputForPhi(GateRef gate,bool ignoreConstant)558 TypeInfo NumberSpeculativeRetype::GetOutputForPhi(GateRef gate, bool ignoreConstant)
559 {
560     size_t valueNum = acc_.GetNumValueIn(gate);
561     bool hasConstantInput = false;
562     TypeInfo tempType = TypeInfo::NONE;
563     for (size_t i = 0; i < valueNum; ++i) {
564         GateRef input = acc_.GetValueIn(gate, i);
565         TypeInfo inputInfo = GetOutputTypeInfo(input);
566         if (ignoreConstant && acc_.IsConstantNumber(input)) {
567             hasConstantInput = true;
568             continue;
569         }
570         if (inputInfo == TypeInfo::NONE) {
571             continue;
572         }
573         // use less general input as phi output
574         if (tempType == TypeInfo::NONE) {
575             tempType = inputInfo;
576         } else if (tempType != inputInfo) {
577             tempType = TypeInfo::TAGGED;
578             break;
579         }
580     }
581 
582     if (hasConstantInput && ignoreConstant && (tempType == TypeInfo::NONE || tempType == TypeInfo::CHAR)) {
583         return GetOutputForPhi(gate, false);
584     }
585     return tempType;
586 }
587 
VisitPhi(GateRef gate)588 GateRef NumberSpeculativeRetype::VisitPhi(GateRef gate)
589 {
590     if (IsRetype()) {
591         auto tempType = GetOutputForPhi(gate, true);
592         TypeInfo typeInfo = GetOutputTypeInfo(gate);
593         if (typeInfo != tempType) {
594             SetOutputTypeInfo(gate, tempType);
595             return gate;
596         }
597         return Circuit::NullGate();
598     }
599     ASSERT(IsConvert());
600     size_t valueNum = acc_.GetNumValueIn(gate);
601     auto merge = acc_.GetState(gate);
602     auto dependSelector = acc_.GetDependSelectorFromMerge(merge);
603     TypeInfo output = GetOutputTypeInfo(gate);
604     for (size_t i = 0; i < valueNum; ++i) {
605         GateRef input = acc_.GetValueIn(gate, i);
606         if (output == TypeInfo::TAGGED || output == TypeInfo::NONE) {
607             input = ConvertToTagged(input);
608         } else {
609             auto state = acc_.GetState(merge, i);
610             auto depend = acc_.GetDep(dependSelector, i);
611             Environment env(state, depend, {}, circuit_, &builder_);
612             input = ConvertTaggedToNJSValue(input, output);
613             acc_.ReplaceStateIn(merge, builder_.GetState(), i);
614             acc_.ReplaceDependIn(dependSelector, builder_.GetDepend(), i);
615         }
616         acc_.ReplaceValueIn(gate, input, i);
617     }
618     return Circuit::NullGate();
619 }
620 
ConvertTaggedToNJSValue(GateRef gate,TypeInfo output)621 GateRef NumberSpeculativeRetype::ConvertTaggedToNJSValue(GateRef gate, TypeInfo output)
622 {
623     TypeInfo curOutput = GetOutputTypeInfo(gate);
624     if (curOutput != TypeInfo::TAGGED) {
625         return gate;
626     }
627     switch (output) {
628         case TypeInfo::INT1:
629             return CheckAndConvertToBool(gate, GateType::BooleanType());
630         case TypeInfo::INT32:
631         case TypeInfo::UINT32:
632             return CheckAndConvertToInt32(gate, GateType::NumberType());
633         case TypeInfo::FLOAT64:
634             return CheckAndConvertToFloat64(gate, GateType::NumberType());
635         default:
636             LOG_COMPILER(FATAL) << "this branch is unreachable";
637             UNREACHABLE();
638             return Circuit::NullGate();
639     }
640 }
641 
VisitNumberBinaryOp(GateRef gate)642 GateRef NumberSpeculativeRetype::VisitNumberBinaryOp(GateRef gate)
643 {
644     TypedBinOp op = acc_.GetTypedBinaryOp(gate);
645     switch (op) {
646         case TypedBinOp::TYPED_ADD:
647         case TypedBinOp::TYPED_SUB:
648         case TypedBinOp::TYPED_MUL:
649         case TypedBinOp::TYPED_DIV:
650         case TypedBinOp::TYPED_MOD: {
651             return VisitNumberCalculate(gate);
652         }
653         case TypedBinOp::TYPED_LESS:
654         case TypedBinOp::TYPED_LESSEQ:
655         case TypedBinOp::TYPED_GREATER:
656         case TypedBinOp::TYPED_GREATEREQ:
657         case TypedBinOp::TYPED_EQ:
658         case TypedBinOp::TYPED_NOTEQ:
659         case TypedBinOp::TYPED_STRICTEQ:
660         case TypedBinOp::TYPED_STRICTNOTEQ: {
661             return VisitNumberCompare(gate);
662         }
663         case TypedBinOp::TYPED_SHL:
664         case TypedBinOp::TYPED_SHR:
665         case TypedBinOp::TYPED_ASHR:
666         case TypedBinOp::TYPED_AND:
667         case TypedBinOp::TYPED_OR:
668         case TypedBinOp::TYPED_XOR: {
669             return VisitNumberShiftAndLogical(gate);
670         }
671         default: {
672             TypedBinaryAccessor accessor(acc_.TryGetValue(gate));
673             const ParamType paramType = accessor.GetParamType();
674             return VisitNumberRelated(gate, paramType);
675         }
676     }
677 }
678 
VisitTypedUnaryOp(GateRef gate)679 GateRef NumberSpeculativeRetype::VisitTypedUnaryOp(GateRef gate)
680 {
681     Environment env(gate, circuit_, &builder_);
682     TypedUnOp Op = acc_.GetTypedUnAccessor(gate).GetTypedUnOp();
683     switch (Op) {
684         case TypedUnOp::TYPED_INC:
685         case TypedUnOp::TYPED_DEC:
686         case TypedUnOp::TYPED_NEG:
687             return VisitNumberMonocular(gate);
688         case TypedUnOp::TYPED_NOT:
689             return VisitNumberNot(gate);
690         case TypedUnOp::TYPED_ISFALSE:
691         case TypedUnOp::TYPED_ISTRUE:
692             return VisitIsTrueOrFalse(gate);
693         default: {
694             TypedUnaryAccessor accessor(acc_.TryGetValue(gate));
695             ParamType paramType = accessor.GetParamType();
696             return VisitNumberRelated(gate, paramType);
697         }
698     }
699 }
700 
VisitTypedConditionJump(GateRef gate)701 GateRef NumberSpeculativeRetype::VisitTypedConditionJump(GateRef gate)
702 {
703     Environment env(gate, circuit_, &builder_);
704     TypedJumpAccessor accessor(acc_.TryGetValue(gate));
705     ParamType type = accessor.GetParamType();
706     if (type.IsBooleanType()) {
707         return VisitBooleanJump(gate);
708     } else {
709         UNREACHABLE();
710         return Circuit::NullGate();
711     }
712 }
713 
VisitNumberCalculate(GateRef gate)714 GateRef NumberSpeculativeRetype::VisitNumberCalculate(GateRef gate)
715 {
716     if (IsRetype()) {
717         TypedBinaryAccessor accessor(acc_.TryGetValue(gate));
718         const ParamType paramType = accessor.GetParamType();
719         ASSERT(paramType.HasNumberType());
720         return SetOutputType(gate, paramType);
721     } else if (IsConvert()) {
722         Environment env(gate, circuit_, &builder_);
723         ConvertForNumberBinaryOp(gate);
724     }
725     return Circuit::NullGate();
726 }
727 
VisitNumberCompare(GateRef gate)728 GateRef NumberSpeculativeRetype::VisitNumberCompare(GateRef gate)
729 {
730     if (IsRetype()) {
731         return SetOutputType(gate, GateType::BooleanType());
732     }
733     if (IsConvert()) {
734         Environment env(gate, circuit_, &builder_);
735         ConvertForNumberCompareOp(gate);
736     }
737     return Circuit::NullGate();
738 }
739 
VisitNumberShiftAndLogical(GateRef gate)740 GateRef NumberSpeculativeRetype::VisitNumberShiftAndLogical(GateRef gate)
741 {
742     if (IsRetype()) {
743         return SetOutputType(gate, GateType::IntType());
744     }
745     if (IsConvert()) {
746         Environment env(gate, circuit_, &builder_);
747         ConvertForNumberShiftAndLogicalOperator(gate);
748     }
749     return Circuit::NullGate();
750 }
751 
VisitNumberMonocular(GateRef gate)752 GateRef NumberSpeculativeRetype::VisitNumberMonocular(GateRef gate)
753 {
754     TypedUnaryAccessor accessor(acc_.TryGetValue(gate));
755     ParamType type = accessor.GetParamType();
756     ASSERT(type.HasNumberType());
757     if (type.IsIntType()) {
758         return VisitIntMonocular(gate);
759     } else {
760         return VisitDoubleMonocular(gate);
761     }
762 }
763 
VisitIntMonocular(GateRef gate)764 GateRef NumberSpeculativeRetype::VisitIntMonocular(GateRef gate)
765 {
766     if (IsRetype()) {
767         return SetOutputType(gate, GateType::IntType());
768     }
769 
770     if (IsConvert()) {
771         GateRef value = acc_.GetValueIn(gate, 0);
772         acc_.ReplaceValueIn(gate, CheckAndConvertToInt32(value, GateType::IntType()), 0);
773         acc_.ReplaceStateIn(gate, builder_.GetState());
774         acc_.ReplaceDependIn(gate, builder_.GetDepend());
775     }
776     return Circuit::NullGate();
777 }
778 
VisitDoubleMonocular(GateRef gate)779 GateRef NumberSpeculativeRetype::VisitDoubleMonocular(GateRef gate)
780 {
781     if (IsRetype()) {
782         return SetOutputType(gate, GateType::DoubleType());
783     }
784 
785     if (IsConvert()) {
786         TypedUnaryAccessor accessor(acc_.TryGetValue(gate));
787         ParamType paramType = accessor.GetParamType();
788         GateRef value = acc_.GetValueIn(gate, 0);
789         GateType valueType = GateType::NumberType();
790         if (paramType.IsIntType()) {
791             valueType = GateType::IntType();
792         } else if (paramType.IsDoubleType()) {
793             valueType = GateType::DoubleType();
794         }
795         acc_.ReplaceValueIn(gate, CheckAndConvertToFloat64(value, valueType), 0);
796         acc_.ReplaceStateIn(gate, builder_.GetState());
797         acc_.ReplaceDependIn(gate, builder_.GetDepend());
798     }
799     return Circuit::NullGate();
800 }
801 
VisitIsTrueOrFalse(GateRef gate)802 GateRef NumberSpeculativeRetype::VisitIsTrueOrFalse(GateRef gate)
803 {
804     TypedUnaryAccessor accessor(acc_.TryGetValue(gate));
805     ParamType paramType = accessor.GetParamType();
806     ASSERT(paramType.HasNumberType() || paramType.IsBooleanType());
807     if (IsRetype()) {
808         return SetOutputType(gate, GateType::BooleanType());
809     }
810     if (IsConvert()) {
811         Environment env(gate, circuit_, &builder_);
812         GateRef value = acc_.GetValueIn(gate, 0);
813         GateType valueType = GateType::NumberType();
814         // NOTICE-PGO: wx support undefined
815         if (paramType.IsIntType()) {
816             valueType = GateType::IntType();
817         } else if (paramType.IsDoubleType()) {
818             valueType = GateType::DoubleType();
819         } else if (paramType.IsBooleanType()) {
820             valueType = GateType::BooleanType();
821         }
822         auto input = CheckAndConvertToBool(value, valueType);
823         ResizeAndSetTypeInfo(input, TypeInfo::INT1);
824         acc_.ReplaceValueIn(gate, input, 0);
825         acc_.ReplaceStateIn(gate, builder_.GetState());
826         acc_.ReplaceDependIn(gate, builder_.GetDepend());
827     }
828     return Circuit::NullGate();
829 }
830 
VisitNumberNot(GateRef gate)831 GateRef NumberSpeculativeRetype::VisitNumberNot(GateRef gate)
832 {
833     TypedUnaryAccessor accessor(acc_.TryGetValue(gate));
834     ParamType paramType = accessor.GetParamType();
835     ASSERT(paramType.HasNumberType());
836     if (IsRetype()) {
837         return SetOutputType(gate, GateType::IntType());
838     }
839     if (IsConvert()) {
840         Environment env(gate, circuit_, &builder_);
841         GateRef value = acc_.GetValueIn(gate, 0);
842         GateType valueType = GateType::NumberType();
843         if (paramType.IsIntType()) {
844             valueType = GateType::IntType();
845         } else if (paramType.IsDoubleType()) {
846             valueType = GateType::DoubleType();
847         }
848         acc_.ReplaceValueIn(gate,
849             CheckAndConvertToInt32(value, valueType, ConvertSupport::ENABLE, OpType::SHIFT_AND_LOGICAL, false), 0);
850         acc_.ReplaceStateIn(gate, builder_.GetState());
851         acc_.ReplaceDependIn(gate, builder_.GetDepend());
852     }
853     return Circuit::NullGate();
854 }
855 
VisitBooleanJump(GateRef gate)856 GateRef NumberSpeculativeRetype::VisitBooleanJump(GateRef gate)
857 {
858     if (IsRetype()) {
859         return SetOutputType(gate, GateType::AnyType());
860     }
861     if (IsConvert()) {
862         Environment env(gate, circuit_, &builder_);
863         GateRef value = acc_.GetValueIn(gate, 0);
864         GateRef input = Circuit::NullGate();
865         if (GetOutputTypeInfo(value) == TypeInfo::TAGGED) {
866             // use TaggedIsTrue
867             input = builder_.ConvertTaggedBooleanToBool(value);
868         } else {
869             input = CheckAndConvertToBool(value, GateType::BooleanType());
870         }
871         ResizeAndSetTypeInfo(input, TypeInfo::INT1);
872         acc_.ReplaceValueIn(gate, input, 0);
873         acc_.ReplaceStateIn(gate, builder_.GetState());
874         acc_.ReplaceDependIn(gate, builder_.GetDepend());
875     }
876     return Circuit::NullGate();
877 }
878 
VisitNumberRelated(GateRef gate,ParamType paramType)879 GateRef NumberSpeculativeRetype::VisitNumberRelated(GateRef gate, ParamType paramType)
880 {
881     if (IsRetype()) {
882         return SetOutputType(gate, GateType::NumberType());
883     }
884     if (IsConvert()) {
885         Environment env(gate, circuit_, &builder_);
886         size_t valueNum = acc_.GetNumValueIn(gate);
887         GateType inputType = GateType::AnyType();
888         if (paramType.IsIntType() || paramType.IsIntOverflowType()) {
889             inputType = GateType::IntType();
890         } else if (paramType.IsDoubleType()) {
891             inputType = GateType::DoubleType();
892         } else if (paramType.IsNumberType()) {
893             inputType = GateType::NumberType();
894         } else if (paramType.IsBooleanType()) {
895             inputType = GateType::BooleanType();
896         }
897         for (size_t i = 0; i < valueNum; ++i) {
898             GateRef input = acc_.GetValueIn(gate, i);
899             if (paramType.HasNumberType() || paramType.IsBooleanType()) {
900                 acc_.ReplaceValueIn(gate, CheckAndConvertToTagged(input, inputType, ConvertToNumber::BOOL_ONLY), i);
901             }
902         }
903         acc_.ReplaceStateIn(gate, builder_.GetState());
904         acc_.ReplaceDependIn(gate, builder_.GetDepend());
905     }
906     return Circuit::NullGate();
907 }
908 
VisitFrameState(GateRef gate)909 GateRef NumberSpeculativeRetype::VisitFrameState(GateRef gate)
910 {
911     if (IsRetype()) {
912         return SetOutputType(gate, GateType::AnyType());
913     }
914     GateRef frameValue = acc_.GetFrameValue(gate);
915     size_t numValueIn = acc_.GetNumValueIn(frameValue);
916     for (size_t i = 0; i < numValueIn; i++) {
917         GateRef val = acc_.GetValueIn(frameValue, i);
918         TypeInfo output = GetOutputTypeInfo(val);
919         // The convert of char type needs to be converted into ecmastring, and other types of variables are converted
920         // in the ir builder stage. Because the typeinfo::char information will be lost after passing this pass.
921         switch (output) {
922             case TypeInfo::CHAR:
923                 acc_.ReplaceValueIn(frameValue, ConvertToTagged(val), i);
924                 break;
925             case TypeInfo::NONE:
926             case TypeInfo::INT1:
927             case TypeInfo::INT32:
928             case TypeInfo::UINT32:
929             case TypeInfo::FLOAT64:
930             case TypeInfo::TAGGED:
931                 break;
932             default:
933                 // Other new types are intercepted here. Please confirm that the new types will not allocate heap
934                 // objects after ConvertToTagged occurs. This check is skipped after confirmation.
935                 LOG_ECMA(FATAL) << "Please check new kind of TypeInfo";
936                 UNREACHABLE();
937                 break;
938         }
939     }
940     return Circuit::NullGate();
941 }
942 
VisitOthers(GateRef gate,GateType outputType)943 GateRef NumberSpeculativeRetype::VisitOthers(GateRef gate, GateType outputType)
944 {
945     if (IsRetype()) {
946         return SetOutputType(gate, outputType);
947     }
948     if (IsConvert()) {
949         size_t valueNum = acc_.GetNumValueIn(gate);
950         for (size_t i = 0; i < valueNum; ++i) {
951             GateRef input = acc_.GetValueIn(gate, i);
952             acc_.ReplaceValueIn(gate, ConvertToTagged(input), i);
953         }
954     }
955     return Circuit::NullGate();
956 }
957 
VisitOthersWithoutConvert(GateRef gate,GateType outputType)958 GateRef NumberSpeculativeRetype::VisitOthersWithoutConvert(GateRef gate, GateType outputType)
959 {
960     if (IsRetype()) {
961         return SetOutputType(gate, outputType);
962     }
963     return Circuit::NullGate();
964 }
965 
VisitWithConstantValue(GateRef gate,size_t ignoreIndex)966 GateRef NumberSpeculativeRetype::VisitWithConstantValue(GateRef gate, size_t ignoreIndex)
967 {
968     if (IsRetype()) {
969         return SetOutputType(gate, GateType::AnyType());
970     }
971     if (IsConvert()) {
972         size_t valueNum = acc_.GetNumValueIn(gate);
973         for (size_t i = 0; i < valueNum; ++i) {
974             if (i == ignoreIndex) {
975                 continue;
976             }
977             GateRef input = acc_.GetValueIn(gate, i);
978             acc_.ReplaceValueIn(gate, ConvertToTagged(input), i);
979         }
980     }
981     return Circuit::NullGate();
982 }
983 
CheckAndConvertToBool(GateRef gate,GateType gateType)984 GateRef NumberSpeculativeRetype::CheckAndConvertToBool(GateRef gate, GateType gateType)
985 {
986     TypeInfo output = GetOutputTypeInfo(gate);
987     switch (output) {
988         case TypeInfo::INT1:
989             return gate;
990         case TypeInfo::INT32:
991             return builder_.ConvertInt32ToBool(gate);
992         case TypeInfo::UINT32:
993             return builder_.ConvertUInt32ToBool(gate);
994         case TypeInfo::FLOAT64:
995             return builder_.ConvertFloat64ToBool(gate);
996         case TypeInfo::CHAR:
997             // CHAR refers to string of length 1, while only empty string converts to false in a boolean context.
998             return builder_.Boolean(true);
999         case TypeInfo::NONE:
1000         case TypeInfo::TAGGED: {
1001             if (gateType.IsBooleanType()) {
1002                 return builder_.CheckTaggedBooleanAndConvertToBool(gate);
1003             } else if (gateType.IsUndefinedType()) {
1004                 return builder_.CheckUndefinedAndConvertToBool(gate);
1005             } else if (gateType.IsNullType()) {
1006                 return builder_.CheckNullAndConvertToBool(gate);
1007             } else {
1008                 ASSERT(gateType.IsNumberType());
1009                 return builder_.CheckTaggedNumberAndConvertToBool(gate);
1010             }
1011         }
1012         default: {
1013             UNREACHABLE();
1014             return Circuit::NullGate();
1015         }
1016     }
1017 }
1018 
ConvertForNumberBinaryOp(GateRef gate)1019 void NumberSpeculativeRetype::ConvertForNumberBinaryOp(GateRef gate)
1020 {
1021     TypedBinaryAccessor accessor(acc_.TryGetValue(gate));
1022     const ParamType paramType = accessor.GetParamType();
1023     ASSERT(paramType.HasNumberType());
1024     if (paramType.IsIntType()) {
1025         ConvertForIntOperator(gate, GateType::IntType(), GateType::IntType());
1026     } else if (paramType.IsIntOverflowType()) {
1027         ConvertForDoubleOperator(gate, GateType::IntType(), GateType::IntType());
1028     } else if (paramType.IsDoubleType()) {
1029         ConvertForDoubleOperator(gate, GateType::DoubleType(), GateType::DoubleType());
1030     } else if (paramType.IsNumberType()) {
1031         ConvertForDoubleOperator(gate, GateType::NumberType(), GateType::NumberType());
1032     }
1033 }
1034 
ConvertForNumberCompareOp(GateRef gate)1035 void NumberSpeculativeRetype::ConvertForNumberCompareOp(GateRef gate)
1036 {
1037     TypedBinaryAccessor accessor(acc_.TryGetValue(gate));
1038     const ParamType paramType = accessor.GetParamType();
1039     ASSERT(paramType.HasNumberType());
1040     ASSERT(!paramType.IsIntOverflowType());
1041     if (paramType.IsIntType()) {
1042         ConvertForIntOperator(gate, GateType::IntType(), GateType::IntType());
1043     } else {
1044         ConvertForDoubleOperator(gate, GateType::NumberType(), GateType::NumberType());
1045     }
1046 }
1047 
ConvertForNumberShiftAndLogicalOperator(GateRef gate)1048 void NumberSpeculativeRetype::ConvertForNumberShiftAndLogicalOperator(GateRef gate)
1049 {
1050     TypedBinaryAccessor accessor(acc_.TryGetValue(gate));
1051     const ParamType paramType = accessor.GetParamType();
1052     ASSERT(paramType.HasNumberType());
1053     if (paramType.IsIntType()) {
1054         ConvertForShiftAndLogicalOperator(gate, GateType::IntType(), GateType::IntType());
1055     } else {
1056         ConvertForShiftAndLogicalOperator(gate, GateType::NumberType(), GateType::NumberType());
1057     }
1058 }
1059 
ConvertForIntOperator(GateRef gate,GateType leftType,GateType rightType)1060 void NumberSpeculativeRetype::ConvertForIntOperator(GateRef gate, GateType leftType, GateType rightType)
1061 {
1062     GateRef left = acc_.GetValueIn(gate, 0);
1063     GateRef right = acc_.GetValueIn(gate, 1);
1064 
1065     acc_.ReplaceValueIn(gate, CheckAndConvertToInt32(left, leftType), 0);
1066     acc_.ReplaceValueIn(gate, CheckAndConvertToInt32(right, rightType), 1);
1067 
1068     acc_.ReplaceStateIn(gate, builder_.GetState());
1069     acc_.ReplaceDependIn(gate, builder_.GetDepend());
1070 }
1071 
ConvertForShiftAndLogicalOperator(GateRef gate,GateType leftType,GateType rightType)1072 void NumberSpeculativeRetype::ConvertForShiftAndLogicalOperator(GateRef gate, GateType leftType, GateType rightType)
1073 {
1074     GateRef left = acc_.GetValueIn(gate, 0);
1075     GateRef right = acc_.GetValueIn(gate, 1);
1076     GateRef cLeft = CheckAndConvertToInt32(left, leftType, ConvertSupport::ENABLE, OpType::SHIFT_AND_LOGICAL, false);
1077     GateRef cRight = CheckAndConvertToInt32(right, rightType, ConvertSupport::ENABLE, OpType::SHIFT_AND_LOGICAL, false);
1078 
1079     acc_.ReplaceValueIn(gate, cLeft, 0);
1080     acc_.ReplaceValueIn(gate, cRight, 1);
1081 
1082     acc_.ReplaceStateIn(gate, builder_.GetState());
1083     acc_.ReplaceDependIn(gate, builder_.GetDepend());
1084 }
1085 
ConvertForDoubleOperator(GateRef gate,GateType leftType,GateType rightType)1086 void NumberSpeculativeRetype::ConvertForDoubleOperator(GateRef gate, GateType leftType, GateType rightType)
1087 {
1088     GateRef left = acc_.GetValueIn(gate, 0);
1089     GateRef right = acc_.GetValueIn(gate, 1);
1090 
1091     acc_.ReplaceValueIn(gate, CheckAndConvertToFloat64(left, leftType), 0);
1092     acc_.ReplaceValueIn(gate, CheckAndConvertToFloat64(right, rightType), 1);
1093 
1094     acc_.ReplaceStateIn(gate, builder_.GetState());
1095     acc_.ReplaceDependIn(gate, builder_.GetDepend());
1096 }
1097 
TryConvertConstant(GateRef gate,bool needInt32)1098 GateRef NumberSpeculativeRetype::TryConvertConstant(GateRef gate, bool needInt32)
1099 {
1100     if (acc_.GetOpCode(gate) != OpCode::CONSTANT) {
1101         return Circuit::NullGate();
1102     }
1103 
1104     if (acc_.GetGateType(gate).IsNJSValueType()) {
1105         MachineType mType = acc_.GetMachineType(gate);
1106         if (mType == MachineType::I32) {
1107             int32_t rawValue = acc_.GetInt32FromConstant(gate);
1108             return needInt32 ? builder_.Int32(rawValue) : builder_.Double(static_cast<double>(rawValue));
1109         } else if (mType == MachineType::F64 && !needInt32) {
1110             double rawValue = acc_.GetFloat64FromConstant(gate);
1111             return builder_.Double(rawValue);
1112         } else {
1113             return Circuit::NullGate();
1114         }
1115     }
1116 
1117     JSTaggedValue value(acc_.GetConstantValue(gate));
1118     if (value.IsInt()) {
1119         int32_t rawValue = value.GetInt();
1120         return needInt32 ? builder_.Int32(rawValue) : builder_.Double(static_cast<double>(rawValue));
1121     } else if (value.IsDouble() && !needInt32) {
1122         double rawValue = value.GetDouble();
1123         return builder_.Double(rawValue);
1124     }
1125     return Circuit::NullGate();
1126 }
1127 
TryConvertConstantToInt32(GateRef gate)1128 GateRef NumberSpeculativeRetype::TryConvertConstantToInt32(GateRef gate)
1129 {
1130     if (acc_.GetOpCode(gate) != OpCode::CONSTANT) {
1131         return Circuit::NullGate();
1132     }
1133 
1134     if (acc_.GetGateType(gate).IsNJSValueType()) {
1135         MachineType mType = acc_.GetMachineType(gate);
1136         if (mType == MachineType::I32) {
1137             int32_t rawValue = acc_.GetInt32FromConstant(gate);
1138             return builder_.Int32(rawValue);
1139         } else if (mType == MachineType::F64) {
1140             double rawValue = acc_.GetFloat64FromConstant(gate);
1141             int32_t int32Value = base::NumberHelper::DoubleInRangeInt32(rawValue);
1142             return builder_.Int32(int32Value);
1143         } else {
1144             return Circuit::NullGate();
1145         }
1146     }
1147 
1148     JSTaggedValue value(acc_.GetConstantValue(gate));
1149     if (value.IsInt()) {
1150         int32_t rawValue = value.GetInt();
1151         return builder_.Int32(rawValue);
1152     } else if (value.IsDouble()) {
1153         double rawValue = value.GetDouble();
1154         int32_t int32Value = base::NumberHelper::DoubleInRangeInt32(rawValue);
1155         return builder_.Int32(int32Value);
1156     }
1157     return Circuit::NullGate();
1158 }
1159 
CheckTaggedAndConvertToInt32(GateRef gate,GateType gateType,OpType type)1160 GateRef NumberSpeculativeRetype::CheckTaggedAndConvertToInt32(GateRef gate, GateType gateType, OpType type)
1161 {
1162     GateRef result = Circuit::NullGate();
1163     if (gateType.IsIntType()) {
1164         result = builder_.CheckTaggedIntAndConvertToInt32(gate);
1165     } else if (gateType.IsDoubleType()) {
1166         result = builder_.CheckTaggedDoubleAndConvertToInt32(gate);
1167     } else if (gateType.IsNullType()) {
1168         result = builder_.CheckNullAndConvertToInt32(gate);
1169     } else if (gateType.IsBooleanType()) {
1170         result = builder_.CheckTaggedBooleanAndConvertToInt32(gate);
1171     } else if (gateType.IsUndefinedType()) {
1172         if (type == OpType::SHIFT_AND_LOGICAL) {
1173             result = builder_.CheckUndefinedAndConvertToInt32(gate);
1174         } else {
1175             LOG_ECMA(FATAL) << "undefined cannot convert to int type";
1176         }
1177     } else {
1178         ASSERT(gateType.IsNumberType() || gateType.IsAnyType());
1179         result = builder_.CheckTaggedNumberAndConvertToInt32(gate);
1180     }
1181     return result;
1182 }
1183 
CheckAndConvertToInt32(GateRef gate,GateType gateType,ConvertSupport support,OpType type,bool needCheckFloat64)1184 GateRef NumberSpeculativeRetype::CheckAndConvertToInt32(GateRef gate, GateType gateType, ConvertSupport support,
1185                                                         OpType type, bool needCheckFloat64)
1186 {
1187     auto result = TryConvertConstant(gate, true);
1188     if (result != Circuit::NullGate()) {
1189         acc_.DeleteGateIfNoUse(gate);
1190         ResizeAndSetTypeInfo(result, TypeInfo::INT32);
1191         return result;
1192     }
1193     TypeInfo output = GetOutputTypeInfo(gate);
1194     switch (output) {
1195         case TypeInfo::INT1:
1196             result = builder_.ConvertBoolToInt32(gate, support);
1197             break;
1198         case TypeInfo::CHAR: {
1199             result = builder_.ConvertCharToInt32(gate);
1200             break;
1201         }
1202         case TypeInfo::INT32:
1203             return gate;
1204         case TypeInfo::UINT32: {
1205             if (type != OpType::SHIFT_AND_LOGICAL) {
1206                 result = builder_.CheckUInt32AndConvertToInt32(gate);
1207             } else {
1208                 result = gate;
1209             }
1210             break;
1211         }
1212         case TypeInfo::FLOAT64: {
1213             if (needCheckFloat64) {
1214                 result = builder_.CheckFloat64ConvertToInt32Legally(gate);
1215             } else {
1216                 result = builder_.ConvertFloat64ToInt32(gate);
1217             }
1218             break;
1219         }
1220         case TypeInfo::HOLE_INT:
1221             result = builder_.CheckHoleIntAndConvertToInt32(gate);
1222             break;
1223         case TypeInfo::HOLE_DOUBLE:
1224             result = builder_.CheckHoleDoubleAndConvertToInt32(gate);
1225             break;
1226         case TypeInfo::NONE:
1227         case TypeInfo::TAGGED: {
1228             result = CheckTaggedAndConvertToInt32(gate, gateType, type);
1229             break;
1230         }
1231         default: {
1232             LOG_ECMA(FATAL) << "this branch is unreachable";
1233             UNREACHABLE();
1234             return Circuit::NullGate();
1235         }
1236     }
1237     ResizeAndSetTypeInfo(result, TypeInfo::INT32);
1238     return result;
1239 }
1240 
CheckBoundAndConvertToInt32(GateRef gate,ConvertSupport support,OpType type)1241 GateRef NumberSpeculativeRetype::CheckBoundAndConvertToInt32(GateRef gate, ConvertSupport support, OpType type)
1242 {
1243     auto result = TryConvertConstantToInt32(gate);
1244     GateType gateType = acc_.GetGateType(gate);
1245     if (result != Circuit::NullGate()) {
1246         acc_.DeleteGateIfNoUse(gate);
1247         ResizeAndSetTypeInfo(result, TypeInfo::INT32);
1248         return result;
1249     }
1250     TypeInfo output = GetOutputTypeInfo(gate);
1251     switch (output) {
1252         case TypeInfo::INT1:
1253             result = builder_.ConvertBoolToInt32(gate, support);
1254             break;
1255         case TypeInfo::CHAR: {
1256             result = builder_.ConvertCharToInt32(gate);
1257             break;
1258         }
1259         case TypeInfo::INT32:
1260             return gate;
1261         case TypeInfo::UINT32: {
1262             result = builder_.CheckUInt32AndConvertToInt32(gate);
1263             break;
1264         }
1265         case TypeInfo::FLOAT64: {
1266             result = builder_.DoubleCheckINFInRangeInt32(gate);
1267             break;
1268         }
1269         case TypeInfo::HOLE_INT:
1270             result = builder_.CheckHoleIntAndConvertToInt32(gate);
1271             break;
1272         case TypeInfo::HOLE_DOUBLE:
1273             result = builder_.CheckHoleDoubleAndConvertToInt32(gate);
1274             break;
1275         case TypeInfo::NONE:
1276         case TypeInfo::TAGGED: {
1277             if (gateType.IsIntType()) {
1278                 result = builder_.CheckTaggedIntAndConvertToInt32(gate);
1279             } else if (gateType.IsDoubleType()) {
1280                 GateRef doubleValue = builder_.CheckTaggedDoubleAndConvertToFloat64(gate);
1281                 result = builder_.DoubleInRangeInt32(doubleValue);
1282             } else if (gateType.IsNullType()) {
1283                 result = builder_.CheckNullAndConvertToInt32(gate);
1284             } else if (gateType.IsBooleanType()) {
1285                 result = builder_.CheckTaggedBooleanAndConvertToInt32(gate);
1286             } else if (gateType.IsUndefinedType()) {
1287                 if (type == OpType::SHIFT_AND_LOGICAL) {
1288                     result = builder_.CheckUndefinedAndConvertToInt32(gate);
1289                 } else {
1290                     LOG_ECMA(FATAL) << "undefined cannot convert to int type";
1291                 }
1292             } else {
1293                 GateRef doubleValue = builder_.CheckTaggedNumberAndConvertToFloat64(gate);
1294                 result = builder_.DoubleInRangeInt32(doubleValue);
1295             }
1296             break;
1297         }
1298         default: {
1299             LOG_ECMA(FATAL) << "this branch is unreachable";
1300             UNREACHABLE();
1301             return Circuit::NullGate();
1302         }
1303     }
1304     ResizeAndSetTypeInfo(result, TypeInfo::INT32);
1305     return result;
1306 }
1307 
CheckAndConvertToFloat64(GateRef gate,GateType gateType,ConvertToNumber convert)1308 GateRef NumberSpeculativeRetype::CheckAndConvertToFloat64(GateRef gate, GateType gateType,
1309                                                           ConvertToNumber convert)
1310 {
1311     auto result = TryConvertConstant(gate, false);
1312     if (result != Circuit::NullGate()) {
1313         acc_.DeleteGateIfNoUse(gate);
1314         ResizeAndSetTypeInfo(result, TypeInfo::FLOAT64);
1315         return result;
1316     }
1317     TypeInfo output = GetOutputTypeInfo(gate);
1318     switch (output) {
1319         case TypeInfo::INT1:
1320             result = builder_.ConvertBoolToFloat64(gate, ToConvertSupport(convert));
1321             break;
1322         case TypeInfo::CHAR: {
1323             result = builder_.ConvertCharToDouble(gate);
1324             break;
1325         }
1326         case TypeInfo::INT32:
1327             result = builder_.ConvertInt32ToFloat64(gate);
1328             break;
1329         case TypeInfo::UINT32:
1330             result = builder_.ConvertUInt32ToFloat64(gate);
1331             break;
1332         case TypeInfo::FLOAT64:
1333             return gate;
1334         case TypeInfo::HOLE_INT:
1335             result = builder_.CheckHoleIntAndConvertToFloat64(gate);
1336             break;
1337         case TypeInfo::HOLE_DOUBLE:
1338             result = builder_.CheckHoleDoubleAndConvertToFloat64(gate);
1339             break;
1340         case TypeInfo::NONE:
1341         case TypeInfo::TAGGED: {
1342             if (gateType.IsIntType()) {
1343                 result = builder_.CheckTaggedIntAndConvertToFloat64(gate);
1344             } else if (gateType.IsDoubleType()) {
1345                 result = builder_.CheckTaggedDoubleAndConvertToFloat64(gate);
1346             } else if (gateType.IsNullType()) {
1347                 result = builder_.CheckNullAndConvertToFloat64(gate);
1348             } else if (gateType.IsBooleanType()) {
1349                 result = builder_.CheckTaggedBooleanAndConvertToFloat64(gate);
1350             } else if (gateType.IsUndefinedType()) {
1351                 result = builder_.CheckUndefinedAndConvertToFloat64(gate);
1352             } else {
1353                 if (convert == ConvertToNumber::ALL) {
1354                     GateRef glue = acc_.GetGlueFromArgList();
1355                     GateRef number = builder_.ToNumber(glue, gate, glue);
1356                     ResizeAndSetTypeInfo(number, TypeInfo::TAGGED);
1357                     result = builder_.GetDoubleOfTNumber(number);
1358                 } else {
1359                     result = builder_.CheckTaggedNumberAndConvertToFloat64(gate);
1360                 }
1361             }
1362             break;
1363         }
1364         default: {
1365             LOG_ECMA(FATAL) << "this branch is unreachable";
1366             UNREACHABLE();
1367             return Circuit::NullGate();
1368         }
1369     }
1370     ResizeAndSetTypeInfo(result, TypeInfo::FLOAT64);
1371     return result;
1372 }
1373 
CheckAndConvertToTagged(GateRef gate,GateType gateType,ConvertToNumber convert)1374 GateRef NumberSpeculativeRetype::CheckAndConvertToTagged(GateRef gate, GateType gateType, ConvertToNumber convert)
1375 {
1376     TypeInfo output = GetOutputTypeInfo(gate);
1377     switch (output) {
1378         case TypeInfo::INT1: {
1379             if (gateType.IsNumberType() && convert != ConvertToNumber::DISABLE) {
1380                 return builder_.ConvertInt32ToTaggedInt(builder_.BooleanToInt32(gate));
1381             }
1382             return builder_.ConvertBoolToTaggedBoolean(gate);
1383         }
1384         case TypeInfo::INT32:
1385             return builder_.ConvertInt32ToTaggedInt(gate);
1386         case TypeInfo::UINT32:
1387             return builder_.ConvertUInt32ToTaggedNumber(gate);
1388         case TypeInfo::FLOAT64:
1389             return builder_.ConvertFloat64ToTaggedDouble(gate);
1390         case TypeInfo::CHAR:
1391             return builder_.ConvertCharToEcmaString(gate);
1392         case TypeInfo::HOLE_INT:
1393             return builder_.CheckHoleIntAndConvertToTaggedInt(gate);
1394         case TypeInfo::HOLE_DOUBLE:
1395             return builder_.CheckHoleDoubleAndConvertToTaggedDouble(gate);
1396         case TypeInfo::NONE:
1397         case TypeInfo::TAGGED: {
1398             if (convert == ConvertToNumber::ALL) {
1399                 // Convert if not number
1400                 ASSERT(gateType.IsNumberType());
1401                 GateRef glue = acc_.GetGlueFromArgList();
1402                 GateRef ret = builder_.ToNumber(glue, gate, glue);
1403                 ResizeAndSetTypeInfo(ret, TypeInfo::TAGGED);
1404                 return ret;
1405             }
1406             // Deoptimize if not number
1407             ASSERT(gateType.IsNumberType() || gateType.IsBooleanType());
1408             builder_.TryPrimitiveTypeCheck(gateType, gate);
1409             return gate;
1410         }
1411         default:
1412             LOG_ECMA(FATAL) << "this branch is unreachable";
1413             UNREACHABLE();
1414             return Circuit::NullGate();
1415     }
1416 }
1417 
ConvertToTagged(GateRef gate)1418 GateRef NumberSpeculativeRetype::ConvertToTagged(GateRef gate)
1419 {
1420     TypeInfo output = GetOutputTypeInfo(gate);
1421     switch (output) {
1422         case TypeInfo::INT1:
1423             return builder_.ConvertBoolToTaggedBoolean(gate);
1424         case TypeInfo::INT32:
1425             return builder_.ConvertInt32ToTaggedInt(gate);
1426         case TypeInfo::UINT32:
1427             return builder_.ConvertUInt32ToTaggedNumber(gate);
1428         case TypeInfo::FLOAT64:
1429             return builder_.ConvertFloat64ToTaggedDouble(gate);
1430         case TypeInfo::CHAR:
1431             return builder_.ConvertCharToEcmaString(gate);
1432         case TypeInfo::HOLE_INT:
1433             return builder_.ConvertSpecialHoleIntToTagged(gate);
1434         case TypeInfo::HOLE_DOUBLE:
1435             return builder_.ConvertSpecialHoleDoubleToTagged(gate);
1436         case TypeInfo::NONE:
1437         case TypeInfo::TAGGED: {
1438             return gate;
1439         }
1440         default:
1441             LOG_ECMA(FATAL) << "this branch is unreachable";
1442             UNREACHABLE();
1443             return Circuit::NullGate();
1444     }
1445 }
1446 
VisitRangeCheckPredicate(GateRef gate)1447 GateRef NumberSpeculativeRetype::VisitRangeCheckPredicate(GateRef gate)
1448 {
1449     if (IsRetype()) {
1450         return SetOutputType(gate, GateType::IntType());
1451     }
1452 
1453     if (IsConvert()) {
1454         Environment env(gate, circuit_, &builder_);
1455         GateRef value0 = acc_.GetValueIn(gate, 0);
1456         GateRef value1 = acc_.GetValueIn(gate, 1);
1457         GateType value0Type = acc_.GetGateType(value0);
1458         GateType value1Type = acc_.GetGateType(value1);
1459         acc_.ReplaceValueIn(gate, CheckAndConvertToInt32(value0, value0Type, ConvertSupport::ENABLE, OpType::NORMAL,
1460             false), 0);
1461         acc_.ReplaceValueIn(gate, CheckAndConvertToInt32(value1, value1Type, ConvertSupport::ENABLE, OpType::NORMAL,
1462             false), 1);
1463 
1464         acc_.ReplaceStateIn(gate, builder_.GetState());
1465         acc_.ReplaceDependIn(gate, builder_.GetDepend());
1466     }
1467 
1468     return Circuit::NullGate();
1469 }
1470 
VisitIndexCheck(GateRef gate)1471 GateRef NumberSpeculativeRetype::VisitIndexCheck(GateRef gate)
1472 {
1473     if (IsRetype()) {
1474         return SetOutputType(gate, GateType::IntType());
1475     }
1476 
1477     if (IsConvert()) {
1478         Environment env(gate, circuit_, &builder_);
1479         GateRef receiver = acc_.GetValueIn(gate, 0);
1480         GateRef index = acc_.GetValueIn(gate, 1);
1481         GateType receiverType = acc_.GetGateType(receiver);
1482         GateType indexType = acc_.GetGateType(index);
1483         if (indexType.IsAnyType()) {
1484             indexType = GateType::IntType();
1485         }
1486         acc_.ReplaceValueIn(gate, CheckAndConvertToInt32(receiver, receiverType, ConvertSupport::ENABLE, OpType::NORMAL,
1487             false), 0);
1488         acc_.ReplaceValueIn(gate, CheckAndConvertToInt32(index, indexType, ConvertSupport::ENABLE, OpType::NORMAL,
1489             false), 1);
1490 
1491         acc_.ReplaceStateIn(gate, builder_.GetState());
1492         acc_.ReplaceDependIn(gate, builder_.GetDepend());
1493     }
1494 
1495     return Circuit::NullGate();
1496 }
1497 
VisitLoadArrayLength(GateRef gate)1498 GateRef NumberSpeculativeRetype::VisitLoadArrayLength(GateRef gate)
1499 {
1500     if (IsRetype()) {
1501         return SetOutputType(gate, GateType::IntType());
1502     }
1503 
1504     return Circuit::NullGate();
1505 }
1506 
VisitLoadStringLength(GateRef gate)1507 GateRef NumberSpeculativeRetype::VisitLoadStringLength(GateRef gate)
1508 {
1509     if (IsRetype()) {
1510         return SetOutputType(gate, GateType::IntType());
1511     }
1512 
1513     if (IsConvert()) {
1514         GateRef input = acc_.GetValueIn(gate, 0);
1515         TypeInfo typeInfo = GetOutputTypeInfo(input);
1516         if (typeInfo == TypeInfo::CHAR) {
1517             acc_.ReplaceValueIn(gate, ConvertToTagged(input), 0);
1518         }
1519     }
1520     return Circuit::NullGate();
1521 }
1522 
VisitLoadMapSize(GateRef gate)1523 GateRef NumberSpeculativeRetype::VisitLoadMapSize(GateRef gate)
1524 {
1525     if (IsRetype()) {
1526         return SetOutputType(gate, GateType::IntType());
1527     }
1528 
1529     return Circuit::NullGate();
1530 }
1531 
VisitLoadElement(GateRef gate)1532 GateRef NumberSpeculativeRetype::VisitLoadElement(GateRef gate)
1533 {
1534     if (IsRetype()) {
1535         auto op = acc_.GetTypedLoadOp(gate);
1536         switch (op) {
1537             case TypedLoadOp::INT8ARRAY_LOAD_ELEMENT:
1538             case TypedLoadOp::UINT8ARRAY_LOAD_ELEMENT:
1539             case TypedLoadOp::UINT8CLAMPEDARRAY_LOAD_ELEMENT:
1540             case TypedLoadOp::INT16ARRAY_LOAD_ELEMENT:
1541             case TypedLoadOp::UINT16ARRAY_LOAD_ELEMENT:
1542             case TypedLoadOp::INT32ARRAY_LOAD_ELEMENT:
1543                 return SetOutputType(gate, GateType::IntType());
1544             case TypedLoadOp::UINT32ARRAY_LOAD_ELEMENT:
1545                 return SetOutputType(gate, TypeInfo::UINT32);
1546             case TypedLoadOp::FLOAT32ARRAY_LOAD_ELEMENT:
1547             case TypedLoadOp::FLOAT64ARRAY_LOAD_ELEMENT:
1548                 return SetOutputType(gate, GateType::DoubleType());
1549             case TypedLoadOp::STRING_LOAD_ELEMENT:
1550                 return SetOutputType(gate, TypeInfo::CHAR);
1551             case TypedLoadOp::ARRAY_LOAD_HOLE_INT_ELEMENT:
1552                 return SetOutputType(gate, TypeInfo::HOLE_INT);
1553             case TypedLoadOp::ARRAY_LOAD_HOLE_DOUBLE_ELEMENT:
1554                 return SetOutputType(gate, TypeInfo::HOLE_DOUBLE);
1555             default:
1556                 return SetOutputType(gate, GateType::AnyType());
1557         }
1558     }
1559 
1560     if (IsConvert()) {
1561         Environment env(gate, circuit_, &builder_);
1562         GateRef index = acc_.GetValueIn(gate, 1); // 1: value idx
1563         GateType indexType = acc_.GetGateType(index);
1564         acc_.ReplaceValueIn(gate, CheckAndConvertToInt32(index, indexType), 1);
1565         acc_.ReplaceStateIn(gate, builder_.GetState());
1566         acc_.ReplaceDependIn(gate, builder_.GetDepend());
1567     }
1568 
1569     return Circuit::NullGate();
1570 }
1571 
VisitStoreElement(GateRef gate)1572 GateRef NumberSpeculativeRetype::VisitStoreElement(GateRef gate)
1573 {
1574     if (IsRetype()) {
1575         return SetOutputType(gate, GateType::AnyType());
1576     }
1577 
1578     if (IsConvert()) {
1579         Environment env(gate, circuit_, &builder_);
1580         GateRef index = acc_.GetValueIn(gate, 1); // 1: value idx
1581         GateType indexType = acc_.GetGateType(index);
1582         GateRef value = acc_.GetValueIn(gate, 2); // 2: value idx
1583         acc_.ReplaceValueIn(gate, CheckAndConvertToInt32(index, indexType), 1); // 1: value idx
1584         auto op = acc_.GetTypedStoreOp(gate);
1585         switch (op) {
1586             case TypedStoreOp::INT8ARRAY_STORE_ELEMENT:
1587             case TypedStoreOp::UINT8ARRAY_STORE_ELEMENT:
1588             case TypedStoreOp::UINT8CLAMPEDARRAY_STORE_ELEMENT:
1589             case TypedStoreOp::INT16ARRAY_STORE_ELEMENT:
1590             case TypedStoreOp::UINT16ARRAY_STORE_ELEMENT:
1591             case TypedStoreOp::INT32ARRAY_STORE_ELEMENT:
1592             case TypedStoreOp::UINT32ARRAY_STORE_ELEMENT:
1593             case TypedStoreOp::ARRAY_STORE_INT_ELEMENT:
1594                 acc_.ReplaceValueIn(gate, CheckAndConvertToInt32(value, GateType::NumberType(), ConvertSupport::ENABLE,
1595                     OpType::NORMAL, false), 2);   // 2: value idx
1596                 break;
1597             case TypedStoreOp::FLOAT32ARRAY_STORE_ELEMENT:
1598             case TypedStoreOp::FLOAT64ARRAY_STORE_ELEMENT:
1599             case TypedStoreOp::ARRAY_STORE_DOUBLE_ELEMENT:
1600                 acc_.ReplaceValueIn(gate, CheckAndConvertToFloat64(value, GateType::NumberType()), 2);  // 2: value idx
1601                 break;
1602             default:
1603                 acc_.ReplaceValueIn(gate, ConvertToTagged(value), 2);   // 2: value idx
1604                 break;
1605         }
1606         acc_.ReplaceStateIn(gate, builder_.GetState());
1607         acc_.ReplaceDependIn(gate, builder_.GetDepend());
1608     }
1609 
1610     return Circuit::NullGate();
1611 }
1612 
VisitStoreProperty(GateRef gate)1613 GateRef NumberSpeculativeRetype::VisitStoreProperty(GateRef gate)
1614 {
1615     if (IsRetype()) {
1616         return SetOutputType(gate, GateType::AnyType());
1617     }
1618     ASSERT(IsConvert());
1619     GateRef value = acc_.GetValueIn(gate, 2); // 2: value
1620 
1621     Environment env(gate, circuit_, &builder_);
1622     GateRef propertyLookupResult = acc_.GetValueIn(gate, 1);
1623     PropertyLookupResult plr(acc_.TryGetValue(propertyLookupResult));
1624     if (plr.GetRepresentation() == Representation::DOUBLE) {
1625         acc_.SetMetaData(gate, circuit_->StorePropertyNoBarrier());
1626         acc_.ReplaceValueIn(
1627             gate, CheckAndConvertToFloat64(value, GateType::NumberType(), ConvertToNumber::DISABLE), 2); // 2: value
1628     } else if (plr.GetRepresentation() == Representation::INT) {
1629         acc_.SetMetaData(gate, circuit_->StorePropertyNoBarrier());
1630         acc_.ReplaceValueIn(
1631             gate, CheckAndConvertToInt32(value, GateType::IntType(), ConvertSupport::DISABLE), 2); // 2: value
1632     } else {
1633         TypeInfo valueType = GetOutputTypeInfo(value);
1634         if (valueType == TypeInfo::INT1 || valueType == TypeInfo::INT32 || valueType == TypeInfo::FLOAT64) {
1635             acc_.SetMetaData(gate, circuit_->StorePropertyNoBarrier());
1636         }
1637         acc_.ReplaceValueIn(gate, ConvertToTagged(value), 2); // 2: value
1638     }
1639 
1640     GateRef receiver = acc_.GetValueIn(gate, 0); // receiver
1641     acc_.ReplaceValueIn(gate, ConvertToTagged(receiver), 0); // 0: value idx
1642     acc_.ReplaceStateIn(gate, builder_.GetState());
1643     acc_.ReplaceDependIn(gate, builder_.GetDepend());
1644     return Circuit::NullGate();
1645 }
1646 
VisitLoadProperty(GateRef gate)1647 GateRef NumberSpeculativeRetype::VisitLoadProperty(GateRef gate)
1648 {
1649     if (IsRetype()) {
1650         GateRef propertyLookupResult = acc_.GetValueIn(gate, 1); // 1: value idx
1651         PropertyLookupResult plr(acc_.TryGetValue(propertyLookupResult));
1652         return SetOutputType(gate, plr.GetRepresentation());
1653     }
1654 
1655     ASSERT(IsConvert());
1656 
1657     return VisitWithConstantValue(gate, PROPERTY_LOOKUP_RESULT_INDEX); // ignoreIndex
1658 }
1659 
VisitTypeConvert(GateRef gate)1660 GateRef NumberSpeculativeRetype::VisitTypeConvert(GateRef gate)
1661 {
1662     GateRef input = acc_.GetValueIn(gate, 0); // 0: value idx
1663     TypeInfo inputInfo = GetOutputTypeInfo(input);
1664     TypeConvertAccessor accessor(acc_.TryGetValue(gate));
1665     ParamType paramType = accessor.GetLeftType();
1666     bool optForConstant = acc_.IsConstantNumber(input) || acc_.GetOpCode(input) == OpCode::TYPE_CONVERT;
1667     if (IsRetype()) {
1668         if (inputInfo == TypeInfo::CHAR || inputInfo == TypeInfo::INT1) {
1669             ASSERT(paramType.HasNumberType());
1670             return SetOutputType(gate, paramType);
1671         }
1672         if (inputInfo == TypeInfo::TAGGED) {
1673             if (optForConstant) {
1674                 TypeInfo oldType = GetOutputTypeInfo(gate);
1675                 acc_.SetGateType(gate, acc_.GetGateType(input));
1676                 SetOutputTypeInfo(gate, inputInfo);
1677                 return oldType == inputInfo ? Circuit::NullGate() : gate;
1678             }
1679             ASSERT(paramType.HasNumberType());
1680             return SetOutputType(gate, paramType);
1681         }
1682         TypeInfo oldType = GetOutputTypeInfo(gate);
1683         SetOutputTypeInfo(gate, inputInfo);
1684         return oldType == inputInfo ? Circuit::NullGate() : gate;
1685     }
1686     ASSERT(IsConvert());
1687     ASSERT(inputInfo != TypeInfo::NONE);
1688     Environment env(gate, circuit_, &builder_);
1689     if ((inputInfo == TypeInfo::TAGGED && !optForConstant) ||
1690         inputInfo == TypeInfo::CHAR || inputInfo == TypeInfo::INT1) {
1691         ASSERT(paramType.HasNumberType());
1692         if (paramType.IsIntType()) {
1693             input = CheckAndConvertToInt32(input, GateType::IntType());
1694             ResizeAndSetTypeInfo(input, TypeInfo::INT32);
1695         } else {
1696             input = CheckAndConvertToFloat64(input, acc_.GetGateType(input));
1697             ResizeAndSetTypeInfo(input, TypeInfo::FLOAT64);
1698         }
1699     }
1700     acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), input);
1701     return Circuit::NullGate();
1702 }
1703 
VisitMathDoubleParamsBuiltin(GateRef gate)1704 GateRef NumberSpeculativeRetype::VisitMathDoubleParamsBuiltin(GateRef gate)
1705 {
1706     if (IsRetype()) {
1707         return SetOutputType(gate, GateType::DoubleType());
1708     }
1709     ASSERT(IsConvert());
1710     Environment env(gate, circuit_, &builder_);
1711     size_t valueNum = acc_.GetNumValueIn(gate);
1712     for (size_t i = 0; i < valueNum; ++i) {
1713         GateRef input = acc_.GetValueIn(gate, i);
1714         GateRef convertedInput = CheckAndConvertToFloat64(input, GateType::NumberType(), ConvertToNumber::BOOL_ONLY);
1715         acc_.ReplaceValueIn(gate, convertedInput, i);
1716     }
1717     acc_.ReplaceStateIn(gate, builder_.GetState());
1718     acc_.ReplaceDependIn(gate, builder_.GetDepend());
1719     return Circuit::NullGate();
1720 }
1721 
GetDoubleValueFromConst(GateRef gate)1722 double NumberSpeculativeRetype::GetDoubleValueFromConst(GateRef gate)
1723 {
1724     ASSERT(acc_.GetOpCode(gate) == OpCode::CONSTANT);
1725     double rawValue;
1726     if (acc_.GetGateType(gate).IsNJSValueType()) {
1727         ASSERT(GetNumberInputTypeInfo(gate) == TypeInfo::FLOAT64);
1728         rawValue = acc_.GetFloat64FromConstant(gate);
1729     } else {
1730         JSTaggedValue value(acc_.GetConstantValue(gate));
1731         ASSERT(value.IsDouble());
1732         rawValue = value.GetDouble();
1733     }
1734     return rawValue;
1735 }
1736 
1737 template <bool IS_NAN>
VisitNumberOrGlobalBuiltin(GateRef gate)1738 GateRef NumberSpeculativeRetype::VisitNumberOrGlobalBuiltin(GateRef gate)
1739 {
1740     if (IsRetype()) {
1741         ASSERT(acc_.GetOpCode(gate) == OpCode::GLOBAL_IS_FINITE ||
1742                acc_.GetOpCode(gate) == OpCode::NUMBER_IS_FINITE ||
1743                acc_.GetOpCode(gate) == OpCode::GLOBAL_IS_NAN ||
1744                acc_.GetOpCode(gate) == OpCode::NUMBER_IS_NAN);
1745         return SetOutputType(gate, GateType::BooleanType());
1746     }
1747     ASSERT(IsConvert());
1748     Environment env(gate, circuit_, &builder_);
1749     ASSERT(acc_.GetNumValueIn(gate) == 1);
1750     GateRef input = acc_.GetValueIn(gate, 0);
1751 
1752     // We change IsNan/IsFinite to constant if input is INT32 without check
1753     // So we skip tagged input with int profiled type
1754     auto type = GetNumberInputTypeInfo(input, true);
1755     if (type == TypeInfo::INT32) {
1756         GateRef result;
1757         if constexpr (IS_NAN) {
1758             result = builder_.Boolean(false);
1759         } else {
1760             result = builder_.Boolean(true);
1761         }
1762         ResizeAndSetTypeInfo(result, TypeInfo::INT1);
1763         acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
1764         return Circuit::NullGate();
1765     } else {
1766         ASSERT(type == TypeInfo::FLOAT64);
1767         input = CheckAndConvertToFloat64(input, GateType::NumberType());
1768     }
1769 
1770     acc_.ReplaceValueIn(gate, input, 0);
1771     ResizeAndSetTypeInfo(input, TypeInfo::FLOAT64);
1772     acc_.ReplaceStateIn(gate, builder_.GetState());
1773     acc_.ReplaceDependIn(gate, builder_.GetDepend());
1774     return Circuit::NullGate();
1775 }
1776 
VisitNumberIsInteger(GateRef gate)1777 GateRef NumberSpeculativeRetype::VisitNumberIsInteger(GateRef gate)
1778 {
1779     if (IsRetype()) {
1780         ASSERT(acc_.GetOpCode(gate) == OpCode::NUMBER_IS_INTEGER ||
1781                acc_.GetOpCode(gate) == OpCode::NUMBER_IS_SAFEINTEGER);
1782         return SetOutputType(gate, GateType::BooleanType());
1783     }
1784     ASSERT(IsConvert());
1785     Environment env(gate, circuit_, &builder_);
1786     ASSERT(acc_.GetNumValueIn(gate) == 1);
1787     GateRef input = acc_.GetValueIn(gate, 0);
1788     auto type = GetNumberInputTypeInfo<false>(input);
1789     if (type == TypeInfo::INT32 || type == TypeInfo::INT1) {
1790         GateRef result = type == TypeInfo::INT32 ? builder_.True() : builder_.False();
1791         ResizeAndSetTypeInfo(result, TypeInfo::INT1);
1792         acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
1793         return Circuit::NullGate();
1794     }
1795     ASSERT(type == TypeInfo::FLOAT64);
1796     input = ConvertToTagged(input);
1797     acc_.ReplaceValueIn(gate, input, 0);
1798     ResizeAndSetTypeInfo(input, TypeInfo::TAGGED);
1799     acc_.ReplaceStateIn(gate, builder_.GetState());
1800     acc_.ReplaceDependIn(gate, builder_.GetDepend());
1801     return Circuit::NullGate();
1802 }
1803 
VisitNumberParseFloat(GateRef gate)1804 GateRef NumberSpeculativeRetype::VisitNumberParseFloat(GateRef gate)
1805 {
1806     if (IsRetype()) {
1807         return SetOutputType(gate, GateType::DoubleType());
1808     }
1809     ASSERT(IsConvert());
1810     Environment env(gate, circuit_, &builder_);
1811     GateRef input = acc_.GetValueIn(gate, 0);
1812     TypeInfo type = GetNumberTypeInfo(input);
1813     if (type == TypeInfo::INT32) {
1814         // replace parseFloat with cast
1815         input = CheckAndConvertToFloat64(input, GateType::NumberType(), ConvertToNumber::DISABLE);
1816         acc_.ReplaceGate(gate, builder_.GetStateDepend(), input);
1817     } else {
1818         acc_.ReplaceValueIn(gate, ConvertToTagged(input), 0);
1819         acc_.ReplaceStateIn(gate, builder_.GetState());
1820         acc_.ReplaceDependIn(gate, builder_.GetDepend());
1821     }
1822     return Circuit::NullGate();
1823 }
1824 
VisitNumberParseInt(GateRef gate)1825 GateRef NumberSpeculativeRetype::VisitNumberParseInt(GateRef gate)
1826 {
1827     if (IsRetype()) {
1828         return SetOutputType(gate, GateType::IntType());
1829     }
1830     ASSERT(IsConvert());
1831     return Circuit::NullGate();
1832 }
1833 
VisitClz32Builtin(GateRef gate)1834 GateRef NumberSpeculativeRetype::VisitClz32Builtin(GateRef gate)
1835 {
1836     if (IsRetype()) {
1837         return SetOutputType(gate, GateType::IntType());
1838     }
1839     ASSERT(IsConvert());
1840     Environment env(gate, circuit_, &builder_);
1841     GateRef input = acc_.GetValueIn(gate, 0);
1842 
1843     TypeInfo type = GetNumberTypeInfo(input);
1844     if (type == TypeInfo::INT32) {
1845         input = CheckAndConvertToInt32(input, GateType::IntType());
1846         acc_.SetMetaData(gate, circuit_->MathClz32Int32());
1847     } else {  // All other types describe in ConvertToFloat64
1848         input = CheckAndConvertToFloat64(input, GateType::NumberType(), ConvertToNumber::BOOL_ONLY);
1849         acc_.SetMetaData(gate, circuit_->MathClz32Double());
1850     }
1851     acc_.ReplaceValueIn(gate, input, 0);
1852     acc_.ReplaceStateIn(gate, builder_.GetState());
1853     acc_.ReplaceDependIn(gate, builder_.GetDepend());
1854     return Circuit::NullGate();
1855 }
1856 
GetNewMeta(OpCode op,TypeInfo type)1857 const GateMetaData *NumberSpeculativeRetype::GetNewMeta(OpCode op, TypeInfo type)
1858 {
1859     if (type == TypeInfo::INT32) {
1860         switch (op) {
1861             case OpCode::MATH_ABS:
1862                 return circuit_->MathAbsInt32();
1863             case OpCode::MATH_MIN:
1864                 return circuit_->MathMinInt32();
1865             case OpCode::MATH_MAX:
1866                 return circuit_->MathMaxInt32();
1867             default:
1868                 return nullptr;
1869         }
1870     } else if (type == TypeInfo::FLOAT64) {
1871         switch (op) {
1872             case OpCode::MATH_ABS:
1873                 return circuit_->MathAbsDouble();
1874             case OpCode::MATH_MIN:
1875                 return circuit_->MathMinDouble();
1876             case OpCode::MATH_MAX:
1877                 return circuit_->MathMaxDouble();
1878             case OpCode::MATH_ROUND:
1879                 return circuit_->MathRoundDouble();
1880             default:
1881                 return nullptr;
1882         }
1883     } else if (type == TypeInfo::TAGGED) {
1884         if (op == OpCode::MATH_SIGN) {
1885             return circuit_->MathSignTagged();
1886         }
1887         return nullptr;
1888     } else {
1889         return nullptr;
1890     }
1891 }
1892 
UpdateMeta(GateRef gate,TypeInfo newType,const GateMetaData * meta)1893 void NumberSpeculativeRetype::UpdateMeta(GateRef gate, TypeInfo newType, const GateMetaData *meta)
1894 {
1895     if (meta == nullptr) {
1896         return;
1897     }
1898     acc_.SetMetaData(gate, meta);
1899     if (newType != TypeInfo::TAGGED) {
1900         ASSERT(newType == TypeInfo::INT32 || newType == TypeInfo::FLOAT64);
1901         acc_.SetGateType(gate, GateType::NJSValue());
1902         acc_.SetMachineType(gate, newType == TypeInfo::INT32 ? MachineType::I32 : MachineType::F64);
1903     } else {
1904         ASSERT(acc_.GetGateType(gate) != GateType::NJSValue() && acc_.GetMachineType(gate) == MachineType::I64);
1905     }
1906 }
1907 
VisitMathTaggedNumberParamsBuiltin(GateRef gate)1908 GateRef NumberSpeculativeRetype::VisitMathTaggedNumberParamsBuiltin(GateRef gate)
1909 {
1910     size_t valueNum = acc_.GetNumValueIn(gate);
1911     ASSERT(valueNum <= 2U);
1912     OpCode op = acc_.GetOpCode(gate);
1913     if (IsRetype()) {
1914         TypeInfo type = GetNumberTypeInfo(acc_.GetValueIn(gate, 0));
1915         if (valueNum > 1U) {
1916             TypeInfo secondInputType = GetNumberTypeInfo(acc_.GetValueIn(gate, 1U));
1917             type = GetCommonTypeInfo(type, secondInputType);
1918         }
1919         if (type == TypeInfo::TAGGED && op == OpCode::MATH_ROUND) {
1920             type = TypeInfo::FLOAT64;
1921         }
1922         if (op == OpCode::MATH_SIGN) {
1923             if (type == TypeInfo::INT32) {
1924                 return SetOutputType(gate, TypeInfo::INT32);
1925             }
1926             return SetOutputType(gate, TypeInfo::TAGGED);
1927         }
1928         return SetOutputType(gate, type);
1929     }
1930     ASSERT(IsConvert());
1931     TypeInfo type = GetOutputTypeInfo(gate); // load type computed in retype phase
1932     if (op == OpCode::MATH_ROUND) {
1933         type = GetNumberTypeInfo(acc_.GetValueIn(gate, 0));
1934     }
1935     const GateMetaData* meta = GetNewMeta(op, type);
1936     UpdateMeta(gate, type, meta);
1937     Environment env(gate, circuit_, &builder_);
1938     for (size_t i = 0; i < valueNum; ++i) {
1939         GateRef input = acc_.GetValueIn(gate, i);
1940         if (type == TypeInfo::INT32) {
1941             input = CheckAndConvertToInt32(input, GateType::IntType());
1942         } else if (type == TypeInfo::FLOAT64) {
1943             input = CheckAndConvertToFloat64(input, acc_.GetGateType(input), ConvertToNumber::BOOL_ONLY);
1944         } else {
1945             ASSERT(type == TypeInfo::TAGGED);
1946             input = CheckAndConvertToTagged(input, GateType::NumberType(), ConvertToNumber::BOOL_ONLY);
1947         }
1948         acc_.ReplaceValueIn(gate, input, i);
1949     }
1950     acc_.ReplaceStateIn(gate, builder_.GetState());
1951     acc_.ReplaceDependIn(gate, builder_.GetDepend());
1952     return Circuit::NullGate();
1953 }
1954 
VisitMathTrunc(GateRef gate)1955 GateRef NumberSpeculativeRetype::VisitMathTrunc(GateRef gate)
1956 {
1957     if (IsRetype()) {
1958         return SetOutputType(gate, GateType::DoubleType());
1959     }
1960     ASSERT(IsConvert());
1961     Environment env(gate, circuit_, &builder_);
1962     ASSERT(acc_.GetNumValueIn(gate) == 1);
1963     GateRef input = acc_.GetValueIn(gate, 0);
1964     acc_.ReplaceValueIn(gate, CheckAndConvertToTagged(input, GateType::NumberType(), ConvertToNumber::BOOL_ONLY), 0);
1965     acc_.ReplaceStateIn(gate, builder_.GetState());
1966     acc_.ReplaceDependIn(gate, builder_.GetDepend());
1967     return Circuit::NullGate();
1968 }
1969 
VisitBigIntAsIntN(GateRef gate)1970 GateRef NumberSpeculativeRetype::VisitBigIntAsIntN(GateRef gate)
1971 {
1972     if (IsRetype()) {
1973         return SetOutputType(gate, GateType::AnyType());
1974     }
1975     ASSERT(IsConvert());
1976     Environment env(gate, circuit_, &builder_);
1977     ASSERT(acc_.GetNumValueIn(gate) == 3U);
1978     GateRef bits = acc_.GetValueIn(gate, 0);
1979     acc_.ReplaceValueIn(gate, ConvertToTagged(CheckAndConvertToFloat64(bits, GateType::NumberType(),
1980                                                                        ConvertToNumber::BOOL_ONLY)), 0);
1981     GateRef bigint = acc_.GetValueIn(gate, 1);
1982     acc_.ReplaceValueIn(gate, ConvertToTagged(bigint), 1);
1983     acc_.ReplaceStateIn(gate, builder_.GetState());
1984     acc_.ReplaceDependIn(gate, builder_.GetDepend());
1985     return Circuit::NullGate();
1986 }
1987 
1988 template<bool BOOL_AS_INT>
GetNumberInputTypeInfo(GateRef gate,bool skipTagged)1989 TypeInfo NumberSpeculativeRetype::GetNumberInputTypeInfo(GateRef gate, bool skipTagged)
1990 {
1991     TypeInfo typeInfo = GetOutputTypeInfo(gate);
1992     switch (typeInfo) {
1993         case TypeInfo::INT1:
1994             return BOOL_AS_INT ? TypeInfo::INT32 : TypeInfo::INT1;
1995         case TypeInfo::INT32:
1996         case TypeInfo::HOLE_INT:
1997             return TypeInfo::INT32;
1998         case TypeInfo::NONE:
1999         case TypeInfo::TAGGED: {
2000             if (skipTagged) {
2001                 return TypeInfo::FLOAT64;
2002             }
2003             GateType gateType = acc_.GetGateType(gate);
2004             if (gateType.IsIntType()) {
2005                 return TypeInfo::INT32;
2006             }
2007             if (gateType.IsBooleanType()) {
2008                 return BOOL_AS_INT ? TypeInfo::INT32 : TypeInfo::INT1;
2009             }
2010             return TypeInfo::FLOAT64;
2011         }
2012         default:
2013             return TypeInfo::FLOAT64;
2014     }
2015 }
2016 
SetNewInputForMathImul(GateRef gate,int idx)2017 void NumberSpeculativeRetype::SetNewInputForMathImul(GateRef gate, int idx)
2018 {
2019     GateRef input = acc_.GetValueIn(gate, idx);
2020     auto type = GetNumberInputTypeInfo(input);
2021     if (type == TypeInfo::INT32) {
2022         input = CheckAndConvertToInt32(input, GateType::IntType());
2023     } else {
2024         ASSERT(type == TypeInfo::FLOAT64);
2025         input = CheckAndConvertToFloat64(input, GateType::NumberType(), ConvertToNumber::BOOL_ONLY);
2026         input = builder_.TruncDoubleToInt(acc_.GetGlueFromArgList(), input, base::INT32_BITS);
2027     }
2028     ResizeAndSetTypeInfo(input, TypeInfo::INT32);
2029     acc_.ReplaceValueIn(gate, input, idx);
2030 }
2031 
VisitMathImul(GateRef gate)2032 GateRef NumberSpeculativeRetype::VisitMathImul(GateRef gate)
2033 {
2034     if (IsRetype()) {
2035         return SetOutputType(gate, GateType::IntType());
2036     }
2037     ASSERT(IsConvert());
2038     Environment env(gate, circuit_, &builder_);
2039     ASSERT(acc_.GetNumValueIn(gate) == 2U);
2040 
2041     SetNewInputForMathImul(gate, 0);
2042     SetNewInputForMathImul(gate, 1);
2043 
2044     acc_.SetGateType(gate, GateType::NJSValue());
2045     acc_.SetMachineType(gate, MachineType::I32);
2046     acc_.ReplaceStateIn(gate, builder_.GetState());
2047     acc_.ReplaceDependIn(gate, builder_.GetDepend());
2048     return Circuit::NullGate();
2049 }
2050 
VisitDataViewGet(GateRef gate)2051 GateRef NumberSpeculativeRetype::VisitDataViewGet(GateRef gate)
2052 {
2053     GateRef builtinsID = acc_.GetValueIn(gate, 2);
2054     auto ID = static_cast<BuiltinsStubCSigns::ID>(acc_.GetConstantValue(builtinsID));
2055     if (IsRetype()) {
2056         switch (ID) {
2057             case BuiltinsStubCSigns::ID::DataViewGetInt8:
2058                 return SetOutputType(gate, GateType::IntType());
2059             case BuiltinsStubCSigns::ID::DataViewGetUint8:
2060                 return SetOutputType(gate, GateType::IntType());
2061             case BuiltinsStubCSigns::ID::DataViewGetInt16:
2062                 return SetOutputType(gate, GateType::IntType());
2063             case BuiltinsStubCSigns::ID::DataViewGetUint16:
2064                 return SetOutputType(gate, GateType::IntType());
2065             case BuiltinsStubCSigns::ID::DataViewGetInt32:
2066                 return SetOutputType(gate, GateType::IntType());
2067             case BuiltinsStubCSigns::ID::DataViewGetUint32:
2068                 return SetOutputType(gate, TypeInfo::UINT32);
2069             case BuiltinsStubCSigns::ID::DataViewGetFloat32:
2070                 return SetOutputType(gate, GateType::DoubleType());
2071             case BuiltinsStubCSigns::ID::DataViewGetFloat64:
2072                 return SetOutputType(gate, GateType::DoubleType());
2073             default:
2074                 UNREACHABLE();
2075         }
2076     }
2077     ASSERT(IsConvert());
2078     Environment env(gate, circuit_, &builder_);
2079     GateRef isLittleEndian = acc_.GetValueIn(gate, 3);  // 3: isLittleEndian
2080     GateRef inputIsLittleEndian = CheckAndConvertToBool(isLittleEndian, GateType::BooleanType());
2081     acc_.ReplaceValueIn(gate, inputIsLittleEndian, 3); // 3: replace input value to Bool
2082     return Circuit::NullGate();
2083 }
2084 
VisitBigIntConstructor(GateRef gate)2085 GateRef NumberSpeculativeRetype::VisitBigIntConstructor(GateRef gate)
2086 {
2087     if (IsRetype()) {
2088         return SetOutputType(gate, GateType::BigIntType());
2089     }
2090     GateRef input = acc_.GetValueIn(gate, 0);
2091     TypeInfo typeInfo = GetOutputTypeInfo(input);
2092     const GateMetaData* meta = nullptr;
2093     switch (typeInfo) {
2094         case TypeInfo::INT32:
2095             meta = circuit_->BigIntConstructorInt32();
2096             break;
2097         case TypeInfo::UINT32:
2098             meta = circuit_->BigIntConstructorUint32();
2099             break;
2100         default:
2101             auto int32_cnst = TryConvertConstant(input, true);
2102             if (int32_cnst != Circuit::NullGate()) {
2103                 acc_.ReplaceValueIn(gate, int32_cnst, 0);
2104                 int32_t rawValue = acc_.GetInt32FromConstant(int32_cnst);
2105                 if (rawValue < 0) {
2106                     meta = circuit_->BigIntConstructorInt32();
2107                 } else {
2108                     meta = circuit_->BigIntConstructorUint32();
2109                 }
2110             }
2111             break;
2112     }
2113     if (meta != nullptr) {
2114         // int or uint input
2115         acc_.SetMetaData(gate, meta);
2116     } else {
2117         // double, object or some other input
2118         acc_.ReplaceValueIn(gate, ConvertToTagged(input), 0);
2119     }
2120     return Circuit::NullGate();
2121 }
2122 
VisitDataViewSet(GateRef gate)2123 GateRef NumberSpeculativeRetype::VisitDataViewSet(GateRef gate)
2124 {
2125     if (IsRetype()) {
2126         return SetOutputType(gate, GateType::UndefinedType());
2127     }
2128     ASSERT(IsConvert());
2129     Environment env(gate, circuit_, &builder_);
2130     GateRef value = acc_.GetValueIn(gate, 2);
2131     GateRef inputValue = CheckAndConvertToFloat64(value, acc_.GetGateType(value), ConvertToNumber::BOOL_ONLY);
2132     GateRef isLittleEndian = acc_.GetValueIn(gate, 4);  // 4: isLittleEndian
2133     GateRef inputIsLittleEndian = CheckAndConvertToBool(isLittleEndian, GateType::BooleanType());
2134     acc_.ReplaceValueIn(gate, inputValue, 2); // 2: replace input value to Double64
2135     acc_.ReplaceValueIn(gate, inputIsLittleEndian, 4); // 4: replace input value to Bool
2136     acc_.ReplaceStateIn(gate, builder_.GetState());
2137     acc_.ReplaceDependIn(gate, builder_.GetDepend());
2138     return Circuit::NullGate();
2139 }
2140 
VisitDateGetTime(GateRef gate)2141 GateRef NumberSpeculativeRetype::VisitDateGetTime(GateRef gate)
2142 {
2143     if (IsRetype()) {
2144         return SetOutputType(gate, GateType::TaggedValue());
2145     }
2146     ASSERT(IsConvert());
2147     // Nothing to do, because one input and it is object "this"
2148     return Circuit::NullGate();
2149 }
2150 
VisitDateNow(GateRef gate)2151 GateRef NumberSpeculativeRetype::VisitDateNow(GateRef gate)
2152 {
2153     if (IsRetype()) {
2154         return SetOutputType(gate, GateType::DoubleType());
2155     }
2156     ASSERT(IsConvert());
2157     // Nothing to do, because don't have inputs
2158     return Circuit::NullGate();
2159 }
2160 
VisitArrayIncludesIndexOf(GateRef gate)2161 GateRef NumberSpeculativeRetype::VisitArrayIncludesIndexOf(GateRef gate)
2162 {
2163     using Indices = CircuitArgIndices::ArrayIncludesIndexOf;
2164     Environment env(gate, circuit_, &builder_);
2165     GateRef callID = acc_.GetValueIn(gate, Indices::CALL_ID);
2166     BuiltinsStubCSigns::ID id = static_cast<BuiltinsStubCSigns::ID>(acc_.GetConstantValue(callID));
2167     if (IsRetype()) {
2168         if (id == BuiltinsStubCSigns::ID::ArrayIncludes) {
2169             return SetOutputType(gate, GateType::BooleanType());
2170         } else {
2171             return SetOutputType(gate, GateType::IntType());
2172         }
2173     }
2174     GateRef findElement = acc_.GetValueIn(gate, Indices::TARGET);
2175     acc_.ReplaceValueIn(gate, ConvertToTagged(findElement), Indices::TARGET);
2176     acc_.ReplaceDependIn(gate, builder_.GetDepend());
2177     acc_.ReplaceStateIn(gate, builder_.GetState());
2178     return Circuit::NullGate();
2179 }
2180 
VisitStringCharCodeAt(GateRef gate)2181 GateRef NumberSpeculativeRetype::VisitStringCharCodeAt(GateRef gate)
2182 {
2183     Environment env(gate, circuit_, &builder_);
2184     if (IsRetype()) {
2185         return SetOutputType(gate, GateType::AnyType());
2186     }
2187     if (IsConvert()) {
2188         GateRef thisValue = acc_.GetValueIn(gate, 0);
2189         acc_.ReplaceValueIn(gate, ConvertToTagged(thisValue), 0);
2190         GateRef pos = acc_.GetValueIn(gate, 1);
2191         acc_.ReplaceValueIn(gate, CheckAndConvertToInt32(pos, GateType::IntType()), 1);
2192         acc_.ReplaceStateIn(gate, builder_.GetState());
2193         acc_.ReplaceDependIn(gate, builder_.GetDepend());
2194     }
2195     return Circuit::NullGate();
2196 }
2197 
VisitString(GateRef gate)2198 GateRef NumberSpeculativeRetype::VisitString(GateRef gate)
2199 {
2200     Environment env(gate, circuit_, &builder_);
2201     if (IsRetype()) {
2202         return SetOutputType(gate, GateType::AnyType());
2203     }
2204     if (IsConvert()) {
2205         GateRef thisValue = acc_.GetValueIn(gate, 0);
2206         acc_.ReplaceValueIn(gate, ConvertToTagged(thisValue), 0);
2207         auto argc = acc_.GetNumValueIn(gate);
2208         for (size_t i = 1; i < argc; i++) {
2209             GateRef arg = acc_.GetValueIn(gate, i);
2210             acc_.ReplaceValueIn(gate, CheckAndConvertToInt32(arg, GateType::IntType()), i);
2211         }
2212         acc_.ReplaceStateIn(gate, builder_.GetState());
2213         acc_.ReplaceDependIn(gate, builder_.GetDepend());
2214     }
2215     return Circuit::NullGate();
2216 }
2217 
VisitMonoLoadPropertyOnProto(GateRef gate)2218 GateRef NumberSpeculativeRetype::VisitMonoLoadPropertyOnProto(GateRef gate)
2219 {
2220     if (IsRetype()) {
2221         GateRef propertyLookupResult = acc_.GetValueIn(gate, 1);
2222         PropertyLookupResult plr(acc_.TryGetValue(propertyLookupResult));
2223         return SetOutputType(gate, plr.GetRepresentation());
2224     }
2225 
2226     ASSERT(IsConvert());
2227     ConvertMonoAccessorValueIn(gate);
2228 
2229     return Circuit::NullGate();
2230 }
2231 
VisitMonoCallGetterOnProto(GateRef gate)2232 GateRef NumberSpeculativeRetype::VisitMonoCallGetterOnProto(GateRef gate)
2233 {
2234     if (IsRetype()) {
2235         return SetOutputType(gate, GateType::AnyType());
2236     }
2237     if (IsConvert()) {
2238         ConvertMonoAccessorValueIn(gate);
2239     }
2240     return Circuit::NullGate();
2241 }
2242 
VisitMonoStoreProperty(GateRef gate)2243 GateRef NumberSpeculativeRetype::VisitMonoStoreProperty(GateRef gate)
2244 {
2245     if (IsRetype()) {
2246         return SetOutputType(gate, GateType::AnyType());
2247     }
2248     ASSERT(IsConvert());
2249 
2250     GateRef value = acc_.GetValueIn(gate, 4); // 4: value
2251 
2252     Environment env(gate, circuit_, &builder_);
2253     GateRef propertyLookupResult = acc_.GetValueIn(gate, 1);
2254     PropertyLookupResult plr(acc_.TryGetValue(propertyLookupResult));
2255     if (plr.IsAccessor()) {
2256         size_t valueNum = acc_.GetNumValueIn(gate);
2257         for (size_t i = 0; i < valueNum; ++i) {
2258             if (i == PROPERTY_LOOKUP_RESULT_INDEX || i == HCLASS_INDEX) {
2259                 continue;
2260             }
2261             GateRef input = acc_.GetValueIn(gate, i);
2262             acc_.ReplaceValueIn(gate, ConvertToTagged(input), i);
2263         }
2264         return Circuit::NullGate();
2265     }
2266 
2267     if (plr.GetRepresentation() == Representation::DOUBLE) {
2268         acc_.SetStoreNoBarrier(gate, true);
2269         acc_.ReplaceValueIn(
2270             gate, CheckAndConvertToFloat64(value, GateType::NumberType(), ConvertToNumber::DISABLE), 4); // 4: value
2271     } else if (plr.GetRepresentation() == Representation::INT) {
2272         acc_.SetStoreNoBarrier(gate, true);
2273         acc_.ReplaceValueIn(
2274             gate, CheckAndConvertToInt32(value, GateType::IntType(), ConvertSupport::DISABLE), 4); // 4: value
2275     } else {
2276         TypeInfo valueType = GetOutputTypeInfo(value);
2277         if (valueType == TypeInfo::INT1 || valueType == TypeInfo::INT32 || valueType == TypeInfo::FLOAT64) {
2278             acc_.SetStoreNoBarrier(gate, true);
2279         }
2280         acc_.ReplaceValueIn(gate, ConvertToTagged(value), 4); // 4: value
2281     }
2282 
2283     GateRef receiver = acc_.GetValueIn(gate, 0); // receiver
2284     acc_.ReplaceValueIn(gate, ConvertToTagged(receiver), 0);
2285     acc_.ReplaceStateIn(gate, builder_.GetState());
2286     acc_.ReplaceDependIn(gate, builder_.GetDepend());
2287     return Circuit::NullGate();
2288 }
2289 
VisitGate(GateRef gate)2290 GateRef NumberSpeculativeRetypeManager::VisitGate(GateRef gate)
2291 {
2292     retype_->setState(state_);
2293     return retype_->VisitGate(gate);
2294 }
2295 
2296 }  // namespace panda::ecmascript::kungfu
2297