| 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/compiler/graph-inl.h" | 5 #include "src/compiler/graph-inl.h" |
| 6 #include "src/compiler/js-operator.h" | 6 #include "src/compiler/js-operator.h" |
| 7 #include "src/compiler/node.h" | 7 #include "src/compiler/node.h" |
| 8 #include "src/compiler/node-properties-inl.h" | 8 #include "src/compiler/node-properties-inl.h" |
| 9 #include "src/compiler/node-properties.h" | 9 #include "src/compiler/node-properties.h" |
| 10 #include "src/compiler/simplified-operator.h" | 10 #include "src/compiler/simplified-operator.h" |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 63 | 63 |
| 64 | 64 |
| 65 class Typer::Visitor : public NullNodeVisitor { | 65 class Typer::Visitor : public NullNodeVisitor { |
| 66 public: | 66 public: |
| 67 Visitor(Typer* typer, MaybeHandle<Context> context) | 67 Visitor(Typer* typer, MaybeHandle<Context> context) |
| 68 : typer_(typer), context_(context) {} | 68 : typer_(typer), context_(context) {} |
| 69 | 69 |
| 70 Bounds TypeNode(Node* node) { | 70 Bounds TypeNode(Node* node) { |
| 71 switch (node->opcode()) { | 71 switch (node->opcode()) { |
| 72 #define DECLARE_CASE(x) case IrOpcode::k##x: return Type##x(node); | 72 #define DECLARE_CASE(x) case IrOpcode::k##x: return Type##x(node); |
| 73 DECLARE_CASE(Start) |
| 73 VALUE_OP_LIST(DECLARE_CASE) | 74 VALUE_OP_LIST(DECLARE_CASE) |
| 74 #undef DECLARE_CASE | 75 #undef DECLARE_CASE |
| 75 | 76 |
| 76 #define DECLARE_CASE(x) case IrOpcode::k##x: | 77 #define DECLARE_CASE(x) case IrOpcode::k##x: |
| 77 CONTROL_OP_LIST(DECLARE_CASE) | 78 DECLARE_CASE(End) |
| 79 INNER_CONTROL_OP_LIST(DECLARE_CASE) |
| 78 #undef DECLARE_CASE | 80 #undef DECLARE_CASE |
| 79 break; | 81 break; |
| 80 } | 82 } |
| 81 return Bounds(Type::None(zone())); | 83 UNREACHABLE(); |
| 84 return Bounds(); |
| 82 } | 85 } |
| 83 | 86 |
| 84 Type* TypeConstant(Handle<Object> value); | 87 Type* TypeConstant(Handle<Object> value); |
| 85 | 88 |
| 86 protected: | 89 protected: |
| 87 #define DECLARE_METHOD(x) inline Bounds Type##x(Node* node); | 90 #define DECLARE_METHOD(x) inline Bounds Type##x(Node* node); |
| 91 DECLARE_METHOD(Start) |
| 88 VALUE_OP_LIST(DECLARE_METHOD) | 92 VALUE_OP_LIST(DECLARE_METHOD) |
| 89 #undef DECLARE_METHOD | 93 #undef DECLARE_METHOD |
| 90 | 94 |
| 91 Bounds OperandType(Node* node, int i) { | 95 Bounds OperandType(Node* node, int i) { |
| 92 return NodeProperties::GetBounds(NodeProperties::GetValueInput(node, i)); | 96 return NodeProperties::GetBounds(NodeProperties::GetValueInput(node, i)); |
| 93 } | 97 } |
| 94 | 98 |
| 95 Type* ContextType(Node* node) { | 99 Type* ContextType(Node* node) { |
| 96 Bounds result = | 100 Bounds result = |
| 97 NodeProperties::GetBounds(NodeProperties::GetContextInput(node)); | 101 NodeProperties::GetBounds(NodeProperties::GetContextInput(node)); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 111 }; | 115 }; |
| 112 | 116 |
| 113 | 117 |
| 114 class Typer::RunVisitor : public Typer::Visitor { | 118 class Typer::RunVisitor : public Typer::Visitor { |
| 115 public: | 119 public: |
| 116 RunVisitor(Typer* typer, MaybeHandle<Context> context) | 120 RunVisitor(Typer* typer, MaybeHandle<Context> context) |
| 117 : Visitor(typer, context), | 121 : Visitor(typer, context), |
| 118 phis(NodeSet::key_compare(), NodeSet::allocator_type(typer->zone())) {} | 122 phis(NodeSet::key_compare(), NodeSet::allocator_type(typer->zone())) {} |
| 119 | 123 |
| 120 GenericGraphVisit::Control Post(Node* node) { | 124 GenericGraphVisit::Control Post(Node* node) { |
| 121 Bounds bounds = TypeNode(node); | 125 if (OperatorProperties::HasValueOutput(node->op())) { |
| 122 if (node->opcode() == IrOpcode::kPhi) { | 126 Bounds bounds = TypeNode(node); |
| 127 NodeProperties::SetBounds(node, bounds); |
| 123 // Remember phis for least fixpoint iteration. | 128 // Remember phis for least fixpoint iteration. |
| 124 phis.insert(node); | 129 if (node->opcode() == IrOpcode::kPhi) phis.insert(node); |
| 125 } else { | |
| 126 NodeProperties::SetBounds(node, bounds); | |
| 127 } | 130 } |
| 128 return GenericGraphVisit::CONTINUE; | 131 return GenericGraphVisit::CONTINUE; |
| 129 } | 132 } |
| 130 | 133 |
| 131 NodeSet phis; | 134 NodeSet phis; |
| 132 }; | 135 }; |
| 133 | 136 |
| 134 | 137 |
| 135 class Typer::NarrowVisitor : public Typer::Visitor { | 138 class Typer::NarrowVisitor : public Typer::Visitor { |
| 136 public: | 139 public: |
| 137 NarrowVisitor(Typer* typer, MaybeHandle<Context> context) | 140 NarrowVisitor(Typer* typer, MaybeHandle<Context> context) |
| 138 : Visitor(typer, context) {} | 141 : Visitor(typer, context) {} |
| 139 | 142 |
| 140 GenericGraphVisit::Control Pre(Node* node) { | 143 GenericGraphVisit::Control Pre(Node* node) { |
| 141 Bounds previous = NodeProperties::GetBounds(node); | 144 if (OperatorProperties::HasValueOutput(node->op())) { |
| 142 Bounds bounds = TypeNode(node); | 145 Bounds previous = NodeProperties::GetBounds(node); |
| 143 NodeProperties::SetBounds(node, Bounds::Both(bounds, previous, zone())); | 146 Bounds bounds = TypeNode(node); |
| 144 DCHECK(bounds.Narrows(previous)); | 147 NodeProperties::SetBounds(node, Bounds::Both(bounds, previous, zone())); |
| 145 // Stop when nothing changed (but allow reentry in case it does later). | 148 DCHECK(bounds.Narrows(previous)); |
| 146 return previous.Narrows(bounds) | 149 // Stop when nothing changed (but allow re-entry in case it does later). |
| 147 ? GenericGraphVisit::DEFER : GenericGraphVisit::REENTER; | 150 return previous.Narrows(bounds) |
| 151 ? GenericGraphVisit::DEFER : GenericGraphVisit::REENTER; |
| 152 } else { |
| 153 return GenericGraphVisit::SKIP; |
| 154 } |
| 148 } | 155 } |
| 149 | 156 |
| 150 GenericGraphVisit::Control Post(Node* node) { | 157 GenericGraphVisit::Control Post(Node* node) { |
| 151 return GenericGraphVisit::REENTER; | 158 return GenericGraphVisit::REENTER; |
| 152 } | 159 } |
| 153 }; | 160 }; |
| 154 | 161 |
| 155 | 162 |
| 156 class Typer::WidenVisitor : public Typer::Visitor { | 163 class Typer::WidenVisitor : public Typer::Visitor { |
| 157 public: | 164 public: |
| 158 WidenVisitor(Typer* typer, MaybeHandle<Context> context) | 165 WidenVisitor(Typer* typer, MaybeHandle<Context> context) |
| 159 : Visitor(typer, context) {} | 166 : Visitor(typer, context) {} |
| 160 | 167 |
| 161 GenericGraphVisit::Control Pre(Node* node) { | 168 GenericGraphVisit::Control Pre(Node* node) { |
| 162 Bounds previous = NodeProperties::GetBounds(node); | 169 if (OperatorProperties::HasValueOutput(node->op())) { |
| 163 Bounds bounds = TypeNode(node); | 170 Bounds previous = NodeProperties::GetBounds(node); |
| 164 DCHECK(previous.lower->Is(bounds.lower)); | 171 Bounds bounds = TypeNode(node); |
| 165 DCHECK(previous.upper->Is(bounds.upper)); | 172 DCHECK(previous.lower->Is(bounds.lower)); |
| 166 NodeProperties::SetBounds(node, bounds); // TODO(rossberg): Either? | 173 DCHECK(previous.upper->Is(bounds.upper)); |
| 167 // Stop when nothing changed (but allow reentry in case it does later). | 174 NodeProperties::SetBounds(node, bounds); // TODO(rossberg): Either? |
| 168 return bounds.Narrows(previous) | 175 // Stop when nothing changed (but allow re-entry in case it does later). |
| 169 ? GenericGraphVisit::DEFER : GenericGraphVisit::REENTER; | 176 return bounds.Narrows(previous) |
| 177 ? GenericGraphVisit::DEFER : GenericGraphVisit::REENTER; |
| 178 } else { |
| 179 return GenericGraphVisit::SKIP; |
| 180 } |
| 170 } | 181 } |
| 171 | 182 |
| 172 GenericGraphVisit::Control Post(Node* node) { | 183 GenericGraphVisit::Control Post(Node* node) { |
| 173 return GenericGraphVisit::REENTER; | 184 return GenericGraphVisit::REENTER; |
| 174 } | 185 } |
| 175 }; | 186 }; |
| 176 | 187 |
| 177 | 188 |
| 178 void Typer::Run(Graph* graph, MaybeHandle<Context> context) { | 189 void Typer::Run(Graph* graph, MaybeHandle<Context> context) { |
| 179 RunVisitor typing(this, context); | 190 RunVisitor typing(this, context); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 197 } | 208 } |
| 198 | 209 |
| 199 | 210 |
| 200 void Typer::Init(Node* node) { | 211 void Typer::Init(Node* node) { |
| 201 Visitor typing(this, MaybeHandle<Context>()); | 212 Visitor typing(this, MaybeHandle<Context>()); |
| 202 Bounds bounds = typing.TypeNode(node); | 213 Bounds bounds = typing.TypeNode(node); |
| 203 NodeProperties::SetBounds(node, bounds); | 214 NodeProperties::SetBounds(node, bounds); |
| 204 } | 215 } |
| 205 | 216 |
| 206 | 217 |
| 218 // ----------------------------------------------------------------------------- |
| 219 |
| 220 |
| 221 // Control operators. |
| 222 |
| 223 Bounds Typer::Visitor::TypeStart(Node* node) { |
| 224 return Bounds(Type::Internal(zone())); |
| 225 } |
| 226 |
| 227 |
| 207 // Common operators. | 228 // Common operators. |
| 229 |
| 208 Bounds Typer::Visitor::TypeParameter(Node* node) { | 230 Bounds Typer::Visitor::TypeParameter(Node* node) { |
| 209 return Bounds::Unbounded(zone()); | 231 return Bounds::Unbounded(zone()); |
| 210 } | 232 } |
| 211 | 233 |
| 212 | 234 |
| 213 Bounds Typer::Visitor::TypeInt32Constant(Node* node) { | 235 Bounds Typer::Visitor::TypeInt32Constant(Node* node) { |
| 214 // TODO(titzer): only call Type::Of() if the type is not already known. | 236 // TODO(titzer): only call Type::Of() if the type is not already known. |
| 215 return Bounds(Type::Of(OpParameter<int32_t>(node), zone())); | 237 return Bounds(Type::Of(OpParameter<int32_t>(node), zone())); |
| 216 } | 238 } |
| 217 | 239 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 249 int arity = OperatorProperties::GetValueInputCount(node->op()); | 271 int arity = OperatorProperties::GetValueInputCount(node->op()); |
| 250 Bounds bounds = OperandType(node, 0); | 272 Bounds bounds = OperandType(node, 0); |
| 251 for (int i = 1; i < arity; ++i) { | 273 for (int i = 1; i < arity; ++i) { |
| 252 bounds = Bounds::Either(bounds, OperandType(node, i), zone()); | 274 bounds = Bounds::Either(bounds, OperandType(node, i), zone()); |
| 253 } | 275 } |
| 254 return bounds; | 276 return bounds; |
| 255 } | 277 } |
| 256 | 278 |
| 257 | 279 |
| 258 Bounds Typer::Visitor::TypeEffectPhi(Node* node) { | 280 Bounds Typer::Visitor::TypeEffectPhi(Node* node) { |
| 259 return Bounds(Type::None(zone())); | 281 UNREACHABLE(); |
| 282 return Bounds(); |
| 260 } | 283 } |
| 261 | 284 |
| 262 | 285 |
| 263 Bounds Typer::Visitor::TypeControlEffect(Node* node) { | 286 Bounds Typer::Visitor::TypeControlEffect(Node* node) { |
| 264 return Bounds(Type::None(zone())); | 287 UNREACHABLE(); |
| 288 return Bounds(); |
| 265 } | 289 } |
| 266 | 290 |
| 267 | 291 |
| 268 Bounds Typer::Visitor::TypeValueEffect(Node* node) { | 292 Bounds Typer::Visitor::TypeValueEffect(Node* node) { |
| 269 return Bounds(Type::None(zone())); | 293 UNREACHABLE(); |
| 294 return Bounds(); |
| 270 } | 295 } |
| 271 | 296 |
| 272 | 297 |
| 273 Bounds Typer::Visitor::TypeFinish(Node* node) { return OperandType(node, 0); } | 298 Bounds Typer::Visitor::TypeFinish(Node* node) { |
| 299 return OperandType(node, 0); |
| 300 } |
| 274 | 301 |
| 275 | 302 |
| 276 Bounds Typer::Visitor::TypeFrameState(Node* node) { | 303 Bounds Typer::Visitor::TypeFrameState(Node* node) { |
| 277 return Bounds(Type::None(zone())); | 304 UNREACHABLE(); |
| 305 return Bounds(); |
| 278 } | 306 } |
| 279 | 307 |
| 280 | 308 |
| 281 Bounds Typer::Visitor::TypeStateValues(Node* node) { | 309 Bounds Typer::Visitor::TypeStateValues(Node* node) { |
| 282 return Bounds(Type::None(zone())); | 310 UNREACHABLE(); |
| 311 return Bounds(); |
| 283 } | 312 } |
| 284 | 313 |
| 285 | 314 |
| 286 Bounds Typer::Visitor::TypeCall(Node* node) { | 315 Bounds Typer::Visitor::TypeCall(Node* node) { |
| 287 return Bounds::Unbounded(zone()); | 316 return Bounds::Unbounded(zone()); |
| 288 } | 317 } |
| 289 | 318 |
| 290 | 319 |
| 291 Bounds Typer::Visitor::TypeProjection(Node* node) { | 320 Bounds Typer::Visitor::TypeProjection(Node* node) { |
| 292 // TODO(titzer): use the output type of the input to determine the bounds. | 321 // TODO(titzer): use the output type of the input to determine the bounds. |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 417 return Bounds(Type::None(zone()), Type::String(zone())); | 446 return Bounds(Type::None(zone()), Type::String(zone())); |
| 418 } | 447 } |
| 419 | 448 |
| 420 | 449 |
| 421 Bounds Typer::Visitor::TypeJSToName(Node* node) { | 450 Bounds Typer::Visitor::TypeJSToName(Node* node) { |
| 422 return Bounds(Type::None(zone()), Type::Name(zone())); | 451 return Bounds(Type::None(zone()), Type::Name(zone())); |
| 423 } | 452 } |
| 424 | 453 |
| 425 | 454 |
| 426 Bounds Typer::Visitor::TypeJSToObject(Node* node) { | 455 Bounds Typer::Visitor::TypeJSToObject(Node* node) { |
| 427 return Bounds(Type::None(zone()), Type::Object(zone())); | 456 return Bounds(Type::None(zone()), Type::Receiver(zone())); |
| 428 } | 457 } |
| 429 | 458 |
| 430 | 459 |
| 431 // JS object operators. | 460 // JS object operators. |
| 432 | 461 |
| 433 Bounds Typer::Visitor::TypeJSCreate(Node* node) { | 462 Bounds Typer::Visitor::TypeJSCreate(Node* node) { |
| 434 return Bounds(Type::None(zone()), Type::Object(zone())); | 463 return Bounds(Type::None(zone()), Type::Object(zone())); |
| 435 } | 464 } |
| 436 | 465 |
| 437 | 466 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 451 return result; | 480 return result; |
| 452 } | 481 } |
| 453 | 482 |
| 454 | 483 |
| 455 Bounds Typer::Visitor::TypeJSLoadNamed(Node* node) { | 484 Bounds Typer::Visitor::TypeJSLoadNamed(Node* node) { |
| 456 return Bounds::Unbounded(zone()); | 485 return Bounds::Unbounded(zone()); |
| 457 } | 486 } |
| 458 | 487 |
| 459 | 488 |
| 460 Bounds Typer::Visitor::TypeJSStoreProperty(Node* node) { | 489 Bounds Typer::Visitor::TypeJSStoreProperty(Node* node) { |
| 461 return Bounds(Type::None(zone())); | 490 UNREACHABLE(); |
| 491 return Bounds(); |
| 462 } | 492 } |
| 463 | 493 |
| 464 | 494 |
| 465 Bounds Typer::Visitor::TypeJSStoreNamed(Node* node) { | 495 Bounds Typer::Visitor::TypeJSStoreNamed(Node* node) { |
| 466 return Bounds(Type::None(zone())); | 496 UNREACHABLE(); |
| 497 return Bounds(); |
| 467 } | 498 } |
| 468 | 499 |
| 469 | 500 |
| 470 Bounds Typer::Visitor::TypeJSDeleteProperty(Node* node) { | 501 Bounds Typer::Visitor::TypeJSDeleteProperty(Node* node) { |
| 471 return Bounds(Type::Boolean(zone())); | 502 return Bounds(Type::Boolean(zone())); |
| 472 } | 503 } |
| 473 | 504 |
| 474 | 505 |
| 475 Bounds Typer::Visitor::TypeJSHasProperty(Node* node) { | 506 Bounds Typer::Visitor::TypeJSHasProperty(Node* node) { |
| 476 return Bounds(Type::Boolean(zone())); | 507 return Bounds(Type::Boolean(zone())); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 516 } else { | 547 } else { |
| 517 Handle<Object> value = | 548 Handle<Object> value = |
| 518 handle(context.ToHandleChecked()->get(access.index()), isolate()); | 549 handle(context.ToHandleChecked()->get(access.index()), isolate()); |
| 519 Type* lower = TypeConstant(value); | 550 Type* lower = TypeConstant(value); |
| 520 return Bounds(lower, Type::Any(zone())); | 551 return Bounds(lower, Type::Any(zone())); |
| 521 } | 552 } |
| 522 } | 553 } |
| 523 | 554 |
| 524 | 555 |
| 525 Bounds Typer::Visitor::TypeJSStoreContext(Node* node) { | 556 Bounds Typer::Visitor::TypeJSStoreContext(Node* node) { |
| 526 return Bounds(Type::None(zone())); | 557 UNREACHABLE(); |
| 558 return Bounds(); |
| 527 } | 559 } |
| 528 | 560 |
| 529 | 561 |
| 530 Bounds Typer::Visitor::TypeJSCreateFunctionContext(Node* node) { | 562 Bounds Typer::Visitor::TypeJSCreateFunctionContext(Node* node) { |
| 531 Type* outer = ContextType(node); | 563 Type* outer = ContextType(node); |
| 532 return Bounds(Type::Context(outer, zone())); | 564 return Bounds(Type::Context(outer, zone())); |
| 533 } | 565 } |
| 534 | 566 |
| 535 | 567 |
| 536 Bounds Typer::Visitor::TypeJSCreateCatchContext(Node* node) { | 568 Bounds Typer::Visitor::TypeJSCreateCatchContext(Node* node) { |
| (...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 737 return Bounds(FieldAccessOf(node->op()).type); | 769 return Bounds(FieldAccessOf(node->op()).type); |
| 738 } | 770 } |
| 739 | 771 |
| 740 | 772 |
| 741 Bounds Typer::Visitor::TypeLoadElement(Node* node) { | 773 Bounds Typer::Visitor::TypeLoadElement(Node* node) { |
| 742 return Bounds(ElementAccessOf(node->op()).type); | 774 return Bounds(ElementAccessOf(node->op()).type); |
| 743 } | 775 } |
| 744 | 776 |
| 745 | 777 |
| 746 Bounds Typer::Visitor::TypeStoreField(Node* node) { | 778 Bounds Typer::Visitor::TypeStoreField(Node* node) { |
| 747 return Bounds(Type::None()); | 779 UNREACHABLE(); |
| 780 return Bounds(); |
| 748 } | 781 } |
| 749 | 782 |
| 750 | 783 |
| 751 Bounds Typer::Visitor::TypeStoreElement(Node* node) { | 784 Bounds Typer::Visitor::TypeStoreElement(Node* node) { |
| 752 return Bounds(Type::None()); | 785 UNREACHABLE(); |
| 786 return Bounds(); |
| 753 } | 787 } |
| 754 | 788 |
| 755 | 789 |
| 756 // Machine operators. | 790 // Machine operators. |
| 757 | 791 |
| 758 // TODO(rossberg): implement | 792 // TODO(rossberg): implement |
| 759 #define DEFINE_METHOD(x) \ | 793 #define DEFINE_METHOD(x) \ |
| 760 Bounds Typer::Visitor::Type##x(Node* node) { return Bounds(Type::None()); } | 794 Bounds Typer::Visitor::Type##x(Node* node) { return Bounds(Type::None()); } |
| 761 MACHINE_OP_LIST(DEFINE_METHOD) | 795 MACHINE_OP_LIST(DEFINE_METHOD) |
| 762 #undef DEFINE_METHOD | 796 #undef DEFINE_METHOD |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 841 } | 875 } |
| 842 | 876 |
| 843 | 877 |
| 844 void Typer::DecorateGraph(Graph* graph) { | 878 void Typer::DecorateGraph(Graph* graph) { |
| 845 graph->AddDecorator(new (zone()) TyperDecorator(this)); | 879 graph->AddDecorator(new (zone()) TyperDecorator(this)); |
| 846 } | 880 } |
| 847 | 881 |
| 848 } | 882 } |
| 849 } | 883 } |
| 850 } // namespace v8::internal::compiler | 884 } // namespace v8::internal::compiler |
| OLD | NEW |