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
5 #include "src/compiler/typer.h"
6
7 #include <iomanip>
8
9 #include "src/base/flags.h"
10 #include "src/codegen/tick-counter.h"
11 #include "src/compiler/common-operator.h"
12 #include "src/compiler/graph-reducer.h"
13 #include "src/compiler/js-heap-broker.h"
14 #include "src/compiler/js-operator.h"
15 #include "src/compiler/linkage.h"
16 #include "src/compiler/loop-variable-optimizer.h"
17 #include "src/compiler/node-properties.h"
18 #include "src/compiler/node.h"
19 #include "src/compiler/operation-typer.h"
20 #include "src/compiler/simplified-operator.h"
21 #include "src/compiler/type-cache.h"
22 #include "src/init/bootstrapper.h"
23 #include "src/objects/objects-inl.h"
24
25 namespace v8 {
26 namespace internal {
27 namespace compiler {
28
29 class Typer::Decorator final : public GraphDecorator {
30 public:
Decorator(Typer * typer)31 explicit Decorator(Typer* typer) : typer_(typer) {}
32 void Decorate(Node* node) final;
33
34 private:
35 Typer* const typer_;
36 };
37
Typer(JSHeapBroker * broker,Flags flags,Graph * graph,TickCounter * tick_counter)38 Typer::Typer(JSHeapBroker* broker, Flags flags, Graph* graph,
39 TickCounter* tick_counter)
40 : flags_(flags),
41 graph_(graph),
42 decorator_(nullptr),
43 cache_(TypeCache::Get()),
44 broker_(broker),
45 operation_typer_(broker, zone()),
46 tick_counter_(tick_counter) {
47 singleton_false_ = operation_typer_.singleton_false();
48 singleton_true_ = operation_typer_.singleton_true();
49
50 decorator_ = zone()->New<Decorator>(this);
51 graph_->AddDecorator(decorator_);
52 }
53
~Typer()54 Typer::~Typer() {
55 graph_->RemoveDecorator(decorator_);
56 }
57
58
59 class Typer::Visitor : public Reducer {
60 public:
Visitor(Typer * typer,LoopVariableOptimizer * induction_vars)61 explicit Visitor(Typer* typer, LoopVariableOptimizer* induction_vars)
62 : typer_(typer),
63 induction_vars_(induction_vars),
64 weakened_nodes_(typer->zone()) {}
65
reducer_name() const66 const char* reducer_name() const override { return "Typer"; }
67
Reduce(Node * node)68 Reduction Reduce(Node* node) override {
69 if (node->op()->ValueOutputCount() == 0) return NoChange();
70 return UpdateType(node, TypeNode(node));
71 }
72
TypeNode(Node * node)73 Type TypeNode(Node* node) {
74 switch (node->opcode()) {
75 #define DECLARE_UNARY_CASE(x, ...) \
76 case IrOpcode::k##x: \
77 return Type##x(Operand(node, 0));
78 JS_SIMPLE_UNOP_LIST(DECLARE_UNARY_CASE)
79 SIMPLIFIED_NUMBER_UNOP_LIST(DECLARE_UNARY_CASE)
80 SIMPLIFIED_BIGINT_UNOP_LIST(DECLARE_UNARY_CASE)
81 SIMPLIFIED_SPECULATIVE_NUMBER_UNOP_LIST(DECLARE_UNARY_CASE)
82 SIMPLIFIED_SPECULATIVE_BIGINT_UNOP_LIST(DECLARE_UNARY_CASE)
83 #undef DECLARE_UNARY_CASE
84 #define DECLARE_BINARY_CASE(x, ...) \
85 case IrOpcode::k##x: \
86 return Type##x(Operand(node, 0), Operand(node, 1));
87 JS_SIMPLE_BINOP_LIST(DECLARE_BINARY_CASE)
88 SIMPLIFIED_NUMBER_BINOP_LIST(DECLARE_BINARY_CASE)
89 SIMPLIFIED_BIGINT_BINOP_LIST(DECLARE_BINARY_CASE)
90 SIMPLIFIED_SPECULATIVE_NUMBER_BINOP_LIST(DECLARE_BINARY_CASE)
91 SIMPLIFIED_SPECULATIVE_BIGINT_BINOP_LIST(DECLARE_BINARY_CASE)
92 #undef DECLARE_BINARY_CASE
93 #define DECLARE_OTHER_CASE(x, ...) \
94 case IrOpcode::k##x: \
95 return Type##x(node);
96 DECLARE_OTHER_CASE(Start)
97 DECLARE_OTHER_CASE(IfException)
98 COMMON_OP_LIST(DECLARE_OTHER_CASE)
99 SIMPLIFIED_COMPARE_BINOP_LIST(DECLARE_OTHER_CASE)
100 SIMPLIFIED_OTHER_OP_LIST(DECLARE_OTHER_CASE)
101 JS_OBJECT_OP_LIST(DECLARE_OTHER_CASE)
102 JS_CONTEXT_OP_LIST(DECLARE_OTHER_CASE)
103 JS_OTHER_OP_LIST(DECLARE_OTHER_CASE)
104 #undef DECLARE_OTHER_CASE
105 #define DECLARE_IMPOSSIBLE_CASE(x, ...) case IrOpcode::k##x:
106 DECLARE_IMPOSSIBLE_CASE(Loop)
107 DECLARE_IMPOSSIBLE_CASE(Branch)
108 DECLARE_IMPOSSIBLE_CASE(IfTrue)
109 DECLARE_IMPOSSIBLE_CASE(IfFalse)
110 DECLARE_IMPOSSIBLE_CASE(IfSuccess)
111 DECLARE_IMPOSSIBLE_CASE(Switch)
112 DECLARE_IMPOSSIBLE_CASE(IfValue)
113 DECLARE_IMPOSSIBLE_CASE(IfDefault)
114 DECLARE_IMPOSSIBLE_CASE(Merge)
115 DECLARE_IMPOSSIBLE_CASE(Deoptimize)
116 DECLARE_IMPOSSIBLE_CASE(DeoptimizeIf)
117 DECLARE_IMPOSSIBLE_CASE(DeoptimizeUnless)
118 DECLARE_IMPOSSIBLE_CASE(TrapIf)
119 DECLARE_IMPOSSIBLE_CASE(TrapUnless)
120 DECLARE_IMPOSSIBLE_CASE(Return)
121 DECLARE_IMPOSSIBLE_CASE(TailCall)
122 DECLARE_IMPOSSIBLE_CASE(Terminate)
123 DECLARE_IMPOSSIBLE_CASE(Throw)
124 DECLARE_IMPOSSIBLE_CASE(End)
125 SIMPLIFIED_CHANGE_OP_LIST(DECLARE_IMPOSSIBLE_CASE)
126 SIMPLIFIED_CHECKED_OP_LIST(DECLARE_IMPOSSIBLE_CASE)
127 MACHINE_SIMD_OP_LIST(DECLARE_IMPOSSIBLE_CASE)
128 MACHINE_OP_LIST(DECLARE_IMPOSSIBLE_CASE)
129 #undef DECLARE_IMPOSSIBLE_CASE
130 UNREACHABLE();
131 }
132 }
133
134 Type TypeConstant(Handle<Object> value);
135
136 bool InductionVariablePhiTypeIsPrefixedPoint(
137 InductionVariable* induction_var);
138
139 private:
140 Typer* typer_;
141 LoopVariableOptimizer* induction_vars_;
142 ZoneSet<NodeId> weakened_nodes_;
143
144 #define DECLARE_METHOD(x, ...) inline Type Type##x(Node* node);
145 DECLARE_METHOD(Start)
DECLARE_METHOD(IfException)146 DECLARE_METHOD(IfException)
147 COMMON_OP_LIST(DECLARE_METHOD)
148 SIMPLIFIED_COMPARE_BINOP_LIST(DECLARE_METHOD)
149 SIMPLIFIED_OTHER_OP_LIST(DECLARE_METHOD)
150 JS_OBJECT_OP_LIST(DECLARE_METHOD)
151 JS_CONTEXT_OP_LIST(DECLARE_METHOD)
152 JS_OTHER_OP_LIST(DECLARE_METHOD)
153 #undef DECLARE_METHOD
154 #define DECLARE_METHOD(x, ...) inline Type Type##x(Type input);
155 JS_SIMPLE_UNOP_LIST(DECLARE_METHOD)
156 #undef DECLARE_METHOD
157
158 Type TypeOrNone(Node* node) {
159 return NodeProperties::IsTyped(node) ? NodeProperties::GetType(node)
160 : Type::None();
161 }
162
Operand(Node * node,int i)163 Type Operand(Node* node, int i) {
164 Node* operand_node = NodeProperties::GetValueInput(node, i);
165 return TypeOrNone(operand_node);
166 }
167
168 Type Weaken(Node* node, Type current_type, Type previous_type);
169
zone()170 Zone* zone() { return typer_->zone(); }
graph()171 Graph* graph() { return typer_->graph(); }
172
SetWeakened(NodeId node_id)173 void SetWeakened(NodeId node_id) { weakened_nodes_.insert(node_id); }
IsWeakened(NodeId node_id)174 bool IsWeakened(NodeId node_id) {
175 return weakened_nodes_.find(node_id) != weakened_nodes_.end();
176 }
177
178 using UnaryTyperFun = Type (*)(Type, Typer* t);
179 using BinaryTyperFun = Type (*)(Type, Type, Typer* t);
180
181 inline Type TypeUnaryOp(Node* node, UnaryTyperFun);
182 inline Type TypeBinaryOp(Node* node, BinaryTyperFun);
183 inline Type TypeUnaryOp(Type input, UnaryTyperFun);
184 inline Type TypeBinaryOp(Type left, Type right, BinaryTyperFun);
185
186 static Type BinaryNumberOpTyper(Type lhs, Type rhs, Typer* t,
187 BinaryTyperFun f);
188
189 enum ComparisonOutcomeFlags {
190 kComparisonTrue = 1,
191 kComparisonFalse = 2,
192 kComparisonUndefined = 4
193 };
194 using ComparisonOutcome = base::Flags<ComparisonOutcomeFlags>;
195
196 static ComparisonOutcome Invert(ComparisonOutcome, Typer*);
197 static Type FalsifyUndefined(ComparisonOutcome, Typer*);
198
199 static Type BitwiseNot(Type, Typer*);
200 static Type Decrement(Type, Typer*);
201 static Type Increment(Type, Typer*);
202 static Type Negate(Type, Typer*);
203
204 static Type ToPrimitive(Type, Typer*);
205 static Type ToBoolean(Type, Typer*);
206 static Type ToInteger(Type, Typer*);
207 static Type ToLength(Type, Typer*);
208 static Type ToName(Type, Typer*);
209 static Type ToNumber(Type, Typer*);
210 static Type ToNumberConvertBigInt(Type, Typer*);
211 static Type ToNumeric(Type, Typer*);
212 static Type ToObject(Type, Typer*);
213 static Type ToString(Type, Typer*);
214 #define DECLARE_METHOD(Name) \
215 static Type Name(Type type, Typer* t) { \
216 return t->operation_typer_.Name(type); \
217 }
218 SIMPLIFIED_NUMBER_UNOP_LIST(DECLARE_METHOD)
219 SIMPLIFIED_BIGINT_UNOP_LIST(DECLARE_METHOD)
220 SIMPLIFIED_SPECULATIVE_NUMBER_UNOP_LIST(DECLARE_METHOD)
221 SIMPLIFIED_SPECULATIVE_BIGINT_UNOP_LIST(DECLARE_METHOD)
222 #undef DECLARE_METHOD
223 #define DECLARE_METHOD(Name) \
224 static Type Name(Type lhs, Type rhs, Typer* t) { \
225 return t->operation_typer_.Name(lhs, rhs); \
226 }
227 SIMPLIFIED_NUMBER_BINOP_LIST(DECLARE_METHOD)
228 SIMPLIFIED_BIGINT_BINOP_LIST(DECLARE_METHOD)
229 SIMPLIFIED_SPECULATIVE_NUMBER_BINOP_LIST(DECLARE_METHOD)
230 SIMPLIFIED_SPECULATIVE_BIGINT_BINOP_LIST(DECLARE_METHOD)
231 #undef DECLARE_METHOD
232 #define DECLARE_METHOD(Name, ...) \
233 inline Type Type##Name(Type left, Type right) { \
234 return TypeBinaryOp(left, right, Name##Typer); \
235 }
236 JS_SIMPLE_BINOP_LIST(DECLARE_METHOD)
237 #undef DECLARE_METHOD
238 #define DECLARE_METHOD(Name, ...) \
239 inline Type Type##Name(Type left, Type right) { \
240 return TypeBinaryOp(left, right, Name); \
241 }
242 SIMPLIFIED_NUMBER_BINOP_LIST(DECLARE_METHOD)
243 SIMPLIFIED_BIGINT_BINOP_LIST(DECLARE_METHOD)
244 SIMPLIFIED_SPECULATIVE_NUMBER_BINOP_LIST(DECLARE_METHOD)
245 SIMPLIFIED_SPECULATIVE_BIGINT_BINOP_LIST(DECLARE_METHOD)
246 #undef DECLARE_METHOD
247 #define DECLARE_METHOD(Name, ...) \
248 inline Type Type##Name(Type input) { return TypeUnaryOp(input, Name); }
249 SIMPLIFIED_NUMBER_UNOP_LIST(DECLARE_METHOD)
250 SIMPLIFIED_BIGINT_UNOP_LIST(DECLARE_METHOD)
251 SIMPLIFIED_SPECULATIVE_NUMBER_UNOP_LIST(DECLARE_METHOD)
252 SIMPLIFIED_SPECULATIVE_BIGINT_UNOP_LIST(DECLARE_METHOD)
253 #undef DECLARE_METHOD
254 static Type ObjectIsArrayBufferView(Type, Typer*);
255 static Type ObjectIsBigInt(Type, Typer*);
256 static Type ObjectIsCallable(Type, Typer*);
257 static Type ObjectIsConstructor(Type, Typer*);
258 static Type ObjectIsDetectableCallable(Type, Typer*);
259 static Type ObjectIsMinusZero(Type, Typer*);
260 static Type NumberIsMinusZero(Type, Typer*);
261 static Type ObjectIsNaN(Type, Typer*);
262 static Type NumberIsNaN(Type, Typer*);
263 static Type ObjectIsNonCallable(Type, Typer*);
264 static Type ObjectIsNumber(Type, Typer*);
265 static Type ObjectIsReceiver(Type, Typer*);
266 static Type ObjectIsSmi(Type, Typer*);
267 static Type ObjectIsString(Type, Typer*);
268 static Type ObjectIsSymbol(Type, Typer*);
269 static Type ObjectIsUndetectable(Type, Typer*);
270
271 static ComparisonOutcome JSCompareTyper(Type, Type, Typer*);
272 static ComparisonOutcome NumberCompareTyper(Type, Type, Typer*);
273
274 #define DECLARE_METHOD(x, ...) static Type x##Typer(Type, Type, Typer*);
275 JS_SIMPLE_BINOP_LIST(DECLARE_METHOD)
276 #undef DECLARE_METHOD
277
278 static Type JSCallTyper(Type, Typer*);
279
280 static Type NumberEqualTyper(Type, Type, Typer*);
281 static Type NumberLessThanTyper(Type, Type, Typer*);
282 static Type NumberLessThanOrEqualTyper(Type, Type, Typer*);
283 static Type ReferenceEqualTyper(Type, Type, Typer*);
284 static Type SameValueTyper(Type, Type, Typer*);
285 static Type SameValueNumbersOnlyTyper(Type, Type, Typer*);
286 static Type StringFromSingleCharCodeTyper(Type, Typer*);
287 static Type StringFromSingleCodePointTyper(Type, Typer*);
288
UpdateType(Node * node,Type current)289 Reduction UpdateType(Node* node, Type current) {
290 if (NodeProperties::IsTyped(node)) {
291 // Widen the type of a previously typed node.
292 Type previous = NodeProperties::GetType(node);
293 if (node->opcode() == IrOpcode::kPhi ||
294 node->opcode() == IrOpcode::kInductionVariablePhi) {
295 // Speed up termination in the presence of range types:
296 current = Weaken(node, current, previous);
297 }
298
299 if (V8_UNLIKELY(!previous.Is(current))) {
300 AllowHandleDereference allow;
301 std::ostringstream ostream;
302 node->Print(ostream);
303 FATAL("UpdateType error for node %s", ostream.str().c_str());
304 }
305
306 NodeProperties::SetType(node, current);
307 if (!current.Is(previous)) {
308 // If something changed, revisit all uses.
309 return Changed(node);
310 }
311 return NoChange();
312 } else {
313 // No previous type, simply update the type.
314 NodeProperties::SetType(node, current);
315 return Changed(node);
316 }
317 }
318 };
319
Run()320 void Typer::Run() { Run(NodeVector(zone()), nullptr); }
321
Run(const NodeVector & roots,LoopVariableOptimizer * induction_vars)322 void Typer::Run(const NodeVector& roots,
323 LoopVariableOptimizer* induction_vars) {
324 if (induction_vars != nullptr) {
325 induction_vars->ChangeToInductionVariablePhis();
326 }
327 Visitor visitor(this, induction_vars);
328 GraphReducer graph_reducer(zone(), graph(), tick_counter_, broker());
329 graph_reducer.AddReducer(&visitor);
330 for (Node* const root : roots) graph_reducer.ReduceNode(root);
331 graph_reducer.ReduceGraph();
332
333 if (induction_vars != nullptr) {
334 // Validate the types computed by TypeInductionVariablePhi.
335 for (auto entry : induction_vars->induction_variables()) {
336 InductionVariable* induction_var = entry.second;
337 if (induction_var->phi()->opcode() == IrOpcode::kInductionVariablePhi) {
338 CHECK(visitor.InductionVariablePhiTypeIsPrefixedPoint(induction_var));
339 }
340 }
341
342 induction_vars->ChangeToPhisAndInsertGuards();
343 }
344 }
345
Decorate(Node * node)346 void Typer::Decorator::Decorate(Node* node) {
347 if (node->op()->ValueOutputCount() > 0) {
348 // Only eagerly type-decorate nodes with known input types.
349 // Other cases will generally require a proper fixpoint iteration with Run.
350 bool is_typed = NodeProperties::IsTyped(node);
351 if (is_typed || NodeProperties::AllValueInputsAreTyped(node)) {
352 Visitor typing(typer_, nullptr);
353 Type type = typing.TypeNode(node);
354 if (is_typed) {
355 type = Type::Intersect(type, NodeProperties::GetType(node),
356 typer_->zone());
357 }
358 NodeProperties::SetType(node, type);
359 }
360 }
361 }
362
363
364 // -----------------------------------------------------------------------------
365
366 // Helper functions that lift a function f on types to a function on bounds,
367 // and uses that to type the given node. Note that f is never called with None
368 // as an argument.
369
TypeUnaryOp(Node * node,UnaryTyperFun f)370 Type Typer::Visitor::TypeUnaryOp(Node* node, UnaryTyperFun f) {
371 Type input = Operand(node, 0);
372 return TypeUnaryOp(input, f);
373 }
374
TypeUnaryOp(Type input,UnaryTyperFun f)375 Type Typer::Visitor::TypeUnaryOp(Type input, UnaryTyperFun f) {
376 return input.IsNone() ? Type::None() : f(input, typer_);
377 }
378
TypeBinaryOp(Node * node,BinaryTyperFun f)379 Type Typer::Visitor::TypeBinaryOp(Node* node, BinaryTyperFun f) {
380 Type left = Operand(node, 0);
381 Type right = Operand(node, 1);
382 return TypeBinaryOp(left, right, f);
383 }
384
TypeBinaryOp(Type left,Type right,BinaryTyperFun f)385 Type Typer::Visitor::TypeBinaryOp(Type left, Type right, BinaryTyperFun f) {
386 return left.IsNone() || right.IsNone() ? Type::None()
387 : f(left, right, typer_);
388 }
389
BinaryNumberOpTyper(Type lhs,Type rhs,Typer * t,BinaryTyperFun f)390 Type Typer::Visitor::BinaryNumberOpTyper(Type lhs, Type rhs, Typer* t,
391 BinaryTyperFun f) {
392 lhs = ToNumeric(lhs, t);
393 rhs = ToNumeric(rhs, t);
394 if (lhs.IsNone() || rhs.IsNone()) return Type::None();
395
396 bool lhs_is_number = lhs.Is(Type::Number());
397 bool rhs_is_number = rhs.Is(Type::Number());
398 if (lhs_is_number && rhs_is_number) {
399 return f(lhs, rhs, t);
400 }
401 // In order to maintain monotonicity, the following two conditions are
402 // intentionally asymmetric.
403 if (lhs_is_number) {
404 return Type::Number();
405 }
406 if (lhs.Is(Type::BigInt())) {
407 return Type::BigInt();
408 }
409 return Type::Numeric();
410 }
411
Invert(ComparisonOutcome outcome,Typer * t)412 Typer::Visitor::ComparisonOutcome Typer::Visitor::Invert(
413 ComparisonOutcome outcome, Typer* t) {
414 ComparisonOutcome result(0);
415 if ((outcome & kComparisonUndefined) != 0) result |= kComparisonUndefined;
416 if ((outcome & kComparisonTrue) != 0) result |= kComparisonFalse;
417 if ((outcome & kComparisonFalse) != 0) result |= kComparisonTrue;
418 return result;
419 }
420
FalsifyUndefined(ComparisonOutcome outcome,Typer * t)421 Type Typer::Visitor::FalsifyUndefined(ComparisonOutcome outcome, Typer* t) {
422 if (outcome == 0) return Type::None();
423 if ((outcome & kComparisonFalse) != 0 ||
424 (outcome & kComparisonUndefined) != 0) {
425 return (outcome & kComparisonTrue) != 0 ? Type::Boolean()
426 : t->singleton_false_;
427 }
428 DCHECK_NE(0, outcome & kComparisonTrue);
429 return t->singleton_true_;
430 }
431
BitwiseNot(Type type,Typer * t)432 Type Typer::Visitor::BitwiseNot(Type type, Typer* t) {
433 type = ToNumeric(type, t);
434 if (type.Is(Type::Number())) {
435 return NumberBitwiseXor(type, t->cache_->kSingletonMinusOne, t);
436 }
437 return Type::Numeric();
438 }
439
Decrement(Type type,Typer * t)440 Type Typer::Visitor::Decrement(Type type, Typer* t) {
441 type = ToNumeric(type, t);
442 if (type.Is(Type::Number())) {
443 return NumberSubtract(type, t->cache_->kSingletonOne, t);
444 }
445 return Type::Numeric();
446 }
447
Increment(Type type,Typer * t)448 Type Typer::Visitor::Increment(Type type, Typer* t) {
449 type = ToNumeric(type, t);
450 if (type.Is(Type::Number())) {
451 return NumberAdd(type, t->cache_->kSingletonOne, t);
452 }
453 return Type::Numeric();
454 }
455
Negate(Type type,Typer * t)456 Type Typer::Visitor::Negate(Type type, Typer* t) {
457 type = ToNumeric(type, t);
458 if (type.Is(Type::Number())) {
459 return NumberMultiply(type, t->cache_->kSingletonMinusOne, t);
460 }
461 return Type::Numeric();
462 }
463
464 // Type conversion.
465
ToPrimitive(Type type,Typer * t)466 Type Typer::Visitor::ToPrimitive(Type type, Typer* t) {
467 if (type.Is(Type::Primitive()) && !type.Maybe(Type::Receiver())) {
468 return type;
469 }
470 return Type::Primitive();
471 }
472
ToBoolean(Type type,Typer * t)473 Type Typer::Visitor::ToBoolean(Type type, Typer* t) {
474 return t->operation_typer()->ToBoolean(type);
475 }
476
477
478 // static
ToInteger(Type type,Typer * t)479 Type Typer::Visitor::ToInteger(Type type, Typer* t) {
480 // ES6 section 7.1.4 ToInteger ( argument )
481 type = ToNumber(type, t);
482 if (type.Is(t->cache_->kInteger)) return type;
483 if (type.Is(t->cache_->kIntegerOrMinusZeroOrNaN)) {
484 return Type::Union(Type::Intersect(type, t->cache_->kInteger, t->zone()),
485 t->cache_->kSingletonZero, t->zone());
486 }
487 return t->cache_->kInteger;
488 }
489
490
491 // static
ToLength(Type type,Typer * t)492 Type Typer::Visitor::ToLength(Type type, Typer* t) {
493 // ES6 section 7.1.15 ToLength ( argument )
494 type = ToInteger(type, t);
495 if (type.IsNone()) return type;
496 double min = type.Min();
497 double max = type.Max();
498 if (max <= 0.0) {
499 return Type::Constant(0, t->zone());
500 }
501 if (min >= kMaxSafeInteger) {
502 return Type::Constant(kMaxSafeInteger, t->zone());
503 }
504 if (min <= 0.0) min = 0.0;
505 if (max >= kMaxSafeInteger) max = kMaxSafeInteger;
506 return Type::Range(min, max, t->zone());
507 }
508
509
510 // static
ToName(Type type,Typer * t)511 Type Typer::Visitor::ToName(Type type, Typer* t) {
512 // ES6 section 7.1.14 ToPropertyKey ( argument )
513 type = ToPrimitive(type, t);
514 if (type.Is(Type::Name())) return type;
515 if (type.Maybe(Type::Symbol())) return Type::Name();
516 return ToString(type, t);
517 }
518
519
520 // static
ToNumber(Type type,Typer * t)521 Type Typer::Visitor::ToNumber(Type type, Typer* t) {
522 return t->operation_typer_.ToNumber(type);
523 }
524
525 // static
ToNumberConvertBigInt(Type type,Typer * t)526 Type Typer::Visitor::ToNumberConvertBigInt(Type type, Typer* t) {
527 return t->operation_typer_.ToNumberConvertBigInt(type);
528 }
529
530 // static
ToNumeric(Type type,Typer * t)531 Type Typer::Visitor::ToNumeric(Type type, Typer* t) {
532 return t->operation_typer_.ToNumeric(type);
533 }
534
535 // static
ToObject(Type type,Typer * t)536 Type Typer::Visitor::ToObject(Type type, Typer* t) {
537 // ES6 section 7.1.13 ToObject ( argument )
538 if (type.Is(Type::Receiver())) return type;
539 if (type.Is(Type::Primitive())) return Type::OtherObject();
540 if (!type.Maybe(Type::OtherUndetectable())) {
541 return Type::DetectableReceiver();
542 }
543 return Type::Receiver();
544 }
545
546
547 // static
ToString(Type type,Typer * t)548 Type Typer::Visitor::ToString(Type type, Typer* t) {
549 // ES6 section 7.1.12 ToString ( argument )
550 type = ToPrimitive(type, t);
551 if (type.Is(Type::String())) return type;
552 return Type::String();
553 }
554
555 // Type checks.
556
ObjectIsArrayBufferView(Type type,Typer * t)557 Type Typer::Visitor::ObjectIsArrayBufferView(Type type, Typer* t) {
558 // TODO(turbofan): Introduce a Type::ArrayBufferView?
559 CHECK(!type.IsNone());
560 if (!type.Maybe(Type::OtherObject())) return t->singleton_false_;
561 return Type::Boolean();
562 }
563
ObjectIsBigInt(Type type,Typer * t)564 Type Typer::Visitor::ObjectIsBigInt(Type type, Typer* t) {
565 CHECK(!type.IsNone());
566 if (type.Is(Type::BigInt())) return t->singleton_true_;
567 if (!type.Maybe(Type::BigInt())) return t->singleton_false_;
568 return Type::Boolean();
569 }
570
ObjectIsCallable(Type type,Typer * t)571 Type Typer::Visitor::ObjectIsCallable(Type type, Typer* t) {
572 CHECK(!type.IsNone());
573 if (type.Is(Type::Callable())) return t->singleton_true_;
574 if (!type.Maybe(Type::Callable())) return t->singleton_false_;
575 return Type::Boolean();
576 }
577
ObjectIsConstructor(Type type,Typer * t)578 Type Typer::Visitor::ObjectIsConstructor(Type type, Typer* t) {
579 // TODO(turbofan): Introduce a Type::Constructor?
580 CHECK(!type.IsNone());
581 if (type.IsHeapConstant() &&
582 type.AsHeapConstant()->Ref().map().is_constructor()) {
583 return t->singleton_true_;
584 }
585 if (!type.Maybe(Type::Callable())) return t->singleton_false_;
586 return Type::Boolean();
587 }
588
ObjectIsDetectableCallable(Type type,Typer * t)589 Type Typer::Visitor::ObjectIsDetectableCallable(Type type, Typer* t) {
590 CHECK(!type.IsNone());
591 if (type.Is(Type::DetectableCallable())) return t->singleton_true_;
592 if (!type.Maybe(Type::DetectableCallable())) return t->singleton_false_;
593 return Type::Boolean();
594 }
595
ObjectIsMinusZero(Type type,Typer * t)596 Type Typer::Visitor::ObjectIsMinusZero(Type type, Typer* t) {
597 CHECK(!type.IsNone());
598 if (type.Is(Type::MinusZero())) return t->singleton_true_;
599 if (!type.Maybe(Type::MinusZero())) return t->singleton_false_;
600 return Type::Boolean();
601 }
602
NumberIsMinusZero(Type type,Typer * t)603 Type Typer::Visitor::NumberIsMinusZero(Type type, Typer* t) {
604 CHECK(!type.IsNone());
605 if (type.Is(Type::MinusZero())) return t->singleton_true_;
606 if (!type.Maybe(Type::MinusZero())) return t->singleton_false_;
607 return Type::Boolean();
608 }
609
ObjectIsNaN(Type type,Typer * t)610 Type Typer::Visitor::ObjectIsNaN(Type type, Typer* t) {
611 CHECK(!type.IsNone());
612 if (type.Is(Type::NaN())) return t->singleton_true_;
613 if (!type.Maybe(Type::NaN())) return t->singleton_false_;
614 return Type::Boolean();
615 }
616
NumberIsNaN(Type type,Typer * t)617 Type Typer::Visitor::NumberIsNaN(Type type, Typer* t) {
618 CHECK(!type.IsNone());
619 if (type.Is(Type::NaN())) return t->singleton_true_;
620 if (!type.Maybe(Type::NaN())) return t->singleton_false_;
621 return Type::Boolean();
622 }
623
ObjectIsNonCallable(Type type,Typer * t)624 Type Typer::Visitor::ObjectIsNonCallable(Type type, Typer* t) {
625 CHECK(!type.IsNone());
626 if (type.Is(Type::NonCallable())) return t->singleton_true_;
627 if (!type.Maybe(Type::NonCallable())) return t->singleton_false_;
628 return Type::Boolean();
629 }
630
ObjectIsNumber(Type type,Typer * t)631 Type Typer::Visitor::ObjectIsNumber(Type type, Typer* t) {
632 CHECK(!type.IsNone());
633 if (type.Is(Type::Number())) return t->singleton_true_;
634 if (!type.Maybe(Type::Number())) return t->singleton_false_;
635 return Type::Boolean();
636 }
637
ObjectIsReceiver(Type type,Typer * t)638 Type Typer::Visitor::ObjectIsReceiver(Type type, Typer* t) {
639 CHECK(!type.IsNone());
640 if (type.Is(Type::Receiver())) return t->singleton_true_;
641 if (!type.Maybe(Type::Receiver())) return t->singleton_false_;
642 return Type::Boolean();
643 }
644
ObjectIsSmi(Type type,Typer * t)645 Type Typer::Visitor::ObjectIsSmi(Type type, Typer* t) {
646 if (!type.Maybe(Type::SignedSmall())) return t->singleton_false_;
647 return Type::Boolean();
648 }
649
ObjectIsString(Type type,Typer * t)650 Type Typer::Visitor::ObjectIsString(Type type, Typer* t) {
651 CHECK(!type.IsNone());
652 if (type.Is(Type::String())) return t->singleton_true_;
653 if (!type.Maybe(Type::String())) return t->singleton_false_;
654 return Type::Boolean();
655 }
656
ObjectIsSymbol(Type type,Typer * t)657 Type Typer::Visitor::ObjectIsSymbol(Type type, Typer* t) {
658 CHECK(!type.IsNone());
659 if (type.Is(Type::Symbol())) return t->singleton_true_;
660 if (!type.Maybe(Type::Symbol())) return t->singleton_false_;
661 return Type::Boolean();
662 }
663
ObjectIsUndetectable(Type type,Typer * t)664 Type Typer::Visitor::ObjectIsUndetectable(Type type, Typer* t) {
665 CHECK(!type.IsNone());
666 if (type.Is(Type::Undetectable())) return t->singleton_true_;
667 if (!type.Maybe(Type::Undetectable())) return t->singleton_false_;
668 return Type::Boolean();
669 }
670
671
672 // -----------------------------------------------------------------------------
673
674
675 // Control operators.
676
TypeStart(Node * node)677 Type Typer::Visitor::TypeStart(Node* node) { return Type::Internal(); }
678
TypeIfException(Node * node)679 Type Typer::Visitor::TypeIfException(Node* node) { return Type::NonInternal(); }
680
681 // Common operators.
682
TypeParameter(Node * node)683 Type Typer::Visitor::TypeParameter(Node* node) {
684 StartNode start{node->InputAt(0)};
685 int const index = ParameterIndexOf(node->op());
686 if (index == Linkage::kJSCallClosureParamIndex) {
687 return Type::Function();
688 } else if (index == 0) {
689 if (typer_->flags() & Typer::kThisIsReceiver) {
690 return Type::Receiver();
691 } else {
692 // Parameter[this] can be the_hole for derived class constructors.
693 return Type::Union(Type::Hole(), Type::NonInternal(), typer_->zone());
694 }
695 } else if (index == start.NewTargetParameterIndex()) {
696 if (typer_->flags() & Typer::kNewTargetIsReceiver) {
697 return Type::Receiver();
698 } else {
699 return Type::Union(Type::Receiver(), Type::Undefined(), typer_->zone());
700 }
701 } else if (index == start.ArgCountParameterIndex()) {
702 return Type::Range(0.0, FixedArray::kMaxLength, typer_->zone());
703 } else if (index == start.ContextParameterIndex()) {
704 return Type::OtherInternal();
705 }
706 return Type::NonInternal();
707 }
708
TypeOsrValue(Node * node)709 Type Typer::Visitor::TypeOsrValue(Node* node) {
710 if (OsrValueIndexOf(node->op()) == Linkage::kOsrContextSpillSlotIndex) {
711 return Type::OtherInternal();
712 } else {
713 return Type::Any();
714 }
715 }
716
TypeRetain(Node * node)717 Type Typer::Visitor::TypeRetain(Node* node) { UNREACHABLE(); }
718
TypeInt32Constant(Node * node)719 Type Typer::Visitor::TypeInt32Constant(Node* node) { UNREACHABLE(); }
720
TypeInt64Constant(Node * node)721 Type Typer::Visitor::TypeInt64Constant(Node* node) { UNREACHABLE(); }
722
TypeTaggedIndexConstant(Node * node)723 Type Typer::Visitor::TypeTaggedIndexConstant(Node* node) { UNREACHABLE(); }
724
TypeRelocatableInt32Constant(Node * node)725 Type Typer::Visitor::TypeRelocatableInt32Constant(Node* node) { UNREACHABLE(); }
726
TypeRelocatableInt64Constant(Node * node)727 Type Typer::Visitor::TypeRelocatableInt64Constant(Node* node) { UNREACHABLE(); }
728
TypeFloat32Constant(Node * node)729 Type Typer::Visitor::TypeFloat32Constant(Node* node) { UNREACHABLE(); }
730
TypeFloat64Constant(Node * node)731 Type Typer::Visitor::TypeFloat64Constant(Node* node) { UNREACHABLE(); }
732
TypeNumberConstant(Node * node)733 Type Typer::Visitor::TypeNumberConstant(Node* node) {
734 double number = OpParameter<double>(node->op());
735 return Type::Constant(number, zone());
736 }
737
TypeHeapConstant(Node * node)738 Type Typer::Visitor::TypeHeapConstant(Node* node) {
739 return TypeConstant(HeapConstantOf(node->op()));
740 }
741
TypeCompressedHeapConstant(Node * node)742 Type Typer::Visitor::TypeCompressedHeapConstant(Node* node) { UNREACHABLE(); }
743
TypeExternalConstant(Node * node)744 Type Typer::Visitor::TypeExternalConstant(Node* node) {
745 return Type::ExternalPointer();
746 }
747
TypePointerConstant(Node * node)748 Type Typer::Visitor::TypePointerConstant(Node* node) {
749 return Type::ExternalPointer();
750 }
751
TypeSelect(Node * node)752 Type Typer::Visitor::TypeSelect(Node* node) {
753 return Type::Union(Operand(node, 1), Operand(node, 2), zone());
754 }
755
TypePhi(Node * node)756 Type Typer::Visitor::TypePhi(Node* node) {
757 int arity = node->op()->ValueInputCount();
758 Type type = Operand(node, 0);
759 for (int i = 1; i < arity; ++i) {
760 type = Type::Union(type, Operand(node, i), zone());
761 }
762 return type;
763 }
764
TypeInductionVariablePhi(Node * node)765 Type Typer::Visitor::TypeInductionVariablePhi(Node* node) {
766 int arity = NodeProperties::GetControlInput(node)->op()->ControlInputCount();
767 DCHECK_EQ(IrOpcode::kLoop, NodeProperties::GetControlInput(node)->opcode());
768 DCHECK_EQ(2, NodeProperties::GetControlInput(node)->InputCount());
769
770 Type initial_type = Operand(node, 0);
771 Type increment_type = Operand(node, 2);
772
773 // Fallback to normal phi typing in a variety of cases:
774 // - when the induction variable is not initially of type Integer, because we
775 // want to work with ranges in the algorithm below.
776 // - when the increment is zero, because in that case normal phi typing will
777 // generally yield a more precise type.
778 // - when the induction variable can become NaN (through addition/subtraction
779 // of opposing infinities), because the code below can't handle that case.
780 if (initial_type.IsNone() ||
781 increment_type.Is(typer_->cache_->kSingletonZero) ||
782 !initial_type.Is(typer_->cache_->kInteger) ||
783 !increment_type.Is(typer_->cache_->kInteger) ||
784 increment_type.Min() == -V8_INFINITY ||
785 increment_type.Max() == +V8_INFINITY) {
786 // Unfortunately, without baking in the previous type, monotonicity might be
787 // violated because we might not yet have retyped the incrementing operation
788 // even though the increment's type might been already reflected in the
789 // induction variable phi.
790 Type type = NodeProperties::IsTyped(node) ? NodeProperties::GetType(node)
791 : Type::None();
792 for (int i = 0; i < arity; ++i) {
793 type = Type::Union(type, Operand(node, i), zone());
794 }
795 return type;
796 }
797
798 auto res = induction_vars_->induction_variables().find(node->id());
799 DCHECK_NE(res, induction_vars_->induction_variables().end());
800 InductionVariable* induction_var = res->second;
801 InductionVariable::ArithmeticType arithmetic_type = induction_var->Type();
802
803 double min = -V8_INFINITY;
804 double max = V8_INFINITY;
805
806 double increment_min;
807 double increment_max;
808 if (arithmetic_type == InductionVariable::ArithmeticType::kAddition) {
809 increment_min = increment_type.Min();
810 increment_max = increment_type.Max();
811 } else {
812 DCHECK_EQ(arithmetic_type, InductionVariable::ArithmeticType::kSubtraction);
813 increment_min = -increment_type.Max();
814 increment_max = -increment_type.Min();
815 }
816
817 if (increment_min >= 0) {
818 // Increasing sequence.
819 min = initial_type.Min();
820 for (auto bound : induction_var->upper_bounds()) {
821 Type bound_type = TypeOrNone(bound.bound);
822 // If the type is not an integer, just skip the bound.
823 if (!bound_type.Is(typer_->cache_->kInteger)) continue;
824 // If the type is not inhabited, then we can take the initial value.
825 if (bound_type.IsNone()) {
826 max = initial_type.Max();
827 break;
828 }
829 double bound_max = bound_type.Max();
830 if (bound.kind == InductionVariable::kStrict) {
831 bound_max -= 1;
832 }
833 max = std::min(max, bound_max + increment_max);
834 }
835 // The upper bound must be at least the initial value's upper bound.
836 max = std::max(max, initial_type.Max());
837 } else if (increment_max <= 0) {
838 // Decreasing sequence.
839 max = initial_type.Max();
840 for (auto bound : induction_var->lower_bounds()) {
841 Type bound_type = TypeOrNone(bound.bound);
842 // If the type is not an integer, just skip the bound.
843 if (!bound_type.Is(typer_->cache_->kInteger)) continue;
844 // If the type is not inhabited, then we can take the initial value.
845 if (bound_type.IsNone()) {
846 min = initial_type.Min();
847 break;
848 }
849 double bound_min = bound_type.Min();
850 if (bound.kind == InductionVariable::kStrict) {
851 bound_min += 1;
852 }
853 min = std::max(min, bound_min + increment_min);
854 }
855 // The lower bound must be at most the initial value's lower bound.
856 min = std::min(min, initial_type.Min());
857 } else {
858 // If the increment can be both positive and negative, the variable can go
859 // arbitrarily far. Use the maximal range in that case. Note that this may
860 // be less precise than what ordinary typing would produce.
861 min = -V8_INFINITY;
862 max = +V8_INFINITY;
863 }
864
865 if (FLAG_trace_turbo_loop) {
866 StdoutStream{} << std::setprecision(10) << "Loop ("
867 << NodeProperties::GetControlInput(node)->id()
868 << ") variable bounds in "
869 << (arithmetic_type ==
870 InductionVariable::ArithmeticType::kAddition
871 ? "addition"
872 : "subtraction")
873 << " for phi " << node->id() << ": (" << min << ", " << max
874 << ")\n";
875 }
876
877 return Type::Range(min, max, typer_->zone());
878 }
879
InductionVariablePhiTypeIsPrefixedPoint(InductionVariable * induction_var)880 bool Typer::Visitor::InductionVariablePhiTypeIsPrefixedPoint(
881 InductionVariable* induction_var) {
882 Node* node = induction_var->phi();
883 DCHECK_EQ(node->opcode(), IrOpcode::kInductionVariablePhi);
884 Node* arith = node->InputAt(1);
885 Type type = NodeProperties::GetType(node);
886 Type initial_type = Operand(node, 0);
887 Type arith_type = Operand(node, 1);
888 Type increment_type = Operand(node, 2);
889
890 // Intersect {type} with useful bounds.
891 for (auto bound : induction_var->upper_bounds()) {
892 Type bound_type = TypeOrNone(bound.bound);
893 if (!bound_type.Is(typer_->cache_->kInteger)) continue;
894 if (!bound_type.IsNone()) {
895 bound_type = Type::Range(
896 -V8_INFINITY,
897 bound_type.Max() - (bound.kind == InductionVariable::kStrict),
898 zone());
899 }
900 type = Type::Intersect(type, bound_type, typer_->zone());
901 }
902 for (auto bound : induction_var->lower_bounds()) {
903 Type bound_type = TypeOrNone(bound.bound);
904 if (!bound_type.Is(typer_->cache_->kInteger)) continue;
905 if (!bound_type.IsNone()) {
906 bound_type = Type::Range(
907 bound_type.Min() + (bound.kind == InductionVariable::kStrict),
908 +V8_INFINITY, typer_->zone());
909 }
910 type = Type::Intersect(type, bound_type, typer_->zone());
911 }
912
913 if (arith_type.IsNone()) {
914 type = Type::None();
915 } else {
916 // Apply ordinary typing to the "increment" operation.
917 // clang-format off
918 switch (arith->opcode()) {
919 #define CASE(x) \
920 case IrOpcode::k##x: \
921 type = Type##x(type, increment_type); \
922 break;
923 CASE(JSAdd)
924 CASE(JSSubtract)
925 CASE(NumberAdd)
926 CASE(NumberSubtract)
927 CASE(SpeculativeNumberAdd)
928 CASE(SpeculativeNumberSubtract)
929 CASE(SpeculativeSafeIntegerAdd)
930 CASE(SpeculativeSafeIntegerSubtract)
931 #undef CASE
932 default:
933 UNREACHABLE();
934 }
935 // clang-format on
936 }
937
938 type = Type::Union(initial_type, type, typer_->zone());
939
940 return type.Is(NodeProperties::GetType(node));
941 }
942
TypeEffectPhi(Node * node)943 Type Typer::Visitor::TypeEffectPhi(Node* node) { UNREACHABLE(); }
944
TypeLoopExit(Node * node)945 Type Typer::Visitor::TypeLoopExit(Node* node) { UNREACHABLE(); }
946
TypeLoopExitValue(Node * node)947 Type Typer::Visitor::TypeLoopExitValue(Node* node) { return Operand(node, 0); }
948
TypeLoopExitEffect(Node * node)949 Type Typer::Visitor::TypeLoopExitEffect(Node* node) { UNREACHABLE(); }
950
TypeEnsureWritableFastElements(Node * node)951 Type Typer::Visitor::TypeEnsureWritableFastElements(Node* node) {
952 return Operand(node, 1);
953 }
954
TypeMaybeGrowFastElements(Node * node)955 Type Typer::Visitor::TypeMaybeGrowFastElements(Node* node) {
956 return Operand(node, 1);
957 }
958
TypeTransitionElementsKind(Node * node)959 Type Typer::Visitor::TypeTransitionElementsKind(Node* node) { UNREACHABLE(); }
960
TypeCheckpoint(Node * node)961 Type Typer::Visitor::TypeCheckpoint(Node* node) { UNREACHABLE(); }
962
TypeBeginRegion(Node * node)963 Type Typer::Visitor::TypeBeginRegion(Node* node) { UNREACHABLE(); }
964
TypeFinishRegion(Node * node)965 Type Typer::Visitor::TypeFinishRegion(Node* node) { return Operand(node, 0); }
966
TypeFrameState(Node * node)967 Type Typer::Visitor::TypeFrameState(Node* node) {
968 // TODO(rossberg): Ideally FrameState wouldn't have a value output.
969 return Type::Internal();
970 }
971
TypeStateValues(Node * node)972 Type Typer::Visitor::TypeStateValues(Node* node) { return Type::Internal(); }
973
TypeTypedStateValues(Node * node)974 Type Typer::Visitor::TypeTypedStateValues(Node* node) {
975 return Type::Internal();
976 }
977
TypeObjectId(Node * node)978 Type Typer::Visitor::TypeObjectId(Node* node) { UNREACHABLE(); }
979
TypeArgumentsElementsState(Node * node)980 Type Typer::Visitor::TypeArgumentsElementsState(Node* node) {
981 return Type::Internal();
982 }
983
TypeArgumentsLengthState(Node * node)984 Type Typer::Visitor::TypeArgumentsLengthState(Node* node) {
985 return Type::Internal();
986 }
987
TypeObjectState(Node * node)988 Type Typer::Visitor::TypeObjectState(Node* node) { return Type::Internal(); }
989
TypeTypedObjectState(Node * node)990 Type Typer::Visitor::TypeTypedObjectState(Node* node) {
991 return Type::Internal();
992 }
993
TypeCall(Node * node)994 Type Typer::Visitor::TypeCall(Node* node) { return Type::Any(); }
995
TypeFastApiCall(Node * node)996 Type Typer::Visitor::TypeFastApiCall(Node* node) { return Type::Any(); }
997
998 #if V8_ENABLE_WEBASSEMBLY
TypeJSWasmCall(Node * node)999 Type Typer::Visitor::TypeJSWasmCall(Node* node) {
1000 const JSWasmCallParameters& op_params = JSWasmCallParametersOf(node->op());
1001 const wasm::FunctionSig* wasm_signature = op_params.signature();
1002 if (wasm_signature->return_count() > 0) {
1003 return JSWasmCallNode::TypeForWasmReturnType(wasm_signature->GetReturn());
1004 }
1005 return Type::Any();
1006 }
1007 #endif // V8_ENABLE_WEBASSEMBLY
1008
TypeProjection(Node * node)1009 Type Typer::Visitor::TypeProjection(Node* node) {
1010 Type const type = Operand(node, 0);
1011 if (type.Is(Type::None())) return Type::None();
1012 int const index = static_cast<int>(ProjectionIndexOf(node->op()));
1013 if (type.IsTuple() && index < type.AsTuple()->Arity()) {
1014 return type.AsTuple()->Element(index);
1015 }
1016 return Type::Any();
1017 }
1018
TypeMapGuard(Node * node)1019 Type Typer::Visitor::TypeMapGuard(Node* node) { UNREACHABLE(); }
1020
TypeTypeGuard(Node * node)1021 Type Typer::Visitor::TypeTypeGuard(Node* node) {
1022 Type const type = Operand(node, 0);
1023 return typer_->operation_typer()->TypeTypeGuard(node->op(), type);
1024 }
1025
TypeFoldConstant(Node * node)1026 Type Typer::Visitor::TypeFoldConstant(Node* node) { return Operand(node, 0); }
1027
TypeDead(Node * node)1028 Type Typer::Visitor::TypeDead(Node* node) { return Type::None(); }
TypeDeadValue(Node * node)1029 Type Typer::Visitor::TypeDeadValue(Node* node) { return Type::None(); }
TypeUnreachable(Node * node)1030 Type Typer::Visitor::TypeUnreachable(Node* node) { return Type::None(); }
1031
TypePlug(Node * node)1032 Type Typer::Visitor::TypePlug(Node* node) { UNREACHABLE(); }
TypeStaticAssert(Node * node)1033 Type Typer::Visitor::TypeStaticAssert(Node* node) { UNREACHABLE(); }
TypeSLVerifierHint(Node * node)1034 Type Typer::Visitor::TypeSLVerifierHint(Node* node) { UNREACHABLE(); }
1035
1036 // JS comparison operators.
1037
JSEqualTyper(Type lhs,Type rhs,Typer * t)1038 Type Typer::Visitor::JSEqualTyper(Type lhs, Type rhs, Typer* t) {
1039 if (lhs.IsNone() || rhs.IsNone()) return Type::None();
1040 if (lhs.Is(Type::NaN()) || rhs.Is(Type::NaN())) return t->singleton_false_;
1041 if (lhs.Is(Type::NullOrUndefined()) && rhs.Is(Type::NullOrUndefined())) {
1042 return t->singleton_true_;
1043 }
1044 if (lhs.Is(Type::Number()) && rhs.Is(Type::Number()) &&
1045 (lhs.Max() < rhs.Min() || lhs.Min() > rhs.Max())) {
1046 return t->singleton_false_;
1047 }
1048 if (lhs.IsSingleton() && rhs.Is(lhs)) {
1049 // Types are equal and are inhabited only by a single semantic value,
1050 // which is not nan due to the earlier check.
1051 DCHECK(lhs.Is(rhs));
1052 return t->singleton_true_;
1053 }
1054 return Type::Boolean();
1055 }
1056
JSStrictEqualTyper(Type lhs,Type rhs,Typer * t)1057 Type Typer::Visitor::JSStrictEqualTyper(Type lhs, Type rhs, Typer* t) {
1058 return t->operation_typer()->StrictEqual(lhs, rhs);
1059 }
1060
1061 // The EcmaScript specification defines the four relational comparison operators
1062 // (<, <=, >=, >) with the help of a single abstract one. It behaves like <
1063 // but returns undefined when the inputs cannot be compared.
1064 // We implement the typing analogously.
JSCompareTyper(Type lhs,Type rhs,Typer * t)1065 Typer::Visitor::ComparisonOutcome Typer::Visitor::JSCompareTyper(Type lhs,
1066 Type rhs,
1067 Typer* t) {
1068 lhs = ToPrimitive(lhs, t);
1069 rhs = ToPrimitive(rhs, t);
1070 if (lhs.Maybe(Type::String()) && rhs.Maybe(Type::String())) {
1071 return ComparisonOutcome(kComparisonTrue) |
1072 ComparisonOutcome(kComparisonFalse);
1073 }
1074 lhs = ToNumeric(lhs, t);
1075 rhs = ToNumeric(rhs, t);
1076 if (lhs.Is(Type::Number()) && rhs.Is(Type::Number())) {
1077 return NumberCompareTyper(lhs, rhs, t);
1078 }
1079 return ComparisonOutcome(kComparisonTrue) |
1080 ComparisonOutcome(kComparisonFalse) |
1081 ComparisonOutcome(kComparisonUndefined);
1082 }
1083
NumberCompareTyper(Type lhs,Type rhs,Typer * t)1084 Typer::Visitor::ComparisonOutcome Typer::Visitor::NumberCompareTyper(Type lhs,
1085 Type rhs,
1086 Typer* t) {
1087 DCHECK(lhs.Is(Type::Number()));
1088 DCHECK(rhs.Is(Type::Number()));
1089
1090 if (lhs.IsNone() || rhs.IsNone()) return {};
1091
1092 // Shortcut for NaNs.
1093 if (lhs.Is(Type::NaN()) || rhs.Is(Type::NaN())) return kComparisonUndefined;
1094
1095 ComparisonOutcome result;
1096 if (lhs.IsHeapConstant() && rhs.Is(lhs)) {
1097 // Types are equal and are inhabited only by a single semantic value.
1098 result = kComparisonFalse;
1099 } else if (lhs.Min() >= rhs.Max()) {
1100 result = kComparisonFalse;
1101 } else if (lhs.Max() < rhs.Min()) {
1102 result = kComparisonTrue;
1103 } else {
1104 return ComparisonOutcome(kComparisonTrue) |
1105 ComparisonOutcome(kComparisonFalse) |
1106 ComparisonOutcome(kComparisonUndefined);
1107 }
1108 // Add the undefined if we could see NaN.
1109 if (lhs.Maybe(Type::NaN()) || rhs.Maybe(Type::NaN())) {
1110 result |= kComparisonUndefined;
1111 }
1112 return result;
1113 }
1114
JSLessThanTyper(Type lhs,Type rhs,Typer * t)1115 Type Typer::Visitor::JSLessThanTyper(Type lhs, Type rhs, Typer* t) {
1116 return FalsifyUndefined(JSCompareTyper(lhs, rhs, t), t);
1117 }
1118
JSGreaterThanTyper(Type lhs,Type rhs,Typer * t)1119 Type Typer::Visitor::JSGreaterThanTyper(Type lhs, Type rhs, Typer* t) {
1120 return FalsifyUndefined(JSCompareTyper(rhs, lhs, t), t);
1121 }
1122
JSLessThanOrEqualTyper(Type lhs,Type rhs,Typer * t)1123 Type Typer::Visitor::JSLessThanOrEqualTyper(Type lhs, Type rhs, Typer* t) {
1124 return FalsifyUndefined(Invert(JSCompareTyper(rhs, lhs, t), t), t);
1125 }
1126
JSGreaterThanOrEqualTyper(Type lhs,Type rhs,Typer * t)1127 Type Typer::Visitor::JSGreaterThanOrEqualTyper(Type lhs, Type rhs, Typer* t) {
1128 return FalsifyUndefined(Invert(JSCompareTyper(lhs, rhs, t), t), t);
1129 }
1130
1131 // JS bitwise operators.
1132
JSBitwiseOrTyper(Type lhs,Type rhs,Typer * t)1133 Type Typer::Visitor::JSBitwiseOrTyper(Type lhs, Type rhs, Typer* t) {
1134 return BinaryNumberOpTyper(lhs, rhs, t, NumberBitwiseOr);
1135 }
1136
JSBitwiseAndTyper(Type lhs,Type rhs,Typer * t)1137 Type Typer::Visitor::JSBitwiseAndTyper(Type lhs, Type rhs, Typer* t) {
1138 return BinaryNumberOpTyper(lhs, rhs, t, NumberBitwiseAnd);
1139 }
1140
JSBitwiseXorTyper(Type lhs,Type rhs,Typer * t)1141 Type Typer::Visitor::JSBitwiseXorTyper(Type lhs, Type rhs, Typer* t) {
1142 return BinaryNumberOpTyper(lhs, rhs, t, NumberBitwiseXor);
1143 }
1144
JSShiftLeftTyper(Type lhs,Type rhs,Typer * t)1145 Type Typer::Visitor::JSShiftLeftTyper(Type lhs, Type rhs, Typer* t) {
1146 return BinaryNumberOpTyper(lhs, rhs, t, NumberShiftLeft);
1147 }
1148
JSShiftRightTyper(Type lhs,Type rhs,Typer * t)1149 Type Typer::Visitor::JSShiftRightTyper(Type lhs, Type rhs, Typer* t) {
1150 return BinaryNumberOpTyper(lhs, rhs, t, NumberShiftRight);
1151 }
1152
JSShiftRightLogicalTyper(Type lhs,Type rhs,Typer * t)1153 Type Typer::Visitor::JSShiftRightLogicalTyper(Type lhs, Type rhs, Typer* t) {
1154 return NumberShiftRightLogical(ToNumber(lhs, t), ToNumber(rhs, t), t);
1155 }
1156
1157
1158 // JS arithmetic operators.
1159
JSAddTyper(Type lhs,Type rhs,Typer * t)1160 Type Typer::Visitor::JSAddTyper(Type lhs, Type rhs, Typer* t) {
1161 lhs = ToPrimitive(lhs, t);
1162 rhs = ToPrimitive(rhs, t);
1163 if (lhs.Maybe(Type::String()) || rhs.Maybe(Type::String())) {
1164 if (lhs.Is(Type::String()) || rhs.Is(Type::String())) {
1165 return Type::String();
1166 } else {
1167 return Type::NumericOrString();
1168 }
1169 }
1170 // The addition must be numeric.
1171 return BinaryNumberOpTyper(lhs, rhs, t, NumberAdd);
1172 }
1173
JSSubtractTyper(Type lhs,Type rhs,Typer * t)1174 Type Typer::Visitor::JSSubtractTyper(Type lhs, Type rhs, Typer* t) {
1175 return BinaryNumberOpTyper(lhs, rhs, t, NumberSubtract);
1176 }
1177
JSMultiplyTyper(Type lhs,Type rhs,Typer * t)1178 Type Typer::Visitor::JSMultiplyTyper(Type lhs, Type rhs, Typer* t) {
1179 return BinaryNumberOpTyper(lhs, rhs, t, NumberMultiply);
1180 }
1181
JSDivideTyper(Type lhs,Type rhs,Typer * t)1182 Type Typer::Visitor::JSDivideTyper(Type lhs, Type rhs, Typer* t) {
1183 return BinaryNumberOpTyper(lhs, rhs, t, NumberDivide);
1184 }
1185
JSModulusTyper(Type lhs,Type rhs,Typer * t)1186 Type Typer::Visitor::JSModulusTyper(Type lhs, Type rhs, Typer* t) {
1187 return BinaryNumberOpTyper(lhs, rhs, t, NumberModulus);
1188 }
1189
JSExponentiateTyper(Type lhs,Type rhs,Typer * t)1190 Type Typer::Visitor::JSExponentiateTyper(Type lhs, Type rhs, Typer* t) {
1191 // TODO(neis): Refine using BinaryNumberOpTyper?
1192 return Type::Numeric();
1193 }
1194
1195 // JS unary operators.
1196
1197 #define DEFINE_METHOD(Name) \
1198 Type Typer::Visitor::TypeJS##Name(Type input) { \
1199 return TypeUnaryOp(input, Name); \
1200 }
1201 DEFINE_METHOD(BitwiseNot)
DEFINE_METHOD(Decrement)1202 DEFINE_METHOD(Decrement)
1203 DEFINE_METHOD(Increment)
1204 DEFINE_METHOD(Negate)
1205 DEFINE_METHOD(ToLength)
1206 DEFINE_METHOD(ToName)
1207 DEFINE_METHOD(ToNumber)
1208 DEFINE_METHOD(ToNumberConvertBigInt)
1209 DEFINE_METHOD(ToNumeric)
1210 DEFINE_METHOD(ToObject)
1211 DEFINE_METHOD(ToString)
1212 #undef DEFINE_METHOD
1213
1214 Type Typer::Visitor::TypeTypeOf(Node* node) {
1215 return Type::InternalizedString();
1216 }
1217
1218 // JS conversion operators.
1219
TypeToBoolean(Node * node)1220 Type Typer::Visitor::TypeToBoolean(Node* node) {
1221 return TypeUnaryOp(node, ToBoolean);
1222 }
1223
1224 // JS object operators.
1225
TypeJSCreate(Node * node)1226 Type Typer::Visitor::TypeJSCreate(Node* node) { return Type::Object(); }
1227
TypeJSCreateArguments(Node * node)1228 Type Typer::Visitor::TypeJSCreateArguments(Node* node) {
1229 switch (CreateArgumentsTypeOf(node->op())) {
1230 case CreateArgumentsType::kRestParameter:
1231 return Type::Array();
1232 case CreateArgumentsType::kMappedArguments:
1233 case CreateArgumentsType::kUnmappedArguments:
1234 return Type::OtherObject();
1235 }
1236 UNREACHABLE();
1237 }
1238
TypeJSCreateArray(Node * node)1239 Type Typer::Visitor::TypeJSCreateArray(Node* node) { return Type::Array(); }
1240
TypeJSCreateArrayIterator(Node * node)1241 Type Typer::Visitor::TypeJSCreateArrayIterator(Node* node) {
1242 return Type::OtherObject();
1243 }
1244
TypeJSCreateAsyncFunctionObject(Node * node)1245 Type Typer::Visitor::TypeJSCreateAsyncFunctionObject(Node* node) {
1246 return Type::OtherObject();
1247 }
1248
TypeJSCreateCollectionIterator(Node * node)1249 Type Typer::Visitor::TypeJSCreateCollectionIterator(Node* node) {
1250 return Type::OtherObject();
1251 }
1252
TypeJSCreateBoundFunction(Node * node)1253 Type Typer::Visitor::TypeJSCreateBoundFunction(Node* node) {
1254 return Type::BoundFunction();
1255 }
1256
TypeJSCreateGeneratorObject(Node * node)1257 Type Typer::Visitor::TypeJSCreateGeneratorObject(Node* node) {
1258 return Type::OtherObject();
1259 }
1260
TypeJSCreateClosure(Node * node)1261 Type Typer::Visitor::TypeJSCreateClosure(Node* node) {
1262 SharedFunctionInfoRef shared =
1263 JSCreateClosureNode{node}.Parameters().shared_info(typer_->broker());
1264 if (IsClassConstructor(shared.kind())) {
1265 return Type::ClassConstructor();
1266 } else {
1267 return Type::CallableFunction();
1268 }
1269 }
1270
TypeJSCreateIterResultObject(Node * node)1271 Type Typer::Visitor::TypeJSCreateIterResultObject(Node* node) {
1272 return Type::OtherObject();
1273 }
1274
TypeJSCreateStringIterator(Node * node)1275 Type Typer::Visitor::TypeJSCreateStringIterator(Node* node) {
1276 return Type::OtherObject();
1277 }
1278
TypeJSCreateKeyValueArray(Node * node)1279 Type Typer::Visitor::TypeJSCreateKeyValueArray(Node* node) {
1280 return Type::Array();
1281 }
1282
TypeJSCreateObject(Node * node)1283 Type Typer::Visitor::TypeJSCreateObject(Node* node) {
1284 return Type::OtherObject();
1285 }
1286
TypeJSCreatePromise(Node * node)1287 Type Typer::Visitor::TypeJSCreatePromise(Node* node) {
1288 return Type::OtherObject();
1289 }
1290
TypeJSCreateTypedArray(Node * node)1291 Type Typer::Visitor::TypeJSCreateTypedArray(Node* node) {
1292 return Type::OtherObject();
1293 }
1294
TypeJSCreateLiteralArray(Node * node)1295 Type Typer::Visitor::TypeJSCreateLiteralArray(Node* node) {
1296 return Type::Array();
1297 }
1298
TypeJSCreateEmptyLiteralArray(Node * node)1299 Type Typer::Visitor::TypeJSCreateEmptyLiteralArray(Node* node) {
1300 return Type::Array();
1301 }
1302
TypeJSCreateArrayFromIterable(Node * node)1303 Type Typer::Visitor::TypeJSCreateArrayFromIterable(Node* node) {
1304 return Type::Array();
1305 }
1306
TypeJSCreateLiteralObject(Node * node)1307 Type Typer::Visitor::TypeJSCreateLiteralObject(Node* node) {
1308 return Type::OtherObject();
1309 }
1310
TypeJSCreateEmptyLiteralObject(Node * node)1311 Type Typer::Visitor::TypeJSCreateEmptyLiteralObject(Node* node) {
1312 return Type::OtherObject();
1313 }
1314
TypeJSCloneObject(Node * node)1315 Type Typer::Visitor::TypeJSCloneObject(Node* node) {
1316 return Type::OtherObject();
1317 }
1318
TypeJSCreateLiteralRegExp(Node * node)1319 Type Typer::Visitor::TypeJSCreateLiteralRegExp(Node* node) {
1320 return Type::OtherObject();
1321 }
1322
TypeJSGetTemplateObject(Node * node)1323 Type Typer::Visitor::TypeJSGetTemplateObject(Node* node) {
1324 return Type::Array();
1325 }
1326
TypeJSLoadProperty(Node * node)1327 Type Typer::Visitor::TypeJSLoadProperty(Node* node) { return Type::Any(); }
1328
TypeJSLoadNamed(Node * node)1329 Type Typer::Visitor::TypeJSLoadNamed(Node* node) {
1330 #ifdef DEBUG
1331 // Loading of private methods is compiled to a named load of a BlockContext
1332 // via a private brand, which is an internal object. However, native context
1333 // specialization should always apply for those cases, so assert that the name
1334 // is not a private brand here. Otherwise Type::NonInternal() is wrong.
1335 JSLoadNamedNode n(node);
1336 NamedAccess const& p = n.Parameters();
1337 DCHECK(!p.name(typer_->broker()).object()->IsPrivateBrand());
1338 #endif
1339 return Type::NonInternal();
1340 }
1341
TypeJSLoadNamedFromSuper(Node * node)1342 Type Typer::Visitor::TypeJSLoadNamedFromSuper(Node* node) {
1343 return Type::NonInternal();
1344 }
1345
TypeJSLoadGlobal(Node * node)1346 Type Typer::Visitor::TypeJSLoadGlobal(Node* node) {
1347 return Type::NonInternal();
1348 }
1349
TypeJSParseInt(Type input)1350 Type Typer::Visitor::TypeJSParseInt(Type input) { return Type::Number(); }
1351
TypeJSRegExpTest(Node * node)1352 Type Typer::Visitor::TypeJSRegExpTest(Node* node) { return Type::Boolean(); }
1353
1354 // Returns a somewhat larger range if we previously assigned
1355 // a (smaller) range to this node. This is used to speed up
1356 // the fixpoint calculation in case there appears to be a loop
1357 // in the graph. In the current implementation, we are
1358 // increasing the limits to the closest power of two.
Weaken(Node * node,Type current_type,Type previous_type)1359 Type Typer::Visitor::Weaken(Node* node, Type current_type, Type previous_type) {
1360 static const double kWeakenMinLimits[] = {
1361 0.0, -1073741824.0, -2147483648.0, -4294967296.0, -8589934592.0,
1362 -17179869184.0, -34359738368.0, -68719476736.0, -137438953472.0,
1363 -274877906944.0, -549755813888.0, -1099511627776.0, -2199023255552.0,
1364 -4398046511104.0, -8796093022208.0, -17592186044416.0, -35184372088832.0,
1365 -70368744177664.0, -140737488355328.0, -281474976710656.0,
1366 -562949953421312.0};
1367 static const double kWeakenMaxLimits[] = {
1368 0.0, 1073741823.0, 2147483647.0, 4294967295.0, 8589934591.0,
1369 17179869183.0, 34359738367.0, 68719476735.0, 137438953471.0,
1370 274877906943.0, 549755813887.0, 1099511627775.0, 2199023255551.0,
1371 4398046511103.0, 8796093022207.0, 17592186044415.0, 35184372088831.0,
1372 70368744177663.0, 140737488355327.0, 281474976710655.0,
1373 562949953421311.0};
1374 STATIC_ASSERT(arraysize(kWeakenMinLimits) == arraysize(kWeakenMaxLimits));
1375
1376 // If the types have nothing to do with integers, return the types.
1377 Type const integer = typer_->cache_->kInteger;
1378 if (!previous_type.Maybe(integer)) {
1379 return current_type;
1380 }
1381 DCHECK(current_type.Maybe(integer));
1382
1383 Type current_integer = Type::Intersect(current_type, integer, zone());
1384 Type previous_integer = Type::Intersect(previous_type, integer, zone());
1385
1386 // Once we start weakening a node, we should always weaken.
1387 if (!IsWeakened(node->id())) {
1388 // Only weaken if there is range involved; we should converge quickly
1389 // for all other types (the exception is a union of many constants,
1390 // but we currently do not increase the number of constants in unions).
1391 Type previous = previous_integer.GetRange();
1392 Type current = current_integer.GetRange();
1393 if (current.IsInvalid() || previous.IsInvalid()) {
1394 return current_type;
1395 }
1396 // Range is involved => we are weakening.
1397 SetWeakened(node->id());
1398 }
1399
1400 double current_min = current_integer.Min();
1401 double new_min = current_min;
1402 // Find the closest lower entry in the list of allowed
1403 // minima (or negative infinity if there is no such entry).
1404 if (current_min != previous_integer.Min()) {
1405 new_min = -V8_INFINITY;
1406 for (double const min : kWeakenMinLimits) {
1407 if (min <= current_min) {
1408 new_min = min;
1409 break;
1410 }
1411 }
1412 }
1413
1414 double current_max = current_integer.Max();
1415 double new_max = current_max;
1416 // Find the closest greater entry in the list of allowed
1417 // maxima (or infinity if there is no such entry).
1418 if (current_max != previous_integer.Max()) {
1419 new_max = V8_INFINITY;
1420 for (double const max : kWeakenMaxLimits) {
1421 if (max >= current_max) {
1422 new_max = max;
1423 break;
1424 }
1425 }
1426 }
1427
1428 return Type::Union(current_type,
1429 Type::Range(new_min, new_max, typer_->zone()),
1430 typer_->zone());
1431 }
1432
TypeJSSetKeyedProperty(Node * node)1433 Type Typer::Visitor::TypeJSSetKeyedProperty(Node* node) { UNREACHABLE(); }
1434
TypeJSDefineKeyedOwnProperty(Node * node)1435 Type Typer::Visitor::TypeJSDefineKeyedOwnProperty(Node* node) { UNREACHABLE(); }
1436
TypeJSSetNamedProperty(Node * node)1437 Type Typer::Visitor::TypeJSSetNamedProperty(Node* node) { UNREACHABLE(); }
1438
TypeJSStoreGlobal(Node * node)1439 Type Typer::Visitor::TypeJSStoreGlobal(Node* node) { UNREACHABLE(); }
1440
TypeJSDefineNamedOwnProperty(Node * node)1441 Type Typer::Visitor::TypeJSDefineNamedOwnProperty(Node* node) { UNREACHABLE(); }
1442
TypeJSDefineKeyedOwnPropertyInLiteral(Node * node)1443 Type Typer::Visitor::TypeJSDefineKeyedOwnPropertyInLiteral(Node* node) {
1444 UNREACHABLE();
1445 }
1446
TypeJSStoreInArrayLiteral(Node * node)1447 Type Typer::Visitor::TypeJSStoreInArrayLiteral(Node* node) { UNREACHABLE(); }
1448
TypeJSDeleteProperty(Node * node)1449 Type Typer::Visitor::TypeJSDeleteProperty(Node* node) {
1450 return Type::Boolean();
1451 }
1452
TypeJSHasProperty(Node * node)1453 Type Typer::Visitor::TypeJSHasProperty(Node* node) { return Type::Boolean(); }
1454
1455 // JS instanceof operator.
1456
JSHasInPrototypeChainTyper(Type lhs,Type rhs,Typer * t)1457 Type Typer::Visitor::JSHasInPrototypeChainTyper(Type lhs, Type rhs, Typer* t) {
1458 return Type::Boolean();
1459 }
1460
JSInstanceOfTyper(Type lhs,Type rhs,Typer * t)1461 Type Typer::Visitor::JSInstanceOfTyper(Type lhs, Type rhs, Typer* t) {
1462 return Type::Boolean();
1463 }
1464
JSOrdinaryHasInstanceTyper(Type lhs,Type rhs,Typer * t)1465 Type Typer::Visitor::JSOrdinaryHasInstanceTyper(Type lhs, Type rhs, Typer* t) {
1466 return Type::Boolean();
1467 }
1468
TypeJSGetSuperConstructor(Node * node)1469 Type Typer::Visitor::TypeJSGetSuperConstructor(Node* node) {
1470 return Type::NonInternal();
1471 }
1472
1473 // JS context operators.
TypeJSHasContextExtension(Node * node)1474 Type Typer::Visitor::TypeJSHasContextExtension(Node* node) {
1475 return Type::Boolean();
1476 }
1477
TypeJSLoadContext(Node * node)1478 Type Typer::Visitor::TypeJSLoadContext(Node* node) {
1479 ContextAccess const& access = ContextAccessOf(node->op());
1480 switch (access.index()) {
1481 case Context::PREVIOUS_INDEX:
1482 case Context::SCOPE_INFO_INDEX:
1483 return Type::OtherInternal();
1484 default:
1485 return Type::Any();
1486 }
1487 }
1488
TypeJSStoreContext(Node * node)1489 Type Typer::Visitor::TypeJSStoreContext(Node* node) { UNREACHABLE(); }
1490
TypeJSCreateFunctionContext(Node * node)1491 Type Typer::Visitor::TypeJSCreateFunctionContext(Node* node) {
1492 return Type::OtherInternal();
1493 }
1494
TypeJSCreateCatchContext(Node * node)1495 Type Typer::Visitor::TypeJSCreateCatchContext(Node* node) {
1496 return Type::OtherInternal();
1497 }
1498
TypeJSCreateWithContext(Node * node)1499 Type Typer::Visitor::TypeJSCreateWithContext(Node* node) {
1500 return Type::OtherInternal();
1501 }
1502
TypeJSCreateBlockContext(Node * node)1503 Type Typer::Visitor::TypeJSCreateBlockContext(Node* node) {
1504 return Type::OtherInternal();
1505 }
1506
1507 // JS other operators.
1508
TypeJSConstructForwardVarargs(Node * node)1509 Type Typer::Visitor::TypeJSConstructForwardVarargs(Node* node) {
1510 return Type::Receiver();
1511 }
1512
TypeJSConstruct(Node * node)1513 Type Typer::Visitor::TypeJSConstruct(Node* node) { return Type::Receiver(); }
1514
TypeJSConstructWithArrayLike(Node * node)1515 Type Typer::Visitor::TypeJSConstructWithArrayLike(Node* node) {
1516 return Type::Receiver();
1517 }
1518
TypeJSConstructWithSpread(Node * node)1519 Type Typer::Visitor::TypeJSConstructWithSpread(Node* node) {
1520 return Type::Receiver();
1521 }
1522
TypeJSObjectIsArray(Node * node)1523 Type Typer::Visitor::TypeJSObjectIsArray(Node* node) { return Type::Boolean(); }
1524
TypeDateNow(Node * node)1525 Type Typer::Visitor::TypeDateNow(Node* node) { return Type::Number(); }
1526
JSCallTyper(Type fun,Typer * t)1527 Type Typer::Visitor::JSCallTyper(Type fun, Typer* t) {
1528 if (!fun.IsHeapConstant() || !fun.AsHeapConstant()->Ref().IsJSFunction()) {
1529 return Type::NonInternal();
1530 }
1531 JSFunctionRef function = fun.AsHeapConstant()->Ref().AsJSFunction();
1532 if (!function.shared().HasBuiltinId()) {
1533 return Type::NonInternal();
1534 }
1535 switch (function.shared().builtin_id()) {
1536 case Builtin::kMathRandom:
1537 return Type::PlainNumber();
1538 case Builtin::kMathFloor:
1539 case Builtin::kMathCeil:
1540 case Builtin::kMathRound:
1541 case Builtin::kMathTrunc:
1542 return t->cache_->kIntegerOrMinusZeroOrNaN;
1543 // Unary math functions.
1544 case Builtin::kMathAbs:
1545 case Builtin::kMathExp:
1546 return Type::Union(Type::PlainNumber(), Type::NaN(), t->zone());
1547 case Builtin::kMathAcos:
1548 case Builtin::kMathAcosh:
1549 case Builtin::kMathAsin:
1550 case Builtin::kMathAsinh:
1551 case Builtin::kMathAtan:
1552 case Builtin::kMathAtanh:
1553 case Builtin::kMathCbrt:
1554 case Builtin::kMathCos:
1555 case Builtin::kMathExpm1:
1556 case Builtin::kMathFround:
1557 case Builtin::kMathLog:
1558 case Builtin::kMathLog1p:
1559 case Builtin::kMathLog10:
1560 case Builtin::kMathLog2:
1561 case Builtin::kMathSin:
1562 case Builtin::kMathSqrt:
1563 case Builtin::kMathTan:
1564 return Type::Number();
1565 case Builtin::kMathSign:
1566 return t->cache_->kMinusOneToOneOrMinusZeroOrNaN;
1567 // Binary math functions.
1568 case Builtin::kMathAtan2:
1569 case Builtin::kMathPow:
1570 case Builtin::kMathMax:
1571 case Builtin::kMathMin:
1572 case Builtin::kMathHypot:
1573 return Type::Number();
1574 case Builtin::kMathImul:
1575 return Type::Signed32();
1576 case Builtin::kMathClz32:
1577 return t->cache_->kZeroToThirtyTwo;
1578 // Date functions.
1579 case Builtin::kDateNow:
1580 return t->cache_->kTimeValueType;
1581 case Builtin::kDatePrototypeGetDate:
1582 return t->cache_->kJSDateDayType;
1583 case Builtin::kDatePrototypeGetDay:
1584 return t->cache_->kJSDateWeekdayType;
1585 case Builtin::kDatePrototypeGetFullYear:
1586 return t->cache_->kJSDateYearType;
1587 case Builtin::kDatePrototypeGetHours:
1588 return t->cache_->kJSDateHourType;
1589 case Builtin::kDatePrototypeGetMilliseconds:
1590 return Type::Union(Type::Range(0.0, 999.0, t->zone()), Type::NaN(),
1591 t->zone());
1592 case Builtin::kDatePrototypeGetMinutes:
1593 return t->cache_->kJSDateMinuteType;
1594 case Builtin::kDatePrototypeGetMonth:
1595 return t->cache_->kJSDateMonthType;
1596 case Builtin::kDatePrototypeGetSeconds:
1597 return t->cache_->kJSDateSecondType;
1598 case Builtin::kDatePrototypeGetTime:
1599 return t->cache_->kJSDateValueType;
1600
1601 // Symbol functions.
1602 case Builtin::kSymbolConstructor:
1603 return Type::Symbol();
1604 case Builtin::kSymbolPrototypeToString:
1605 return Type::String();
1606 case Builtin::kSymbolPrototypeValueOf:
1607 return Type::Symbol();
1608
1609 // BigInt functions.
1610 case Builtin::kBigIntConstructor:
1611 return Type::BigInt();
1612
1613 // Number functions.
1614 case Builtin::kNumberConstructor:
1615 return Type::Number();
1616 case Builtin::kNumberIsFinite:
1617 case Builtin::kNumberIsInteger:
1618 case Builtin::kNumberIsNaN:
1619 case Builtin::kNumberIsSafeInteger:
1620 return Type::Boolean();
1621 case Builtin::kNumberParseFloat:
1622 return Type::Number();
1623 case Builtin::kNumberParseInt:
1624 return t->cache_->kIntegerOrMinusZeroOrNaN;
1625 case Builtin::kNumberToString:
1626 return Type::String();
1627
1628 // String functions.
1629 case Builtin::kStringConstructor:
1630 return Type::String();
1631 case Builtin::kStringPrototypeCharCodeAt:
1632 return Type::Union(Type::Range(0, kMaxUInt16, t->zone()), Type::NaN(),
1633 t->zone());
1634 case Builtin::kStringCharAt:
1635 return Type::String();
1636 case Builtin::kStringPrototypeCodePointAt:
1637 return Type::Union(Type::Range(0.0, String::kMaxCodePoint, t->zone()),
1638 Type::Undefined(), t->zone());
1639 case Builtin::kStringPrototypeConcat:
1640 case Builtin::kStringFromCharCode:
1641 case Builtin::kStringFromCodePoint:
1642 return Type::String();
1643 case Builtin::kStringPrototypeIndexOf:
1644 case Builtin::kStringPrototypeLastIndexOf:
1645 return Type::Range(-1.0, String::kMaxLength, t->zone());
1646 case Builtin::kStringPrototypeEndsWith:
1647 case Builtin::kStringPrototypeIncludes:
1648 return Type::Boolean();
1649 case Builtin::kStringRaw:
1650 case Builtin::kStringRepeat:
1651 case Builtin::kStringPrototypeSlice:
1652 return Type::String();
1653 case Builtin::kStringPrototypeStartsWith:
1654 return Type::Boolean();
1655 case Builtin::kStringPrototypeSubstr:
1656 case Builtin::kStringSubstring:
1657 case Builtin::kStringPrototypeToString:
1658 #ifdef V8_INTL_SUPPORT
1659 case Builtin::kStringPrototypeToLowerCaseIntl:
1660 case Builtin::kStringPrototypeToUpperCaseIntl:
1661 #else
1662 case Builtin::kStringPrototypeToLowerCase:
1663 case Builtin::kStringPrototypeToUpperCase:
1664 #endif
1665 case Builtin::kStringPrototypeTrim:
1666 case Builtin::kStringPrototypeTrimEnd:
1667 case Builtin::kStringPrototypeTrimStart:
1668 case Builtin::kStringPrototypeValueOf:
1669 return Type::String();
1670
1671 case Builtin::kStringPrototypeIterator:
1672 case Builtin::kStringIteratorPrototypeNext:
1673 return Type::OtherObject();
1674
1675 case Builtin::kArrayPrototypeEntries:
1676 case Builtin::kArrayPrototypeKeys:
1677 case Builtin::kArrayPrototypeValues:
1678 case Builtin::kTypedArrayPrototypeEntries:
1679 case Builtin::kTypedArrayPrototypeKeys:
1680 case Builtin::kTypedArrayPrototypeValues:
1681 case Builtin::kArrayIteratorPrototypeNext:
1682 case Builtin::kMapIteratorPrototypeNext:
1683 case Builtin::kSetIteratorPrototypeNext:
1684 return Type::OtherObject();
1685 case Builtin::kTypedArrayPrototypeToStringTag:
1686 return Type::Union(Type::InternalizedString(), Type::Undefined(),
1687 t->zone());
1688
1689 // Array functions.
1690 case Builtin::kArrayIsArray:
1691 return Type::Boolean();
1692 case Builtin::kArrayConcat:
1693 return Type::Receiver();
1694 case Builtin::kArrayEvery:
1695 return Type::Boolean();
1696 case Builtin::kArrayPrototypeFill:
1697 case Builtin::kArrayFilter:
1698 return Type::Receiver();
1699 case Builtin::kArrayPrototypeFindIndex:
1700 return Type::Range(-1, kMaxSafeInteger, t->zone());
1701 case Builtin::kArrayForEach:
1702 return Type::Undefined();
1703 case Builtin::kArrayIncludes:
1704 return Type::Boolean();
1705 case Builtin::kArrayIndexOf:
1706 return Type::Range(-1, kMaxSafeInteger, t->zone());
1707 case Builtin::kArrayPrototypeJoin:
1708 return Type::String();
1709 case Builtin::kArrayPrototypeLastIndexOf:
1710 return Type::Range(-1, kMaxSafeInteger, t->zone());
1711 case Builtin::kArrayMap:
1712 return Type::Receiver();
1713 case Builtin::kArrayPush:
1714 return t->cache_->kPositiveSafeInteger;
1715 case Builtin::kArrayPrototypeReverse:
1716 case Builtin::kArrayPrototypeSlice:
1717 return Type::Receiver();
1718 case Builtin::kArraySome:
1719 return Type::Boolean();
1720 case Builtin::kArrayPrototypeSplice:
1721 return Type::Receiver();
1722 case Builtin::kArrayUnshift:
1723 return t->cache_->kPositiveSafeInteger;
1724
1725 // ArrayBuffer functions.
1726 case Builtin::kArrayBufferIsView:
1727 return Type::Boolean();
1728
1729 // Object functions.
1730 case Builtin::kObjectAssign:
1731 return Type::Receiver();
1732 case Builtin::kObjectCreate:
1733 return Type::OtherObject();
1734 case Builtin::kObjectIs:
1735 case Builtin::kObjectHasOwn:
1736 case Builtin::kObjectPrototypeHasOwnProperty:
1737 case Builtin::kObjectPrototypeIsPrototypeOf:
1738 return Type::Boolean();
1739 case Builtin::kObjectToString:
1740 return Type::String();
1741
1742 case Builtin::kPromiseAll:
1743 return Type::Receiver();
1744 case Builtin::kPromisePrototypeThen:
1745 return Type::Receiver();
1746 case Builtin::kPromiseRace:
1747 return Type::Receiver();
1748 case Builtin::kPromiseReject:
1749 return Type::Receiver();
1750 case Builtin::kPromiseResolveTrampoline:
1751 return Type::Receiver();
1752
1753 // RegExp functions.
1754 case Builtin::kRegExpPrototypeCompile:
1755 return Type::OtherObject();
1756 case Builtin::kRegExpPrototypeExec:
1757 return Type::Union(Type::Array(), Type::Null(), t->zone());
1758 case Builtin::kRegExpPrototypeTest:
1759 return Type::Boolean();
1760 case Builtin::kRegExpPrototypeToString:
1761 return Type::String();
1762
1763 // Function functions.
1764 case Builtin::kFunctionPrototypeBind:
1765 return Type::BoundFunction();
1766 case Builtin::kFunctionPrototypeHasInstance:
1767 return Type::Boolean();
1768
1769 // Global functions.
1770 case Builtin::kGlobalDecodeURI:
1771 case Builtin::kGlobalDecodeURIComponent:
1772 case Builtin::kGlobalEncodeURI:
1773 case Builtin::kGlobalEncodeURIComponent:
1774 case Builtin::kGlobalEscape:
1775 case Builtin::kGlobalUnescape:
1776 return Type::String();
1777 case Builtin::kGlobalIsFinite:
1778 case Builtin::kGlobalIsNaN:
1779 return Type::Boolean();
1780
1781 // Map functions.
1782 case Builtin::kMapPrototypeClear:
1783 case Builtin::kMapPrototypeForEach:
1784 return Type::Undefined();
1785 case Builtin::kMapPrototypeDelete:
1786 case Builtin::kMapPrototypeHas:
1787 return Type::Boolean();
1788 case Builtin::kMapPrototypeEntries:
1789 case Builtin::kMapPrototypeKeys:
1790 case Builtin::kMapPrototypeSet:
1791 case Builtin::kMapPrototypeValues:
1792 return Type::OtherObject();
1793
1794 // Set functions.
1795 case Builtin::kSetPrototypeAdd:
1796 case Builtin::kSetPrototypeEntries:
1797 case Builtin::kSetPrototypeValues:
1798 return Type::OtherObject();
1799 case Builtin::kSetPrototypeClear:
1800 case Builtin::kSetPrototypeForEach:
1801 return Type::Undefined();
1802 case Builtin::kSetPrototypeDelete:
1803 case Builtin::kSetPrototypeHas:
1804 return Type::Boolean();
1805
1806 // WeakMap functions.
1807 case Builtin::kWeakMapPrototypeDelete:
1808 case Builtin::kWeakMapPrototypeHas:
1809 return Type::Boolean();
1810 case Builtin::kWeakMapPrototypeSet:
1811 return Type::OtherObject();
1812
1813 // WeakSet functions.
1814 case Builtin::kWeakSetPrototypeAdd:
1815 return Type::OtherObject();
1816 case Builtin::kWeakSetPrototypeDelete:
1817 case Builtin::kWeakSetPrototypeHas:
1818 return Type::Boolean();
1819 default:
1820 return Type::NonInternal();
1821 }
1822 }
1823
TypeJSCallForwardVarargs(Node * node)1824 Type Typer::Visitor::TypeJSCallForwardVarargs(Node* node) {
1825 return TypeUnaryOp(node, JSCallTyper);
1826 }
1827
TypeJSCall(Node * node)1828 Type Typer::Visitor::TypeJSCall(Node* node) {
1829 // TODO(bmeurer): We could infer better types if we wouldn't ignore the
1830 // argument types for the JSCallTyper above.
1831 return TypeUnaryOp(node, JSCallTyper);
1832 }
1833
TypeJSCallWithArrayLike(Node * node)1834 Type Typer::Visitor::TypeJSCallWithArrayLike(Node* node) {
1835 return TypeUnaryOp(node, JSCallTyper);
1836 }
1837
TypeJSCallWithSpread(Node * node)1838 Type Typer::Visitor::TypeJSCallWithSpread(Node* node) {
1839 return TypeUnaryOp(node, JSCallTyper);
1840 }
1841
TypeJSCallRuntime(Node * node)1842 Type Typer::Visitor::TypeJSCallRuntime(Node* node) {
1843 switch (CallRuntimeParametersOf(node->op()).id()) {
1844 case Runtime::kInlineCreateIterResultObject:
1845 return Type::OtherObject();
1846 case Runtime::kHasInPrototypeChain:
1847 return Type::Boolean();
1848 default:
1849 break;
1850 }
1851 // TODO(turbofan): This should be Type::NonInternal(), but unfortunately we
1852 // have a few weird runtime calls that return the hole or even FixedArrays;
1853 // change this once those weird runtime calls have been removed.
1854 return Type::Any();
1855 }
1856
TypeJSForInEnumerate(Node * node)1857 Type Typer::Visitor::TypeJSForInEnumerate(Node* node) {
1858 return Type::OtherInternal();
1859 }
1860
TypeJSForInNext(Node * node)1861 Type Typer::Visitor::TypeJSForInNext(Node* node) {
1862 return Type::Union(Type::String(), Type::Undefined(), zone());
1863 }
1864
TypeJSForInPrepare(Node * node)1865 Type Typer::Visitor::TypeJSForInPrepare(Node* node) {
1866 STATIC_ASSERT(Map::Bits3::EnumLengthBits::kMax <= FixedArray::kMaxLength);
1867 Type const cache_type =
1868 Type::Union(Type::SignedSmall(), Type::OtherInternal(), zone());
1869 Type const cache_array = Type::OtherInternal();
1870 Type const cache_length = typer_->cache_->kFixedArrayLengthType;
1871 return Type::Tuple(cache_type, cache_array, cache_length, zone());
1872 }
1873
TypeJSLoadMessage(Node * node)1874 Type Typer::Visitor::TypeJSLoadMessage(Node* node) { return Type::Any(); }
1875
TypeJSStoreMessage(Node * node)1876 Type Typer::Visitor::TypeJSStoreMessage(Node* node) { UNREACHABLE(); }
1877
TypeJSLoadModule(Node * node)1878 Type Typer::Visitor::TypeJSLoadModule(Node* node) { return Type::Any(); }
1879
TypeJSStoreModule(Node * node)1880 Type Typer::Visitor::TypeJSStoreModule(Node* node) { UNREACHABLE(); }
1881
TypeJSGetImportMeta(Node * node)1882 Type Typer::Visitor::TypeJSGetImportMeta(Node* node) { return Type::Any(); }
1883
TypeJSGeneratorStore(Node * node)1884 Type Typer::Visitor::TypeJSGeneratorStore(Node* node) { UNREACHABLE(); }
1885
TypeJSGeneratorRestoreContinuation(Node * node)1886 Type Typer::Visitor::TypeJSGeneratorRestoreContinuation(Node* node) {
1887 return Type::SignedSmall();
1888 }
1889
TypeJSGeneratorRestoreContext(Node * node)1890 Type Typer::Visitor::TypeJSGeneratorRestoreContext(Node* node) {
1891 return Type::Any();
1892 }
1893
TypeJSGeneratorRestoreRegister(Node * node)1894 Type Typer::Visitor::TypeJSGeneratorRestoreRegister(Node* node) {
1895 return Type::Any();
1896 }
1897
TypeJSGeneratorRestoreInputOrDebugPos(Node * node)1898 Type Typer::Visitor::TypeJSGeneratorRestoreInputOrDebugPos(Node* node) {
1899 return Type::Any();
1900 }
1901
TypeJSStackCheck(Node * node)1902 Type Typer::Visitor::TypeJSStackCheck(Node* node) { return Type::Any(); }
1903
TypeJSDebugger(Node * node)1904 Type Typer::Visitor::TypeJSDebugger(Node* node) { return Type::Any(); }
1905
TypeJSAsyncFunctionEnter(Node * node)1906 Type Typer::Visitor::TypeJSAsyncFunctionEnter(Node* node) {
1907 return Type::OtherObject();
1908 }
1909
TypeJSAsyncFunctionReject(Node * node)1910 Type Typer::Visitor::TypeJSAsyncFunctionReject(Node* node) {
1911 return Type::OtherObject();
1912 }
1913
TypeJSAsyncFunctionResolve(Node * node)1914 Type Typer::Visitor::TypeJSAsyncFunctionResolve(Node* node) {
1915 return Type::OtherObject();
1916 }
1917
TypeJSFulfillPromise(Node * node)1918 Type Typer::Visitor::TypeJSFulfillPromise(Node* node) {
1919 return Type::Undefined();
1920 }
1921
TypeJSPerformPromiseThen(Node * node)1922 Type Typer::Visitor::TypeJSPerformPromiseThen(Node* node) {
1923 return Type::Receiver();
1924 }
1925
TypeJSPromiseResolve(Node * node)1926 Type Typer::Visitor::TypeJSPromiseResolve(Node* node) {
1927 return Type::Receiver();
1928 }
1929
TypeJSRejectPromise(Node * node)1930 Type Typer::Visitor::TypeJSRejectPromise(Node* node) {
1931 return Type::Undefined();
1932 }
1933
TypeJSResolvePromise(Node * node)1934 Type Typer::Visitor::TypeJSResolvePromise(Node* node) {
1935 return Type::Undefined();
1936 }
1937
1938 // Simplified operators.
1939
TypeBooleanNot(Node * node)1940 Type Typer::Visitor::TypeBooleanNot(Node* node) { return Type::Boolean(); }
1941
1942 // static
NumberEqualTyper(Type lhs,Type rhs,Typer * t)1943 Type Typer::Visitor::NumberEqualTyper(Type lhs, Type rhs, Typer* t) {
1944 return JSEqualTyper(ToNumber(lhs, t), ToNumber(rhs, t), t);
1945 }
1946
1947 // static
NumberLessThanTyper(Type lhs,Type rhs,Typer * t)1948 Type Typer::Visitor::NumberLessThanTyper(Type lhs, Type rhs, Typer* t) {
1949 return FalsifyUndefined(
1950 NumberCompareTyper(ToNumber(lhs, t), ToNumber(rhs, t), t), t);
1951 }
1952
1953 // static
NumberLessThanOrEqualTyper(Type lhs,Type rhs,Typer * t)1954 Type Typer::Visitor::NumberLessThanOrEqualTyper(Type lhs, Type rhs, Typer* t) {
1955 return FalsifyUndefined(
1956 Invert(JSCompareTyper(ToNumber(rhs, t), ToNumber(lhs, t), t), t), t);
1957 }
1958
TypeNumberEqual(Node * node)1959 Type Typer::Visitor::TypeNumberEqual(Node* node) {
1960 return TypeBinaryOp(node, NumberEqualTyper);
1961 }
1962
TypeNumberLessThan(Node * node)1963 Type Typer::Visitor::TypeNumberLessThan(Node* node) {
1964 return TypeBinaryOp(node, NumberLessThanTyper);
1965 }
1966
TypeNumberLessThanOrEqual(Node * node)1967 Type Typer::Visitor::TypeNumberLessThanOrEqual(Node* node) {
1968 return TypeBinaryOp(node, NumberLessThanOrEqualTyper);
1969 }
1970
TypeSpeculativeNumberEqual(Node * node)1971 Type Typer::Visitor::TypeSpeculativeNumberEqual(Node* node) {
1972 return TypeBinaryOp(node, NumberEqualTyper);
1973 }
1974
TypeSpeculativeNumberLessThan(Node * node)1975 Type Typer::Visitor::TypeSpeculativeNumberLessThan(Node* node) {
1976 return TypeBinaryOp(node, NumberLessThanTyper);
1977 }
1978
TypeSpeculativeNumberLessThanOrEqual(Node * node)1979 Type Typer::Visitor::TypeSpeculativeNumberLessThanOrEqual(Node* node) {
1980 return TypeBinaryOp(node, NumberLessThanOrEqualTyper);
1981 }
1982
TypeStringConcat(Node * node)1983 Type Typer::Visitor::TypeStringConcat(Node* node) { return Type::String(); }
1984
TypeStringToNumber(Node * node)1985 Type Typer::Visitor::TypeStringToNumber(Node* node) {
1986 return TypeUnaryOp(node, ToNumber);
1987 }
1988
TypePlainPrimitiveToNumber(Node * node)1989 Type Typer::Visitor::TypePlainPrimitiveToNumber(Node* node) {
1990 return TypeUnaryOp(node, ToNumber);
1991 }
1992
TypePlainPrimitiveToWord32(Node * node)1993 Type Typer::Visitor::TypePlainPrimitiveToWord32(Node* node) {
1994 return Type::Integral32();
1995 }
1996
TypePlainPrimitiveToFloat64(Node * node)1997 Type Typer::Visitor::TypePlainPrimitiveToFloat64(Node* node) {
1998 return Type::Number();
1999 }
2000
2001 // static
ReferenceEqualTyper(Type lhs,Type rhs,Typer * t)2002 Type Typer::Visitor::ReferenceEqualTyper(Type lhs, Type rhs, Typer* t) {
2003 if (lhs.IsHeapConstant() && rhs.Is(lhs)) {
2004 return t->singleton_true_;
2005 }
2006 return Type::Boolean();
2007 }
2008
TypeReferenceEqual(Node * node)2009 Type Typer::Visitor::TypeReferenceEqual(Node* node) {
2010 return TypeBinaryOp(node, ReferenceEqualTyper);
2011 }
2012
2013 // static
SameValueTyper(Type lhs,Type rhs,Typer * t)2014 Type Typer::Visitor::SameValueTyper(Type lhs, Type rhs, Typer* t) {
2015 return t->operation_typer()->SameValue(lhs, rhs);
2016 }
2017
2018 // static
SameValueNumbersOnlyTyper(Type lhs,Type rhs,Typer * t)2019 Type Typer::Visitor::SameValueNumbersOnlyTyper(Type lhs, Type rhs, Typer* t) {
2020 return t->operation_typer()->SameValueNumbersOnly(lhs, rhs);
2021 }
2022
TypeSameValue(Node * node)2023 Type Typer::Visitor::TypeSameValue(Node* node) {
2024 return TypeBinaryOp(node, SameValueTyper);
2025 }
2026
TypeSameValueNumbersOnly(Node * node)2027 Type Typer::Visitor::TypeSameValueNumbersOnly(Node* node) {
2028 return TypeBinaryOp(node, SameValueNumbersOnlyTyper);
2029 }
2030
TypeNumberSameValue(Node * node)2031 Type Typer::Visitor::TypeNumberSameValue(Node* node) { UNREACHABLE(); }
2032
TypeStringEqual(Node * node)2033 Type Typer::Visitor::TypeStringEqual(Node* node) { return Type::Boolean(); }
2034
TypeStringLessThan(Node * node)2035 Type Typer::Visitor::TypeStringLessThan(Node* node) { return Type::Boolean(); }
2036
TypeStringLessThanOrEqual(Node * node)2037 Type Typer::Visitor::TypeStringLessThanOrEqual(Node* node) {
2038 return Type::Boolean();
2039 }
2040
StringFromSingleCharCodeTyper(Type type,Typer * t)2041 Type Typer::Visitor::StringFromSingleCharCodeTyper(Type type, Typer* t) {
2042 return Type::String();
2043 }
2044
StringFromSingleCodePointTyper(Type type,Typer * t)2045 Type Typer::Visitor::StringFromSingleCodePointTyper(Type type, Typer* t) {
2046 return Type::String();
2047 }
2048
TypeStringToLowerCaseIntl(Node * node)2049 Type Typer::Visitor::TypeStringToLowerCaseIntl(Node* node) {
2050 return Type::String();
2051 }
2052
TypeStringToUpperCaseIntl(Node * node)2053 Type Typer::Visitor::TypeStringToUpperCaseIntl(Node* node) {
2054 return Type::String();
2055 }
2056
TypeStringCharCodeAt(Node * node)2057 Type Typer::Visitor::TypeStringCharCodeAt(Node* node) {
2058 return typer_->cache_->kUint16;
2059 }
2060
TypeStringCodePointAt(Node * node)2061 Type Typer::Visitor::TypeStringCodePointAt(Node* node) {
2062 return Type::Range(0.0, String::kMaxCodePoint, zone());
2063 }
2064
TypeStringFromSingleCharCode(Node * node)2065 Type Typer::Visitor::TypeStringFromSingleCharCode(Node* node) {
2066 return TypeUnaryOp(node, StringFromSingleCharCodeTyper);
2067 }
2068
TypeStringFromSingleCodePoint(Node * node)2069 Type Typer::Visitor::TypeStringFromSingleCodePoint(Node* node) {
2070 return TypeUnaryOp(node, StringFromSingleCodePointTyper);
2071 }
2072
TypeStringFromCodePointAt(Node * node)2073 Type Typer::Visitor::TypeStringFromCodePointAt(Node* node) {
2074 return Type::String();
2075 }
2076
TypeStringIndexOf(Node * node)2077 Type Typer::Visitor::TypeStringIndexOf(Node* node) {
2078 return Type::Range(-1.0, String::kMaxLength, zone());
2079 }
2080
TypeStringLength(Node * node)2081 Type Typer::Visitor::TypeStringLength(Node* node) {
2082 return typer_->cache_->kStringLengthType;
2083 }
2084
TypeStringSubstring(Node * node)2085 Type Typer::Visitor::TypeStringSubstring(Node* node) { return Type::String(); }
2086
TypeCheckBounds(Node * node)2087 Type Typer::Visitor::TypeCheckBounds(Node* node) {
2088 return typer_->operation_typer_.CheckBounds(Operand(node, 0),
2089 Operand(node, 1));
2090 }
2091
TypeCheckHeapObject(Node * node)2092 Type Typer::Visitor::TypeCheckHeapObject(Node* node) {
2093 Type type = Operand(node, 0);
2094 return type;
2095 }
2096
TypeCheckIf(Node * node)2097 Type Typer::Visitor::TypeCheckIf(Node* node) { UNREACHABLE(); }
2098
TypeCheckInternalizedString(Node * node)2099 Type Typer::Visitor::TypeCheckInternalizedString(Node* node) {
2100 Type arg = Operand(node, 0);
2101 return Type::Intersect(arg, Type::InternalizedString(), zone());
2102 }
2103
TypeCheckMaps(Node * node)2104 Type Typer::Visitor::TypeCheckMaps(Node* node) { UNREACHABLE(); }
2105
TypeCompareMaps(Node * node)2106 Type Typer::Visitor::TypeCompareMaps(Node* node) { return Type::Boolean(); }
2107
TypeCheckNumber(Node * node)2108 Type Typer::Visitor::TypeCheckNumber(Node* node) {
2109 return typer_->operation_typer_.CheckNumber(Operand(node, 0));
2110 }
2111
TypeCheckReceiver(Node * node)2112 Type Typer::Visitor::TypeCheckReceiver(Node* node) {
2113 Type arg = Operand(node, 0);
2114 return Type::Intersect(arg, Type::Receiver(), zone());
2115 }
2116
TypeCheckReceiverOrNullOrUndefined(Node * node)2117 Type Typer::Visitor::TypeCheckReceiverOrNullOrUndefined(Node* node) {
2118 Type arg = Operand(node, 0);
2119 return Type::Intersect(arg, Type::ReceiverOrNullOrUndefined(), zone());
2120 }
2121
TypeCheckSmi(Node * node)2122 Type Typer::Visitor::TypeCheckSmi(Node* node) {
2123 Type arg = Operand(node, 0);
2124 return Type::Intersect(arg, Type::SignedSmall(), zone());
2125 }
2126
TypeCheckString(Node * node)2127 Type Typer::Visitor::TypeCheckString(Node* node) {
2128 Type arg = Operand(node, 0);
2129 return Type::Intersect(arg, Type::String(), zone());
2130 }
2131
TypeCheckSymbol(Node * node)2132 Type Typer::Visitor::TypeCheckSymbol(Node* node) {
2133 Type arg = Operand(node, 0);
2134 return Type::Intersect(arg, Type::Symbol(), zone());
2135 }
2136
TypeCheckFloat64Hole(Node * node)2137 Type Typer::Visitor::TypeCheckFloat64Hole(Node* node) {
2138 return typer_->operation_typer_.CheckFloat64Hole(Operand(node, 0));
2139 }
2140
TypeCheckNotTaggedHole(Node * node)2141 Type Typer::Visitor::TypeCheckNotTaggedHole(Node* node) {
2142 Type type = Operand(node, 0);
2143 type = Type::Intersect(type, Type::NonInternal(), zone());
2144 return type;
2145 }
2146
TypeCheckClosure(Node * node)2147 Type Typer::Visitor::TypeCheckClosure(Node* node) {
2148 FeedbackCellRef cell = MakeRef(typer_->broker(), FeedbackCellOf(node->op()));
2149 base::Optional<SharedFunctionInfoRef> shared = cell.shared_function_info();
2150 if (!shared.has_value()) return Type::Function();
2151
2152 if (IsClassConstructor(shared->kind())) {
2153 return Type::ClassConstructor();
2154 } else {
2155 return Type::CallableFunction();
2156 }
2157 }
2158
TypeConvertReceiver(Node * node)2159 Type Typer::Visitor::TypeConvertReceiver(Node* node) {
2160 Type arg = Operand(node, 0);
2161 return typer_->operation_typer_.ConvertReceiver(arg);
2162 }
2163
TypeConvertTaggedHoleToUndefined(Node * node)2164 Type Typer::Visitor::TypeConvertTaggedHoleToUndefined(Node* node) {
2165 Type type = Operand(node, 0);
2166 return typer_->operation_typer()->ConvertTaggedHoleToUndefined(type);
2167 }
2168
TypeCheckEqualsInternalizedString(Node * node)2169 Type Typer::Visitor::TypeCheckEqualsInternalizedString(Node* node) {
2170 UNREACHABLE();
2171 }
2172
TypeCheckEqualsSymbol(Node * node)2173 Type Typer::Visitor::TypeCheckEqualsSymbol(Node* node) { UNREACHABLE(); }
2174
TypeAllocate(Node * node)2175 Type Typer::Visitor::TypeAllocate(Node* node) {
2176 return AllocateTypeOf(node->op());
2177 }
2178
TypeAllocateRaw(Node * node)2179 Type Typer::Visitor::TypeAllocateRaw(Node* node) { UNREACHABLE(); }
2180
TypeLoadFieldByIndex(Node * node)2181 Type Typer::Visitor::TypeLoadFieldByIndex(Node* node) {
2182 return Type::NonInternal();
2183 }
2184
TypeLoadField(Node * node)2185 Type Typer::Visitor::TypeLoadField(Node* node) {
2186 return FieldAccessOf(node->op()).type;
2187 }
2188
TypeLoadMessage(Node * node)2189 Type Typer::Visitor::TypeLoadMessage(Node* node) { return Type::Any(); }
2190
TypeLoadElement(Node * node)2191 Type Typer::Visitor::TypeLoadElement(Node* node) {
2192 return ElementAccessOf(node->op()).type;
2193 }
2194
TypeLoadStackArgument(Node * node)2195 Type Typer::Visitor::TypeLoadStackArgument(Node* node) {
2196 return Type::NonInternal();
2197 }
2198
TypeLoadFromObject(Node * node)2199 Type Typer::Visitor::TypeLoadFromObject(Node* node) { UNREACHABLE(); }
TypeLoadImmutableFromObject(Node * node)2200 Type Typer::Visitor::TypeLoadImmutableFromObject(Node* node) { UNREACHABLE(); }
2201
TypeLoadTypedElement(Node * node)2202 Type Typer::Visitor::TypeLoadTypedElement(Node* node) {
2203 switch (ExternalArrayTypeOf(node->op())) {
2204 #define TYPED_ARRAY_CASE(ElemType, type, TYPE, ctype) \
2205 case kExternal##ElemType##Array: \
2206 return typer_->cache_->k##ElemType;
2207 TYPED_ARRAYS(TYPED_ARRAY_CASE)
2208 #undef TYPED_ARRAY_CASE
2209 }
2210 UNREACHABLE();
2211 }
2212
TypeLoadDataViewElement(Node * node)2213 Type Typer::Visitor::TypeLoadDataViewElement(Node* node) {
2214 switch (ExternalArrayTypeOf(node->op())) {
2215 #define TYPED_ARRAY_CASE(ElemType, type, TYPE, ctype) \
2216 case kExternal##ElemType##Array: \
2217 return typer_->cache_->k##ElemType;
2218 TYPED_ARRAYS(TYPED_ARRAY_CASE)
2219 #undef TYPED_ARRAY_CASE
2220 }
2221 UNREACHABLE();
2222 }
2223
TypeStoreField(Node * node)2224 Type Typer::Visitor::TypeStoreField(Node* node) { UNREACHABLE(); }
2225
TypeStoreMessage(Node * node)2226 Type Typer::Visitor::TypeStoreMessage(Node* node) { UNREACHABLE(); }
2227
TypeStoreElement(Node * node)2228 Type Typer::Visitor::TypeStoreElement(Node* node) { UNREACHABLE(); }
2229
TypeStoreToObject(Node * node)2230 Type Typer::Visitor::TypeStoreToObject(Node* node) { UNREACHABLE(); }
TypeInitializeImmutableInObject(Node * node)2231 Type Typer::Visitor::TypeInitializeImmutableInObject(Node* node) {
2232 UNREACHABLE();
2233 }
2234
TypeTransitionAndStoreElement(Node * node)2235 Type Typer::Visitor::TypeTransitionAndStoreElement(Node* node) {
2236 UNREACHABLE();
2237 }
2238
TypeTransitionAndStoreNumberElement(Node * node)2239 Type Typer::Visitor::TypeTransitionAndStoreNumberElement(Node* node) {
2240 UNREACHABLE();
2241 }
2242
TypeTransitionAndStoreNonNumberElement(Node * node)2243 Type Typer::Visitor::TypeTransitionAndStoreNonNumberElement(Node* node) {
2244 UNREACHABLE();
2245 }
2246
TypeStoreSignedSmallElement(Node * node)2247 Type Typer::Visitor::TypeStoreSignedSmallElement(Node* node) { UNREACHABLE(); }
2248
TypeStoreTypedElement(Node * node)2249 Type Typer::Visitor::TypeStoreTypedElement(Node* node) { UNREACHABLE(); }
2250
TypeStoreDataViewElement(Node * node)2251 Type Typer::Visitor::TypeStoreDataViewElement(Node* node) { UNREACHABLE(); }
2252
TypeObjectIsArrayBufferView(Node * node)2253 Type Typer::Visitor::TypeObjectIsArrayBufferView(Node* node) {
2254 return TypeUnaryOp(node, ObjectIsArrayBufferView);
2255 }
2256
TypeObjectIsBigInt(Node * node)2257 Type Typer::Visitor::TypeObjectIsBigInt(Node* node) {
2258 return TypeUnaryOp(node, ObjectIsBigInt);
2259 }
2260
TypeObjectIsCallable(Node * node)2261 Type Typer::Visitor::TypeObjectIsCallable(Node* node) {
2262 return TypeUnaryOp(node, ObjectIsCallable);
2263 }
2264
TypeObjectIsConstructor(Node * node)2265 Type Typer::Visitor::TypeObjectIsConstructor(Node* node) {
2266 return TypeUnaryOp(node, ObjectIsConstructor);
2267 }
2268
TypeObjectIsDetectableCallable(Node * node)2269 Type Typer::Visitor::TypeObjectIsDetectableCallable(Node* node) {
2270 return TypeUnaryOp(node, ObjectIsDetectableCallable);
2271 }
2272
TypeObjectIsMinusZero(Node * node)2273 Type Typer::Visitor::TypeObjectIsMinusZero(Node* node) {
2274 return TypeUnaryOp(node, ObjectIsMinusZero);
2275 }
2276
TypeNumberIsMinusZero(Node * node)2277 Type Typer::Visitor::TypeNumberIsMinusZero(Node* node) {
2278 return TypeUnaryOp(node, NumberIsMinusZero);
2279 }
2280
TypeNumberIsFloat64Hole(Node * node)2281 Type Typer::Visitor::TypeNumberIsFloat64Hole(Node* node) {
2282 return Type::Boolean();
2283 }
2284
TypeNumberIsFinite(Node * node)2285 Type Typer::Visitor::TypeNumberIsFinite(Node* node) { return Type::Boolean(); }
2286
TypeObjectIsFiniteNumber(Node * node)2287 Type Typer::Visitor::TypeObjectIsFiniteNumber(Node* node) {
2288 return Type::Boolean();
2289 }
2290
TypeNumberIsInteger(Node * node)2291 Type Typer::Visitor::TypeNumberIsInteger(Node* node) { UNREACHABLE(); }
2292
TypeObjectIsSafeInteger(Node * node)2293 Type Typer::Visitor::TypeObjectIsSafeInteger(Node* node) {
2294 return Type::Boolean();
2295 }
2296
TypeNumberIsSafeInteger(Node * node)2297 Type Typer::Visitor::TypeNumberIsSafeInteger(Node* node) { UNREACHABLE(); }
2298
TypeObjectIsInteger(Node * node)2299 Type Typer::Visitor::TypeObjectIsInteger(Node* node) { return Type::Boolean(); }
2300
TypeObjectIsNaN(Node * node)2301 Type Typer::Visitor::TypeObjectIsNaN(Node* node) {
2302 return TypeUnaryOp(node, ObjectIsNaN);
2303 }
2304
TypeNumberIsNaN(Node * node)2305 Type Typer::Visitor::TypeNumberIsNaN(Node* node) {
2306 return TypeUnaryOp(node, NumberIsNaN);
2307 }
2308
TypeObjectIsNonCallable(Node * node)2309 Type Typer::Visitor::TypeObjectIsNonCallable(Node* node) {
2310 return TypeUnaryOp(node, ObjectIsNonCallable);
2311 }
2312
TypeObjectIsNumber(Node * node)2313 Type Typer::Visitor::TypeObjectIsNumber(Node* node) {
2314 return TypeUnaryOp(node, ObjectIsNumber);
2315 }
2316
TypeObjectIsReceiver(Node * node)2317 Type Typer::Visitor::TypeObjectIsReceiver(Node* node) {
2318 return TypeUnaryOp(node, ObjectIsReceiver);
2319 }
2320
TypeObjectIsSmi(Node * node)2321 Type Typer::Visitor::TypeObjectIsSmi(Node* node) {
2322 return TypeUnaryOp(node, ObjectIsSmi);
2323 }
2324
TypeObjectIsString(Node * node)2325 Type Typer::Visitor::TypeObjectIsString(Node* node) {
2326 return TypeUnaryOp(node, ObjectIsString);
2327 }
2328
TypeObjectIsSymbol(Node * node)2329 Type Typer::Visitor::TypeObjectIsSymbol(Node* node) {
2330 return TypeUnaryOp(node, ObjectIsSymbol);
2331 }
2332
TypeObjectIsUndetectable(Node * node)2333 Type Typer::Visitor::TypeObjectIsUndetectable(Node* node) {
2334 return TypeUnaryOp(node, ObjectIsUndetectable);
2335 }
2336
TypeArgumentsLength(Node * node)2337 Type Typer::Visitor::TypeArgumentsLength(Node* node) {
2338 return TypeCache::Get()->kArgumentsLengthType;
2339 }
2340
TypeRestLength(Node * node)2341 Type Typer::Visitor::TypeRestLength(Node* node) {
2342 return TypeCache::Get()->kArgumentsLengthType;
2343 }
2344
TypeNewDoubleElements(Node * node)2345 Type Typer::Visitor::TypeNewDoubleElements(Node* node) {
2346 return Type::OtherInternal();
2347 }
2348
TypeNewSmiOrObjectElements(Node * node)2349 Type Typer::Visitor::TypeNewSmiOrObjectElements(Node* node) {
2350 return Type::OtherInternal();
2351 }
2352
TypeNewArgumentsElements(Node * node)2353 Type Typer::Visitor::TypeNewArgumentsElements(Node* node) {
2354 return Type::OtherInternal();
2355 }
2356
TypeNewConsString(Node * node)2357 Type Typer::Visitor::TypeNewConsString(Node* node) { return Type::String(); }
2358
TypeDelayedStringConstant(Node * node)2359 Type Typer::Visitor::TypeDelayedStringConstant(Node* node) {
2360 return Type::String();
2361 }
2362
TypeFindOrderedHashMapEntry(Node * node)2363 Type Typer::Visitor::TypeFindOrderedHashMapEntry(Node* node) {
2364 return Type::Range(-1.0, FixedArray::kMaxLength, zone());
2365 }
2366
TypeFindOrderedHashMapEntryForInt32Key(Node * node)2367 Type Typer::Visitor::TypeFindOrderedHashMapEntryForInt32Key(Node* node) {
2368 return Type::Range(-1.0, FixedArray::kMaxLength, zone());
2369 }
2370
TypeRuntimeAbort(Node * node)2371 Type Typer::Visitor::TypeRuntimeAbort(Node* node) { UNREACHABLE(); }
2372
TypeAssertType(Node * node)2373 Type Typer::Visitor::TypeAssertType(Node* node) { UNREACHABLE(); }
2374
TypeVerifyType(Node * node)2375 Type Typer::Visitor::TypeVerifyType(Node* node) {
2376 return TypeOrNone(node->InputAt(0));
2377 }
2378
2379 // Heap constants.
2380
TypeConstant(Handle<Object> value)2381 Type Typer::Visitor::TypeConstant(Handle<Object> value) {
2382 return Type::Constant(typer_->broker(), value, zone());
2383 }
2384
TypeJSGetIterator(Node * node)2385 Type Typer::Visitor::TypeJSGetIterator(Node* node) { return Type::Any(); }
2386
2387 } // namespace compiler
2388 } // namespace internal
2389 } // namespace v8
2390