blob: 137829e92d9bb1b077fc31b10b4fa14e6b6c181c [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// 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
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005#include "src/bootstrapper.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006#include "src/compiler/graph-inl.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007#include "src/compiler/graph-reducer.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008#include "src/compiler/js-operator.h"
9#include "src/compiler/node.h"
10#include "src/compiler/node-properties-inl.h"
11#include "src/compiler/node-properties.h"
12#include "src/compiler/simplified-operator.h"
13#include "src/compiler/typer.h"
14
15namespace v8 {
16namespace internal {
17namespace compiler {
18
Emily Bernierd0a1eb72015-03-24 16:35:39 -040019#define NATIVE_TYPES(V) \
20 V(Int8) \
21 V(Uint8) \
22 V(Int16) \
23 V(Uint16) \
24 V(Int32) \
25 V(Uint32) \
26 V(Float32) \
27 V(Float64)
28
29enum LazyCachedType {
30 kNumberFunc0,
31 kNumberFunc1,
32 kNumberFunc2,
33 kImulFunc,
34 kClz32Func,
35 kArrayBufferFunc,
36#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
37 k##Type, k##Type##Array, k##Type##ArrayFunc,
38 TYPED_ARRAYS(TYPED_ARRAY_CASE)
39#undef TYPED_ARRAY_CASE
40 kNumLazyCachedTypes
41};
42
43
44// Constructs and caches types lazily.
45// TODO(turbofan): these types could be globally cached or cached per isolate.
46class LazyTypeCache FINAL : public ZoneObject {
47 public:
48 explicit LazyTypeCache(Zone* zone) : zone_(zone) {
49 memset(cache_, 0, sizeof(cache_));
50 }
51
52 inline Type* Get(LazyCachedType type) {
53 int index = static_cast<int>(type);
54 DCHECK(index < kNumLazyCachedTypes);
55 if (cache_[index] == NULL) cache_[index] = Create(type);
56 return cache_[index];
57 }
58
59 private:
60 Type* Create(LazyCachedType type) {
61 switch (type) {
62 case kInt8:
63 return CreateNative(CreateRange<int8_t>(), Type::UntaggedSigned8());
64 case kUint8:
65 return CreateNative(CreateRange<uint8_t>(), Type::UntaggedUnsigned8());
66 case kInt16:
67 return CreateNative(CreateRange<int16_t>(), Type::UntaggedSigned16());
68 case kUint16:
69 return CreateNative(CreateRange<uint16_t>(),
70 Type::UntaggedUnsigned16());
71 case kInt32:
72 return CreateNative(Type::Signed32(), Type::UntaggedSigned32());
73 case kUint32:
74 return CreateNative(Type::Unsigned32(), Type::UntaggedUnsigned32());
75 case kFloat32:
76 return CreateNative(Type::Number(), Type::UntaggedFloat32());
77 case kFloat64:
78 return CreateNative(Type::Number(), Type::UntaggedFloat64());
79 case kUint8Clamped:
80 return Get(kUint8);
81 case kNumberFunc0:
82 return Type::Function(Type::Number(), zone());
83 case kNumberFunc1:
84 return Type::Function(Type::Number(), Type::Number(), zone());
85 case kNumberFunc2:
86 return Type::Function(Type::Number(), Type::Number(), Type::Number(),
87 zone());
88 case kImulFunc:
89 return Type::Function(Type::Signed32(), Type::Integral32(),
90 Type::Integral32(), zone());
91 case kClz32Func:
92 return Type::Function(CreateRange(0, 32), Type::Number(), zone());
93 case kArrayBufferFunc:
94 return Type::Function(Type::Object(zone()), Type::Unsigned32(), zone());
95#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
96 case k##Type##Array: \
97 return CreateArray(Get(k##Type)); \
98 case k##Type##ArrayFunc: \
99 return CreateArrayFunction(Get(k##Type##Array));
100 TYPED_ARRAYS(TYPED_ARRAY_CASE)
101#undef TYPED_ARRAY_CASE
102 case kNumLazyCachedTypes:
103 break;
104 }
105 UNREACHABLE();
106 return NULL;
107 }
108
109 Type* CreateArray(Type* element) const {
110 return Type::Array(element, zone());
111 }
112
113 Type* CreateArrayFunction(Type* array) const {
114 Type* arg1 = Type::Union(Type::Unsigned32(), Type::Object(), zone());
115 Type* arg2 = Type::Union(Type::Unsigned32(), Type::Undefined(), zone());
116 Type* arg3 = arg2;
117 return Type::Function(array, arg1, arg2, arg3, zone());
118 }
119
120 Type* CreateNative(Type* semantic, Type* representation) const {
121 return Type::Intersect(semantic, representation, zone());
122 }
123
124 template <typename T>
125 Type* CreateRange() const {
126 return CreateRange(std::numeric_limits<T>::min(),
127 std::numeric_limits<T>::max());
128 }
129
130 Type* CreateRange(double min, double max) const {
131 return Type::Range(factory()->NewNumber(min), factory()->NewNumber(max),
132 zone());
133 }
134
135 Factory* factory() const { return isolate()->factory(); }
136 Isolate* isolate() const { return zone()->isolate(); }
137 Zone* zone() const { return zone_; }
138
139 Type* cache_[kNumLazyCachedTypes];
140 Zone* zone_;
141};
142
143
144class Typer::Decorator FINAL : public GraphDecorator {
145 public:
146 explicit Decorator(Typer* typer) : typer_(typer) {}
147 void Decorate(Node* node) FINAL;
148
149 private:
150 Typer* typer_;
151};
152
153
154Typer::Typer(Graph* graph, MaybeHandle<Context> context)
155 : graph_(graph),
156 context_(context),
157 decorator_(NULL),
158 cache_(new (graph->zone()) LazyTypeCache(graph->zone())),
159 weaken_min_limits_(graph->zone()),
160 weaken_max_limits_(graph->zone()) {
161 Zone* zone = this->zone();
162 Factory* f = zone->isolate()->factory();
163
164 Handle<Object> zero = f->NewNumber(0);
165 Handle<Object> one = f->NewNumber(1);
166 Handle<Object> infinity = f->NewNumber(+V8_INFINITY);
167 Handle<Object> minusinfinity = f->NewNumber(-V8_INFINITY);
168
169 Type* number = Type::Number();
170 Type* signed32 = Type::Signed32();
171 Type* unsigned32 = Type::Unsigned32();
172 Type* nan_or_minuszero = Type::Union(Type::NaN(), Type::MinusZero(), zone);
173 Type* truncating_to_zero =
174 Type::Union(Type::Union(Type::Constant(infinity, zone),
175 Type::Constant(minusinfinity, zone), zone),
176 nan_or_minuszero, zone);
177
178 boolean_or_number = Type::Union(Type::Boolean(), Type::Number(), zone);
179 undefined_or_null = Type::Union(Type::Undefined(), Type::Null(), zone);
180 undefined_or_number = Type::Union(Type::Undefined(), Type::Number(), zone);
181 singleton_false = Type::Constant(f->false_value(), zone);
182 singleton_true = Type::Constant(f->true_value(), zone);
183 singleton_zero = Type::Range(zero, zero, zone);
184 singleton_one = Type::Range(one, one, zone);
185 zero_or_one = Type::Union(singleton_zero, singleton_one, zone);
186 zeroish = Type::Union(singleton_zero, nan_or_minuszero, zone);
187 signed32ish = Type::Union(signed32, truncating_to_zero, zone);
188 unsigned32ish = Type::Union(unsigned32, truncating_to_zero, zone);
189 falsish = Type::Union(Type::Undetectable(),
190 Type::Union(Type::Union(singleton_false, zeroish, zone),
191 undefined_or_null, zone),
192 zone);
193 truish = Type::Union(
194 singleton_true,
195 Type::Union(Type::DetectableReceiver(), Type::Symbol(), zone), zone);
196 integer = Type::Range(minusinfinity, infinity, zone);
197 weakint = Type::Union(integer, nan_or_minuszero, zone);
198
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000199 number_fun0_ = Type::Function(number, zone);
200 number_fun1_ = Type::Function(number, number, zone);
201 number_fun2_ = Type::Function(number, number, number, zone);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000202
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400203 weakint_fun1_ = Type::Function(weakint, number, zone);
204 random_fun_ = Type::Function(Type::OrderedNumber(), zone);
205
206 const int limits_count = 20;
207
208 weaken_min_limits_.reserve(limits_count + 1);
209 weaken_max_limits_.reserve(limits_count + 1);
210
211 double limit = 1 << 30;
212 weaken_min_limits_.push_back(f->NewNumber(0));
213 weaken_max_limits_.push_back(f->NewNumber(0));
214 for (int i = 0; i < limits_count; i++) {
215 weaken_min_limits_.push_back(f->NewNumber(-limit));
216 weaken_max_limits_.push_back(f->NewNumber(limit - 1));
217 limit *= 2;
218 }
219
220 decorator_ = new (zone) Decorator(this);
221 graph_->AddDecorator(decorator_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000222}
223
224
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400225Typer::~Typer() {
226 graph_->RemoveDecorator(decorator_);
227}
228
229
230class Typer::Visitor : public Reducer {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000231 public:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400232 explicit Visitor(Typer* typer) : typer_(typer) {}
233
234 Reduction Reduce(Node* node) OVERRIDE {
235 if (node->op()->ValueOutputCount() == 0) return NoChange();
236 switch (node->opcode()) {
237#define DECLARE_CASE(x) \
238 case IrOpcode::k##x: \
239 return UpdateBounds(node, TypeBinaryOp(node, x##Typer));
240 JS_SIMPLE_BINOP_LIST(DECLARE_CASE)
241#undef DECLARE_CASE
242
243#define DECLARE_CASE(x) \
244 case IrOpcode::k##x: \
245 return UpdateBounds(node, Type##x(node));
246 DECLARE_CASE(Start)
247 // VALUE_OP_LIST without JS_SIMPLE_BINOP_LIST:
248 COMMON_OP_LIST(DECLARE_CASE)
249 SIMPLIFIED_OP_LIST(DECLARE_CASE)
250 MACHINE_OP_LIST(DECLARE_CASE)
251 JS_SIMPLE_UNOP_LIST(DECLARE_CASE)
252 JS_OBJECT_OP_LIST(DECLARE_CASE)
253 JS_CONTEXT_OP_LIST(DECLARE_CASE)
254 JS_OTHER_OP_LIST(DECLARE_CASE)
255#undef DECLARE_CASE
256
257#define DECLARE_CASE(x) case IrOpcode::k##x:
258 DECLARE_CASE(End)
259 INNER_CONTROL_OP_LIST(DECLARE_CASE)
260#undef DECLARE_CASE
261 break;
262 }
263 return NoChange();
264 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000265
266 Bounds TypeNode(Node* node) {
267 switch (node->opcode()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400268#define DECLARE_CASE(x) \
269 case IrOpcode::k##x: return TypeBinaryOp(node, x##Typer);
270 JS_SIMPLE_BINOP_LIST(DECLARE_CASE)
271#undef DECLARE_CASE
272
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000273#define DECLARE_CASE(x) case IrOpcode::k##x: return Type##x(node);
274 DECLARE_CASE(Start)
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400275 // VALUE_OP_LIST without JS_SIMPLE_BINOP_LIST:
276 COMMON_OP_LIST(DECLARE_CASE)
277 SIMPLIFIED_OP_LIST(DECLARE_CASE)
278 MACHINE_OP_LIST(DECLARE_CASE)
279 JS_SIMPLE_UNOP_LIST(DECLARE_CASE)
280 JS_OBJECT_OP_LIST(DECLARE_CASE)
281 JS_CONTEXT_OP_LIST(DECLARE_CASE)
282 JS_OTHER_OP_LIST(DECLARE_CASE)
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000283#undef DECLARE_CASE
284
285#define DECLARE_CASE(x) case IrOpcode::k##x:
286 DECLARE_CASE(End)
287 INNER_CONTROL_OP_LIST(DECLARE_CASE)
288#undef DECLARE_CASE
289 break;
290 }
291 UNREACHABLE();
292 return Bounds();
293 }
294
295 Type* TypeConstant(Handle<Object> value);
296
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400297 private:
298 Typer* typer_;
299 MaybeHandle<Context> context_;
300
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000301#define DECLARE_METHOD(x) inline Bounds Type##x(Node* node);
302 DECLARE_METHOD(Start)
303 VALUE_OP_LIST(DECLARE_METHOD)
304#undef DECLARE_METHOD
305
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400306 Bounds BoundsOrNone(Node* node) {
307 return NodeProperties::IsTyped(node) ? NodeProperties::GetBounds(node)
308 : Bounds(Type::None());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000309 }
310
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400311 Bounds Operand(Node* node, int i) {
312 Node* operand_node = NodeProperties::GetValueInput(node, i);
313 return BoundsOrNone(operand_node);
314 }
315
316 Bounds ContextOperand(Node* node) {
317 Bounds result = BoundsOrNone(NodeProperties::GetContextInput(node));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000318 DCHECK(result.upper->Maybe(Type::Internal()));
319 // TODO(rossberg): More precisely, instead of the above assertion, we should
320 // back-propagate the constraint that it has to be a subtype of Internal.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400321 return result;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000322 }
323
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400324 Type* Weaken(Type* current_type, Type* previous_type);
325
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000326 Zone* zone() { return typer_->zone(); }
327 Isolate* isolate() { return typer_->isolate(); }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400328 Graph* graph() { return typer_->graph(); }
329 MaybeHandle<Context> context() { return typer_->context(); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000330
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400331 typedef Type* (*UnaryTyperFun)(Type*, Typer* t);
332 typedef Type* (*BinaryTyperFun)(Type*, Type*, Typer* t);
333
334 Bounds TypeUnaryOp(Node* node, UnaryTyperFun);
335 Bounds TypeBinaryOp(Node* node, BinaryTyperFun);
336
337 static Type* Invert(Type*, Typer*);
338 static Type* FalsifyUndefined(Type*, Typer*);
339 static Type* Rangify(Type*, Typer*);
340
341 static Type* ToPrimitive(Type*, Typer*);
342 static Type* ToBoolean(Type*, Typer*);
343 static Type* ToNumber(Type*, Typer*);
344 static Type* ToString(Type*, Typer*);
345 static Type* NumberToInt32(Type*, Typer*);
346 static Type* NumberToUint32(Type*, Typer*);
347
348 static Type* JSAddRanger(Type::RangeType*, Type::RangeType*, Typer*);
349 static Type* JSSubtractRanger(Type::RangeType*, Type::RangeType*, Typer*);
350 static Type* JSMultiplyRanger(Type::RangeType*, Type::RangeType*, Typer*);
351 static Type* JSDivideRanger(Type::RangeType*, Type::RangeType*, Typer*);
352 static Type* JSModulusRanger(Type::RangeType*, Type::RangeType*, Typer*);
353
354 static Type* JSCompareTyper(Type*, Type*, Typer*);
355
356#define DECLARE_METHOD(x) static Type* x##Typer(Type*, Type*, Typer*);
357 JS_SIMPLE_BINOP_LIST(DECLARE_METHOD)
358#undef DECLARE_METHOD
359
360 static Type* JSUnaryNotTyper(Type*, Typer*);
361 static Type* JSLoadPropertyTyper(Type*, Type*, Typer*);
362 static Type* JSCallFunctionTyper(Type*, Typer*);
363
364 Reduction UpdateBounds(Node* node, Bounds current) {
365 if (NodeProperties::IsTyped(node)) {
366 // Widen the bounds of a previously typed node.
367 Bounds previous = NodeProperties::GetBounds(node);
368 // Speed up termination in the presence of range types:
369 current.upper = Weaken(current.upper, previous.upper);
370 current.lower = Weaken(current.lower, previous.lower);
371
372 // Types should not get less precise.
373 DCHECK(previous.lower->Is(current.lower));
374 DCHECK(previous.upper->Is(current.upper));
375
376 NodeProperties::SetBounds(node, current);
377 if (!(previous.Narrows(current) && current.Narrows(previous))) {
378 // If something changed, revisit all uses.
379 return Changed(node);
380 }
381 return NoChange();
382 } else {
383 // No previous type, simply update the bounds.
384 NodeProperties::SetBounds(node, current);
385 return Changed(node);
386 }
387 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000388};
389
390
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400391void Typer::Run() {
392 {
393 // TODO(titzer): this is a hack. Reset types for interior nodes first.
394 NodeDeque deque(zone());
395 NodeMarker<bool> marked(graph(), 2);
396 deque.push_front(graph()->end());
397 marked.Set(graph()->end(), true);
398 while (!deque.empty()) {
399 Node* node = deque.front();
400 deque.pop_front();
401 // TODO(titzer): there shouldn't be a need to retype constants.
402 if (node->op()->ValueOutputCount() > 0)
403 NodeProperties::RemoveBounds(node);
404 for (Node* input : node->inputs()) {
405 if (!marked.Get(input)) {
406 marked.Set(input, true);
407 deque.push_back(input);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000408 }
409 }
410 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000411 }
412
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400413 Visitor visitor(this);
414 GraphReducer graph_reducer(graph(), zone());
415 graph_reducer.AddReducer(&visitor);
416 graph_reducer.ReduceGraph();
417}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000418
419
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400420void Typer::Decorator::Decorate(Node* node) {
421 if (node->op()->ValueOutputCount() > 0) {
422 // Only eagerly type-decorate nodes with known input types.
423 // Other cases will generally require a proper fixpoint iteration with Run.
424 bool is_typed = NodeProperties::IsTyped(node);
425 if (is_typed || NodeProperties::AllValueInputsAreTyped(node)) {
426 Visitor typing(typer_);
427 Bounds bounds = typing.TypeNode(node);
428 if (is_typed) {
429 bounds =
430 Bounds::Both(bounds, NodeProperties::GetBounds(node), typer_->zone());
431 }
432 NodeProperties::SetBounds(node, bounds);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000433 }
434 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000435}
436
437
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400438// -----------------------------------------------------------------------------
439
440// Helper functions that lift a function f on types to a function on bounds,
441// and uses that to type the given node. Note that f is never called with None
442// as an argument.
443
444
445Bounds Typer::Visitor::TypeUnaryOp(Node* node, UnaryTyperFun f) {
446 Bounds input = Operand(node, 0);
447 Type* upper = input.upper->Is(Type::None())
448 ? Type::None()
449 : f(input.upper, typer_);
450 Type* lower = input.lower->Is(Type::None())
451 ? Type::None()
452 : (input.lower == input.upper || upper->IsConstant())
453 ? upper // TODO(neis): Extend this to Range(x,x), NaN, MinusZero, ...?
454 : f(input.lower, typer_);
455 // TODO(neis): Figure out what to do with lower bound.
456 return Bounds(lower, upper);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000457}
458
459
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400460Bounds Typer::Visitor::TypeBinaryOp(Node* node, BinaryTyperFun f) {
461 Bounds left = Operand(node, 0);
462 Bounds right = Operand(node, 1);
463 Type* upper = left.upper->Is(Type::None()) || right.upper->Is(Type::None())
464 ? Type::None()
465 : f(left.upper, right.upper, typer_);
466 Type* lower = left.lower->Is(Type::None()) || right.lower->Is(Type::None())
467 ? Type::None()
468 : ((left.lower == left.upper && right.lower == right.upper) ||
469 upper->IsConstant())
470 ? upper
471 : f(left.lower, right.lower, typer_);
472 // TODO(neis): Figure out what to do with lower bound.
473 return Bounds(lower, upper);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000474}
475
476
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400477Type* Typer::Visitor::Invert(Type* type, Typer* t) {
478 if (type->Is(t->singleton_false)) return t->singleton_true;
479 if (type->Is(t->singleton_true)) return t->singleton_false;
480 return type;
481}
482
483
484Type* Typer::Visitor::FalsifyUndefined(Type* type, Typer* t) {
485 if (type->Is(Type::Undefined())) return t->singleton_false;
486 return type;
487}
488
489
490Type* Typer::Visitor::Rangify(Type* type, Typer* t) {
491 if (type->IsRange()) return type; // Shortcut.
492 if (!type->Is(t->integer) && !type->Is(Type::Integral32())) {
493 return type; // Give up on non-integer types.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000494 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400495 double min = type->Min();
496 double max = type->Max();
497 // Handle the degenerate case of empty bitset types (such as
498 // OtherUnsigned31 and OtherSigned32 on 64-bit architectures).
499 if (std::isnan(min)) {
500 DCHECK(std::isnan(max));
501 return type;
502 }
503 Factory* f = t->isolate()->factory();
504 return Type::Range(f->NewNumber(min), f->NewNumber(max), t->zone());
505}
506
507
508// Type conversion.
509
510
511Type* Typer::Visitor::ToPrimitive(Type* type, Typer* t) {
512 if (type->Is(Type::Primitive()) && !type->Maybe(Type::Receiver())) {
513 return type;
514 }
515 return Type::Primitive();
516}
517
518
519Type* Typer::Visitor::ToBoolean(Type* type, Typer* t) {
520 if (type->Is(Type::Boolean())) return type;
521 if (type->Is(t->falsish)) return t->singleton_false;
522 if (type->Is(t->truish)) return t->singleton_true;
523 if (type->Is(Type::PlainNumber()) && (type->Max() < 0 || 0 < type->Min())) {
524 return t->singleton_true; // Ruled out nan, -0 and +0.
525 }
526 return Type::Boolean();
527}
528
529
530Type* Typer::Visitor::ToNumber(Type* type, Typer* t) {
531 if (type->Is(Type::Number())) return type;
532 if (type->Is(Type::Null())) return t->singleton_zero;
533 if (type->Is(Type::Undefined())) return Type::NaN();
534 if (type->Is(t->undefined_or_null)) {
535 return Type::Union(Type::NaN(), t->singleton_zero, t->zone());
536 }
537 if (type->Is(t->undefined_or_number)) {
538 return Type::Union(Type::Intersect(type, Type::Number(), t->zone()),
539 Type::NaN(), t->zone());
540 }
541 if (type->Is(t->singleton_false)) return t->singleton_zero;
542 if (type->Is(t->singleton_true)) return t->singleton_one;
543 if (type->Is(Type::Boolean())) return t->zero_or_one;
544 if (type->Is(t->boolean_or_number)) {
545 return Type::Union(Type::Intersect(type, Type::Number(), t->zone()),
546 t->zero_or_one, t->zone());
547 }
548 return Type::Number();
549}
550
551
552Type* Typer::Visitor::ToString(Type* type, Typer* t) {
553 if (type->Is(Type::String())) return type;
554 return Type::String();
555}
556
557
558Type* Typer::Visitor::NumberToInt32(Type* type, Typer* t) {
559 // TODO(neis): DCHECK(type->Is(Type::Number()));
560 if (type->Is(Type::Signed32())) return type;
561 if (type->Is(t->zeroish)) return t->singleton_zero;
562 if (type->Is(t->signed32ish)) {
563 return Type::Intersect(Type::Union(type, t->singleton_zero, t->zone()),
564 Type::Signed32(), t->zone());
565 }
566 return Type::Signed32();
567}
568
569
570Type* Typer::Visitor::NumberToUint32(Type* type, Typer* t) {
571 // TODO(neis): DCHECK(type->Is(Type::Number()));
572 if (type->Is(Type::Unsigned32())) return type;
573 if (type->Is(t->zeroish)) return t->singleton_zero;
574 if (type->Is(t->unsigned32ish)) {
575 return Type::Intersect(Type::Union(type, t->singleton_zero, t->zone()),
576 Type::Unsigned32(), t->zone());
577 }
578 return Type::Unsigned32();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000579}
580
581
582// -----------------------------------------------------------------------------
583
584
585// Control operators.
586
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400587
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000588Bounds Typer::Visitor::TypeStart(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400589 return Bounds(Type::None(zone()), Type::Internal(zone()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000590}
591
592
593// Common operators.
594
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400595
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000596Bounds Typer::Visitor::TypeParameter(Node* node) {
597 return Bounds::Unbounded(zone());
598}
599
600
601Bounds Typer::Visitor::TypeInt32Constant(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400602 Factory* f = isolate()->factory();
603 Handle<Object> number = f->NewNumber(OpParameter<int32_t>(node));
604 return Bounds(Type::Intersect(
605 Type::Range(number, number, zone()), Type::UntaggedSigned32(), zone()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000606}
607
608
609Bounds Typer::Visitor::TypeInt64Constant(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400610 // TODO(rossberg): This actually seems to be a PointerConstant so far...
611 return Bounds(Type::Internal()); // TODO(rossberg): Add int64 bitset type?
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000612}
613
614
615Bounds Typer::Visitor::TypeFloat32Constant(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400616 return Bounds(Type::Intersect(
617 Type::Of(OpParameter<float>(node), zone()),
618 Type::UntaggedFloat32(), zone()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000619}
620
621
622Bounds Typer::Visitor::TypeFloat64Constant(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400623 return Bounds(Type::Intersect(
624 Type::Of(OpParameter<double>(node), zone()),
625 Type::UntaggedFloat64(), zone()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000626}
627
628
629Bounds Typer::Visitor::TypeNumberConstant(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400630 Factory* f = isolate()->factory();
631 return Bounds(Type::Constant(
632 f->NewNumber(OpParameter<double>(node)), zone()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000633}
634
635
636Bounds Typer::Visitor::TypeHeapConstant(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400637 return Bounds(TypeConstant(OpParameter<Unique<HeapObject> >(node).handle()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000638}
639
640
641Bounds Typer::Visitor::TypeExternalConstant(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400642 return Bounds(Type::None(zone()), Type::Internal(zone()));
643}
644
645
646Bounds Typer::Visitor::TypeSelect(Node* node) {
647 return Bounds::Either(Operand(node, 1), Operand(node, 2), zone());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000648}
649
650
651Bounds Typer::Visitor::TypePhi(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400652 int arity = node->op()->ValueInputCount();
653 Bounds bounds = Operand(node, 0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000654 for (int i = 1; i < arity; ++i) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400655 bounds = Bounds::Either(bounds, Operand(node, i), zone());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000656 }
657 return bounds;
658}
659
660
661Bounds Typer::Visitor::TypeEffectPhi(Node* node) {
662 UNREACHABLE();
663 return Bounds();
664}
665
666
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000667Bounds Typer::Visitor::TypeValueEffect(Node* node) {
668 UNREACHABLE();
669 return Bounds();
670}
671
672
673Bounds Typer::Visitor::TypeFinish(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400674 return Operand(node, 0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000675}
676
677
678Bounds Typer::Visitor::TypeFrameState(Node* node) {
679 // TODO(rossberg): Ideally FrameState wouldn't have a value output.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400680 return Bounds(Type::None(zone()), Type::Internal(zone()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000681}
682
683
684Bounds Typer::Visitor::TypeStateValues(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400685 return Bounds(Type::None(zone()), Type::Internal(zone()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000686}
687
688
689Bounds Typer::Visitor::TypeCall(Node* node) {
690 return Bounds::Unbounded(zone());
691}
692
693
694Bounds Typer::Visitor::TypeProjection(Node* node) {
695 // TODO(titzer): use the output type of the input to determine the bounds.
696 return Bounds::Unbounded(zone());
697}
698
699
700// JS comparison operators.
701
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400702
703Type* Typer::Visitor::JSEqualTyper(Type* lhs, Type* rhs, Typer* t) {
704 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return t->singleton_false;
705 if (lhs->Is(t->undefined_or_null) && rhs->Is(t->undefined_or_null)) {
706 return t->singleton_true;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000707 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400708 if (lhs->Is(Type::Number()) && rhs->Is(Type::Number()) &&
709 (lhs->Max() < rhs->Min() || lhs->Min() > rhs->Max())) {
710 return t->singleton_false;
711 }
712 if (lhs->IsConstant() && rhs->Is(lhs)) {
713 // Types are equal and are inhabited only by a single semantic value,
714 // which is not nan due to the earlier check.
715 // TODO(neis): Extend this to Range(x,x), MinusZero, ...?
716 return t->singleton_true;
717 }
718 return Type::Boolean();
719}
720
721
722Type* Typer::Visitor::JSNotEqualTyper(Type* lhs, Type* rhs, Typer* t) {
723 return Invert(JSEqualTyper(lhs, rhs, t), t);
724}
725
726
727static Type* JSType(Type* type) {
728 if (type->Is(Type::Boolean())) return Type::Boolean();
729 if (type->Is(Type::String())) return Type::String();
730 if (type->Is(Type::Number())) return Type::Number();
731 if (type->Is(Type::Undefined())) return Type::Undefined();
732 if (type->Is(Type::Null())) return Type::Null();
733 if (type->Is(Type::Symbol())) return Type::Symbol();
734 if (type->Is(Type::Receiver())) return Type::Receiver(); // JS "Object"
735 return Type::Any();
736}
737
738
739Type* Typer::Visitor::JSStrictEqualTyper(Type* lhs, Type* rhs, Typer* t) {
740 if (!JSType(lhs)->Maybe(JSType(rhs))) return t->singleton_false;
741 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return t->singleton_false;
742 if (lhs->Is(Type::Number()) && rhs->Is(Type::Number()) &&
743 (lhs->Max() < rhs->Min() || lhs->Min() > rhs->Max())) {
744 return t->singleton_false;
745 }
746 if (lhs->IsConstant() && rhs->Is(lhs)) {
747 // Types are equal and are inhabited only by a single semantic value,
748 // which is not nan due to the earlier check.
749 return t->singleton_true;
750 }
751 return Type::Boolean();
752}
753
754
755Type* Typer::Visitor::JSStrictNotEqualTyper(Type* lhs, Type* rhs, Typer* t) {
756 return Invert(JSStrictEqualTyper(lhs, rhs, t), t);
757}
758
759
760// The EcmaScript specification defines the four relational comparison operators
761// (<, <=, >=, >) with the help of a single abstract one. It behaves like <
762// but returns undefined when the inputs cannot be compared.
763// We implement the typing analogously.
764Type* Typer::Visitor::JSCompareTyper(Type* lhs, Type* rhs, Typer* t) {
765 lhs = ToPrimitive(lhs, t);
766 rhs = ToPrimitive(rhs, t);
767 if (lhs->Maybe(Type::String()) && rhs->Maybe(Type::String())) {
768 return Type::Boolean();
769 }
770 lhs = ToNumber(lhs, t);
771 rhs = ToNumber(rhs, t);
772 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::Undefined();
773 if (lhs->IsConstant() && rhs->Is(lhs)) {
774 // Types are equal and are inhabited only by a single semantic value,
775 // which is not NaN due to the previous check.
776 return t->singleton_false;
777 }
778 if (lhs->Min() >= rhs->Max()) return t->singleton_false;
779 if (lhs->Max() < rhs->Min() &&
780 !lhs->Maybe(Type::NaN()) && !rhs->Maybe(Type::NaN())) {
781 return t->singleton_true;
782 }
783 return Type::Boolean();
784}
785
786
787Type* Typer::Visitor::JSLessThanTyper(Type* lhs, Type* rhs, Typer* t) {
788 return FalsifyUndefined(JSCompareTyper(lhs, rhs, t), t);
789}
790
791
792Type* Typer::Visitor::JSGreaterThanTyper(Type* lhs, Type* rhs, Typer* t) {
793 return FalsifyUndefined(JSCompareTyper(rhs, lhs, t), t);
794}
795
796
797Type* Typer::Visitor::JSLessThanOrEqualTyper(Type* lhs, Type* rhs, Typer* t) {
798 return FalsifyUndefined(Invert(JSCompareTyper(rhs, lhs, t), t), t);
799}
800
801
802Type* Typer::Visitor::JSGreaterThanOrEqualTyper(
803 Type* lhs, Type* rhs, Typer* t) {
804 return FalsifyUndefined(Invert(JSCompareTyper(lhs, rhs, t), t), t);
805}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000806
807
808// JS bitwise operators.
809
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400810
811Type* Typer::Visitor::JSBitwiseOrTyper(Type* lhs, Type* rhs, Typer* t) {
812 Factory* f = t->isolate()->factory();
813 lhs = NumberToInt32(ToNumber(lhs, t), t);
814 rhs = NumberToInt32(ToNumber(rhs, t), t);
815 double lmin = lhs->Min();
816 double rmin = rhs->Min();
817 double lmax = lhs->Max();
818 double rmax = rhs->Max();
819 // Or-ing any two values results in a value no smaller than their minimum.
820 // Even no smaller than their maximum if both values are non-negative.
821 double min =
822 lmin >= 0 && rmin >= 0 ? std::max(lmin, rmin) : std::min(lmin, rmin);
823 double max = Type::Signed32()->Max();
824
825 // Or-ing with 0 is essentially a conversion to int32.
826 if (rmin == 0 && rmax == 0) {
827 min = lmin;
828 max = lmax;
829 }
830 if (lmin == 0 && lmax == 0) {
831 min = rmin;
832 max = rmax;
833 }
834
835 if (lmax < 0 || rmax < 0) {
836 // Or-ing two values of which at least one is negative results in a negative
837 // value.
838 max = std::min(max, -1.0);
839 }
840 return Type::Range(f->NewNumber(min), f->NewNumber(max), t->zone());
841 // TODO(neis): Be precise for singleton inputs, here and elsewhere.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000842}
843
844
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400845Type* Typer::Visitor::JSBitwiseAndTyper(Type* lhs, Type* rhs, Typer* t) {
846 Factory* f = t->isolate()->factory();
847 lhs = NumberToInt32(ToNumber(lhs, t), t);
848 rhs = NumberToInt32(ToNumber(rhs, t), t);
849 double lmin = lhs->Min();
850 double rmin = rhs->Min();
851 double lmax = lhs->Max();
852 double rmax = rhs->Max();
853 double min = Type::Signed32()->Min();
854 // And-ing any two values results in a value no larger than their maximum.
855 // Even no larger than their minimum if both values are non-negative.
856 double max =
857 lmin >= 0 && rmin >= 0 ? std::min(lmax, rmax) : std::max(lmax, rmax);
858 // And-ing with a non-negative value x causes the result to be between
859 // zero and x.
860 if (lmin >= 0) {
861 min = 0;
862 max = std::min(max, lmax);
863 }
864 if (rmin >= 0) {
865 min = 0;
866 max = std::min(max, rmax);
867 }
868 return Type::Range(f->NewNumber(min), f->NewNumber(max), t->zone());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000869}
870
871
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400872Type* Typer::Visitor::JSBitwiseXorTyper(Type* lhs, Type* rhs, Typer* t) {
873 lhs = NumberToInt32(ToNumber(lhs, t), t);
874 rhs = NumberToInt32(ToNumber(rhs, t), t);
875 double lmin = lhs->Min();
876 double rmin = rhs->Min();
877 double lmax = lhs->Max();
878 double rmax = rhs->Max();
879 if ((lmin >= 0 && rmin >= 0) || (lmax < 0 && rmax < 0)) {
880 // Xor-ing negative or non-negative values results in a non-negative value.
881 return Type::NonNegativeSigned32();
882 }
883 if ((lmax < 0 && rmin >= 0) || (lmin >= 0 && rmax < 0)) {
884 // Xor-ing a negative and a non-negative value results in a negative value.
885 // TODO(jarin) Use a range here.
886 return Type::NegativeSigned32();
887 }
888 return Type::Signed32();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000889}
890
891
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400892Type* Typer::Visitor::JSShiftLeftTyper(Type* lhs, Type* rhs, Typer* t) {
893 return Type::Signed32();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000894}
895
896
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400897Type* Typer::Visitor::JSShiftRightTyper(Type* lhs, Type* rhs, Typer* t) {
898 lhs = NumberToInt32(ToNumber(lhs, t), t);
899 rhs = NumberToUint32(ToNumber(rhs, t), t);
900 double min = kMinInt;
901 double max = kMaxInt;
902 if (lhs->Min() >= 0) {
903 // Right-shifting a non-negative value cannot make it negative, nor larger.
904 min = std::max(min, 0.0);
905 max = std::min(max, lhs->Max());
906 }
907 if (lhs->Max() < 0) {
908 // Right-shifting a negative value cannot make it non-negative, nor smaller.
909 min = std::max(min, lhs->Min());
910 max = std::min(max, -1.0);
911 }
912 if (rhs->Min() > 0 && rhs->Max() <= 31) {
913 // Right-shifting by a positive value yields a small integer value.
914 double shift_min = kMinInt >> static_cast<int>(rhs->Min());
915 double shift_max = kMaxInt >> static_cast<int>(rhs->Min());
916 min = std::max(min, shift_min);
917 max = std::min(max, shift_max);
918 }
919 // TODO(jarin) Ideally, the following micro-optimization should be performed
920 // by the type constructor.
921 if (max != Type::Signed32()->Max() || min != Type::Signed32()->Min()) {
922 Factory* f = t->isolate()->factory();
923 return Type::Range(f->NewNumber(min), f->NewNumber(max), t->zone());
924 }
925 return Type::Signed32();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000926}
927
928
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400929Type* Typer::Visitor::JSShiftRightLogicalTyper(Type* lhs, Type* rhs, Typer* t) {
930 lhs = NumberToUint32(ToNumber(lhs, t), t);
931 Factory* f = t->isolate()->factory();
932 // Logical right-shifting any value cannot make it larger.
933 Handle<Object> min = f->NewNumber(0);
934 Handle<Object> max = f->NewNumber(lhs->Max());
935 return Type::Range(min, max, t->zone());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000936}
937
938
939// JS arithmetic operators.
940
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400941
942// Returns the array's least element, ignoring NaN.
943// There must be at least one non-NaN element.
944// Any -0 is converted to 0.
945static double array_min(double a[], size_t n) {
946 DCHECK(n != 0);
947 double x = +V8_INFINITY;
948 for (size_t i = 0; i < n; ++i) {
949 if (!std::isnan(a[i])) {
950 x = std::min(a[i], x);
951 }
952 }
953 DCHECK(!std::isnan(x));
954 return x == 0 ? 0 : x; // -0 -> 0
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000955}
956
957
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400958// Returns the array's greatest element, ignoring NaN.
959// There must be at least one non-NaN element.
960// Any -0 is converted to 0.
961static double array_max(double a[], size_t n) {
962 DCHECK(n != 0);
963 double x = -V8_INFINITY;
964 for (size_t i = 0; i < n; ++i) {
965 if (!std::isnan(a[i])) {
966 x = std::max(a[i], x);
967 }
968 }
969 DCHECK(!std::isnan(x));
970 return x == 0 ? 0 : x; // -0 -> 0
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000971}
972
973
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400974Type* Typer::Visitor::JSAddRanger(Type::RangeType* lhs, Type::RangeType* rhs,
975 Typer* t) {
976 double results[4];
977 results[0] = lhs->Min()->Number() + rhs->Min()->Number();
978 results[1] = lhs->Min()->Number() + rhs->Max()->Number();
979 results[2] = lhs->Max()->Number() + rhs->Min()->Number();
980 results[3] = lhs->Max()->Number() + rhs->Max()->Number();
981 // Since none of the inputs can be -0, the result cannot be -0 either.
982 // However, it can be nan (the sum of two infinities of opposite sign).
983 // On the other hand, if none of the "results" above is nan, then the actual
984 // result cannot be nan either.
985 int nans = 0;
986 for (int i = 0; i < 4; ++i) {
987 if (std::isnan(results[i])) ++nans;
988 }
989 if (nans == 4) return Type::NaN(); // [-inf..-inf] + [inf..inf] or vice versa
990 Factory* f = t->isolate()->factory();
991 Type* range = Type::Range(f->NewNumber(array_min(results, 4)),
992 f->NewNumber(array_max(results, 4)), t->zone());
993 return nans == 0 ? range : Type::Union(range, Type::NaN(), t->zone());
994 // Examples:
995 // [-inf, -inf] + [+inf, +inf] = NaN
996 // [-inf, -inf] + [n, +inf] = [-inf, -inf] \/ NaN
997 // [-inf, +inf] + [n, +inf] = [-inf, +inf] \/ NaN
998 // [-inf, m] + [n, +inf] = [-inf, +inf] \/ NaN
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000999}
1000
1001
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001002Type* Typer::Visitor::JSAddTyper(Type* lhs, Type* rhs, Typer* t) {
1003 lhs = ToPrimitive(lhs, t);
1004 rhs = ToPrimitive(rhs, t);
1005 if (lhs->Maybe(Type::String()) || rhs->Maybe(Type::String())) {
1006 if (lhs->Is(Type::String()) || rhs->Is(Type::String())) {
1007 return Type::String();
1008 } else {
1009 return Type::NumberOrString();
1010 }
1011 }
1012 lhs = Rangify(ToNumber(lhs, t), t);
1013 rhs = Rangify(ToNumber(rhs, t), t);
1014 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN();
1015 if (lhs->IsRange() && rhs->IsRange()) {
1016 return JSAddRanger(lhs->AsRange(), rhs->AsRange(), t);
1017 }
1018 // TODO(neis): Deal with numeric bitsets here and elsewhere.
1019 return Type::Number();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001020}
1021
1022
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001023Type* Typer::Visitor::JSSubtractRanger(Type::RangeType* lhs,
1024 Type::RangeType* rhs, Typer* t) {
1025 double results[4];
1026 results[0] = lhs->Min()->Number() - rhs->Min()->Number();
1027 results[1] = lhs->Min()->Number() - rhs->Max()->Number();
1028 results[2] = lhs->Max()->Number() - rhs->Min()->Number();
1029 results[3] = lhs->Max()->Number() - rhs->Max()->Number();
1030 // Since none of the inputs can be -0, the result cannot be -0.
1031 // However, it can be nan (the subtraction of two infinities of same sign).
1032 // On the other hand, if none of the "results" above is nan, then the actual
1033 // result cannot be nan either.
1034 int nans = 0;
1035 for (int i = 0; i < 4; ++i) {
1036 if (std::isnan(results[i])) ++nans;
1037 }
1038 if (nans == 4) return Type::NaN(); // [inf..inf] - [inf..inf] (all same sign)
1039 Factory* f = t->isolate()->factory();
1040 Type* range = Type::Range(f->NewNumber(array_min(results, 4)),
1041 f->NewNumber(array_max(results, 4)), t->zone());
1042 return nans == 0 ? range : Type::Union(range, Type::NaN(), t->zone());
1043 // Examples:
1044 // [-inf, +inf] - [-inf, +inf] = [-inf, +inf] \/ NaN
1045 // [-inf, -inf] - [-inf, -inf] = NaN
1046 // [-inf, -inf] - [n, +inf] = [-inf, -inf] \/ NaN
1047 // [m, +inf] - [-inf, n] = [-inf, +inf] \/ NaN
1048}
1049
1050
1051Type* Typer::Visitor::JSSubtractTyper(Type* lhs, Type* rhs, Typer* t) {
1052 lhs = Rangify(ToNumber(lhs, t), t);
1053 rhs = Rangify(ToNumber(rhs, t), t);
1054 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN();
1055 if (lhs->IsRange() && rhs->IsRange()) {
1056 return JSSubtractRanger(lhs->AsRange(), rhs->AsRange(), t);
1057 }
1058 return Type::Number();
1059}
1060
1061
1062Type* Typer::Visitor::JSMultiplyRanger(Type::RangeType* lhs,
1063 Type::RangeType* rhs, Typer* t) {
1064 double results[4];
1065 double lmin = lhs->Min()->Number();
1066 double lmax = lhs->Max()->Number();
1067 double rmin = rhs->Min()->Number();
1068 double rmax = rhs->Max()->Number();
1069 results[0] = lmin * rmin;
1070 results[1] = lmin * rmax;
1071 results[2] = lmax * rmin;
1072 results[3] = lmax * rmax;
1073 // If the result may be nan, we give up on calculating a precise type, because
1074 // the discontinuity makes it too complicated. Note that even if none of the
1075 // "results" above is nan, the actual result may still be, so we have to do a
1076 // different check:
1077 bool maybe_nan = (lhs->Maybe(t->singleton_zero) &&
1078 (rmin == -V8_INFINITY || rmax == +V8_INFINITY)) ||
1079 (rhs->Maybe(t->singleton_zero) &&
1080 (lmin == -V8_INFINITY || lmax == +V8_INFINITY));
1081 if (maybe_nan) return t->weakint; // Giving up.
1082 bool maybe_minuszero = (lhs->Maybe(t->singleton_zero) && rmin < 0) ||
1083 (rhs->Maybe(t->singleton_zero) && lmin < 0);
1084 Factory* f = t->isolate()->factory();
1085 Type* range = Type::Range(f->NewNumber(array_min(results, 4)),
1086 f->NewNumber(array_max(results, 4)), t->zone());
1087 return maybe_minuszero ? Type::Union(range, Type::MinusZero(), t->zone())
1088 : range;
1089}
1090
1091
1092Type* Typer::Visitor::JSMultiplyTyper(Type* lhs, Type* rhs, Typer* t) {
1093 lhs = Rangify(ToNumber(lhs, t), t);
1094 rhs = Rangify(ToNumber(rhs, t), t);
1095 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN();
1096 if (lhs->IsRange() && rhs->IsRange()) {
1097 return JSMultiplyRanger(lhs->AsRange(), rhs->AsRange(), t);
1098 }
1099 return Type::Number();
1100}
1101
1102
1103Type* Typer::Visitor::JSDivideTyper(Type* lhs, Type* rhs, Typer* t) {
1104 lhs = ToNumber(lhs, t);
1105 rhs = ToNumber(rhs, t);
1106 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN();
1107 // Division is tricky, so all we do is try ruling out nan.
1108 // TODO(neis): try ruling out -0 as well?
1109 bool maybe_nan =
1110 lhs->Maybe(Type::NaN()) || rhs->Maybe(t->zeroish) ||
1111 ((lhs->Min() == -V8_INFINITY || lhs->Max() == +V8_INFINITY) &&
1112 (rhs->Min() == -V8_INFINITY || rhs->Max() == +V8_INFINITY));
1113 return maybe_nan ? Type::Number() : Type::OrderedNumber();
1114}
1115
1116
1117Type* Typer::Visitor::JSModulusRanger(Type::RangeType* lhs,
1118 Type::RangeType* rhs, Typer* t) {
1119 double lmin = lhs->Min()->Number();
1120 double lmax = lhs->Max()->Number();
1121 double rmin = rhs->Min()->Number();
1122 double rmax = rhs->Max()->Number();
1123
1124 double labs = std::max(std::abs(lmin), std::abs(lmax));
1125 double rabs = std::max(std::abs(rmin), std::abs(rmax)) - 1;
1126 double abs = std::min(labs, rabs);
1127 bool maybe_minus_zero = false;
1128 double omin = 0;
1129 double omax = 0;
1130 if (lmin >= 0) { // {lhs} positive.
1131 omin = 0;
1132 omax = abs;
1133 } else if (lmax <= 0) { // {lhs} negative.
1134 omin = 0 - abs;
1135 omax = 0;
1136 maybe_minus_zero = true;
1137 } else {
1138 omin = 0 - abs;
1139 omax = abs;
1140 maybe_minus_zero = true;
1141 }
1142
1143 Factory* f = t->isolate()->factory();
1144 Type* result = Type::Range(f->NewNumber(omin), f->NewNumber(omax), t->zone());
1145 if (maybe_minus_zero)
1146 result = Type::Union(result, Type::MinusZero(), t->zone());
1147 return result;
1148}
1149
1150
1151Type* Typer::Visitor::JSModulusTyper(Type* lhs, Type* rhs, Typer* t) {
1152 lhs = ToNumber(lhs, t);
1153 rhs = ToNumber(rhs, t);
1154 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN();
1155
1156 if (lhs->Maybe(Type::NaN()) || rhs->Maybe(t->zeroish) ||
1157 lhs->Min() == -V8_INFINITY || lhs->Max() == +V8_INFINITY) {
1158 // Result maybe NaN.
1159 return Type::Number();
1160 }
1161
1162 lhs = Rangify(lhs, t);
1163 rhs = Rangify(rhs, t);
1164 if (lhs->IsRange() && rhs->IsRange()) {
1165 return JSModulusRanger(lhs->AsRange(), rhs->AsRange(), t);
1166 }
1167 return Type::OrderedNumber();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001168}
1169
1170
1171// JS unary operators.
1172
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001173
1174Type* Typer::Visitor::JSUnaryNotTyper(Type* type, Typer* t) {
1175 return Invert(ToBoolean(type, t), t);
1176}
1177
1178
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001179Bounds Typer::Visitor::TypeJSUnaryNot(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001180 return TypeUnaryOp(node, JSUnaryNotTyper);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001181}
1182
1183
1184Bounds Typer::Visitor::TypeJSTypeOf(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001185 return Bounds(Type::None(zone()), Type::InternalizedString(zone()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001186}
1187
1188
1189// JS conversion operators.
1190
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001191
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001192Bounds Typer::Visitor::TypeJSToBoolean(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001193 return TypeUnaryOp(node, ToBoolean);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001194}
1195
1196
1197Bounds Typer::Visitor::TypeJSToNumber(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001198 return TypeUnaryOp(node, ToNumber);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001199}
1200
1201
1202Bounds Typer::Visitor::TypeJSToString(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001203 return TypeUnaryOp(node, ToString);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001204}
1205
1206
1207Bounds Typer::Visitor::TypeJSToName(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001208 return Bounds(Type::None(), Type::Name());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001209}
1210
1211
1212Bounds Typer::Visitor::TypeJSToObject(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001213 return Bounds(Type::None(), Type::Receiver());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001214}
1215
1216
1217// JS object operators.
1218
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001219
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001220Bounds Typer::Visitor::TypeJSCreate(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001221 return Bounds(Type::None(), Type::Object());
1222}
1223
1224
1225Type* Typer::Visitor::JSLoadPropertyTyper(Type* object, Type* name, Typer* t) {
1226 // TODO(rossberg): Use range types and sized array types to filter undefined.
1227 if (object->IsArray() && name->Is(Type::Integral32())) {
1228 return Type::Union(
1229 object->AsArray()->Element(), Type::Undefined(), t->zone());
1230 }
1231 return Type::Any();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001232}
1233
1234
1235Bounds Typer::Visitor::TypeJSLoadProperty(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001236 return TypeBinaryOp(node, JSLoadPropertyTyper);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001237}
1238
1239
1240Bounds Typer::Visitor::TypeJSLoadNamed(Node* node) {
1241 return Bounds::Unbounded(zone());
1242}
1243
1244
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001245// Returns a somewhat larger range if we previously assigned
1246// a (smaller) range to this node. This is used to speed up
1247// the fixpoint calculation in case there appears to be a loop
1248// in the graph. In the current implementation, we are
1249// increasing the limits to the closest power of two.
1250Type* Typer::Visitor::Weaken(Type* current_type, Type* previous_type) {
1251 Type::RangeType* previous = previous_type->GetRange();
1252 Type::RangeType* current = current_type->GetRange();
1253 if (previous != NULL && current != NULL) {
1254 double current_min = current->Min()->Number();
1255 Handle<Object> new_min = current->Min();
1256
1257 // Find the closest lower entry in the list of allowed
1258 // minima (or negative infinity if there is no such entry).
1259 if (current_min != previous->Min()->Number()) {
1260 new_min = typer_->integer->AsRange()->Min();
1261 for (const auto val : typer_->weaken_min_limits_) {
1262 if (val->Number() <= current_min) {
1263 new_min = val;
1264 break;
1265 }
1266 }
1267 }
1268
1269 double current_max = current->Max()->Number();
1270 Handle<Object> new_max = current->Max();
1271 // Find the closest greater entry in the list of allowed
1272 // maxima (or infinity if there is no such entry).
1273 if (current_max != previous->Max()->Number()) {
1274 new_max = typer_->integer->AsRange()->Max();
1275 for (const auto val : typer_->weaken_max_limits_) {
1276 if (val->Number() >= current_max) {
1277 new_max = val;
1278 break;
1279 }
1280 }
1281 }
1282
1283 return Type::Union(current_type,
1284 Type::Range(new_min, new_max, typer_->zone()),
1285 typer_->zone());
1286 }
1287 return current_type;
1288}
1289
1290
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001291Bounds Typer::Visitor::TypeJSStoreProperty(Node* node) {
1292 UNREACHABLE();
1293 return Bounds();
1294}
1295
1296
1297Bounds Typer::Visitor::TypeJSStoreNamed(Node* node) {
1298 UNREACHABLE();
1299 return Bounds();
1300}
1301
1302
1303Bounds Typer::Visitor::TypeJSDeleteProperty(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001304 return Bounds(Type::None(zone()), Type::Boolean(zone()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001305}
1306
1307
1308Bounds Typer::Visitor::TypeJSHasProperty(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001309 return Bounds(Type::None(zone()), Type::Boolean(zone()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001310}
1311
1312
1313Bounds Typer::Visitor::TypeJSInstanceOf(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001314 return Bounds(Type::None(zone()), Type::Boolean(zone()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001315}
1316
1317
1318// JS context operators.
1319
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001320
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001321Bounds Typer::Visitor::TypeJSLoadContext(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001322 Bounds outer = Operand(node, 0);
1323 Type* context_type = outer.upper;
1324 if (context_type->Is(Type::None())) {
1325 // Upper bound of context is not yet known.
1326 return Bounds(Type::None(), Type::Any());
1327 }
1328
1329 DCHECK(context_type->Maybe(Type::Internal()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001330 // TODO(rossberg): More precisely, instead of the above assertion, we should
1331 // back-propagate the constraint that it has to be a subtype of Internal.
1332
1333 ContextAccess access = OpParameter<ContextAccess>(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001334 MaybeHandle<Context> context;
1335 if (context_type->IsConstant()) {
1336 context = Handle<Context>::cast(context_type->AsConstant()->Value());
1337 }
1338 // Walk context chain (as far as known), mirroring dynamic lookup.
1339 // Since contexts are mutable, the information is only useful as a lower
1340 // bound.
1341 // TODO(rossberg): Could use scope info to fix upper bounds for constant
1342 // bindings if we know that this code is never shared.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001343 for (size_t i = access.depth(); i > 0; --i) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001344 if (context_type->IsContext()) {
1345 context_type = context_type->AsContext()->Outer();
1346 if (context_type->IsConstant()) {
1347 context = Handle<Context>::cast(context_type->AsConstant()->Value());
1348 }
1349 } else if (!context.is_null()) {
1350 context = handle(context.ToHandleChecked()->previous(), isolate());
1351 }
1352 }
1353 if (context.is_null()) {
1354 return Bounds::Unbounded(zone());
1355 } else {
1356 Handle<Object> value =
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001357 handle(context.ToHandleChecked()->get(static_cast<int>(access.index())),
1358 isolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001359 Type* lower = TypeConstant(value);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001360 return Bounds(lower, Type::Any());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001361 }
1362}
1363
1364
1365Bounds Typer::Visitor::TypeJSStoreContext(Node* node) {
1366 UNREACHABLE();
1367 return Bounds();
1368}
1369
1370
1371Bounds Typer::Visitor::TypeJSCreateFunctionContext(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001372 Bounds outer = ContextOperand(node);
1373 return Bounds(Type::Context(outer.upper, zone()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001374}
1375
1376
1377Bounds Typer::Visitor::TypeJSCreateCatchContext(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001378 Bounds outer = ContextOperand(node);
1379 return Bounds(Type::Context(outer.upper, zone()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001380}
1381
1382
1383Bounds Typer::Visitor::TypeJSCreateWithContext(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001384 Bounds outer = ContextOperand(node);
1385 return Bounds(Type::Context(outer.upper, zone()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001386}
1387
1388
1389Bounds Typer::Visitor::TypeJSCreateBlockContext(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001390 Bounds outer = ContextOperand(node);
1391 return Bounds(Type::Context(outer.upper, zone()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001392}
1393
1394
1395Bounds Typer::Visitor::TypeJSCreateModuleContext(Node* node) {
1396 // TODO(rossberg): this is probably incorrect
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001397 Bounds outer = ContextOperand(node);
1398 return Bounds(Type::Context(outer.upper, zone()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001399}
1400
1401
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001402Bounds Typer::Visitor::TypeJSCreateScriptContext(Node* node) {
1403 Bounds outer = ContextOperand(node);
1404 return Bounds(Type::Context(outer.upper, zone()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001405}
1406
1407
1408// JS other operators.
1409
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001410
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001411Bounds Typer::Visitor::TypeJSYield(Node* node) {
1412 return Bounds::Unbounded(zone());
1413}
1414
1415
1416Bounds Typer::Visitor::TypeJSCallConstruct(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001417 return Bounds(Type::None(), Type::Receiver());
1418}
1419
1420
1421Type* Typer::Visitor::JSCallFunctionTyper(Type* fun, Typer* t) {
1422 return fun->IsFunction() ? fun->AsFunction()->Result() : Type::Any();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001423}
1424
1425
1426Bounds Typer::Visitor::TypeJSCallFunction(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001427 return TypeUnaryOp(node, JSCallFunctionTyper); // We ignore argument types.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001428}
1429
1430
1431Bounds Typer::Visitor::TypeJSCallRuntime(Node* node) {
1432 return Bounds::Unbounded(zone());
1433}
1434
1435
1436Bounds Typer::Visitor::TypeJSDebugger(Node* node) {
1437 return Bounds::Unbounded(zone());
1438}
1439
1440
1441// Simplified operators.
1442
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001443
1444Bounds Typer::Visitor::TypeAnyToBoolean(Node* node) {
1445 return TypeUnaryOp(node, ToBoolean);
1446}
1447
1448
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001449Bounds Typer::Visitor::TypeBooleanNot(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001450 return Bounds(Type::None(zone()), Type::Boolean(zone()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001451}
1452
1453
1454Bounds Typer::Visitor::TypeBooleanToNumber(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001455 return Bounds(Type::None(zone()), typer_->zero_or_one);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001456}
1457
1458
1459Bounds Typer::Visitor::TypeNumberEqual(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001460 return Bounds(Type::None(zone()), Type::Boolean(zone()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001461}
1462
1463
1464Bounds Typer::Visitor::TypeNumberLessThan(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001465 return Bounds(Type::None(zone()), Type::Boolean(zone()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001466}
1467
1468
1469Bounds Typer::Visitor::TypeNumberLessThanOrEqual(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001470 return Bounds(Type::None(zone()), Type::Boolean(zone()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001471}
1472
1473
1474Bounds Typer::Visitor::TypeNumberAdd(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001475 return Bounds(Type::None(zone()), Type::Number(zone()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001476}
1477
1478
1479Bounds Typer::Visitor::TypeNumberSubtract(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001480 return Bounds(Type::None(zone()), Type::Number(zone()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001481}
1482
1483
1484Bounds Typer::Visitor::TypeNumberMultiply(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001485 return Bounds(Type::None(zone()), Type::Number(zone()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001486}
1487
1488
1489Bounds Typer::Visitor::TypeNumberDivide(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001490 return Bounds(Type::None(zone()), Type::Number(zone()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001491}
1492
1493
1494Bounds Typer::Visitor::TypeNumberModulus(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001495 return Bounds(Type::None(zone()), Type::Number(zone()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001496}
1497
1498
1499Bounds Typer::Visitor::TypeNumberToInt32(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001500 return TypeUnaryOp(node, NumberToInt32);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001501}
1502
1503
1504Bounds Typer::Visitor::TypeNumberToUint32(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001505 return TypeUnaryOp(node, NumberToUint32);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001506}
1507
1508
1509Bounds Typer::Visitor::TypeReferenceEqual(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001510 return Bounds(Type::None(zone()), Type::Boolean(zone()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001511}
1512
1513
1514Bounds Typer::Visitor::TypeStringEqual(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001515 return Bounds(Type::None(zone()), Type::Boolean(zone()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001516}
1517
1518
1519Bounds Typer::Visitor::TypeStringLessThan(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001520 return Bounds(Type::None(zone()), Type::Boolean(zone()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001521}
1522
1523
1524Bounds Typer::Visitor::TypeStringLessThanOrEqual(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001525 return Bounds(Type::None(zone()), Type::Boolean(zone()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001526}
1527
1528
1529Bounds Typer::Visitor::TypeStringAdd(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001530 return Bounds(Type::None(zone()), Type::String(zone()));
1531}
1532
1533
1534static Type* ChangeRepresentation(Type* type, Type* rep, Zone* zone) {
1535 // TODO(neis): Enable when expressible.
1536 /*
1537 return Type::Union(
1538 Type::Intersect(type, Type::Semantic(), zone),
1539 Type::Intersect(rep, Type::Representation(), zone), zone);
1540 */
1541 return type;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001542}
1543
1544
1545Bounds Typer::Visitor::TypeChangeTaggedToInt32(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001546 Bounds arg = Operand(node, 0);
1547 // TODO(neis): DCHECK(arg.upper->Is(Type::Signed32()));
1548 return Bounds(
1549 ChangeRepresentation(arg.lower, Type::UntaggedSigned32(), zone()),
1550 ChangeRepresentation(arg.upper, Type::UntaggedSigned32(), zone()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001551}
1552
1553
1554Bounds Typer::Visitor::TypeChangeTaggedToUint32(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001555 Bounds arg = Operand(node, 0);
1556 // TODO(neis): DCHECK(arg.upper->Is(Type::Unsigned32()));
1557 return Bounds(
1558 ChangeRepresentation(arg.lower, Type::UntaggedUnsigned32(), zone()),
1559 ChangeRepresentation(arg.upper, Type::UntaggedUnsigned32(), zone()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001560}
1561
1562
1563Bounds Typer::Visitor::TypeChangeTaggedToFloat64(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001564 Bounds arg = Operand(node, 0);
1565 // TODO(neis): DCHECK(arg.upper->Is(Type::Number()));
1566 return Bounds(
1567 ChangeRepresentation(arg.lower, Type::UntaggedFloat64(), zone()),
1568 ChangeRepresentation(arg.upper, Type::UntaggedFloat64(), zone()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001569}
1570
1571
1572Bounds Typer::Visitor::TypeChangeInt32ToTagged(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001573 Bounds arg = Operand(node, 0);
1574 // TODO(neis): DCHECK(arg.upper->Is(Type::Signed32()));
1575 return Bounds(
1576 ChangeRepresentation(arg.lower, Type::Tagged(), zone()),
1577 ChangeRepresentation(arg.upper, Type::Tagged(), zone()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001578}
1579
1580
1581Bounds Typer::Visitor::TypeChangeUint32ToTagged(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001582 Bounds arg = Operand(node, 0);
1583 // TODO(neis): DCHECK(arg.upper->Is(Type::Unsigned32()));
1584 return Bounds(
1585 ChangeRepresentation(arg.lower, Type::Tagged(), zone()),
1586 ChangeRepresentation(arg.upper, Type::Tagged(), zone()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001587}
1588
1589
1590Bounds Typer::Visitor::TypeChangeFloat64ToTagged(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001591 Bounds arg = Operand(node, 0);
1592 // TODO(neis): CHECK(arg.upper->Is(Type::Number()));
1593 return Bounds(
1594 ChangeRepresentation(arg.lower, Type::Tagged(), zone()),
1595 ChangeRepresentation(arg.upper, Type::Tagged(), zone()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001596}
1597
1598
1599Bounds Typer::Visitor::TypeChangeBoolToBit(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001600 Bounds arg = Operand(node, 0);
1601 // TODO(neis): DCHECK(arg.upper->Is(Type::Boolean()));
1602 return Bounds(
1603 ChangeRepresentation(arg.lower, Type::UntaggedBit(), zone()),
1604 ChangeRepresentation(arg.upper, Type::UntaggedBit(), zone()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001605}
1606
1607
1608Bounds Typer::Visitor::TypeChangeBitToBool(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001609 Bounds arg = Operand(node, 0);
1610 // TODO(neis): DCHECK(arg.upper->Is(Type::Boolean()));
1611 return Bounds(
1612 ChangeRepresentation(arg.lower, Type::TaggedPointer(), zone()),
1613 ChangeRepresentation(arg.upper, Type::TaggedPointer(), zone()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001614}
1615
1616
1617Bounds Typer::Visitor::TypeLoadField(Node* node) {
1618 return Bounds(FieldAccessOf(node->op()).type);
1619}
1620
1621
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001622Bounds Typer::Visitor::TypeLoadBuffer(Node* node) {
1623 // TODO(bmeurer): This typing is not yet correct. Since we can still access
1624 // out of bounds, the type in the general case has to include Undefined.
1625 switch (BufferAccessOf(node->op()).external_array_type()) {
1626#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
1627 case kExternal##Type##Array: \
1628 return Bounds(typer_->cache_->Get(k##Type));
1629 TYPED_ARRAYS(TYPED_ARRAY_CASE)
1630#undef TYPED_ARRAY_CASE
1631 }
1632 UNREACHABLE();
1633 return Bounds();
1634}
1635
1636
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001637Bounds Typer::Visitor::TypeLoadElement(Node* node) {
1638 return Bounds(ElementAccessOf(node->op()).type);
1639}
1640
1641
1642Bounds Typer::Visitor::TypeStoreField(Node* node) {
1643 UNREACHABLE();
1644 return Bounds();
1645}
1646
1647
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001648Bounds Typer::Visitor::TypeStoreBuffer(Node* node) {
1649 UNREACHABLE();
1650 return Bounds();
1651}
1652
1653
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001654Bounds Typer::Visitor::TypeStoreElement(Node* node) {
1655 UNREACHABLE();
1656 return Bounds();
1657}
1658
1659
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001660Bounds Typer::Visitor::TypeObjectIsSmi(Node* node) {
1661 return Bounds(Type::Boolean());
1662}
1663
1664
1665Bounds Typer::Visitor::TypeObjectIsNonNegativeSmi(Node* node) {
1666 return Bounds(Type::Boolean());
1667}
1668
1669
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001670// Machine operators.
1671
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001672Bounds Typer::Visitor::TypeLoad(Node* node) {
1673 return Bounds::Unbounded(zone());
1674}
1675
1676
1677Bounds Typer::Visitor::TypeStore(Node* node) {
1678 UNREACHABLE();
1679 return Bounds();
1680}
1681
1682
1683Bounds Typer::Visitor::TypeWord32And(Node* node) {
1684 return Bounds(Type::Integral32());
1685}
1686
1687
1688Bounds Typer::Visitor::TypeWord32Or(Node* node) {
1689 return Bounds(Type::Integral32());
1690}
1691
1692
1693Bounds Typer::Visitor::TypeWord32Xor(Node* node) {
1694 return Bounds(Type::Integral32());
1695}
1696
1697
1698Bounds Typer::Visitor::TypeWord32Shl(Node* node) {
1699 return Bounds(Type::Integral32());
1700}
1701
1702
1703Bounds Typer::Visitor::TypeWord32Shr(Node* node) {
1704 return Bounds(Type::Integral32());
1705}
1706
1707
1708Bounds Typer::Visitor::TypeWord32Sar(Node* node) {
1709 return Bounds(Type::Integral32());
1710}
1711
1712
1713Bounds Typer::Visitor::TypeWord32Ror(Node* node) {
1714 return Bounds(Type::Integral32());
1715}
1716
1717
1718Bounds Typer::Visitor::TypeWord32Equal(Node* node) {
1719 return Bounds(Type::Boolean());
1720}
1721
1722
1723Bounds Typer::Visitor::TypeWord64And(Node* node) {
1724 return Bounds(Type::Internal());
1725}
1726
1727
1728Bounds Typer::Visitor::TypeWord64Or(Node* node) {
1729 return Bounds(Type::Internal());
1730}
1731
1732
1733Bounds Typer::Visitor::TypeWord64Xor(Node* node) {
1734 return Bounds(Type::Internal());
1735}
1736
1737
1738Bounds Typer::Visitor::TypeWord64Shl(Node* node) {
1739 return Bounds(Type::Internal());
1740}
1741
1742
1743Bounds Typer::Visitor::TypeWord64Shr(Node* node) {
1744 return Bounds(Type::Internal());
1745}
1746
1747
1748Bounds Typer::Visitor::TypeWord64Sar(Node* node) {
1749 return Bounds(Type::Internal());
1750}
1751
1752
1753Bounds Typer::Visitor::TypeWord64Ror(Node* node) {
1754 return Bounds(Type::Internal());
1755}
1756
1757
1758Bounds Typer::Visitor::TypeWord64Equal(Node* node) {
1759 return Bounds(Type::Boolean());
1760}
1761
1762
1763Bounds Typer::Visitor::TypeInt32Add(Node* node) {
1764 return Bounds(Type::Integral32());
1765}
1766
1767
1768Bounds Typer::Visitor::TypeInt32AddWithOverflow(Node* node) {
1769 return Bounds(Type::Internal());
1770}
1771
1772
1773Bounds Typer::Visitor::TypeInt32Sub(Node* node) {
1774 return Bounds(Type::Integral32());
1775}
1776
1777
1778Bounds Typer::Visitor::TypeInt32SubWithOverflow(Node* node) {
1779 return Bounds(Type::Internal());
1780}
1781
1782
1783Bounds Typer::Visitor::TypeInt32Mul(Node* node) {
1784 return Bounds(Type::Integral32());
1785}
1786
1787
1788Bounds Typer::Visitor::TypeInt32MulHigh(Node* node) {
1789 return Bounds(Type::Signed32());
1790}
1791
1792
1793Bounds Typer::Visitor::TypeInt32Div(Node* node) {
1794 return Bounds(Type::Integral32());
1795}
1796
1797
1798Bounds Typer::Visitor::TypeInt32Mod(Node* node) {
1799 return Bounds(Type::Integral32());
1800}
1801
1802
1803Bounds Typer::Visitor::TypeInt32LessThan(Node* node) {
1804 return Bounds(Type::Boolean());
1805}
1806
1807
1808Bounds Typer::Visitor::TypeInt32LessThanOrEqual(Node* node) {
1809 return Bounds(Type::Boolean());
1810}
1811
1812
1813Bounds Typer::Visitor::TypeUint32Div(Node* node) {
1814 return Bounds(Type::Unsigned32());
1815}
1816
1817
1818Bounds Typer::Visitor::TypeUint32LessThan(Node* node) {
1819 return Bounds(Type::Boolean());
1820}
1821
1822
1823Bounds Typer::Visitor::TypeUint32LessThanOrEqual(Node* node) {
1824 return Bounds(Type::Boolean());
1825}
1826
1827
1828Bounds Typer::Visitor::TypeUint32Mod(Node* node) {
1829 return Bounds(Type::Unsigned32());
1830}
1831
1832
1833Bounds Typer::Visitor::TypeUint32MulHigh(Node* node) {
1834 return Bounds(Type::Unsigned32());
1835}
1836
1837
1838Bounds Typer::Visitor::TypeInt64Add(Node* node) {
1839 return Bounds(Type::Internal());
1840}
1841
1842
1843Bounds Typer::Visitor::TypeInt64Sub(Node* node) {
1844 return Bounds(Type::Internal());
1845}
1846
1847
1848Bounds Typer::Visitor::TypeInt64Mul(Node* node) {
1849 return Bounds(Type::Internal());
1850}
1851
1852
1853Bounds Typer::Visitor::TypeInt64Div(Node* node) {
1854 return Bounds(Type::Internal());
1855}
1856
1857
1858Bounds Typer::Visitor::TypeInt64Mod(Node* node) {
1859 return Bounds(Type::Internal());
1860}
1861
1862
1863Bounds Typer::Visitor::TypeInt64LessThan(Node* node) {
1864 return Bounds(Type::Boolean());
1865}
1866
1867
1868Bounds Typer::Visitor::TypeInt64LessThanOrEqual(Node* node) {
1869 return Bounds(Type::Boolean());
1870}
1871
1872
1873Bounds Typer::Visitor::TypeUint64Div(Node* node) {
1874 return Bounds(Type::Internal());
1875}
1876
1877
1878Bounds Typer::Visitor::TypeUint64LessThan(Node* node) {
1879 return Bounds(Type::Boolean());
1880}
1881
1882
1883Bounds Typer::Visitor::TypeUint64Mod(Node* node) {
1884 return Bounds(Type::Internal());
1885}
1886
1887
1888Bounds Typer::Visitor::TypeChangeFloat32ToFloat64(Node* node) {
1889 return Bounds(Type::Intersect(
1890 Type::Number(), Type::UntaggedFloat64(), zone()));
1891}
1892
1893
1894Bounds Typer::Visitor::TypeChangeFloat64ToInt32(Node* node) {
1895 return Bounds(Type::Intersect(
1896 Type::Signed32(), Type::UntaggedSigned32(), zone()));
1897}
1898
1899
1900Bounds Typer::Visitor::TypeChangeFloat64ToUint32(Node* node) {
1901 return Bounds(Type::Intersect(
1902 Type::Unsigned32(), Type::UntaggedUnsigned32(), zone()));
1903}
1904
1905
1906Bounds Typer::Visitor::TypeChangeInt32ToFloat64(Node* node) {
1907 return Bounds(Type::Intersect(
1908 Type::Signed32(), Type::UntaggedFloat64(), zone()));
1909}
1910
1911
1912Bounds Typer::Visitor::TypeChangeInt32ToInt64(Node* node) {
1913 return Bounds(Type::Internal());
1914}
1915
1916
1917Bounds Typer::Visitor::TypeChangeUint32ToFloat64(Node* node) {
1918 return Bounds(Type::Intersect(
1919 Type::Unsigned32(), Type::UntaggedFloat64(), zone()));
1920}
1921
1922
1923Bounds Typer::Visitor::TypeChangeUint32ToUint64(Node* node) {
1924 return Bounds(Type::Internal());
1925}
1926
1927
1928Bounds Typer::Visitor::TypeTruncateFloat64ToFloat32(Node* node) {
1929 return Bounds(Type::Intersect(
1930 Type::Number(), Type::UntaggedFloat32(), zone()));
1931}
1932
1933
1934Bounds Typer::Visitor::TypeTruncateFloat64ToInt32(Node* node) {
1935 return Bounds(Type::Intersect(
1936 Type::Signed32(), Type::UntaggedSigned32(), zone()));
1937}
1938
1939
1940Bounds Typer::Visitor::TypeTruncateInt64ToInt32(Node* node) {
1941 return Bounds(Type::Intersect(
1942 Type::Signed32(), Type::UntaggedSigned32(), zone()));
1943}
1944
1945
1946Bounds Typer::Visitor::TypeFloat64Add(Node* node) {
1947 return Bounds(Type::Number());
1948}
1949
1950
1951Bounds Typer::Visitor::TypeFloat64Sub(Node* node) {
1952 return Bounds(Type::Number());
1953}
1954
1955
1956Bounds Typer::Visitor::TypeFloat64Mul(Node* node) {
1957 return Bounds(Type::Number());
1958}
1959
1960
1961Bounds Typer::Visitor::TypeFloat64Div(Node* node) {
1962 return Bounds(Type::Number());
1963}
1964
1965
1966Bounds Typer::Visitor::TypeFloat64Mod(Node* node) {
1967 return Bounds(Type::Number());
1968}
1969
1970
1971Bounds Typer::Visitor::TypeFloat64Sqrt(Node* node) {
1972 return Bounds(Type::Number());
1973}
1974
1975
1976Bounds Typer::Visitor::TypeFloat64Equal(Node* node) {
1977 return Bounds(Type::Boolean());
1978}
1979
1980
1981Bounds Typer::Visitor::TypeFloat64LessThan(Node* node) {
1982 return Bounds(Type::Boolean());
1983}
1984
1985
1986Bounds Typer::Visitor::TypeFloat64LessThanOrEqual(Node* node) {
1987 return Bounds(Type::Boolean());
1988}
1989
1990
1991Bounds Typer::Visitor::TypeFloat64Floor(Node* node) {
1992 // TODO(sigurds): We could have a tighter bound here.
1993 return Bounds(Type::Number());
1994}
1995
1996
1997Bounds Typer::Visitor::TypeFloat64Ceil(Node* node) {
1998 // TODO(sigurds): We could have a tighter bound here.
1999 return Bounds(Type::Number());
2000}
2001
2002
2003Bounds Typer::Visitor::TypeFloat64RoundTruncate(Node* node) {
2004 // TODO(sigurds): We could have a tighter bound here.
2005 return Bounds(Type::Number());
2006}
2007
2008
2009Bounds Typer::Visitor::TypeFloat64RoundTiesAway(Node* node) {
2010 // TODO(sigurds): We could have a tighter bound here.
2011 return Bounds(Type::Number());
2012}
2013
2014
2015Bounds Typer::Visitor::TypeLoadStackPointer(Node* node) {
2016 return Bounds(Type::Internal());
2017}
2018
2019
2020Bounds Typer::Visitor::TypeCheckedLoad(Node* node) {
2021 return Bounds::Unbounded(zone());
2022}
2023
2024
2025Bounds Typer::Visitor::TypeCheckedStore(Node* node) {
2026 UNREACHABLE();
2027 return Bounds();
2028}
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002029
2030
2031// Heap constants.
2032
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002033
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002034Type* Typer::Visitor::TypeConstant(Handle<Object> value) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002035 if (value->IsJSFunction()) {
2036 if (JSFunction::cast(*value)->shared()->HasBuiltinFunctionId()) {
2037 switch (JSFunction::cast(*value)->shared()->builtin_function_id()) {
2038 case kMathRandom:
2039 return typer_->random_fun_;
2040 case kMathFloor:
2041 return typer_->weakint_fun1_;
2042 case kMathRound:
2043 return typer_->weakint_fun1_;
2044 case kMathCeil:
2045 return typer_->weakint_fun1_;
2046 // Unary math functions.
2047 case kMathAbs: // TODO(rossberg): can't express overloading
2048 case kMathLog:
2049 case kMathExp:
2050 case kMathSqrt:
2051 case kMathCos:
2052 case kMathSin:
2053 case kMathTan:
2054 case kMathAcos:
2055 case kMathAsin:
2056 case kMathAtan:
2057 case kMathFround:
2058 return typer_->cache_->Get(kNumberFunc1);
2059 // Binary math functions.
2060 case kMathAtan2:
2061 case kMathPow:
2062 case kMathMax:
2063 case kMathMin:
2064 return typer_->cache_->Get(kNumberFunc2);
2065 case kMathImul:
2066 return typer_->cache_->Get(kImulFunc);
2067 case kMathClz32:
2068 return typer_->cache_->Get(kClz32Func);
2069 default:
2070 break;
2071 }
2072 } else if (JSFunction::cast(*value)->IsBuiltin() && !context().is_null()) {
2073 Handle<Context> native =
2074 handle(context().ToHandleChecked()->native_context(), isolate());
2075 if (*value == native->array_buffer_fun()) {
2076 return typer_->cache_->Get(kArrayBufferFunc);
2077 } else if (*value == native->int8_array_fun()) {
2078 return typer_->cache_->Get(kInt8ArrayFunc);
2079 } else if (*value == native->int16_array_fun()) {
2080 return typer_->cache_->Get(kInt16ArrayFunc);
2081 } else if (*value == native->int32_array_fun()) {
2082 return typer_->cache_->Get(kInt32ArrayFunc);
2083 } else if (*value == native->uint8_array_fun()) {
2084 return typer_->cache_->Get(kUint8ArrayFunc);
2085 } else if (*value == native->uint16_array_fun()) {
2086 return typer_->cache_->Get(kUint16ArrayFunc);
2087 } else if (*value == native->uint32_array_fun()) {
2088 return typer_->cache_->Get(kUint32ArrayFunc);
2089 } else if (*value == native->float32_array_fun()) {
2090 return typer_->cache_->Get(kFloat32ArrayFunc);
2091 } else if (*value == native->float64_array_fun()) {
2092 return typer_->cache_->Get(kFloat64ArrayFunc);
2093 }
2094 }
2095 } else if (value->IsJSTypedArray()) {
2096 switch (JSTypedArray::cast(*value)->type()) {
2097#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
2098 case kExternal##Type##Array: \
2099 return typer_->cache_->Get(k##Type##Array);
2100 TYPED_ARRAYS(TYPED_ARRAY_CASE)
2101#undef TYPED_ARRAY_CASE
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002102 }
2103 }
2104 return Type::Constant(value, zone());
2105}
2106
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002107} // namespace compiler
2108} // namespace internal
2109} // namespace v8