| 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;
|
| }
|
|
|
|
|
|
|