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