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