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