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/bootstrapper.h"
11 #include "src/compiler/common-operator.h"
12 #include "src/compiler/graph-reducer.h"
13 #include "src/compiler/js-operator.h"
14 #include "src/compiler/linkage.h"
15 #include "src/compiler/loop-variable-optimizer.h"
16 #include "src/compiler/node-properties.h"
17 #include "src/compiler/node.h"
18 #include "src/compiler/operation-typer.h"
19 #include "src/compiler/simplified-operator.h"
20 #include "src/compiler/type-cache.h"
21 #include "src/objects-inl.h"
22
23 namespace v8 {
24 namespace internal {
25 namespace compiler {
26
27 class Typer::Decorator final : public GraphDecorator {
28 public:
Decorator(Typer * typer)29 explicit Decorator(Typer* typer) : typer_(typer) {}
30 void Decorate(Node* node) final;
31
32 private:
33 Typer* const typer_;
34 };
35
Typer(Isolate * isolate,Flags flags,Graph * graph)36 Typer::Typer(Isolate* isolate, Flags flags, Graph* graph)
37 : isolate_(isolate),
38 flags_(flags),
39 graph_(graph),
40 decorator_(nullptr),
41 cache_(TypeCache::Get()),
42 operation_typer_(isolate, zone()) {
43 Zone* zone = this->zone();
44 Factory* const factory = isolate->factory();
45
46 singleton_false_ = Type::HeapConstant(factory->false_value(), zone);
47 singleton_true_ = Type::HeapConstant(factory->true_value(), zone);
48 singleton_the_hole_ = Type::HeapConstant(factory->the_hole_value(), zone);
49 falsish_ = Type::Union(
50 Type::Undetectable(),
51 Type::Union(Type::Union(singleton_false_, cache_.kZeroish, zone),
52 singleton_the_hole_, zone),
53 zone);
54 truish_ = Type::Union(
55 singleton_true_,
56 Type::Union(Type::DetectableReceiver(), Type::Symbol(), zone), zone);
57
58 decorator_ = new (zone) Decorator(this);
59 graph_->AddDecorator(decorator_);
60 }
61
62
~Typer()63 Typer::~Typer() {
64 graph_->RemoveDecorator(decorator_);
65 }
66
67
68 class Typer::Visitor : public Reducer {
69 public:
Visitor(Typer * typer,LoopVariableOptimizer * induction_vars)70 explicit Visitor(Typer* typer, LoopVariableOptimizer* induction_vars)
71 : typer_(typer),
72 induction_vars_(induction_vars),
73 weakened_nodes_(typer->zone()) {}
74
Reduce(Node * node)75 Reduction Reduce(Node* node) override {
76 if (node->op()->ValueOutputCount() == 0) return NoChange();
77 switch (node->opcode()) {
78 #define DECLARE_CASE(x) \
79 case IrOpcode::k##x: \
80 return UpdateType(node, TypeBinaryOp(node, x##Typer));
81 JS_SIMPLE_BINOP_LIST(DECLARE_CASE)
82 #undef DECLARE_CASE
83
84 #define DECLARE_CASE(x) \
85 case IrOpcode::k##x: \
86 return UpdateType(node, Type##x(node));
87 DECLARE_CASE(Start)
88 DECLARE_CASE(IfException)
89 // VALUE_OP_LIST without JS_SIMPLE_BINOP_LIST:
90 COMMON_OP_LIST(DECLARE_CASE)
91 SIMPLIFIED_COMPARE_BINOP_LIST(DECLARE_CASE)
92 SIMPLIFIED_OTHER_OP_LIST(DECLARE_CASE)
93 JS_SIMPLE_UNOP_LIST(DECLARE_CASE)
94 JS_OBJECT_OP_LIST(DECLARE_CASE)
95 JS_CONTEXT_OP_LIST(DECLARE_CASE)
96 JS_OTHER_OP_LIST(DECLARE_CASE)
97 #undef DECLARE_CASE
98
99 #define DECLARE_CASE(x) \
100 case IrOpcode::k##x: \
101 return UpdateType(node, TypeBinaryOp(node, x));
102 SIMPLIFIED_NUMBER_BINOP_LIST(DECLARE_CASE)
103 SIMPLIFIED_SPECULATIVE_NUMBER_BINOP_LIST(DECLARE_CASE)
104 #undef DECLARE_CASE
105
106 #define DECLARE_CASE(x) \
107 case IrOpcode::k##x: \
108 return UpdateType(node, TypeUnaryOp(node, x));
109 SIMPLIFIED_NUMBER_UNOP_LIST(DECLARE_CASE)
110 #undef DECLARE_CASE
111
112 #define DECLARE_CASE(x) case IrOpcode::k##x:
113 DECLARE_CASE(Loop)
114 DECLARE_CASE(Branch)
115 DECLARE_CASE(IfTrue)
116 DECLARE_CASE(IfFalse)
117 DECLARE_CASE(IfSuccess)
118 DECLARE_CASE(Switch)
119 DECLARE_CASE(IfValue)
120 DECLARE_CASE(IfDefault)
121 DECLARE_CASE(Merge)
122 DECLARE_CASE(Deoptimize)
123 DECLARE_CASE(DeoptimizeIf)
124 DECLARE_CASE(DeoptimizeUnless)
125 DECLARE_CASE(Return)
126 DECLARE_CASE(TailCall)
127 DECLARE_CASE(Terminate)
128 DECLARE_CASE(OsrNormalEntry)
129 DECLARE_CASE(OsrLoopEntry)
130 DECLARE_CASE(Throw)
131 DECLARE_CASE(End)
132 SIMPLIFIED_CHANGE_OP_LIST(DECLARE_CASE)
133 SIMPLIFIED_CHECKED_OP_LIST(DECLARE_CASE)
134 MACHINE_SIMD_OP_LIST(DECLARE_CASE)
135 MACHINE_OP_LIST(DECLARE_CASE)
136 #undef DECLARE_CASE
137 break;
138 }
139 return NoChange();
140 }
141
TypeNode(Node * node)142 Type* TypeNode(Node* node) {
143 switch (node->opcode()) {
144 #define DECLARE_CASE(x) \
145 case IrOpcode::k##x: return TypeBinaryOp(node, x##Typer);
146 JS_SIMPLE_BINOP_LIST(DECLARE_CASE)
147 #undef DECLARE_CASE
148
149 #define DECLARE_CASE(x) case IrOpcode::k##x: return Type##x(node);
150 DECLARE_CASE(Start)
151 DECLARE_CASE(IfException)
152 // VALUE_OP_LIST without JS_SIMPLE_BINOP_LIST:
153 COMMON_OP_LIST(DECLARE_CASE)
154 SIMPLIFIED_COMPARE_BINOP_LIST(DECLARE_CASE)
155 SIMPLIFIED_OTHER_OP_LIST(DECLARE_CASE)
156 JS_SIMPLE_UNOP_LIST(DECLARE_CASE)
157 JS_OBJECT_OP_LIST(DECLARE_CASE)
158 JS_CONTEXT_OP_LIST(DECLARE_CASE)
159 JS_OTHER_OP_LIST(DECLARE_CASE)
160 #undef DECLARE_CASE
161
162 #define DECLARE_CASE(x) \
163 case IrOpcode::k##x: \
164 return TypeBinaryOp(node, x);
165 SIMPLIFIED_NUMBER_BINOP_LIST(DECLARE_CASE)
166 SIMPLIFIED_SPECULATIVE_NUMBER_BINOP_LIST(DECLARE_CASE)
167 #undef DECLARE_CASE
168
169 #define DECLARE_CASE(x) \
170 case IrOpcode::k##x: \
171 return TypeUnaryOp(node, x);
172 SIMPLIFIED_NUMBER_UNOP_LIST(DECLARE_CASE)
173 #undef DECLARE_CASE
174
175 #define DECLARE_CASE(x) case IrOpcode::k##x:
176 DECLARE_CASE(Loop)
177 DECLARE_CASE(Branch)
178 DECLARE_CASE(IfTrue)
179 DECLARE_CASE(IfFalse)
180 DECLARE_CASE(IfSuccess)
181 DECLARE_CASE(Switch)
182 DECLARE_CASE(IfValue)
183 DECLARE_CASE(IfDefault)
184 DECLARE_CASE(Merge)
185 DECLARE_CASE(Deoptimize)
186 DECLARE_CASE(DeoptimizeIf)
187 DECLARE_CASE(DeoptimizeUnless)
188 DECLARE_CASE(Return)
189 DECLARE_CASE(TailCall)
190 DECLARE_CASE(Terminate)
191 DECLARE_CASE(OsrNormalEntry)
192 DECLARE_CASE(OsrLoopEntry)
193 DECLARE_CASE(Throw)
194 DECLARE_CASE(End)
195 SIMPLIFIED_CHANGE_OP_LIST(DECLARE_CASE)
196 SIMPLIFIED_CHECKED_OP_LIST(DECLARE_CASE)
197 MACHINE_SIMD_OP_LIST(DECLARE_CASE)
198 MACHINE_OP_LIST(DECLARE_CASE)
199 #undef DECLARE_CASE
200 break;
201 }
202 UNREACHABLE();
203 return nullptr;
204 }
205
206 Type* TypeConstant(Handle<Object> value);
207
208 private:
209 Typer* typer_;
210 LoopVariableOptimizer* induction_vars_;
211 ZoneSet<NodeId> weakened_nodes_;
212
213 #define DECLARE_METHOD(x) inline Type* Type##x(Node* node);
214 DECLARE_METHOD(Start)
DECLARE_METHOD(IfException)215 DECLARE_METHOD(IfException)
216 COMMON_OP_LIST(DECLARE_METHOD)
217 SIMPLIFIED_COMPARE_BINOP_LIST(DECLARE_METHOD)
218 SIMPLIFIED_OTHER_OP_LIST(DECLARE_METHOD)
219 JS_OP_LIST(DECLARE_METHOD)
220 #undef DECLARE_METHOD
221
222 Type* TypeOrNone(Node* node) {
223 return NodeProperties::IsTyped(node) ? NodeProperties::GetType(node)
224 : Type::None();
225 }
226
Operand(Node * node,int i)227 Type* Operand(Node* node, int i) {
228 Node* operand_node = NodeProperties::GetValueInput(node, i);
229 return TypeOrNone(operand_node);
230 }
231
232 Type* Weaken(Node* node, Type* current_type, Type* previous_type);
233
zone()234 Zone* zone() { return typer_->zone(); }
isolate()235 Isolate* isolate() { return typer_->isolate(); }
graph()236 Graph* graph() { return typer_->graph(); }
237
SetWeakened(NodeId node_id)238 void SetWeakened(NodeId node_id) { weakened_nodes_.insert(node_id); }
IsWeakened(NodeId node_id)239 bool IsWeakened(NodeId node_id) {
240 return weakened_nodes_.find(node_id) != weakened_nodes_.end();
241 }
242
243 typedef Type* (*UnaryTyperFun)(Type*, Typer* t);
244 typedef Type* (*BinaryTyperFun)(Type*, Type*, Typer* t);
245
246 Type* TypeUnaryOp(Node* node, UnaryTyperFun);
247 Type* TypeBinaryOp(Node* node, BinaryTyperFun);
248
249 enum ComparisonOutcomeFlags {
250 kComparisonTrue = 1,
251 kComparisonFalse = 2,
252 kComparisonUndefined = 4
253 };
254 typedef base::Flags<ComparisonOutcomeFlags> ComparisonOutcome;
255
256 static ComparisonOutcome Invert(ComparisonOutcome, Typer*);
257 static Type* Invert(Type*, Typer*);
258 static Type* FalsifyUndefined(ComparisonOutcome, Typer*);
259
260 static Type* ToPrimitive(Type*, Typer*);
261 static Type* ToBoolean(Type*, Typer*);
262 static Type* ToInteger(Type*, Typer*);
263 static Type* ToLength(Type*, Typer*);
264 static Type* ToName(Type*, Typer*);
265 static Type* ToNumber(Type*, Typer*);
266 static Type* ToObject(Type*, Typer*);
267 static Type* ToString(Type*, Typer*);
268 #define DECLARE_METHOD(Name) \
269 static Type* Name(Type* type, Typer* t) { \
270 return t->operation_typer_.Name(type); \
271 }
272 SIMPLIFIED_NUMBER_UNOP_LIST(DECLARE_METHOD)
273 #undef DECLARE_METHOD
274 #define DECLARE_METHOD(Name) \
275 static Type* Name(Type* lhs, Type* rhs, Typer* t) { \
276 return t->operation_typer_.Name(lhs, rhs); \
277 }
278 SIMPLIFIED_NUMBER_BINOP_LIST(DECLARE_METHOD)
279 SIMPLIFIED_SPECULATIVE_NUMBER_BINOP_LIST(DECLARE_METHOD)
280 #undef DECLARE_METHOD
281
282 static Type* ObjectIsCallable(Type*, Typer*);
283 static Type* ObjectIsNumber(Type*, Typer*);
284 static Type* ObjectIsReceiver(Type*, Typer*);
285 static Type* ObjectIsSmi(Type*, Typer*);
286 static Type* ObjectIsString(Type*, Typer*);
287 static Type* ObjectIsUndetectable(Type*, Typer*);
288
289 static ComparisonOutcome JSCompareTyper(Type*, Type*, Typer*);
290
291 #define DECLARE_METHOD(x) static Type* x##Typer(Type*, Type*, Typer*);
292 JS_SIMPLE_BINOP_LIST(DECLARE_METHOD)
293 #undef DECLARE_METHOD
294
295 static Type* JSCallFunctionTyper(Type*, Typer*);
296
297 static Type* ReferenceEqualTyper(Type*, Type*, Typer*);
298 static Type* StringFromCharCodeTyper(Type*, Typer*);
299 static Type* StringFromCodePointTyper(Type*, Typer*);
300
UpdateType(Node * node,Type * current)301 Reduction UpdateType(Node* node, Type* current) {
302 if (NodeProperties::IsTyped(node)) {
303 // Widen the type of a previously typed node.
304 Type* previous = NodeProperties::GetType(node);
305 if (node->opcode() == IrOpcode::kPhi ||
306 node->opcode() == IrOpcode::kInductionVariablePhi) {
307 // Speed up termination in the presence of range types:
308 current = Weaken(node, current, previous);
309 }
310
311 CHECK(previous->Is(current));
312
313 NodeProperties::SetType(node, current);
314 if (!current->Is(previous)) {
315 // If something changed, revisit all uses.
316 return Changed(node);
317 }
318 return NoChange();
319 } else {
320 // No previous type, simply update the type.
321 NodeProperties::SetType(node, current);
322 return Changed(node);
323 }
324 }
325 };
326
Run()327 void Typer::Run() { Run(NodeVector(zone()), nullptr); }
328
Run(const NodeVector & roots,LoopVariableOptimizer * induction_vars)329 void Typer::Run(const NodeVector& roots,
330 LoopVariableOptimizer* induction_vars) {
331 if (induction_vars != nullptr) {
332 induction_vars->ChangeToInductionVariablePhis();
333 }
334 Visitor visitor(this, induction_vars);
335 GraphReducer graph_reducer(zone(), graph());
336 graph_reducer.AddReducer(&visitor);
337 for (Node* const root : roots) graph_reducer.ReduceNode(root);
338 graph_reducer.ReduceGraph();
339
340 if (induction_vars != nullptr) {
341 induction_vars->ChangeToPhisAndInsertGuards();
342 }
343 }
344
Decorate(Node * node)345 void Typer::Decorator::Decorate(Node* node) {
346 if (node->op()->ValueOutputCount() > 0) {
347 // Only eagerly type-decorate nodes with known input types.
348 // Other cases will generally require a proper fixpoint iteration with Run.
349 bool is_typed = NodeProperties::IsTyped(node);
350 if (is_typed || NodeProperties::AllValueInputsAreTyped(node)) {
351 Visitor typing(typer_, nullptr);
352 Type* type = typing.TypeNode(node);
353 if (is_typed) {
354 type = Type::Intersect(type, NodeProperties::GetType(node),
355 typer_->zone());
356 }
357 NodeProperties::SetType(node, type);
358 }
359 }
360 }
361
362
363 // -----------------------------------------------------------------------------
364
365 // Helper functions that lift a function f on types to a function on bounds,
366 // and uses that to type the given node. Note that f is never called with None
367 // as an argument.
368
369
TypeUnaryOp(Node * node,UnaryTyperFun f)370 Type* Typer::Visitor::TypeUnaryOp(Node* node, UnaryTyperFun f) {
371 Type* input = Operand(node, 0);
372 return input->IsInhabited() ? f(input, typer_) : Type::None();
373 }
374
375
TypeBinaryOp(Node * node,BinaryTyperFun f)376 Type* Typer::Visitor::TypeBinaryOp(Node* node, BinaryTyperFun f) {
377 Type* left = Operand(node, 0);
378 Type* right = Operand(node, 1);
379 return left->IsInhabited() && right->IsInhabited() ? f(left, right, typer_)
380 : Type::None();
381 }
382
383
Invert(Type * type,Typer * t)384 Type* Typer::Visitor::Invert(Type* type, Typer* t) {
385 DCHECK(type->Is(Type::Boolean()));
386 DCHECK(type->IsInhabited());
387 if (type->Is(t->singleton_false_)) return t->singleton_true_;
388 if (type->Is(t->singleton_true_)) return t->singleton_false_;
389 return type;
390 }
391
392
Invert(ComparisonOutcome outcome,Typer * t)393 Typer::Visitor::ComparisonOutcome Typer::Visitor::Invert(
394 ComparisonOutcome outcome, Typer* t) {
395 ComparisonOutcome result(0);
396 if ((outcome & kComparisonUndefined) != 0) result |= kComparisonUndefined;
397 if ((outcome & kComparisonTrue) != 0) result |= kComparisonFalse;
398 if ((outcome & kComparisonFalse) != 0) result |= kComparisonTrue;
399 return result;
400 }
401
402
FalsifyUndefined(ComparisonOutcome outcome,Typer * t)403 Type* Typer::Visitor::FalsifyUndefined(ComparisonOutcome outcome, Typer* t) {
404 if ((outcome & kComparisonFalse) != 0 ||
405 (outcome & kComparisonUndefined) != 0) {
406 return (outcome & kComparisonTrue) != 0 ? Type::Boolean()
407 : t->singleton_false_;
408 }
409 // Type should be non empty, so we know it should be true.
410 DCHECK((outcome & kComparisonTrue) != 0);
411 return t->singleton_true_;
412 }
413
414 // Type conversion.
415
ToPrimitive(Type * type,Typer * t)416 Type* Typer::Visitor::ToPrimitive(Type* type, Typer* t) {
417 if (type->Is(Type::Primitive()) && !type->Maybe(Type::Receiver())) {
418 return type;
419 }
420 return Type::Primitive();
421 }
422
423
ToBoolean(Type * type,Typer * t)424 Type* Typer::Visitor::ToBoolean(Type* type, Typer* t) {
425 if (type->Is(Type::Boolean())) return type;
426 if (type->Is(t->falsish_)) return t->singleton_false_;
427 if (type->Is(t->truish_)) return t->singleton_true_;
428 if (type->Is(Type::Number())) {
429 return t->operation_typer()->NumberToBoolean(type);
430 }
431 return Type::Boolean();
432 }
433
434
435 // static
ToInteger(Type * type,Typer * t)436 Type* Typer::Visitor::ToInteger(Type* type, Typer* t) {
437 // ES6 section 7.1.4 ToInteger ( argument )
438 type = ToNumber(type, t);
439 if (type->Is(t->cache_.kIntegerOrMinusZero)) return type;
440 if (type->Is(t->cache_.kIntegerOrMinusZeroOrNaN)) {
441 return Type::Union(
442 Type::Intersect(type, t->cache_.kIntegerOrMinusZero, t->zone()),
443 t->cache_.kSingletonZero, t->zone());
444 }
445 return t->cache_.kIntegerOrMinusZero;
446 }
447
448
449 // static
ToLength(Type * type,Typer * t)450 Type* Typer::Visitor::ToLength(Type* type, Typer* t) {
451 // ES6 section 7.1.15 ToLength ( argument )
452 type = ToInteger(type, t);
453 double min = type->Min();
454 double max = type->Max();
455 if (min <= 0.0) min = 0.0;
456 if (max > kMaxSafeInteger) max = kMaxSafeInteger;
457 if (max <= min) max = min;
458 return Type::Range(min, max, t->zone());
459 }
460
461
462 // static
ToName(Type * type,Typer * t)463 Type* Typer::Visitor::ToName(Type* type, Typer* t) {
464 // ES6 section 7.1.14 ToPropertyKey ( argument )
465 type = ToPrimitive(type, t);
466 if (type->Is(Type::Name())) return type;
467 if (type->Maybe(Type::Symbol())) return Type::Name();
468 return ToString(type, t);
469 }
470
471
472 // static
ToNumber(Type * type,Typer * t)473 Type* Typer::Visitor::ToNumber(Type* type, Typer* t) {
474 return t->operation_typer_.ToNumber(type);
475 }
476
477
478 // static
ToObject(Type * type,Typer * t)479 Type* Typer::Visitor::ToObject(Type* type, Typer* t) {
480 // ES6 section 7.1.13 ToObject ( argument )
481 if (type->Is(Type::Receiver())) return type;
482 if (type->Is(Type::Primitive())) return Type::OtherObject();
483 if (!type->Maybe(Type::OtherUndetectable())) {
484 return Type::DetectableReceiver();
485 }
486 return Type::Receiver();
487 }
488
489
490 // static
ToString(Type * type,Typer * t)491 Type* Typer::Visitor::ToString(Type* type, Typer* t) {
492 // ES6 section 7.1.12 ToString ( argument )
493 type = ToPrimitive(type, t);
494 if (type->Is(Type::String())) return type;
495 return Type::String();
496 }
497
498 // Type checks.
499
ObjectIsCallable(Type * type,Typer * t)500 Type* Typer::Visitor::ObjectIsCallable(Type* type, Typer* t) {
501 if (type->Is(Type::Function())) return t->singleton_true_;
502 if (type->Is(Type::Primitive())) return t->singleton_false_;
503 return Type::Boolean();
504 }
505
ObjectIsNumber(Type * type,Typer * t)506 Type* Typer::Visitor::ObjectIsNumber(Type* type, Typer* t) {
507 if (type->Is(Type::Number())) return t->singleton_true_;
508 if (!type->Maybe(Type::Number())) return t->singleton_false_;
509 return Type::Boolean();
510 }
511
512
ObjectIsReceiver(Type * type,Typer * t)513 Type* Typer::Visitor::ObjectIsReceiver(Type* type, Typer* t) {
514 if (type->Is(Type::Receiver())) return t->singleton_true_;
515 if (!type->Maybe(Type::Receiver())) return t->singleton_false_;
516 return Type::Boolean();
517 }
518
519
ObjectIsSmi(Type * type,Typer * t)520 Type* Typer::Visitor::ObjectIsSmi(Type* type, Typer* t) {
521 if (!type->Maybe(Type::SignedSmall())) return t->singleton_false_;
522 return Type::Boolean();
523 }
524
ObjectIsString(Type * type,Typer * t)525 Type* Typer::Visitor::ObjectIsString(Type* type, Typer* t) {
526 if (type->Is(Type::String())) return t->singleton_true_;
527 if (!type->Maybe(Type::String())) return t->singleton_false_;
528 return Type::Boolean();
529 }
530
ObjectIsUndetectable(Type * type,Typer * t)531 Type* Typer::Visitor::ObjectIsUndetectable(Type* type, Typer* t) {
532 if (type->Is(Type::Undetectable())) return t->singleton_true_;
533 if (!type->Maybe(Type::Undetectable())) return t->singleton_false_;
534 return Type::Boolean();
535 }
536
537
538 // -----------------------------------------------------------------------------
539
540
541 // Control operators.
542
TypeStart(Node * node)543 Type* Typer::Visitor::TypeStart(Node* node) { return Type::Internal(); }
544
TypeIfException(Node * node)545 Type* Typer::Visitor::TypeIfException(Node* node) {
546 return Type::NonInternal();
547 }
548
549 // Common operators.
550
TypeParameter(Node * node)551 Type* Typer::Visitor::TypeParameter(Node* node) {
552 Node* const start = node->InputAt(0);
553 DCHECK_EQ(IrOpcode::kStart, start->opcode());
554 int const parameter_count = start->op()->ValueOutputCount() - 4;
555 DCHECK_LE(1, parameter_count);
556 int const index = ParameterIndexOf(node->op());
557 if (index == Linkage::kJSCallClosureParamIndex) {
558 return Type::Function();
559 } else if (index == 0) {
560 if (typer_->flags() & Typer::kThisIsReceiver) {
561 return Type::Receiver();
562 } else {
563 // Parameter[this] can be the_hole for derived class constructors.
564 return Type::Union(Type::Hole(), Type::NonInternal(), typer_->zone());
565 }
566 } else if (index == Linkage::GetJSCallNewTargetParamIndex(parameter_count)) {
567 if (typer_->flags() & Typer::kNewTargetIsReceiver) {
568 return Type::Receiver();
569 } else {
570 return Type::Union(Type::Receiver(), Type::Undefined(), typer_->zone());
571 }
572 } else if (index == Linkage::GetJSCallArgCountParamIndex(parameter_count)) {
573 return Type::Range(0.0, Code::kMaxArguments, typer_->zone());
574 } else if (index == Linkage::GetJSCallContextParamIndex(parameter_count)) {
575 return Type::OtherInternal();
576 }
577 return Type::NonInternal();
578 }
579
TypeOsrValue(Node * node)580 Type* Typer::Visitor::TypeOsrValue(Node* node) { return Type::Any(); }
581
TypeOsrGuard(Node * node)582 Type* Typer::Visitor::TypeOsrGuard(Node* node) {
583 switch (OsrGuardTypeOf(node->op())) {
584 case OsrGuardType::kUninitialized:
585 return Type::None();
586 case OsrGuardType::kSignedSmall:
587 return Type::SignedSmall();
588 case OsrGuardType::kAny:
589 return Type::Any();
590 }
591 UNREACHABLE();
592 return nullptr;
593 }
594
TypeRetain(Node * node)595 Type* Typer::Visitor::TypeRetain(Node* node) {
596 UNREACHABLE();
597 return nullptr;
598 }
599
TypeInt32Constant(Node * node)600 Type* Typer::Visitor::TypeInt32Constant(Node* node) {
601 UNREACHABLE();
602 return nullptr;
603 }
604
TypeInt64Constant(Node * node)605 Type* Typer::Visitor::TypeInt64Constant(Node* node) {
606 UNREACHABLE();
607 return nullptr;
608 }
609
TypeRelocatableInt32Constant(Node * node)610 Type* Typer::Visitor::TypeRelocatableInt32Constant(Node* node) {
611 UNREACHABLE();
612 return nullptr;
613 }
614
TypeRelocatableInt64Constant(Node * node)615 Type* Typer::Visitor::TypeRelocatableInt64Constant(Node* node) {
616 UNREACHABLE();
617 return nullptr;
618 }
619
TypeFloat32Constant(Node * node)620 Type* Typer::Visitor::TypeFloat32Constant(Node* node) {
621 UNREACHABLE();
622 return nullptr;
623 }
624
TypeFloat64Constant(Node * node)625 Type* Typer::Visitor::TypeFloat64Constant(Node* node) {
626 UNREACHABLE();
627 return nullptr;
628 }
629
TypeNumberConstant(Node * node)630 Type* Typer::Visitor::TypeNumberConstant(Node* node) {
631 double number = OpParameter<double>(node);
632 return Type::NewConstant(number, zone());
633 }
634
TypeHeapConstant(Node * node)635 Type* Typer::Visitor::TypeHeapConstant(Node* node) {
636 return TypeConstant(OpParameter<Handle<HeapObject>>(node));
637 }
638
TypeExternalConstant(Node * node)639 Type* Typer::Visitor::TypeExternalConstant(Node* node) {
640 return Type::ExternalPointer();
641 }
642
TypePointerConstant(Node * node)643 Type* Typer::Visitor::TypePointerConstant(Node* node) {
644 return Type::ExternalPointer();
645 }
646
TypeSelect(Node * node)647 Type* Typer::Visitor::TypeSelect(Node* node) {
648 return Type::Union(Operand(node, 1), Operand(node, 2), zone());
649 }
650
TypePhi(Node * node)651 Type* Typer::Visitor::TypePhi(Node* node) {
652 int arity = node->op()->ValueInputCount();
653 Type* type = Operand(node, 0);
654 for (int i = 1; i < arity; ++i) {
655 type = Type::Union(type, Operand(node, i), zone());
656 }
657 return type;
658 }
659
TypeInductionVariablePhi(Node * node)660 Type* Typer::Visitor::TypeInductionVariablePhi(Node* node) {
661 int arity = NodeProperties::GetControlInput(node)->op()->ControlInputCount();
662 DCHECK_EQ(IrOpcode::kLoop, NodeProperties::GetControlInput(node)->opcode());
663 DCHECK_EQ(2, NodeProperties::GetControlInput(node)->InputCount());
664
665 Type* initial_type = Operand(node, 0);
666 Type* increment_type = Operand(node, 2);
667
668 // We only handle integer induction variables (otherwise ranges
669 // do not apply and we cannot do anything).
670 if (!initial_type->Is(typer_->cache_.kInteger) ||
671 !increment_type->Is(typer_->cache_.kInteger)) {
672 // Fallback to normal phi typing, but ensure monotonicity.
673 // (Unfortunately, without baking in the previous type, monotonicity might
674 // be violated because we might not yet have retyped the incrementing
675 // operation even though the increment's type might been already reflected
676 // in the induction variable phi.)
677 Type* type = NodeProperties::IsTyped(node) ? NodeProperties::GetType(node)
678 : Type::None();
679 for (int i = 0; i < arity; ++i) {
680 type = Type::Union(type, Operand(node, i), zone());
681 }
682 return type;
683 }
684 // If we do not have enough type information for the initial value or
685 // the increment, just return the initial value's type.
686 if (!initial_type->IsInhabited() ||
687 increment_type->Is(typer_->cache_.kSingletonZero)) {
688 return initial_type;
689 }
690
691 // Now process the bounds.
692 auto res = induction_vars_->induction_variables().find(node->id());
693 DCHECK(res != induction_vars_->induction_variables().end());
694 InductionVariable* induction_var = res->second;
695
696 InductionVariable::ArithmeticType arithmetic_type = induction_var->Type();
697
698 double min = -V8_INFINITY;
699 double max = V8_INFINITY;
700
701 double increment_min;
702 double increment_max;
703 if (arithmetic_type == InductionVariable::ArithmeticType::kAddition) {
704 increment_min = increment_type->Min();
705 increment_max = increment_type->Max();
706 } else {
707 DCHECK(arithmetic_type == InductionVariable::ArithmeticType::kSubtraction);
708 increment_min = -increment_type->Max();
709 increment_max = -increment_type->Min();
710 }
711
712 if (increment_min >= 0) {
713 // increasing sequence
714 min = initial_type->Min();
715 for (auto bound : induction_var->upper_bounds()) {
716 Type* bound_type = TypeOrNone(bound.bound);
717 // If the type is not an integer, just skip the bound.
718 if (!bound_type->Is(typer_->cache_.kInteger)) continue;
719 // If the type is not inhabited, then we can take the initial value.
720 if (!bound_type->IsInhabited()) {
721 max = initial_type->Max();
722 break;
723 }
724 double bound_max = bound_type->Max();
725 if (bound.kind == InductionVariable::kStrict) {
726 bound_max -= 1;
727 }
728 max = std::min(max, bound_max + increment_max);
729 }
730 // The upper bound must be at least the initial value's upper bound.
731 max = std::max(max, initial_type->Max());
732 } else if (increment_max <= 0) {
733 // decreasing sequence
734 max = initial_type->Max();
735 for (auto bound : induction_var->lower_bounds()) {
736 Type* bound_type = TypeOrNone(bound.bound);
737 // If the type is not an integer, just skip the bound.
738 if (!bound_type->Is(typer_->cache_.kInteger)) continue;
739 // If the type is not inhabited, then we can take the initial value.
740 if (!bound_type->IsInhabited()) {
741 min = initial_type->Min();
742 break;
743 }
744 double bound_min = bound_type->Min();
745 if (bound.kind == InductionVariable::kStrict) {
746 bound_min += 1;
747 }
748 min = std::max(min, bound_min + increment_min);
749 }
750 // The lower bound must be at most the initial value's lower bound.
751 min = std::min(min, initial_type->Min());
752 } else {
753 // Shortcut: If the increment can be both positive and negative,
754 // the variable can go arbitrarily far, so just return integer.
755 return typer_->cache_.kInteger;
756 }
757 if (FLAG_trace_turbo_loop) {
758 OFStream os(stdout);
759 os << std::setprecision(10);
760 os << "Loop (" << NodeProperties::GetControlInput(node)->id()
761 << ") variable bounds in "
762 << (arithmetic_type == InductionVariable::ArithmeticType::kAddition
763 ? "addition"
764 : "subtraction")
765 << " for phi " << node->id() << ": (" << min << ", " << max << ")\n";
766 }
767 return Type::Range(min, max, typer_->zone());
768 }
769
TypeEffectPhi(Node * node)770 Type* Typer::Visitor::TypeEffectPhi(Node* node) {
771 UNREACHABLE();
772 return nullptr;
773 }
774
TypeLoopExit(Node * node)775 Type* Typer::Visitor::TypeLoopExit(Node* node) {
776 UNREACHABLE();
777 return nullptr;
778 }
779
TypeLoopExitValue(Node * node)780 Type* Typer::Visitor::TypeLoopExitValue(Node* node) { return Operand(node, 0); }
781
TypeLoopExitEffect(Node * node)782 Type* Typer::Visitor::TypeLoopExitEffect(Node* node) {
783 UNREACHABLE();
784 return nullptr;
785 }
786
TypeEnsureWritableFastElements(Node * node)787 Type* Typer::Visitor::TypeEnsureWritableFastElements(Node* node) {
788 return Operand(node, 1);
789 }
790
TypeMaybeGrowFastElements(Node * node)791 Type* Typer::Visitor::TypeMaybeGrowFastElements(Node* node) {
792 return Operand(node, 1);
793 }
794
TypeTransitionElementsKind(Node * node)795 Type* Typer::Visitor::TypeTransitionElementsKind(Node* node) {
796 UNREACHABLE();
797 return nullptr;
798 }
799
TypeCheckpoint(Node * node)800 Type* Typer::Visitor::TypeCheckpoint(Node* node) {
801 UNREACHABLE();
802 return nullptr;
803 }
804
TypeBeginRegion(Node * node)805 Type* Typer::Visitor::TypeBeginRegion(Node* node) {
806 UNREACHABLE();
807 return nullptr;
808 }
809
810
TypeFinishRegion(Node * node)811 Type* Typer::Visitor::TypeFinishRegion(Node* node) { return Operand(node, 0); }
812
813
TypeFrameState(Node * node)814 Type* Typer::Visitor::TypeFrameState(Node* node) {
815 // TODO(rossberg): Ideally FrameState wouldn't have a value output.
816 return Type::Internal();
817 }
818
TypeStateValues(Node * node)819 Type* Typer::Visitor::TypeStateValues(Node* node) { return Type::Internal(); }
820
TypeTypedStateValues(Node * node)821 Type* Typer::Visitor::TypeTypedStateValues(Node* node) {
822 return Type::Internal();
823 }
824
TypeObjectState(Node * node)825 Type* Typer::Visitor::TypeObjectState(Node* node) { return Type::Internal(); }
826
TypeTypedObjectState(Node * node)827 Type* Typer::Visitor::TypeTypedObjectState(Node* node) {
828 return Type::Internal();
829 }
830
TypeCall(Node * node)831 Type* Typer::Visitor::TypeCall(Node* node) { return Type::Any(); }
832
833
TypeProjection(Node * node)834 Type* Typer::Visitor::TypeProjection(Node* node) {
835 Type* const type = Operand(node, 0);
836 if (type->Is(Type::None())) return Type::None();
837 int const index = static_cast<int>(ProjectionIndexOf(node->op()));
838 if (type->IsTuple() && index < type->AsTuple()->Arity()) {
839 return type->AsTuple()->Element(index);
840 }
841 return Type::Any();
842 }
843
TypeTypeGuard(Node * node)844 Type* Typer::Visitor::TypeTypeGuard(Node* node) {
845 Type* const type = Operand(node, 0);
846 return typer_->operation_typer()->TypeTypeGuard(node->op(), type);
847 }
848
TypeDead(Node * node)849 Type* Typer::Visitor::TypeDead(Node* node) { return Type::None(); }
850
851 // JS comparison operators.
852
853
JSEqualTyper(Type * lhs,Type * rhs,Typer * t)854 Type* Typer::Visitor::JSEqualTyper(Type* lhs, Type* rhs, Typer* t) {
855 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return t->singleton_false_;
856 if (lhs->Is(Type::NullOrUndefined()) && rhs->Is(Type::NullOrUndefined())) {
857 return t->singleton_true_;
858 }
859 if (lhs->Is(Type::Number()) && rhs->Is(Type::Number()) &&
860 (lhs->Max() < rhs->Min() || lhs->Min() > rhs->Max())) {
861 return t->singleton_false_;
862 }
863 if (lhs->IsHeapConstant() && rhs->Is(lhs)) {
864 // Types are equal and are inhabited only by a single semantic value,
865 // which is not nan due to the earlier check.
866 return t->singleton_true_;
867 }
868 return Type::Boolean();
869 }
870
871
JSNotEqualTyper(Type * lhs,Type * rhs,Typer * t)872 Type* Typer::Visitor::JSNotEqualTyper(Type* lhs, Type* rhs, Typer* t) {
873 return Invert(JSEqualTyper(lhs, rhs, t), t);
874 }
875
876
JSType(Type * type)877 static Type* JSType(Type* type) {
878 if (type->Is(Type::Boolean())) return Type::Boolean();
879 if (type->Is(Type::String())) return Type::String();
880 if (type->Is(Type::Number())) return Type::Number();
881 if (type->Is(Type::Undefined())) return Type::Undefined();
882 if (type->Is(Type::Null())) return Type::Null();
883 if (type->Is(Type::Symbol())) return Type::Symbol();
884 if (type->Is(Type::Receiver())) return Type::Receiver(); // JS "Object"
885 return Type::Any();
886 }
887
888
JSStrictEqualTyper(Type * lhs,Type * rhs,Typer * t)889 Type* Typer::Visitor::JSStrictEqualTyper(Type* lhs, Type* rhs, Typer* t) {
890 if (!JSType(lhs)->Maybe(JSType(rhs))) return t->singleton_false_;
891 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return t->singleton_false_;
892 if (lhs->Is(Type::Number()) && rhs->Is(Type::Number()) &&
893 (lhs->Max() < rhs->Min() || lhs->Min() > rhs->Max())) {
894 return t->singleton_false_;
895 }
896 if ((lhs->Is(t->singleton_the_hole_) || rhs->Is(t->singleton_the_hole_)) &&
897 !lhs->Maybe(rhs)) {
898 return t->singleton_false_;
899 }
900 if (lhs->IsHeapConstant() && rhs->Is(lhs)) {
901 // Types are equal and are inhabited only by a single semantic value,
902 // which is not nan due to the earlier check.
903 return t->singleton_true_;
904 }
905 return Type::Boolean();
906 }
907
908
JSStrictNotEqualTyper(Type * lhs,Type * rhs,Typer * t)909 Type* Typer::Visitor::JSStrictNotEqualTyper(Type* lhs, Type* rhs, Typer* t) {
910 return Invert(JSStrictEqualTyper(lhs, rhs, t), t);
911 }
912
913
914 // The EcmaScript specification defines the four relational comparison operators
915 // (<, <=, >=, >) with the help of a single abstract one. It behaves like <
916 // but returns undefined when the inputs cannot be compared.
917 // We implement the typing analogously.
JSCompareTyper(Type * lhs,Type * rhs,Typer * t)918 Typer::Visitor::ComparisonOutcome Typer::Visitor::JSCompareTyper(Type* lhs,
919 Type* rhs,
920 Typer* t) {
921 lhs = ToPrimitive(lhs, t);
922 rhs = ToPrimitive(rhs, t);
923 if (lhs->Maybe(Type::String()) && rhs->Maybe(Type::String())) {
924 return ComparisonOutcome(kComparisonTrue) |
925 ComparisonOutcome(kComparisonFalse);
926 }
927 lhs = ToNumber(lhs, t);
928 rhs = ToNumber(rhs, t);
929
930 // Shortcut for NaNs.
931 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return kComparisonUndefined;
932
933 ComparisonOutcome result;
934 if (lhs->IsHeapConstant() && rhs->Is(lhs)) {
935 // Types are equal and are inhabited only by a single semantic value.
936 result = kComparisonFalse;
937 } else if (lhs->Min() >= rhs->Max()) {
938 result = kComparisonFalse;
939 } else if (lhs->Max() < rhs->Min()) {
940 result = kComparisonTrue;
941 } else {
942 // We cannot figure out the result, return both true and false. (We do not
943 // have to return undefined because that cannot affect the result of
944 // FalsifyUndefined.)
945 return ComparisonOutcome(kComparisonTrue) |
946 ComparisonOutcome(kComparisonFalse);
947 }
948 // Add the undefined if we could see NaN.
949 if (lhs->Maybe(Type::NaN()) || rhs->Maybe(Type::NaN())) {
950 result |= kComparisonUndefined;
951 }
952 return result;
953 }
954
955
JSLessThanTyper(Type * lhs,Type * rhs,Typer * t)956 Type* Typer::Visitor::JSLessThanTyper(Type* lhs, Type* rhs, Typer* t) {
957 return FalsifyUndefined(JSCompareTyper(lhs, rhs, t), t);
958 }
959
960
JSGreaterThanTyper(Type * lhs,Type * rhs,Typer * t)961 Type* Typer::Visitor::JSGreaterThanTyper(Type* lhs, Type* rhs, Typer* t) {
962 return FalsifyUndefined(JSCompareTyper(rhs, lhs, t), t);
963 }
964
965
JSLessThanOrEqualTyper(Type * lhs,Type * rhs,Typer * t)966 Type* Typer::Visitor::JSLessThanOrEqualTyper(Type* lhs, Type* rhs, Typer* t) {
967 return FalsifyUndefined(Invert(JSCompareTyper(rhs, lhs, t), t), t);
968 }
969
970
JSGreaterThanOrEqualTyper(Type * lhs,Type * rhs,Typer * t)971 Type* Typer::Visitor::JSGreaterThanOrEqualTyper(
972 Type* lhs, Type* rhs, Typer* t) {
973 return FalsifyUndefined(Invert(JSCompareTyper(lhs, rhs, t), t), t);
974 }
975
976 // JS bitwise operators.
977
978
JSBitwiseOrTyper(Type * lhs,Type * rhs,Typer * t)979 Type* Typer::Visitor::JSBitwiseOrTyper(Type* lhs, Type* rhs, Typer* t) {
980 return NumberBitwiseOr(ToNumber(lhs, t), ToNumber(rhs, t), t);
981 }
982
983
JSBitwiseAndTyper(Type * lhs,Type * rhs,Typer * t)984 Type* Typer::Visitor::JSBitwiseAndTyper(Type* lhs, Type* rhs, Typer* t) {
985 return NumberBitwiseAnd(ToNumber(lhs, t), ToNumber(rhs, t), t);
986 }
987
988
JSBitwiseXorTyper(Type * lhs,Type * rhs,Typer * t)989 Type* Typer::Visitor::JSBitwiseXorTyper(Type* lhs, Type* rhs, Typer* t) {
990 return NumberBitwiseXor(ToNumber(lhs, t), ToNumber(rhs, t), t);
991 }
992
993
JSShiftLeftTyper(Type * lhs,Type * rhs,Typer * t)994 Type* Typer::Visitor::JSShiftLeftTyper(Type* lhs, Type* rhs, Typer* t) {
995 return NumberShiftLeft(ToNumber(lhs, t), ToNumber(rhs, t), t);
996 }
997
998
JSShiftRightTyper(Type * lhs,Type * rhs,Typer * t)999 Type* Typer::Visitor::JSShiftRightTyper(Type* lhs, Type* rhs, Typer* t) {
1000 return NumberShiftRight(ToNumber(lhs, t), ToNumber(rhs, t), t);
1001 }
1002
1003
JSShiftRightLogicalTyper(Type * lhs,Type * rhs,Typer * t)1004 Type* Typer::Visitor::JSShiftRightLogicalTyper(Type* lhs, Type* rhs, Typer* t) {
1005 return NumberShiftRightLogical(ToNumber(lhs, t), ToNumber(rhs, t), t);
1006 }
1007
1008
1009 // JS arithmetic operators.
1010
JSAddTyper(Type * lhs,Type * rhs,Typer * t)1011 Type* Typer::Visitor::JSAddTyper(Type* lhs, Type* rhs, Typer* t) {
1012 lhs = ToPrimitive(lhs, t);
1013 rhs = ToPrimitive(rhs, t);
1014 if (lhs->Maybe(Type::String()) || rhs->Maybe(Type::String())) {
1015 if (lhs->Is(Type::String()) || rhs->Is(Type::String())) {
1016 return Type::String();
1017 } else {
1018 return Type::NumberOrString();
1019 }
1020 }
1021 // The addition must be numeric.
1022 return NumberAdd(ToNumber(lhs, t), ToNumber(rhs, t), t);
1023 }
1024
JSSubtractTyper(Type * lhs,Type * rhs,Typer * t)1025 Type* Typer::Visitor::JSSubtractTyper(Type* lhs, Type* rhs, Typer* t) {
1026 return NumberSubtract(ToNumber(lhs, t), ToNumber(rhs, t), t);
1027 }
1028
JSMultiplyTyper(Type * lhs,Type * rhs,Typer * t)1029 Type* Typer::Visitor::JSMultiplyTyper(Type* lhs, Type* rhs, Typer* t) {
1030 return NumberMultiply(ToNumber(lhs, t), ToNumber(rhs, t), t);
1031 }
1032
JSDivideTyper(Type * lhs,Type * rhs,Typer * t)1033 Type* Typer::Visitor::JSDivideTyper(Type* lhs, Type* rhs, Typer* t) {
1034 return NumberDivide(ToNumber(lhs, t), ToNumber(rhs, t), t);
1035 }
1036
JSModulusTyper(Type * lhs,Type * rhs,Typer * t)1037 Type* Typer::Visitor::JSModulusTyper(Type* lhs, Type* rhs, Typer* t) {
1038 return NumberModulus(ToNumber(lhs, t), ToNumber(rhs, t), t);
1039 }
1040
1041
1042 // JS unary operators.
1043
1044
TypeJSTypeOf(Node * node)1045 Type* Typer::Visitor::TypeJSTypeOf(Node* node) {
1046 return Type::InternalizedString();
1047 }
1048
1049
1050 // JS conversion operators.
1051
1052
TypeJSToBoolean(Node * node)1053 Type* Typer::Visitor::TypeJSToBoolean(Node* node) {
1054 return TypeUnaryOp(node, ToBoolean);
1055 }
1056
TypeJSToInteger(Node * node)1057 Type* Typer::Visitor::TypeJSToInteger(Node* node) {
1058 return TypeUnaryOp(node, ToInteger);
1059 }
1060
TypeJSToLength(Node * node)1061 Type* Typer::Visitor::TypeJSToLength(Node* node) {
1062 return TypeUnaryOp(node, ToLength);
1063 }
1064
TypeJSToName(Node * node)1065 Type* Typer::Visitor::TypeJSToName(Node* node) {
1066 return TypeUnaryOp(node, ToName);
1067 }
1068
TypeJSToNumber(Node * node)1069 Type* Typer::Visitor::TypeJSToNumber(Node* node) {
1070 return TypeUnaryOp(node, ToNumber);
1071 }
1072
TypeJSToObject(Node * node)1073 Type* Typer::Visitor::TypeJSToObject(Node* node) {
1074 return TypeUnaryOp(node, ToObject);
1075 }
1076
TypeJSToString(Node * node)1077 Type* Typer::Visitor::TypeJSToString(Node* node) {
1078 return TypeUnaryOp(node, ToString);
1079 }
1080
1081 // JS object operators.
1082
1083
TypeJSCreate(Node * node)1084 Type* Typer::Visitor::TypeJSCreate(Node* node) { return Type::Object(); }
1085
1086
TypeJSCreateArguments(Node * node)1087 Type* Typer::Visitor::TypeJSCreateArguments(Node* node) {
1088 return Type::OtherObject();
1089 }
1090
1091
TypeJSCreateArray(Node * node)1092 Type* Typer::Visitor::TypeJSCreateArray(Node* node) {
1093 return Type::OtherObject();
1094 }
1095
1096
TypeJSCreateClosure(Node * node)1097 Type* Typer::Visitor::TypeJSCreateClosure(Node* node) {
1098 return Type::Function();
1099 }
1100
1101
TypeJSCreateIterResultObject(Node * node)1102 Type* Typer::Visitor::TypeJSCreateIterResultObject(Node* node) {
1103 return Type::OtherObject();
1104 }
1105
TypeJSCreateKeyValueArray(Node * node)1106 Type* Typer::Visitor::TypeJSCreateKeyValueArray(Node* node) {
1107 return Type::OtherObject();
1108 }
1109
TypeJSCreateLiteralArray(Node * node)1110 Type* Typer::Visitor::TypeJSCreateLiteralArray(Node* node) {
1111 return Type::OtherObject();
1112 }
1113
1114
TypeJSCreateLiteralObject(Node * node)1115 Type* Typer::Visitor::TypeJSCreateLiteralObject(Node* node) {
1116 return Type::OtherObject();
1117 }
1118
1119
TypeJSCreateLiteralRegExp(Node * node)1120 Type* Typer::Visitor::TypeJSCreateLiteralRegExp(Node* node) {
1121 return Type::OtherObject();
1122 }
1123
1124
TypeJSLoadProperty(Node * node)1125 Type* Typer::Visitor::TypeJSLoadProperty(Node* node) {
1126 return Type::NonInternal();
1127 }
1128
1129
TypeJSLoadNamed(Node * node)1130 Type* Typer::Visitor::TypeJSLoadNamed(Node* node) {
1131 return Type::NonInternal();
1132 }
1133
TypeJSLoadGlobal(Node * node)1134 Type* Typer::Visitor::TypeJSLoadGlobal(Node* node) {
1135 return Type::NonInternal();
1136 }
1137
1138 // Returns a somewhat larger range if we previously assigned
1139 // a (smaller) range to this node. This is used to speed up
1140 // the fixpoint calculation in case there appears to be a loop
1141 // in the graph. In the current implementation, we are
1142 // increasing the limits to the closest power of two.
Weaken(Node * node,Type * current_type,Type * previous_type)1143 Type* Typer::Visitor::Weaken(Node* node, Type* current_type,
1144 Type* previous_type) {
1145 static const double kWeakenMinLimits[] = {
1146 0.0, -1073741824.0, -2147483648.0, -4294967296.0, -8589934592.0,
1147 -17179869184.0, -34359738368.0, -68719476736.0, -137438953472.0,
1148 -274877906944.0, -549755813888.0, -1099511627776.0, -2199023255552.0,
1149 -4398046511104.0, -8796093022208.0, -17592186044416.0, -35184372088832.0,
1150 -70368744177664.0, -140737488355328.0, -281474976710656.0,
1151 -562949953421312.0};
1152 static const double kWeakenMaxLimits[] = {
1153 0.0, 1073741823.0, 2147483647.0, 4294967295.0, 8589934591.0,
1154 17179869183.0, 34359738367.0, 68719476735.0, 137438953471.0,
1155 274877906943.0, 549755813887.0, 1099511627775.0, 2199023255551.0,
1156 4398046511103.0, 8796093022207.0, 17592186044415.0, 35184372088831.0,
1157 70368744177663.0, 140737488355327.0, 281474976710655.0,
1158 562949953421311.0};
1159 STATIC_ASSERT(arraysize(kWeakenMinLimits) == arraysize(kWeakenMaxLimits));
1160
1161 // If the types have nothing to do with integers, return the types.
1162 Type* const integer = typer_->cache_.kInteger;
1163 if (!previous_type->Maybe(integer)) {
1164 return current_type;
1165 }
1166 DCHECK(current_type->Maybe(integer));
1167
1168 Type* current_integer = Type::Intersect(current_type, integer, zone());
1169 Type* previous_integer = Type::Intersect(previous_type, integer, zone());
1170
1171 // Once we start weakening a node, we should always weaken.
1172 if (!IsWeakened(node->id())) {
1173 // Only weaken if there is range involved; we should converge quickly
1174 // for all other types (the exception is a union of many constants,
1175 // but we currently do not increase the number of constants in unions).
1176 Type* previous = previous_integer->GetRange();
1177 Type* current = current_integer->GetRange();
1178 if (current == nullptr || previous == nullptr) {
1179 return current_type;
1180 }
1181 // Range is involved => we are weakening.
1182 SetWeakened(node->id());
1183 }
1184
1185 double current_min = current_integer->Min();
1186 double new_min = current_min;
1187 // Find the closest lower entry in the list of allowed
1188 // minima (or negative infinity if there is no such entry).
1189 if (current_min != previous_integer->Min()) {
1190 new_min = -V8_INFINITY;
1191 for (double const min : kWeakenMinLimits) {
1192 if (min <= current_min) {
1193 new_min = min;
1194 break;
1195 }
1196 }
1197 }
1198
1199 double current_max = current_integer->Max();
1200 double new_max = current_max;
1201 // Find the closest greater entry in the list of allowed
1202 // maxima (or infinity if there is no such entry).
1203 if (current_max != previous_integer->Max()) {
1204 new_max = V8_INFINITY;
1205 for (double const max : kWeakenMaxLimits) {
1206 if (max >= current_max) {
1207 new_max = max;
1208 break;
1209 }
1210 }
1211 }
1212
1213 return Type::Union(current_type,
1214 Type::Range(new_min, new_max, typer_->zone()),
1215 typer_->zone());
1216 }
1217
1218
TypeJSStoreProperty(Node * node)1219 Type* Typer::Visitor::TypeJSStoreProperty(Node* node) {
1220 UNREACHABLE();
1221 return nullptr;
1222 }
1223
1224
TypeJSStoreNamed(Node * node)1225 Type* Typer::Visitor::TypeJSStoreNamed(Node* node) {
1226 UNREACHABLE();
1227 return nullptr;
1228 }
1229
1230
TypeJSStoreGlobal(Node * node)1231 Type* Typer::Visitor::TypeJSStoreGlobal(Node* node) {
1232 UNREACHABLE();
1233 return nullptr;
1234 }
1235
1236
TypeJSDeleteProperty(Node * node)1237 Type* Typer::Visitor::TypeJSDeleteProperty(Node* node) {
1238 return Type::Boolean();
1239 }
1240
TypeJSHasProperty(Node * node)1241 Type* Typer::Visitor::TypeJSHasProperty(Node* node) { return Type::Boolean(); }
1242
TypeJSInstanceOf(Node * node)1243 Type* Typer::Visitor::TypeJSInstanceOf(Node* node) { return Type::Boolean(); }
1244
TypeJSOrdinaryHasInstance(Node * node)1245 Type* Typer::Visitor::TypeJSOrdinaryHasInstance(Node* node) {
1246 return Type::Boolean();
1247 }
1248
1249 // JS context operators.
1250
1251
TypeJSLoadContext(Node * node)1252 Type* Typer::Visitor::TypeJSLoadContext(Node* node) {
1253 ContextAccess const& access = ContextAccessOf(node->op());
1254 switch (access.index()) {
1255 case Context::PREVIOUS_INDEX:
1256 case Context::NATIVE_CONTEXT_INDEX:
1257 return Type::OtherInternal();
1258 case Context::CLOSURE_INDEX:
1259 return Type::Function();
1260 default:
1261 return Type::Any();
1262 }
1263 }
1264
1265
TypeJSStoreContext(Node * node)1266 Type* Typer::Visitor::TypeJSStoreContext(Node* node) {
1267 UNREACHABLE();
1268 return nullptr;
1269 }
1270
1271
TypeJSCreateFunctionContext(Node * node)1272 Type* Typer::Visitor::TypeJSCreateFunctionContext(Node* node) {
1273 return Type::OtherInternal();
1274 }
1275
TypeJSCreateCatchContext(Node * node)1276 Type* Typer::Visitor::TypeJSCreateCatchContext(Node* node) {
1277 return Type::OtherInternal();
1278 }
1279
TypeJSCreateWithContext(Node * node)1280 Type* Typer::Visitor::TypeJSCreateWithContext(Node* node) {
1281 return Type::OtherInternal();
1282 }
1283
TypeJSCreateBlockContext(Node * node)1284 Type* Typer::Visitor::TypeJSCreateBlockContext(Node* node) {
1285 return Type::OtherInternal();
1286 }
1287
TypeJSCreateScriptContext(Node * node)1288 Type* Typer::Visitor::TypeJSCreateScriptContext(Node* node) {
1289 return Type::OtherInternal();
1290 }
1291
1292 // JS other operators.
1293
1294
TypeJSCallConstruct(Node * node)1295 Type* Typer::Visitor::TypeJSCallConstruct(Node* node) {
1296 return Type::Receiver();
1297 }
1298
JSCallFunctionTyper(Type * fun,Typer * t)1299 Type* Typer::Visitor::JSCallFunctionTyper(Type* fun, Typer* t) {
1300 if (fun->IsHeapConstant() && fun->AsHeapConstant()->Value()->IsJSFunction()) {
1301 Handle<JSFunction> function =
1302 Handle<JSFunction>::cast(fun->AsHeapConstant()->Value());
1303 if (function->shared()->HasBuiltinFunctionId()) {
1304 switch (function->shared()->builtin_function_id()) {
1305 case kMathRandom:
1306 return Type::PlainNumber();
1307 case kMathFloor:
1308 case kMathCeil:
1309 case kMathRound:
1310 case kMathTrunc:
1311 return t->cache_.kIntegerOrMinusZeroOrNaN;
1312 // Unary math functions.
1313 case kMathAbs:
1314 case kMathExp:
1315 case kMathExpm1:
1316 return Type::Union(Type::PlainNumber(), Type::NaN(), t->zone());
1317 case kMathAcos:
1318 case kMathAcosh:
1319 case kMathAsin:
1320 case kMathAsinh:
1321 case kMathAtan:
1322 case kMathAtanh:
1323 case kMathCbrt:
1324 case kMathCos:
1325 case kMathFround:
1326 case kMathLog:
1327 case kMathLog1p:
1328 case kMathLog10:
1329 case kMathLog2:
1330 case kMathSin:
1331 case kMathSqrt:
1332 case kMathTan:
1333 return Type::Number();
1334 case kMathSign:
1335 return t->cache_.kMinusOneToOneOrMinusZeroOrNaN;
1336 // Binary math functions.
1337 case kMathAtan2:
1338 case kMathPow:
1339 case kMathMax:
1340 case kMathMin:
1341 return Type::Number();
1342 case kMathImul:
1343 return Type::Signed32();
1344 case kMathClz32:
1345 return t->cache_.kZeroToThirtyTwo;
1346 // Date functions.
1347 case kDateGetDate:
1348 return t->cache_.kJSDateDayType;
1349 case kDateGetDay:
1350 return t->cache_.kJSDateWeekdayType;
1351 case kDateGetFullYear:
1352 return t->cache_.kJSDateYearType;
1353 case kDateGetHours:
1354 return t->cache_.kJSDateHourType;
1355 case kDateGetMilliseconds:
1356 return Type::Union(Type::Range(0.0, 999.0, t->zone()), Type::NaN(),
1357 t->zone());
1358 case kDateGetMinutes:
1359 return t->cache_.kJSDateMinuteType;
1360 case kDateGetMonth:
1361 return t->cache_.kJSDateMonthType;
1362 case kDateGetSeconds:
1363 return t->cache_.kJSDateSecondType;
1364 case kDateGetTime:
1365 return t->cache_.kJSDateValueType;
1366 // Number functions.
1367 case kNumberIsFinite:
1368 case kNumberIsInteger:
1369 case kNumberIsNaN:
1370 case kNumberIsSafeInteger:
1371 return Type::Boolean();
1372 case kNumberParseFloat:
1373 return Type::Number();
1374 case kNumberParseInt:
1375 return t->cache_.kIntegerOrMinusZeroOrNaN;
1376 case kNumberToString:
1377 return Type::String();
1378 // String functions.
1379 case kStringCharCodeAt:
1380 return Type::Union(Type::Range(0, kMaxUInt16, t->zone()), Type::NaN(),
1381 t->zone());
1382 case kStringCharAt:
1383 case kStringConcat:
1384 case kStringFromCharCode:
1385 case kStringSubstr:
1386 case kStringToLowerCase:
1387 case kStringToUpperCase:
1388 return Type::String();
1389
1390 case kStringIterator:
1391 case kStringIteratorNext:
1392 return Type::OtherObject();
1393
1394 case kArrayEntries:
1395 case kArrayKeys:
1396 case kArrayValues:
1397 case kTypedArrayEntries:
1398 case kTypedArrayKeys:
1399 case kTypedArrayValues:
1400 case kArrayIteratorNext:
1401 return Type::OtherObject();
1402
1403 // Array functions.
1404 case kArrayIndexOf:
1405 case kArrayLastIndexOf:
1406 return Type::Range(-1, kMaxSafeInteger, t->zone());
1407 case kArrayPush:
1408 return t->cache_.kPositiveSafeInteger;
1409
1410 // Object functions.
1411 case kObjectHasOwnProperty:
1412 return Type::Boolean();
1413
1414 // Function functions.
1415 case kFunctionHasInstance:
1416 return Type::Boolean();
1417
1418 // Global functions.
1419 case kGlobalDecodeURI:
1420 case kGlobalDecodeURIComponent:
1421 case kGlobalEncodeURI:
1422 case kGlobalEncodeURIComponent:
1423 case kGlobalEscape:
1424 case kGlobalUnescape:
1425 return Type::String();
1426 case kGlobalIsFinite:
1427 case kGlobalIsNaN:
1428 return Type::Boolean();
1429 default:
1430 break;
1431 }
1432 }
1433 }
1434 return Type::NonInternal();
1435 }
1436
1437
TypeJSCallFunction(Node * node)1438 Type* Typer::Visitor::TypeJSCallFunction(Node* node) {
1439 // TODO(bmeurer): We could infer better types if we wouldn't ignore the
1440 // argument types for the JSCallFunctionTyper above.
1441 return TypeUnaryOp(node, JSCallFunctionTyper);
1442 }
1443
1444
TypeJSCallRuntime(Node * node)1445 Type* Typer::Visitor::TypeJSCallRuntime(Node* node) {
1446 switch (CallRuntimeParametersOf(node->op()).id()) {
1447 case Runtime::kInlineIsJSReceiver:
1448 return TypeUnaryOp(node, ObjectIsReceiver);
1449 case Runtime::kInlineIsSmi:
1450 return TypeUnaryOp(node, ObjectIsSmi);
1451 case Runtime::kInlineIsArray:
1452 case Runtime::kInlineIsDate:
1453 case Runtime::kInlineIsTypedArray:
1454 case Runtime::kInlineIsRegExp:
1455 return Type::Boolean();
1456 case Runtime::kInlineCreateIterResultObject:
1457 return Type::OtherObject();
1458 case Runtime::kInlineSubString:
1459 case Runtime::kInlineStringCharFromCode:
1460 return Type::String();
1461 case Runtime::kInlineToInteger:
1462 return TypeUnaryOp(node, ToInteger);
1463 case Runtime::kInlineToLength:
1464 return TypeUnaryOp(node, ToLength);
1465 case Runtime::kInlineToNumber:
1466 return TypeUnaryOp(node, ToNumber);
1467 case Runtime::kInlineToObject:
1468 return TypeUnaryOp(node, ToObject);
1469 case Runtime::kInlineToString:
1470 return TypeUnaryOp(node, ToString);
1471 case Runtime::kHasInPrototypeChain:
1472 return Type::Boolean();
1473 default:
1474 break;
1475 }
1476 // TODO(turbofan): This should be Type::NonInternal(), but unfortunately we
1477 // have a few weird runtime calls that return the hole or even FixedArrays;
1478 // change this once those weird runtime calls have been removed.
1479 return Type::Any();
1480 }
1481
1482
TypeJSConvertReceiver(Node * node)1483 Type* Typer::Visitor::TypeJSConvertReceiver(Node* node) {
1484 return Type::Receiver();
1485 }
1486
1487
TypeJSForInNext(Node * node)1488 Type* Typer::Visitor::TypeJSForInNext(Node* node) {
1489 return Type::Union(Type::Name(), Type::Undefined(), zone());
1490 }
1491
1492
TypeJSForInPrepare(Node * node)1493 Type* Typer::Visitor::TypeJSForInPrepare(Node* node) {
1494 STATIC_ASSERT(Map::EnumLengthBits::kMax <= FixedArray::kMaxLength);
1495 Type* const cache_type =
1496 Type::Union(Type::SignedSmall(), Type::OtherInternal(), zone());
1497 Type* const cache_array = Type::OtherInternal();
1498 Type* const cache_length = typer_->cache_.kFixedArrayLengthType;
1499 return Type::Tuple(cache_type, cache_array, cache_length, zone());
1500 }
1501
1502
TypeJSLoadMessage(Node * node)1503 Type* Typer::Visitor::TypeJSLoadMessage(Node* node) { return Type::Any(); }
1504
1505
TypeJSStoreMessage(Node * node)1506 Type* Typer::Visitor::TypeJSStoreMessage(Node* node) {
1507 UNREACHABLE();
1508 return nullptr;
1509 }
1510
TypeJSLoadModule(Node * node)1511 Type* Typer::Visitor::TypeJSLoadModule(Node* node) { return Type::Any(); }
1512
TypeJSStoreModule(Node * node)1513 Type* Typer::Visitor::TypeJSStoreModule(Node* node) {
1514 UNREACHABLE();
1515 return nullptr;
1516 }
1517
TypeJSGeneratorStore(Node * node)1518 Type* Typer::Visitor::TypeJSGeneratorStore(Node* node) {
1519 UNREACHABLE();
1520 return nullptr;
1521 }
1522
TypeJSGeneratorRestoreContinuation(Node * node)1523 Type* Typer::Visitor::TypeJSGeneratorRestoreContinuation(Node* node) {
1524 return Type::SignedSmall();
1525 }
1526
TypeJSGeneratorRestoreRegister(Node * node)1527 Type* Typer::Visitor::TypeJSGeneratorRestoreRegister(Node* node) {
1528 return Type::Any();
1529 }
1530
TypeJSStackCheck(Node * node)1531 Type* Typer::Visitor::TypeJSStackCheck(Node* node) { return Type::Any(); }
1532
1533 // Simplified operators.
1534
TypeBooleanNot(Node * node)1535 Type* Typer::Visitor::TypeBooleanNot(Node* node) { return Type::Boolean(); }
1536
TypeNumberEqual(Node * node)1537 Type* Typer::Visitor::TypeNumberEqual(Node* node) { return Type::Boolean(); }
1538
TypeNumberLessThan(Node * node)1539 Type* Typer::Visitor::TypeNumberLessThan(Node* node) { return Type::Boolean(); }
1540
TypeNumberLessThanOrEqual(Node * node)1541 Type* Typer::Visitor::TypeNumberLessThanOrEqual(Node* node) {
1542 return Type::Boolean();
1543 }
1544
TypeSpeculativeNumberEqual(Node * node)1545 Type* Typer::Visitor::TypeSpeculativeNumberEqual(Node* node) {
1546 return Type::Boolean();
1547 }
1548
TypeSpeculativeNumberLessThan(Node * node)1549 Type* Typer::Visitor::TypeSpeculativeNumberLessThan(Node* node) {
1550 return Type::Boolean();
1551 }
1552
TypeSpeculativeNumberLessThanOrEqual(Node * node)1553 Type* Typer::Visitor::TypeSpeculativeNumberLessThanOrEqual(Node* node) {
1554 return Type::Boolean();
1555 }
1556
TypePlainPrimitiveToNumber(Node * node)1557 Type* Typer::Visitor::TypePlainPrimitiveToNumber(Node* node) {
1558 return TypeUnaryOp(node, ToNumber);
1559 }
1560
TypePlainPrimitiveToWord32(Node * node)1561 Type* Typer::Visitor::TypePlainPrimitiveToWord32(Node* node) {
1562 return Type::Integral32();
1563 }
1564
TypePlainPrimitiveToFloat64(Node * node)1565 Type* Typer::Visitor::TypePlainPrimitiveToFloat64(Node* node) {
1566 return Type::Number();
1567 }
1568
1569 // static
ReferenceEqualTyper(Type * lhs,Type * rhs,Typer * t)1570 Type* Typer::Visitor::ReferenceEqualTyper(Type* lhs, Type* rhs, Typer* t) {
1571 if (lhs->IsHeapConstant() && rhs->Is(lhs)) {
1572 return t->singleton_true_;
1573 }
1574 return Type::Boolean();
1575 }
1576
1577
TypeReferenceEqual(Node * node)1578 Type* Typer::Visitor::TypeReferenceEqual(Node* node) {
1579 return TypeBinaryOp(node, ReferenceEqualTyper);
1580 }
1581
TypeStringEqual(Node * node)1582 Type* Typer::Visitor::TypeStringEqual(Node* node) { return Type::Boolean(); }
1583
TypeStringLessThan(Node * node)1584 Type* Typer::Visitor::TypeStringLessThan(Node* node) { return Type::Boolean(); }
1585
TypeStringLessThanOrEqual(Node * node)1586 Type* Typer::Visitor::TypeStringLessThanOrEqual(Node* node) {
1587 return Type::Boolean();
1588 }
1589
StringFromCharCodeTyper(Type * type,Typer * t)1590 Type* Typer::Visitor::StringFromCharCodeTyper(Type* type, Typer* t) {
1591 return Type::String();
1592 }
1593
StringFromCodePointTyper(Type * type,Typer * t)1594 Type* Typer::Visitor::StringFromCodePointTyper(Type* type, Typer* t) {
1595 return Type::String();
1596 }
1597
TypeStringCharCodeAt(Node * node)1598 Type* Typer::Visitor::TypeStringCharCodeAt(Node* node) {
1599 return typer_->cache_.kUint16;
1600 }
1601
TypeStringFromCharCode(Node * node)1602 Type* Typer::Visitor::TypeStringFromCharCode(Node* node) {
1603 return TypeUnaryOp(node, StringFromCharCodeTyper);
1604 }
1605
TypeStringFromCodePoint(Node * node)1606 Type* Typer::Visitor::TypeStringFromCodePoint(Node* node) {
1607 return TypeUnaryOp(node, StringFromCodePointTyper);
1608 }
1609
TypeCheckBounds(Node * node)1610 Type* Typer::Visitor::TypeCheckBounds(Node* node) {
1611 Type* index = Operand(node, 0);
1612 Type* length = Operand(node, 1);
1613 index = Type::Intersect(index, Type::Integral32(), zone());
1614 if (!index->IsInhabited() || !length->IsInhabited()) return Type::None();
1615 double min = std::max(index->Min(), 0.0);
1616 double max = std::min(index->Max(), length->Max() - 1);
1617 if (max < min) return Type::None();
1618 return Type::Range(min, max, zone());
1619 }
1620
TypeCheckHeapObject(Node * node)1621 Type* Typer::Visitor::TypeCheckHeapObject(Node* node) {
1622 Type* type = Operand(node, 0);
1623 return type;
1624 }
1625
TypeCheckIf(Node * node)1626 Type* Typer::Visitor::TypeCheckIf(Node* node) {
1627 UNREACHABLE();
1628 return nullptr;
1629 }
1630
TypeCheckMaps(Node * node)1631 Type* Typer::Visitor::TypeCheckMaps(Node* node) {
1632 UNREACHABLE();
1633 return nullptr;
1634 }
1635
TypeCheckNumber(Node * node)1636 Type* Typer::Visitor::TypeCheckNumber(Node* node) {
1637 Type* arg = Operand(node, 0);
1638 return Type::Intersect(arg, Type::Number(), zone());
1639 }
1640
TypeCheckSmi(Node * node)1641 Type* Typer::Visitor::TypeCheckSmi(Node* node) {
1642 Type* arg = Operand(node, 0);
1643 return Type::Intersect(arg, Type::SignedSmall(), zone());
1644 }
1645
TypeCheckString(Node * node)1646 Type* Typer::Visitor::TypeCheckString(Node* node) {
1647 Type* arg = Operand(node, 0);
1648 return Type::Intersect(arg, Type::String(), zone());
1649 }
1650
TypeCheckFloat64Hole(Node * node)1651 Type* Typer::Visitor::TypeCheckFloat64Hole(Node* node) {
1652 Type* type = Operand(node, 0);
1653 return type;
1654 }
1655
TypeCheckTaggedHole(Node * node)1656 Type* Typer::Visitor::TypeCheckTaggedHole(Node* node) {
1657 Type* type = Operand(node, 0);
1658 type = Type::Intersect(type, Type::NonInternal(), zone());
1659 return type;
1660 }
1661
TypeConvertTaggedHoleToUndefined(Node * node)1662 Type* Typer::Visitor::TypeConvertTaggedHoleToUndefined(Node* node) {
1663 Type* type = Operand(node, 0);
1664 if (type->Maybe(Type::Hole())) {
1665 // Turn "the hole" into undefined.
1666 type = Type::Intersect(type, Type::NonInternal(), zone());
1667 type = Type::Union(type, Type::Undefined(), zone());
1668 }
1669 return type;
1670 }
1671
TypeAllocate(Node * node)1672 Type* Typer::Visitor::TypeAllocate(Node* node) { return Type::Any(); }
1673
TypeLoadField(Node * node)1674 Type* Typer::Visitor::TypeLoadField(Node* node) {
1675 return FieldAccessOf(node->op()).type;
1676 }
1677
TypeLoadBuffer(Node * node)1678 Type* Typer::Visitor::TypeLoadBuffer(Node* node) {
1679 switch (BufferAccessOf(node->op()).external_array_type()) {
1680 #define TYPED_ARRAY_CASE(ElemType, type, TYPE, ctype, size) \
1681 case kExternal##ElemType##Array: \
1682 return Type::Union(typer_->cache_.k##ElemType, Type::Undefined(), zone());
1683 TYPED_ARRAYS(TYPED_ARRAY_CASE)
1684 #undef TYPED_ARRAY_CASE
1685 }
1686 UNREACHABLE();
1687 return nullptr;
1688 }
1689
1690
TypeLoadElement(Node * node)1691 Type* Typer::Visitor::TypeLoadElement(Node* node) {
1692 return ElementAccessOf(node->op()).type;
1693 }
1694
TypeLoadTypedElement(Node * node)1695 Type* Typer::Visitor::TypeLoadTypedElement(Node* node) {
1696 switch (ExternalArrayTypeOf(node->op())) {
1697 #define TYPED_ARRAY_CASE(ElemType, type, TYPE, ctype, size) \
1698 case kExternal##ElemType##Array: \
1699 return typer_->cache_.k##ElemType;
1700 TYPED_ARRAYS(TYPED_ARRAY_CASE)
1701 #undef TYPED_ARRAY_CASE
1702 }
1703 UNREACHABLE();
1704 return nullptr;
1705 }
1706
TypeStoreField(Node * node)1707 Type* Typer::Visitor::TypeStoreField(Node* node) {
1708 UNREACHABLE();
1709 return nullptr;
1710 }
1711
1712
TypeStoreBuffer(Node * node)1713 Type* Typer::Visitor::TypeStoreBuffer(Node* node) {
1714 UNREACHABLE();
1715 return nullptr;
1716 }
1717
1718
TypeStoreElement(Node * node)1719 Type* Typer::Visitor::TypeStoreElement(Node* node) {
1720 UNREACHABLE();
1721 return nullptr;
1722 }
1723
TypeStoreTypedElement(Node * node)1724 Type* Typer::Visitor::TypeStoreTypedElement(Node* node) {
1725 UNREACHABLE();
1726 return nullptr;
1727 }
1728
TypeObjectIsCallable(Node * node)1729 Type* Typer::Visitor::TypeObjectIsCallable(Node* node) {
1730 return TypeUnaryOp(node, ObjectIsCallable);
1731 }
1732
TypeObjectIsNumber(Node * node)1733 Type* Typer::Visitor::TypeObjectIsNumber(Node* node) {
1734 return TypeUnaryOp(node, ObjectIsNumber);
1735 }
1736
1737
TypeObjectIsReceiver(Node * node)1738 Type* Typer::Visitor::TypeObjectIsReceiver(Node* node) {
1739 return TypeUnaryOp(node, ObjectIsReceiver);
1740 }
1741
1742
TypeObjectIsSmi(Node * node)1743 Type* Typer::Visitor::TypeObjectIsSmi(Node* node) {
1744 return TypeUnaryOp(node, ObjectIsSmi);
1745 }
1746
TypeObjectIsString(Node * node)1747 Type* Typer::Visitor::TypeObjectIsString(Node* node) {
1748 return TypeUnaryOp(node, ObjectIsString);
1749 }
1750
TypeObjectIsUndetectable(Node * node)1751 Type* Typer::Visitor::TypeObjectIsUndetectable(Node* node) {
1752 return TypeUnaryOp(node, ObjectIsUndetectable);
1753 }
1754
TypeArrayBufferWasNeutered(Node * node)1755 Type* Typer::Visitor::TypeArrayBufferWasNeutered(Node* node) {
1756 return Type::Boolean();
1757 }
1758
1759 // Heap constants.
1760
TypeConstant(Handle<Object> value)1761 Type* Typer::Visitor::TypeConstant(Handle<Object> value) {
1762 if (Type::IsInteger(*value)) {
1763 return Type::Range(value->Number(), value->Number(), zone());
1764 }
1765 return Type::NewConstant(value, zone());
1766 }
1767
1768 } // namespace compiler
1769 } // namespace internal
1770 } // namespace v8
1771