2015-01-12 11:39:48 +00:00
|
|
|
// Copyright 2014 the V8 project authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
|
|
// found in the LICENSE file.
|
|
|
|
|
|
|
|
#include "src/compiler.h"
|
|
|
|
#include "src/compiler/common-operator.h"
|
|
|
|
#include "src/compiler/control-reducer.h"
|
|
|
|
#include "src/compiler/frame.h"
|
|
|
|
#include "src/compiler/graph.h"
|
|
|
|
#include "src/compiler/js-graph.h"
|
2015-01-29 09:46:24 +00:00
|
|
|
#include "src/compiler/loop-analysis.h"
|
2015-01-12 11:39:48 +00:00
|
|
|
#include "src/compiler/node.h"
|
|
|
|
#include "src/compiler/node-marker.h"
|
|
|
|
#include "src/compiler/osr.h"
|
|
|
|
#include "src/scopes.h"
|
|
|
|
|
|
|
|
namespace v8 {
|
|
|
|
namespace internal {
|
|
|
|
namespace compiler {
|
|
|
|
|
|
|
|
OsrHelper::OsrHelper(CompilationInfo* info)
|
|
|
|
: parameter_count_(info->scope()->num_parameters()),
|
2015-02-02 10:19:52 +00:00
|
|
|
stack_slot_count_(info->scope()->num_stack_slots() +
|
|
|
|
info->osr_expr_stack_height()) {}
|
2015-01-12 11:39:48 +00:00
|
|
|
|
|
|
|
|
2015-01-29 09:46:24 +00:00
|
|
|
bool OsrHelper::Deconstruct(JSGraph* jsgraph, CommonOperatorBuilder* common,
|
2015-01-12 11:39:48 +00:00
|
|
|
Zone* tmp_zone) {
|
|
|
|
Graph* graph = jsgraph->graph();
|
2015-01-29 09:46:24 +00:00
|
|
|
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;
|
2015-01-12 11:39:48 +00:00
|
|
|
}
|
2015-01-29 09:46:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (osr_loop_entry == nullptr) {
|
|
|
|
// No OSR entry found, do nothing.
|
2015-01-30 09:29:25 +00:00
|
|
|
CHECK(osr_normal_entry);
|
2015-01-29 09:46:24 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (Node* use : osr_loop_entry->uses()) {
|
|
|
|
if (use->opcode() == IrOpcode::kLoop) {
|
2015-01-30 09:29:25 +00:00
|
|
|
CHECK(!osr_loop); // should be only one OSR loop.
|
2015-01-29 09:46:24 +00:00
|
|
|
osr_loop = use; // found the OSR loop.
|
2015-01-12 11:39:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-30 09:29:25 +00:00
|
|
|
CHECK(osr_loop); // Should have found the OSR loop.
|
2015-01-29 09:46:24 +00:00
|
|
|
|
|
|
|
// 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());
|
2015-01-12 11:39:48 +00:00
|
|
|
ControlReducer::ReduceGraph(tmp_zone, jsgraph, common);
|
2015-01-29 09:46:24 +00:00
|
|
|
|
|
|
|
return true;
|
2015-01-12 11:39:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void OsrHelper::SetupFrame(Frame* frame) {
|
|
|
|
// The optimized frame will subsume the unoptimized frame. Do so by reserving
|
|
|
|
// the first spill slots.
|
|
|
|
frame->ReserveSpillSlots(UnoptimizedFrameSlots());
|
2015-02-02 10:19:52 +00:00
|
|
|
// The frame needs to be adjusted by the number of unoptimized frame slots.
|
|
|
|
frame->SetOsrStackSlotCount(static_cast<int>(UnoptimizedFrameSlots()));
|
2015-01-12 11:39:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
} // namespace compiler
|
|
|
|
} // namespace internal
|
|
|
|
} // namespace v8
|