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