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 #include "ecmascript/compiler/circuit_builder-inl.h"
18 #include "ecmascript/compiler/share_gate_meta_data.h"
19 #include "ecmascript/compiler/number_gate_info.h"
20 #include "ecmascript/compiler/type.h"
21 #include <cstdint>
22
23 namespace panda::ecmascript::kungfu {
SetOutputType(GateRef gate,GateType gateType)24 GateRef NumberSpeculativeRetype::SetOutputType(GateRef gate, GateType gateType)
25 {
26 TypeInfo type = GetOutputTypeInfo(gate);
27 TypeInfo old = type;
28 if (gateType.IsIntType()) {
29 type = TypeInfo::INT32;
30 } else if (gateType.IsDoubleType()) {
31 type = TypeInfo::FLOAT64;
32 } else if (gateType.IsBooleanType()) {
33 type = TypeInfo::INT1;
34 } else {
35 type = TypeInfo::TAGGED;
36 }
37 SetOutputTypeInfo(gate, type);
38 return old == type ? Circuit::NullGate() : gate;
39 }
40
SetOutputType(GateRef gate,PGOSampleType pgoType)41 GateRef NumberSpeculativeRetype::SetOutputType(GateRef gate, PGOSampleType pgoType)
42 {
43 TypeInfo type = GetOutputTypeInfo(gate);
44 TypeInfo old = type;
45 if (pgoType.IsInt()) {
46 type = TypeInfo::INT32;
47 } else {
48 type = TypeInfo::FLOAT64;
49 }
50 SetOutputTypeInfo(gate, type);
51 return old == type ? Circuit::NullGate() : gate;
52 }
53
SetOutputType(GateRef gate,Representation rep)54 GateRef NumberSpeculativeRetype::SetOutputType(GateRef gate, Representation rep)
55 {
56 TypeInfo type = GetOutputTypeInfo(gate);
57 TypeInfo old = type;
58 if (rep == Representation::INT) {
59 type = TypeInfo::INT32;
60 } else if (rep == Representation::DOUBLE) {
61 type = TypeInfo::FLOAT64;
62 } else {
63 type = TypeInfo::TAGGED;
64 }
65 SetOutputTypeInfo(gate, type);
66 return old == type ? Circuit::NullGate() : gate;
67 }
68
SetOutputType(GateRef gate,TypeInfo type)69 GateRef NumberSpeculativeRetype::SetOutputType(GateRef gate, TypeInfo type)
70 {
71 TypeInfo old = GetOutputTypeInfo(gate);
72 SetOutputTypeInfo(gate, type);
73 return old == type ? Circuit::NullGate() : gate;
74 }
setState(NumberSpeculativeRetype::State state)75 void NumberSpeculativeRetype::setState(NumberSpeculativeRetype::State state)
76 {
77 state_ = state;
78 }
79
VisitGate(GateRef gate)80 GateRef NumberSpeculativeRetype::VisitGate(GateRef gate)
81 {
82 OpCode op = acc_.GetOpCode(gate);
83 switch (op) {
84 case OpCode::TYPED_BINARY_OP:
85 return VisitTypedBinaryOp(gate);
86 case OpCode::TYPED_UNARY_OP:
87 return VisitTypedUnaryOp(gate);
88 case OpCode::TYPED_CONDITION_JUMP:
89 return VisitTypedConditionJump(gate);
90 case OpCode::RANGE_CHECK_PREDICATE:
91 return VisitRangeCheckPredicate(gate);
92 case OpCode::INDEX_CHECK:
93 return VisitIndexCheck(gate);
94 case OpCode::LOAD_ARRAY_LENGTH:
95 case OpCode::LOAD_TYPED_ARRAY_LENGTH:
96 return VisitLoadArrayLength(gate);
97 case OpCode::LOAD_STRING_LENGTH:
98 return VisitLoadStringLength(gate);
99 case OpCode::LOAD_ELEMENT:
100 return VisitLoadElement(gate);
101 case OpCode::STORE_ELEMENT:
102 return VisitStoreElement(gate);
103 case OpCode::STORE_PROPERTY:
104 return VisitStoreProperty(gate);
105 case OpCode::LOAD_PROPERTY:
106 return VisitLoadProperty(gate);
107 case OpCode::MONO_LOAD_PROPERTY_ON_PROTO:
108 return VisitMonoLoadPropertyOnProto(gate);
109 case OpCode::MONO_CALL_GETTER_ON_PROTO:
110 return VisitMonoCallGetterOnProto(gate);
111 case OpCode::MONO_STORE_PROPERTY:
112 case OpCode::MONO_STORE_PROPERTY_LOOK_UP_PROTO:
113 return VisitMonoStoreProperty(gate);
114 case OpCode::VALUE_SELECTOR:
115 return VisitPhi(gate);
116 case OpCode::CONSTANT:
117 return VisitConstant(gate);
118 case OpCode::TYPED_CALL_BUILTIN:
119 return VisitCallBuiltins(gate);
120 case OpCode::TYPE_CONVERT:
121 return VisitTypeConvert(gate);
122 case OpCode::FRAME_STATE:
123 return VisitFrameState(gate);
124 case OpCode::CALL_GETTER:
125 case OpCode::CALL_SETTER:
126 case OpCode::CONSTRUCT:
127 case OpCode::TYPEDCALL:
128 case OpCode::TYPEDFASTCALL:
129 case OpCode::OBJECT_TYPE_CHECK:
130 return VisitWithConstantValue(gate, PROPERTY_LOOKUP_RESULT_INDEX);
131 case OpCode::LOOP_EXIT_VALUE:
132 case OpCode::RANGE_GUARD:
133 return VisitIntermediateValue(gate);
134 case OpCode::JS_BYTECODE:
135 case OpCode::PRIMITIVE_TYPE_CHECK:
136 case OpCode::STABLE_ARRAY_CHECK:
137 case OpCode::TYPED_ARRAY_CHECK:
138 case OpCode::TYPED_CALLTARGETCHECK_OP:
139 case OpCode::TYPED_CALL_CHECK:
140 case OpCode::HEAP_ALLOC:
141 case OpCode::TYPED_NEW_ALLOCATE_THIS:
142 case OpCode::TYPED_SUPER_ALLOCATE_THIS:
143 case OpCode::GET_SUPER_CONSTRUCTOR:
144 case OpCode::ARG:
145 case OpCode::RETURN:
146 case OpCode::FRAME_ARGS:
147 case OpCode::SAVE_REGISTER:
148 case OpCode::RESTORE_REGISTER:
149 case OpCode::LOAD_CONST_OFFSET:
150 case OpCode::STORE_CONST_OFFSET:
151 case OpCode::LEX_VAR_IS_HOLE_CHECK:
152 case OpCode::TYPE_OF_CHECK:
153 case OpCode::ARRAY_CONSTRUCTOR:
154 case OpCode::OBJECT_CONSTRUCTOR:
155 case OpCode::LD_LOCAL_MODULE_VAR:
156 case OpCode::STORE_MODULE_VAR:
157 case OpCode::STRING_FROM_SINGLE_CHAR_CODE:
158 case OpCode::ORDINARY_HAS_INSTANCE:
159 case OpCode::ECMA_STRING_CHECK:
160 return VisitOthers(gate);
161 default:
162 return Circuit::NullGate();
163 }
164 }
165
VisitTypedBinaryOp(GateRef gate)166 GateRef NumberSpeculativeRetype::VisitTypedBinaryOp(GateRef gate)
167 {
168 if (acc_.HasStringType(gate)) {
169 return VisitStringBinaryOp(gate);
170 }
171
172 if (acc_.GetTypedBinaryOp(gate) != TypedBinOp::TYPED_STRICTEQ &&
173 acc_.GetTypedBinaryOp(gate) != TypedBinOp::TYPED_STRICTNOTEQ &&
174 acc_.GetTypedBinaryOp(gate) != TypedBinOp::TYPED_EQ &&
175 acc_.GetTypedBinaryOp(gate) != TypedBinOp::TYPED_NOTEQ) {
176 if (acc_.HasPrimitiveNumberType(gate)) {
177 return VisitNumberBinaryOp(gate);
178 }
179 }
180
181 return VisitEqualCompareOrNotEqualCompare(gate);
182 }
183
VisitEqualCompareOrNotEqualCompare(GateRef gate)184 GateRef NumberSpeculativeRetype::VisitEqualCompareOrNotEqualCompare(GateRef gate)
185 {
186 if (acc_.HasNumberType(gate)) {
187 return VisitNumberBinaryOp(gate);
188 } else {
189 return VisitUndefinedEqualCompareOrUndefinedNotEqualCompare(gate);
190 }
191 }
192
VisitUndefinedEqualCompareOrUndefinedNotEqualCompare(GateRef gate)193 GateRef NumberSpeculativeRetype::VisitUndefinedEqualCompareOrUndefinedNotEqualCompare(GateRef gate)
194 {
195 ASSERT(acc_.GetTypedBinaryOp(gate) == TypedBinOp::TYPED_STRICTEQ ||
196 acc_.GetTypedBinaryOp(gate) == TypedBinOp::TYPED_STRICTNOTEQ ||
197 acc_.GetTypedBinaryOp(gate) == TypedBinOp::TYPED_EQ ||
198 acc_.GetTypedBinaryOp(gate) == TypedBinOp::TYPED_NOTEQ);
199 GateRef left = acc_.GetValueIn(gate, 0);
200 GateRef right = acc_.GetValueIn(gate, 1);
201 ASSERT((acc_.IsUndefinedOrNull(left)) || (acc_.IsUndefinedOrNull(right)));
202 if (IsRetype()) {
203 return SetOutputType(gate, GateType::BooleanType());
204 }
205 if (IsConvert()) {
206 acc_.ReplaceValueIn(gate, ConvertToTagged(left), 0);
207 acc_.ReplaceValueIn(gate, ConvertToTagged(right), 1);
208 }
209 return Circuit::NullGate();
210 }
211
VisitConstant(GateRef gate)212 GateRef NumberSpeculativeRetype::VisitConstant(GateRef gate)
213 {
214 if (IsRetype()) {
215 if (acc_.GetGateType(gate).IsNJSValueType()) {
216 auto machineType = acc_.GetMachineType(gate);
217 switch (machineType) {
218 case MachineType::I1:
219 SetOutputTypeInfo(gate, TypeInfo::INT1);
220 break;
221 case MachineType::I32:
222 SetOutputTypeInfo(gate, TypeInfo::INT32);
223 break;
224 case MachineType::F64:
225 SetOutputTypeInfo(gate, TypeInfo::FLOAT64);
226 break;
227 default:
228 SetOutputTypeInfo(gate, TypeInfo::NONE);
229 break;
230 }
231 } else {
232 return SetOutputType(gate, GateType::AnyType());
233 }
234 }
235 return Circuit::NullGate();
236 }
237
VisitIntermediateValue(GateRef gate)238 GateRef NumberSpeculativeRetype::VisitIntermediateValue(GateRef gate)
239 {
240 GateRef value = acc_.GetValueIn(gate, 0);
241 TypeInfo valueInfo = GetOutputTypeInfo(value);
242 if (IsRetype()) {
243 TypeInfo oldType = GetOutputTypeInfo(gate);
244 SetOutputTypeInfo(gate, valueInfo);
245 return oldType == valueInfo ? Circuit::NullGate() : gate;
246 }
247 return Circuit::NullGate();
248 }
249
VisitStringBinaryOp(GateRef gate)250 GateRef NumberSpeculativeRetype::VisitStringBinaryOp(GateRef gate)
251 {
252 TypedBinOp op = acc_.GetTypedBinaryOp(gate);
253 switch (op) {
254 case TypedBinOp::TYPED_EQ:
255 return VisitStringCompare(gate);
256 case TypedBinOp::TYPED_ADD:
257 return VisitStringAdd(gate);
258 default:
259 return Circuit::NullGate();
260 }
261 }
262
VisitStringCompare(GateRef gate)263 GateRef NumberSpeculativeRetype::VisitStringCompare(GateRef gate)
264 {
265 if (IsRetype()) {
266 return SetOutputType(gate, GateType::BooleanType());
267 }
268
269 Environment env(gate, circuit_, &builder_);
270 GateRef left = acc_.GetValueIn(gate, 0);
271 GateRef right = acc_.GetValueIn(gate, 1);
272 TypeInfo leftInfo = GetOutputTypeInfo(left);
273 TypeInfo rightInfo = GetOutputTypeInfo(right);
274 if (leftInfo == TypeInfo::CHAR && rightInfo == TypeInfo::CHAR) {
275 return Circuit::NullGate();
276 }
277 if (leftInfo == TypeInfo::CHAR) {
278 GateRef rep = builder_.ConvertCharToEcmaString(left);
279 acc_.ReplaceValueIn(gate, rep, 0);
280 }
281 if (rightInfo == TypeInfo::CHAR) {
282 GateRef rep = builder_.ConvertCharToEcmaString(right);
283 acc_.ReplaceValueIn(gate, rep, 1);
284 }
285 return Circuit::NullGate();
286 }
287
VisitStringAdd(GateRef gate)288 GateRef NumberSpeculativeRetype::VisitStringAdd(GateRef gate)
289 {
290 if (IsRetype()) {
291 return SetOutputType(gate, GateType::StringType());
292 }
293 if (IsConvert()) {
294 Environment env(gate, circuit_, &builder_);
295 size_t valueNum = acc_.GetNumValueIn(gate);
296 for (size_t i = 0; i < valueNum; ++i) {
297 GateRef input = acc_.GetValueIn(gate, i);
298 TypeInfo inputInfo = GetOutputTypeInfo(input);
299 if (inputInfo == TypeInfo::CHAR) {
300 GateRef glue = acc_.GetGlueFromArgList();
301 input = builder_.CallStub(glue, gate, CommonStubCSigns::CreateStringBySingleCharCode, { glue, input });
302 }
303 acc_.ReplaceValueIn(gate, input, i);
304 }
305 }
306 return Circuit::NullGate();
307 }
308
GetOuputForPhi(GateRef gate,bool ignoreConstant)309 TypeInfo NumberSpeculativeRetype::GetOuputForPhi(GateRef gate, bool ignoreConstant)
310 {
311 size_t valueNum = acc_.GetNumValueIn(gate);
312 bool hasConstantInput = false;
313 TypeInfo tempType = TypeInfo::NONE;
314 for (size_t i = 0; i < valueNum; ++i) {
315 GateRef input = acc_.GetValueIn(gate, i);
316 TypeInfo inputInfo = GetOutputTypeInfo(input);
317 if (inputInfo == TypeInfo::NONE) {
318 continue;
319 }
320 if (ignoreConstant && acc_.IsConstantNumber(input)) {
321 hasConstantInput = true;
322 continue;
323 }
324 // use less general input as phi output
325 if (tempType == TypeInfo::NONE) {
326 tempType = inputInfo;
327 } else if (tempType != inputInfo) {
328 tempType = TypeInfo::TAGGED;
329 break;
330 }
331 }
332
333 if (hasConstantInput && ignoreConstant && tempType == TypeInfo::NONE) {
334 return GetOuputForPhi(gate, false);
335 }
336 return tempType;
337 }
338
VisitPhi(GateRef gate)339 GateRef NumberSpeculativeRetype::VisitPhi(GateRef gate)
340 {
341 if (IsRetype()) {
342 auto tempType = GetOuputForPhi(gate, true);
343 TypeInfo typeInfo = GetOutputTypeInfo(gate);
344 if (typeInfo != tempType) {
345 SetOutputTypeInfo(gate, tempType);
346 return gate;
347 }
348 return Circuit::NullGate();
349 }
350 ASSERT(IsConvert());
351 size_t valueNum = acc_.GetNumValueIn(gate);
352 auto merge = acc_.GetState(gate);
353 auto dependSelector = acc_.GetDependSelectorFromMerge(merge);
354 TypeInfo output = GetOutputTypeInfo(gate);
355 for (size_t i = 0; i < valueNum; ++i) {
356 GateRef input = acc_.GetValueIn(gate, i);
357 if (output == TypeInfo::TAGGED || output == TypeInfo::NONE) {
358 input = ConvertToTagged(input);
359 } else {
360 auto state = acc_.GetState(merge, i);
361 auto depend = acc_.GetDep(dependSelector, i);
362 Environment env(state, depend, {}, circuit_, &builder_);
363 input = ConvertTaggedToNJSValue(input, output);
364 acc_.ReplaceStateIn(merge, builder_.GetState(), i);
365 acc_.ReplaceDependIn(dependSelector, builder_.GetDepend(), i);
366 }
367 acc_.ReplaceValueIn(gate, input, i);
368 }
369 return Circuit::NullGate();
370 }
371
ConvertTaggedToNJSValue(GateRef gate,TypeInfo output)372 GateRef NumberSpeculativeRetype::ConvertTaggedToNJSValue(GateRef gate, TypeInfo output)
373 {
374 TypeInfo curOutput = GetOutputTypeInfo(gate);
375 if (curOutput != TypeInfo::TAGGED) {
376 return gate;
377 }
378 switch (output) {
379 case TypeInfo::INT1:
380 return CheckAndConvertToBool(gate, GateType::BooleanType());
381 case TypeInfo::INT32:
382 return CheckAndConvertToInt32(gate, GateType::NumberType());
383 case TypeInfo::FLOAT64:
384 return CheckAndConvertToFloat64(gate, GateType::NumberType());
385 default:
386 LOG_COMPILER(FATAL) << "this branch is unreachable";
387 UNREACHABLE();
388 return Circuit::NullGate();
389 }
390 }
391
VisitNumberBinaryOp(GateRef gate)392 GateRef NumberSpeculativeRetype::VisitNumberBinaryOp(GateRef gate)
393 {
394 TypedBinOp op = acc_.GetTypedBinaryOp(gate);
395 switch (op) {
396 case TypedBinOp::TYPED_ADD:
397 case TypedBinOp::TYPED_SUB:
398 case TypedBinOp::TYPED_MUL:
399 case TypedBinOp::TYPED_DIV: {
400 return VisitNumberCalculate(gate);
401 }
402 case TypedBinOp::TYPED_LESS:
403 case TypedBinOp::TYPED_LESSEQ:
404 case TypedBinOp::TYPED_GREATER:
405 case TypedBinOp::TYPED_GREATEREQ:
406 case TypedBinOp::TYPED_EQ:
407 case TypedBinOp::TYPED_NOTEQ:
408 case TypedBinOp::TYPED_STRICTEQ:
409 case TypedBinOp::TYPED_STRICTNOTEQ: {
410 return VisitNumberCompare(gate);
411 }
412 case TypedBinOp::TYPED_SHL:
413 case TypedBinOp::TYPED_SHR:
414 case TypedBinOp::TYPED_ASHR:
415 case TypedBinOp::TYPED_AND:
416 case TypedBinOp::TYPED_OR:
417 case TypedBinOp::TYPED_XOR: {
418 return VisitNumberShiftAndLogical(gate);
419 }
420 case TypedBinOp::TYPED_MOD: {
421 return VisitNumberMod(gate);
422 }
423 default:
424 return VisitNumberRelated(gate);
425 }
426 }
427
VisitTypedUnaryOp(GateRef gate)428 GateRef NumberSpeculativeRetype::VisitTypedUnaryOp(GateRef gate)
429 {
430 Environment env(gate, circuit_, &builder_);
431 TypedUnOp Op = acc_.GetTypedUnAccessor(gate).GetTypedUnOp();
432 switch (Op) {
433 case TypedUnOp::TYPED_INC:
434 case TypedUnOp::TYPED_DEC:
435 case TypedUnOp::TYPED_NEG:
436 return VisitNumberMonocular(gate);
437 case TypedUnOp::TYPED_NOT:
438 return VisitNumberNot(gate);
439 case TypedUnOp::TYPED_ISFALSE:
440 case TypedUnOp::TYPED_ISTRUE:
441 return VisitIsTrueOrFalse(gate);
442 default:
443 return VisitNumberRelated(gate);
444 }
445 }
446
VisitTypedConditionJump(GateRef gate)447 GateRef NumberSpeculativeRetype::VisitTypedConditionJump(GateRef gate)
448 {
449 Environment env(gate, circuit_, &builder_);
450 TypedUnaryAccessor accessor(acc_.TryGetValue(gate));
451 auto type = accessor.GetTypeValue();
452 if (type.IsBooleanType()) {
453 return VisitBooleanJump(gate);
454 } else {
455 UNREACHABLE();
456 return Circuit::NullGate();
457 }
458 }
459
VisitNumberCalculate(GateRef gate)460 GateRef NumberSpeculativeRetype::VisitNumberCalculate(GateRef gate)
461 {
462 if (IsRetype()) {
463 const PGOSampleType *sampleType = acc_.GetTypedBinaryType(gate).GetPGOSampleType();
464 if (sampleType->IsNumber()) {
465 return SetOutputType(gate, *sampleType);
466 } else {
467 GateType gateType = acc_.GetGateType(gate);
468 GateType resType = gateType.IsIntType() ? GateType::IntType() : GateType::DoubleType();
469 return SetOutputType(gate, resType);
470 }
471 } else if (IsConvert()) {
472 Environment env(gate, circuit_, &builder_);
473 ConvertForBinaryOp(gate);
474 }
475 return Circuit::NullGate();
476 }
477
VisitNumberCompare(GateRef gate)478 GateRef NumberSpeculativeRetype::VisitNumberCompare(GateRef gate)
479 {
480 if (IsRetype()) {
481 return SetOutputType(gate, GateType::BooleanType());
482 }
483 if (IsConvert()) {
484 Environment env(gate, circuit_, &builder_);
485 ConvertForCompareOp(gate);
486 }
487 return Circuit::NullGate();
488 }
489
VisitNumberShiftAndLogical(GateRef gate)490 GateRef NumberSpeculativeRetype::VisitNumberShiftAndLogical(GateRef gate)
491 {
492 if (IsRetype()) {
493 return SetOutputType(gate, GateType::IntType());
494 }
495 if (IsConvert()) {
496 Environment env(gate, circuit_, &builder_);
497 GateType leftType = acc_.GetLeftType(gate);
498 GateType rightType = acc_.GetRightType(gate);
499 const PGOSampleType *sampleType = acc_.GetTypedBinaryType(gate).GetPGOSampleType();
500 if (sampleType->IsNumber()) {
501 if (sampleType->IsInt()) {
502 leftType = GateType::IntType();
503 rightType = GateType::IntType();
504 } else {
505 leftType = GateType::NumberType();
506 rightType = GateType::NumberType();
507 }
508 }
509 ConvertForShiftAndLogicalOperator(gate, leftType, rightType);
510 }
511 return Circuit::NullGate();
512 }
513
VisitNumberMonocular(GateRef gate)514 GateRef NumberSpeculativeRetype::VisitNumberMonocular(GateRef gate)
515 {
516 TypedUnaryAccessor accessor(acc_.TryGetValue(gate));
517 GateType type = accessor.GetTypeValue();
518 ASSERT(type.IsPrimitiveNumberType());
519 if (type.IsIntType()) {
520 return VisitIntMonocular(gate);
521 } else {
522 return VisitDoubleMonocular(gate);
523 }
524 }
525
VisitIntMonocular(GateRef gate)526 GateRef NumberSpeculativeRetype::VisitIntMonocular(GateRef gate)
527 {
528 if (IsRetype()) {
529 return SetOutputType(gate, GateType::IntType());
530 }
531
532 if (IsConvert()) {
533 GateRef value = acc_.GetValueIn(gate, 0);
534 acc_.ReplaceValueIn(gate, CheckAndConvertToInt32(value, GateType::IntType()), 0);
535 acc_.ReplaceStateIn(gate, builder_.GetState());
536 acc_.ReplaceDependIn(gate, builder_.GetDepend());
537 }
538 return Circuit::NullGate();
539 }
540
VisitDoubleMonocular(GateRef gate)541 GateRef NumberSpeculativeRetype::VisitDoubleMonocular(GateRef gate)
542 {
543 if (IsRetype()) {
544 return SetOutputType(gate, GateType::DoubleType());
545 }
546
547 if (IsConvert()) {
548 TypedUnaryAccessor accessor(acc_.TryGetValue(gate));
549 GateRef value = acc_.GetValueIn(gate, 0);
550 acc_.ReplaceValueIn(gate, CheckAndConvertToFloat64(value, accessor.GetTypeValue()), 0);
551 acc_.ReplaceStateIn(gate, builder_.GetState());
552 acc_.ReplaceDependIn(gate, builder_.GetDepend());
553 }
554 return Circuit::NullGate();
555 }
556
VisitIsTrueOrFalse(GateRef gate)557 GateRef NumberSpeculativeRetype::VisitIsTrueOrFalse(GateRef gate)
558 {
559 TypedUnaryAccessor accessor(acc_.TryGetValue(gate));
560 GateType valueType = accessor.GetTypeValue();
561 ASSERT(valueType.IsPrimitiveNumberType());
562 if (IsRetype()) {
563 return SetOutputType(gate, GateType::BooleanType());
564 }
565 if (IsConvert()) {
566 Environment env(gate, circuit_, &builder_);
567 GateRef value = acc_.GetValueIn(gate, 0);
568 auto input = CheckAndConvertToBool(value, valueType);
569 ResizeAndSetTypeInfo(input, TypeInfo::INT1);
570 acc_.ReplaceValueIn(gate, input, 0);
571 acc_.ReplaceStateIn(gate, builder_.GetState());
572 acc_.ReplaceDependIn(gate, builder_.GetDepend());
573 }
574 return Circuit::NullGate();
575 }
576
VisitNumberNot(GateRef gate)577 GateRef NumberSpeculativeRetype::VisitNumberNot(GateRef gate)
578 {
579 TypedUnaryAccessor accessor(acc_.TryGetValue(gate));
580 GateType valueType = accessor.GetTypeValue();
581 ASSERT(valueType.IsPrimitiveNumberType());
582 if (IsRetype()) {
583 return SetOutputType(gate, GateType::IntType());
584 }
585 if (IsConvert()) {
586 Environment env(gate, circuit_, &builder_);
587 GateRef value = acc_.GetValueIn(gate, 0);
588 acc_.ReplaceValueIn(gate,
589 CheckAndConvertToInt32(value, valueType, ConvertSupport::ENABLE, OpType::SHIFT_AND_LOGICAL), 0);
590 acc_.ReplaceStateIn(gate, builder_.GetState());
591 acc_.ReplaceDependIn(gate, builder_.GetDepend());
592 }
593 return Circuit::NullGate();
594 }
595
VisitBooleanJump(GateRef gate)596 GateRef NumberSpeculativeRetype::VisitBooleanJump(GateRef gate)
597 {
598 if (IsRetype()) {
599 return SetOutputType(gate, GateType::AnyType());
600 }
601 if (IsConvert()) {
602 Environment env(gate, circuit_, &builder_);
603 GateRef value = acc_.GetValueIn(gate, 0);
604 GateRef input = Circuit::NullGate();
605 if (GetOutputTypeInfo(value) == TypeInfo::TAGGED) {
606 // use TaggedIsTrue
607 input = builder_.ConvertTaggedBooleanToBool(value);
608 } else {
609 input = CheckAndConvertToBool(value, GateType::BooleanType());
610 }
611 ResizeAndSetTypeInfo(input, TypeInfo::INT1);
612 acc_.ReplaceValueIn(gate, input, 0);
613 acc_.ReplaceStateIn(gate, builder_.GetState());
614 acc_.ReplaceDependIn(gate, builder_.GetDepend());
615 }
616 return Circuit::NullGate();
617 }
618
VisitNumberRelated(GateRef gate)619 GateRef NumberSpeculativeRetype::VisitNumberRelated(GateRef gate)
620 {
621 if (IsRetype()) {
622 return SetOutputType(gate, GateType::NumberType());
623 }
624 if (IsConvert()) {
625 Environment env(gate, circuit_, &builder_);
626 size_t valueNum = acc_.GetNumValueIn(gate);
627 for (size_t i = 0; i < valueNum; ++i) {
628 GateRef input = acc_.GetValueIn(gate, i);
629 GateType inputType = acc_.GetGateType(input);
630 if (inputType.IsNumberType() || inputType.IsBooleanType()) {
631 acc_.ReplaceValueIn(gate, CheckAndConvertToTagged(input, inputType), i);
632 }
633 }
634 acc_.ReplaceStateIn(gate, builder_.GetState());
635 acc_.ReplaceDependIn(gate, builder_.GetDepend());
636 }
637 return Circuit::NullGate();
638 }
639
VisitCallBuiltins(GateRef gate)640 GateRef NumberSpeculativeRetype::VisitCallBuiltins(GateRef gate)
641 {
642 auto valuesIn = acc_.GetNumValueIn(gate);
643 auto idGate = acc_.GetValueIn(gate, valuesIn - 1);
644 auto id = static_cast<BuiltinsStubCSigns::ID>(acc_.GetConstantValue(idGate));
645 if (id != BUILTINS_STUB_ID(SQRT)) {
646 return VisitOthers(gate);
647 }
648
649 if (IsRetype()) {
650 // Sqrt output is double
651 return SetOutputType(gate, GateType::DoubleType());
652 }
653 if (IsConvert()) {
654 Environment env(gate, circuit_, &builder_);
655 acc_.ReplaceValueIn(gate, ConvertToTagged(idGate), valuesIn - 1);
656 for (size_t i = 0; i < valuesIn - 1; ++i) {
657 GateRef input = acc_.GetValueIn(gate, i);
658 acc_.ReplaceValueIn(gate, CheckAndConvertToFloat64(input, GateType::NumberType()), i);
659 }
660 acc_.ReplaceStateIn(gate, builder_.GetState());
661 acc_.ReplaceDependIn(gate, builder_.GetDepend());
662 }
663 return Circuit::NullGate();
664 }
665
VisitFrameState(GateRef gate)666 GateRef NumberSpeculativeRetype::VisitFrameState(GateRef gate)
667 {
668 if (IsRetype()) {
669 return SetOutputType(gate, GateType::AnyType());
670 }
671 return Circuit::NullGate();
672 }
673
VisitOthers(GateRef gate)674 GateRef NumberSpeculativeRetype::VisitOthers(GateRef gate)
675 {
676 if (IsRetype()) {
677 return SetOutputType(gate, GateType::AnyType());
678 }
679 if (IsConvert()) {
680 size_t valueNum = acc_.GetNumValueIn(gate);
681 for (size_t i = 0; i < valueNum; ++i) {
682 GateRef input = acc_.GetValueIn(gate, i);
683 acc_.ReplaceValueIn(gate, ConvertToTagged(input), i);
684 }
685 }
686 return Circuit::NullGate();
687 }
688
VisitWithConstantValue(GateRef gate,size_t ignoreIndex)689 GateRef NumberSpeculativeRetype::VisitWithConstantValue(GateRef gate, size_t ignoreIndex)
690 {
691 if (IsRetype()) {
692 return SetOutputType(gate, GateType::AnyType());
693 }
694 if (IsConvert()) {
695 size_t valueNum = acc_.GetNumValueIn(gate);
696 for (size_t i = 0; i < valueNum; ++i) {
697 if (i == ignoreIndex) {
698 continue;
699 }
700 GateRef input = acc_.GetValueIn(gate, i);
701 acc_.ReplaceValueIn(gate, ConvertToTagged(input), i);
702 }
703 }
704 return Circuit::NullGate();
705 }
706
CheckAndConvertToBool(GateRef gate,GateType gateType)707 GateRef NumberSpeculativeRetype::CheckAndConvertToBool(GateRef gate, GateType gateType)
708 {
709 TypeInfo output = GetOutputTypeInfo(gate);
710 switch (output) {
711 case TypeInfo::INT1:
712 return gate;
713 case TypeInfo::INT32:
714 return builder_.ConvertInt32ToBool(gate);
715 case TypeInfo::UINT32:
716 return builder_.ConvertUInt32ToBool(gate);
717 case TypeInfo::FLOAT64:
718 return builder_.ConvertFloat64ToBool(gate);
719 case TypeInfo::NONE:
720 case TypeInfo::TAGGED: {
721 if (gateType.IsBooleanType()) {
722 return builder_.CheckTaggedBooleanAndConvertToBool(gate);
723 } else if (gateType.IsUndefinedType()) {
724 return builder_.CheckUndefinedAndConvertToBool(gate);
725 } else if (gateType.IsNullType()) {
726 return builder_.CheckNullAndConvertToBool(gate);
727 } else {
728 ASSERT(gateType.IsNumberType());
729 return builder_.CheckTaggedNumberAndConvertToBool(gate);
730 }
731 }
732 default: {
733 UNREACHABLE();
734 return Circuit::NullGate();
735 }
736 }
737 }
738
ConvertForBinaryOp(GateRef gate)739 void NumberSpeculativeRetype::ConvertForBinaryOp(GateRef gate)
740 {
741 const PGOSampleType *sampleType = acc_.GetTypedBinaryType(gate).GetPGOSampleType();
742 if (sampleType->IsNumber()) {
743 if (sampleType->IsInt()) {
744 GateType leftType = GateType::IntType();
745 GateType rightType = GateType::IntType();
746 ConvertForIntOperator(gate, leftType, rightType);
747 } else {
748 GateType leftType = GateType::NumberType();
749 GateType rightType = GateType::NumberType();
750 if (sampleType->IsIntOverFlow()) {
751 leftType = GateType::IntType();
752 rightType = GateType::IntType();
753 } else if (sampleType->IsDouble()) {
754 leftType = GateType::DoubleType();
755 rightType = GateType::DoubleType();
756 }
757 ConvertForDoubleOperator(gate, leftType, rightType);
758 }
759 } else {
760 GateType gateType = acc_.GetGateType(gate);
761 GateType leftType = acc_.GetLeftType(gate);
762 GateType rightType = acc_.GetRightType(gate);
763 if (gateType.IsIntType()) {
764 ConvertForIntOperator(gate, leftType, rightType);
765 } else {
766 ConvertForDoubleOperator(gate, leftType, rightType);
767 }
768 }
769 }
770
ConvertForCompareOp(GateRef gate)771 void NumberSpeculativeRetype::ConvertForCompareOp(GateRef gate)
772 {
773 const PGOSampleType *sampleType = acc_.GetTypedBinaryType(gate).GetPGOSampleType();
774 if (sampleType->IsNumber()) {
775 if (sampleType->IsInt()) {
776 GateType leftType = GateType::IntType();
777 GateType rightType = GateType::IntType();
778 ConvertForIntOperator(gate, leftType, rightType);
779 } else {
780 GateType leftType = GateType::NumberType();
781 GateType rightType = GateType::NumberType();
782 ConvertForDoubleOperator(gate, leftType, rightType);
783 }
784 } else {
785 GateType leftType = acc_.GetLeftType(gate);
786 GateType rightType = acc_.GetRightType(gate);
787 if (leftType.IsIntType() && rightType.IsIntType()) {
788 ConvertForIntOperator(gate, leftType, rightType);
789 } else {
790 ConvertForDoubleOperator(gate, leftType, rightType);
791 }
792 }
793 }
794
ConvertForIntOperator(GateRef gate,GateType leftType,GateType rightType)795 void NumberSpeculativeRetype::ConvertForIntOperator(GateRef gate, GateType leftType, GateType rightType)
796 {
797 GateRef left = acc_.GetValueIn(gate, 0);
798 GateRef right = acc_.GetValueIn(gate, 1);
799
800 acc_.ReplaceValueIn(gate, CheckAndConvertToInt32(left, leftType), 0);
801 acc_.ReplaceValueIn(gate, CheckAndConvertToInt32(right, rightType), 1);
802
803 acc_.ReplaceStateIn(gate, builder_.GetState());
804 acc_.ReplaceDependIn(gate, builder_.GetDepend());
805 }
806
ConvertForShiftAndLogicalOperator(GateRef gate,GateType leftType,GateType rightType)807 void NumberSpeculativeRetype::ConvertForShiftAndLogicalOperator(GateRef gate, GateType leftType, GateType rightType)
808 {
809 GateRef left = acc_.GetValueIn(gate, 0);
810 GateRef right = acc_.GetValueIn(gate, 1);
811 GateRef cLeft = CheckAndConvertToInt32(left, leftType, ConvertSupport::ENABLE, OpType::SHIFT_AND_LOGICAL);
812 GateRef cRight = CheckAndConvertToInt32(right, rightType, ConvertSupport::ENABLE, OpType::SHIFT_AND_LOGICAL);
813
814 acc_.ReplaceValueIn(gate, cLeft, 0);
815 acc_.ReplaceValueIn(gate, cRight, 1);
816
817 acc_.ReplaceStateIn(gate, builder_.GetState());
818 acc_.ReplaceDependIn(gate, builder_.GetDepend());
819 }
820
ConvertForDoubleOperator(GateRef gate,GateType leftType,GateType rightType)821 void NumberSpeculativeRetype::ConvertForDoubleOperator(GateRef gate, GateType leftType, GateType rightType)
822 {
823 GateRef left = acc_.GetValueIn(gate, 0);
824 GateRef right = acc_.GetValueIn(gate, 1);
825
826 acc_.ReplaceValueIn(gate, CheckAndConvertToFloat64(left, leftType), 0);
827 acc_.ReplaceValueIn(gate, CheckAndConvertToFloat64(right, rightType), 1);
828
829 acc_.ReplaceStateIn(gate, builder_.GetState());
830 acc_.ReplaceDependIn(gate, builder_.GetDepend());
831 }
832
TryConvertConstant(GateRef gate,bool needInt32)833 GateRef NumberSpeculativeRetype::TryConvertConstant(GateRef gate, bool needInt32)
834 {
835 if (acc_.GetOpCode(gate) != OpCode::CONSTANT) {
836 return Circuit::NullGate();
837 }
838
839 if (acc_.GetGateType(gate).IsNJSValueType()) {
840 MachineType mType = acc_.GetMachineType(gate);
841 if (mType == MachineType::I32) {
842 int32_t rawValue = acc_.GetInt32FromConstant(gate);
843 double value = static_cast<double>(rawValue);
844 return needInt32 ? builder_.Int32(rawValue) : builder_.Double(value);
845 } else if (mType == MachineType::F64 && !needInt32) {
846 double rawValue = acc_.GetFloat64FromConstant(gate);
847 return builder_.Double(rawValue);
848 } else {
849 return Circuit::NullGate();
850 }
851 }
852
853 JSTaggedValue value(acc_.GetConstantValue(gate));
854 if (value.IsInt()) {
855 int32_t rawValue = value.GetInt();
856 double doubleValue = static_cast<double>(rawValue);
857 return needInt32 ? builder_.Int32(rawValue) : builder_.Double(doubleValue);
858 } else if (value.IsDouble() && !needInt32) {
859 double rawValue = value.GetDouble();
860 return builder_.Double(rawValue);
861 }
862 return Circuit::NullGate();
863 }
864
CheckAndConvertToInt32(GateRef gate,GateType gateType,ConvertSupport support,OpType type)865 GateRef NumberSpeculativeRetype::CheckAndConvertToInt32(GateRef gate, GateType gateType, ConvertSupport support,
866 OpType type)
867 {
868 auto result = TryConvertConstant(gate, true);
869 if (result != Circuit::NullGate()) {
870 acc_.DeleteGateIfNoUse(gate);
871 ResizeAndSetTypeInfo(result, TypeInfo::INT32);
872 return result;
873 }
874 TypeInfo output = GetOutputTypeInfo(gate);
875 switch (output) {
876 case TypeInfo::INT1:
877 result = builder_.ConvertBoolToInt32(gate, support);
878 break;
879 case TypeInfo::CHAR:
880 case TypeInfo::INT32:
881 return gate;
882 case TypeInfo::UINT32: {
883 if (type != OpType::SHIFT_AND_LOGICAL) {
884 result = builder_.CheckUInt32AndConvertToInt32(gate);
885 } else {
886 result = gate;
887 }
888 break;
889 }
890 case TypeInfo::FLOAT64:
891 result = builder_.ConvertFloat64ToInt32(gate);
892 break;
893 case TypeInfo::NONE:
894 case TypeInfo::TAGGED: {
895 if (gateType.IsIntType()) {
896 result = builder_.CheckTaggedIntAndConvertToInt32(gate);
897 } else if (gateType.IsDoubleType()) {
898 result = builder_.CheckTaggedDoubleAndConvertToInt32(gate);
899 } else if (gateType.IsNullType()) {
900 result = builder_.CheckNullAndConvertToInt32(gate);
901 } else if (gateType.IsBooleanType()) {
902 result = builder_.CheckTaggedBooleanAndConvertToInt32(gate);
903 } else if (gateType.IsUndefinedType()) {
904 if (type == OpType::SHIFT_AND_LOGICAL) {
905 result = builder_.CheckUndefinedAndConvertToInt32(gate);
906 } else {
907 LOG_ECMA(FATAL) << "undefined cannot convert to int type";
908 }
909 } else {
910 ASSERT(gateType.IsNumberType());
911 result = builder_.CheckTaggedNumberAndConvertToInt32(gate);
912 }
913 break;
914 }
915 default: {
916 LOG_ECMA(FATAL) << "this branch is unreachable";
917 UNREACHABLE();
918 return Circuit::NullGate();
919 }
920 }
921 ResizeAndSetTypeInfo(result, TypeInfo::INT32);
922 return result;
923 }
924
CheckAndConvertToFloat64(GateRef gate,GateType gateType,ConvertSupport support)925 GateRef NumberSpeculativeRetype::CheckAndConvertToFloat64(GateRef gate, GateType gateType, ConvertSupport support)
926 {
927 auto result = TryConvertConstant(gate, false);
928 if (result != Circuit::NullGate()) {
929 acc_.DeleteGateIfNoUse(gate);
930 ResizeAndSetTypeInfo(result, TypeInfo::FLOAT64);
931 return result;
932 }
933 TypeInfo output = GetOutputTypeInfo(gate);
934 switch (output) {
935 case TypeInfo::INT1:
936 result = builder_.ConvertBoolToFloat64(gate, support);
937 break;
938 case TypeInfo::INT32:
939 result = builder_.ConvertInt32ToFloat64(gate);
940 break;
941 case TypeInfo::UINT32:
942 result = builder_.ConvertUInt32ToFloat64(gate);
943 break;
944 case TypeInfo::FLOAT64:
945 return gate;
946 case TypeInfo::NONE:
947 case TypeInfo::TAGGED: {
948 if (gateType.IsIntType()) {
949 result = builder_.CheckTaggedIntAndConvertToFloat64(gate);
950 } else if (gateType.IsDoubleType()) {
951 result = builder_.CheckTaggedDoubleAndConvertToFloat64(gate);
952 } else if (gateType.IsNullType()) {
953 result = builder_.CheckNullAndConvertToFloat64(gate);
954 } else if (gateType.IsBooleanType()) {
955 result = builder_.CheckTaggedBooleanAndConvertToFloat64(gate);
956 } else if (gateType.IsUndefinedType()) {
957 result = builder_.CheckUndefinedAndConvertToFloat64(gate);
958 } else {
959 ASSERT(gateType.IsNumberType());
960 result = builder_.CheckTaggedNumberAndConvertToFloat64(gate);
961 }
962 break;
963 }
964 default: {
965 LOG_ECMA(FATAL) << "this branch is unreachable";
966 UNREACHABLE();
967 return Circuit::NullGate();
968 }
969 }
970 ResizeAndSetTypeInfo(result, TypeInfo::FLOAT64);
971 return result;
972 }
973
CheckAndConvertToTagged(GateRef gate,GateType gateType)974 GateRef NumberSpeculativeRetype::CheckAndConvertToTagged(GateRef gate, GateType gateType)
975 {
976 TypeInfo output = GetOutputTypeInfo(gate);
977 switch (output) {
978 case TypeInfo::INT1:
979 return builder_.ConvertBoolToTaggedBoolean(gate);
980 case TypeInfo::INT32:
981 return builder_.ConvertInt32ToTaggedInt(gate);
982 case TypeInfo::UINT32:
983 return builder_.ConvertUInt32ToTaggedNumber(gate);
984 case TypeInfo::FLOAT64:
985 return builder_.ConvertFloat64ToTaggedDouble(gate);
986 case TypeInfo::NONE:
987 case TypeInfo::TAGGED: {
988 ASSERT(gateType.IsNumberType() || gateType.IsBooleanType());
989 builder_.TryPrimitiveTypeCheck(gateType, gate);
990 return gate;
991 }
992 default:
993 LOG_ECMA(FATAL) << "this branch is unreachable";
994 UNREACHABLE();
995 return Circuit::NullGate();
996 }
997 }
998
ConvertToTagged(GateRef gate)999 GateRef NumberSpeculativeRetype::ConvertToTagged(GateRef gate)
1000 {
1001 TypeInfo output = GetOutputTypeInfo(gate);
1002 switch (output) {
1003 case TypeInfo::INT1:
1004 return builder_.ConvertBoolToTaggedBoolean(gate);
1005 case TypeInfo::INT32:
1006 return builder_.ConvertInt32ToTaggedInt(gate);
1007 case TypeInfo::UINT32:
1008 return builder_.ConvertUInt32ToTaggedNumber(gate);
1009 case TypeInfo::FLOAT64:
1010 return builder_.ConvertFloat64ToTaggedDouble(gate);
1011 case TypeInfo::CHAR:
1012 return builder_.ConvertCharToEcmaString(gate);
1013 case TypeInfo::NONE:
1014 case TypeInfo::TAGGED: {
1015 return gate;
1016 }
1017 default:
1018 LOG_ECMA(FATAL) << "this branch is unreachable";
1019 UNREACHABLE();
1020 return Circuit::NullGate();
1021 }
1022 }
1023
VisitRangeCheckPredicate(GateRef gate)1024 GateRef NumberSpeculativeRetype::VisitRangeCheckPredicate(GateRef gate)
1025 {
1026 if (IsRetype()) {
1027 return SetOutputType(gate, GateType::IntType());
1028 }
1029
1030 if (IsConvert()) {
1031 Environment env(gate, circuit_, &builder_);
1032 GateRef value0 = acc_.GetValueIn(gate, 0);
1033 GateRef value1 = acc_.GetValueIn(gate, 1);
1034 GateType value0Type = acc_.GetGateType(value0);
1035 GateType value1Type = acc_.GetGateType(value1);
1036 acc_.ReplaceValueIn(gate, CheckAndConvertToInt32(value0, value0Type), 0);
1037 acc_.ReplaceValueIn(gate, CheckAndConvertToInt32(value1, value1Type), 1);
1038
1039 acc_.ReplaceStateIn(gate, builder_.GetState());
1040 acc_.ReplaceDependIn(gate, builder_.GetDepend());
1041 }
1042
1043 return Circuit::NullGate();
1044 }
1045
VisitIndexCheck(GateRef gate)1046 GateRef NumberSpeculativeRetype::VisitIndexCheck(GateRef gate)
1047 {
1048 if (IsRetype()) {
1049 return SetOutputType(gate, GateType::IntType());
1050 }
1051
1052 if (IsConvert()) {
1053 Environment env(gate, circuit_, &builder_);
1054 GateRef receiver = acc_.GetValueIn(gate, 0);
1055 GateRef index = acc_.GetValueIn(gate, 1);
1056 GateType receiverType = acc_.GetGateType(receiver);
1057 GateType indexType = acc_.GetGateType(index);
1058 acc_.ReplaceValueIn(gate, CheckAndConvertToInt32(receiver, receiverType), 0);
1059 acc_.ReplaceValueIn(gate, CheckAndConvertToInt32(index, indexType), 1);
1060
1061 acc_.ReplaceStateIn(gate, builder_.GetState());
1062 acc_.ReplaceDependIn(gate, builder_.GetDepend());
1063 }
1064
1065 return Circuit::NullGate();
1066 }
1067
VisitLoadArrayLength(GateRef gate)1068 GateRef NumberSpeculativeRetype::VisitLoadArrayLength(GateRef gate)
1069 {
1070 if (IsRetype()) {
1071 return SetOutputType(gate, GateType::IntType());
1072 }
1073
1074 return Circuit::NullGate();
1075 }
1076
VisitLoadStringLength(GateRef gate)1077 GateRef NumberSpeculativeRetype::VisitLoadStringLength(GateRef gate)
1078 {
1079 if (IsRetype()) {
1080 return SetOutputType(gate, GateType::IntType());
1081 }
1082
1083 return Circuit::NullGate();
1084 }
1085
VisitLoadElement(GateRef gate)1086 GateRef NumberSpeculativeRetype::VisitLoadElement(GateRef gate)
1087 {
1088 if (IsRetype()) {
1089 auto op = acc_.GetTypedLoadOp(gate);
1090 switch (op) {
1091 case TypedLoadOp::INT8ARRAY_LOAD_ELEMENT:
1092 case TypedLoadOp::UINT8ARRAY_LOAD_ELEMENT:
1093 case TypedLoadOp::UINT8CLAMPEDARRAY_LOAD_ELEMENT:
1094 case TypedLoadOp::INT16ARRAY_LOAD_ELEMENT:
1095 case TypedLoadOp::UINT16ARRAY_LOAD_ELEMENT:
1096 case TypedLoadOp::INT32ARRAY_LOAD_ELEMENT:
1097 return SetOutputType(gate, GateType::IntType());
1098 case TypedLoadOp::UINT32ARRAY_LOAD_ELEMENT:
1099 return SetOutputType(gate, TypeInfo::UINT32);
1100 case TypedLoadOp::FLOAT32ARRAY_LOAD_ELEMENT:
1101 case TypedLoadOp::FLOAT64ARRAY_LOAD_ELEMENT:
1102 return SetOutputType(gate, GateType::DoubleType());
1103 case TypedLoadOp::STRING_LOAD_ELEMENT:
1104 return SetOutputType(gate, TypeInfo::CHAR);
1105 default:
1106 return SetOutputType(gate, GateType::AnyType());
1107 }
1108 }
1109
1110 if (IsConvert()) {
1111 Environment env(gate, circuit_, &builder_);
1112 GateRef index = acc_.GetValueIn(gate, 1);
1113 GateType indexType = acc_.GetGateType(index);
1114 acc_.ReplaceValueIn(gate, CheckAndConvertToInt32(index, indexType), 1);
1115 acc_.ReplaceStateIn(gate, builder_.GetState());
1116 acc_.ReplaceDependIn(gate, builder_.GetDepend());
1117 }
1118
1119 return Circuit::NullGate();
1120 }
1121
VisitStoreElement(GateRef gate)1122 GateRef NumberSpeculativeRetype::VisitStoreElement(GateRef gate)
1123 {
1124 if (IsRetype()) {
1125 return SetOutputType(gate, GateType::AnyType());
1126 }
1127
1128 if (IsConvert()) {
1129 Environment env(gate, circuit_, &builder_);
1130 GateRef index = acc_.GetValueIn(gate, 1);
1131 GateType indexType = acc_.GetGateType(index);
1132 GateRef value = acc_.GetValueIn(gate, 2);
1133 acc_.ReplaceValueIn(gate, CheckAndConvertToInt32(index, indexType), 1);
1134 auto op = acc_.GetTypedStoreOp(gate);
1135 switch (op) {
1136 case TypedStoreOp::INT8ARRAY_STORE_ELEMENT:
1137 case TypedStoreOp::UINT8ARRAY_STORE_ELEMENT:
1138 case TypedStoreOp::UINT8CLAMPEDARRAY_STORE_ELEMENT:
1139 case TypedStoreOp::INT16ARRAY_STORE_ELEMENT:
1140 case TypedStoreOp::UINT16ARRAY_STORE_ELEMENT:
1141 case TypedStoreOp::INT32ARRAY_STORE_ELEMENT:
1142 case TypedStoreOp::UINT32ARRAY_STORE_ELEMENT:
1143 acc_.ReplaceValueIn(gate, CheckAndConvertToInt32(value, GateType::NumberType()), 2); // 2: value idx
1144 break;
1145 case TypedStoreOp::FLOAT32ARRAY_STORE_ELEMENT:
1146 case TypedStoreOp::FLOAT64ARRAY_STORE_ELEMENT:
1147 acc_.ReplaceValueIn(gate, CheckAndConvertToFloat64(value, GateType::NumberType()), 2); // 2: value idx
1148 break;
1149 default:
1150 acc_.ReplaceValueIn(gate, ConvertToTagged(value), 2); // 2: value idx
1151 break;
1152 }
1153 acc_.ReplaceStateIn(gate, builder_.GetState());
1154 acc_.ReplaceDependIn(gate, builder_.GetDepend());
1155 }
1156
1157 return Circuit::NullGate();
1158 }
1159
VisitStoreProperty(GateRef gate)1160 GateRef NumberSpeculativeRetype::VisitStoreProperty(GateRef gate)
1161 {
1162 if (IsRetype()) {
1163 return SetOutputType(gate, GateType::AnyType());
1164 }
1165 ASSERT(IsConvert());
1166 GateRef value = acc_.GetValueIn(gate, 2); // 2: value
1167
1168 Environment env(gate, circuit_, &builder_);
1169 GateRef propertyLookupResult = acc_.GetValueIn(gate, 1);
1170 PropertyLookupResult plr(acc_.TryGetValue(propertyLookupResult));
1171 if (plr.GetRepresentation() == Representation::DOUBLE) {
1172 acc_.SetMetaData(gate, circuit_->StorePropertyNoBarrier());
1173 acc_.ReplaceValueIn(
1174 gate, CheckAndConvertToFloat64(value, GateType::NumberType(), ConvertSupport::DISABLE), 2); // 2: value
1175 } else if (plr.GetRepresentation() == Representation::INT) {
1176 acc_.SetMetaData(gate, circuit_->StorePropertyNoBarrier());
1177 acc_.ReplaceValueIn(
1178 gate, CheckAndConvertToInt32(value, GateType::IntType(), ConvertSupport::DISABLE), 2); // 2: value
1179 } else {
1180 TypeInfo valueType = GetOutputTypeInfo(value);
1181 if (valueType == TypeInfo::INT1 || valueType == TypeInfo::INT32 || valueType == TypeInfo::FLOAT64) {
1182 acc_.SetMetaData(gate, circuit_->StorePropertyNoBarrier());
1183 }
1184 acc_.ReplaceValueIn(gate, ConvertToTagged(value), 2); // 2: value
1185 }
1186
1187 GateRef receiver = acc_.GetValueIn(gate, 0); // receiver
1188 acc_.ReplaceValueIn(gate, ConvertToTagged(receiver), 0);
1189 acc_.ReplaceStateIn(gate, builder_.GetState());
1190 acc_.ReplaceDependIn(gate, builder_.GetDepend());
1191 return Circuit::NullGate();
1192 }
1193
VisitLoadProperty(GateRef gate)1194 GateRef NumberSpeculativeRetype::VisitLoadProperty(GateRef gate)
1195 {
1196 if (IsRetype()) {
1197 GateRef propertyLookupResult = acc_.GetValueIn(gate, 1);
1198 PropertyLookupResult plr(acc_.TryGetValue(propertyLookupResult));
1199 return SetOutputType(gate, plr.GetRepresentation());
1200 }
1201
1202 ASSERT(IsConvert());
1203
1204 return VisitWithConstantValue(gate, PROPERTY_LOOKUP_RESULT_INDEX); // ignoreIndex
1205 }
1206
VisitTypeConvert(GateRef gate)1207 GateRef NumberSpeculativeRetype::VisitTypeConvert(GateRef gate)
1208 {
1209 GateRef input = acc_.GetValueIn(gate, 0);
1210 TypeInfo inputInfo = GetOutputTypeInfo(input);
1211 if (IsRetype()) {
1212 if (inputInfo == TypeInfo::TAGGED) {
1213 if (acc_.IsConstantNumber(input)) {
1214 return Circuit::NullGate();
1215 }
1216 GateType gateType = acc_.GetGateType(gate);
1217 ASSERT(gateType.IsNumberType());
1218 GateType resType = gateType.IsIntType() ? GateType::IntType() : GateType::DoubleType();
1219 return SetOutputType(gate, resType);
1220 }
1221 TypeInfo oldType = GetOutputTypeInfo(gate);
1222 SetOutputTypeInfo(gate, inputInfo);
1223 return oldType == inputInfo ? Circuit::NullGate() : gate;
1224 }
1225 ASSERT(IsConvert());
1226 ASSERT(inputInfo != TypeInfo::INT1 && inputInfo != TypeInfo::NONE);
1227 Environment env(gate, circuit_, &builder_);
1228 if (inputInfo == TypeInfo::TAGGED && !acc_.IsConstantNumber(input)) {
1229 GateType gateType = acc_.GetGateType(gate);
1230 ASSERT(gateType.IsNumberType());
1231 if (gateType.IsIntType()) {
1232 input = CheckAndConvertToInt32(input, GateType::IntType());
1233 ResizeAndSetTypeInfo(input, TypeInfo::INT32);
1234 } else {
1235 input = CheckAndConvertToFloat64(input, acc_.GetGateType(input));
1236 ResizeAndSetTypeInfo(input, TypeInfo::FLOAT64);
1237 }
1238 }
1239 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), input);
1240 return Circuit::NullGate();
1241 }
1242
VisitNumberMod(GateRef gate)1243 GateRef NumberSpeculativeRetype::VisitNumberMod(GateRef gate)
1244 {
1245 if (IsRetype()) {
1246 const PGOSampleType *sampleType = acc_.GetTypedBinaryType(gate).GetPGOSampleType();
1247 if (sampleType->IsNumber()) {
1248 return SetOutputType(gate, *sampleType);
1249 } else {
1250 GateType gateType = acc_.GetGateType(gate);
1251 GateType resType = gateType.IsIntType() ? GateType::IntType() : GateType::DoubleType();
1252 return SetOutputType(gate, resType);
1253 }
1254 } else if (IsConvert()) {
1255 Environment env(gate, circuit_, &builder_);
1256 ConvertForBinaryOp(gate);
1257 }
1258
1259 return Circuit::NullGate();
1260 }
1261
VisitMonoLoadPropertyOnProto(GateRef gate)1262 GateRef NumberSpeculativeRetype::VisitMonoLoadPropertyOnProto(GateRef gate)
1263 {
1264 if (IsRetype()) {
1265 GateRef propertyLookupResult = acc_.GetValueIn(gate, 1);
1266 PropertyLookupResult plr(acc_.TryGetValue(propertyLookupResult));
1267 return SetOutputType(gate, plr.GetRepresentation());
1268 }
1269
1270 ASSERT(IsConvert());
1271 size_t valueNum = acc_.GetNumValueIn(gate);
1272 for (size_t i = 0; i < valueNum; ++i) {
1273 if (i == PROPERTY_LOOKUP_RESULT_INDEX || i == HCLASS_INDEX) {
1274 continue;
1275 }
1276 GateRef input = acc_.GetValueIn(gate, i);
1277 acc_.ReplaceValueIn(gate, ConvertToTagged(input), i);
1278 }
1279
1280 return Circuit::NullGate();
1281 }
1282
VisitMonoCallGetterOnProto(GateRef gate)1283 GateRef NumberSpeculativeRetype::VisitMonoCallGetterOnProto(GateRef gate)
1284 {
1285 if (IsRetype()) {
1286 return SetOutputType(gate, GateType::AnyType());
1287 }
1288 if (IsConvert()) {
1289 size_t valueNum = acc_.GetNumValueIn(gate);
1290 for (size_t i = 0; i < valueNum; ++i) {
1291 if (i == PROPERTY_LOOKUP_RESULT_INDEX || i == HCLASS_INDEX) {
1292 continue;
1293 }
1294 GateRef input = acc_.GetValueIn(gate, i);
1295 acc_.ReplaceValueIn(gate, ConvertToTagged(input), i);
1296 }
1297 }
1298 return Circuit::NullGate();
1299 }
1300
VisitMonoStoreProperty(GateRef gate)1301 GateRef NumberSpeculativeRetype::VisitMonoStoreProperty(GateRef gate)
1302 {
1303 if (IsRetype()) {
1304 return SetOutputType(gate, GateType::AnyType());
1305 }
1306 ASSERT(IsConvert());
1307
1308 GateRef value = acc_.GetValueIn(gate, 4); // 4: value
1309
1310 Environment env(gate, circuit_, &builder_);
1311 GateRef propertyLookupResult = acc_.GetValueIn(gate, 1);
1312 PropertyLookupResult plr(acc_.TryGetValue(propertyLookupResult));
1313 if (plr.IsAccessor()) {
1314 size_t valueNum = acc_.GetNumValueIn(gate);
1315 for (size_t i = 0; i < valueNum; ++i) {
1316 if (i == PROPERTY_LOOKUP_RESULT_INDEX || i == HCLASS_INDEX) {
1317 continue;
1318 }
1319 GateRef input = acc_.GetValueIn(gate, i);
1320 acc_.ReplaceValueIn(gate, ConvertToTagged(input), i);
1321 }
1322 return Circuit::NullGate();
1323 }
1324
1325 if (plr.GetRepresentation() == Representation::DOUBLE) {
1326 acc_.SetStoreNoBarrier(gate, true);
1327 acc_.ReplaceValueIn(
1328 gate, CheckAndConvertToFloat64(value, GateType::NumberType(), ConvertSupport::DISABLE), 4); // 4: value
1329 } else if (plr.GetRepresentation() == Representation::INT) {
1330 acc_.SetStoreNoBarrier(gate, true);
1331 acc_.ReplaceValueIn(
1332 gate, CheckAndConvertToInt32(value, GateType::IntType(), ConvertSupport::DISABLE), 4); // 4: value
1333 } else {
1334 TypeInfo valueType = GetOutputTypeInfo(value);
1335 if (valueType == TypeInfo::INT1 || valueType == TypeInfo::INT32 || valueType == TypeInfo::FLOAT64) {
1336 acc_.SetStoreNoBarrier(gate, true);
1337 }
1338 acc_.ReplaceValueIn(gate, ConvertToTagged(value), 4); // 4: value
1339 }
1340
1341 GateRef receiver = acc_.GetValueIn(gate, 0); // receiver
1342 acc_.ReplaceValueIn(gate, ConvertToTagged(receiver), 0);
1343 acc_.ReplaceStateIn(gate, builder_.GetState());
1344 acc_.ReplaceDependIn(gate, builder_.GetDepend());
1345 return Circuit::NullGate();
1346 }
1347
VisitGate(GateRef gate)1348 GateRef NumberSpeculativeRetypeManager::VisitGate(GateRef gate)
1349 {
1350 retype_->setState(state_);
1351 return retype_->VisitGate(gate);
1352 }
1353
1354 } // namespace panda::ecmascript::kungfu
1355