v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
turbofan-typer.cc
Go to the documentation of this file.
1// Copyright 2014 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
6
7#include <iomanip>
8
9#include "src/base/flags.h"
18#include "src/compiler/node.h"
24
25namespace v8 {
26namespace internal {
27namespace compiler {
28
29class Typer::Decorator final : public GraphDecorator {
30 public:
31 explicit Decorator(Typer* typer) : typer_(typer) {}
32 void Decorate(Node* node) final;
33
34 private:
35 Typer* const typer_;
36};
37
39 TickCounter* tick_counter)
40 : flags_(flags),
41 graph_(graph),
42 decorator_(nullptr),
43 cache_(TypeCache::Get()),
45 operation_typer_(broker, zone()),
46 tick_counter_(tick_counter) {
49
50 decorator_ = zone()->New<Decorator>(this);
52}
53
55
56class Typer::Visitor : public Reducer {
57 public:
58 explicit Visitor(Typer* typer, LoopVariableOptimizer* induction_vars)
59 : typer_(typer),
60 induction_vars_(induction_vars),
61 weakened_nodes_(typer->zone()) {}
62
63 const char* reducer_name() const override { return "Typer"; }
64
65 Reduction Reduce(Node* node) override {
66 if (node->op()->ValueOutputCount() == 0) return NoChange();
67 return UpdateType(node, TypeNode(node));
68 }
69
71 switch (node->opcode()) {
72#define DECLARE_UNARY_CASE(x, ...) \
73 case IrOpcode::k##x: \
74 return Type##x(Operand(node, 0));
80 DECLARE_UNARY_CASE(ChangeUint32ToUint64)
81#undef DECLARE_UNARY_CASE
82#define DECLARE_BINARY_CASE(x, ...) \
83 case IrOpcode::k##x: \
84 return Type##x(Operand(node, 0), Operand(node, 1));
91#undef DECLARE_BINARY_CASE
92#define DECLARE_OTHER_CASE(x, ...) \
93 case IrOpcode::k##x: \
94 return Type##x(node);
96 DECLARE_OTHER_CASE(IfException)
103#undef DECLARE_OTHER_CASE
104#define DECLARE_IMPOSSIBLE_CASE(x, ...) case IrOpcode::k##x:
109 DECLARE_IMPOSSIBLE_CASE(IfSuccess)
112 DECLARE_IMPOSSIBLE_CASE(IfDefault)
114 DECLARE_IMPOSSIBLE_CASE(Deoptimize)
115 DECLARE_IMPOSSIBLE_CASE(DeoptimizeIf)
116 DECLARE_IMPOSSIBLE_CASE(DeoptimizeUnless)
118 DECLARE_IMPOSSIBLE_CASE(TrapUnless)
131 DECLARE_IMPOSSIBLE_CASE(Word32Xor)
132 DECLARE_IMPOSSIBLE_CASE(Word32Sar)
133 DECLARE_IMPOSSIBLE_CASE(Word32Rol)
134 DECLARE_IMPOSSIBLE_CASE(Word32Ror)
135 DECLARE_IMPOSSIBLE_CASE(Int32AddWithOverflow)
136 DECLARE_IMPOSSIBLE_CASE(Int32SubWithOverflow)
138 DECLARE_IMPOSSIBLE_CASE(Int32MulWithOverflow)
139 DECLARE_IMPOSSIBLE_CASE(Int32MulHigh)
142 DECLARE_IMPOSSIBLE_CASE(Uint32Mod)
143 DECLARE_IMPOSSIBLE_CASE(Uint32MulHigh)
145 DECLARE_IMPOSSIBLE_CASE(Word64Xor)
146 DECLARE_IMPOSSIBLE_CASE(Word64Sar)
147 DECLARE_IMPOSSIBLE_CASE(Word64Rol)
148 DECLARE_IMPOSSIBLE_CASE(Word64Ror)
149 DECLARE_IMPOSSIBLE_CASE(Word64RolLowerable)
150 DECLARE_IMPOSSIBLE_CASE(Word64RorLowerable)
151 DECLARE_IMPOSSIBLE_CASE(Int64AddWithOverflow)
152 DECLARE_IMPOSSIBLE_CASE(Int64SubWithOverflow)
154 DECLARE_IMPOSSIBLE_CASE(Int64MulHigh)
155 DECLARE_IMPOSSIBLE_CASE(Int64MulWithOverflow)
158 DECLARE_IMPOSSIBLE_CASE(Uint64Mod)
159 DECLARE_IMPOSSIBLE_CASE(Uint64MulHigh)
160 DECLARE_IMPOSSIBLE_CASE(Word64Equal)
161 DECLARE_IMPOSSIBLE_CASE(Int32LessThan)
162 DECLARE_IMPOSSIBLE_CASE(Int64LessThan)
163 DECLARE_IMPOSSIBLE_CASE(Int64LessThanOrEqual)
164 DECLARE_IMPOSSIBLE_CASE(Float32Equal)
165 DECLARE_IMPOSSIBLE_CASE(Float32LessThan)
166 DECLARE_IMPOSSIBLE_CASE(Float32LessThanOrEqual)
167 DECLARE_IMPOSSIBLE_CASE(Float64Equal)
168 DECLARE_IMPOSSIBLE_CASE(Float64LessThan)
169 DECLARE_IMPOSSIBLE_CASE(Float64LessThanOrEqual)
175 DECLARE_IMPOSSIBLE_CASE(AbortCSADcheck)
176 DECLARE_IMPOSSIBLE_CASE(DebugBreak)
178 DECLARE_IMPOSSIBLE_CASE(LoadImmutable)
179 DECLARE_IMPOSSIBLE_CASE(StorePair)
181 DECLARE_IMPOSSIBLE_CASE(StoreIndirectPointer)
182 DECLARE_IMPOSSIBLE_CASE(StackSlot)
183 DECLARE_IMPOSSIBLE_CASE(Word32Popcnt)
184 DECLARE_IMPOSSIBLE_CASE(Word64Popcnt)
185 DECLARE_IMPOSSIBLE_CASE(Word64Clz)
186 DECLARE_IMPOSSIBLE_CASE(Word64Ctz)
187 DECLARE_IMPOSSIBLE_CASE(Word64ClzLowerable)
188 DECLARE_IMPOSSIBLE_CASE(Word64CtzLowerable)
189 DECLARE_IMPOSSIBLE_CASE(Word64ReverseBits)
190 DECLARE_IMPOSSIBLE_CASE(Word64ReverseBytes)
191 DECLARE_IMPOSSIBLE_CASE(Simd128ReverseBytes)
192 DECLARE_IMPOSSIBLE_CASE(Int64AbsWithOverflow)
193 DECLARE_IMPOSSIBLE_CASE(BitcastTaggedToWord)
194 DECLARE_IMPOSSIBLE_CASE(BitcastTaggedToWordForTagAndSmiBits)
195 DECLARE_IMPOSSIBLE_CASE(BitcastWordToTagged)
196 DECLARE_IMPOSSIBLE_CASE(BitcastWordToTaggedSigned)
197 DECLARE_IMPOSSIBLE_CASE(TruncateFloat64ToWord32)
198 DECLARE_IMPOSSIBLE_CASE(ChangeFloat32ToFloat64)
199 DECLARE_IMPOSSIBLE_CASE(ChangeFloat64ToInt32)
200 DECLARE_IMPOSSIBLE_CASE(ChangeFloat64ToInt64)
201 DECLARE_IMPOSSIBLE_CASE(ChangeFloat64ToUint32)
202 DECLARE_IMPOSSIBLE_CASE(ChangeFloat64ToUint64)
203 DECLARE_IMPOSSIBLE_CASE(Float64SilenceNaN)
204 DECLARE_IMPOSSIBLE_CASE(TruncateFloat64ToInt64)
205 DECLARE_IMPOSSIBLE_CASE(TruncateFloat64ToUint32)
206 DECLARE_IMPOSSIBLE_CASE(TruncateFloat32ToInt32)
207 DECLARE_IMPOSSIBLE_CASE(TruncateFloat32ToUint32)
208 DECLARE_IMPOSSIBLE_CASE(TryTruncateFloat32ToInt64)
209 DECLARE_IMPOSSIBLE_CASE(TryTruncateFloat64ToInt64)
210 DECLARE_IMPOSSIBLE_CASE(TryTruncateFloat32ToUint64)
211 DECLARE_IMPOSSIBLE_CASE(TryTruncateFloat64ToUint64)
212 DECLARE_IMPOSSIBLE_CASE(TryTruncateFloat64ToInt32)
213 DECLARE_IMPOSSIBLE_CASE(TryTruncateFloat64ToUint32)
214 DECLARE_IMPOSSIBLE_CASE(ChangeInt32ToFloat64)
215 DECLARE_IMPOSSIBLE_CASE(BitcastWord32ToWord64)
216 DECLARE_IMPOSSIBLE_CASE(ChangeInt32ToInt64)
217 DECLARE_IMPOSSIBLE_CASE(ChangeInt64ToFloat64)
218 DECLARE_IMPOSSIBLE_CASE(ChangeUint32ToFloat64)
219 DECLARE_IMPOSSIBLE_CASE(ChangeFloat16RawBitsToFloat64)
220 DECLARE_IMPOSSIBLE_CASE(TruncateFloat64ToFloat32)
221 DECLARE_IMPOSSIBLE_CASE(TruncateFloat64ToFloat16RawBits)
222 DECLARE_IMPOSSIBLE_CASE(TruncateInt64ToInt32)
223 DECLARE_IMPOSSIBLE_CASE(RoundFloat64ToInt32)
224 DECLARE_IMPOSSIBLE_CASE(RoundInt32ToFloat32)
225 DECLARE_IMPOSSIBLE_CASE(RoundInt64ToFloat32)
226 DECLARE_IMPOSSIBLE_CASE(RoundInt64ToFloat64)
227 DECLARE_IMPOSSIBLE_CASE(RoundUint32ToFloat32)
228 DECLARE_IMPOSSIBLE_CASE(RoundUint64ToFloat32)
229 DECLARE_IMPOSSIBLE_CASE(RoundUint64ToFloat64)
230 DECLARE_IMPOSSIBLE_CASE(BitcastFloat32ToInt32)
231 DECLARE_IMPOSSIBLE_CASE(BitcastFloat64ToInt64)
232 DECLARE_IMPOSSIBLE_CASE(BitcastInt32ToFloat32)
233 DECLARE_IMPOSSIBLE_CASE(BitcastInt64ToFloat64)
234 DECLARE_IMPOSSIBLE_CASE(Float64ExtractLowWord32)
235 DECLARE_IMPOSSIBLE_CASE(Float64ExtractHighWord32)
236 DECLARE_IMPOSSIBLE_CASE(Float64InsertLowWord32)
237 DECLARE_IMPOSSIBLE_CASE(Float64InsertHighWord32)
238 DECLARE_IMPOSSIBLE_CASE(Word32Select)
239 DECLARE_IMPOSSIBLE_CASE(Word64Select)
240 DECLARE_IMPOSSIBLE_CASE(Float32Select)
241 DECLARE_IMPOSSIBLE_CASE(Float64Select)
242 DECLARE_IMPOSSIBLE_CASE(LoadStackCheckOffset)
243 DECLARE_IMPOSSIBLE_CASE(LoadFramePointer)
244 IF_WASM(DECLARE_IMPOSSIBLE_CASE, LoadStackPointer)
245 IF_WASM(DECLARE_IMPOSSIBLE_CASE, SetStackPointer)
246 DECLARE_IMPOSSIBLE_CASE(LoadParentFramePointer)
247 DECLARE_IMPOSSIBLE_CASE(LoadRootRegister)
248 DECLARE_IMPOSSIBLE_CASE(UnalignedLoad)
249 DECLARE_IMPOSSIBLE_CASE(UnalignedStore)
250 DECLARE_IMPOSSIBLE_CASE(Int32PairAdd)
251 DECLARE_IMPOSSIBLE_CASE(Int32PairSub)
252 DECLARE_IMPOSSIBLE_CASE(Int32PairMul)
253 DECLARE_IMPOSSIBLE_CASE(Word32PairShl)
254 DECLARE_IMPOSSIBLE_CASE(Word32PairShr)
255 DECLARE_IMPOSSIBLE_CASE(Word32PairSar)
256 DECLARE_IMPOSSIBLE_CASE(ProtectedLoad)
257 DECLARE_IMPOSSIBLE_CASE(ProtectedStore)
258 DECLARE_IMPOSSIBLE_CASE(LoadTrapOnNull)
259 DECLARE_IMPOSSIBLE_CASE(StoreTrapOnNull)
260 DECLARE_IMPOSSIBLE_CASE(MemoryBarrier)
261 DECLARE_IMPOSSIBLE_CASE(SignExtendWord8ToInt32)
262 DECLARE_IMPOSSIBLE_CASE(SignExtendWord16ToInt32)
263 DECLARE_IMPOSSIBLE_CASE(SignExtendWord8ToInt64)
264 DECLARE_IMPOSSIBLE_CASE(SignExtendWord16ToInt64)
265 DECLARE_IMPOSSIBLE_CASE(SignExtendWord32ToInt64)
266 DECLARE_IMPOSSIBLE_CASE(StackPointerGreaterThan)
267 DECLARE_IMPOSSIBLE_CASE(TraceInstruction)
268
269#undef DECLARE_IMPOSSIBLE_CASE
270 UNREACHABLE();
271 }
272 }
273
275
277 InductionVariable* induction_var);
278
279 private:
283
284#define DECLARE_METHOD(x, ...) inline Type Type##x(Node* node);
285 DECLARE_METHOD(Start)
286 DECLARE_METHOD(IfException)
293#undef DECLARE_METHOD
294#define DECLARE_METHOD(x, ...) inline Type Type##x(Type input);
296#undef DECLARE_METHOD
297
300 : Type::None();
301 }
302
303 Type Operand(Node* node, int i) {
304 Node* operand_node = NodeProperties::GetValueInput(node, i);
305 return TypeOrNone(operand_node);
306 }
307
308 Type Weaken(Node* node, Type current_type, Type previous_type);
309
310 Zone* zone() { return typer_->zone(); }
311 TFGraph* graph() { return typer_->graph(); }
313
314 void SetWeakened(NodeId node_id) { weakened_nodes_.insert(node_id); }
315 bool IsWeakened(NodeId node_id) {
316 return weakened_nodes_.find(node_id) != weakened_nodes_.end();
317 }
318
319 using UnaryTyperFun = Type (*)(Type, Typer* t);
320 using BinaryTyperFun = Type (*)(Type, Type, Typer* t);
321
322 inline Type TypeUnaryOp(Node* node, UnaryTyperFun);
323 inline Type TypeBinaryOp(Node* node, BinaryTyperFun);
324 inline Type TypeUnaryOp(Type input, UnaryTyperFun);
325 inline Type TypeBinaryOp(Type left, Type right, BinaryTyperFun);
326
327 static Type BinaryNumberOpTyper(Type lhs, Type rhs, Typer* t,
329
336
339
340 static Type BitwiseNot(Type, Typer*);
341 static Type Decrement(Type, Typer*);
342 static Type Increment(Type, Typer*);
343 static Type Negate(Type, Typer*);
344
345 static Type ToPrimitive(Type, Typer*);
346 static Type ToBoolean(Type, Typer*);
347 static Type ToInteger(Type, Typer*);
348 static Type ToLength(Type, Typer*);
349 static Type ToName(Type, Typer*);
350 static Type ToNumber(Type, Typer*);
352 static Type ToBigInt(Type, Typer*);
354 static Type ToNumeric(Type, Typer*);
355 static Type ToObject(Type, Typer*);
356 static Type ToString(Type, Typer*);
357#define DECLARE_METHOD(Name) \
358 static Type Name(Type type, Typer* t) { \
359 return t->operation_typer_.Name(type); \
360 }
365 DECLARE_METHOD(ChangeUint32ToUint64)
366#undef DECLARE_METHOD
367#define DECLARE_METHOD(Name) \
368 static Type Name(Type lhs, Type rhs, Typer* t) { \
369 return t->operation_typer_.Name(lhs, rhs); \
370 }
376#undef DECLARE_METHOD
377#define DECLARE_METHOD(Name, ...) \
378 inline Type Type##Name(Type left, Type right) { \
379 return TypeBinaryOp(left, right, Name##Typer); \
380 }
382#undef DECLARE_METHOD
383#define DECLARE_METHOD(Name, ...) \
384 inline Type Type##Name(Type left, Type right) { \
385 return TypeBinaryOp(left, right, Name); \
386 }
392#undef DECLARE_METHOD
393#define DECLARE_METHOD(Name, ...) \
394 inline Type Type##Name(Type input) { return TypeUnaryOp(input, Name); }
399 DECLARE_METHOD(ChangeUint32ToUint64)
400#undef DECLARE_METHOD
402 static Type ObjectIsBigInt(Type, Typer*);
408 static Type ObjectIsNaN(Type, Typer*);
409 static Type NumberIsNaN(Type, Typer*);
411 static Type ObjectIsNumber(Type, Typer*);
413 static Type ObjectIsSmi(Type, Typer*);
414 static Type ObjectIsString(Type, Typer*);
415 static Type ObjectIsSymbol(Type, Typer*);
417
420
421#define DECLARE_METHOD(x, ...) static Type x##Typer(Type, Type, Typer*);
423#undef DECLARE_METHOD
424
425 static Type JSCallTyper(Type, Typer*);
426
432 static Type SameValueTyper(Type, Type, Typer*);
436
437 Reduction UpdateType(Node* node, Type current) {
438 if (NodeProperties::IsTyped(node)) {
439 // Widen the type of a previously typed node.
441 if (node->opcode() == IrOpcode::kPhi ||
442 node->opcode() == IrOpcode::kInductionVariablePhi) {
443 // Speed up termination in the presence of range types:
444 current = Weaken(node, current, previous);
445 }
446
447 if (V8_UNLIKELY(!previous.Is(current))) {
449 std::ostringstream ostream;
450 node->Print(ostream);
451 FATAL("UpdateType error for node %s", ostream.str().c_str());
452 }
453
454 NodeProperties::SetType(node, current);
455 if (!current.Is(previous)) {
456 // If something changed, revisit all uses.
457 return Changed(node);
458 }
459 return NoChange();
460 } else {
461 // No previous type, simply update the type.
462 NodeProperties::SetType(node, current);
463 return Changed(node);
464 }
465 }
466};
467
468void Typer::Run() { Run(NodeVector(zone()), nullptr); }
469
470void Typer::Run(const NodeVector& roots,
471 LoopVariableOptimizer* induction_vars) {
472 if (induction_vars != nullptr) {
473 induction_vars->ChangeToInductionVariablePhis();
474 }
475 Visitor visitor(this, induction_vars);
476 GraphReducer graph_reducer(zone(), graph(), tick_counter_, broker());
477 graph_reducer.AddReducer(&visitor);
478 for (Node* const root : roots) graph_reducer.ReduceNode(root);
479 graph_reducer.ReduceGraph();
480
481 if (induction_vars != nullptr) {
482 // Validate the types computed by TypeInductionVariablePhi.
483 for (auto entry : induction_vars->induction_variables()) {
484 InductionVariable* induction_var = entry.second;
485 if (induction_var->phi()->opcode() == IrOpcode::kInductionVariablePhi) {
486 CHECK(visitor.InductionVariablePhiTypeIsPrefixedPoint(induction_var));
487 }
488 }
489
490 induction_vars->ChangeToPhisAndInsertGuards();
491 }
492}
493
495 if (node->op()->ValueOutputCount() > 0) {
496 // Only eagerly type-decorate nodes with known input types.
497 // Other cases will generally require a proper fixpoint iteration with Run.
498 bool is_typed = NodeProperties::IsTyped(node);
499 if (is_typed || NodeProperties::AllValueInputsAreTyped(node)) {
500 Visitor typing(typer_, nullptr);
501 Type type = typing.TypeNode(node);
502 if (is_typed) {
503 type = Type::Intersect(type, NodeProperties::GetType(node),
504 typer_->zone());
505 }
506 NodeProperties::SetType(node, type);
507 }
508 }
509}
510
511// -----------------------------------------------------------------------------
512
513// Helper functions that lift a function f on types to a function on bounds,
514// and uses that to type the given node. Note that f is never called with None
515// as an argument.
516
518 Type input = Operand(node, 0);
519 return TypeUnaryOp(input, f);
520}
521
523 return input.IsNone() ? Type::None() : f(input, typer_);
524}
525
527 Type left = Operand(node, 0);
528 Type right = Operand(node, 1);
529 return TypeBinaryOp(left, right, f);
530}
531
533 return left.IsNone() || right.IsNone() ? Type::None()
534 : f(left, right, typer_);
535}
536
538 BinaryTyperFun f) {
539 lhs = ToNumeric(lhs, t);
540 rhs = ToNumeric(rhs, t);
541 if (lhs.IsNone() || rhs.IsNone()) return Type::None();
542
543 bool lhs_is_number = lhs.Is(Type::Number());
544 bool rhs_is_number = rhs.Is(Type::Number());
545 if (lhs_is_number && rhs_is_number) {
546 return f(lhs, rhs, t);
547 }
548 // In order to maintain monotonicity, the following two conditions are
549 // intentionally asymmetric.
550 if (lhs_is_number) {
551 return Type::Number();
552 }
553 if (lhs.Is(Type::BigInt())) {
554 return Type::BigInt();
555 }
556 return Type::Numeric();
557}
558
560 ComparisonOutcome outcome, Typer* t) {
562 if ((outcome & kComparisonUndefined) != 0) result |= kComparisonUndefined;
563 if ((outcome & kComparisonTrue) != 0) result |= kComparisonFalse;
564 if ((outcome & kComparisonFalse) != 0) result |= kComparisonTrue;
565 return result;
566}
567
569 if (outcome == 0) return Type::None();
570 if ((outcome & kComparisonFalse) != 0 ||
571 (outcome & kComparisonUndefined) != 0) {
572 return (outcome & kComparisonTrue) != 0 ? Type::Boolean()
573 : t->singleton_false_;
574 }
575 DCHECK_NE(0, outcome & kComparisonTrue);
576 return t->singleton_true_;
577}
578
580 type = ToNumeric(type, t);
581 if (type.Is(Type::Number())) {
582 return NumberBitwiseXor(type, t->cache_->kSingletonMinusOne, t);
583 }
584 if (type.Is(Type::BigInt())) {
585 return Type::BigInt();
586 }
587 return Type::Numeric();
588}
589
591 type = ToNumeric(type, t);
592 if (type.Is(Type::Number())) {
593 return NumberSubtract(type, t->cache_->kSingletonOne, t);
594 }
595 if (type.Is(Type::BigInt())) {
596 return Type::BigInt();
597 }
598 return Type::Numeric();
599}
600
602 type = ToNumeric(type, t);
603 if (type.Is(Type::Number())) {
604 return NumberAdd(type, t->cache_->kSingletonOne, t);
605 }
606 if (type.Is(Type::BigInt())) {
607 return Type::BigInt();
608 }
609 return Type::Numeric();
610}
611
613 type = ToNumeric(type, t);
614 if (type.Is(Type::Number())) {
615 return NumberMultiply(type, t->cache_->kSingletonMinusOne, t);
616 }
617 if (type.Is(Type::BigInt())) {
618 return Type::BigInt();
619 }
620 return Type::Numeric();
621}
622
623// Type conversion.
624
626 if (type.Is(Type::Primitive()) && !type.Maybe(Type::Receiver())) {
627 return type;
628 }
629 return Type::Primitive();
630}
631
633 return t->operation_typer()->ToBoolean(type);
634}
635
636// static
638 // ES6 section 7.1.4 ToInteger ( argument )
639 type = ToNumber(type, t);
640 if (type.Is(t->cache_->kInteger)) return type;
641 if (type.Is(t->cache_->kIntegerOrMinusZeroOrNaN)) {
642 return Type::Union(Type::Intersect(type, t->cache_->kInteger, t->zone()),
643 t->cache_->kSingletonZero, t->zone());
644 }
645 return t->cache_->kInteger;
646}
647
648// static
650 // ES6 section 7.1.15 ToLength ( argument )
651 type = ToInteger(type, t);
652 if (type.IsNone()) return type;
653 double min = type.Min();
654 double max = type.Max();
655 if (max <= 0.0) {
656 return Type::Constant(0, t->zone());
657 }
658 if (min >= kMaxSafeInteger) {
659 return Type::Constant(kMaxSafeInteger, t->zone());
660 }
661 if (min <= 0.0) min = 0.0;
662 if (max >= kMaxSafeInteger) max = kMaxSafeInteger;
663 return Type::Range(min, max, t->zone());
664}
665
666// static
668 // ES6 section 7.1.14 ToPropertyKey ( argument )
669 type = ToPrimitive(type, t);
670 if (type.Is(Type::Name())) return type;
671 if (type.Maybe(Type::Symbol())) return Type::Name();
672 return ToString(type, t);
673}
674
675// static
677 return t->operation_typer_.ToNumber(type);
678}
679
680// static
682 return t->operation_typer_.ToNumberConvertBigInt(type);
683}
684
685// static
687 return t->operation_typer_.ToBigInt(type);
688}
689
690// static
692 return t->operation_typer_.ToBigIntConvertNumber(type);
693}
694
695// static
697 return t->operation_typer_.ToNumeric(type);
698}
699
700// static
702 // ES6 section 7.1.13 ToObject ( argument )
703 if (type.Is(Type::Receiver())) return type;
704 if (type.Is(Type::Primitive())) return Type::StringWrapperOrOtherObject();
705 if (!type.Maybe(Type::OtherUndetectable())) {
706 return Type::DetectableReceiver();
707 }
708 return Type::Receiver();
709}
710
711// static
713 // ES6 section 7.1.12 ToString ( argument )
714 type = ToPrimitive(type, t);
715 if (type.Is(Type::String())) return type;
716 return Type::String();
717}
718
719// Type checks.
720
722 // TODO(turbofan): Introduce a Type::ArrayBufferView?
723 CHECK(!type.IsNone());
724 if (type.Is(Type::TypedArray())) return t->singleton_true_;
725 if (!type.Maybe(Type::TypedArray()) && !type.Maybe(Type::OtherObject())) {
726 return t->singleton_false_;
727 }
728 return Type::Boolean();
729}
730
732 CHECK(!type.IsNone());
733 if (type.Is(Type::BigInt())) return t->singleton_true_;
734 if (!type.Maybe(Type::BigInt())) return t->singleton_false_;
735 return Type::Boolean();
736}
737
739 CHECK(!type.IsNone());
740 if (type.Is(Type::Callable())) return t->singleton_true_;
741 if (!type.Maybe(Type::Callable())) return t->singleton_false_;
742 return Type::Boolean();
743}
744
746 // TODO(turbofan): Introduce a Type::Constructor?
747 CHECK(!type.IsNone());
748 if (type.IsHeapConstant() &&
749 type.AsHeapConstant()->Ref().map(t->broker()).is_constructor()) {
750 return t->singleton_true_;
751 }
752 if (!type.Maybe(Type::Callable())) return t->singleton_false_;
753 return Type::Boolean();
754}
755
757 CHECK(!type.IsNone());
758 if (type.Is(Type::DetectableCallable())) return t->singleton_true_;
759 if (!type.Maybe(Type::DetectableCallable())) return t->singleton_false_;
760 return Type::Boolean();
761}
762
764 CHECK(!type.IsNone());
765 if (type.Is(Type::MinusZero())) return t->singleton_true_;
766 if (!type.Maybe(Type::MinusZero())) return t->singleton_false_;
767 return Type::Boolean();
768}
769
771 CHECK(!type.IsNone());
772 if (type.Is(Type::MinusZero())) return t->singleton_true_;
773 if (!type.Maybe(Type::MinusZero())) return t->singleton_false_;
774 return Type::Boolean();
775}
776
778 CHECK(!type.IsNone());
779 if (type.Is(Type::NaN())) return t->singleton_true_;
780 if (!type.Maybe(Type::NaN())) return t->singleton_false_;
781 return Type::Boolean();
782}
783
785 CHECK(!type.IsNone());
786 if (type.Is(Type::NaN())) return t->singleton_true_;
787 if (!type.Maybe(Type::NaN())) return t->singleton_false_;
788 return Type::Boolean();
789}
790
792 CHECK(!type.IsNone());
793 if (type.Is(Type::NonCallable())) return t->singleton_true_;
794 if (!type.Maybe(Type::NonCallable())) return t->singleton_false_;
795 return Type::Boolean();
796}
797
799 CHECK(!type.IsNone());
800 if (type.Is(Type::Number())) return t->singleton_true_;
801 if (!type.Maybe(Type::Number())) return t->singleton_false_;
802 return Type::Boolean();
803}
804
806 CHECK(!type.IsNone());
807 if (type.Is(Type::Receiver())) return t->singleton_true_;
808 if (!type.Maybe(Type::Receiver())) return t->singleton_false_;
809 return Type::Boolean();
810}
811
813 if (!type.Maybe(Type::SignedSmall())) return t->singleton_false_;
814 return Type::Boolean();
815}
816
818 CHECK(!type.IsNone());
819 if (type.Is(Type::String())) return t->singleton_true_;
820 if (!type.Maybe(Type::String())) return t->singleton_false_;
821 return Type::Boolean();
822}
823
825 CHECK(!type.IsNone());
826 if (type.Is(Type::Symbol())) return t->singleton_true_;
827 if (!type.Maybe(Type::Symbol())) return t->singleton_false_;
828 return Type::Boolean();
829}
830
832 CHECK(!type.IsNone());
833 if (type.Is(Type::Undetectable())) return t->singleton_true_;
834 if (!type.Maybe(Type::Undetectable())) return t->singleton_false_;
835 return Type::Boolean();
836}
837
838// -----------------------------------------------------------------------------
839
840// Control operators.
841
842Type Typer::Visitor::TypeStart(Node* node) { return Type::Internal(); }
843
844Type Typer::Visitor::TypeIfException(Node* node) { return Type::NonInternal(); }
845
846// Common operators.
847
848Type Typer::Visitor::TypeParameter(Node* node) {
849 StartNode start{node->InputAt(0)};
850 int const index = ParameterIndexOf(node->op());
852 return Type::Function();
853 } else if (index == 0) {
854 if (typer_->flags() & Typer::kThisIsReceiver) {
855 return Type::Receiver();
856 } else {
857 // Parameter[this] can be a hole type for derived class constructors.
858 return Type::Union(Type::Hole(), Type::NonInternal(), typer_->zone());
859 }
860 } else if (index == start.NewTargetParameterIndex()) {
861 if (typer_->flags() & Typer::kNewTargetIsReceiver) {
862 return Type::Receiver();
863 } else {
864 return Type::Union(Type::Receiver(), Type::Undefined(), typer_->zone());
865 }
866 } else if (index == start.ArgCountParameterIndex()) {
867 return Type::Range(0.0, FixedArray::kMaxLength, typer_->zone());
868 } else if (index == start.ContextParameterIndex()) {
869 return Type::OtherInternal();
870 }
871 return Type::NonInternal();
872}
873
874Type Typer::Visitor::TypeOsrValue(Node* node) {
876 return Type::OtherInternal();
877 } else {
878 return Type::Any();
879 }
880}
881
882Type Typer::Visitor::TypeRetain(Node* node) { UNREACHABLE(); }
883
884Type Typer::Visitor::TypeInt32Constant(Node* node) { return Type::Machine(); }
885
886Type Typer::Visitor::TypeInt64Constant(Node* node) { return Type::Machine(); }
887
888Type Typer::Visitor::TypeTaggedIndexConstant(Node* node) { UNREACHABLE(); }
889
890Type Typer::Visitor::TypeRelocatableInt32Constant(Node* node) { UNREACHABLE(); }
891
892Type Typer::Visitor::TypeRelocatableInt64Constant(Node* node) { UNREACHABLE(); }
893
894Type Typer::Visitor::TypeFloat32Constant(Node* node) { UNREACHABLE(); }
895
896Type Typer::Visitor::TypeFloat64Constant(Node* node) { UNREACHABLE(); }
897
898Type Typer::Visitor::TypeNumberConstant(Node* node) {
899 double number = OpParameter<double>(node->op());
900 return Type::Constant(number, zone());
901}
902
903Type Typer::Visitor::TypeHeapConstant(Node* node) {
904 return TypeConstant(HeapConstantOf(node->op()));
905}
906
907Type Typer::Visitor::TypeCompressedHeapConstant(Node* node) { UNREACHABLE(); }
908
909Type Typer::Visitor::TypeTrustedHeapConstant(Node* node) {
910 return TypeConstant(HeapConstantOf(node->op()));
911}
912
913Type Typer::Visitor::TypeExternalConstant(Node* node) {
914 return Type::ExternalPointer();
915}
916
917Type Typer::Visitor::TypePointerConstant(Node* node) {
918 return Type::ExternalPointer();
919}
920
921Type Typer::Visitor::TypeSelect(Node* node) {
922 return Type::Union(Operand(node, 1), Operand(node, 2), zone());
923}
924
925Type Typer::Visitor::TypePhi(Node* node) {
926 int arity = node->op()->ValueInputCount();
927 Type type = Operand(node, 0);
928 for (int i = 1; i < arity; ++i) {
929 type = Type::Union(type, Operand(node, i), zone());
930 }
931 return type;
932}
933
934Type Typer::Visitor::TypeEnterMachineGraph(Node* node) {
935 return Type::Machine();
936}
937
938Type Typer::Visitor::TypeExitMachineGraph(Node* node) {
939 return ExitMachineGraphParametersOf(node->op()).output_type();
940}
941
942Type Typer::Visitor::TypeInductionVariablePhi(Node* node) {
943 int arity = NodeProperties::GetControlInput(node)->op()->ControlInputCount();
944 DCHECK_EQ(IrOpcode::kLoop, NodeProperties::GetControlInput(node)->opcode());
945 DCHECK_EQ(2, NodeProperties::GetControlInput(node)->InputCount());
946
947 Type initial_type = Operand(node, 0);
948 Type increment_type = Operand(node, 2);
949
950 // Fallback to normal phi typing in a variety of cases:
951 // - when the induction variable is not initially of type Integer, because we
952 // want to work with ranges in the algorithm below.
953 // - when the increment is zero, because in that case normal phi typing will
954 // generally yield a more precise type.
955 // - when the induction variable can become NaN (through addition/subtraction
956 // of opposing infinities), because the code below can't handle that case.
957 if (initial_type.IsNone() ||
958 increment_type.Is(typer_->cache_->kSingletonZero) ||
959 !initial_type.Is(typer_->cache_->kInteger) ||
960 !increment_type.Is(typer_->cache_->kInteger) ||
961 increment_type.Min() == -V8_INFINITY ||
962 increment_type.Max() == +V8_INFINITY) {
963 // Unfortunately, without baking in the previous type, monotonicity might be
964 // violated because we might not yet have retyped the incrementing operation
965 // even though the increment's type might been already reflected in the
966 // induction variable phi.
967 Type type = NodeProperties::IsTyped(node) ? NodeProperties::GetType(node)
968 : Type::None();
969 for (int i = 0; i < arity; ++i) {
970 type = Type::Union(type, Operand(node, i), zone());
971 }
972 return type;
973 }
974
975 auto res = induction_vars_->induction_variables().find(node->id());
976 DCHECK_NE(res, induction_vars_->induction_variables().end());
977 InductionVariable* induction_var = res->second;
978 InductionVariable::ArithmeticType arithmetic_type = induction_var->Type();
979
980 double min = -V8_INFINITY;
981 double max = V8_INFINITY;
982
983 double increment_min;
984 double increment_max;
985 if (arithmetic_type == InductionVariable::ArithmeticType::kAddition) {
986 increment_min = increment_type.Min();
987 increment_max = increment_type.Max();
988 } else {
990 increment_min = -increment_type.Max();
991 increment_max = -increment_type.Min();
992 }
993
994 if (increment_min >= 0) {
995 // Increasing sequence.
996 min = initial_type.Min();
997 for (auto bound : induction_var->upper_bounds()) {
998 Type bound_type = TypeOrNone(bound.bound);
999 // If the type is not an integer, just skip the bound.
1000 if (!bound_type.Is(typer_->cache_->kInteger)) continue;
1001 // If the type is not inhabited, then we can take the initial value.
1002 if (bound_type.IsNone()) {
1003 max = initial_type.Max();
1004 break;
1005 }
1006 double bound_max = bound_type.Max();
1007 if (bound.kind == InductionVariable::kStrict) {
1008 bound_max -= 1;
1009 }
1010 max = std::min(max, bound_max + increment_max);
1011 }
1012 // The upper bound must be at least the initial value's upper bound.
1013 max = std::max(max, initial_type.Max());
1014 } else if (increment_max <= 0) {
1015 // Decreasing sequence.
1016 max = initial_type.Max();
1017 for (auto bound : induction_var->lower_bounds()) {
1018 Type bound_type = TypeOrNone(bound.bound);
1019 // If the type is not an integer, just skip the bound.
1020 if (!bound_type.Is(typer_->cache_->kInteger)) continue;
1021 // If the type is not inhabited, then we can take the initial value.
1022 if (bound_type.IsNone()) {
1023 min = initial_type.Min();
1024 break;
1025 }
1026 double bound_min = bound_type.Min();
1027 if (bound.kind == InductionVariable::kStrict) {
1028 bound_min += 1;
1029 }
1030 min = std::max(min, bound_min + increment_min);
1031 }
1032 // The lower bound must be at most the initial value's lower bound.
1033 min = std::min(min, initial_type.Min());
1034 } else {
1035 // If the increment can be both positive and negative, the variable can go
1036 // arbitrarily far. Use the maximal range in that case. Note that this may
1037 // be less precise than what ordinary typing would produce.
1038 min = -V8_INFINITY;
1039 max = +V8_INFINITY;
1040 }
1041
1042 if (v8_flags.trace_turbo_loop) {
1043 StdoutStream{} << std::setprecision(10) << "Loop ("
1045 << ") variable bounds in "
1046 << (arithmetic_type ==
1048 ? "addition"
1049 : "subtraction")
1050 << " for phi " << node->id() << ": (" << min << ", " << max
1051 << ")\n";
1052 }
1053
1054 return Type::Range(min, max, typer_->zone());
1055}
1056
1058 InductionVariable* induction_var) {
1059 Node* node = induction_var->phi();
1060 DCHECK_EQ(node->opcode(), IrOpcode::kInductionVariablePhi);
1061 Node* arith = node->InputAt(1);
1062 Type type = NodeProperties::GetType(node);
1063 Type initial_type = Operand(node, 0);
1064 Type arith_type = Operand(node, 1);
1065 Type increment_type = Operand(node, 2);
1066
1067 // Intersect {type} with useful bounds.
1068 for (auto bound : induction_var->upper_bounds()) {
1069 Type bound_type = TypeOrNone(bound.bound);
1070 if (!bound_type.Is(typer_->cache_->kInteger)) continue;
1071 if (!bound_type.IsNone()) {
1072 bound_type = Type::Range(
1073 -V8_INFINITY,
1074 bound_type.Max() - (bound.kind == InductionVariable::kStrict),
1075 zone());
1076 }
1077 type = Type::Intersect(type, bound_type, typer_->zone());
1078 }
1079 for (auto bound : induction_var->lower_bounds()) {
1080 Type bound_type = TypeOrNone(bound.bound);
1081 if (!bound_type.Is(typer_->cache_->kInteger)) continue;
1082 if (!bound_type.IsNone()) {
1083 bound_type = Type::Range(
1084 bound_type.Min() + (bound.kind == InductionVariable::kStrict),
1085 +V8_INFINITY, typer_->zone());
1086 }
1087 type = Type::Intersect(type, bound_type, typer_->zone());
1088 }
1089
1090 if (arith_type.IsNone()) {
1091 type = Type::None();
1092 } else {
1093 // We support a few additional type conversions on the lhs of the arithmetic
1094 // operation. This needs to be kept in sync with the corresponding code in
1095 // {LoopVariableOptimizer::TryGetInductionVariable}.
1096 Node* arith_input = arith->InputAt(0);
1097 switch (arith_input->opcode()) {
1098 case IrOpcode::kSpeculativeToNumber:
1099 type = typer_->operation_typer_.SpeculativeToNumber(type);
1100 break;
1101 case IrOpcode::kJSToNumber:
1102 type = typer_->operation_typer_.ToNumber(type);
1103 break;
1104 case IrOpcode::kJSToNumberConvertBigInt:
1105 type = typer_->operation_typer_.ToNumberConvertBigInt(type);
1106 break;
1107 default:
1108 break;
1109 }
1110
1111 // Apply ordinary typing to the "increment" operation.
1112 // clang-format off
1113 switch (arith->opcode()) {
1114#define CASE(x) \
1115 case IrOpcode::k##x: \
1116 type = Type##x(type, increment_type); \
1117 break;
1118 CASE(JSAdd)
1119 CASE(JSSubtract)
1120 CASE(NumberAdd)
1121 CASE(NumberSubtract)
1122 CASE(SpeculativeNumberAdd)
1123 CASE(SpeculativeNumberSubtract)
1124 CASE(SpeculativeAdditiveSafeIntegerAdd)
1125 CASE(SpeculativeAdditiveSafeIntegerSubtract)
1126 CASE(SpeculativeSmallIntegerAdd)
1127 CASE(SpeculativeSmallIntegerSubtract)
1128#undef CASE
1129 default:
1130 UNREACHABLE();
1131 }
1132 // clang-format on
1133 }
1134
1135 type = Type::Union(initial_type, type, typer_->zone());
1136
1137 return type.Is(NodeProperties::GetType(node));
1138}
1139
1140Type Typer::Visitor::TypeEffectPhi(Node* node) { UNREACHABLE(); }
1141
1142Type Typer::Visitor::TypeLoopExit(Node* node) { UNREACHABLE(); }
1143
1144Type Typer::Visitor::TypeLoopExitValue(Node* node) { return Operand(node, 0); }
1145
1146Type Typer::Visitor::TypeLoopExitEffect(Node* node) { UNREACHABLE(); }
1147
1148Type Typer::Visitor::TypeEnsureWritableFastElements(Node* node) {
1149 return Operand(node, 1);
1150}
1151
1152Type Typer::Visitor::TypeMaybeGrowFastElements(Node* node) {
1153 return Operand(node, 1);
1154}
1155
1156Type Typer::Visitor::TypeTransitionElementsKind(Node* node) { UNREACHABLE(); }
1157
1158Type Typer::Visitor::TypeTransitionElementsKindOrCheckMap(Node* node) {
1159 UNREACHABLE();
1160}
1161
1162Type Typer::Visitor::TypeCheckpoint(Node* node) { UNREACHABLE(); }
1163
1164Type Typer::Visitor::TypeBeginRegion(Node* node) { UNREACHABLE(); }
1165
1166Type Typer::Visitor::TypeFinishRegion(Node* node) { return Operand(node, 0); }
1167
1168Type Typer::Visitor::TypeFrameState(Node* node) {
1169 // TODO(rossberg): Ideally FrameState wouldn't have a value output.
1170 return Type::Internal();
1171}
1172
1173Type Typer::Visitor::TypeStateValues(Node* node) { return Type::Internal(); }
1174
1175Type Typer::Visitor::TypeTypedStateValues(Node* node) {
1176 return Type::Internal();
1177}
1178
1179Type Typer::Visitor::TypeObjectId(Node* node) { UNREACHABLE(); }
1180
1181Type Typer::Visitor::TypeArgumentsElementsState(Node* node) {
1182 return Type::Internal();
1183}
1184
1185Type Typer::Visitor::TypeArgumentsLengthState(Node* node) {
1186 return Type::Internal();
1187}
1188
1189Type Typer::Visitor::TypeObjectState(Node* node) { return Type::Internal(); }
1190
1191Type Typer::Visitor::TypeTypedObjectState(Node* node) {
1192 return Type::Internal();
1193}
1194
1195Type Typer::Visitor::TypeCall(Node* node) { return Type::Any(); }
1196
1197Type Typer::Visitor::TypeFastApiCall(Node* node) {
1198 FastApiCallParameters const& op_params = FastApiCallParametersOf(node->op());
1199
1200 const CFunctionInfo* c_signature = op_params.c_function().signature;
1201 CTypeInfo return_type = c_signature->ReturnInfo();
1202
1203 switch (return_type.GetType()) {
1205 return Type::Boolean();
1208 return Type::Number();
1210 return Type::Signed32();
1212 if (c_signature->GetInt64Representation() ==
1214 return Type::SignedBigInt64();
1215 }
1216 DCHECK_EQ(c_signature->GetInt64Representation(),
1218 return Type::Number();
1220 return Type::String();
1222 return Type::Unsigned32();
1224 if (c_signature->GetInt64Representation() ==
1226 return Type::UnsignedBigInt64();
1227 }
1228 DCHECK_EQ(c_signature->GetInt64Representation(),
1230 return Type::Number();
1232 return Type::UnsignedSmall();
1234 // This type is only supposed to be used for parameters, not returns.
1235 UNREACHABLE();
1240 return Type::Any();
1241 }
1242}
1243
1244#ifdef V8_ENABLE_CONTINUATION_PRESERVED_EMBEDDER_DATA
1245Type Typer::Visitor::TypeGetContinuationPreservedEmbedderData(Node* node) {
1246 return Type::Any();
1247}
1248
1249Type Typer::Visitor::TypeSetContinuationPreservedEmbedderData(Node* node) {
1250 UNREACHABLE();
1251}
1252#endif // V8_ENABLE_CONTINUATION_PRESERVED_EMBEDDER_DATA
1253
1254#if V8_ENABLE_WEBASSEMBLY
1255Type Typer::Visitor::TypeJSWasmCall(Node* node) {
1256 const JSWasmCallParameters& op_params = JSWasmCallParametersOf(node->op());
1257 const wasm::CanonicalSig* wasm_signature = op_params.signature();
1258 if (wasm_signature->return_count() > 0) {
1259 return JSWasmCallNode::TypeForWasmReturnType(wasm_signature->GetReturn());
1260 }
1261 return Type::Any();
1262}
1263#endif // V8_ENABLE_WEBASSEMBLY
1264
1265Type Typer::Visitor::TypeProjection(Node* node) {
1266 Type const type = Operand(node, 0);
1267 if (type.Is(Type::None())) return Type::None();
1268 int const index = static_cast<int>(ProjectionIndexOf(node->op()));
1269 if (type.IsTuple() && index < type.AsTuple()->Arity()) {
1270 return type.AsTuple()->Element(index);
1271 }
1272 return Type::Any();
1273}
1274
1275Type Typer::Visitor::TypeMapGuard(Node* node) { UNREACHABLE(); }
1276
1277Type Typer::Visitor::TypeTypeGuard(Node* node) {
1278 Type const type = Operand(node, 0);
1279 return typer_->operation_typer()->TypeTypeGuard(node->op(), type);
1280}
1281
1282Type Typer::Visitor::TypeDead(Node* node) { return Type::None(); }
1283Type Typer::Visitor::TypeDeadValue(Node* node) { return Type::None(); }
1284Type Typer::Visitor::TypeUnreachable(Node* node) { return Type::None(); }
1285
1286Type Typer::Visitor::TypePlug(Node* node) { UNREACHABLE(); }
1287Type Typer::Visitor::TypeStaticAssert(Node* node) { UNREACHABLE(); }
1288Type Typer::Visitor::TypeSLVerifierHint(Node* node) { UNREACHABLE(); }
1289
1290// JS comparison operators.
1291
1292Type Typer::Visitor::JSEqualTyper(Type lhs, Type rhs, Typer* t) {
1293 if (lhs.IsNone() || rhs.IsNone()) return Type::None();
1294 if (lhs.Is(Type::NaN()) || rhs.Is(Type::NaN())) return t->singleton_false_;
1295 if (lhs.Is(Type::NullOrUndefined()) && rhs.Is(Type::NullOrUndefined())) {
1296 return t->singleton_true_;
1297 }
1298 if (lhs.Is(Type::Number()) && rhs.Is(Type::Number()) &&
1299 (lhs.Max() < rhs.Min() || lhs.Min() > rhs.Max())) {
1300 return t->singleton_false_;
1301 }
1302 if (lhs.IsSingleton() && rhs.Is(lhs)) {
1303 // Types are equal and are inhabited only by a single semantic value,
1304 // which is not nan due to the earlier check.
1305 DCHECK(lhs.Is(rhs));
1306 return t->singleton_true_;
1307 }
1308 return Type::Boolean();
1309}
1310
1311Type Typer::Visitor::JSStrictEqualTyper(Type lhs, Type rhs, Typer* t) {
1312 return t->operation_typer()->StrictEqual(lhs, rhs);
1313}
1314
1315// The ECMAScript specification defines the four relational comparison operators
1316// (<, <=, >=, >) with the help of a single abstract one. It behaves like <
1317// but returns undefined when the inputs cannot be compared.
1318// We implement the typing analogously.
1320 Type rhs,
1321 Typer* t) {
1322 lhs = ToPrimitive(lhs, t);
1323 rhs = ToPrimitive(rhs, t);
1324 if (lhs.Maybe(Type::String()) && rhs.Maybe(Type::String())) {
1325 return ComparisonOutcome(kComparisonTrue) |
1326 ComparisonOutcome(kComparisonFalse);
1327 }
1328 lhs = ToNumeric(lhs, t);
1329 rhs = ToNumeric(rhs, t);
1330 if (lhs.Is(Type::Number()) && rhs.Is(Type::Number())) {
1331 return NumberCompareTyper(lhs, rhs, t);
1332 }
1333 return ComparisonOutcome(kComparisonTrue) |
1334 ComparisonOutcome(kComparisonFalse) |
1335 ComparisonOutcome(kComparisonUndefined);
1336}
1337
1339 Type rhs,
1340 Typer* t) {
1341 DCHECK(lhs.Is(Type::Number()));
1342 DCHECK(rhs.Is(Type::Number()));
1343
1344 if (lhs.IsNone() || rhs.IsNone()) return {};
1345
1346 // Shortcut for NaNs.
1347 if (lhs.Is(Type::NaN()) || rhs.Is(Type::NaN())) return kComparisonUndefined;
1348
1350 if (lhs.IsHeapConstant() && rhs.Is(lhs)) {
1351 // Types are equal and are inhabited only by a single semantic value.
1352 result = kComparisonFalse;
1353 } else if (lhs.Min() >= rhs.Max()) {
1354 result = kComparisonFalse;
1355 } else if (lhs.Max() < rhs.Min()) {
1356 result = kComparisonTrue;
1357 } else {
1358 return ComparisonOutcome(kComparisonTrue) |
1359 ComparisonOutcome(kComparisonFalse) |
1360 ComparisonOutcome(kComparisonUndefined);
1361 }
1362 // Add the undefined if we could see NaN.
1363 if (lhs.Maybe(Type::NaN()) || rhs.Maybe(Type::NaN())) {
1364 result |= kComparisonUndefined;
1365 }
1366 return result;
1367}
1368
1369Type Typer::Visitor::JSLessThanTyper(Type lhs, Type rhs, Typer* t) {
1370 return FalsifyUndefined(JSCompareTyper(lhs, rhs, t), t);
1371}
1372
1373Type Typer::Visitor::JSGreaterThanTyper(Type lhs, Type rhs, Typer* t) {
1374 return FalsifyUndefined(JSCompareTyper(rhs, lhs, t), t);
1375}
1376
1377Type Typer::Visitor::JSLessThanOrEqualTyper(Type lhs, Type rhs, Typer* t) {
1378 return FalsifyUndefined(Invert(JSCompareTyper(rhs, lhs, t), t), t);
1379}
1380
1381Type Typer::Visitor::JSGreaterThanOrEqualTyper(Type lhs, Type rhs, Typer* t) {
1382 return FalsifyUndefined(Invert(JSCompareTyper(lhs, rhs, t), t), t);
1383}
1384
1385// JS bitwise operators.
1386
1387Type Typer::Visitor::JSBitwiseOrTyper(Type lhs, Type rhs, Typer* t) {
1388 return BinaryNumberOpTyper(lhs, rhs, t, NumberBitwiseOr);
1389}
1390
1391Type Typer::Visitor::JSBitwiseAndTyper(Type lhs, Type rhs, Typer* t) {
1392 return BinaryNumberOpTyper(lhs, rhs, t, NumberBitwiseAnd);
1393}
1394
1395Type Typer::Visitor::JSBitwiseXorTyper(Type lhs, Type rhs, Typer* t) {
1396 return BinaryNumberOpTyper(lhs, rhs, t, NumberBitwiseXor);
1397}
1398
1399Type Typer::Visitor::JSShiftLeftTyper(Type lhs, Type rhs, Typer* t) {
1400 return BinaryNumberOpTyper(lhs, rhs, t, NumberShiftLeft);
1401}
1402
1403Type Typer::Visitor::JSShiftRightTyper(Type lhs, Type rhs, Typer* t) {
1404 return BinaryNumberOpTyper(lhs, rhs, t, NumberShiftRight);
1405}
1406
1407Type Typer::Visitor::JSShiftRightLogicalTyper(Type lhs, Type rhs, Typer* t) {
1408 return NumberShiftRightLogical(ToNumber(lhs, t), ToNumber(rhs, t), t);
1409}
1410
1411// JS arithmetic operators.
1412
1413Type Typer::Visitor::JSAddTyper(Type lhs, Type rhs, Typer* t) {
1414 lhs = ToPrimitive(lhs, t);
1415 rhs = ToPrimitive(rhs, t);
1416 if (lhs.Maybe(Type::String()) || rhs.Maybe(Type::String())) {
1417 if (lhs.Is(Type::String()) || rhs.Is(Type::String())) {
1418 return Type::String();
1419 } else {
1420 return Type::NumericOrString();
1421 }
1422 }
1423 // The addition must be numeric.
1424 return BinaryNumberOpTyper(lhs, rhs, t, NumberAdd);
1425}
1426
1427Type Typer::Visitor::JSSubtractTyper(Type lhs, Type rhs, Typer* t) {
1428 return BinaryNumberOpTyper(lhs, rhs, t, NumberSubtract);
1429}
1430
1431Type Typer::Visitor::JSMultiplyTyper(Type lhs, Type rhs, Typer* t) {
1432 return BinaryNumberOpTyper(lhs, rhs, t, NumberMultiply);
1433}
1434
1435Type Typer::Visitor::JSDivideTyper(Type lhs, Type rhs, Typer* t) {
1436 return BinaryNumberOpTyper(lhs, rhs, t, NumberDivide);
1437}
1438
1439Type Typer::Visitor::JSModulusTyper(Type lhs, Type rhs, Typer* t) {
1440 return BinaryNumberOpTyper(lhs, rhs, t, NumberModulus);
1441}
1442
1443Type Typer::Visitor::JSExponentiateTyper(Type lhs, Type rhs, Typer* t) {
1444 // TODO(neis): Refine using BinaryNumberOpTyper?
1445 return Type::Numeric();
1446}
1447
1448// JS unary operators.
1449
1450#define DEFINE_METHOD(Name) \
1451 Type Typer::Visitor::TypeJS##Name(Type input) { \
1452 return TypeUnaryOp(input, Name); \
1453 }
1454DEFINE_METHOD(BitwiseNot)
1455DEFINE_METHOD(Decrement)
1456DEFINE_METHOD(Increment)
1457DEFINE_METHOD(Negate)
1458DEFINE_METHOD(ToLength)
1459DEFINE_METHOD(ToName)
1461DEFINE_METHOD(ToNumberConvertBigInt)
1462DEFINE_METHOD(ToBigInt)
1463DEFINE_METHOD(ToBigIntConvertNumber)
1464DEFINE_METHOD(ToNumeric)
1465DEFINE_METHOD(ToObject)
1467#undef DEFINE_METHOD
1468
1469Type Typer::Visitor::TypeTypeOf(Node* node) {
1470 return Type::InternalizedString();
1471}
1472
1473// JS conversion operators.
1474
1475Type Typer::Visitor::TypeToBoolean(Node* node) {
1476 return TypeUnaryOp(node, ToBoolean);
1477}
1478
1479// JS object operators.
1480
1481Type Typer::Visitor::TypeJSCreate(Node* node) { return Type::Object(); }
1482
1483Type Typer::Visitor::TypeJSCreateArguments(Node* node) {
1484 switch (CreateArgumentsTypeOf(node->op())) {
1486 return Type::Array();
1489 return Type::OtherObject();
1490 }
1491 UNREACHABLE();
1492}
1493
1494Type Typer::Visitor::TypeJSCreateArray(Node* node) { return Type::Array(); }
1495
1496Type Typer::Visitor::TypeJSCreateArrayIterator(Node* node) {
1497 return Type::OtherObject();
1498}
1499
1500Type Typer::Visitor::TypeJSCreateAsyncFunctionObject(Node* node) {
1501 return Type::OtherObject();
1502}
1503
1504Type Typer::Visitor::TypeJSCreateCollectionIterator(Node* node) {
1505 return Type::OtherObject();
1506}
1507
1508Type Typer::Visitor::TypeJSCreateBoundFunction(Node* node) {
1509 return Type::BoundFunction();
1510}
1511
1512Type Typer::Visitor::TypeJSCreateGeneratorObject(Node* node) {
1513 return Type::OtherObject();
1514}
1515
1516Type Typer::Visitor::TypeJSCreateClosure(Node* node) {
1517 SharedFunctionInfoRef shared =
1518 JSCreateClosureNode{node}.Parameters().shared_info();
1519 if (IsClassConstructor(shared.kind())) {
1520 return Type::ClassConstructor();
1521 } else {
1522 return Type::CallableFunction();
1523 }
1524}
1525
1526Type Typer::Visitor::TypeJSCreateIterResultObject(Node* node) {
1527 return Type::OtherObject();
1528}
1529
1530Type Typer::Visitor::TypeJSCreateStringIterator(Node* node) {
1531 return Type::OtherObject();
1532}
1533
1534Type Typer::Visitor::TypeJSCreateKeyValueArray(Node* node) {
1535 return Type::Array();
1536}
1537
1538Type Typer::Visitor::TypeJSCreateObject(Node* node) {
1539 return Type::OtherObject();
1540}
1541
1542Type Typer::Visitor::TypeJSCreateStringWrapper(Node* node) {
1543 return Type::StringWrapper();
1544}
1545
1546Type Typer::Visitor::TypeJSCreatePromise(Node* node) {
1547 return Type::OtherObject();
1548}
1549
1550Type Typer::Visitor::TypeJSCreateTypedArray(Node* node) {
1551 return Type::TypedArray();
1552}
1553
1554Type Typer::Visitor::TypeJSCreateLiteralArray(Node* node) {
1555 return Type::Array();
1556}
1557
1558Type Typer::Visitor::TypeJSCreateEmptyLiteralArray(Node* node) {
1559 return Type::Array();
1560}
1561
1562Type Typer::Visitor::TypeJSCreateArrayFromIterable(Node* node) {
1563 return Type::Array();
1564}
1565
1566Type Typer::Visitor::TypeJSCreateLiteralObject(Node* node) {
1567 return Type::OtherObject();
1568}
1569
1570Type Typer::Visitor::TypeJSCreateEmptyLiteralObject(Node* node) {
1571 return Type::OtherObject();
1572}
1573
1574Type Typer::Visitor::TypeJSCloneObject(Node* node) {
1575 return Type::OtherObject();
1576}
1577
1578Type Typer::Visitor::TypeJSCreateLiteralRegExp(Node* node) {
1579 return Type::OtherObject();
1580}
1581
1582Type Typer::Visitor::TypeJSGetTemplateObject(Node* node) {
1583 return Type::Array();
1584}
1585
1586Type Typer::Visitor::TypeJSLoadProperty(Node* node) { return Type::Any(); }
1587
1588Type Typer::Visitor::TypeJSLoadNamed(Node* node) {
1589#ifdef DEBUG
1590 // Loading of private methods is compiled to a named load of a BlockContext
1591 // via a private brand, which is an internal object. However, native context
1592 // specialization should always apply for those cases, so assert that the name
1593 // is not a private brand here. Otherwise Type::NonInternal() is wrong.
1594 JSLoadNamedNode n(node);
1595 NamedAccess const& p = n.Parameters();
1596 DCHECK(!p.name().object()->IsPrivateBrand());
1597#endif
1598 return Type::NonInternal();
1599}
1600
1601Type Typer::Visitor::TypeJSLoadNamedFromSuper(Node* node) {
1602 return Type::NonInternal();
1603}
1604
1605Type Typer::Visitor::TypeJSLoadGlobal(Node* node) {
1606 return Type::NonInternal();
1607}
1608
1609Type Typer::Visitor::TypeJSParseInt(Type input) { return Type::Number(); }
1610
1611Type Typer::Visitor::TypeJSRegExpTest(Node* node) { return Type::Boolean(); }
1612
1613// Returns a somewhat larger range if we previously assigned
1614// a (smaller) range to this node. This is used to speed up
1615// the fixpoint calculation in case there appears to be a loop
1616// in the graph. In the current implementation, we are
1617// increasing the limits to the closest power of two.
1618Type Typer::Visitor::Weaken(Node* node, Type current_type, Type previous_type) {
1619 static const double kWeakenMinLimits[] = {0.0,
1620 -1073741824.0,
1621 -2147483648.0,
1622 -4294967296.0,
1623 -8589934592.0,
1624 -17179869184.0,
1625 -34359738368.0,
1626 -68719476736.0,
1627 -137438953472.0,
1628 -274877906944.0,
1629 -549755813888.0,
1630 -1099511627776.0,
1631 -2199023255552.0,
1632 -4398046511104.0,
1633 -8796093022208.0,
1634 -17592186044416.0,
1635 -35184372088832.0,
1636 -70368744177664.0,
1637 -140737488355328.0,
1638 -281474976710656.0,
1639 -562949953421312.0};
1640 static const double kWeakenMaxLimits[] = {0.0,
1641 1073741823.0,
1642 2147483647.0,
1643 4294967295.0,
1644 8589934591.0,
1645 17179869183.0,
1646 34359738367.0,
1647 68719476735.0,
1648 137438953471.0,
1649 274877906943.0,
1650 549755813887.0,
1651 1099511627775.0,
1652 2199023255551.0,
1653 4398046511103.0,
1654 8796093022207.0,
1655 17592186044415.0,
1656 35184372088831.0,
1657 70368744177663.0,
1658 140737488355327.0,
1659 281474976710655.0,
1660 562949953421311.0};
1661 static_assert(arraysize(kWeakenMinLimits) == arraysize(kWeakenMaxLimits));
1662
1663 // If the types have nothing to do with integers, return the types.
1664 Type const integer = typer_->cache_->kInteger;
1665 if (!previous_type.Maybe(integer)) {
1666 return current_type;
1667 }
1668 DCHECK(current_type.Maybe(integer));
1669
1670 Type current_integer = Type::Intersect(current_type, integer, zone());
1671 Type previous_integer = Type::Intersect(previous_type, integer, zone());
1672
1673 // Once we start weakening a node, we should always weaken.
1674 if (!IsWeakened(node->id())) {
1675 // Only weaken if there is range involved; we should converge quickly
1676 // for all other types (the exception is a union of many constants,
1677 // but we currently do not increase the number of constants in unions).
1678 Type previous = previous_integer.GetRange();
1679 Type current = current_integer.GetRange();
1680 if (current.IsInvalid() || previous.IsInvalid()) {
1681 return current_type;
1682 }
1683 // Range is involved => we are weakening.
1684 SetWeakened(node->id());
1685 }
1686
1687 double current_min = current_integer.Min();
1688 double new_min = current_min;
1689 // Find the closest lower entry in the list of allowed
1690 // minima (or negative infinity if there is no such entry).
1691 if (current_min != previous_integer.Min()) {
1692 new_min = -V8_INFINITY;
1693 for (double const min : kWeakenMinLimits) {
1694 if (min <= current_min) {
1695 new_min = min;
1696 break;
1697 }
1698 }
1699 }
1700
1701 double current_max = current_integer.Max();
1702 double new_max = current_max;
1703 // Find the closest greater entry in the list of allowed
1704 // maxima (or infinity if there is no such entry).
1705 if (current_max != previous_integer.Max()) {
1706 new_max = V8_INFINITY;
1707 for (double const max : kWeakenMaxLimits) {
1708 if (max >= current_max) {
1709 new_max = max;
1710 break;
1711 }
1712 }
1713 }
1714
1715 return Type::Union(current_type,
1716 Type::Range(new_min, new_max, typer_->zone()),
1717 typer_->zone());
1718}
1719
1720Type Typer::Visitor::TypeJSSetKeyedProperty(Node* node) { UNREACHABLE(); }
1721
1722Type Typer::Visitor::TypeJSDefineKeyedOwnProperty(Node* node) { UNREACHABLE(); }
1723
1724Type Typer::Visitor::TypeJSSetNamedProperty(Node* node) { UNREACHABLE(); }
1725
1726Type Typer::Visitor::TypeJSStoreGlobal(Node* node) { UNREACHABLE(); }
1727
1728Type Typer::Visitor::TypeJSDefineNamedOwnProperty(Node* node) { UNREACHABLE(); }
1729
1730Type Typer::Visitor::TypeJSDefineKeyedOwnPropertyInLiteral(Node* node) {
1731 UNREACHABLE();
1732}
1733
1734Type Typer::Visitor::TypeJSStoreInArrayLiteral(Node* node) { UNREACHABLE(); }
1735
1736Type Typer::Visitor::TypeJSDeleteProperty(Node* node) {
1737 return Type::Boolean();
1738}
1739
1740Type Typer::Visitor::TypeJSHasProperty(Node* node) { return Type::Boolean(); }
1741
1742// JS instanceof operator.
1743
1744Type Typer::Visitor::JSHasInPrototypeChainTyper(Type lhs, Type rhs, Typer* t) {
1745 return Type::Boolean();
1746}
1747
1748Type Typer::Visitor::JSInstanceOfTyper(Type lhs, Type rhs, Typer* t) {
1749 return Type::Boolean();
1750}
1751
1752Type Typer::Visitor::JSOrdinaryHasInstanceTyper(Type lhs, Type rhs, Typer* t) {
1753 return Type::Boolean();
1754}
1755
1756Type Typer::Visitor::TypeJSGetSuperConstructor(Node* node) {
1757 return Type::NonInternal();
1758}
1759
1760Type Typer::Visitor::TypeJSFindNonDefaultConstructorOrConstruct(Node* node) {
1761 return Type::Tuple(Type::Boolean(), Type::ReceiverOrNull(), zone());
1762}
1763
1764// JS context operators.
1765Type Typer::Visitor::TypeJSHasContextExtension(Node* node) {
1766 return Type::Boolean();
1767}
1768
1769Type Typer::Visitor::TypeJSLoadContext(Node* node) {
1770 ContextAccess const& access = ContextAccessOf(node->op());
1771 switch (access.index()) {
1774 return Type::OtherInternal();
1775 default:
1776 return Type::Any();
1777 }
1778}
1779
1780Type Typer::Visitor::TypeJSLoadScriptContext(Node* node) {
1781 ContextAccess const& access = ContextAccessOf(node->op());
1782 switch (access.index()) {
1786 return Type::OtherInternal();
1787 default:
1788 return Type::Any();
1789 }
1790}
1791
1792Type Typer::Visitor::TypeJSStoreContext(Node* node) { UNREACHABLE(); }
1793
1794Type Typer::Visitor::TypeJSStoreScriptContext(Node* node) { UNREACHABLE(); }
1795
1796Type Typer::Visitor::TypeJSCreateFunctionContext(Node* node) {
1797 return Type::OtherInternal();
1798}
1799
1800Type Typer::Visitor::TypeJSCreateCatchContext(Node* node) {
1801 return Type::OtherInternal();
1802}
1803
1804Type Typer::Visitor::TypeJSCreateWithContext(Node* node) {
1805 return Type::OtherInternal();
1806}
1807
1808Type Typer::Visitor::TypeJSCreateBlockContext(Node* node) {
1809 return Type::OtherInternal();
1810}
1811
1812// JS other operators.
1813
1814Type Typer::Visitor::TypeJSConstructForwardVarargs(Node* node) {
1815 return Type::Receiver();
1816}
1817
1818Type Typer::Visitor::TypeJSConstructForwardAllArgs(Node* node) {
1819 return Type::Receiver();
1820}
1821
1822Type Typer::Visitor::TypeJSConstruct(Node* node) { return Type::Receiver(); }
1823
1824Type Typer::Visitor::TypeJSConstructWithArrayLike(Node* node) {
1825 return Type::Receiver();
1826}
1827
1828Type Typer::Visitor::TypeJSConstructWithSpread(Node* node) {
1829 return Type::Receiver();
1830}
1831
1832Type Typer::Visitor::TypeJSObjectIsArray(Node* node) { return Type::Boolean(); }
1833
1834Type Typer::Visitor::TypeDateNow(Node* node) { return Type::Number(); }
1835
1836Type Typer::Visitor::TypeDoubleArrayMin(Node* node) { return Type::Number(); }
1837
1838Type Typer::Visitor::TypeDoubleArrayMax(Node* node) { return Type::Number(); }
1839
1840Type Typer::Visitor::TypeUnsigned32Divide(Node* node) {
1841 Type lhs = Operand(node, 0);
1842 return Type::Range(0, lhs.Max(), zone());
1843}
1844
1846 if (!fun.IsHeapConstant() || !fun.AsHeapConstant()->Ref().IsJSFunction()) {
1847 return Type::NonInternal();
1848 }
1849 JSFunctionRef function = fun.AsHeapConstant()->Ref().AsJSFunction();
1850 if (!function.shared(t->broker()).HasBuiltinId()) {
1851 return Type::NonInternal();
1852 }
1853 switch (function.shared(t->broker()).builtin_id()) {
1854 case Builtin::kMathRandom:
1855 return Type::PlainNumber();
1856 case Builtin::kMathFloor:
1857 case Builtin::kMathCeil:
1858 case Builtin::kMathRound:
1859 case Builtin::kMathTrunc:
1860 return t->cache_->kIntegerOrMinusZeroOrNaN;
1861 // Unary math functions.
1862 case Builtin::kMathAbs:
1863 case Builtin::kMathExp:
1864 return Type::Union(Type::PlainNumber(), Type::NaN(), t->zone());
1865 case Builtin::kMathAcos:
1866 case Builtin::kMathAcosh:
1867 case Builtin::kMathAsin:
1868 case Builtin::kMathAsinh:
1869 case Builtin::kMathAtan:
1870 case Builtin::kMathAtanh:
1871 case Builtin::kMathCbrt:
1872 case Builtin::kMathCos:
1873 case Builtin::kMathExpm1:
1874 case Builtin::kMathFround:
1875 case Builtin::kMathLog:
1876 case Builtin::kMathLog1p:
1877 case Builtin::kMathLog10:
1878 case Builtin::kMathLog2:
1879 case Builtin::kMathSin:
1880 case Builtin::kMathSqrt:
1881 case Builtin::kMathTan:
1882 return Type::Number();
1883 case Builtin::kMathSign:
1884 return t->cache_->kMinusOneToOneOrMinusZeroOrNaN;
1885 // Binary math functions.
1886 case Builtin::kMathAtan2:
1887 case Builtin::kMathPow:
1888 case Builtin::kMathMax:
1889 case Builtin::kMathMin:
1890 case Builtin::kMathHypot:
1891 return Type::Number();
1892 case Builtin::kMathImul:
1893 return Type::Signed32();
1894 case Builtin::kMathClz32:
1895 return t->cache_->kZeroToThirtyTwo;
1896 // Date functions.
1897 case Builtin::kDateNow:
1898 return t->cache_->kTimeValueType;
1899 case Builtin::kDatePrototypeGetDate:
1900 return t->cache_->kJSDateDayType;
1901 case Builtin::kDatePrototypeGetDay:
1902 return t->cache_->kJSDateWeekdayType;
1903 case Builtin::kDatePrototypeGetFullYear:
1904 return t->cache_->kJSDateYearType;
1905 case Builtin::kDatePrototypeGetHours:
1906 return t->cache_->kJSDateHourType;
1907 case Builtin::kDatePrototypeGetMilliseconds:
1908 return Type::Union(Type::Range(0.0, 999.0, t->zone()), Type::NaN(),
1909 t->zone());
1910 case Builtin::kDatePrototypeGetMinutes:
1911 return t->cache_->kJSDateMinuteType;
1912 case Builtin::kDatePrototypeGetMonth:
1913 return t->cache_->kJSDateMonthType;
1914 case Builtin::kDatePrototypeGetSeconds:
1915 return t->cache_->kJSDateSecondType;
1916 case Builtin::kDatePrototypeGetTime:
1917 return t->cache_->kJSDateValueType;
1918
1919 // Symbol functions.
1920 case Builtin::kSymbolConstructor:
1921 return Type::Symbol();
1922 case Builtin::kSymbolPrototypeToString:
1923 return Type::String();
1924 case Builtin::kSymbolPrototypeValueOf:
1925 return Type::Symbol();
1926
1927 // BigInt functions.
1928 case Builtin::kBigIntConstructor:
1929 return Type::BigInt();
1930
1931 // Number functions.
1932 case Builtin::kNumberConstructor:
1933 return Type::Number();
1934 case Builtin::kNumberIsFinite:
1935 case Builtin::kNumberIsInteger:
1936 case Builtin::kNumberIsNaN:
1937 case Builtin::kNumberIsSafeInteger:
1938 return Type::Boolean();
1939 case Builtin::kNumberParseFloat:
1940 return Type::Number();
1941 case Builtin::kNumberParseInt:
1942 return t->cache_->kIntegerOrMinusZeroOrNaN;
1943 case Builtin::kNumberToString:
1944 return Type::String();
1945
1946 // String functions.
1947 case Builtin::kStringConstructor:
1948 return Type::String();
1949 case Builtin::kStringPrototypeCharCodeAt:
1950 return Type::Union(Type::Range(0, kMaxUInt16, t->zone()), Type::NaN(),
1951 t->zone());
1952 case Builtin::kStringCharAt:
1953 return Type::String();
1954 case Builtin::kStringPrototypeCodePointAt:
1955 return Type::Union(Type::Range(0.0, String::kMaxCodePoint, t->zone()),
1956 Type::Undefined(), t->zone());
1957 case Builtin::kStringPrototypeConcat:
1958 case Builtin::kStringFromCharCode:
1959 case Builtin::kStringFromCodePoint:
1960 return Type::String();
1961 case Builtin::kStringPrototypeIndexOf:
1962 case Builtin::kStringPrototypeLastIndexOf:
1963 return Type::Range(-1.0, String::kMaxLength, t->zone());
1964 case Builtin::kStringPrototypeEndsWith:
1965 case Builtin::kStringPrototypeIncludes:
1966 return Type::Boolean();
1967 case Builtin::kStringRaw:
1968 case Builtin::kStringRepeat:
1969 case Builtin::kStringPrototypeSlice:
1970 return Type::String();
1971 case Builtin::kStringPrototypeStartsWith:
1972 return Type::Boolean();
1973 case Builtin::kStringPrototypeSubstr:
1974 case Builtin::kStringSubstring:
1975 case Builtin::kStringPrototypeToString:
1976#ifdef V8_INTL_SUPPORT
1977 case Builtin::kStringPrototypeToLowerCaseIntl:
1978 case Builtin::kStringPrototypeToUpperCaseIntl:
1979#else
1980 case Builtin::kStringPrototypeToLowerCase:
1981 case Builtin::kStringPrototypeToUpperCase:
1982#endif
1983 case Builtin::kStringPrototypeTrim:
1984 case Builtin::kStringPrototypeTrimEnd:
1985 case Builtin::kStringPrototypeTrimStart:
1986 case Builtin::kStringPrototypeValueOf:
1987 return Type::String();
1988
1989 case Builtin::kStringPrototypeIterator:
1990 case Builtin::kStringIteratorPrototypeNext:
1991 return Type::OtherObject();
1992
1993 case Builtin::kArrayPrototypeEntries:
1994 case Builtin::kArrayPrototypeKeys:
1995 case Builtin::kArrayPrototypeValues:
1996 case Builtin::kTypedArrayPrototypeEntries:
1997 case Builtin::kTypedArrayPrototypeKeys:
1998 case Builtin::kTypedArrayPrototypeValues:
1999 case Builtin::kArrayIteratorPrototypeNext:
2000 case Builtin::kMapIteratorPrototypeNext:
2001 case Builtin::kSetIteratorPrototypeNext:
2002 return Type::OtherObject();
2003 case Builtin::kTypedArrayPrototypeToStringTag:
2004 return Type::Union(Type::InternalizedString(), Type::Undefined(),
2005 t->zone());
2006
2007 // Array functions.
2008 case Builtin::kArrayIsArray:
2009 return Type::Boolean();
2010 case Builtin::kArrayConcat:
2011 return Type::Receiver();
2012 case Builtin::kArrayEvery:
2013 return Type::Boolean();
2014 case Builtin::kArrayPrototypeFill:
2015 case Builtin::kArrayFilter:
2016 return Type::Receiver();
2017 case Builtin::kArrayPrototypeFindIndex:
2018 return Type::Range(-1, kMaxSafeInteger, t->zone());
2019 case Builtin::kArrayForEach:
2020 return Type::Undefined();
2021 case Builtin::kArrayIncludes:
2022 return Type::Boolean();
2023 case Builtin::kArrayIndexOf:
2024 return Type::Range(-1, kMaxSafeInteger, t->zone());
2025 case Builtin::kArrayPrototypeJoin:
2026 return Type::String();
2027 case Builtin::kArrayPrototypeLastIndexOf:
2028 return Type::Range(-1, kMaxSafeInteger, t->zone());
2029 case Builtin::kArrayMap:
2030 return Type::Receiver();
2031 case Builtin::kArrayPush:
2032 return t->cache_->kPositiveSafeInteger;
2033 case Builtin::kArrayPrototypeReverse:
2034 case Builtin::kArrayPrototypeSlice:
2035 return Type::Receiver();
2036 case Builtin::kArraySome:
2037 return Type::Boolean();
2038 case Builtin::kArrayPrototypeSplice:
2039 return Type::Receiver();
2040 case Builtin::kArrayUnshift:
2041 return t->cache_->kPositiveSafeInteger;
2042
2043 // ArrayBuffer functions.
2044 case Builtin::kArrayBufferIsView:
2045 return Type::Boolean();
2046
2047 // Object functions.
2048 case Builtin::kObjectAssign:
2049 return Type::Receiver();
2050 case Builtin::kObjectCreate:
2051 return Type::OtherObject();
2052 case Builtin::kObjectIs:
2053 case Builtin::kObjectHasOwn:
2054 case Builtin::kObjectPrototypeHasOwnProperty:
2055 case Builtin::kObjectPrototypeIsPrototypeOf:
2056 return Type::Boolean();
2057 case Builtin::kObjectToString:
2058 return Type::String();
2059
2060 case Builtin::kPromiseAll:
2061 return Type::Receiver();
2062 case Builtin::kPromisePrototypeThen:
2063 return Type::Receiver();
2064 case Builtin::kPromiseRace:
2065 return Type::Receiver();
2066 case Builtin::kPromiseReject:
2067 return Type::Receiver();
2068 case Builtin::kPromiseResolveTrampoline:
2069 return Type::Receiver();
2070
2071 // RegExp functions.
2072 case Builtin::kRegExpPrototypeCompile:
2073 return Type::OtherObject();
2074 case Builtin::kRegExpPrototypeExec:
2075 return Type::Union(Type::Array(), Type::Null(), t->zone());
2076 case Builtin::kRegExpPrototypeTest:
2077 return Type::Boolean();
2078 case Builtin::kRegExpPrototypeToString:
2079 return Type::String();
2080
2081 // Function functions.
2082 case Builtin::kFunctionPrototypeBind:
2083 return Type::BoundFunction();
2084 case Builtin::kFunctionPrototypeHasInstance:
2085 return Type::Boolean();
2086
2087 // Global functions.
2088 case Builtin::kGlobalDecodeURI:
2089 case Builtin::kGlobalDecodeURIComponent:
2090 case Builtin::kGlobalEncodeURI:
2091 case Builtin::kGlobalEncodeURIComponent:
2092 case Builtin::kGlobalEscape:
2093 case Builtin::kGlobalUnescape:
2094 return Type::String();
2095 case Builtin::kGlobalIsFinite:
2096 case Builtin::kGlobalIsNaN:
2097 return Type::Boolean();
2098
2099 // Map functions.
2100 case Builtin::kMapPrototypeClear:
2101 case Builtin::kMapPrototypeForEach:
2102 return Type::Undefined();
2103 case Builtin::kMapPrototypeDelete:
2104 case Builtin::kMapPrototypeHas:
2105 return Type::Boolean();
2106 case Builtin::kMapPrototypeEntries:
2107 case Builtin::kMapPrototypeKeys:
2108 case Builtin::kMapPrototypeSet:
2109 case Builtin::kMapPrototypeValues:
2110 return Type::OtherObject();
2111
2112 // Set functions.
2113 case Builtin::kSetPrototypeAdd:
2114 case Builtin::kSetPrototypeEntries:
2115 case Builtin::kSetPrototypeValues:
2116 return Type::OtherObject();
2117 case Builtin::kSetPrototypeClear:
2118 case Builtin::kSetPrototypeForEach:
2119 return Type::Undefined();
2120 case Builtin::kSetPrototypeDelete:
2121 case Builtin::kSetPrototypeHas:
2122 return Type::Boolean();
2123
2124 // WeakMap functions.
2125 case Builtin::kWeakMapPrototypeDelete:
2126 case Builtin::kWeakMapPrototypeHas:
2127 return Type::Boolean();
2128 case Builtin::kWeakMapPrototypeSet:
2129 return Type::OtherObject();
2130
2131 // WeakSet functions.
2132 case Builtin::kWeakSetPrototypeAdd:
2133 return Type::OtherObject();
2134 case Builtin::kWeakSetPrototypeDelete:
2135 case Builtin::kWeakSetPrototypeHas:
2136 return Type::Boolean();
2137 default:
2138 return Type::NonInternal();
2139 }
2140}
2141
2142Type Typer::Visitor::TypeJSCallForwardVarargs(Node* node) {
2143 return TypeUnaryOp(node, JSCallTyper);
2144}
2145
2146Type Typer::Visitor::TypeJSCall(Node* node) {
2147 // TODO(bmeurer): We could infer better types if we wouldn't ignore the
2148 // argument types for the JSCallTyper above.
2149 return TypeUnaryOp(node, JSCallTyper);
2150}
2151
2152Type Typer::Visitor::TypeJSCallWithArrayLike(Node* node) {
2153 return TypeUnaryOp(node, JSCallTyper);
2154}
2155
2156Type Typer::Visitor::TypeJSCallWithSpread(Node* node) {
2157 return TypeUnaryOp(node, JSCallTyper);
2158}
2159
2160Type Typer::Visitor::TypeJSCallRuntime(Node* node) {
2161 switch (CallRuntimeParametersOf(node->op()).id()) {
2162 case Runtime::kInlineCreateIterResultObject:
2163 return Type::OtherObject();
2164 case Runtime::kHasInPrototypeChain:
2165 return Type::Boolean();
2166 default:
2167 break;
2168 }
2169 // TODO(turbofan): This should be Type::NonInternal(), but unfortunately we
2170 // have a few weird runtime calls that return the hole or even FixedArrays;
2171 // change this once those weird runtime calls have been removed.
2172 return Type::Any();
2173}
2174
2175Type Typer::Visitor::TypeJSForInEnumerate(Node* node) {
2176 return Type::OtherInternal();
2177}
2178
2179Type Typer::Visitor::TypeJSForInNext(Node* node) {
2180 return Type::Union(Type::String(), Type::Undefined(), zone());
2181}
2182
2183Type Typer::Visitor::TypeJSForInPrepare(Node* node) {
2184 static_assert(Map::Bits3::EnumLengthBits::kMax <= FixedArray::kMaxLength);
2185 Type const cache_type =
2186 Type::Union(Type::SignedSmall(), Type::OtherInternal(), zone());
2187 Type const cache_array = Type::OtherInternal();
2188 Type const cache_length = typer_->cache_->kFixedArrayLengthType;
2189 return Type::Tuple(cache_type, cache_array, cache_length, zone());
2190}
2191
2192Type Typer::Visitor::TypeJSLoadMessage(Node* node) { return Type::Any(); }
2193
2194Type Typer::Visitor::TypeJSStoreMessage(Node* node) { UNREACHABLE(); }
2195
2196Type Typer::Visitor::TypeJSLoadModule(Node* node) { return Type::Any(); }
2197
2198Type Typer::Visitor::TypeJSStoreModule(Node* node) { UNREACHABLE(); }
2199
2200Type Typer::Visitor::TypeJSGetImportMeta(Node* node) { return Type::Any(); }
2201
2202Type Typer::Visitor::TypeJSGeneratorStore(Node* node) { UNREACHABLE(); }
2203
2204Type Typer::Visitor::TypeJSGeneratorRestoreContinuation(Node* node) {
2205 return Type::SignedSmall();
2206}
2207
2208Type Typer::Visitor::TypeJSGeneratorRestoreContext(Node* node) {
2209 return Type::Any();
2210}
2211
2212Type Typer::Visitor::TypeJSGeneratorRestoreRegister(Node* node) {
2213 return Type::Any();
2214}
2215
2216Type Typer::Visitor::TypeJSGeneratorRestoreInputOrDebugPos(Node* node) {
2217 return Type::Any();
2218}
2219
2220Type Typer::Visitor::TypeJSStackCheck(Node* node) { return Type::Any(); }
2221
2222Type Typer::Visitor::TypeJSDebugger(Node* node) { return Type::Any(); }
2223
2224Type Typer::Visitor::TypeJSAsyncFunctionEnter(Node* node) {
2225 return Type::OtherObject();
2226}
2227
2228Type Typer::Visitor::TypeJSAsyncFunctionReject(Node* node) {
2229 return Type::OtherObject();
2230}
2231
2232Type Typer::Visitor::TypeJSAsyncFunctionResolve(Node* node) {
2233 return Type::OtherObject();
2234}
2235
2236Type Typer::Visitor::TypeJSFulfillPromise(Node* node) {
2237 return Type::Undefined();
2238}
2239
2240Type Typer::Visitor::TypeJSPerformPromiseThen(Node* node) {
2241 return Type::Receiver();
2242}
2243
2244Type Typer::Visitor::TypeJSPromiseResolve(Node* node) {
2245 return Type::Receiver();
2246}
2247
2248Type Typer::Visitor::TypeJSRejectPromise(Node* node) {
2249 return Type::Undefined();
2250}
2251
2252Type Typer::Visitor::TypeJSResolvePromise(Node* node) {
2253 return Type::Undefined();
2254}
2255
2256// Simplified operators.
2257
2258Type Typer::Visitor::TypeBooleanNot(Node* node) { return Type::Boolean(); }
2259
2260// static
2262 return JSEqualTyper(ToNumber(lhs, t), ToNumber(rhs, t), t);
2263}
2264
2265// static
2267 return FalsifyUndefined(
2268 NumberCompareTyper(ToNumber(lhs, t), ToNumber(rhs, t), t), t);
2269}
2270
2271// static
2273 return FalsifyUndefined(
2274 Invert(JSCompareTyper(ToNumber(rhs, t), ToNumber(lhs, t), t), t), t);
2275}
2276
2277// static
2279 if (lhs.IsNone() || rhs.IsNone()) {
2280 return Type::None();
2281 }
2282 return Type::Boolean();
2283}
2284
2285Type Typer::Visitor::TypeNumberEqual(Node* node) {
2286 return TypeBinaryOp(node, NumberEqualTyper);
2287}
2288
2289Type Typer::Visitor::TypeNumberLessThan(Node* node) {
2290 return TypeBinaryOp(node, NumberLessThanTyper);
2291}
2292
2293Type Typer::Visitor::TypeNumberLessThanOrEqual(Node* node) {
2294 return TypeBinaryOp(node, NumberLessThanOrEqualTyper);
2295}
2296
2297Type Typer::Visitor::TypeSpeculativeNumberEqual(Node* node) {
2298 return TypeBinaryOp(node, NumberEqualTyper);
2299}
2300
2301Type Typer::Visitor::TypeSpeculativeNumberLessThan(Node* node) {
2302 return TypeBinaryOp(node, NumberLessThanTyper);
2303}
2304
2305Type Typer::Visitor::TypeSpeculativeNumberLessThanOrEqual(Node* node) {
2306 return TypeBinaryOp(node, NumberLessThanOrEqualTyper);
2307}
2308
2309#define BIGINT_COMPARISON_BINOP(Name) \
2310 Type Typer::Visitor::Type##Name(Node* node) { \
2311 return TypeBinaryOp(node, BigIntCompareTyper); \
2312 }
2313BIGINT_COMPARISON_BINOP(BigIntEqual)
2314BIGINT_COMPARISON_BINOP(BigIntLessThan)
2315BIGINT_COMPARISON_BINOP(BigIntLessThanOrEqual)
2316BIGINT_COMPARISON_BINOP(SpeculativeBigIntEqual)
2317BIGINT_COMPARISON_BINOP(SpeculativeBigIntLessThan)
2318BIGINT_COMPARISON_BINOP(SpeculativeBigIntLessThanOrEqual)
2319#undef BIGINT_COMPARISON_BINOP
2320
2321Type Typer::Visitor::TypeStringConcat(Node* node) { return Type::String(); }
2322
2323Type Typer::Visitor::TypeStringToNumber(Node* node) {
2324 return TypeUnaryOp(node, ToNumber);
2325}
2326
2327Type Typer::Visitor::TypePlainPrimitiveToNumber(Node* node) {
2328 return TypeUnaryOp(node, ToNumber);
2329}
2330
2331Type Typer::Visitor::TypePlainPrimitiveToWord32(Node* node) {
2332 return Type::Integral32();
2333}
2334
2335Type Typer::Visitor::TypePlainPrimitiveToFloat64(Node* node) {
2336 return Type::Number();
2337}
2338
2339// static
2341 if (lhs.IsHeapConstant() && rhs.Is(lhs)) {
2342 return t->singleton_true_;
2343 }
2344 return Type::Boolean();
2345}
2346
2347Type Typer::Visitor::TypeReferenceEqual(Node* node) {
2348 return TypeBinaryOp(node, ReferenceEqualTyper);
2349}
2350
2351// static
2353 return t->operation_typer()->SameValue(lhs, rhs);
2354}
2355
2356// static
2358 return t->operation_typer()->SameValueNumbersOnly(lhs, rhs);
2359}
2360
2361Type Typer::Visitor::TypeSameValue(Node* node) {
2362 return TypeBinaryOp(node, SameValueTyper);
2363}
2364
2365Type Typer::Visitor::TypeSameValueNumbersOnly(Node* node) {
2366 return TypeBinaryOp(node, SameValueNumbersOnlyTyper);
2367}
2368
2369Type Typer::Visitor::TypeNumberSameValue(Node* node) { UNREACHABLE(); }
2370
2371Type Typer::Visitor::TypeStringEqual(Node* node) { return Type::Boolean(); }
2372
2373Type Typer::Visitor::TypeStringLessThan(Node* node) { return Type::Boolean(); }
2374
2375Type Typer::Visitor::TypeStringLessThanOrEqual(Node* node) {
2376 return Type::Boolean();
2377}
2378
2380 return Type::String();
2381}
2382
2384 return Type::String();
2385}
2386
2387Type Typer::Visitor::TypeStringToLowerCaseIntl(Node* node) {
2388 return Type::String();
2389}
2390
2391Type Typer::Visitor::TypeStringToUpperCaseIntl(Node* node) {
2392 return Type::String();
2393}
2394
2395Type Typer::Visitor::TypeStringCharCodeAt(Node* node) {
2396 return typer_->cache_->kUint16;
2397}
2398
2399Type Typer::Visitor::TypeStringCodePointAt(Node* node) {
2400 return Type::Range(0.0, String::kMaxCodePoint, zone());
2401}
2402
2403Type Typer::Visitor::TypeStringFromSingleCharCode(Node* node) {
2404 return TypeUnaryOp(node, StringFromSingleCharCodeTyper);
2405}
2406
2407Type Typer::Visitor::TypeStringFromSingleCodePoint(Node* node) {
2408 return TypeUnaryOp(node, StringFromSingleCodePointTyper);
2409}
2410
2411Type Typer::Visitor::TypeStringFromCodePointAt(Node* node) {
2412 return Type::String();
2413}
2414
2415Type Typer::Visitor::TypeStringIndexOf(Node* node) {
2416 return Type::Range(-1.0, String::kMaxLength, zone());
2417}
2418
2419Type Typer::Visitor::TypeStringLength(Node* node) {
2420 return typer_->cache_->kStringLengthType;
2421}
2422
2423Type Typer::Visitor::TypeStringWrapperLength(Node* node) {
2424 return typer_->cache_->kStringLengthType;
2425}
2426
2427Type Typer::Visitor::TypeStringSubstring(Node* node) { return Type::String(); }
2428
2429Type Typer::Visitor::TypeCheckBounds(Node* node) {
2430 return typer_->operation_typer_.CheckBounds(Operand(node, 0),
2431 Operand(node, 1));
2432}
2433
2434Type Typer::Visitor::TypeCheckHeapObject(Node* node) {
2435 Type type = Operand(node, 0);
2436 return type;
2437}
2438
2439Type Typer::Visitor::TypeCheckIf(Node* node) { UNREACHABLE(); }
2440
2441Type Typer::Visitor::TypeCheckInternalizedString(Node* node) {
2442 Type arg = Operand(node, 0);
2443 return Type::Intersect(arg, Type::InternalizedString(), zone());
2444}
2445
2446Type Typer::Visitor::TypeCheckMaps(Node* node) { UNREACHABLE(); }
2447
2448Type Typer::Visitor::TypeCompareMaps(Node* node) { return Type::Boolean(); }
2449
2450Type Typer::Visitor::TypeCheckNumber(Node* node) {
2451 return typer_->operation_typer_.CheckNumber(Operand(node, 0));
2452}
2453
2454Type Typer::Visitor::TypeCheckNumberFitsInt32(Node* node) {
2455 return typer_->operation_typer_.CheckNumberFitsInt32(Operand(node, 0));
2456}
2457
2458Type Typer::Visitor::TypeCheckReceiver(Node* node) {
2459 Type arg = Operand(node, 0);
2460 return Type::Intersect(arg, Type::Receiver(), zone());
2461}
2462
2463Type Typer::Visitor::TypeCheckReceiverOrNullOrUndefined(Node* node) {
2464 Type arg = Operand(node, 0);
2465 return Type::Intersect(arg, Type::ReceiverOrNullOrUndefined(), zone());
2466}
2467
2468Type Typer::Visitor::TypeCheckSmi(Node* node) {
2469 Type arg = Operand(node, 0);
2470 return Type::Intersect(arg, Type::SignedSmall(), zone());
2471}
2472
2473Type Typer::Visitor::TypeCheckString(Node* node) {
2474 Type arg = Operand(node, 0);
2475 return Type::Intersect(arg, Type::String(), zone());
2476}
2477
2478Type Typer::Visitor::TypeCheckStringOrStringWrapper(Node* node) {
2479 Type arg = Operand(node, 0);
2480 return Type::Intersect(arg, Type::StringOrStringWrapper(), zone());
2481}
2482
2483Type Typer::Visitor::TypeCheckSymbol(Node* node) {
2484 Type arg = Operand(node, 0);
2485 return Type::Intersect(arg, Type::Symbol(), zone());
2486}
2487
2488Type Typer::Visitor::TypeCheckFloat64Hole(Node* node) {
2489 return typer_->operation_typer_.CheckFloat64Hole(Operand(node, 0));
2490}
2491
2492Type Typer::Visitor::TypeChangeFloat64HoleToTagged(Node* node) {
2493 return typer_->operation_typer_.CheckFloat64Hole(Operand(node, 0));
2494}
2495
2496Type Typer::Visitor::TypeCheckNotTaggedHole(Node* node) {
2497 Type type = Operand(node, 0);
2498 type = Type::Intersect(type, Type::NonInternal(), zone());
2499 return type;
2500}
2501
2502Type Typer::Visitor::TypeCheckClosure(Node* node) {
2503 FeedbackCellRef cell = MakeRef(typer_->broker(), FeedbackCellOf(node->op()));
2504 OptionalSharedFunctionInfoRef shared = cell.shared_function_info(broker());
2505 if (!shared.has_value()) return Type::Function();
2506
2507 if (IsClassConstructor(shared->kind())) {
2508 return Type::ClassConstructor();
2509 } else {
2510 return Type::CallableFunction();
2511 }
2512}
2513
2514Type Typer::Visitor::TypeConvertReceiver(Node* node) {
2515 Type arg = Operand(node, 0);
2516 return typer_->operation_typer_.ConvertReceiver(arg);
2517}
2518
2519Type Typer::Visitor::TypeConvertTaggedHoleToUndefined(Node* node) {
2520 Type type = Operand(node, 0);
2521 return typer_->operation_typer()->ConvertTaggedHoleToUndefined(type);
2522}
2523
2524Type Typer::Visitor::TypeCheckEqualsInternalizedString(Node* node) {
2525 UNREACHABLE();
2526}
2527
2528Type Typer::Visitor::TypeCheckEqualsSymbol(Node* node) { UNREACHABLE(); }
2529
2530Type Typer::Visitor::TypeAllocate(Node* node) {
2531 return AllocateTypeOf(node->op());
2532}
2533
2534Type Typer::Visitor::TypeAllocateRaw(Node* node) { UNREACHABLE(); }
2535
2536Type Typer::Visitor::TypeLoadFieldByIndex(Node* node) {
2537 return Type::NonInternal();
2538}
2539
2540Type Typer::Visitor::TypeLoadField(Node* node) {
2541 return FieldAccessOf(node->op()).type;
2542}
2543
2544Type Typer::Visitor::TypeLoadMessage(Node* node) { return Type::Any(); }
2545
2546Type Typer::Visitor::TypeLoadElement(Node* node) {
2547 return ElementAccessOf(node->op()).type;
2548}
2549
2550Type Typer::Visitor::TypeLoadStackArgument(Node* node) {
2551 return Type::NonInternal();
2552}
2553
2554Type Typer::Visitor::TypeLoadFromObject(Node* node) { UNREACHABLE(); }
2555Type Typer::Visitor::TypeLoadImmutableFromObject(Node* node) { UNREACHABLE(); }
2556
2557Type Typer::Visitor::TypeLoadTypedElement(Node* node) {
2558 switch (ExternalArrayTypeOf(node->op())) {
2559#define TYPED_ARRAY_CASE(ElemType, type, TYPE, ctype) \
2560 case kExternal##ElemType##Array: \
2561 return typer_->cache_->k##ElemType;
2563#undef TYPED_ARRAY_CASE
2564 }
2565 UNREACHABLE();
2566}
2567
2568Type Typer::Visitor::TypeLoadDataViewElement(Node* node) {
2569 switch (ExternalArrayTypeOf(node->op())) {
2570#define TYPED_ARRAY_CASE(ElemType, type, TYPE, ctype) \
2571 case kExternal##ElemType##Array: \
2572 return typer_->cache_->k##ElemType;
2574#undef TYPED_ARRAY_CASE
2575 }
2576 UNREACHABLE();
2577}
2578
2579Type Typer::Visitor::TypeStoreField(Node* node) { UNREACHABLE(); }
2580
2581Type Typer::Visitor::TypeStoreMessage(Node* node) { UNREACHABLE(); }
2582
2583Type Typer::Visitor::TypeStoreElement(Node* node) { UNREACHABLE(); }
2584
2585Type Typer::Visitor::TypeStoreToObject(Node* node) { UNREACHABLE(); }
2586Type Typer::Visitor::TypeInitializeImmutableInObject(Node* node) {
2587 UNREACHABLE();
2588}
2589
2590Type Typer::Visitor::TypeTransitionAndStoreElement(Node* node) {
2591 UNREACHABLE();
2592}
2593
2594Type Typer::Visitor::TypeTransitionAndStoreNumberElement(Node* node) {
2595 UNREACHABLE();
2596}
2597
2598Type Typer::Visitor::TypeTransitionAndStoreNonNumberElement(Node* node) {
2599 UNREACHABLE();
2600}
2601
2602Type Typer::Visitor::TypeStoreSignedSmallElement(Node* node) { UNREACHABLE(); }
2603
2604Type Typer::Visitor::TypeStoreTypedElement(Node* node) { UNREACHABLE(); }
2605
2606Type Typer::Visitor::TypeStoreDataViewElement(Node* node) { UNREACHABLE(); }
2607
2608Type Typer::Visitor::TypeObjectIsArrayBufferView(Node* node) {
2609 return TypeUnaryOp(node, ObjectIsArrayBufferView);
2610}
2611
2612Type Typer::Visitor::TypeObjectIsBigInt(Node* node) {
2613 return TypeUnaryOp(node, ObjectIsBigInt);
2614}
2615
2616Type Typer::Visitor::TypeObjectIsCallable(Node* node) {
2617 return TypeUnaryOp(node, ObjectIsCallable);
2618}
2619
2620Type Typer::Visitor::TypeObjectIsConstructor(Node* node) {
2621 return TypeUnaryOp(node, ObjectIsConstructor);
2622}
2623
2624Type Typer::Visitor::TypeObjectIsDetectableCallable(Node* node) {
2625 return TypeUnaryOp(node, ObjectIsDetectableCallable);
2626}
2627
2628Type Typer::Visitor::TypeObjectIsMinusZero(Node* node) {
2629 return TypeUnaryOp(node, ObjectIsMinusZero);
2630}
2631
2632Type Typer::Visitor::TypeNumberIsMinusZero(Node* node) {
2633 return TypeUnaryOp(node, NumberIsMinusZero);
2634}
2635
2636Type Typer::Visitor::TypeNumberIsFloat64Hole(Node* node) {
2637 return Type::Boolean();
2638}
2639
2640Type Typer::Visitor::TypeNumberIsFinite(Node* node) { return Type::Boolean(); }
2641
2642Type Typer::Visitor::TypeObjectIsFiniteNumber(Node* node) {
2643 return Type::Boolean();
2644}
2645
2646Type Typer::Visitor::TypeNumberIsInteger(Node* node) { UNREACHABLE(); }
2647
2648Type Typer::Visitor::TypeObjectIsSafeInteger(Node* node) {
2649 return Type::Boolean();
2650}
2651
2652Type Typer::Visitor::TypeNumberIsSafeInteger(Node* node) { UNREACHABLE(); }
2653
2654Type Typer::Visitor::TypeObjectIsInteger(Node* node) { return Type::Boolean(); }
2655
2656Type Typer::Visitor::TypeObjectIsNaN(Node* node) {
2657 return TypeUnaryOp(node, ObjectIsNaN);
2658}
2659
2660Type Typer::Visitor::TypeNumberIsNaN(Node* node) {
2661 return TypeUnaryOp(node, NumberIsNaN);
2662}
2663
2664Type Typer::Visitor::TypeObjectIsNonCallable(Node* node) {
2665 return TypeUnaryOp(node, ObjectIsNonCallable);
2666}
2667
2668Type Typer::Visitor::TypeObjectIsNumber(Node* node) {
2669 return TypeUnaryOp(node, ObjectIsNumber);
2670}
2671
2672Type Typer::Visitor::TypeObjectIsReceiver(Node* node) {
2673 return TypeUnaryOp(node, ObjectIsReceiver);
2674}
2675
2676Type Typer::Visitor::TypeObjectIsSmi(Node* node) {
2677 return TypeUnaryOp(node, ObjectIsSmi);
2678}
2679
2680Type Typer::Visitor::TypeObjectIsString(Node* node) {
2681 return TypeUnaryOp(node, ObjectIsString);
2682}
2683
2684Type Typer::Visitor::TypeObjectIsSymbol(Node* node) {
2685 return TypeUnaryOp(node, ObjectIsSymbol);
2686}
2687
2688Type Typer::Visitor::TypeObjectIsUndetectable(Node* node) {
2689 return TypeUnaryOp(node, ObjectIsUndetectable);
2690}
2691
2692Type Typer::Visitor::TypeArgumentsLength(Node* node) {
2694}
2695
2696Type Typer::Visitor::TypeRestLength(Node* node) {
2698}
2699
2700Type Typer::Visitor::TypeTypedArrayLength(Node* node) {
2701 return typer_->cache_->kJSTypedArrayLengthType;
2702}
2703
2704Type Typer::Visitor::TypeNewDoubleElements(Node* node) {
2705 return Type::OtherInternal();
2706}
2707
2708Type Typer::Visitor::TypeNewSmiOrObjectElements(Node* node) {
2709 return Type::OtherInternal();
2710}
2711
2712Type Typer::Visitor::TypeNewArgumentsElements(Node* node) {
2713 return Type::OtherInternal();
2714}
2715
2716Type Typer::Visitor::TypeNewConsString(Node* node) { return Type::String(); }
2717
2718Type Typer::Visitor::TypeFindOrderedHashMapEntry(Node* node) {
2719 return Type::Range(-1.0, FixedArray::kMaxLength, zone());
2720}
2721
2722Type Typer::Visitor::TypeFindOrderedHashMapEntryForInt32Key(Node* node) {
2723 return Type::Range(-1.0, FixedArray::kMaxLength, zone());
2724}
2725
2726Type Typer::Visitor::TypeFindOrderedHashSetEntry(Node* node) {
2727 return Type::Range(-1.0, FixedArray::kMaxLength, zone());
2728}
2729
2730Type Typer::Visitor::TypeRuntimeAbort(Node* node) { UNREACHABLE(); }
2731
2732Type Typer::Visitor::TypeAssertType(Node* node) { UNREACHABLE(); }
2733
2734Type Typer::Visitor::TypeVerifyType(Node* node) { UNREACHABLE(); }
2735
2736Type Typer::Visitor::TypeCheckTurboshaftTypeOf(Node* node) {
2737 return TypeOrNone(node->InputAt(0));
2738}
2739
2740// Heap constants.
2741
2743 return Type::Constant(typer_->broker(), value, zone());
2744}
2745
2746Type Typer::Visitor::TypeJSGetIterator(Node* node) { return Type::Any(); }
2747
2748} // namespace compiler
2749} // namespace internal
2750} // namespace v8
#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype)
#define Assert(condition)
static constexpr int kMaxLength
static const uint32_t kMaxLength
Definition string.h:511
static const base::uc32 kMaxCodePoint
Definition string.h:504
T * New(Args &&... args)
Definition zone.h:114
static constexpr int kJSCallClosureParamIndex
Definition linkage.h:504
static const int kOsrContextSpillSlotIndex
Definition linkage.h:508
const ZoneMap< int, InductionVariable * > & induction_variables()
static Type GetType(const Node *node)
static bool IsTyped(const Node *node)
static bool AllValueInputsAreTyped(Node *node)
static Node * GetValueInput(Node *node, int index)
static void SetType(Node *node, Type type)
static Node * GetControlInput(Node *node, int index=0)
constexpr IrOpcode::Value opcode() const
Definition node.h:52
const Operator * op() const
Definition node.h:50
Node * InputAt(int index) const
Definition node.h:70
NodeId id() const
Definition node.h:57
Type TypeTypeGuard(const Operator *sigma_op, Type input)
Type CheckBounds(Type index, Type length)
static Reduction Changed(Node *node)
void AddDecorator(GraphDecorator *decorator)
void RemoveDecorator(GraphDecorator *decorator)
static TypeCache const * Get()
static Type Union(Type type1, Type type2, Zone *zone)
bool Maybe(Type that) const
const HeapConstantType * AsHeapConstant() const
static Type Constant(JSHeapBroker *broker, Handle< i::Object > value, Zone *zone)
static Type Tuple(Type first, Type second, Type third, Zone *zone)
static Type Intersect(Type type1, Type type2, Zone *zone)
bool Is(Type that) const
static Type Range(double min, double max, Zone *zone)
Type TypeUnaryOp(Node *node, UnaryTyperFun)
static Type ToInteger(Type, Typer *)
static Type JSCallTyper(Type, Typer *)
static ComparisonOutcome JSCompareTyper(Type, Type, Typer *)
Type Weaken(Node *node, Type current_type, Type previous_type)
static Type ObjectIsNumber(Type, Typer *)
static Type SameValueTyper(Type, Type, Typer *)
static Type StringFromSingleCharCodeTyper(Type, Typer *)
static Type ToBigIntConvertNumber(Type, Typer *)
bool InductionVariablePhiTypeIsPrefixedPoint(InductionVariable *induction_var)
static ComparisonOutcome NumberCompareTyper(Type, Type, Typer *)
static Type ObjectIsBigInt(Type, Typer *)
static Type Decrement(Type, Typer *)
static Type ObjectIsNonCallable(Type, Typer *)
static Type ObjectIsCallable(Type, Typer *)
static Type NumberLessThanTyper(Type, Type, Typer *)
static Type ObjectIsString(Type, Typer *)
static Type StringFromSingleCodePointTyper(Type, Typer *)
Type TypeBinaryOp(Node *node, BinaryTyperFun)
static Type BinaryNumberOpTyper(Type lhs, Type rhs, Typer *t, BinaryTyperFun f)
static Type NumberLessThanOrEqualTyper(Type, Type, Typer *)
static Type ReferenceEqualTyper(Type, Type, Typer *)
static Type NumberIsMinusZero(Type, Typer *)
Reduction UpdateType(Node *node, Type current)
static Type ToNumeric(Type, Typer *)
static Type ToObject(Type, Typer *)
Visitor(Typer *typer, LoopVariableOptimizer *induction_vars)
static Type ObjectIsUndetectable(Type, Typer *)
const char * reducer_name() const override
static Type NumberEqualTyper(Type, Type, Typer *)
static Type BigIntCompareTyper(Type, Type, Typer *)
static Type BitwiseNot(Type, Typer *)
static Type ObjectIsMinusZero(Type, Typer *)
static Type ToBoolean(Type, Typer *)
static Type SameValueNumbersOnlyTyper(Type, Type, Typer *)
static Type ObjectIsSmi(Type, Typer *)
static Type ToLength(Type, Typer *)
static Type ObjectIsDetectableCallable(Type, Typer *)
static Type ToString(Type, Typer *)
static Type ObjectIsSymbol(Type, Typer *)
static ComparisonOutcome Invert(ComparisonOutcome, Typer *)
static Type ToPrimitive(Type, Typer *)
static Type Increment(Type, Typer *)
static Type ToBigInt(Type, Typer *)
Type(*)(Type, Type, Typer *t) BinaryTyperFun
static Type NumberIsNaN(Type, Typer *)
static Type ObjectIsArrayBufferView(Type, Typer *)
static Type FalsifyUndefined(ComparisonOutcome, Typer *)
Reduction Reduce(Node *node) override
static Type ToNumberConvertBigInt(Type, Typer *)
static Type ToNumber(Type, Typer *)
Type TypeConstant(Handle< Object > value)
static Type ObjectIsConstructor(Type, Typer *)
static Type ObjectIsNaN(Type, Typer *)
static Type ObjectIsReceiver(Type, Typer *)
JSHeapBroker * broker() const
OperationTyper * operation_typer()
TickCounter *const tick_counter_
Typer(JSHeapBroker *broker, Flags flags, TFGraph *graph, TickCounter *tick_counter)
#define V8_INFINITY
Definition globals.h:23
JSRegExp::Flags flags_
JSHeapBroker *const broker_
int start
LineAndColumn previous
#define TYPED_ARRAYS(V)
JSHeapBroker * broker
ZoneVector< RpoNumber > & result
int n
Definition mul-fft.cc:296
V8_INLINE const Operation & Get(const Graph &graph, OpIndex index)
Definition graph.h:1231
FastApiCallParameters const & FastApiCallParametersOf(const Operator *op)
size_t ProjectionIndexOf(const Operator *const op)
const CallRuntimeParameters & CallRuntimeParametersOf(const Operator *op)
Handle< HeapObject > HeapConstantOf(const Operator *op)
ZoneVector< Node * > NodeVector
Definition node.h:374
int ParameterIndexOf(const Operator *const op)
const FieldAccess & FieldAccessOf(const Operator *op)
const ElementAccess & ElementAccessOf(const Operator *op)
Type AllocateTypeOf(const Operator *op)
Handle< FeedbackCell > FeedbackCellOf(const Operator *op)
ExternalArrayType ExternalArrayTypeOf(const Operator *op)
T const & OpParameter(const Operator *op)
Definition operator.h:214
std::string ToString(const BytecodeLivenessState &liveness)
CreateArgumentsType const & CreateArgumentsTypeOf(const Operator *op)
const ExitMachineGraphParameters & ExitMachineGraphParametersOf(const Operator *op)
ContextAccess const & ContextAccessOf(Operator const *op)
int OsrValueIndexOf(Operator const *op)
ref_traits< T >::ref_type MakeRef(JSHeapBroker *broker, Tagged< T > object)
constexpr double kMaxSafeInteger
Definition globals.h:1985
bool IsClassConstructor(FunctionKind kind)
constexpr int kMaxUInt16
Definition globals.h:382
int ToNumber(Register reg)
void Terminate(Isolate *isolate)
Definition bigint.cc:1187
V8_EXPORT_PRIVATE FlagValues v8_flags
@ None
Definition v8-object.h:141
#define SIMPLIFIED_OTHER_OP_LIST(V)
Definition opcodes.h:449
#define MACHINE_SIMD256_OP_LIST(V)
Definition opcodes.h:1159
#define JS_CONTEXT_OP_LIST(V)
Definition opcodes.h:201
#define MACHINE_FLOAT32_UNOP_LIST(V)
Definition opcodes.h:687
#define SIMPLIFIED_BIGINT_UNOP_LIST(V)
Definition opcodes.h:434
#define JS_SIMPLE_UNOP_LIST(V)
Definition opcodes.h:152
#define SIMPLIFIED_BIGINT_BINOP_LIST(V)
Definition opcodes.h:367
#define SIMPLIFIED_CHECKED_OP_LIST(V)
Definition opcodes.h:290
#define JS_OTHER_OP_LIST(V)
Definition opcodes.h:226
#define SIMPLIFIED_NUMBER_UNOP_LIST(V)
Definition opcodes.h:397
#define MACHINE_FLOAT32_BINOP_LIST(V)
Definition opcodes.h:696
#define JS_OBJECT_OP_LIST(V)
Definition opcodes.h:183
#define SIMPLIFIED_SPECULATIVE_BIGINT_UNOP_LIST(V)
Definition opcodes.h:573
#define SIMPLIFIED_SPECULATIVE_NUMBER_UNOP_LIST(V)
Definition opcodes.h:439
#define SIMPLIFIED_COMPARE_BINOP_LIST(V)
Definition opcodes.h:328
#define COMMON_OP_LIST(V)
Definition opcodes.h:88
#define JS_SIMPLE_BINOP_LIST(V)
Definition opcodes.h:124
#define MACHINE_FLOAT64_BINOP_LIST(V)
Definition opcodes.h:733
#define MACHINE_UNOP_32_LIST(V)
Definition opcodes.h:616
#define MACHINE_ATOMIC_OP_LIST(V)
Definition opcodes.h:744
#define MACHINE_SIMD128_OP_LIST(V)
Definition opcodes.h:879
#define SIMPLIFIED_SPECULATIVE_BIGINT_BINOP_LIST(V)
Definition opcodes.h:561
#define SIMPLIFIED_SPECULATIVE_NUMBER_BINOP_LIST(V)
Definition opcodes.h:379
#define SIMPLIFIED_WASM_OP_LIST(V)
Definition opcodes.h:579
#define SIMPLIFIED_NUMBER_BINOP_LIST(V)
Definition opcodes.h:349
#define SIMPLIFIED_CHANGE_OP_LIST(V)
Definition opcodes.h:265
#define MACHINE_FLOAT64_UNOP_LIST(V)
Definition opcodes.h:704
#define DECLARE_METHOD(Name)
#define TYPER_SUPPORTED_MACHINE_BINOP_LIST(V)
#define FATAL(...)
Definition logging.h:47
#define CHECK(condition)
Definition logging.h:124
#define DCHECK_NE(v1, v2)
Definition logging.h:486
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_EQ(v1, v2)
Definition logging.h:485
#define arraysize(array)
Definition macros.h:67
#define IF_WASM(V,...)
Definition macros.h:472
#define DECLARE_BINARY_CASE(x,...)
#define DECLARE_UNARY_CASE(x,...)
#define BIGINT_COMPARISON_BINOP(Name)
#define DECLARE_IMPOSSIBLE_CASE(x,...)
#define DEFINE_METHOD(Name)
#define DECLARE_OTHER_CASE(x,...)
#define V8_UNLIKELY(condition)
Definition v8config.h:660
TFGraph * graph_
wasm::ValueType type