| 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/compiler/graph-inl.h" | 6 #include "src/compiler/graph-inl.h" |
| 6 #include "src/compiler/js-operator.h" | 7 #include "src/compiler/js-operator.h" |
| 7 #include "src/compiler/node.h" | 8 #include "src/compiler/node.h" |
| 8 #include "src/compiler/node-properties-inl.h" | 9 #include "src/compiler/node-properties-inl.h" |
| 9 #include "src/compiler/node-properties.h" | 10 #include "src/compiler/node-properties.h" |
| 10 #include "src/compiler/simplified-operator.h" | 11 #include "src/compiler/simplified-operator.h" |
| 11 #include "src/compiler/typer.h" | 12 #include "src/compiler/typer.h" |
| 12 | 13 |
| 13 namespace v8 { | 14 namespace v8 { |
| 14 namespace internal { | 15 namespace internal { |
| 15 namespace compiler { | 16 namespace compiler { |
| 16 | 17 |
| 17 Typer::Typer(Zone* zone) : zone_(zone) { | 18 class Typer::Decorator : public GraphDecorator { |
| 19 public: |
| 20 explicit Decorator(Typer* typer) : typer_(typer) {} |
| 21 virtual void Decorate(Node* node); |
| 22 |
| 23 private: |
| 24 Typer* typer_; |
| 25 }; |
| 26 |
| 27 |
| 28 Typer::Typer(Graph* graph, MaybeHandle<Context> context) |
| 29 : graph_(graph), context_(context), decorator_(NULL) { |
| 30 Zone* zone = this->zone(); |
| 18 Factory* f = zone->isolate()->factory(); | 31 Factory* f = zone->isolate()->factory(); |
| 19 | 32 |
| 20 Type* number = Type::Number(); | 33 Type* number = Type::Number(); |
| 21 Type* signed32 = Type::Signed32(); | 34 Type* signed32 = Type::Signed32(); |
| 22 Type* unsigned32 = Type::Unsigned32(); | 35 Type* unsigned32 = Type::Unsigned32(); |
| 23 Type* integral32 = Type::Integral32(); | 36 Type* integral32 = Type::Integral32(); |
| 24 Type* object = Type::Object(); | 37 Type* object = Type::Object(); |
| 25 Type* undefined = Type::Undefined(); | 38 Type* undefined = Type::Undefined(); |
| 26 Type* weakint = Type::Union( | 39 Type* weakint = Type::Union( |
| 27 Type::Range(f->NewNumber(-V8_INFINITY), f->NewNumber(+V8_INFINITY), zone), | 40 Type::Range(f->NewNumber(-V8_INFINITY), f->NewNumber(+V8_INFINITY), zone), |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 62 Type* arg3 = arg2; | 75 Type* arg3 = arg2; |
| 63 array_buffer_fun_ = Type::Function(buffer, unsigned32, zone); | 76 array_buffer_fun_ = Type::Function(buffer, unsigned32, zone); |
| 64 int8_array_fun_ = Type::Function(int8_array, arg1, arg2, arg3, zone); | 77 int8_array_fun_ = Type::Function(int8_array, arg1, arg2, arg3, zone); |
| 65 int16_array_fun_ = Type::Function(int16_array, arg1, arg2, arg3, zone); | 78 int16_array_fun_ = Type::Function(int16_array, arg1, arg2, arg3, zone); |
| 66 int32_array_fun_ = Type::Function(int32_array, arg1, arg2, arg3, zone); | 79 int32_array_fun_ = Type::Function(int32_array, arg1, arg2, arg3, zone); |
| 67 uint8_array_fun_ = Type::Function(uint8_array, arg1, arg2, arg3, zone); | 80 uint8_array_fun_ = Type::Function(uint8_array, arg1, arg2, arg3, zone); |
| 68 uint16_array_fun_ = Type::Function(uint16_array, arg1, arg2, arg3, zone); | 81 uint16_array_fun_ = Type::Function(uint16_array, arg1, arg2, arg3, zone); |
| 69 uint32_array_fun_ = Type::Function(uint32_array, arg1, arg2, arg3, zone); | 82 uint32_array_fun_ = Type::Function(uint32_array, arg1, arg2, arg3, zone); |
| 70 float32_array_fun_ = Type::Function(float32_array, arg1, arg2, arg3, zone); | 83 float32_array_fun_ = Type::Function(float32_array, arg1, arg2, arg3, zone); |
| 71 float64_array_fun_ = Type::Function(float64_array, arg1, arg2, arg3, zone); | 84 float64_array_fun_ = Type::Function(float64_array, arg1, arg2, arg3, zone); |
| 85 |
| 86 decorator_ = new (zone) Decorator(this); |
| 87 graph_->AddDecorator(decorator_); |
| 88 } |
| 89 |
| 90 |
| 91 Typer::~Typer() { |
| 92 graph_->RemoveDecorator(decorator_); |
| 72 } | 93 } |
| 73 | 94 |
| 74 | 95 |
| 75 class Typer::Visitor : public NullNodeVisitor { | 96 class Typer::Visitor : public NullNodeVisitor { |
| 76 public: | 97 public: |
| 77 Visitor(Typer* typer, MaybeHandle<Context> context) | 98 explicit Visitor(Typer* typer) : typer_(typer) {} |
| 78 : typer_(typer), context_(context) {} | |
| 79 | 99 |
| 80 Bounds TypeNode(Node* node) { | 100 Bounds TypeNode(Node* node) { |
| 81 switch (node->opcode()) { | 101 switch (node->opcode()) { |
| 82 #define DECLARE_CASE(x) case IrOpcode::k##x: return Type##x(node); | 102 #define DECLARE_CASE(x) case IrOpcode::k##x: return Type##x(node); |
| 83 DECLARE_CASE(Start) | 103 DECLARE_CASE(Start) |
| 84 VALUE_OP_LIST(DECLARE_CASE) | 104 VALUE_OP_LIST(DECLARE_CASE) |
| 85 #undef DECLARE_CASE | 105 #undef DECLARE_CASE |
| 86 | 106 |
| 87 #define DECLARE_CASE(x) case IrOpcode::k##x: | 107 #define DECLARE_CASE(x) case IrOpcode::k##x: |
| 88 DECLARE_CASE(End) | 108 DECLARE_CASE(End) |
| 89 INNER_CONTROL_OP_LIST(DECLARE_CASE) | 109 INNER_CONTROL_OP_LIST(DECLARE_CASE) |
| 90 #undef DECLARE_CASE | 110 #undef DECLARE_CASE |
| 91 break; | 111 break; |
| 92 } | 112 } |
| 93 UNREACHABLE(); | 113 UNREACHABLE(); |
| 94 return Bounds(); | 114 return Bounds(); |
| 95 } | 115 } |
| 96 | 116 |
| 97 Type* TypeConstant(Handle<Object> value); | 117 Type* TypeConstant(Handle<Object> value); |
| 98 | 118 |
| 99 protected: | 119 protected: |
| 100 #define DECLARE_METHOD(x) inline Bounds Type##x(Node* node); | 120 #define DECLARE_METHOD(x) inline Bounds Type##x(Node* node); |
| 101 DECLARE_METHOD(Start) | 121 DECLARE_METHOD(Start) |
| 102 VALUE_OP_LIST(DECLARE_METHOD) | 122 VALUE_OP_LIST(DECLARE_METHOD) |
| 103 #undef DECLARE_METHOD | 123 #undef DECLARE_METHOD |
| 104 | 124 |
| 105 Bounds OperandType(Node* node, int i) { | 125 Bounds BoundsOrNone(Node* node) { |
| 106 return NodeProperties::GetBounds(NodeProperties::GetValueInput(node, i)); | 126 return NodeProperties::IsTyped(node) |
| 127 ? NodeProperties::GetBounds(node) : Bounds(Type::None(zone())); |
| 107 } | 128 } |
| 108 | 129 |
| 109 Type* ContextType(Node* node) { | 130 Bounds Operand(Node* node, int i) { |
| 110 Bounds result = | 131 Node* operand_node = NodeProperties::GetValueInput(node, i); |
| 111 NodeProperties::GetBounds(NodeProperties::GetContextInput(node)); | 132 return BoundsOrNone(operand_node); |
| 133 } |
| 134 |
| 135 Bounds ContextOperand(Node* node) { |
| 136 Bounds result = BoundsOrNone(NodeProperties::GetContextInput(node)); |
| 112 DCHECK(result.upper->Maybe(Type::Internal())); | 137 DCHECK(result.upper->Maybe(Type::Internal())); |
| 113 // TODO(rossberg): More precisely, instead of the above assertion, we should | 138 // TODO(rossberg): More precisely, instead of the above assertion, we should |
| 114 // back-propagate the constraint that it has to be a subtype of Internal. | 139 // back-propagate the constraint that it has to be a subtype of Internal. |
| 115 return result.upper; | 140 return result; |
| 116 } | 141 } |
| 117 | 142 |
| 118 Zone* zone() { return typer_->zone(); } | 143 Zone* zone() { return typer_->zone(); } |
| 119 Isolate* isolate() { return typer_->isolate(); } | 144 Isolate* isolate() { return typer_->isolate(); } |
| 120 MaybeHandle<Context> context() { return context_; } | 145 Graph* graph() { return typer_->graph(); } |
| 146 MaybeHandle<Context> context() { return typer_->context(); } |
| 121 | 147 |
| 122 private: | 148 private: |
| 123 Typer* typer_; | 149 Typer* typer_; |
| 124 MaybeHandle<Context> context_; | |
| 125 }; | 150 }; |
| 126 | 151 |
| 127 | 152 |
| 128 class Typer::RunVisitor : public Typer::Visitor { | 153 class Typer::RunVisitor : public Typer::Visitor { |
| 129 public: | 154 public: |
| 130 RunVisitor(Typer* typer, MaybeHandle<Context> context) | 155 explicit RunVisitor(Typer* typer) |
| 131 : Visitor(typer, context), | 156 : Visitor(typer), |
| 132 redo(NodeSet::key_compare(), NodeSet::allocator_type(typer->zone())) {} | 157 redo(NodeSet::key_compare(), NodeSet::allocator_type(typer->zone())) {} |
| 133 | 158 |
| 134 GenericGraphVisit::Control Post(Node* node) { | 159 GenericGraphVisit::Control Post(Node* node) { |
| 135 if (OperatorProperties::HasValueOutput(node->op())) { | 160 if (OperatorProperties::HasValueOutput(node->op()) && |
| 161 !NodeProperties::IsTyped(node)) { |
| 136 Bounds bounds = TypeNode(node); | 162 Bounds bounds = TypeNode(node); |
| 137 NodeProperties::SetBounds(node, bounds); | 163 NodeProperties::SetBounds(node, bounds); |
| 138 // Remember incompletely typed nodes for least fixpoint iteration. | 164 // Remember incompletely typed nodes for least fixpoint iteration. |
| 139 int arity = OperatorProperties::GetValueInputCount(node->op()); | 165 if (!NodeProperties::AllValueInputsAreTyped(node)) redo.insert(node); |
| 140 for (int i = 0; i < arity; ++i) { | |
| 141 // TODO(rossberg): change once IsTyped is available. | |
| 142 // if (!NodeProperties::IsTyped(NodeProperties::GetValueInput(node, i))) | |
| 143 if (OperandType(node, i).upper->Is(Type::None())) { | |
| 144 redo.insert(node); | |
| 145 break; | |
| 146 } | |
| 147 } | |
| 148 } | 166 } |
| 149 return GenericGraphVisit::CONTINUE; | 167 return GenericGraphVisit::CONTINUE; |
| 150 } | 168 } |
| 151 | 169 |
| 152 NodeSet redo; | 170 NodeSet redo; |
| 153 }; | 171 }; |
| 154 | 172 |
| 155 | 173 |
| 156 class Typer::NarrowVisitor : public Typer::Visitor { | 174 class Typer::NarrowVisitor : public Typer::Visitor { |
| 157 public: | 175 public: |
| 158 NarrowVisitor(Typer* typer, MaybeHandle<Context> context) | 176 explicit NarrowVisitor(Typer* typer) : Visitor(typer) {} |
| 159 : Visitor(typer, context) {} | |
| 160 | 177 |
| 161 GenericGraphVisit::Control Pre(Node* node) { | 178 GenericGraphVisit::Control Pre(Node* node) { |
| 162 if (OperatorProperties::HasValueOutput(node->op())) { | 179 if (OperatorProperties::HasValueOutput(node->op())) { |
| 163 Bounds previous = NodeProperties::GetBounds(node); | 180 Bounds previous = NodeProperties::GetBounds(node); |
| 164 Bounds bounds = TypeNode(node); | 181 Bounds bounds = TypeNode(node); |
| 165 NodeProperties::SetBounds(node, Bounds::Both(bounds, previous, zone())); | 182 NodeProperties::SetBounds(node, Bounds::Both(bounds, previous, zone())); |
| 166 DCHECK(bounds.Narrows(previous)); | 183 DCHECK(bounds.Narrows(previous)); |
| 167 // Stop when nothing changed (but allow re-entry in case it does later). | 184 // Stop when nothing changed (but allow re-entry in case it does later). |
| 168 return previous.Narrows(bounds) | 185 return previous.Narrows(bounds) |
| 169 ? GenericGraphVisit::DEFER : GenericGraphVisit::REENTER; | 186 ? GenericGraphVisit::DEFER : GenericGraphVisit::REENTER; |
| 170 } else { | 187 } else { |
| 171 return GenericGraphVisit::SKIP; | 188 return GenericGraphVisit::SKIP; |
| 172 } | 189 } |
| 173 } | 190 } |
| 174 | 191 |
| 175 GenericGraphVisit::Control Post(Node* node) { | 192 GenericGraphVisit::Control Post(Node* node) { |
| 176 return GenericGraphVisit::REENTER; | 193 return GenericGraphVisit::REENTER; |
| 177 } | 194 } |
| 178 }; | 195 }; |
| 179 | 196 |
| 180 | 197 |
| 181 class Typer::WidenVisitor : public Typer::Visitor { | 198 class Typer::WidenVisitor : public Typer::Visitor { |
| 182 public: | 199 public: |
| 183 WidenVisitor(Typer* typer, MaybeHandle<Context> context) | 200 explicit WidenVisitor(Typer* typer) : Visitor(typer) {} |
| 184 : Visitor(typer, context) {} | |
| 185 | 201 |
| 186 GenericGraphVisit::Control Pre(Node* node) { | 202 GenericGraphVisit::Control Pre(Node* node) { |
| 187 if (OperatorProperties::HasValueOutput(node->op())) { | 203 if (OperatorProperties::HasValueOutput(node->op())) { |
| 188 Bounds previous = NodeProperties::GetBounds(node); | 204 Bounds previous = BoundsOrNone(node); |
| 189 Bounds bounds = TypeNode(node); | 205 Bounds bounds = TypeNode(node); |
| 190 DCHECK(previous.lower->Is(bounds.lower)); | 206 DCHECK(previous.lower->Is(bounds.lower)); |
| 191 DCHECK(previous.upper->Is(bounds.upper)); | 207 DCHECK(previous.upper->Is(bounds.upper)); |
| 192 NodeProperties::SetBounds(node, bounds); // TODO(rossberg): Either? | 208 NodeProperties::SetBounds(node, bounds); |
| 193 // Stop when nothing changed (but allow re-entry in case it does later). | 209 // Stop when nothing changed (but allow re-entry in case it does later). |
| 194 return bounds.Narrows(previous) | 210 return bounds.Narrows(previous) |
| 195 ? GenericGraphVisit::DEFER : GenericGraphVisit::REENTER; | 211 ? GenericGraphVisit::DEFER : GenericGraphVisit::REENTER; |
| 196 } else { | 212 } else { |
| 197 return GenericGraphVisit::SKIP; | 213 return GenericGraphVisit::SKIP; |
| 198 } | 214 } |
| 199 } | 215 } |
| 200 | 216 |
| 201 GenericGraphVisit::Control Post(Node* node) { | 217 GenericGraphVisit::Control Post(Node* node) { |
| 202 return GenericGraphVisit::REENTER; | 218 return GenericGraphVisit::REENTER; |
| 203 } | 219 } |
| 204 }; | 220 }; |
| 205 | 221 |
| 206 | 222 |
| 207 void Typer::Run(Graph* graph, MaybeHandle<Context> context) { | 223 void Typer::Run() { |
| 208 RunVisitor typing(this, context); | 224 RunVisitor typing(this); |
| 209 graph->VisitNodeInputsFromEnd(&typing); | 225 graph_->VisitNodeInputsFromEnd(&typing); |
| 210 // Find least fixpoint. | 226 // Find least fixpoint. |
| 211 for (NodeSetIter i = typing.redo.begin(); i != typing.redo.end(); ++i) { | 227 WidenVisitor widen(this); |
| 212 Widen(graph, *i, context); | 228 for (NodeSetIter it = typing.redo.begin(); it != typing.redo.end(); ++it) { |
| 229 graph_->VisitNodeUsesFrom(*it, &widen); |
| 213 } | 230 } |
| 214 } | 231 } |
| 215 | 232 |
| 216 | 233 |
| 217 void Typer::Narrow(Graph* graph, Node* start, MaybeHandle<Context> context) { | 234 void Typer::Narrow(Node* start) { |
| 218 NarrowVisitor typing(this, context); | 235 NarrowVisitor typing(this); |
| 219 graph->VisitNodeUsesFrom(start, &typing); | 236 graph_->VisitNodeUsesFrom(start, &typing); |
| 220 } | 237 } |
| 221 | 238 |
| 222 | 239 |
| 223 void Typer::Widen(Graph* graph, Node* start, MaybeHandle<Context> context) { | 240 void Typer::Decorator::Decorate(Node* node) { |
| 224 WidenVisitor typing(this, context); | |
| 225 graph->VisitNodeUsesFrom(start, &typing); | |
| 226 } | |
| 227 | |
| 228 | |
| 229 void Typer::Init(Node* node) { | |
| 230 if (OperatorProperties::HasValueOutput(node->op())) { | 241 if (OperatorProperties::HasValueOutput(node->op())) { |
| 231 Visitor typing(this, MaybeHandle<Context>()); | 242 // Only eagerly type-decorate nodes with known input types. |
| 232 Bounds bounds = typing.TypeNode(node); | 243 // Other cases will generally require a proper fixpoint iteration with Run. |
| 233 NodeProperties::SetBounds(node, bounds); | 244 bool is_typed = NodeProperties::IsTyped(node); |
| 245 if (is_typed || NodeProperties::AllValueInputsAreTyped(node)) { |
| 246 Visitor typing(typer_); |
| 247 Bounds bounds = typing.TypeNode(node); |
| 248 if (is_typed) { |
| 249 bounds = |
| 250 Bounds::Both(bounds, NodeProperties::GetBounds(node), typer_->zone()); |
| 251 } |
| 252 NodeProperties::SetBounds(node, bounds); |
| 253 } |
| 234 } | 254 } |
| 235 } | 255 } |
| 236 | 256 |
| 237 | 257 |
| 238 // ----------------------------------------------------------------------------- | 258 // ----------------------------------------------------------------------------- |
| 239 | 259 |
| 240 | 260 |
| 241 // Control operators. | 261 // Control operators. |
| 242 | 262 |
| 243 Bounds Typer::Visitor::TypeStart(Node* node) { | 263 Bounds Typer::Visitor::TypeStart(Node* node) { |
| 244 return Bounds(Type::Internal(zone())); | 264 return Bounds(Type::None(zone()), Type::Internal(zone())); |
| 245 } | 265 } |
| 246 | 266 |
| 247 | 267 |
| 248 // Common operators. | 268 // Common operators. |
| 249 | 269 |
| 250 Bounds Typer::Visitor::TypeParameter(Node* node) { | 270 Bounds Typer::Visitor::TypeParameter(Node* node) { |
| 251 return Bounds::Unbounded(zone()); | 271 return Bounds::Unbounded(zone()); |
| 252 } | 272 } |
| 253 | 273 |
| 254 | 274 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 282 return Bounds(Type::Of(OpParameter<double>(node), zone())); | 302 return Bounds(Type::Of(OpParameter<double>(node), zone())); |
| 283 } | 303 } |
| 284 | 304 |
| 285 | 305 |
| 286 Bounds Typer::Visitor::TypeHeapConstant(Node* node) { | 306 Bounds Typer::Visitor::TypeHeapConstant(Node* node) { |
| 287 return Bounds(TypeConstant(OpParameter<Unique<Object> >(node).handle())); | 307 return Bounds(TypeConstant(OpParameter<Unique<Object> >(node).handle())); |
| 288 } | 308 } |
| 289 | 309 |
| 290 | 310 |
| 291 Bounds Typer::Visitor::TypeExternalConstant(Node* node) { | 311 Bounds Typer::Visitor::TypeExternalConstant(Node* node) { |
| 292 return Bounds(Type::Internal(zone())); | 312 return Bounds(Type::None(zone()), Type::Internal(zone())); |
| 293 } | 313 } |
| 294 | 314 |
| 295 | 315 |
| 296 Bounds Typer::Visitor::TypePhi(Node* node) { | 316 Bounds Typer::Visitor::TypePhi(Node* node) { |
| 297 int arity = OperatorProperties::GetValueInputCount(node->op()); | 317 int arity = OperatorProperties::GetValueInputCount(node->op()); |
| 298 Bounds bounds = OperandType(node, 0); | 318 Bounds bounds = Operand(node, 0); |
| 299 for (int i = 1; i < arity; ++i) { | 319 for (int i = 1; i < arity; ++i) { |
| 300 bounds = Bounds::Either(bounds, OperandType(node, i), zone()); | 320 bounds = Bounds::Either(bounds, Operand(node, i), zone()); |
| 301 } | 321 } |
| 302 return bounds; | 322 return bounds; |
| 303 } | 323 } |
| 304 | 324 |
| 305 | 325 |
| 306 Bounds Typer::Visitor::TypeEffectPhi(Node* node) { | 326 Bounds Typer::Visitor::TypeEffectPhi(Node* node) { |
| 307 UNREACHABLE(); | 327 UNREACHABLE(); |
| 308 return Bounds(); | 328 return Bounds(); |
| 309 } | 329 } |
| 310 | 330 |
| 311 | 331 |
| 312 Bounds Typer::Visitor::TypeValueEffect(Node* node) { | 332 Bounds Typer::Visitor::TypeValueEffect(Node* node) { |
| 313 UNREACHABLE(); | 333 UNREACHABLE(); |
| 314 return Bounds(); | 334 return Bounds(); |
| 315 } | 335 } |
| 316 | 336 |
| 317 | 337 |
| 318 Bounds Typer::Visitor::TypeFinish(Node* node) { | 338 Bounds Typer::Visitor::TypeFinish(Node* node) { |
| 319 return OperandType(node, 0); | 339 return Operand(node, 0); |
| 320 } | 340 } |
| 321 | 341 |
| 322 | 342 |
| 323 Bounds Typer::Visitor::TypeFrameState(Node* node) { | 343 Bounds Typer::Visitor::TypeFrameState(Node* node) { |
| 324 // TODO(rossberg): Ideally FrameState wouldn't have a value output. | 344 // TODO(rossberg): Ideally FrameState wouldn't have a value output. |
| 325 return Bounds(Type::Internal(zone())); | 345 return Bounds(Type::None(zone()), Type::Internal(zone())); |
| 326 } | 346 } |
| 327 | 347 |
| 328 | 348 |
| 329 Bounds Typer::Visitor::TypeStateValues(Node* node) { | 349 Bounds Typer::Visitor::TypeStateValues(Node* node) { |
| 330 return Bounds(Type::Internal(zone())); | 350 return Bounds(Type::None(zone()), Type::Internal(zone())); |
| 331 } | 351 } |
| 332 | 352 |
| 333 | 353 |
| 334 Bounds Typer::Visitor::TypeCall(Node* node) { | 354 Bounds Typer::Visitor::TypeCall(Node* node) { |
| 335 return Bounds::Unbounded(zone()); | 355 return Bounds::Unbounded(zone()); |
| 336 } | 356 } |
| 337 | 357 |
| 338 | 358 |
| 339 Bounds Typer::Visitor::TypeProjection(Node* node) { | 359 Bounds Typer::Visitor::TypeProjection(Node* node) { |
| 340 // TODO(titzer): use the output type of the input to determine the bounds. | 360 // TODO(titzer): use the output type of the input to determine the bounds. |
| 341 return Bounds::Unbounded(zone()); | 361 return Bounds::Unbounded(zone()); |
| 342 } | 362 } |
| 343 | 363 |
| 344 | 364 |
| 345 // JS comparison operators. | 365 // JS comparison operators. |
| 346 | 366 |
| 347 #define DEFINE_METHOD(x) \ | 367 #define DEFINE_METHOD(x) \ |
| 348 Bounds Typer::Visitor::Type##x(Node* node) { \ | 368 Bounds Typer::Visitor::Type##x(Node* node) { \ |
| 349 return Bounds(Type::Boolean(zone())); \ | 369 return Bounds(Type::None(zone()), Type::Boolean(zone())); \ |
| 350 } | 370 } |
| 351 JS_COMPARE_BINOP_LIST(DEFINE_METHOD) | 371 JS_COMPARE_BINOP_LIST(DEFINE_METHOD) |
| 352 #undef DEFINE_METHOD | 372 #undef DEFINE_METHOD |
| 353 | 373 |
| 354 | 374 |
| 355 // JS bitwise operators. | 375 // JS bitwise operators. |
| 356 | 376 |
| 357 Bounds Typer::Visitor::TypeJSBitwiseOr(Node* node) { | 377 Bounds Typer::Visitor::TypeJSBitwiseOr(Node* node) { |
| 358 Bounds left = OperandType(node, 0); | 378 Bounds left = Operand(node, 0); |
| 359 Bounds right = OperandType(node, 1); | 379 Bounds right = Operand(node, 1); |
| 360 Type* upper = Type::Union(left.upper, right.upper, zone()); | 380 Type* upper = Type::Union(left.upper, right.upper, zone()); |
| 361 if (!upper->Is(Type::Signed32())) upper = Type::Signed32(zone()); | 381 if (!upper->Is(Type::Signed32())) upper = Type::Signed32(zone()); |
| 362 Type* lower = Type::Intersect(Type::SignedSmall(zone()), upper, zone()); | 382 Type* lower = Type::Intersect(Type::SignedSmall(zone()), upper, zone()); |
| 363 return Bounds(lower, upper); | 383 return Bounds(lower, upper); |
| 364 } | 384 } |
| 365 | 385 |
| 366 | 386 |
| 367 Bounds Typer::Visitor::TypeJSBitwiseAnd(Node* node) { | 387 Bounds Typer::Visitor::TypeJSBitwiseAnd(Node* node) { |
| 368 Bounds left = OperandType(node, 0); | 388 Bounds left = Operand(node, 0); |
| 369 Bounds right = OperandType(node, 1); | 389 Bounds right = Operand(node, 1); |
| 370 Type* upper = Type::Union(left.upper, right.upper, zone()); | 390 Type* upper = Type::Union(left.upper, right.upper, zone()); |
| 371 if (!upper->Is(Type::Signed32())) upper = Type::Signed32(zone()); | 391 if (!upper->Is(Type::Signed32())) upper = Type::Signed32(zone()); |
| 372 Type* lower = Type::Intersect(Type::SignedSmall(zone()), upper, zone()); | 392 Type* lower = Type::Intersect(Type::SignedSmall(zone()), upper, zone()); |
| 373 return Bounds(lower, upper); | 393 return Bounds(lower, upper); |
| 374 } | 394 } |
| 375 | 395 |
| 376 | 396 |
| 377 Bounds Typer::Visitor::TypeJSBitwiseXor(Node* node) { | 397 Bounds Typer::Visitor::TypeJSBitwiseXor(Node* node) { |
| 378 return Bounds(Type::SignedSmall(zone()), Type::Signed32(zone())); | 398 return Bounds(Type::None(zone()), Type::Signed32(zone())); |
| 379 } | 399 } |
| 380 | 400 |
| 381 | 401 |
| 382 Bounds Typer::Visitor::TypeJSShiftLeft(Node* node) { | 402 Bounds Typer::Visitor::TypeJSShiftLeft(Node* node) { |
| 383 return Bounds(Type::SignedSmall(zone()), Type::Signed32(zone())); | 403 return Bounds(Type::None(zone()), Type::Signed32(zone())); |
| 384 } | 404 } |
| 385 | 405 |
| 386 | 406 |
| 387 Bounds Typer::Visitor::TypeJSShiftRight(Node* node) { | 407 Bounds Typer::Visitor::TypeJSShiftRight(Node* node) { |
| 388 return Bounds(Type::SignedSmall(zone()), Type::Signed32(zone())); | 408 return Bounds(Type::None(zone()), Type::Signed32(zone())); |
| 389 } | 409 } |
| 390 | 410 |
| 391 | 411 |
| 392 Bounds Typer::Visitor::TypeJSShiftRightLogical(Node* node) { | 412 Bounds Typer::Visitor::TypeJSShiftRightLogical(Node* node) { |
| 393 return Bounds(Type::UnsignedSmall(zone()), Type::Unsigned32(zone())); | 413 return Bounds(Type::None(zone()), Type::Unsigned32(zone())); |
| 394 } | 414 } |
| 395 | 415 |
| 396 | 416 |
| 397 // JS arithmetic operators. | 417 // JS arithmetic operators. |
| 398 | 418 |
| 399 Bounds Typer::Visitor::TypeJSAdd(Node* node) { | 419 Bounds Typer::Visitor::TypeJSAdd(Node* node) { |
| 400 Bounds left = OperandType(node, 0); | 420 Bounds left = Operand(node, 0); |
| 401 Bounds right = OperandType(node, 1); | 421 Bounds right = Operand(node, 1); |
| 402 Type* lower = | 422 Type* lower = |
| 403 left.lower->Is(Type::None()) || right.lower->Is(Type::None()) ? | 423 left.lower->Is(Type::None()) || right.lower->Is(Type::None()) ? |
| 404 Type::None(zone()) : | 424 Type::None(zone()) : |
| 405 left.lower->Is(Type::Number()) && right.lower->Is(Type::Number()) ? | 425 left.lower->Is(Type::Number()) && right.lower->Is(Type::Number()) ? |
| 406 Type::SignedSmall(zone()) : | 426 Type::SignedSmall(zone()) : |
| 407 left.lower->Is(Type::String()) || right.lower->Is(Type::String()) ? | 427 left.lower->Is(Type::String()) || right.lower->Is(Type::String()) ? |
| 408 Type::String(zone()) : Type::None(zone()); | 428 Type::String(zone()) : Type::None(zone()); |
| 409 Type* upper = | 429 Type* upper = |
| 410 left.upper->Is(Type::None()) && right.upper->Is(Type::None()) ? | 430 left.upper->Is(Type::None()) && right.upper->Is(Type::None()) ? |
| 411 Type::None(zone()) : | 431 Type::None(zone()) : |
| 412 left.upper->Is(Type::Number()) && right.upper->Is(Type::Number()) ? | 432 left.upper->Is(Type::Number()) && right.upper->Is(Type::Number()) ? |
| 413 Type::Number(zone()) : | 433 Type::Number(zone()) : |
| 414 left.upper->Is(Type::String()) || right.upper->Is(Type::String()) ? | 434 left.upper->Is(Type::String()) || right.upper->Is(Type::String()) ? |
| 415 Type::String(zone()) : Type::NumberOrString(zone()); | 435 Type::String(zone()) : Type::NumberOrString(zone()); |
| 416 return Bounds(lower, upper); | 436 return Bounds(lower, upper); |
| 417 } | 437 } |
| 418 | 438 |
| 419 | 439 |
| 420 Bounds Typer::Visitor::TypeJSSubtract(Node* node) { | 440 Bounds Typer::Visitor::TypeJSSubtract(Node* node) { |
| 421 return Bounds(Type::SignedSmall(zone()), Type::Number(zone())); | 441 return Bounds(Type::None(zone()), Type::Number(zone())); |
| 422 } | 442 } |
| 423 | 443 |
| 424 | 444 |
| 425 Bounds Typer::Visitor::TypeJSMultiply(Node* node) { | 445 Bounds Typer::Visitor::TypeJSMultiply(Node* node) { |
| 426 return Bounds(Type::SignedSmall(zone()), Type::Number(zone())); | 446 return Bounds(Type::None(zone()), Type::Number(zone())); |
| 427 } | 447 } |
| 428 | 448 |
| 429 | 449 |
| 430 Bounds Typer::Visitor::TypeJSDivide(Node* node) { | 450 Bounds Typer::Visitor::TypeJSDivide(Node* node) { |
| 431 return Bounds(Type::SignedSmall(zone()), Type::Number(zone())); | 451 return Bounds(Type::None(zone()), Type::Number(zone())); |
| 432 } | 452 } |
| 433 | 453 |
| 434 | 454 |
| 435 Bounds Typer::Visitor::TypeJSModulus(Node* node) { | 455 Bounds Typer::Visitor::TypeJSModulus(Node* node) { |
| 436 return Bounds(Type::SignedSmall(zone()), Type::Number(zone())); | 456 return Bounds(Type::None(zone()), Type::Number(zone())); |
| 437 } | 457 } |
| 438 | 458 |
| 439 | 459 |
| 440 // JS unary operators. | 460 // JS unary operators. |
| 441 | 461 |
| 442 Bounds Typer::Visitor::TypeJSUnaryNot(Node* node) { | 462 Bounds Typer::Visitor::TypeJSUnaryNot(Node* node) { |
| 443 return Bounds(Type::Boolean(zone())); | 463 return Bounds(Type::None(zone()), Type::Boolean(zone())); |
| 444 } | 464 } |
| 445 | 465 |
| 446 | 466 |
| 447 Bounds Typer::Visitor::TypeJSTypeOf(Node* node) { | 467 Bounds Typer::Visitor::TypeJSTypeOf(Node* node) { |
| 448 return Bounds(Type::InternalizedString(zone())); | 468 return Bounds(Type::None(zone()), Type::InternalizedString(zone())); |
| 449 } | 469 } |
| 450 | 470 |
| 451 | 471 |
| 452 // JS conversion operators. | 472 // JS conversion operators. |
| 453 | 473 |
| 454 Bounds Typer::Visitor::TypeJSToBoolean(Node* node) { | 474 Bounds Typer::Visitor::TypeJSToBoolean(Node* node) { |
| 455 return Bounds(Type::Boolean(zone())); | 475 return Bounds(Type::None(zone()), Type::Boolean(zone())); |
| 456 } | 476 } |
| 457 | 477 |
| 458 | 478 |
| 459 Bounds Typer::Visitor::TypeJSToNumber(Node* node) { | 479 Bounds Typer::Visitor::TypeJSToNumber(Node* node) { |
| 460 return Bounds(Type::SignedSmall(zone()), Type::Number(zone())); | 480 return Bounds(Type::None(zone()), Type::Number(zone())); |
| 461 } | 481 } |
| 462 | 482 |
| 463 | 483 |
| 464 Bounds Typer::Visitor::TypeJSToString(Node* node) { | 484 Bounds Typer::Visitor::TypeJSToString(Node* node) { |
| 465 return Bounds(Type::None(zone()), Type::String(zone())); | 485 return Bounds(Type::None(zone()), Type::String(zone())); |
| 466 } | 486 } |
| 467 | 487 |
| 468 | 488 |
| 469 Bounds Typer::Visitor::TypeJSToName(Node* node) { | 489 Bounds Typer::Visitor::TypeJSToName(Node* node) { |
| 470 return Bounds(Type::None(zone()), Type::Name(zone())); | 490 return Bounds(Type::None(zone()), Type::Name(zone())); |
| 471 } | 491 } |
| 472 | 492 |
| 473 | 493 |
| 474 Bounds Typer::Visitor::TypeJSToObject(Node* node) { | 494 Bounds Typer::Visitor::TypeJSToObject(Node* node) { |
| 475 return Bounds(Type::None(zone()), Type::Receiver(zone())); | 495 return Bounds(Type::None(zone()), Type::Receiver(zone())); |
| 476 } | 496 } |
| 477 | 497 |
| 478 | 498 |
| 479 // JS object operators. | 499 // JS object operators. |
| 480 | 500 |
| 481 Bounds Typer::Visitor::TypeJSCreate(Node* node) { | 501 Bounds Typer::Visitor::TypeJSCreate(Node* node) { |
| 482 return Bounds(Type::None(zone()), Type::Object(zone())); | 502 return Bounds(Type::None(zone()), Type::Object(zone())); |
| 483 } | 503 } |
| 484 | 504 |
| 485 | 505 |
| 486 Bounds Typer::Visitor::TypeJSLoadProperty(Node* node) { | 506 Bounds Typer::Visitor::TypeJSLoadProperty(Node* node) { |
| 487 Bounds object = OperandType(node, 0); | 507 Bounds object = Operand(node, 0); |
| 488 Bounds name = OperandType(node, 1); | 508 Bounds name = Operand(node, 1); |
| 489 Bounds result = Bounds::Unbounded(zone()); | 509 Bounds result = Bounds::Unbounded(zone()); |
| 490 // TODO(rossberg): Use range types and sized array types to filter undefined. | 510 // TODO(rossberg): Use range types and sized array types to filter undefined. |
| 491 if (object.lower->IsArray() && name.lower->Is(Type::Integral32())) { | 511 if (object.lower->IsArray() && name.lower->Is(Type::Integral32())) { |
| 492 result.lower = Type::Union( | 512 result.lower = Type::Union( |
| 493 object.lower->AsArray()->Element(), Type::Undefined(zone()), zone()); | 513 object.lower->AsArray()->Element(), Type::Undefined(zone()), zone()); |
| 494 } | 514 } |
| 495 if (object.upper->IsArray() && name.upper->Is(Type::Integral32())) { | 515 if (object.upper->IsArray() && name.upper->Is(Type::Integral32())) { |
| 496 result.upper = Type::Union( | 516 result.upper = Type::Union( |
| 497 object.upper->AsArray()->Element(), Type::Undefined(zone()), zone()); | 517 object.upper->AsArray()->Element(), Type::Undefined(zone()), zone()); |
| 498 } | 518 } |
| (...skipping 12 matching lines...) Expand all Loading... |
| 511 } | 531 } |
| 512 | 532 |
| 513 | 533 |
| 514 Bounds Typer::Visitor::TypeJSStoreNamed(Node* node) { | 534 Bounds Typer::Visitor::TypeJSStoreNamed(Node* node) { |
| 515 UNREACHABLE(); | 535 UNREACHABLE(); |
| 516 return Bounds(); | 536 return Bounds(); |
| 517 } | 537 } |
| 518 | 538 |
| 519 | 539 |
| 520 Bounds Typer::Visitor::TypeJSDeleteProperty(Node* node) { | 540 Bounds Typer::Visitor::TypeJSDeleteProperty(Node* node) { |
| 521 return Bounds(Type::Boolean(zone())); | 541 return Bounds(Type::None(zone()), Type::Boolean(zone())); |
| 522 } | 542 } |
| 523 | 543 |
| 524 | 544 |
| 525 Bounds Typer::Visitor::TypeJSHasProperty(Node* node) { | 545 Bounds Typer::Visitor::TypeJSHasProperty(Node* node) { |
| 526 return Bounds(Type::Boolean(zone())); | 546 return Bounds(Type::None(zone()), Type::Boolean(zone())); |
| 527 } | 547 } |
| 528 | 548 |
| 529 | 549 |
| 530 Bounds Typer::Visitor::TypeJSInstanceOf(Node* node) { | 550 Bounds Typer::Visitor::TypeJSInstanceOf(Node* node) { |
| 531 return Bounds(Type::Boolean(zone())); | 551 return Bounds(Type::None(zone()), Type::Boolean(zone())); |
| 532 } | 552 } |
| 533 | 553 |
| 534 | 554 |
| 535 // JS context operators. | 555 // JS context operators. |
| 536 | 556 |
| 537 Bounds Typer::Visitor::TypeJSLoadContext(Node* node) { | 557 Bounds Typer::Visitor::TypeJSLoadContext(Node* node) { |
| 538 Bounds outer = OperandType(node, 0); | 558 Bounds outer = Operand(node, 0); |
| 539 DCHECK(outer.upper->Maybe(Type::Internal())); | 559 DCHECK(outer.upper->Maybe(Type::Internal())); |
| 540 // TODO(rossberg): More precisely, instead of the above assertion, we should | 560 // TODO(rossberg): More precisely, instead of the above assertion, we should |
| 541 // back-propagate the constraint that it has to be a subtype of Internal. | 561 // back-propagate the constraint that it has to be a subtype of Internal. |
| 542 | 562 |
| 543 ContextAccess access = OpParameter<ContextAccess>(node); | 563 ContextAccess access = OpParameter<ContextAccess>(node); |
| 544 Type* context_type = outer.upper; | 564 Type* context_type = outer.upper; |
| 545 MaybeHandle<Context> context; | 565 MaybeHandle<Context> context; |
| 546 if (context_type->IsConstant()) { | 566 if (context_type->IsConstant()) { |
| 547 context = Handle<Context>::cast(context_type->AsConstant()->Value()); | 567 context = Handle<Context>::cast(context_type->AsConstant()->Value()); |
| 548 } | 568 } |
| (...skipping 24 matching lines...) Expand all Loading... |
| 573 } | 593 } |
| 574 | 594 |
| 575 | 595 |
| 576 Bounds Typer::Visitor::TypeJSStoreContext(Node* node) { | 596 Bounds Typer::Visitor::TypeJSStoreContext(Node* node) { |
| 577 UNREACHABLE(); | 597 UNREACHABLE(); |
| 578 return Bounds(); | 598 return Bounds(); |
| 579 } | 599 } |
| 580 | 600 |
| 581 | 601 |
| 582 Bounds Typer::Visitor::TypeJSCreateFunctionContext(Node* node) { | 602 Bounds Typer::Visitor::TypeJSCreateFunctionContext(Node* node) { |
| 583 Type* outer = ContextType(node); | 603 Bounds outer = ContextOperand(node); |
| 584 return Bounds(Type::Context(outer, zone())); | 604 return Bounds(Type::Context(outer.upper, zone())); |
| 585 } | 605 } |
| 586 | 606 |
| 587 | 607 |
| 588 Bounds Typer::Visitor::TypeJSCreateCatchContext(Node* node) { | 608 Bounds Typer::Visitor::TypeJSCreateCatchContext(Node* node) { |
| 589 Type* outer = ContextType(node); | 609 Bounds outer = ContextOperand(node); |
| 590 return Bounds(Type::Context(outer, zone())); | 610 return Bounds(Type::Context(outer.upper, zone())); |
| 591 } | 611 } |
| 592 | 612 |
| 593 | 613 |
| 594 Bounds Typer::Visitor::TypeJSCreateWithContext(Node* node) { | 614 Bounds Typer::Visitor::TypeJSCreateWithContext(Node* node) { |
| 595 Type* outer = ContextType(node); | 615 Bounds outer = ContextOperand(node); |
| 596 return Bounds(Type::Context(outer, zone())); | 616 return Bounds(Type::Context(outer.upper, zone())); |
| 597 } | 617 } |
| 598 | 618 |
| 599 | 619 |
| 600 Bounds Typer::Visitor::TypeJSCreateBlockContext(Node* node) { | 620 Bounds Typer::Visitor::TypeJSCreateBlockContext(Node* node) { |
| 601 Type* outer = ContextType(node); | 621 Bounds outer = ContextOperand(node); |
| 602 return Bounds(Type::Context(outer, zone())); | 622 return Bounds(Type::Context(outer.upper, zone())); |
| 603 } | 623 } |
| 604 | 624 |
| 605 | 625 |
| 606 Bounds Typer::Visitor::TypeJSCreateModuleContext(Node* node) { | 626 Bounds Typer::Visitor::TypeJSCreateModuleContext(Node* node) { |
| 607 // TODO(rossberg): this is probably incorrect | 627 // TODO(rossberg): this is probably incorrect |
| 608 Type* outer = ContextType(node); | 628 Bounds outer = ContextOperand(node); |
| 609 return Bounds(Type::Context(outer, zone())); | 629 return Bounds(Type::Context(outer.upper, zone())); |
| 610 } | 630 } |
| 611 | 631 |
| 612 | 632 |
| 613 Bounds Typer::Visitor::TypeJSCreateGlobalContext(Node* node) { | 633 Bounds Typer::Visitor::TypeJSCreateGlobalContext(Node* node) { |
| 614 Type* outer = ContextType(node); | 634 Bounds outer = ContextOperand(node); |
| 615 return Bounds(Type::Context(outer, zone())); | 635 return Bounds(Type::Context(outer.upper, zone())); |
| 616 } | 636 } |
| 617 | 637 |
| 618 | 638 |
| 619 // JS other operators. | 639 // JS other operators. |
| 620 | 640 |
| 621 Bounds Typer::Visitor::TypeJSYield(Node* node) { | 641 Bounds Typer::Visitor::TypeJSYield(Node* node) { |
| 622 return Bounds::Unbounded(zone()); | 642 return Bounds::Unbounded(zone()); |
| 623 } | 643 } |
| 624 | 644 |
| 625 | 645 |
| 626 Bounds Typer::Visitor::TypeJSCallConstruct(Node* node) { | 646 Bounds Typer::Visitor::TypeJSCallConstruct(Node* node) { |
| 627 return Bounds(Type::None(zone()), Type::Receiver(zone())); | 647 return Bounds(Type::None(zone()), Type::Receiver(zone())); |
| 628 } | 648 } |
| 629 | 649 |
| 630 | 650 |
| 631 Bounds Typer::Visitor::TypeJSCallFunction(Node* node) { | 651 Bounds Typer::Visitor::TypeJSCallFunction(Node* node) { |
| 632 Bounds fun = OperandType(node, 0); | 652 Bounds fun = Operand(node, 0); |
| 633 Type* lower = fun.lower->IsFunction() | 653 Type* lower = fun.lower->IsFunction() |
| 634 ? fun.lower->AsFunction()->Result() : Type::None(zone()); | 654 ? fun.lower->AsFunction()->Result() : Type::None(zone()); |
| 635 Type* upper = fun.upper->IsFunction() | 655 Type* upper = fun.upper->IsFunction() |
| 636 ? fun.upper->AsFunction()->Result() : Type::Any(zone()); | 656 ? fun.upper->AsFunction()->Result() : Type::Any(zone()); |
| 637 return Bounds(lower, upper); | 657 return Bounds(lower, upper); |
| 638 } | 658 } |
| 639 | 659 |
| 640 | 660 |
| 641 Bounds Typer::Visitor::TypeJSCallRuntime(Node* node) { | 661 Bounds Typer::Visitor::TypeJSCallRuntime(Node* node) { |
| 642 return Bounds::Unbounded(zone()); | 662 return Bounds::Unbounded(zone()); |
| 643 } | 663 } |
| 644 | 664 |
| 645 | 665 |
| 646 Bounds Typer::Visitor::TypeJSDebugger(Node* node) { | 666 Bounds Typer::Visitor::TypeJSDebugger(Node* node) { |
| 647 return Bounds::Unbounded(zone()); | 667 return Bounds::Unbounded(zone()); |
| 648 } | 668 } |
| 649 | 669 |
| 650 | 670 |
| 651 // Simplified operators. | 671 // Simplified operators. |
| 652 | 672 |
| 653 Bounds Typer::Visitor::TypeBooleanNot(Node* node) { | 673 Bounds Typer::Visitor::TypeBooleanNot(Node* node) { |
| 654 return Bounds(Type::Boolean(zone())); | 674 return Bounds(Type::None(zone()), Type::Boolean(zone())); |
| 655 } | 675 } |
| 656 | 676 |
| 657 | 677 |
| 658 Bounds Typer::Visitor::TypeBooleanToNumber(Node* node) { | 678 Bounds Typer::Visitor::TypeBooleanToNumber(Node* node) { |
| 659 return Bounds(Type::Number(zone())); | 679 return Bounds(Type::None(zone()), Type::Number(zone())); |
| 660 } | 680 } |
| 661 | 681 |
| 662 | 682 |
| 663 Bounds Typer::Visitor::TypeNumberEqual(Node* node) { | 683 Bounds Typer::Visitor::TypeNumberEqual(Node* node) { |
| 664 return Bounds(Type::Boolean(zone())); | 684 return Bounds(Type::None(zone()), Type::Boolean(zone())); |
| 665 } | 685 } |
| 666 | 686 |
| 667 | 687 |
| 668 Bounds Typer::Visitor::TypeNumberLessThan(Node* node) { | 688 Bounds Typer::Visitor::TypeNumberLessThan(Node* node) { |
| 669 return Bounds(Type::Boolean(zone())); | 689 return Bounds(Type::None(zone()), Type::Boolean(zone())); |
| 670 } | 690 } |
| 671 | 691 |
| 672 | 692 |
| 673 Bounds Typer::Visitor::TypeNumberLessThanOrEqual(Node* node) { | 693 Bounds Typer::Visitor::TypeNumberLessThanOrEqual(Node* node) { |
| 674 return Bounds(Type::Boolean(zone())); | 694 return Bounds(Type::None(zone()), Type::Boolean(zone())); |
| 675 } | 695 } |
| 676 | 696 |
| 677 | 697 |
| 678 Bounds Typer::Visitor::TypeNumberAdd(Node* node) { | 698 Bounds Typer::Visitor::TypeNumberAdd(Node* node) { |
| 679 return Bounds(Type::Number(zone())); | 699 return Bounds(Type::None(zone()), Type::Number(zone())); |
| 680 } | 700 } |
| 681 | 701 |
| 682 | 702 |
| 683 Bounds Typer::Visitor::TypeNumberSubtract(Node* node) { | 703 Bounds Typer::Visitor::TypeNumberSubtract(Node* node) { |
| 684 return Bounds(Type::Number(zone())); | 704 return Bounds(Type::None(zone()), Type::Number(zone())); |
| 685 } | 705 } |
| 686 | 706 |
| 687 | 707 |
| 688 Bounds Typer::Visitor::TypeNumberMultiply(Node* node) { | 708 Bounds Typer::Visitor::TypeNumberMultiply(Node* node) { |
| 689 return Bounds(Type::Number(zone())); | 709 return Bounds(Type::None(zone()), Type::Number(zone())); |
| 690 } | 710 } |
| 691 | 711 |
| 692 | 712 |
| 693 Bounds Typer::Visitor::TypeNumberDivide(Node* node) { | 713 Bounds Typer::Visitor::TypeNumberDivide(Node* node) { |
| 694 return Bounds(Type::Number(zone())); | 714 return Bounds(Type::None(zone()), Type::Number(zone())); |
| 695 } | 715 } |
| 696 | 716 |
| 697 | 717 |
| 698 Bounds Typer::Visitor::TypeNumberModulus(Node* node) { | 718 Bounds Typer::Visitor::TypeNumberModulus(Node* node) { |
| 699 return Bounds(Type::Number(zone())); | 719 return Bounds(Type::None(zone()), Type::Number(zone())); |
| 700 } | 720 } |
| 701 | 721 |
| 702 | 722 |
| 703 Bounds Typer::Visitor::TypeNumberToInt32(Node* node) { | 723 Bounds Typer::Visitor::TypeNumberToInt32(Node* node) { |
| 704 Bounds arg = OperandType(node, 0); | 724 Bounds arg = Operand(node, 0); |
| 705 Type* s32 = Type::Signed32(zone()); | 725 Type* s32 = Type::Signed32(zone()); |
| 706 Type* lower = arg.lower->Is(s32) ? arg.lower : s32; | 726 Type* lower = arg.lower->Is(s32) ? arg.lower : s32; |
| 707 Type* upper = arg.upper->Is(s32) ? arg.upper : s32; | 727 Type* upper = arg.upper->Is(s32) ? arg.upper : s32; |
| 708 return Bounds(lower, upper); | 728 return Bounds(lower, upper); |
| 709 } | 729 } |
| 710 | 730 |
| 711 | 731 |
| 712 Bounds Typer::Visitor::TypeNumberToUint32(Node* node) { | 732 Bounds Typer::Visitor::TypeNumberToUint32(Node* node) { |
| 713 Bounds arg = OperandType(node, 0); | 733 Bounds arg = Operand(node, 0); |
| 714 Type* u32 = Type::Unsigned32(zone()); | 734 Type* u32 = Type::Unsigned32(zone()); |
| 715 Type* lower = arg.lower->Is(u32) ? arg.lower : u32; | 735 Type* lower = arg.lower->Is(u32) ? arg.lower : u32; |
| 716 Type* upper = arg.upper->Is(u32) ? arg.upper : u32; | 736 Type* upper = arg.upper->Is(u32) ? arg.upper : u32; |
| 717 return Bounds(lower, upper); | 737 return Bounds(lower, upper); |
| 718 } | 738 } |
| 719 | 739 |
| 720 | 740 |
| 721 Bounds Typer::Visitor::TypeReferenceEqual(Node* node) { | 741 Bounds Typer::Visitor::TypeReferenceEqual(Node* node) { |
| 722 return Bounds(Type::Boolean(zone())); | 742 return Bounds(Type::None(zone()), Type::Boolean(zone())); |
| 723 } | 743 } |
| 724 | 744 |
| 725 | 745 |
| 726 Bounds Typer::Visitor::TypeStringEqual(Node* node) { | 746 Bounds Typer::Visitor::TypeStringEqual(Node* node) { |
| 727 return Bounds(Type::Boolean(zone())); | 747 return Bounds(Type::None(zone()), Type::Boolean(zone())); |
| 728 } | 748 } |
| 729 | 749 |
| 730 | 750 |
| 731 Bounds Typer::Visitor::TypeStringLessThan(Node* node) { | 751 Bounds Typer::Visitor::TypeStringLessThan(Node* node) { |
| 732 return Bounds(Type::Boolean(zone())); | 752 return Bounds(Type::None(zone()), Type::Boolean(zone())); |
| 733 } | 753 } |
| 734 | 754 |
| 735 | 755 |
| 736 Bounds Typer::Visitor::TypeStringLessThanOrEqual(Node* node) { | 756 Bounds Typer::Visitor::TypeStringLessThanOrEqual(Node* node) { |
| 737 return Bounds(Type::Boolean(zone())); | 757 return Bounds(Type::None(zone()), Type::Boolean(zone())); |
| 738 } | 758 } |
| 739 | 759 |
| 740 | 760 |
| 741 Bounds Typer::Visitor::TypeStringAdd(Node* node) { | 761 Bounds Typer::Visitor::TypeStringAdd(Node* node) { |
| 742 return Bounds(Type::String(zone())); | 762 return Bounds(Type::None(zone()), Type::String(zone())); |
| 743 } | 763 } |
| 744 | 764 |
| 745 | 765 |
| 746 Bounds Typer::Visitor::TypeChangeTaggedToInt32(Node* node) { | 766 Bounds Typer::Visitor::TypeChangeTaggedToInt32(Node* node) { |
| 747 // TODO(titzer): type is type of input, representation is Word32. | 767 // TODO(titzer): type is type of input, representation is Word32. |
| 748 return Bounds(Type::Integral32()); | 768 return Bounds(Type::None(zone()), Type::Integral32()); |
| 749 } | 769 } |
| 750 | 770 |
| 751 | 771 |
| 752 Bounds Typer::Visitor::TypeChangeTaggedToUint32(Node* node) { | 772 Bounds Typer::Visitor::TypeChangeTaggedToUint32(Node* node) { |
| 753 return Bounds(Type::Integral32()); // TODO(titzer): add appropriate rep | 773 // TODO(titzer): add appropriate rep |
| 774 return Bounds(Type::None(zone()), Type::Integral32()); |
| 754 } | 775 } |
| 755 | 776 |
| 756 | 777 |
| 757 Bounds Typer::Visitor::TypeChangeTaggedToFloat64(Node* node) { | 778 Bounds Typer::Visitor::TypeChangeTaggedToFloat64(Node* node) { |
| 758 // TODO(titzer): type is type of input, representation is Float64. | 779 // TODO(titzer): type is type of input, representation is Float64. |
| 759 return Bounds(Type::Number()); | 780 return Bounds(Type::None(zone()), Type::Number()); |
| 760 } | 781 } |
| 761 | 782 |
| 762 | 783 |
| 763 Bounds Typer::Visitor::TypeChangeInt32ToTagged(Node* node) { | 784 Bounds Typer::Visitor::TypeChangeInt32ToTagged(Node* node) { |
| 764 // TODO(titzer): type is type of input, representation is Tagged. | 785 // TODO(titzer): type is type of input, representation is Tagged. |
| 765 return Bounds(Type::Integral32()); | 786 return Bounds(Type::None(zone()), Type::Integral32()); |
| 766 } | 787 } |
| 767 | 788 |
| 768 | 789 |
| 769 Bounds Typer::Visitor::TypeChangeUint32ToTagged(Node* node) { | 790 Bounds Typer::Visitor::TypeChangeUint32ToTagged(Node* node) { |
| 770 // TODO(titzer): type is type of input, representation is Tagged. | 791 // TODO(titzer): type is type of input, representation is Tagged. |
| 771 return Bounds(Type::Unsigned32()); | 792 return Bounds(Type::None(zone()), Type::Unsigned32()); |
| 772 } | 793 } |
| 773 | 794 |
| 774 | 795 |
| 775 Bounds Typer::Visitor::TypeChangeFloat64ToTagged(Node* node) { | 796 Bounds Typer::Visitor::TypeChangeFloat64ToTagged(Node* node) { |
| 776 // TODO(titzer): type is type of input, representation is Tagged. | 797 // TODO(titzer): type is type of input, representation is Tagged. |
| 777 return Bounds(Type::Number()); | 798 return Bounds(Type::None(zone()), Type::Number()); |
| 778 } | 799 } |
| 779 | 800 |
| 780 | 801 |
| 781 Bounds Typer::Visitor::TypeChangeBoolToBit(Node* node) { | 802 Bounds Typer::Visitor::TypeChangeBoolToBit(Node* node) { |
| 782 // TODO(titzer): type is type of input, representation is Bit. | 803 // TODO(titzer): type is type of input, representation is Bit. |
| 783 return Bounds(Type::Boolean()); | 804 return Bounds(Type::None(zone()), Type::Boolean()); |
| 784 } | 805 } |
| 785 | 806 |
| 786 | 807 |
| 787 Bounds Typer::Visitor::TypeChangeBitToBool(Node* node) { | 808 Bounds Typer::Visitor::TypeChangeBitToBool(Node* node) { |
| 788 // TODO(titzer): type is type of input, representation is Tagged. | 809 // TODO(titzer): type is type of input, representation is Tagged. |
| 789 return Bounds(Type::Boolean()); | 810 return Bounds(Type::None(zone()), Type::Boolean()); |
| 790 } | 811 } |
| 791 | 812 |
| 792 | 813 |
| 793 Bounds Typer::Visitor::TypeLoadField(Node* node) { | 814 Bounds Typer::Visitor::TypeLoadField(Node* node) { |
| 794 return Bounds(FieldAccessOf(node->op()).type); | 815 return Bounds(FieldAccessOf(node->op()).type); |
| 795 } | 816 } |
| 796 | 817 |
| 797 | 818 |
| 798 Bounds Typer::Visitor::TypeLoadElement(Node* node) { | 819 Bounds Typer::Visitor::TypeLoadElement(Node* node) { |
| 799 return Bounds(ElementAccessOf(node->op()).type); | 820 return Bounds(ElementAccessOf(node->op()).type); |
| 800 } | 821 } |
| 801 | 822 |
| 802 | 823 |
| 803 Bounds Typer::Visitor::TypeStoreField(Node* node) { | 824 Bounds Typer::Visitor::TypeStoreField(Node* node) { |
| 804 UNREACHABLE(); | 825 UNREACHABLE(); |
| 805 return Bounds(); | 826 return Bounds(); |
| 806 } | 827 } |
| 807 | 828 |
| 808 | 829 |
| 809 Bounds Typer::Visitor::TypeStoreElement(Node* node) { | 830 Bounds Typer::Visitor::TypeStoreElement(Node* node) { |
| 810 UNREACHABLE(); | 831 UNREACHABLE(); |
| 811 return Bounds(); | 832 return Bounds(); |
| 812 } | 833 } |
| 813 | 834 |
| 814 | 835 |
| 815 // Machine operators. | 836 // Machine operators. |
| 816 | 837 |
| 817 | |
| 818 Bounds Typer::Visitor::TypeLoad(Node* node) { | 838 Bounds Typer::Visitor::TypeLoad(Node* node) { |
| 819 return Bounds::Unbounded(zone()); | 839 return Bounds::Unbounded(zone()); |
| 820 } | 840 } |
| 821 | 841 |
| 822 | 842 |
| 823 Bounds Typer::Visitor::TypeStore(Node* node) { | 843 Bounds Typer::Visitor::TypeStore(Node* node) { |
| 824 UNREACHABLE(); | 844 UNREACHABLE(); |
| 825 return Bounds(); | 845 return Bounds(); |
| 826 } | 846 } |
| 827 | 847 |
| (...skipping 371 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1199 } else if (*value == native->float32_array_fun()) { | 1219 } else if (*value == native->float32_array_fun()) { |
| 1200 return typer_->float32_array_fun_; | 1220 return typer_->float32_array_fun_; |
| 1201 } else if (*value == native->float64_array_fun()) { | 1221 } else if (*value == native->float64_array_fun()) { |
| 1202 return typer_->float64_array_fun_; | 1222 return typer_->float64_array_fun_; |
| 1203 } | 1223 } |
| 1204 } | 1224 } |
| 1205 } | 1225 } |
| 1206 return Type::Constant(value, zone()); | 1226 return Type::Constant(value, zone()); |
| 1207 } | 1227 } |
| 1208 | 1228 |
| 1209 | |
| 1210 namespace { | |
| 1211 | |
| 1212 class TyperDecorator : public GraphDecorator { | |
| 1213 public: | |
| 1214 explicit TyperDecorator(Typer* typer) : typer_(typer) {} | |
| 1215 virtual void Decorate(Node* node) { typer_->Init(node); } | |
| 1216 | |
| 1217 private: | |
| 1218 Typer* typer_; | |
| 1219 }; | |
| 1220 | |
| 1221 } | |
| 1222 | |
| 1223 | |
| 1224 void Typer::DecorateGraph(Graph* graph) { | |
| 1225 graph->AddDecorator(new (zone()) TyperDecorator(this)); | |
| 1226 } | |
| 1227 | |
| 1228 } | 1229 } |
| 1229 } | 1230 } |
| 1230 } // namespace v8::internal::compiler | 1231 } // namespace v8::internal::compiler |
| OLD | NEW |