Index: src/compiler/osr.cc |
diff --git a/src/compiler/osr.cc b/src/compiler/osr.cc |
index 3360a1a321f81f86259e56523dffea76e161b58f..6f30963067ab21b9f49873a44952646062fa8c1f 100644 |
--- a/src/compiler/osr.cc |
+++ b/src/compiler/osr.cc |
@@ -8,6 +8,7 @@ |
#include "src/compiler/frame.h" |
#include "src/compiler/graph.h" |
#include "src/compiler/js-graph.h" |
+#include "src/compiler/loop-analysis.h" |
#include "src/compiler/node.h" |
#include "src/compiler/node-marker.h" |
#include "src/compiler/osr.h" |
@@ -22,38 +23,51 @@ OsrHelper::OsrHelper(CompilationInfo* info) |
stack_slot_count_(info->scope()->num_stack_slots()) {} |
-void OsrHelper::Deconstruct(JSGraph* jsgraph, CommonOperatorBuilder* common, |
+bool OsrHelper::Deconstruct(JSGraph* jsgraph, CommonOperatorBuilder* common, |
Zone* tmp_zone) { |
- NodeDeque queue(tmp_zone); |
Graph* graph = jsgraph->graph(); |
- NodeMarker<bool> marker(graph, 2); |
- queue.push_back(graph->end()); |
- marker.Set(graph->end(), true); |
- |
- while (!queue.empty()) { |
- Node* node = queue.front(); |
- queue.pop_front(); |
- |
- // Rewrite OSR-related nodes. |
- switch (node->opcode()) { |
- case IrOpcode::kOsrNormalEntry: |
- node->ReplaceUses(graph->NewNode(common->Dead())); |
- break; |
- case IrOpcode::kOsrLoopEntry: |
- node->ReplaceUses(graph->start()); |
- break; |
- default: |
- break; |
+ Node* osr_normal_entry = nullptr; |
+ Node* osr_loop_entry = nullptr; |
+ Node* osr_loop = nullptr; |
+ |
+ for (Node* node : graph->start()->uses()) { |
+ if (node->opcode() == IrOpcode::kOsrLoopEntry) { |
+ osr_loop_entry = node; // found the OSR loop entry |
+ } else if (node->opcode() == IrOpcode::kOsrNormalEntry) { |
+ osr_normal_entry = node; |
} |
- for (Node* const input : node->inputs()) { |
- if (!marker.Get(input)) { |
- marker.Set(input, true); |
- queue.push_back(input); |
- } |
+ } |
+ |
+ if (osr_loop_entry == nullptr) { |
+ // No OSR entry found, do nothing. |
+ CHECK_NE(nullptr, osr_normal_entry); |
+ return true; |
+ } |
+ |
+ for (Node* use : osr_loop_entry->uses()) { |
+ if (use->opcode() == IrOpcode::kLoop) { |
+ CHECK_EQ(nullptr, osr_loop); // should be only one OSR loop. |
+ osr_loop = use; // found the OSR loop. |
} |
} |
+ CHECK_NE(nullptr, osr_loop); // Should have found the OSR loop. |
+ |
+ // Analyze the graph to determine how deeply nested the OSR loop is. |
+ LoopTree* loop_tree = LoopFinder::BuildLoopTree(graph, tmp_zone); |
+ |
+ LoopTree::Loop* loop = loop_tree->ContainingLoop(osr_loop); |
+ if (loop->depth() > 0) return false; // cannot OSR inner loops yet. |
+ |
+ // TODO(titzer): perform loop peeling or graph duplication. |
+ |
+ // Replace the normal entry with {Dead} and the loop entry with {Start} |
+ // and run the control reducer to clean up the graph. |
+ osr_normal_entry->ReplaceUses(graph->NewNode(common->Dead())); |
+ osr_loop_entry->ReplaceUses(graph->start()); |
ControlReducer::ReduceGraph(tmp_zone, jsgraph, common); |
+ |
+ return true; |
} |