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 |