Chromium Code Reviews| OLD | NEW |
|---|---|
| 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" |
| 11 #include "src/compiler/simplified-operator.h" | 11 #include "src/compiler/simplified-operator.h" |
| 12 #include "src/compiler/typer.h" | 12 #include "src/compiler/typer.h" |
| 13 | 13 |
| 14 namespace v8 { | 14 namespace v8 { |
| 15 namespace internal { | 15 namespace internal { |
| 16 namespace compiler { | 16 namespace compiler { |
| 17 | 17 |
| 18 class Typer::Decorator : public GraphDecorator { | 18 class Typer::Decorator : public GraphDecorator { |
| 19 public: | 19 public: |
| 20 explicit Decorator(Typer* typer) : typer_(typer) {} | 20 explicit Decorator(Typer* typer) : typer_(typer) {} |
| 21 virtual void Decorate(Node* node); | 21 virtual void Decorate(Node* node); |
| 22 | 22 |
| 23 private: | 23 private: |
| 24 Typer* typer_; | 24 Typer* typer_; |
| 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), |
| 30 context_(context), | |
| 31 decorator_(NULL), | |
| 32 weaken_min_limits_(graph->zone()), | |
| 33 weaken_max_limits_(graph->zone()) { | |
| 30 Zone* zone = this->zone(); | 34 Zone* zone = this->zone(); |
| 31 Factory* f = zone->isolate()->factory(); | 35 Factory* f = zone->isolate()->factory(); |
| 32 | 36 |
| 33 Handle<Object> zero = f->NewNumber(0); | 37 Handle<Object> zero = f->NewNumber(0); |
| 34 Handle<Object> one = f->NewNumber(1); | 38 Handle<Object> one = f->NewNumber(1); |
| 35 Handle<Object> positive_infinity = f->NewNumber(+V8_INFINITY); | 39 Handle<Object> infinity = f->NewNumber(+V8_INFINITY); |
| 36 Handle<Object> negative_infinity = f->NewNumber(-V8_INFINITY); | 40 Handle<Object> minusinfinity = f->NewNumber(-V8_INFINITY); |
| 37 | 41 |
| 38 negative_signed32 = Type::Union( | 42 negative_signed32 = Type::Union( |
| 39 Type::SignedSmall(), Type::OtherSigned32(), zone); | 43 Type::SignedSmall(), Type::OtherSigned32(), zone); |
| 40 non_negative_signed32 = Type::Union( | 44 non_negative_signed32 = Type::Union( |
| 41 Type::UnsignedSmall(), Type::OtherUnsigned31(), zone); | 45 Type::UnsignedSmall(), Type::OtherUnsigned31(), zone); |
| 42 undefined_or_null = Type::Union(Type::Undefined(), Type::Null(), zone); | 46 undefined_or_null = Type::Union(Type::Undefined(), Type::Null(), zone); |
| 43 singleton_false = Type::Constant(f->false_value(), zone); | 47 singleton_false = Type::Constant(f->false_value(), zone); |
| 44 singleton_true = Type::Constant(f->true_value(), zone); | 48 singleton_true = Type::Constant(f->true_value(), zone); |
| 45 singleton_zero = Type::Range(zero, zero, zone); | 49 singleton_zero = Type::Range(zero, zero, zone); |
| 46 singleton_one = Type::Range(one, one, zone); | 50 singleton_one = Type::Range(one, one, zone); |
| 47 zero_or_one = Type::Union(singleton_zero, singleton_one, zone); | 51 zero_or_one = Type::Union(singleton_zero, singleton_one, zone); |
| 48 zeroish = Type::Union( | 52 zeroish = Type::Union( |
| 49 singleton_zero, Type::Union(Type::NaN(), Type::MinusZero(), zone), zone); | 53 singleton_zero, Type::Union(Type::NaN(), Type::MinusZero(), zone), zone); |
| 50 falsish = Type::Union(Type::Undetectable(), | 54 falsish = Type::Union(Type::Undetectable(), |
| 51 Type::Union(zeroish, undefined_or_null, zone), zone); | 55 Type::Union(zeroish, undefined_or_null, zone), zone); |
| 52 integer = Type::Range(negative_infinity, positive_infinity, zone); | 56 integer = Type::Range(minusinfinity, infinity, zone); |
| 57 weakint = Type::Union( | |
| 58 integer, Type::Union(Type::NaN(), Type::MinusZero(), zone), zone); | |
| 53 | 59 |
| 54 Type* number = Type::Number(); | 60 Type* number = Type::Number(); |
| 55 Type* signed32 = Type::Signed32(); | 61 Type* signed32 = Type::Signed32(); |
| 56 Type* unsigned32 = Type::Unsigned32(); | 62 Type* unsigned32 = Type::Unsigned32(); |
| 57 Type* integral32 = Type::Integral32(); | 63 Type* integral32 = Type::Integral32(); |
| 58 Type* object = Type::Object(); | 64 Type* object = Type::Object(); |
| 59 Type* undefined = Type::Undefined(); | 65 Type* undefined = Type::Undefined(); |
| 60 Type* weakint = Type::Union( | |
| 61 integer, Type::Union(Type::NaN(), Type::MinusZero(), zone), zone); | |
| 62 | 66 |
| 63 number_fun0_ = Type::Function(number, zone); | 67 number_fun0_ = Type::Function(number, zone); |
| 64 number_fun1_ = Type::Function(number, number, zone); | 68 number_fun1_ = Type::Function(number, number, zone); |
| 65 number_fun2_ = Type::Function(number, number, number, zone); | 69 number_fun2_ = Type::Function(number, number, number, zone); |
| 66 weakint_fun1_ = Type::Function(weakint, number, zone); | 70 weakint_fun1_ = Type::Function(weakint, number, zone); |
| 67 imul_fun_ = Type::Function(signed32, integral32, integral32, zone); | 71 imul_fun_ = Type::Function(signed32, integral32, integral32, zone); |
| 68 clz32_fun_ = Type::Function( | 72 clz32_fun_ = Type::Function( |
| 69 Type::Range(zero, f->NewNumber(32), zone), number, zone); | 73 Type::Range(zero, f->NewNumber(32), zone), number, zone); |
| 70 random_fun_ = Type::Function(Type::Union( | 74 random_fun_ = Type::Function(Type::Union( |
| 71 Type::UnsignedSmall(), Type::OtherNumber(), zone), zone); | 75 Type::UnsignedSmall(), Type::OtherNumber(), zone), zone); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 106 array_buffer_fun_ = Type::Function(buffer, unsigned32, zone); | 110 array_buffer_fun_ = Type::Function(buffer, unsigned32, zone); |
| 107 int8_array_fun_ = Type::Function(int8_array, arg1, arg2, arg3, zone); | 111 int8_array_fun_ = Type::Function(int8_array, arg1, arg2, arg3, zone); |
| 108 int16_array_fun_ = Type::Function(int16_array, arg1, arg2, arg3, zone); | 112 int16_array_fun_ = Type::Function(int16_array, arg1, arg2, arg3, zone); |
| 109 int32_array_fun_ = Type::Function(int32_array, arg1, arg2, arg3, zone); | 113 int32_array_fun_ = Type::Function(int32_array, arg1, arg2, arg3, zone); |
| 110 uint8_array_fun_ = Type::Function(uint8_array, arg1, arg2, arg3, zone); | 114 uint8_array_fun_ = Type::Function(uint8_array, arg1, arg2, arg3, zone); |
| 111 uint16_array_fun_ = Type::Function(uint16_array, arg1, arg2, arg3, zone); | 115 uint16_array_fun_ = Type::Function(uint16_array, arg1, arg2, arg3, zone); |
| 112 uint32_array_fun_ = Type::Function(uint32_array, arg1, arg2, arg3, zone); | 116 uint32_array_fun_ = Type::Function(uint32_array, arg1, arg2, arg3, zone); |
| 113 float32_array_fun_ = Type::Function(float32_array, arg1, arg2, arg3, zone); | 117 float32_array_fun_ = Type::Function(float32_array, arg1, arg2, arg3, zone); |
| 114 float64_array_fun_ = Type::Function(float64_array, arg1, arg2, arg3, zone); | 118 float64_array_fun_ = Type::Function(float64_array, arg1, arg2, arg3, zone); |
| 115 | 119 |
| 120 const int limits_count = 50; | |
| 121 weaken_min_limits_.reserve(limits_count + 1); | |
| 122 weaken_max_limits_.reserve(limits_count); | |
| 123 | |
| 124 double limit = 1; | |
|
rossberg
2014/10/23 11:50:33
Wouldn't it make sense to go a bit faster at first
Jarin
2014/10/23 13:32:37
Done.
| |
| 125 weaken_min_limits_.push_back(f->NewNumber(0)); | |
| 126 for (int i = 0; i < limits_count; i++) { | |
| 127 weaken_min_limits_.push_back(f->NewNumber(-limit)); | |
| 128 weaken_max_limits_.push_back(f->NewNumber(limit - 1)); | |
| 129 limit *= 2.0; | |
| 130 } | |
| 131 | |
| 116 decorator_ = new (zone) Decorator(this); | 132 decorator_ = new (zone) Decorator(this); |
| 117 graph_->AddDecorator(decorator_); | 133 graph_->AddDecorator(decorator_); |
| 118 } | 134 } |
| 119 | 135 |
| 120 | 136 |
| 121 Typer::~Typer() { | 137 Typer::~Typer() { |
| 122 graph_->RemoveDecorator(decorator_); | 138 graph_->RemoveDecorator(decorator_); |
| 123 } | 139 } |
| 124 | 140 |
| 125 | 141 |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 158 | 174 |
| 159 Type* TypeConstant(Handle<Object> value); | 175 Type* TypeConstant(Handle<Object> value); |
| 160 | 176 |
| 161 protected: | 177 protected: |
| 162 #define DECLARE_METHOD(x) inline Bounds Type##x(Node* node); | 178 #define DECLARE_METHOD(x) inline Bounds Type##x(Node* node); |
| 163 DECLARE_METHOD(Start) | 179 DECLARE_METHOD(Start) |
| 164 VALUE_OP_LIST(DECLARE_METHOD) | 180 VALUE_OP_LIST(DECLARE_METHOD) |
| 165 #undef DECLARE_METHOD | 181 #undef DECLARE_METHOD |
| 166 | 182 |
| 167 Bounds BoundsOrNone(Node* node) { | 183 Bounds BoundsOrNone(Node* node) { |
| 168 return NodeProperties::IsTyped(node) | 184 return NodeProperties::IsTyped(node) ? NodeProperties::GetBounds(node) |
| 169 ? NodeProperties::GetBounds(node) : Bounds(Type::None(zone())); | 185 : Bounds(Type::None()); |
| 170 } | 186 } |
| 171 | 187 |
| 172 Bounds Operand(Node* node, int i) { | 188 Bounds Operand(Node* node, int i) { |
| 173 Node* operand_node = NodeProperties::GetValueInput(node, i); | 189 Node* operand_node = NodeProperties::GetValueInput(node, i); |
| 174 return BoundsOrNone(operand_node); | 190 return BoundsOrNone(operand_node); |
| 175 } | 191 } |
| 176 | 192 |
| 177 Bounds ContextOperand(Node* node) { | 193 Bounds ContextOperand(Node* node) { |
| 178 Bounds result = BoundsOrNone(NodeProperties::GetContextInput(node)); | 194 Bounds result = BoundsOrNone(NodeProperties::GetContextInput(node)); |
| 179 DCHECK(result.upper->Maybe(Type::Internal())); | 195 DCHECK(result.upper->Maybe(Type::Internal())); |
| 180 // TODO(rossberg): More precisely, instead of the above assertion, we should | 196 // TODO(rossberg): More precisely, instead of the above assertion, we should |
| 181 // back-propagate the constraint that it has to be a subtype of Internal. | 197 // back-propagate the constraint that it has to be a subtype of Internal. |
| 182 return result; | 198 return result; |
| 183 } | 199 } |
| 184 | 200 |
| 201 Type* Weaken(Type::RangeType* previous, Type::RangeType* current); | |
| 202 | |
| 185 Zone* zone() { return typer_->zone(); } | 203 Zone* zone() { return typer_->zone(); } |
| 186 Isolate* isolate() { return typer_->isolate(); } | 204 Isolate* isolate() { return typer_->isolate(); } |
| 187 Graph* graph() { return typer_->graph(); } | 205 Graph* graph() { return typer_->graph(); } |
| 188 MaybeHandle<Context> context() { return typer_->context(); } | 206 MaybeHandle<Context> context() { return typer_->context(); } |
| 189 | 207 |
| 190 private: | 208 private: |
| 191 Typer* typer_; | 209 Typer* typer_; |
| 192 MaybeHandle<Context> context_; | 210 MaybeHandle<Context> context_; |
| 193 | 211 |
| 194 typedef Type* (*UnaryTyperFun)(Type*, Typer* t); | 212 typedef Type* (*UnaryTyperFun)(Type*, Typer* t); |
| 195 typedef Type* (*BinaryTyperFun)(Type*, Type*, Typer* t); | 213 typedef Type* (*BinaryTyperFun)(Type*, Type*, Typer* t); |
| 196 | 214 |
| 197 Bounds TypeUnaryOp(Node* node, UnaryTyperFun); | 215 Bounds TypeUnaryOp(Node* node, UnaryTyperFun); |
| 198 Bounds TypeBinaryOp(Node* node, BinaryTyperFun); | 216 Bounds TypeBinaryOp(Node* node, BinaryTyperFun); |
| 199 | 217 |
| 200 static Type* Invert(Type*, Typer*); | 218 static Type* Invert(Type*, Typer*); |
| 201 static Type* FalsifyUndefined(Type*, Typer*); | 219 static Type* FalsifyUndefined(Type*, Typer*); |
| 220 static Type* Rangify(Type*, Typer*); | |
| 202 | 221 |
| 203 static Type* ToPrimitive(Type*, Typer*); | 222 static Type* ToPrimitive(Type*, Typer*); |
| 204 static Type* ToBoolean(Type*, Typer*); | 223 static Type* ToBoolean(Type*, Typer*); |
| 205 static Type* ToNumber(Type*, Typer*); | 224 static Type* ToNumber(Type*, Typer*); |
| 206 static Type* ToString(Type*, Typer*); | 225 static Type* ToString(Type*, Typer*); |
| 207 static Type* NumberToInt32(Type*, Typer*); | 226 static Type* NumberToInt32(Type*, Typer*); |
| 208 static Type* NumberToUint32(Type*, Typer*); | 227 static Type* NumberToUint32(Type*, Typer*); |
| 209 | 228 |
| 210 static Type* JSAddRanger(Type::RangeType*, Type::RangeType*, Typer*); | 229 static Type* JSAddRanger(Type::RangeType*, Type::RangeType*, Typer*); |
| 211 static Type* JSSubtractRanger(Type::RangeType*, Type::RangeType*, Typer*); | 230 static Type* JSSubtractRanger(Type::RangeType*, Type::RangeType*, Typer*); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 245 }; | 264 }; |
| 246 | 265 |
| 247 | 266 |
| 248 class Typer::NarrowVisitor : public Typer::Visitor { | 267 class Typer::NarrowVisitor : public Typer::Visitor { |
| 249 public: | 268 public: |
| 250 explicit NarrowVisitor(Typer* typer) : Visitor(typer) {} | 269 explicit NarrowVisitor(Typer* typer) : Visitor(typer) {} |
| 251 | 270 |
| 252 GenericGraphVisit::Control Pre(Node* node) { | 271 GenericGraphVisit::Control Pre(Node* node) { |
| 253 if (OperatorProperties::HasValueOutput(node->op())) { | 272 if (OperatorProperties::HasValueOutput(node->op())) { |
| 254 Bounds previous = NodeProperties::GetBounds(node); | 273 Bounds previous = NodeProperties::GetBounds(node); |
| 255 Bounds bounds = TypeNode(node); | 274 Bounds current = TypeNode(node); |
| 256 NodeProperties::SetBounds(node, Bounds::Both(bounds, previous, zone())); | 275 NodeProperties::SetBounds(node, Bounds::Both(current, previous, zone())); |
| 257 DCHECK(bounds.Narrows(previous)); | 276 DCHECK(current.Narrows(previous)); |
| 258 // Stop when nothing changed (but allow re-entry in case it does later). | 277 // Stop when nothing changed (but allow re-entry in case it does later). |
| 259 return previous.Narrows(bounds) | 278 return previous.Narrows(current) ? GenericGraphVisit::DEFER |
| 260 ? GenericGraphVisit::DEFER : GenericGraphVisit::REENTER; | 279 : GenericGraphVisit::REENTER; |
| 261 } else { | 280 } else { |
| 262 return GenericGraphVisit::SKIP; | 281 return GenericGraphVisit::SKIP; |
| 263 } | 282 } |
| 264 } | 283 } |
| 265 | 284 |
| 266 GenericGraphVisit::Control Post(Node* node) { | 285 GenericGraphVisit::Control Post(Node* node) { |
| 267 return GenericGraphVisit::REENTER; | 286 return GenericGraphVisit::REENTER; |
| 268 } | 287 } |
| 288 | |
| 289 private: | |
| 290 // Returns the least integers-only supertype that's not a range. If there is | |
| 291 // no such supertype, it returns Range(-inf, +inf) instead. | |
| 292 Type* MaybeWeaken(Type* current, Type* previous) { | |
|
rossberg
2014/10/23 11:50:33
Move this to Typer::Visitor as protected, to avoid
neis
2014/10/23 12:43:06
Also the comment no longer matches the code.
Jarin
2014/10/23 13:32:37
Done.
| |
| 293 if (current->IsRange() && previous->IsRange()) { | |
| 294 return Weaken(previous->AsRange(), current->AsRange()); | |
| 295 } | |
| 296 return current; | |
| 297 } | |
| 269 }; | 298 }; |
| 270 | 299 |
| 271 | 300 |
| 272 class Typer::WidenVisitor : public Typer::Visitor { | 301 class Typer::WidenVisitor : public Typer::Visitor { |
| 273 public: | 302 public: |
| 274 explicit WidenVisitor(Typer* typer) : Visitor(typer) {} | 303 explicit WidenVisitor(Typer* typer) : Visitor(typer) {} |
| 275 | 304 |
| 276 GenericGraphVisit::Control Pre(Node* node) { | 305 GenericGraphVisit::Control Pre(Node* node) { |
| 277 if (OperatorProperties::HasValueOutput(node->op())) { | 306 if (OperatorProperties::HasValueOutput(node->op())) { |
| 278 Bounds previous = BoundsOrNone(node); | 307 Bounds previous = BoundsOrNone(node); |
| 279 Bounds bounds = TypeNode(node); | 308 Bounds current = TypeNode(node); |
| 280 DCHECK(previous.lower->Is(bounds.lower)); | 309 |
| 281 DCHECK(previous.upper->Is(bounds.upper)); | 310 // Speed up termination in the presence of range types: |
| 282 NodeProperties::SetBounds(node, bounds); | 311 current.upper = MaybeWeaken(current.upper, previous.upper); |
| 312 current.lower = MaybeWeaken(current.lower, previous.lower); | |
| 313 | |
| 314 DCHECK(previous.lower->Is(current.lower)); | |
| 315 DCHECK(previous.upper->Is(current.upper)); | |
| 316 | |
| 317 NodeProperties::SetBounds(node, current); | |
| 283 // Stop when nothing changed (but allow re-entry in case it does later). | 318 // Stop when nothing changed (but allow re-entry in case it does later). |
| 284 return bounds.Narrows(previous) | 319 return previous.Narrows(current) && current.Narrows(previous) |
| 285 ? GenericGraphVisit::DEFER : GenericGraphVisit::REENTER; | 320 ? GenericGraphVisit::DEFER |
| 321 : GenericGraphVisit::REENTER; | |
| 286 } else { | 322 } else { |
| 287 return GenericGraphVisit::SKIP; | 323 return GenericGraphVisit::SKIP; |
| 288 } | 324 } |
| 289 } | 325 } |
| 290 | 326 |
| 291 GenericGraphVisit::Control Post(Node* node) { | 327 GenericGraphVisit::Control Post(Node* node) { |
| 292 return GenericGraphVisit::REENTER; | 328 return GenericGraphVisit::REENTER; |
| 293 } | 329 } |
| 330 | |
| 331 private: | |
| 332 Type* MaybeWeaken(Type* current, Type* previous) { | |
| 333 if (current->IsRange() && previous->IsRange()) { | |
| 334 return Weaken(previous->AsRange(), current->AsRange()); | |
| 335 } | |
| 336 return current; | |
| 337 } | |
| 294 }; | 338 }; |
| 295 | 339 |
| 296 | 340 |
| 297 void Typer::Run() { | 341 void Typer::Run() { |
| 298 RunVisitor typing(this); | 342 RunVisitor typing(this); |
| 299 graph_->VisitNodeInputsFromEnd(&typing); | 343 graph_->VisitNodeInputsFromEnd(&typing); |
| 300 // Find least fixpoint. | 344 // Find least fixpoint. |
| 301 WidenVisitor widen(this); | 345 WidenVisitor widen(this); |
| 302 for (NodeSetIter it = typing.redo.begin(); it != typing.redo.end(); ++it) { | 346 for (NodeSetIter it = typing.redo.begin(); it != typing.redo.end(); ++it) { |
| 303 graph_->VisitNodeUsesFrom(*it, &widen); | 347 graph_->VisitNodeUsesFrom(*it, &widen); |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 374 return type; | 418 return type; |
| 375 } | 419 } |
| 376 | 420 |
| 377 | 421 |
| 378 Type* Typer::Visitor::FalsifyUndefined(Type* type, Typer* t) { | 422 Type* Typer::Visitor::FalsifyUndefined(Type* type, Typer* t) { |
| 379 if (type->Is(Type::Undefined())) return t->singleton_false; | 423 if (type->Is(Type::Undefined())) return t->singleton_false; |
| 380 return type; | 424 return type; |
| 381 } | 425 } |
| 382 | 426 |
| 383 | 427 |
| 428 Type* Typer::Visitor::Rangify(Type* type, Typer* t) { | |
| 429 if (!type->Is(t->integer)) return type; // Give up. | |
| 430 if (type->IsRange()) return type; // Shortcut. | |
|
rossberg
2014/10/23 11:50:33
Nit: put this first.
Jarin
2014/10/23 13:32:37
Done.
| |
| 431 Factory* f = t->isolate()->factory(); | |
| 432 return Type::Range(f->NewNumber(type->Min()), f->NewNumber(type->Max()), | |
| 433 t->zone()); | |
| 434 } | |
| 435 | |
| 436 | |
| 384 // Type conversion. | 437 // Type conversion. |
| 385 | 438 |
| 386 | 439 |
| 387 Type* Typer::Visitor::ToPrimitive(Type* type, Typer* t) { | 440 Type* Typer::Visitor::ToPrimitive(Type* type, Typer* t) { |
| 388 if (type->Is(Type::Primitive()) && !type->Maybe(Type::Receiver())) { | 441 if (type->Is(Type::Primitive()) && !type->Maybe(Type::Receiver())) { |
| 389 return type; | 442 return type; |
| 390 } | 443 } |
| 391 return Type::Primitive(); | 444 return Type::Primitive(); |
| 392 } | 445 } |
| 393 | 446 |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 448 | 501 |
| 449 // Common operators. | 502 // Common operators. |
| 450 | 503 |
| 451 | 504 |
| 452 Bounds Typer::Visitor::TypeParameter(Node* node) { | 505 Bounds Typer::Visitor::TypeParameter(Node* node) { |
| 453 return Bounds::Unbounded(zone()); | 506 return Bounds::Unbounded(zone()); |
| 454 } | 507 } |
| 455 | 508 |
| 456 | 509 |
| 457 Bounds Typer::Visitor::TypeInt32Constant(Node* node) { | 510 Bounds Typer::Visitor::TypeInt32Constant(Node* node) { |
| 458 Factory* f = zone()->isolate()->factory(); | 511 Factory* f = isolate()->factory(); |
| 459 Handle<Object> number = f->NewNumber(OpParameter<int32_t>(node)); | 512 Handle<Object> number = f->NewNumber(OpParameter<int32_t>(node)); |
| 460 return Bounds(Type::Intersect( | 513 return Bounds(Type::Intersect( |
| 461 Type::Range(number, number, zone()), Type::UntaggedInt32(), zone())); | 514 Type::Range(number, number, zone()), Type::UntaggedInt32(), zone())); |
| 462 } | 515 } |
| 463 | 516 |
| 464 | 517 |
| 465 Bounds Typer::Visitor::TypeInt64Constant(Node* node) { | 518 Bounds Typer::Visitor::TypeInt64Constant(Node* node) { |
| 466 return Bounds(Type::Internal()); // TODO(rossberg): Add int64 bitset type? | 519 return Bounds(Type::Internal()); // TODO(rossberg): Add int64 bitset type? |
| 467 } | 520 } |
| 468 | 521 |
| 469 | 522 |
| 470 Bounds Typer::Visitor::TypeFloat32Constant(Node* node) { | 523 Bounds Typer::Visitor::TypeFloat32Constant(Node* node) { |
| 471 return Bounds(Type::Intersect( | 524 return Bounds(Type::Intersect( |
| 472 Type::Of(OpParameter<float>(node), zone()), | 525 Type::Of(OpParameter<float>(node), zone()), |
| 473 Type::UntaggedFloat32(), zone())); | 526 Type::UntaggedFloat32(), zone())); |
| 474 } | 527 } |
| 475 | 528 |
| 476 | 529 |
| 477 Bounds Typer::Visitor::TypeFloat64Constant(Node* node) { | 530 Bounds Typer::Visitor::TypeFloat64Constant(Node* node) { |
| 478 return Bounds(Type::Intersect( | 531 return Bounds(Type::Intersect( |
| 479 Type::Of(OpParameter<double>(node), zone()), | 532 Type::Of(OpParameter<double>(node), zone()), |
| 480 Type::UntaggedFloat64(), zone())); | 533 Type::UntaggedFloat64(), zone())); |
| 481 } | 534 } |
| 482 | 535 |
| 483 | 536 |
| 484 Bounds Typer::Visitor::TypeNumberConstant(Node* node) { | 537 Bounds Typer::Visitor::TypeNumberConstant(Node* node) { |
| 485 Factory* f = zone()->isolate()->factory(); | 538 Factory* f = isolate()->factory(); |
| 486 return Bounds(Type::Constant( | 539 return Bounds(Type::Constant( |
| 487 f->NewNumber(OpParameter<double>(node)), zone())); | 540 f->NewNumber(OpParameter<double>(node)), zone())); |
| 488 } | 541 } |
| 489 | 542 |
| 490 | 543 |
| 491 Bounds Typer::Visitor::TypeHeapConstant(Node* node) { | 544 Bounds Typer::Visitor::TypeHeapConstant(Node* node) { |
| 492 return Bounds(TypeConstant(OpParameter<Unique<Object> >(node).handle())); | 545 return Bounds(TypeConstant(OpParameter<Unique<Object> >(node).handle())); |
| 493 } | 546 } |
| 494 | 547 |
| 495 | 548 |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 652 Type* Typer::Visitor::JSGreaterThanOrEqualTyper( | 705 Type* Typer::Visitor::JSGreaterThanOrEqualTyper( |
| 653 Type* lhs, Type* rhs, Typer* t) { | 706 Type* lhs, Type* rhs, Typer* t) { |
| 654 return FalsifyUndefined(Invert(JSCompareTyper(lhs, rhs, t), t), t); | 707 return FalsifyUndefined(Invert(JSCompareTyper(lhs, rhs, t), t), t); |
| 655 } | 708 } |
| 656 | 709 |
| 657 | 710 |
| 658 // JS bitwise operators. | 711 // JS bitwise operators. |
| 659 | 712 |
| 660 | 713 |
| 661 Type* Typer::Visitor::JSBitwiseOrTyper(Type* lhs, Type* rhs, Typer* t) { | 714 Type* Typer::Visitor::JSBitwiseOrTyper(Type* lhs, Type* rhs, Typer* t) { |
| 662 Factory* f = t->zone()->isolate()->factory(); | 715 Factory* f = t->isolate()->factory(); |
| 663 lhs = NumberToInt32(ToNumber(lhs, t), t); | 716 lhs = NumberToInt32(ToNumber(lhs, t), t); |
| 664 rhs = NumberToInt32(ToNumber(rhs, t), t); | 717 rhs = NumberToInt32(ToNumber(rhs, t), t); |
| 665 double lmin = lhs->Min(); | 718 double lmin = lhs->Min(); |
| 666 double rmin = rhs->Min(); | 719 double rmin = rhs->Min(); |
| 667 double lmax = lhs->Max(); | 720 double lmax = lhs->Max(); |
| 668 double rmax = rhs->Max(); | 721 double rmax = rhs->Max(); |
| 669 // Or-ing any two values results in a value no smaller than their minimum. | 722 // Or-ing any two values results in a value no smaller than their minimum. |
| 670 // Even no smaller than their maximum if both values are non-negative. | 723 // Even no smaller than their maximum if both values are non-negative. |
| 671 Handle<Object> min = f->NewNumber( | 724 Handle<Object> min = f->NewNumber( |
| 672 lmin >= 0 && rmin >= 0 ? std::max(lmin, rmin) : std::min(lmin, rmin)); | 725 lmin >= 0 && rmin >= 0 ? std::max(lmin, rmin) : std::min(lmin, rmin)); |
| 673 if (lmax < 0 || rmax < 0) { | 726 if (lmax < 0 || rmax < 0) { |
| 674 // Or-ing two values of which at least one is negative results in a negative | 727 // Or-ing two values of which at least one is negative results in a negative |
| 675 // value. | 728 // value. |
| 676 Handle<Object> max = f->NewNumber(-1); | 729 Handle<Object> max = f->NewNumber(-1); |
| 677 return Type::Range(min, max, t->zone()); | 730 return Type::Range(min, max, t->zone()); |
| 678 } | 731 } |
| 679 Handle<Object> max = f->NewNumber(Type::Signed32()->Max()); | 732 Handle<Object> max = f->NewNumber(Type::Signed32()->Max()); |
| 680 return Type::Range(min, max, t->zone()); | 733 return Type::Range(min, max, t->zone()); |
| 681 // TODO(neis): Be precise for singleton inputs, here and elsewhere. | 734 // TODO(neis): Be precise for singleton inputs, here and elsewhere. |
| 682 } | 735 } |
| 683 | 736 |
| 684 | 737 |
| 685 Type* Typer::Visitor::JSBitwiseAndTyper(Type* lhs, Type* rhs, Typer* t) { | 738 Type* Typer::Visitor::JSBitwiseAndTyper(Type* lhs, Type* rhs, Typer* t) { |
| 686 Factory* f = t->zone()->isolate()->factory(); | 739 Factory* f = t->isolate()->factory(); |
| 687 lhs = NumberToInt32(ToNumber(lhs, t), t); | 740 lhs = NumberToInt32(ToNumber(lhs, t), t); |
| 688 rhs = NumberToInt32(ToNumber(rhs, t), t); | 741 rhs = NumberToInt32(ToNumber(rhs, t), t); |
| 689 double lmin = lhs->Min(); | 742 double lmin = lhs->Min(); |
| 690 double rmin = rhs->Min(); | 743 double rmin = rhs->Min(); |
| 691 double lmax = lhs->Max(); | 744 double lmax = lhs->Max(); |
| 692 double rmax = rhs->Max(); | 745 double rmax = rhs->Max(); |
| 693 // And-ing any two values results in a value no larger than their maximum. | 746 // And-ing any two values results in a value no larger than their maximum. |
| 694 // Even no larger than their minimum if both values are non-negative. | 747 // Even no larger than their minimum if both values are non-negative. |
| 695 Handle<Object> max = f->NewNumber( | 748 Handle<Object> max = f->NewNumber( |
| 696 lmin >= 0 && rmin >= 0 ? std::min(lmax, rmax) : std::max(lmax, rmax)); | 749 lmin >= 0 && rmin >= 0 ? std::min(lmax, rmax) : std::max(lmax, rmax)); |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 724 } | 777 } |
| 725 | 778 |
| 726 | 779 |
| 727 Type* Typer::Visitor::JSShiftLeftTyper(Type* lhs, Type* rhs, Typer* t) { | 780 Type* Typer::Visitor::JSShiftLeftTyper(Type* lhs, Type* rhs, Typer* t) { |
| 728 return Type::Signed32(); | 781 return Type::Signed32(); |
| 729 } | 782 } |
| 730 | 783 |
| 731 | 784 |
| 732 Type* Typer::Visitor::JSShiftRightTyper(Type* lhs, Type* rhs, Typer* t) { | 785 Type* Typer::Visitor::JSShiftRightTyper(Type* lhs, Type* rhs, Typer* t) { |
| 733 lhs = NumberToInt32(ToNumber(lhs, t), t); | 786 lhs = NumberToInt32(ToNumber(lhs, t), t); |
| 734 Factory* f = t->zone()->isolate()->factory(); | 787 Factory* f = t->isolate()->factory(); |
| 735 if (lhs->Min() >= 0) { | 788 if (lhs->Min() >= 0) { |
| 736 // Right-shifting a non-negative value cannot make it negative, nor larger. | 789 // Right-shifting a non-negative value cannot make it negative, nor larger. |
| 737 Handle<Object> min = f->NewNumber(0); | 790 Handle<Object> min = f->NewNumber(0); |
| 738 Handle<Object> max = f->NewNumber(lhs->Max()); | 791 Handle<Object> max = f->NewNumber(lhs->Max()); |
| 739 return Type::Range(min, max, t->zone()); | 792 return Type::Range(min, max, t->zone()); |
| 740 } | 793 } |
| 741 if (lhs->Max() < 0) { | 794 if (lhs->Max() < 0) { |
| 742 // Right-shifting a negative value cannot make it non-negative, nor smaller. | 795 // Right-shifting a negative value cannot make it non-negative, nor smaller. |
| 743 Handle<Object> min = f->NewNumber(lhs->Min()); | 796 Handle<Object> min = f->NewNumber(lhs->Min()); |
| 744 Handle<Object> max = f->NewNumber(-1); | 797 Handle<Object> max = f->NewNumber(-1); |
| 745 return Type::Range(min, max, t->zone()); | 798 return Type::Range(min, max, t->zone()); |
| 746 } | 799 } |
| 747 return Type::Signed32(); | 800 return Type::Signed32(); |
| 748 } | 801 } |
| 749 | 802 |
| 750 | 803 |
| 751 Type* Typer::Visitor::JSShiftRightLogicalTyper(Type* lhs, Type* rhs, Typer* t) { | 804 Type* Typer::Visitor::JSShiftRightLogicalTyper(Type* lhs, Type* rhs, Typer* t) { |
| 752 lhs = NumberToUint32(ToNumber(lhs, t), t); | 805 lhs = NumberToUint32(ToNumber(lhs, t), t); |
| 753 Factory* f = t->zone()->isolate()->factory(); | 806 Factory* f = t->isolate()->factory(); |
| 754 // Logical right-shifting any value cannot make it larger. | 807 // Logical right-shifting any value cannot make it larger. |
| 755 Handle<Object> min = f->NewNumber(0); | 808 Handle<Object> min = f->NewNumber(0); |
| 756 Handle<Object> max = f->NewNumber(lhs->Max()); | 809 Handle<Object> max = f->NewNumber(lhs->Max()); |
| 757 return Type::Range(min, max, t->zone()); | 810 return Type::Range(min, max, t->zone()); |
| 758 } | 811 } |
| 759 | 812 |
| 760 | 813 |
| 761 // JS arithmetic operators. | 814 // JS arithmetic operators. |
| 762 | 815 |
| 763 | 816 |
| 817 // Returns the array's least element, ignoring NaN. | |
| 818 // There must be at least one non-NaN element. | |
| 819 // Any -0 is converted to 0. | |
| 820 static double array_min(double a[], size_t n) { | |
| 821 DCHECK(n != 0); | |
| 822 double x = a[0]; | |
|
rossberg
2014/10/23 11:50:33
What if this is already a NaN? As discussed offlin
neis
2014/10/23 12:43:06
If x is nan initially, the result of the first min
Jarin
2014/10/23 13:32:37
Done.
| |
| 823 for (size_t i = 1; i < n; ++i) { | |
| 824 x = std::min(std::isnan(a[i]) ? +V8_INFINITY : a[i], x); | |
|
rossberg
2014/10/23 11:50:33
Simplify to
if (!std::isnan(a[i])) x = std::min
Jarin
2014/10/23 13:32:37
Done.
| |
| 825 } | |
| 826 DCHECK(!std::isnan(x)); | |
| 827 return x == 0 ? 0 : x; // -0 -> 0 | |
| 828 } | |
| 829 | |
| 830 | |
| 831 // Returns the array's greatest element, ignoring NaN. | |
| 832 // There must be at least one non-NaN element. | |
| 833 // Any -0 is converted to 0. | |
| 834 static double array_max(double a[], size_t n) { | |
|
rossberg
2014/10/23 11:50:33
Same here.
Jarin
2014/10/23 13:32:37
Done.
| |
| 835 DCHECK(n != 0); | |
| 836 double x = a[0]; | |
| 837 for (size_t i = 1; i < n; ++i) { | |
| 838 x = std::max(std::isnan(a[i]) ? -V8_INFINITY : a[i], x); | |
| 839 } | |
| 840 DCHECK(!std::isnan(x)); | |
| 841 return x == 0 ? 0 : x; // -0 -> 0 | |
| 842 } | |
| 843 | |
| 844 | |
| 845 Type* Typer::Visitor::JSAddRanger(Type::RangeType* lhs, Type::RangeType* rhs, | |
| 846 Typer* t) { | |
| 847 double results[4]; | |
| 848 results[0] = lhs->Min()->Number() + rhs->Min()->Number(); | |
| 849 results[1] = lhs->Min()->Number() + rhs->Max()->Number(); | |
| 850 results[2] = lhs->Max()->Number() + rhs->Min()->Number(); | |
| 851 results[3] = lhs->Max()->Number() + rhs->Max()->Number(); | |
| 852 // Since none of the inputs can be -0, the result cannot be -0 either. | |
| 853 // However, it can be nan (the sum of two infinities of opposite sign). | |
| 854 // On the other hand, if none of the "results" above is nan, then the actual | |
| 855 // result cannot be nan either. | |
| 856 int nans = 0; | |
| 857 for (int i = 0; i < 4; ++i) { | |
| 858 if (std::isnan(results[i])) ++nans; | |
| 859 } | |
| 860 if (nans == 4) return Type::NaN(); // [-inf..-inf] + [inf..inf] or vice versa | |
| 861 Factory* f = t->isolate()->factory(); | |
| 862 Type* range = Type::Range(f->NewNumber(array_min(results, 4)), | |
| 863 f->NewNumber(array_max(results, 4)), t->zone()); | |
| 864 return nans == 0 ? range : Type::Union(range, Type::NaN(), t->zone()); | |
| 865 // Examples: | |
| 866 // [-inf, -inf] + [+inf, +inf] = NaN | |
| 867 // [-inf, -inf] + [n, +inf] = [-inf, -inf] \/ NaN | |
| 868 // [-inf, +inf] + [n, +inf] = [-inf, +inf] \/ NaN | |
| 869 // [-inf, m] + [n, +inf] = [-inf, +inf] \/ NaN | |
| 870 } | |
| 871 | |
| 872 | |
| 764 Type* Typer::Visitor::JSAddTyper(Type* lhs, Type* rhs, Typer* t) { | 873 Type* Typer::Visitor::JSAddTyper(Type* lhs, Type* rhs, Typer* t) { |
| 765 lhs = ToPrimitive(lhs, t); | 874 lhs = ToPrimitive(lhs, t); |
| 766 rhs = ToPrimitive(rhs, t); | 875 rhs = ToPrimitive(rhs, t); |
| 767 if (lhs->Maybe(Type::String()) || rhs->Maybe(Type::String())) { | 876 if (lhs->Maybe(Type::String()) || rhs->Maybe(Type::String())) { |
| 768 if (lhs->Is(Type::String()) || rhs->Is(Type::String())) { | 877 if (lhs->Is(Type::String()) || rhs->Is(Type::String())) { |
| 769 return Type::String(); | 878 return Type::String(); |
| 770 } else { | 879 } else { |
| 771 return Type::NumberOrString(); | 880 return Type::NumberOrString(); |
| 772 } | 881 } |
| 773 } | 882 } |
| 774 lhs = ToNumber(lhs, t); | 883 lhs = Rangify(ToNumber(lhs, t), t); |
| 775 rhs = ToNumber(rhs, t); | 884 rhs = Rangify(ToNumber(rhs, t), t); |
| 776 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN(); | 885 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN(); |
| 777 // TODO(neis): Do some analysis. | 886 if (lhs->IsRange() && rhs->IsRange()) { |
| 887 return JSAddRanger(lhs->AsRange(), rhs->AsRange(), t); | |
| 888 } | |
| 778 // TODO(neis): Deal with numeric bitsets here and elsewhere. | 889 // TODO(neis): Deal with numeric bitsets here and elsewhere. |
|
rossberg
2014/10/23 11:50:33
This seems to be subsumed by Rangify.
neis
2014/10/23 12:43:06
Rangify converts a union of integer constants and
| |
| 779 return Type::Number(); | 890 return Type::Number(); |
| 780 } | 891 } |
| 781 | 892 |
| 782 | 893 |
| 894 Type* Typer::Visitor::JSSubtractRanger(Type::RangeType* lhs, | |
| 895 Type::RangeType* rhs, Typer* t) { | |
| 896 double results[4]; | |
| 897 results[0] = lhs->Min()->Number() - rhs->Min()->Number(); | |
| 898 results[1] = lhs->Min()->Number() - rhs->Max()->Number(); | |
| 899 results[2] = lhs->Max()->Number() - rhs->Min()->Number(); | |
| 900 results[3] = lhs->Max()->Number() - rhs->Max()->Number(); | |
| 901 // Since none of the inputs can be -0, the result cannot be -0. | |
| 902 // However, it can be nan (the subtraction of two infinities of same sign). | |
| 903 // On the other hand, if none of the "results" above is nan, then the actual | |
| 904 // result cannot be nan either. | |
| 905 int nans = 0; | |
| 906 for (int i = 0; i < 4; ++i) { | |
| 907 if (std::isnan(results[i])) ++nans; | |
| 908 } | |
| 909 if (nans == 4) return Type::NaN(); // [inf..inf] - [inf..inf] (all same sign) | |
| 910 Factory* f = t->isolate()->factory(); | |
| 911 Type* range = Type::Range(f->NewNumber(array_min(results, 4)), | |
| 912 f->NewNumber(array_max(results, 4)), t->zone()); | |
| 913 return nans == 0 ? range : Type::Union(range, Type::NaN(), t->zone()); | |
| 914 // Examples: | |
| 915 // [-inf, +inf] - [-inf, +inf] = [-inf, +inf] \/ NaN | |
| 916 // [-inf, -inf] - [-inf, -inf] = NaN | |
| 917 // [-inf, -inf] - [n, +inf] = [-inf, -inf] \/ NaN | |
| 918 // [m, +inf] - [-inf, n] = [-inf, +inf] \/ NaN | |
| 919 } | |
| 920 | |
| 921 | |
| 783 Type* Typer::Visitor::JSSubtractTyper(Type* lhs, Type* rhs, Typer* t) { | 922 Type* Typer::Visitor::JSSubtractTyper(Type* lhs, Type* rhs, Typer* t) { |
| 784 lhs = ToNumber(lhs, t); | 923 lhs = Rangify(ToNumber(lhs, t), t); |
| 785 rhs = ToNumber(rhs, t); | 924 rhs = Rangify(ToNumber(rhs, t), t); |
| 786 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN(); | 925 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN(); |
| 787 // TODO(neis): Do some analysis. | 926 if (lhs->IsRange() && rhs->IsRange()) { |
| 927 return JSSubtractRanger(lhs->AsRange(), rhs->AsRange(), t); | |
| 928 } | |
| 788 return Type::Number(); | 929 return Type::Number(); |
| 789 } | 930 } |
| 790 | 931 |
| 791 | 932 |
| 933 Type* Typer::Visitor::JSMultiplyRanger(Type::RangeType* lhs, | |
| 934 Type::RangeType* rhs, Typer* t) { | |
| 935 double results[4]; | |
| 936 double lmin = lhs->Min()->Number(); | |
| 937 double lmax = lhs->Max()->Number(); | |
| 938 double rmin = rhs->Min()->Number(); | |
| 939 double rmax = rhs->Max()->Number(); | |
| 940 results[0] = lmin * rmin; | |
| 941 results[1] = lmin * rmax; | |
| 942 results[2] = lmax * rmin; | |
| 943 results[3] = lmax * rmax; | |
| 944 // If the result may be nan, we give up on calculating a precise type, because | |
| 945 // the discontinuity makes it too complicated. Note that even if none of the | |
| 946 // "results" above is nan, the actual result may still be, so we have to do a | |
| 947 // different check: | |
| 948 bool maybe_nan = (lhs->Maybe(t->singleton_zero) && | |
| 949 (rmin == -V8_INFINITY || rmax == +V8_INFINITY)) || | |
| 950 (rhs->Maybe(t->singleton_zero) && | |
| 951 (lmin == -V8_INFINITY || lmax == +V8_INFINITY)); | |
| 952 if (maybe_nan) return t->weakint; // Giving up. | |
| 953 bool maybe_minuszero = (lhs->Maybe(t->singleton_zero) && rmin < 0) || | |
| 954 (rhs->Maybe(t->singleton_zero) && lmin < 0); | |
| 955 Factory* f = t->isolate()->factory(); | |
| 956 Type* range = Type::Range(f->NewNumber(array_min(results, 4)), | |
| 957 f->NewNumber(array_max(results, 4)), t->zone()); | |
| 958 return maybe_minuszero ? Type::Union(range, Type::MinusZero(), t->zone()) | |
| 959 : range; | |
| 960 } | |
| 961 | |
| 962 | |
| 792 Type* Typer::Visitor::JSMultiplyTyper(Type* lhs, Type* rhs, Typer* t) { | 963 Type* Typer::Visitor::JSMultiplyTyper(Type* lhs, Type* rhs, Typer* t) { |
| 793 lhs = ToNumber(lhs, t); | 964 lhs = Rangify(ToNumber(lhs, t), t); |
| 794 rhs = ToNumber(rhs, t); | 965 rhs = Rangify(ToNumber(rhs, t), t); |
| 795 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN(); | 966 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN(); |
| 796 // TODO(neis): Do some analysis. | 967 if (lhs->IsRange() && rhs->IsRange()) { |
| 968 return JSMultiplyRanger(lhs->AsRange(), rhs->AsRange(), t); | |
| 969 } | |
| 797 return Type::Number(); | 970 return Type::Number(); |
| 798 } | 971 } |
| 799 | 972 |
| 800 | 973 |
| 801 Type* Typer::Visitor::JSDivideTyper(Type* lhs, Type* rhs, Typer* t) { | 974 Type* Typer::Visitor::JSDivideTyper(Type* lhs, Type* rhs, Typer* t) { |
| 802 lhs = ToNumber(lhs, t); | 975 lhs = ToNumber(lhs, t); |
| 803 rhs = ToNumber(rhs, t); | 976 rhs = ToNumber(rhs, t); |
| 804 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN(); | 977 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN(); |
| 805 // TODO(neis): Do some analysis. | 978 // Division is tricky, so all we do is try ruling out nan. |
| 806 return Type::Number(); | 979 // TODO(neis): try ruling out -0 as well? |
| 980 bool maybe_nan = | |
| 981 lhs->Maybe(Type::NaN()) || rhs->Maybe(Type::NaN()) || | |
| 982 rhs->Maybe(t->singleton_zero) || | |
|
rossberg
2014/10/23 11:50:33
I think this needs to check for -0 as well.
Also,
neis
2014/10/23 12:43:06
Acknowledged.
Jarin
2014/10/23 13:32:37
Done.
| |
| 983 ((lhs->Min() == -V8_INFINITY || lhs->Max() == +V8_INFINITY) && | |
| 984 (rhs->Min() == -V8_INFINITY || rhs->Max() == +V8_INFINITY)); | |
| 985 return maybe_nan ? Type::Number() : Type::OrderedNumber(); | |
| 807 } | 986 } |
| 808 | 987 |
| 809 | 988 |
| 810 Type* Typer::Visitor::JSModulusTyper(Type* lhs, Type* rhs, Typer* t) { | 989 Type* Typer::Visitor::JSModulusTyper(Type* lhs, Type* rhs, Typer* t) { |
| 811 lhs = ToNumber(lhs, t); | 990 lhs = ToNumber(lhs, t); |
| 812 rhs = ToNumber(rhs, t); | 991 rhs = ToNumber(rhs, t); |
| 813 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN(); | 992 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN(); |
| 814 // TODO(neis): Do some analysis. | 993 // Division is tricky, so all we do is try ruling out nan. |
| 815 return Type::Number(); | 994 // TODO(neis): try ruling out -0 as well? |
| 995 bool maybe_nan = | |
| 996 lhs->Maybe(Type::NaN()) || rhs->Maybe(Type::NaN()) || | |
| 997 rhs->Maybe(t->singleton_zero) || | |
|
rossberg
2014/10/23 11:50:33
Same here.
Jarin
2014/10/23 13:32:37
Done.
| |
| 998 ((lhs->Min() == -V8_INFINITY || lhs->Max() == +V8_INFINITY) && | |
| 999 (rhs->Min() == -V8_INFINITY || rhs->Max() == +V8_INFINITY)); | |
| 1000 return maybe_nan ? Type::Number() : Type::OrderedNumber(); | |
| 816 } | 1001 } |
| 817 | 1002 |
| 818 | 1003 |
| 819 // JS unary operators. | 1004 // JS unary operators. |
| 820 | 1005 |
| 821 | 1006 |
| 822 Type* Typer::Visitor::JSUnaryNotTyper(Type* type, Typer* t) { | 1007 Type* Typer::Visitor::JSUnaryNotTyper(Type* type, Typer* t) { |
| 823 return Invert(ToBoolean(type, t), t); | 1008 return Invert(ToBoolean(type, t), t); |
| 824 } | 1009 } |
| 825 | 1010 |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 883 Bounds Typer::Visitor::TypeJSLoadProperty(Node* node) { | 1068 Bounds Typer::Visitor::TypeJSLoadProperty(Node* node) { |
| 884 return TypeBinaryOp(node, JSLoadPropertyTyper); | 1069 return TypeBinaryOp(node, JSLoadPropertyTyper); |
| 885 } | 1070 } |
| 886 | 1071 |
| 887 | 1072 |
| 888 Bounds Typer::Visitor::TypeJSLoadNamed(Node* node) { | 1073 Bounds Typer::Visitor::TypeJSLoadNamed(Node* node) { |
| 889 return Bounds::Unbounded(zone()); | 1074 return Bounds::Unbounded(zone()); |
| 890 } | 1075 } |
| 891 | 1076 |
| 892 | 1077 |
| 1078 Type* Typer::Visitor::Weaken(Type::RangeType* previous, | |
| 1079 Type::RangeType* current) { | |
| 1080 double current_min = current->Min()->Number(); | |
| 1081 double current_max = current->Max()->Number(); | |
| 1082 | |
| 1083 Handle<Object> new_min = current->Min(); | |
| 1084 Handle<Object> new_max = current->Max(); | |
| 1085 | |
| 1086 // Find the closest lower entry in the list of allowed | |
| 1087 // minima (or negative infinity if there is no such entry). | |
| 1088 if (current_min != previous->Min()->Number()) { | |
| 1089 new_min = typer_->integer->AsRange()->Min(); | |
| 1090 for (auto i = typer_->weaken_min_limits_.begin(); | |
|
Benedikt Meurer
2014/10/23 10:33:26
range based for loops: for (const auto val : weake
Jarin
2014/10/23 11:14:52
Done.
| |
| 1091 i != typer_->weaken_min_limits_.end(); i++) { | |
| 1092 if ((*i)->Number() <= current_min) { | |
| 1093 new_min = *i; | |
| 1094 break; | |
| 1095 } | |
| 1096 } | |
| 1097 } | |
| 1098 | |
| 1099 // Find the closest greater entry in the list of allowed | |
| 1100 // maxima (or infinity if there is no such entry). | |
| 1101 if (current_max != previous->Max()->Number()) { | |
| 1102 new_max = typer_->integer->AsRange()->Max(); | |
| 1103 for (auto i = typer_->weaken_max_limits_.begin(); | |
|
Benedikt Meurer
2014/10/23 10:33:26
range based for loops: for (const auto val : weake
Jarin
2014/10/23 11:14:52
Done.
| |
| 1104 i != typer_->weaken_max_limits_.end(); i++) { | |
| 1105 if ((*i)->Number() >= current_max) { | |
| 1106 new_max = *i; | |
| 1107 break; | |
| 1108 } | |
| 1109 } | |
| 1110 } | |
| 1111 | |
| 1112 return Type::Range(new_min, new_max, typer_->zone()); | |
| 1113 } | |
| 1114 | |
| 1115 | |
| 893 Bounds Typer::Visitor::TypeJSStoreProperty(Node* node) { | 1116 Bounds Typer::Visitor::TypeJSStoreProperty(Node* node) { |
| 894 UNREACHABLE(); | 1117 UNREACHABLE(); |
| 895 return Bounds(); | 1118 return Bounds(); |
| 896 } | 1119 } |
| 897 | 1120 |
| 898 | 1121 |
| 899 Bounds Typer::Visitor::TypeJSStoreNamed(Node* node) { | 1122 Bounds Typer::Visitor::TypeJSStoreNamed(Node* node) { |
| 900 UNREACHABLE(); | 1123 UNREACHABLE(); |
| 901 return Bounds(); | 1124 return Bounds(); |
| 902 } | 1125 } |
| (...skipping 732 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1635 return typer_->float64_array_fun_; | 1858 return typer_->float64_array_fun_; |
| 1636 } | 1859 } |
| 1637 } | 1860 } |
| 1638 } | 1861 } |
| 1639 return Type::Constant(value, zone()); | 1862 return Type::Constant(value, zone()); |
| 1640 } | 1863 } |
| 1641 | 1864 |
| 1642 } | 1865 } |
| 1643 } | 1866 } |
| 1644 } // namespace v8::internal::compiler | 1867 } // namespace v8::internal::compiler |
| OLD | NEW |