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