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.h" | 5 #include "src/compiler.h" |
6 #include "src/compiler/common-operator.h" | 6 #include "src/compiler/common-operator.h" |
7 #include "src/compiler/control-reducer.h" | 7 #include "src/compiler/control-reducer.h" |
8 #include "src/compiler/frame.h" | 8 #include "src/compiler/frame.h" |
9 #include "src/compiler/graph.h" | 9 #include "src/compiler/graph.h" |
10 #include "src/compiler/js-graph.h" | 10 #include "src/compiler/js-graph.h" |
| 11 #include "src/compiler/loop-analysis.h" |
11 #include "src/compiler/node.h" | 12 #include "src/compiler/node.h" |
12 #include "src/compiler/node-marker.h" | 13 #include "src/compiler/node-marker.h" |
13 #include "src/compiler/osr.h" | 14 #include "src/compiler/osr.h" |
14 #include "src/scopes.h" | 15 #include "src/scopes.h" |
15 | 16 |
16 namespace v8 { | 17 namespace v8 { |
17 namespace internal { | 18 namespace internal { |
18 namespace compiler { | 19 namespace compiler { |
19 | 20 |
20 OsrHelper::OsrHelper(CompilationInfo* info) | 21 OsrHelper::OsrHelper(CompilationInfo* info) |
21 : parameter_count_(info->scope()->num_parameters()), | 22 : parameter_count_(info->scope()->num_parameters()), |
22 stack_slot_count_(info->scope()->num_stack_slots()) {} | 23 stack_slot_count_(info->scope()->num_stack_slots()) {} |
23 | 24 |
24 | 25 |
25 void OsrHelper::Deconstruct(JSGraph* jsgraph, CommonOperatorBuilder* common, | 26 bool OsrHelper::Deconstruct(JSGraph* jsgraph, CommonOperatorBuilder* common, |
26 Zone* tmp_zone) { | 27 Zone* tmp_zone) { |
27 NodeDeque queue(tmp_zone); | |
28 Graph* graph = jsgraph->graph(); | 28 Graph* graph = jsgraph->graph(); |
29 NodeMarker<bool> marker(graph, 2); | 29 Node* osr_normal_entry = nullptr; |
30 queue.push_back(graph->end()); | 30 Node* osr_loop_entry = nullptr; |
31 marker.Set(graph->end(), true); | 31 Node* osr_loop = nullptr; |
32 | 32 |
33 while (!queue.empty()) { | 33 for (Node* node : graph->start()->uses()) { |
34 Node* node = queue.front(); | 34 if (node->opcode() == IrOpcode::kOsrLoopEntry) { |
35 queue.pop_front(); | 35 osr_loop_entry = node; // found the OSR loop entry |
36 | 36 } else if (node->opcode() == IrOpcode::kOsrNormalEntry) { |
37 // Rewrite OSR-related nodes. | 37 osr_normal_entry = node; |
38 switch (node->opcode()) { | |
39 case IrOpcode::kOsrNormalEntry: | |
40 node->ReplaceUses(graph->NewNode(common->Dead())); | |
41 break; | |
42 case IrOpcode::kOsrLoopEntry: | |
43 node->ReplaceUses(graph->start()); | |
44 break; | |
45 default: | |
46 break; | |
47 } | |
48 for (Node* const input : node->inputs()) { | |
49 if (!marker.Get(input)) { | |
50 marker.Set(input, true); | |
51 queue.push_back(input); | |
52 } | |
53 } | 38 } |
54 } | 39 } |
55 | 40 |
| 41 if (osr_loop_entry == nullptr) { |
| 42 // No OSR entry found, do nothing. |
| 43 CHECK_NE(nullptr, osr_normal_entry); |
| 44 return true; |
| 45 } |
| 46 |
| 47 for (Node* use : osr_loop_entry->uses()) { |
| 48 if (use->opcode() == IrOpcode::kLoop) { |
| 49 CHECK_EQ(nullptr, osr_loop); // should be only one OSR loop. |
| 50 osr_loop = use; // found the OSR loop. |
| 51 } |
| 52 } |
| 53 |
| 54 CHECK_NE(nullptr, osr_loop); // Should have found the OSR loop. |
| 55 |
| 56 // Analyze the graph to determine how deeply nested the OSR loop is. |
| 57 LoopTree* loop_tree = LoopFinder::BuildLoopTree(graph, tmp_zone); |
| 58 |
| 59 LoopTree::Loop* loop = loop_tree->ContainingLoop(osr_loop); |
| 60 if (loop->depth() > 0) return false; // cannot OSR inner loops yet. |
| 61 |
| 62 // TODO(titzer): perform loop peeling or graph duplication. |
| 63 |
| 64 // Replace the normal entry with {Dead} and the loop entry with {Start} |
| 65 // and run the control reducer to clean up the graph. |
| 66 osr_normal_entry->ReplaceUses(graph->NewNode(common->Dead())); |
| 67 osr_loop_entry->ReplaceUses(graph->start()); |
56 ControlReducer::ReduceGraph(tmp_zone, jsgraph, common); | 68 ControlReducer::ReduceGraph(tmp_zone, jsgraph, common); |
| 69 |
| 70 return true; |
57 } | 71 } |
58 | 72 |
59 | 73 |
60 void OsrHelper::SetupFrame(Frame* frame) { | 74 void OsrHelper::SetupFrame(Frame* frame) { |
61 // The optimized frame will subsume the unoptimized frame. Do so by reserving | 75 // The optimized frame will subsume the unoptimized frame. Do so by reserving |
62 // the first spill slots. | 76 // the first spill slots. |
63 frame->ReserveSpillSlots(UnoptimizedFrameSlots()); | 77 frame->ReserveSpillSlots(UnoptimizedFrameSlots()); |
64 } | 78 } |
65 | 79 |
66 | 80 |
67 } // namespace compiler | 81 } // namespace compiler |
68 } // namespace internal | 82 } // namespace internal |
69 } // namespace v8 | 83 } // namespace v8 |
OLD | NEW |