Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(36)

Side by Side Diff: src/compiler/typer.cc

Issue 658743002: Refine typing of addition, subtraction, multiplication, and division. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Rangify (unions of) constants to get monotonicity. Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/compiler/typer.h ('k') | src/types.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 the V8 project authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/bootstrapper.h" 5 #include "src/bootstrapper.h"
6 #include "src/compiler/graph-inl.h" 6 #include "src/compiler/graph-inl.h"
7 #include "src/compiler/js-operator.h" 7 #include "src/compiler/js-operator.h"
8 #include "src/compiler/node.h" 8 #include "src/compiler/node.h"
9 #include "src/compiler/node-properties-inl.h" 9 #include "src/compiler/node-properties-inl.h"
10 #include "src/compiler/node-properties.h" 10 #include "src/compiler/node-properties.h"
(...skipping 14 matching lines...) Expand all
25 }; 25 };
26 26
27 27
28 Typer::Typer(Graph* graph, MaybeHandle<Context> context) 28 Typer::Typer(Graph* graph, MaybeHandle<Context> context)
29 : graph_(graph), context_(context), decorator_(NULL) { 29 : graph_(graph), context_(context), decorator_(NULL) {
30 Zone* zone = this->zone(); 30 Zone* zone = this->zone();
31 Factory* f = zone->isolate()->factory(); 31 Factory* f = zone->isolate()->factory();
32 32
33 Handle<Object> zero = f->NewNumber(0); 33 Handle<Object> zero = f->NewNumber(0);
34 Handle<Object> one = f->NewNumber(1); 34 Handle<Object> one = f->NewNumber(1);
35 Handle<Object> positive_infinity = f->NewNumber(+V8_INFINITY); 35 Handle<Object> infinity = f->NewNumber(+V8_INFINITY);
36 Handle<Object> negative_infinity = f->NewNumber(-V8_INFINITY); 36 Handle<Object> minusinfinity = f->NewNumber(-V8_INFINITY);
37 37
38 negative_signed32 = Type::Union( 38 negative_signed32 = Type::Union(
39 Type::SignedSmall(), Type::OtherSigned32(), zone); 39 Type::SignedSmall(), Type::OtherSigned32(), zone);
40 non_negative_signed32 = Type::Union( 40 non_negative_signed32 = Type::Union(
41 Type::UnsignedSmall(), Type::OtherUnsigned31(), zone); 41 Type::UnsignedSmall(), Type::OtherUnsigned31(), zone);
42 undefined_or_null = Type::Union(Type::Undefined(), Type::Null(), zone); 42 undefined_or_null = Type::Union(Type::Undefined(), Type::Null(), zone);
43 singleton_false = Type::Constant(f->false_value(), zone); 43 singleton_false = Type::Constant(f->false_value(), zone);
44 singleton_true = Type::Constant(f->true_value(), zone); 44 singleton_true = Type::Constant(f->true_value(), zone);
45 singleton_zero = Type::Range(zero, zero, zone); 45 singleton_zero = Type::Range(zero, zero, zone);
46 singleton_one = Type::Range(one, one, zone); 46 singleton_one = Type::Range(one, one, zone);
47 zero_or_one = Type::Union(singleton_zero, singleton_one, zone); 47 zero_or_one = Type::Union(singleton_zero, singleton_one, zone);
48 zeroish = Type::Union( 48 zeroish = Type::Union(
49 singleton_zero, Type::Union(Type::NaN(), Type::MinusZero(), zone), zone); 49 singleton_zero, Type::Union(Type::NaN(), Type::MinusZero(), zone), zone);
50 falsish = Type::Union(Type::Undetectable(), 50 falsish = Type::Union(Type::Undetectable(),
51 Type::Union(zeroish, undefined_or_null, zone), zone); 51 Type::Union(zeroish, undefined_or_null, zone), zone);
52 integer = Type::Range(negative_infinity, positive_infinity, zone); 52 integer = Type::Range(minusinfinity, infinity, zone);
53 weakint = Type::Union(
54 integer, Type::Union(Type::NaN(), Type::MinusZero(), zone), zone);
53 55
54 Type* number = Type::Number(); 56 Type* number = Type::Number();
55 Type* signed32 = Type::Signed32(); 57 Type* signed32 = Type::Signed32();
56 Type* unsigned32 = Type::Unsigned32(); 58 Type* unsigned32 = Type::Unsigned32();
57 Type* integral32 = Type::Integral32(); 59 Type* integral32 = Type::Integral32();
58 Type* object = Type::Object(); 60 Type* object = Type::Object();
59 Type* undefined = Type::Undefined(); 61 Type* undefined = Type::Undefined();
60 Type* weakint = Type::Union(
61 integer, Type::Union(Type::NaN(), Type::MinusZero(), zone), zone);
62 62
63 number_fun0_ = Type::Function(number, zone); 63 number_fun0_ = Type::Function(number, zone);
64 number_fun1_ = Type::Function(number, number, zone); 64 number_fun1_ = Type::Function(number, number, zone);
65 number_fun2_ = Type::Function(number, number, number, zone); 65 number_fun2_ = Type::Function(number, number, number, zone);
66 weakint_fun1_ = Type::Function(weakint, number, zone); 66 weakint_fun1_ = Type::Function(weakint, number, zone);
67 imul_fun_ = Type::Function(signed32, integral32, integral32, zone); 67 imul_fun_ = Type::Function(signed32, integral32, integral32, zone);
68 random_fun_ = Type::Function(Type::Union( 68 random_fun_ = Type::Function(Type::Union(
69 Type::UnsignedSmall(), Type::OtherNumber(), zone), zone); 69 Type::UnsignedSmall(), Type::OtherNumber(), zone), zone);
70 70
71 Type* int8 = Type::Intersect( 71 Type* int8 = Type::Intersect(
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
157 Type* TypeConstant(Handle<Object> value); 157 Type* TypeConstant(Handle<Object> value);
158 158
159 protected: 159 protected:
160 #define DECLARE_METHOD(x) inline Bounds Type##x(Node* node); 160 #define DECLARE_METHOD(x) inline Bounds Type##x(Node* node);
161 DECLARE_METHOD(Start) 161 DECLARE_METHOD(Start)
162 VALUE_OP_LIST(DECLARE_METHOD) 162 VALUE_OP_LIST(DECLARE_METHOD)
163 #undef DECLARE_METHOD 163 #undef DECLARE_METHOD
164 164
165 Bounds BoundsOrNone(Node* node) { 165 Bounds BoundsOrNone(Node* node) {
166 return NodeProperties::IsTyped(node) 166 return NodeProperties::IsTyped(node)
167 ? NodeProperties::GetBounds(node) : Bounds(Type::None(zone())); 167 ? NodeProperties::GetBounds(node) : Bounds(Type::None());
168 } 168 }
169 169
170 Bounds Operand(Node* node, int i) { 170 Bounds Operand(Node* node, int i) {
171 Node* operand_node = NodeProperties::GetValueInput(node, i); 171 Node* operand_node = NodeProperties::GetValueInput(node, i);
172 return BoundsOrNone(operand_node); 172 return BoundsOrNone(operand_node);
173 } 173 }
174 174
175 Bounds ContextOperand(Node* node) { 175 Bounds ContextOperand(Node* node) {
176 Bounds result = BoundsOrNone(NodeProperties::GetContextInput(node)); 176 Bounds result = BoundsOrNone(NodeProperties::GetContextInput(node));
177 DCHECK(result.upper->Maybe(Type::Internal())); 177 DCHECK(result.upper->Maybe(Type::Internal()));
(...skipping 12 matching lines...) Expand all
190 MaybeHandle<Context> context_; 190 MaybeHandle<Context> context_;
191 191
192 typedef Type* (*UnaryTyperFun)(Type*, Typer* t); 192 typedef Type* (*UnaryTyperFun)(Type*, Typer* t);
193 typedef Type* (*BinaryTyperFun)(Type*, Type*, Typer* t); 193 typedef Type* (*BinaryTyperFun)(Type*, Type*, Typer* t);
194 194
195 Bounds TypeUnaryOp(Node* node, UnaryTyperFun); 195 Bounds TypeUnaryOp(Node* node, UnaryTyperFun);
196 Bounds TypeBinaryOp(Node* node, BinaryTyperFun); 196 Bounds TypeBinaryOp(Node* node, BinaryTyperFun);
197 197
198 static Type* Invert(Type*, Typer*); 198 static Type* Invert(Type*, Typer*);
199 static Type* FalsifyUndefined(Type*, Typer*); 199 static Type* FalsifyUndefined(Type*, Typer*);
200 static Type* Rangify(Type*, Typer*);
200 201
201 static Type* ToPrimitive(Type*, Typer*); 202 static Type* ToPrimitive(Type*, Typer*);
202 static Type* ToBoolean(Type*, Typer*); 203 static Type* ToBoolean(Type*, Typer*);
203 static Type* ToNumber(Type*, Typer*); 204 static Type* ToNumber(Type*, Typer*);
204 static Type* ToString(Type*, Typer*); 205 static Type* ToString(Type*, Typer*);
205 static Type* NumberToInt32(Type*, Typer*); 206 static Type* NumberToInt32(Type*, Typer*);
206 static Type* NumberToUint32(Type*, Typer*); 207 static Type* NumberToUint32(Type*, Typer*);
207 208
208 static Type* JSAddRanger(Type::RangeType*, Type::RangeType*, Typer*); 209 static Type* JSAddRanger(Type::RangeType*, Type::RangeType*, Typer*);
209 static Type* JSSubtractRanger(Type::RangeType*, Type::RangeType*, Typer*); 210 static Type* JSSubtractRanger(Type::RangeType*, Type::RangeType*, Typer*);
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
243 }; 244 };
244 245
245 246
246 class Typer::NarrowVisitor : public Typer::Visitor { 247 class Typer::NarrowVisitor : public Typer::Visitor {
247 public: 248 public:
248 explicit NarrowVisitor(Typer* typer) : Visitor(typer) {} 249 explicit NarrowVisitor(Typer* typer) : Visitor(typer) {}
249 250
250 GenericGraphVisit::Control Pre(Node* node) { 251 GenericGraphVisit::Control Pre(Node* node) {
251 if (OperatorProperties::HasValueOutput(node->op())) { 252 if (OperatorProperties::HasValueOutput(node->op())) {
252 Bounds previous = NodeProperties::GetBounds(node); 253 Bounds previous = NodeProperties::GetBounds(node);
253 Bounds bounds = TypeNode(node); 254 Bounds current = TypeNode(node);
254 NodeProperties::SetBounds(node, Bounds::Both(bounds, previous, zone())); 255 NodeProperties::SetBounds(node, Bounds::Both(current, previous, zone()));
255 DCHECK(bounds.Narrows(previous)); 256 DCHECK(current.Narrows(previous));
256 // Stop when nothing changed (but allow re-entry in case it does later). 257 // Stop when nothing changed (but allow re-entry in case it does later).
257 return previous.Narrows(bounds) 258 return previous.Narrows(current)
258 ? GenericGraphVisit::DEFER : GenericGraphVisit::REENTER; 259 ? GenericGraphVisit::DEFER : GenericGraphVisit::REENTER;
259 } else { 260 } else {
260 return GenericGraphVisit::SKIP; 261 return GenericGraphVisit::SKIP;
261 } 262 }
262 } 263 }
263 264
264 GenericGraphVisit::Control Post(Node* node) { 265 GenericGraphVisit::Control Post(Node* node) {
265 return GenericGraphVisit::REENTER; 266 return GenericGraphVisit::REENTER;
266 } 267 }
267 }; 268 };
268 269
269 270
270 class Typer::WidenVisitor : public Typer::Visitor { 271 class Typer::WidenVisitor : public Typer::Visitor {
271 public: 272 public:
272 explicit WidenVisitor(Typer* typer) : Visitor(typer) {} 273 explicit WidenVisitor(Typer* typer) : Visitor(typer) {}
273 274
274 GenericGraphVisit::Control Pre(Node* node) { 275 GenericGraphVisit::Control Pre(Node* node) {
275 if (OperatorProperties::HasValueOutput(node->op())) { 276 if (OperatorProperties::HasValueOutput(node->op())) {
276 Bounds previous = BoundsOrNone(node); 277 Bounds previous = BoundsOrNone(node);
277 Bounds bounds = TypeNode(node); 278 Bounds current = TypeNode(node);
278 DCHECK(previous.lower->Is(bounds.lower)); 279 DCHECK(previous.lower->Is(current.lower));
279 DCHECK(previous.upper->Is(bounds.upper)); 280 DCHECK(previous.upper->Is(current.upper));
280 NodeProperties::SetBounds(node, bounds); 281
282 // Speed up termination in the presence of range types:
283 current.upper = MaybeWeaken(current.upper, previous.upper);
284 current.lower = MaybeWeaken(current.lower, previous.lower);
285
286 NodeProperties::SetBounds(node, current);
281 // Stop when nothing changed (but allow re-entry in case it does later). 287 // Stop when nothing changed (but allow re-entry in case it does later).
282 return bounds.Narrows(previous) 288 return previous.Narrows(current) && current.Narrows(previous)
283 ? GenericGraphVisit::DEFER : GenericGraphVisit::REENTER; 289 ? GenericGraphVisit::DEFER : GenericGraphVisit::REENTER;
284 } else { 290 } else {
285 return GenericGraphVisit::SKIP; 291 return GenericGraphVisit::SKIP;
286 } 292 }
287 } 293 }
288 294
289 GenericGraphVisit::Control Post(Node* node) { 295 GenericGraphVisit::Control Post(Node* node) {
290 return GenericGraphVisit::REENTER; 296 return GenericGraphVisit::REENTER;
291 } 297 }
298
299 private:
300 Type* MaybeWeaken(Type* current, Type* previous) {
301 if (current->IsRange() && previous->IsRange() && !current->Is(previous)) {
302 return current->AsRange()->Weaken(zone());
303 }
304 return current;
305 }
292 }; 306 };
293 307
294 308
295 void Typer::Run() { 309 void Typer::Run() {
296 RunVisitor typing(this); 310 RunVisitor typing(this);
297 graph_->VisitNodeInputsFromEnd(&typing); 311 graph_->VisitNodeInputsFromEnd(&typing);
298 // Find least fixpoint. 312 // Find least fixpoint.
299 WidenVisitor widen(this); 313 WidenVisitor widen(this);
300 for (NodeSetIter it = typing.redo.begin(); it != typing.redo.end(); ++it) { 314 for (NodeSetIter it = typing.redo.begin(); it != typing.redo.end(); ++it) {
301 graph_->VisitNodeUsesFrom(*it, &widen); 315 graph_->VisitNodeUsesFrom(*it, &widen);
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
372 return type; 386 return type;
373 } 387 }
374 388
375 389
376 Type* Typer::Visitor::FalsifyUndefined(Type* type, Typer* t) { 390 Type* Typer::Visitor::FalsifyUndefined(Type* type, Typer* t) {
377 if (type->Is(Type::Undefined())) return t->singleton_false; 391 if (type->Is(Type::Undefined())) return t->singleton_false;
378 return type; 392 return type;
379 } 393 }
380 394
381 395
396 Type* Typer::Visitor::Rangify(Type* type, Typer* t) {
397 if (!type->Is(t->integer)) return type; // Give up.
398 if (type->IsRange()) return type; // Shortcut.
399 Factory* f = t->isolate()->factory();
400 return Type::Range(
401 f->NewNumber(type->Min()), f->NewNumber(type->Max()), t->zone());
402 }
403
404
382 // Type conversion. 405 // Type conversion.
383 406
384 407
385 Type* Typer::Visitor::ToPrimitive(Type* type, Typer* t) { 408 Type* Typer::Visitor::ToPrimitive(Type* type, Typer* t) {
386 if (type->Is(Type::Primitive()) && !type->Maybe(Type::Receiver())) { 409 if (type->Is(Type::Primitive()) && !type->Maybe(Type::Receiver())) {
387 return type; 410 return type;
388 } 411 }
389 return Type::Primitive(); 412 return Type::Primitive();
390 } 413 }
391 414
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
446 469
447 // Common operators. 470 // Common operators.
448 471
449 472
450 Bounds Typer::Visitor::TypeParameter(Node* node) { 473 Bounds Typer::Visitor::TypeParameter(Node* node) {
451 return Bounds::Unbounded(zone()); 474 return Bounds::Unbounded(zone());
452 } 475 }
453 476
454 477
455 Bounds Typer::Visitor::TypeInt32Constant(Node* node) { 478 Bounds Typer::Visitor::TypeInt32Constant(Node* node) {
456 Factory* f = zone()->isolate()->factory(); 479 Factory* f = isolate()->factory();
457 Handle<Object> number = f->NewNumber(OpParameter<int32_t>(node)); 480 Handle<Object> number = f->NewNumber(OpParameter<int32_t>(node));
458 return Bounds(Type::Intersect( 481 return Bounds(Type::Intersect(
459 Type::Range(number, number, zone()), Type::UntaggedInt32(), zone())); 482 Type::Range(number, number, zone()), Type::UntaggedInt32(), zone()));
460 } 483 }
461 484
462 485
463 Bounds Typer::Visitor::TypeInt64Constant(Node* node) { 486 Bounds Typer::Visitor::TypeInt64Constant(Node* node) {
464 return Bounds(Type::Internal()); // TODO(rossberg): Add int64 bitset type? 487 return Bounds(Type::Internal()); // TODO(rossberg): Add int64 bitset type?
465 } 488 }
466 489
467 490
468 Bounds Typer::Visitor::TypeFloat32Constant(Node* node) { 491 Bounds Typer::Visitor::TypeFloat32Constant(Node* node) {
469 return Bounds(Type::Intersect( 492 return Bounds(Type::Intersect(
470 Type::Of(OpParameter<float>(node), zone()), 493 Type::Of(OpParameter<float>(node), zone()),
471 Type::UntaggedFloat32(), zone())); 494 Type::UntaggedFloat32(), zone()));
472 } 495 }
473 496
474 497
475 Bounds Typer::Visitor::TypeFloat64Constant(Node* node) { 498 Bounds Typer::Visitor::TypeFloat64Constant(Node* node) {
476 return Bounds(Type::Intersect( 499 return Bounds(Type::Intersect(
477 Type::Of(OpParameter<double>(node), zone()), 500 Type::Of(OpParameter<double>(node), zone()),
478 Type::UntaggedFloat64(), zone())); 501 Type::UntaggedFloat64(), zone()));
479 } 502 }
480 503
481 504
482 Bounds Typer::Visitor::TypeNumberConstant(Node* node) { 505 Bounds Typer::Visitor::TypeNumberConstant(Node* node) {
483 Factory* f = zone()->isolate()->factory(); 506 Factory* f = isolate()->factory();
484 return Bounds(Type::Constant( 507 return Bounds(Type::Constant(
485 f->NewNumber(OpParameter<double>(node)), zone())); 508 f->NewNumber(OpParameter<double>(node)), zone()));
486 } 509 }
487 510
488 511
489 Bounds Typer::Visitor::TypeHeapConstant(Node* node) { 512 Bounds Typer::Visitor::TypeHeapConstant(Node* node) {
490 return Bounds(TypeConstant(OpParameter<Unique<Object> >(node).handle())); 513 return Bounds(TypeConstant(OpParameter<Unique<Object> >(node).handle()));
491 } 514 }
492 515
493 516
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
650 Type* Typer::Visitor::JSGreaterThanOrEqualTyper( 673 Type* Typer::Visitor::JSGreaterThanOrEqualTyper(
651 Type* lhs, Type* rhs, Typer* t) { 674 Type* lhs, Type* rhs, Typer* t) {
652 return FalsifyUndefined(Invert(JSCompareTyper(lhs, rhs, t), t), t); 675 return FalsifyUndefined(Invert(JSCompareTyper(lhs, rhs, t), t), t);
653 } 676 }
654 677
655 678
656 // JS bitwise operators. 679 // JS bitwise operators.
657 680
658 681
659 Type* Typer::Visitor::JSBitwiseOrTyper(Type* lhs, Type* rhs, Typer* t) { 682 Type* Typer::Visitor::JSBitwiseOrTyper(Type* lhs, Type* rhs, Typer* t) {
660 Factory* f = t->zone()->isolate()->factory(); 683 Factory* f = t->isolate()->factory();
661 lhs = NumberToInt32(ToNumber(lhs, t), t); 684 lhs = NumberToInt32(ToNumber(lhs, t), t);
662 rhs = NumberToInt32(ToNumber(rhs, t), t); 685 rhs = NumberToInt32(ToNumber(rhs, t), t);
663 double lmin = lhs->Min(); 686 double lmin = lhs->Min();
664 double rmin = rhs->Min(); 687 double rmin = rhs->Min();
665 double lmax = lhs->Max(); 688 double lmax = lhs->Max();
666 double rmax = rhs->Max(); 689 double rmax = rhs->Max();
667 // Or-ing any two values results in a value no smaller than their minimum. 690 // Or-ing any two values results in a value no smaller than their minimum.
668 // Even no smaller than their maximum if both values are non-negative. 691 // Even no smaller than their maximum if both values are non-negative.
669 Handle<Object> min = f->NewNumber( 692 Handle<Object> min = f->NewNumber(
670 lmin >= 0 && rmin >= 0 ? std::max(lmin, rmin) : std::min(lmin, rmin)); 693 lmin >= 0 && rmin >= 0 ? std::max(lmin, rmin) : std::min(lmin, rmin));
671 if (lmax < 0 || rmax < 0) { 694 if (lmax < 0 || rmax < 0) {
672 // Or-ing two values of which at least one is negative results in a negative 695 // Or-ing two values of which at least one is negative results in a negative
673 // value. 696 // value.
674 Handle<Object> max = f->NewNumber(-1); 697 Handle<Object> max = f->NewNumber(-1);
675 return Type::Range(min, max, t->zone()); 698 return Type::Range(min, max, t->zone());
676 } 699 }
677 Handle<Object> max = f->NewNumber(Type::Signed32()->Max()); 700 Handle<Object> max = f->NewNumber(Type::Signed32()->Max());
678 return Type::Range(min, max, t->zone()); 701 return Type::Range(min, max, t->zone());
679 // TODO(neis): Be precise for singleton inputs, here and elsewhere. 702 // TODO(neis): Be precise for singleton inputs, here and elsewhere.
680 } 703 }
681 704
682 705
683 Type* Typer::Visitor::JSBitwiseAndTyper(Type* lhs, Type* rhs, Typer* t) { 706 Type* Typer::Visitor::JSBitwiseAndTyper(Type* lhs, Type* rhs, Typer* t) {
684 Factory* f = t->zone()->isolate()->factory(); 707 Factory* f = t->isolate()->factory();
685 lhs = NumberToInt32(ToNumber(lhs, t), t); 708 lhs = NumberToInt32(ToNumber(lhs, t), t);
686 rhs = NumberToInt32(ToNumber(rhs, t), t); 709 rhs = NumberToInt32(ToNumber(rhs, t), t);
687 double lmin = lhs->Min(); 710 double lmin = lhs->Min();
688 double rmin = rhs->Min(); 711 double rmin = rhs->Min();
689 double lmax = lhs->Max(); 712 double lmax = lhs->Max();
690 double rmax = rhs->Max(); 713 double rmax = rhs->Max();
691 // And-ing any two values results in a value no larger than their maximum. 714 // And-ing any two values results in a value no larger than their maximum.
692 // Even no larger than their minimum if both values are non-negative. 715 // Even no larger than their minimum if both values are non-negative.
693 Handle<Object> max = f->NewNumber( 716 Handle<Object> max = f->NewNumber(
694 lmin >= 0 && rmin >= 0 ? std::min(lmax, rmax) : std::max(lmax, rmax)); 717 lmin >= 0 && rmin >= 0 ? std::min(lmax, rmax) : std::max(lmax, rmax));
(...skipping 27 matching lines...) Expand all
722 } 745 }
723 746
724 747
725 Type* Typer::Visitor::JSShiftLeftTyper(Type* lhs, Type* rhs, Typer* t) { 748 Type* Typer::Visitor::JSShiftLeftTyper(Type* lhs, Type* rhs, Typer* t) {
726 return Type::Signed32(); 749 return Type::Signed32();
727 } 750 }
728 751
729 752
730 Type* Typer::Visitor::JSShiftRightTyper(Type* lhs, Type* rhs, Typer* t) { 753 Type* Typer::Visitor::JSShiftRightTyper(Type* lhs, Type* rhs, Typer* t) {
731 lhs = NumberToInt32(ToNumber(lhs, t), t); 754 lhs = NumberToInt32(ToNumber(lhs, t), t);
732 Factory* f = t->zone()->isolate()->factory(); 755 Factory* f = t->isolate()->factory();
733 if (lhs->Min() >= 0) { 756 if (lhs->Min() >= 0) {
734 // Right-shifting a non-negative value cannot make it negative, nor larger. 757 // Right-shifting a non-negative value cannot make it negative, nor larger.
735 Handle<Object> min = f->NewNumber(0); 758 Handle<Object> min = f->NewNumber(0);
736 Handle<Object> max = f->NewNumber(lhs->Max()); 759 Handle<Object> max = f->NewNumber(lhs->Max());
737 return Type::Range(min, max, t->zone()); 760 return Type::Range(min, max, t->zone());
738 } 761 }
739 if (lhs->Max() < 0) { 762 if (lhs->Max() < 0) {
740 // Right-shifting a negative value cannot make it non-negative, nor smaller. 763 // Right-shifting a negative value cannot make it non-negative, nor smaller.
741 Handle<Object> min = f->NewNumber(lhs->Min()); 764 Handle<Object> min = f->NewNumber(lhs->Min());
742 Handle<Object> max = f->NewNumber(-1); 765 Handle<Object> max = f->NewNumber(-1);
743 return Type::Range(min, max, t->zone()); 766 return Type::Range(min, max, t->zone());
744 } 767 }
745 return Type::Signed32(); 768 return Type::Signed32();
746 } 769 }
747 770
748 771
749 Type* Typer::Visitor::JSShiftRightLogicalTyper(Type* lhs, Type* rhs, Typer* t) { 772 Type* Typer::Visitor::JSShiftRightLogicalTyper(Type* lhs, Type* rhs, Typer* t) {
750 lhs = NumberToUint32(ToNumber(lhs, t), t); 773 lhs = NumberToUint32(ToNumber(lhs, t), t);
751 Factory* f = t->zone()->isolate()->factory(); 774 Factory* f = t->isolate()->factory();
752 // Logical right-shifting any value cannot make it larger. 775 // Logical right-shifting any value cannot make it larger.
753 Handle<Object> min = f->NewNumber(0); 776 Handle<Object> min = f->NewNumber(0);
754 Handle<Object> max = f->NewNumber(lhs->Max()); 777 Handle<Object> max = f->NewNumber(lhs->Max());
755 return Type::Range(min, max, t->zone()); 778 return Type::Range(min, max, t->zone());
756 } 779 }
757 780
758 781
759 // JS arithmetic operators. 782 // JS arithmetic operators.
760 783
761 784
785 // Returns the array's least element, ignoring NaN.
786 // There must be at least one non-NaN element.
787 // Any -0 is converted to 0.
788 static double array_min(double a[], size_t n) {
789 DCHECK(n != 0);
790 double x = a[0];
791 for (size_t i = 1; i < n; ++i) {
792 x = std::min(std::isnan(a[i]) ? +V8_INFINITY : a[i], x);
793 }
794 DCHECK(!std::isnan(x));
795 return x == 0 ? 0 : x; // -0 -> 0
796 }
797
798
799 // Returns the array's greatest element, ignoring NaN.
800 // There must be at least one non-NaN element.
801 // Any -0 is converted to 0.
802 static double array_max(double a[], size_t n) {
803 DCHECK(n != 0);
804 double x = a[0];
805 for (size_t i = 1; i < n; ++i) {
806 x = std::max(std::isnan(a[i]) ? -V8_INFINITY : a[i], x);
807 }
808 DCHECK(!std::isnan(x));
809 return x == 0 ? 0 : x; // -0 -> 0
810 }
811
812
813 Type* Typer::Visitor::JSAddRanger(
814 Type::RangeType* lhs, Type::RangeType* rhs, Typer* t) {
815 double results[4];
816 results[0] = lhs->Min()->Number() + rhs->Min()->Number();
817 results[1] = lhs->Min()->Number() + rhs->Max()->Number();
818 results[2] = lhs->Max()->Number() + rhs->Min()->Number();
819 results[3] = lhs->Max()->Number() + rhs->Max()->Number();
820 // Since none of the inputs can be -0, the result cannot be -0 either.
821 // However, it can be nan (the sum of two infinities of opposite sign).
822 // On the other hand, if none of the "results" above is nan, then the actual
823 // result cannot be nan either.
824 int nans = 0;
825 for (int i = 0; i < 4; ++i) {
826 if (std::isnan(results[i])) ++nans;
827 }
828 if (nans == 4) return Type::NaN(); // [-inf..-inf] + [inf..inf] or vice versa
829 Factory* f = t->isolate()->factory();
830 Type* range = Type::Range(
831 f->NewNumber(array_min(results, 4)), f->NewNumber(array_max(results, 4)),
832 t->zone());
833 return nans == 0 ? range : Type::Union(range, Type::NaN(), t->zone());
834 // Examples:
835 // [-inf, -inf] + [+inf, +inf] = NaN
836 // [-inf, -inf] + [n, +inf] = [-inf, -inf] \/ NaN
837 // [-inf, +inf] + [n, +inf] = [-inf, +inf] \/ NaN
838 // [-inf, m] + [n, +inf] = [-inf, +inf] \/ NaN
839 }
840
841
762 Type* Typer::Visitor::JSAddTyper(Type* lhs, Type* rhs, Typer* t) { 842 Type* Typer::Visitor::JSAddTyper(Type* lhs, Type* rhs, Typer* t) {
763 lhs = ToPrimitive(lhs, t); 843 lhs = ToPrimitive(lhs, t);
764 rhs = ToPrimitive(rhs, t); 844 rhs = ToPrimitive(rhs, t);
765 if (lhs->Maybe(Type::String()) || rhs->Maybe(Type::String())) { 845 if (lhs->Maybe(Type::String()) || rhs->Maybe(Type::String())) {
766 if (lhs->Is(Type::String()) || rhs->Is(Type::String())) { 846 if (lhs->Is(Type::String()) || rhs->Is(Type::String())) {
767 return Type::String(); 847 return Type::String();
768 } else { 848 } else {
769 return Type::NumberOrString(); 849 return Type::NumberOrString();
770 } 850 }
771 } 851 }
772 lhs = ToNumber(lhs, t); 852 lhs = Rangify(ToNumber(lhs, t), t);
773 rhs = ToNumber(rhs, t); 853 rhs = Rangify(ToNumber(rhs, t), t);
774 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN(); 854 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN();
775 // TODO(neis): Do some analysis. 855 if (lhs->IsRange() && rhs->IsRange()) {
856 return JSAddRanger(lhs->AsRange(), rhs->AsRange(), t);
857 }
776 // TODO(neis): Deal with numeric bitsets here and elsewhere. 858 // TODO(neis): Deal with numeric bitsets here and elsewhere.
777 return Type::Number(); 859 return Type::Number();
778 } 860 }
779 861
780 862
863 Type* Typer::Visitor::JSSubtractRanger(
864 Type::RangeType* lhs, Type::RangeType* rhs, Typer* t) {
865 double results[4];
866 results[0] = lhs->Min()->Number() - rhs->Min()->Number();
867 results[1] = lhs->Min()->Number() - rhs->Max()->Number();
868 results[2] = lhs->Max()->Number() - rhs->Min()->Number();
869 results[3] = lhs->Max()->Number() - rhs->Max()->Number();
870 // Since none of the inputs can be -0, the result cannot be -0.
871 // However, it can be nan (the subtraction of two infinities of same sign).
872 // On the other hand, if none of the "results" above is nan, then the actual
873 // result cannot be nan either.
874 int nans = 0;
875 for (int i = 0; i < 4; ++i) {
876 if (std::isnan(results[i])) ++nans;
877 }
878 if (nans == 4) return Type::NaN(); // [inf..inf] - [inf..inf] (all same sign)
879 Factory* f = t->isolate()->factory();
880 Type* range = Type::Range(
881 f->NewNumber(array_min(results, 4)), f->NewNumber(array_max(results, 4)),
882 t->zone());
883 return nans == 0 ? range : Type::Union(range, Type::NaN(), t->zone());
884 // Examples:
885 // [-inf, +inf] - [-inf, +inf] = [-inf, +inf] \/ NaN
886 // [-inf, -inf] - [-inf, -inf] = NaN
887 // [-inf, -inf] - [n, +inf] = [-inf, -inf] \/ NaN
888 // [m, +inf] - [-inf, n] = [-inf, +inf] \/ NaN
889 }
890
891
781 Type* Typer::Visitor::JSSubtractTyper(Type* lhs, Type* rhs, Typer* t) { 892 Type* Typer::Visitor::JSSubtractTyper(Type* lhs, Type* rhs, Typer* t) {
782 lhs = ToNumber(lhs, t); 893 lhs = Rangify(ToNumber(lhs, t), t);
783 rhs = ToNumber(rhs, t); 894 rhs = Rangify(ToNumber(rhs, t), t);
784 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN(); 895 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN();
785 // TODO(neis): Do some analysis. 896 if (lhs->IsRange() && rhs->IsRange()) {
897 return JSSubtractRanger(lhs->AsRange(), rhs->AsRange(), t);
898 }
786 return Type::Number(); 899 return Type::Number();
787 } 900 }
788 901
789 902
903 Type* Typer::Visitor::JSMultiplyRanger(
904 Type::RangeType* lhs, Type::RangeType* rhs, Typer* t) {
905 double results[4];
906 double lmin = lhs->Min()->Number();
907 double lmax = lhs->Max()->Number();
908 double rmin = rhs->Min()->Number();
909 double rmax = rhs->Max()->Number();
910 results[0] = lmin * rmin;
911 results[1] = lmin * rmax;
912 results[2] = lmax * rmin;
913 results[3] = lmax * rmax;
914 // If the result may be nan, we give up on calculating a precise type, because
915 // the discontinuity makes it too complicated. Note that even if none of the
916 // "results" above is nan, the actual result may still be, so we have to do a
917 // different check:
918 bool maybe_nan =
919 (lhs->Maybe(t->singleton_zero) &&
920 (rmin == -V8_INFINITY || rmax == +V8_INFINITY)) ||
921 (rhs->Maybe(t->singleton_zero) &&
922 (lmin == -V8_INFINITY || lmax == +V8_INFINITY));
923 if (maybe_nan) return t->weakint; // Giving up.
924 bool maybe_minuszero =
925 (lhs->Maybe(t->singleton_zero) && rmin < 0) ||
926 (rhs->Maybe(t->singleton_zero) && lmin < 0);
927 Factory* f = t->isolate()->factory();
928 Type* range = Type::Range(
929 f->NewNumber(array_min(results, 4)), f->NewNumber(array_max(results, 4)),
930 t->zone());
931 return maybe_minuszero ?
932 Type::Union(range, Type::MinusZero(), t->zone()) : range;
933 }
934
935
790 Type* Typer::Visitor::JSMultiplyTyper(Type* lhs, Type* rhs, Typer* t) { 936 Type* Typer::Visitor::JSMultiplyTyper(Type* lhs, Type* rhs, Typer* t) {
791 lhs = ToNumber(lhs, t); 937 lhs = Rangify(ToNumber(lhs, t), t);
792 rhs = ToNumber(rhs, t); 938 rhs = Rangify(ToNumber(rhs, t), t);
793 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN(); 939 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN();
794 // TODO(neis): Do some analysis. 940 if (lhs->IsRange() && rhs->IsRange()) {
941 return JSMultiplyRanger(lhs->AsRange(), rhs->AsRange(), t);
942 }
795 return Type::Number(); 943 return Type::Number();
796 } 944 }
797 945
798 946
799 Type* Typer::Visitor::JSDivideTyper(Type* lhs, Type* rhs, Typer* t) { 947 Type* Typer::Visitor::JSDivideTyper(Type* lhs, Type* rhs, Typer* t) {
800 lhs = ToNumber(lhs, t); 948 lhs = ToNumber(lhs, t);
801 rhs = ToNumber(rhs, t); 949 rhs = ToNumber(rhs, t);
802 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN(); 950 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN();
803 // TODO(neis): Do some analysis. 951 // Division is tricky, so all we do is try ruling out nan.
804 return Type::Number(); 952 // TODO(neis): try ruling out -0 as well?
953 bool maybe_nan =
954 lhs->Maybe(Type::NaN()) || rhs->Maybe(Type::NaN()) ||
955 rhs->Maybe(t->singleton_zero) ||
956 ((lhs->Min() == -V8_INFINITY || lhs->Max() == +V8_INFINITY) &&
957 (rhs->Min() == -V8_INFINITY || rhs->Max() == +V8_INFINITY));
958 return maybe_nan ? Type::Number() : Type::OrderedNumber();
805 } 959 }
806 960
807 961
808 Type* Typer::Visitor::JSModulusTyper(Type* lhs, Type* rhs, Typer* t) { 962 Type* Typer::Visitor::JSModulusTyper(Type* lhs, Type* rhs, Typer* t) {
809 lhs = ToNumber(lhs, t); 963 lhs = ToNumber(lhs, t);
810 rhs = ToNumber(rhs, t); 964 rhs = ToNumber(rhs, t);
811 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN(); 965 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN();
812 // TODO(neis): Do some analysis. 966 // TODO(neis): Do some analysis.
813 return Type::Number(); 967 return Type::Number();
814 } 968 }
(...skipping 800 matching lines...) Expand 10 before | Expand all | Expand 10 after
1615 return typer_->float64_array_fun_; 1769 return typer_->float64_array_fun_;
1616 } 1770 }
1617 } 1771 }
1618 } 1772 }
1619 return Type::Constant(value, zone()); 1773 return Type::Constant(value, zone());
1620 } 1774 }
1621 1775
1622 } 1776 }
1623 } 1777 }
1624 } // namespace v8::internal::compiler 1778 } // namespace v8::internal::compiler
OLDNEW
« no previous file with comments | « src/compiler/typer.h ('k') | src/types.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698