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" |
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
245 }; | 245 }; |
246 | 246 |
247 | 247 |
248 class Typer::RunVisitor : public Typer::Visitor { | 248 class Typer::RunVisitor : public Typer::Visitor { |
249 public: | 249 public: |
250 explicit RunVisitor(Typer* typer) | 250 explicit RunVisitor(Typer* typer) |
251 : Visitor(typer), | 251 : Visitor(typer), |
252 redo(NodeSet::key_compare(), NodeSet::allocator_type(typer->zone())) {} | 252 redo(NodeSet::key_compare(), NodeSet::allocator_type(typer->zone())) {} |
253 | 253 |
254 GenericGraphVisit::Control Post(Node* node) { | 254 GenericGraphVisit::Control Post(Node* node) { |
255 if (node->op()->ValueOutputCount() > 0 && !NodeProperties::IsTyped(node)) { | 255 if (node->op()->ValueOutputCount() > 0) { |
256 Bounds bounds = TypeNode(node); | 256 Bounds bounds = TypeNode(node); |
257 NodeProperties::SetBounds(node, bounds); | 257 NodeProperties::SetBounds(node, bounds); |
258 // Remember incompletely typed nodes for least fixpoint iteration. | 258 // Remember incompletely typed nodes for least fixpoint iteration. |
259 if (!NodeProperties::AllValueInputsAreTyped(node)) redo.insert(node); | 259 if (!NodeProperties::AllValueInputsAreTyped(node)) redo.insert(node); |
260 } | 260 } |
261 return GenericGraphVisit::CONTINUE; | 261 return GenericGraphVisit::CONTINUE; |
262 } | 262 } |
263 | 263 |
264 NodeSet redo; | 264 NodeSet redo; |
265 }; | 265 }; |
(...skipping 18 matching lines...) Expand all Loading... |
284 } | 284 } |
285 | 285 |
286 GenericGraphVisit::Control Post(Node* node) { | 286 GenericGraphVisit::Control Post(Node* node) { |
287 return GenericGraphVisit::REENTER; | 287 return GenericGraphVisit::REENTER; |
288 } | 288 } |
289 }; | 289 }; |
290 | 290 |
291 | 291 |
292 class Typer::WidenVisitor : public Typer::Visitor { | 292 class Typer::WidenVisitor : public Typer::Visitor { |
293 public: | 293 public: |
294 explicit WidenVisitor(Typer* typer) : Visitor(typer) {} | 294 explicit WidenVisitor(Typer* typer) |
| 295 : Visitor(typer), |
| 296 local_zone_(zone()->isolate()), |
| 297 enabled_(graph()->NodeCount(), true, &local_zone_), |
| 298 queue_(&local_zone_) {} |
295 | 299 |
296 GenericGraphVisit::Control Pre(Node* node) { | 300 void Run(NodeSet* nodes) { |
297 if (node->op()->ValueOutputCount() > 0) { | 301 // Queue all the roots. |
298 Bounds previous = BoundsOrNone(node); | 302 for (Node* node : *nodes) { |
299 Bounds current = TypeNode(node); | 303 Queue(node); |
| 304 } |
300 | 305 |
301 // Speed up termination in the presence of range types: | 306 while (!queue_.empty()) { |
302 current.upper = Weaken(current.upper, previous.upper); | 307 Node* node = queue_.front(); |
303 current.lower = Weaken(current.lower, previous.lower); | 308 queue_.pop(); |
304 | 309 |
305 DCHECK(previous.lower->Is(current.lower)); | 310 if (node->op()->ValueOutputCount() > 0) { |
306 DCHECK(previous.upper->Is(current.upper)); | 311 // Enable future queuing (and thus re-typing) of this node. |
| 312 enabled_[node->id()] = true; |
307 | 313 |
308 NodeProperties::SetBounds(node, current); | 314 // Compute the new type. |
309 // Stop when nothing changed (but allow re-entry in case it does later). | 315 Bounds previous = BoundsOrNone(node); |
310 return previous.Narrows(current) && current.Narrows(previous) | 316 Bounds current = TypeNode(node); |
311 ? GenericGraphVisit::DEFER | 317 |
312 : GenericGraphVisit::REENTER; | 318 // Speed up termination in the presence of range types: |
313 } else { | 319 current.upper = Weaken(current.upper, previous.upper); |
314 return GenericGraphVisit::SKIP; | 320 current.lower = Weaken(current.lower, previous.lower); |
| 321 |
| 322 // Types should not get less precise. |
| 323 DCHECK(previous.lower->Is(current.lower)); |
| 324 DCHECK(previous.upper->Is(current.upper)); |
| 325 |
| 326 NodeProperties::SetBounds(node, current); |
| 327 // If something changed, push all uses into the queue. |
| 328 if (!(previous.Narrows(current) && current.Narrows(previous))) { |
| 329 for (Node* use : node->uses()) { |
| 330 Queue(use); |
| 331 } |
| 332 } |
| 333 } |
| 334 // If there is no value output, we deliberately leave the node disabled |
| 335 // for queuing - there is no need to type it. |
315 } | 336 } |
316 } | 337 } |
317 | 338 |
318 GenericGraphVisit::Control Post(Node* node) { | 339 void Queue(Node* node) { |
319 return GenericGraphVisit::REENTER; | 340 // If the node is enabled for queuing, push it to the queue and disable it |
| 341 // (to avoid queuing it multiple times). |
| 342 if (enabled_[node->id()]) { |
| 343 queue_.push(node); |
| 344 enabled_[node->id()] = false; |
| 345 } |
320 } | 346 } |
| 347 |
| 348 private: |
| 349 Zone local_zone_; |
| 350 BoolVector enabled_; |
| 351 ZoneQueue<Node*> queue_; |
321 }; | 352 }; |
322 | 353 |
323 | 354 |
324 void Typer::Run() { | 355 void Typer::Run() { |
325 RunVisitor typing(this); | 356 RunVisitor typing(this); |
326 graph_->VisitNodeInputsFromEnd(&typing); | 357 graph_->VisitNodeInputsFromEnd(&typing); |
327 // Find least fixpoint. | 358 // Find least fixpoint. |
328 WidenVisitor widen(this); | 359 WidenVisitor widen(this); |
329 for (NodeSetIter it = typing.redo.begin(); it != typing.redo.end(); ++it) { | 360 widen.Run(&typing.redo); |
330 graph_->VisitNodeUsesFrom(*it, &widen); | |
331 } | |
332 } | 361 } |
333 | 362 |
334 | 363 |
335 void Typer::Narrow(Node* start) { | 364 void Typer::Narrow(Node* start) { |
336 NarrowVisitor typing(this); | 365 NarrowVisitor typing(this); |
337 graph_->VisitNodeUsesFrom(start, &typing); | 366 graph_->VisitNodeUsesFrom(start, &typing); |
338 } | 367 } |
339 | 368 |
340 | 369 |
341 void Typer::Decorator::Decorate(Node* node) { | 370 void Typer::Decorator::Decorate(Node* node) { |
(...skipping 1537 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1879 return typer_->float64_array_fun_; | 1908 return typer_->float64_array_fun_; |
1880 } | 1909 } |
1881 } | 1910 } |
1882 } | 1911 } |
1883 return Type::Constant(value, zone()); | 1912 return Type::Constant(value, zone()); |
1884 } | 1913 } |
1885 | 1914 |
1886 } | 1915 } |
1887 } | 1916 } |
1888 } // namespace v8::internal::compiler | 1917 } // namespace v8::internal::compiler |
OLD | NEW |