Commit 5d0a4327 authored by Ross McIlroy's avatar Ross McIlroy Committed by Commit Bot

Revert "[Turbofan] Merged the OSR phase into the graph building phase."

This reverts commit 69c8f16d.

Reason for revert: Causing crashes on Clusterfuzz - http://crbug.com/747154

BUG=chromium:747154

Original change's description:
> [Turbofan] Merged the OSR phase into the graph building phase.
> 
> Now the OSR phase is only used when OSRing from the ast graph builder.
> When OSRing from Turbofan, the implementation is now in the graph
> building phase, at the beginning of the VisitBytecode function.
> We are no longer generating any OSRLoopEntry or OSRNormalEntry nodes,
> nor nodes for the possible code of the OSRed function which is before
> the OSRed loops.
> 
> The trimming and reducing of the OSR phase is not done either. This
> change in the way the way the OSR is done enabled to remove the
> workaround to the bug mentioned below.
> 
> Bug: v8:6112
> Bug: v8:6518
> Change-Id: I1c9231810b923486d55ea618d550d981d695d797
> Reviewed-on: https://chromium-review.googlesource.com/543042
> Commit-Queue: Alexandre Talon <alexandret@google.com>
> Reviewed-by: Michael Starzinger <mstarzinger@chromium.org>
> Reviewed-by: Ross McIlroy <rmcilroy@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#46801}

TBR=rmcilroy@chromium.org,mstarzinger@chromium.org,leszeks@chromium.org,alexandret@google.com

Change-Id: Ifa9bf5d86e888a47cad7fb10446b36fda5029604
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: v8:6112, v8:6518
Reviewed-on: https://chromium-review.googlesource.com/581288Reviewed-by: 's avatarRoss McIlroy <rmcilroy@chromium.org>
Commit-Queue: Ross McIlroy <rmcilroy@chromium.org>
Cr-Commit-Position: refs/heads/master@{#46817}
parent 250ba28a
...@@ -80,9 +80,10 @@ class V8_EXPORT_PRIVATE BytecodeAnalysis BASE_EMBEDDED { ...@@ -80,9 +80,10 @@ class V8_EXPORT_PRIVATE BytecodeAnalysis BASE_EMBEDDED {
const LoopInfo& GetLoopInfoFor(int header_offset) const; const LoopInfo& GetLoopInfoFor(int header_offset) const;
// True if the current analysis has an OSR entry point. // True if the current analysis has an OSR entry point.
bool HasOsrEntryPoint() const { return osr_entry_point_ != -1; } bool HasOSREntryPoint() const { return osr_entry_point_ != -1; }
// True if {offset} is the OSR entry loop header.
bool IsOSREntryPoint(int offset) const { return osr_entry_point_ == offset; }
int osr_entry_point() const { return osr_entry_point_; }
// Gets the in-liveness for the bytecode at {offset}. // Gets the in-liveness for the bytecode at {offset}.
const BytecodeLivenessState* GetInLivenessFor(int offset) const; const BytecodeLivenessState* GetInLivenessFor(int offset) const;
......
...@@ -71,7 +71,7 @@ class BytecodeGraphBuilder::Environment : public ZoneObject { ...@@ -71,7 +71,7 @@ class BytecodeGraphBuilder::Environment : public ZoneObject {
Environment* Copy(); Environment* Copy();
void Merge(Environment* other); void Merge(Environment* other);
void FillWithOsrValues(); void PrepareForOsrEntry();
void PrepareForLoop(const BytecodeLoopAssignments& assignments); void PrepareForLoop(const BytecodeLoopAssignments& assignments);
void PrepareForLoopExit(Node* loop, void PrepareForLoopExit(Node* loop,
const BytecodeLoopAssignments& assignments); const BytecodeLoopAssignments& assignments);
...@@ -307,18 +307,27 @@ void BytecodeGraphBuilder::Environment::PrepareForLoop( ...@@ -307,18 +307,27 @@ void BytecodeGraphBuilder::Environment::PrepareForLoop(
builder()->exit_controls_.push_back(terminate); builder()->exit_controls_.push_back(terminate);
} }
void BytecodeGraphBuilder::Environment::FillWithOsrValues() { void BytecodeGraphBuilder::Environment::PrepareForOsrEntry() {
DCHECK_EQ(IrOpcode::kLoop, GetControlDependency()->opcode());
DCHECK_EQ(1, GetControlDependency()->InputCount());
Node* start = graph()->start(); Node* start = graph()->start();
// Create a control node for the OSR entry point and update the current
// environment's dependencies accordingly.
Node* entry = graph()->NewNode(common()->OsrLoopEntry(), start, start);
UpdateControlDependency(entry);
UpdateEffectDependency(entry);
// Create OSR values for each environment value. // Create OSR values for each environment value.
SetContext(graph()->NewNode( SetContext(graph()->NewNode(
common()->OsrValue(Linkage::kOsrContextSpillSlotIndex), start)); common()->OsrValue(Linkage::kOsrContextSpillSlotIndex), entry));
int size = static_cast<int>(values()->size()); int size = static_cast<int>(values()->size());
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
int idx = i; // Indexing scheme follows {StandardFrame}, adapt accordingly. int idx = i; // Indexing scheme follows {StandardFrame}, adapt accordingly.
if (i >= register_base()) idx += InterpreterFrameConstants::kExtraSlotCount; if (i >= register_base()) idx += InterpreterFrameConstants::kExtraSlotCount;
if (i >= accumulator_base()) idx = Linkage::kOsrAccumulatorRegisterIndex; if (i >= accumulator_base()) idx = Linkage::kOsrAccumulatorRegisterIndex;
values()->at(i) = graph()->NewNode(common()->OsrValue(idx), start); values()->at(i) = graph()->NewNode(common()->OsrValue(idx), entry);
} }
} }
...@@ -431,7 +440,7 @@ BytecodeGraphBuilder::BytecodeGraphBuilder( ...@@ -431,7 +440,7 @@ BytecodeGraphBuilder::BytecodeGraphBuilder(
Handle<FeedbackVector> feedback_vector, BailoutId osr_ast_id, Handle<FeedbackVector> feedback_vector, BailoutId osr_ast_id,
JSGraph* jsgraph, CallFrequency invocation_frequency, JSGraph* jsgraph, CallFrequency invocation_frequency,
SourcePositionTable* source_positions, int inlining_id, SourcePositionTable* source_positions, int inlining_id,
JSTypeHintLowering::Flags flags, bool stack_check) JSTypeHintLowering::Flags flags)
: local_zone_(local_zone), : local_zone_(local_zone),
jsgraph_(jsgraph), jsgraph_(jsgraph),
invocation_frequency_(invocation_frequency), invocation_frequency_(invocation_frequency),
...@@ -448,8 +457,6 @@ BytecodeGraphBuilder::BytecodeGraphBuilder( ...@@ -448,8 +457,6 @@ BytecodeGraphBuilder::BytecodeGraphBuilder(
bytecode_analysis_(nullptr), bytecode_analysis_(nullptr),
environment_(nullptr), environment_(nullptr),
osr_ast_id_(osr_ast_id), osr_ast_id_(osr_ast_id),
currently_peeled_loop_offset_(-1),
stack_check_(stack_check),
merge_environments_(local_zone), merge_environments_(local_zone),
exception_handlers_(local_zone), exception_handlers_(local_zone),
current_exception_handler_(0), current_exception_handler_(0),
...@@ -514,7 +521,7 @@ VectorSlotPair BytecodeGraphBuilder::CreateVectorSlotPair(int slot_id) { ...@@ -514,7 +521,7 @@ VectorSlotPair BytecodeGraphBuilder::CreateVectorSlotPair(int slot_id) {
return VectorSlotPair(feedback_vector(), slot); return VectorSlotPair(feedback_vector(), slot);
} }
void BytecodeGraphBuilder::CreateGraph() { void BytecodeGraphBuilder::CreateGraph(bool stack_check) {
SourcePositionTable::Scope pos_scope(source_positions_, start_position_); SourcePositionTable::Scope pos_scope(source_positions_, start_position_);
// Set up the basic structure of the graph. Outputs for {Start} are the formal // Set up the basic structure of the graph. Outputs for {Start} are the formal
...@@ -528,7 +535,7 @@ void BytecodeGraphBuilder::CreateGraph() { ...@@ -528,7 +535,7 @@ void BytecodeGraphBuilder::CreateGraph() {
GetFunctionContext()); GetFunctionContext());
set_environment(&env); set_environment(&env);
VisitBytecodes(); VisitBytecodes(stack_check);
// Finish the basic structure of the graph. // Finish the basic structure of the graph.
DCHECK_NE(0u, exit_controls_.size()); DCHECK_NE(0u, exit_controls_.size());
...@@ -593,207 +600,38 @@ void BytecodeGraphBuilder::PrepareFrameState(Node* node, ...@@ -593,207 +600,38 @@ void BytecodeGraphBuilder::PrepareFrameState(Node* node,
} }
} }
// Stores the state of the SourcePosition iterator, and the index to the void BytecodeGraphBuilder::VisitBytecodes(bool stack_check) {
// current exception handlers stack. We need, during the OSR graph generation, BytecodeAnalysis bytecode_analysis(bytecode_array(), local_zone(),
// to backup the states of these iterators at the LoopHeader offset of each FLAG_analyze_environment_liveness);
// outer loop which contains the OSR loop. The iterators are then restored when bytecode_analysis.Analyze(osr_ast_id_);
// peeling the loops, so that both exception handling and synchronisation with set_bytecode_analysis(&bytecode_analysis);
// the source position can be achieved.
class BytecodeGraphBuilder::OsrIteratorState {
public:
OsrIteratorState(interpreter::BytecodeArrayIterator* iterator,
SourcePositionTableIterator* source_position_iterator,
BytecodeGraphBuilder* graph_builder)
: iterator_(iterator),
source_position_iterator_(source_position_iterator),
graph_builder_(graph_builder),
saved_states_(graph_builder->local_zone()) {}
void ProcessOsrPrelude() {
ZoneVector<int> outer_loop_offsets(graph_builder_->local_zone());
const BytecodeAnalysis& bytecode_analysis =
*(graph_builder_->bytecode_analysis());
int osr_offset = bytecode_analysis.osr_entry_point();
// We find here the outermost loop which contains the OSR loop.
int outermost_loop_offset = osr_offset;
while ((outermost_loop_offset =
bytecode_analysis.GetLoopInfoFor(outermost_loop_offset)
.parent_offset()) != -1) {
outer_loop_offsets.push_back(outermost_loop_offset);
}
outermost_loop_offset =
outer_loop_offsets.empty() ? osr_offset : outer_loop_offsets.back();
// We will not processs any bytecode before the outermost_loop_offset, but
// the source_position_iterator needs to be advanced step by step through
// the bytecode.
for (; iterator_->current_offset() != outermost_loop_offset;
iterator_->Advance()) {
graph_builder_->UpdateSourcePosition(source_position_iterator_,
iterator_->current_offset());
}
// We save some iterators states at the offsets of the loop headers of the
// outer loops (the ones containing the OSR loop). They will be used for
// jumping back in the bytecode.
for (ZoneVector<int>::const_reverse_iterator it =
outer_loop_offsets.crbegin();
it != outer_loop_offsets.crend(); ++it) {
int next_loop_offset = *it;
for (; iterator_->current_offset() != next_loop_offset;
iterator_->Advance()) {
graph_builder_->UpdateSourcePosition(source_position_iterator_,
iterator_->current_offset());
graph_builder_->EnterAndExitExceptionHandlers(
iterator_->current_offset());
}
saved_states_.push(
IteratorsStates(graph_builder_->current_exception_handler(),
source_position_iterator_->GetState()));
}
// Finishing by advancing to the OSR entry
for (; iterator_->current_offset() != osr_offset; iterator_->Advance()) {
graph_builder_->UpdateSourcePosition(source_position_iterator_,
iterator_->current_offset());
}
graph_builder_->set_currently_peeled_loop_offset(
bytecode_analysis.GetLoopInfoFor(osr_offset).parent_offset());
}
void RestoreState(int target_offset, int new_parent_offset) {
iterator_->SetOffset(target_offset);
// In case of a return, we must not build loop exits for
// not-yet-built outer loops.
graph_builder_->set_currently_peeled_loop_offset(new_parent_offset);
IteratorsStates saved_state = saved_states_.top();
source_position_iterator_->RestoreState(saved_state.source_iterator_state_);
graph_builder_->set_current_exception_handler(
saved_state.exception_handler_index_);
saved_states_.pop();
}
private: interpreter::BytecodeArrayIterator iterator(bytecode_array());
struct IteratorsStates { set_bytecode_iterator(&iterator);
int exception_handler_index_; SourcePositionTableIterator source_position_iterator(
SourcePositionTableIterator::IndexAndPosition source_iterator_state_; handle(bytecode_array()->SourcePositionTable()));
IteratorsStates(
int exception_handler_index,
SourcePositionTableIterator::IndexAndPosition source_iterator_state)
: exception_handler_index_(exception_handler_index),
source_iterator_state_(source_iterator_state) {}
};
interpreter::BytecodeArrayIterator* iterator_;
SourcePositionTableIterator* source_position_iterator_;
BytecodeGraphBuilder* graph_builder_;
ZoneStack<IteratorsStates> saved_states_;
};
void BytecodeGraphBuilder::RemoveMergeEnvironmentsBeforeOffset( if (FLAG_trace_environment_liveness) {
int limit_offset) { OFStream of(stdout);
if (!merge_environments_.empty()) {
ZoneMap<int, Environment*>::iterator it = merge_environments_.begin(); bytecode_analysis.PrintLivenessTo(of);
ZoneMap<int, Environment*>::iterator stop_it = merge_environments_.end();
while (it != stop_it && it->first <= limit_offset) {
it = merge_environments_.erase(it);
}
}
}
// We will iterate through the OSR loop, then its parent, and so on
// until we have reached the outmost loop containing the OSR loop. We do
// not generate nodes for anything before the outermost loop.
void BytecodeGraphBuilder::AdvanceToOsrEntryAndPeelLoops(
interpreter::BytecodeArrayIterator* iterator,
SourcePositionTableIterator* source_position_iterator) {
const BytecodeAnalysis& analysis = *(bytecode_analysis());
int osr_offset = analysis.osr_entry_point();
OsrIteratorState iterator_states(iterator, source_position_iterator, this);
iterator_states.ProcessOsrPrelude();
DCHECK_EQ(iterator->current_offset(), osr_offset);
environment()->FillWithOsrValues();
// Suppose we have n nested loops, loop_0 being the outermost one, and
// loop_n being the OSR loop. We start iterating the bytecode at the header
// of loop_n (the OSR loop), and then we peel the part of the the body of
// loop_{n-1} following the end of loop_n. We then rewind the iterator to
// the header of loop_{n-1}, and so on until we have partly peeled loop 0.
// The full loop_0 body will be generating with the rest of the function,
// outside the OSR generation.
// To do so, if we are visiting a loop, we continue to visit what's left
// of its parent, and then when reaching the parent's JumpLoop, we do not
// create any jump for that but rewind the bytecode iterator to visit the
// parent loop entirely, and so on.
int current_parent_offset =
analysis.GetLoopInfoFor(osr_offset).parent_offset();
while (current_parent_offset != -1) {
LoopInfo current_parent_loop =
analysis.GetLoopInfoFor(current_parent_offset);
// We iterate until the back edge of the parent loop, which we detect by
// the offset that the JumpLoop targets.
for (; !iterator->done(); iterator->Advance()) {
if (iterator->current_bytecode() == interpreter::Bytecode::kJumpLoop &&
iterator->GetJumpTargetOffset() == current_parent_offset) {
// Reached the end of the current parent loop.
break;
} }
VisitSingleBytecode(source_position_iterator);
} BuildOSRNormalEntryPoint();
DCHECK(!iterator->done()); // Should have found the loop's jump target.
for (; !iterator.done(); iterator.Advance()) {
// We also need to take care of the merge environments and exceptions
// handlers here because the omitted JumpLoop bytecode can still be the
// target of jumps or the first bytecode after a try block.
EnterAndExitExceptionHandlers(iterator->current_offset());
SwitchToMergeEnvironment(iterator->current_offset());
// This jump is the jump of our parent loop, which is not yet created.
// So we do not build the jump nodes, but restore the bytecode and the
// SourcePosition iterators to the values they had when we were visiting
// the offset pointed at by the JumpLoop we've just reached.
// We have already built nodes for inner loops, but now we will
// iterate again over them and build new nodes corresponding to the same
// bytecode offsets. Any jump or reference to this inner loops must now
// point to the new nodes we will build, hence we clear the relevant part
// of the environment.
// Completely clearing the environment is not possible because merge
// environments for forward jumps out of the loop need to be preserved
// (e.g. a return or a labeled break in the middle of a loop).
RemoveMergeEnvironmentsBeforeOffset(iterator->current_offset());
iterator_states.RestoreState(current_parent_offset,
current_parent_loop.parent_offset());
current_parent_offset = current_parent_loop.parent_offset();
}
}
// TODO(alexandret) create an iterator which wraps both bytecode_iterator and
// source_position_iterator and increments them in one, so we don't need to
// pass source_position_iterator as an argument here.
void BytecodeGraphBuilder::VisitSingleBytecode(
SourcePositionTableIterator* source_position_iterator) {
const interpreter::BytecodeArrayIterator& iterator = bytecode_iterator();
int current_offset = iterator.current_offset(); int current_offset = iterator.current_offset();
UpdateSourcePosition(source_position_iterator, current_offset); UpdateCurrentSourcePosition(&source_position_iterator, current_offset);
EnterAndExitExceptionHandlers(current_offset); EnterAndExitExceptionHandlers(current_offset);
SwitchToMergeEnvironment(current_offset); SwitchToMergeEnvironment(current_offset);
if (environment() != nullptr) { if (environment() != nullptr) {
BuildLoopHeaderEnvironment(current_offset); BuildLoopHeaderEnvironment(current_offset);
// Skip the first stack check if stack_check is false // Skip the first stack check if stack_check is false
if (!stack_check() && if (!stack_check &&
iterator.current_bytecode() == interpreter::Bytecode::kStackCheck) { iterator.current_bytecode() == interpreter::Bytecode::kStackCheck) {
set_stack_check(true); stack_check = true;
return; continue;
} }
switch (iterator.current_bytecode()) { switch (iterator.current_bytecode()) {
...@@ -805,35 +643,6 @@ void BytecodeGraphBuilder::VisitSingleBytecode( ...@@ -805,35 +643,6 @@ void BytecodeGraphBuilder::VisitSingleBytecode(
#undef BYTECODE_CODE #undef BYTECODE_CODE
} }
} }
}
void BytecodeGraphBuilder::VisitBytecodes() {
BytecodeAnalysis bytecode_analysis(bytecode_array(), local_zone(),
FLAG_analyze_environment_liveness);
bytecode_analysis.Analyze(osr_ast_id_);
set_bytecode_analysis(&bytecode_analysis);
interpreter::BytecodeArrayIterator iterator(bytecode_array());
set_bytecode_iterator(&iterator);
SourcePositionTableIterator source_position_iterator(
handle(bytecode_array()->SourcePositionTable()));
if (FLAG_trace_environment_liveness) {
OFStream of(stdout);
bytecode_analysis.PrintLivenessTo(of);
}
if (bytecode_analysis.HasOsrEntryPoint()) {
// We peel the OSR loop and any outer loop containing it except that we
// leave the nodes corresponding to the whole outermost loop (including
// the last copies of the loops it contains) to be generated by the normal
// bytecode iteration below.
AdvanceToOsrEntryAndPeelLoops(&iterator, &source_position_iterator);
}
for (; !iterator.done(); iterator.Advance()) {
VisitSingleBytecode(&source_position_iterator);
} }
set_bytecode_analysis(nullptr); set_bytecode_analysis(nullptr);
set_bytecode_iterator(nullptr); set_bytecode_iterator(nullptr);
...@@ -1058,8 +867,8 @@ BytecodeGraphBuilder::Environment* BytecodeGraphBuilder::CheckContextExtensions( ...@@ -1058,8 +867,8 @@ BytecodeGraphBuilder::Environment* BytecodeGraphBuilder::CheckContextExtensions(
// Output environment where the context has an extension // Output environment where the context has an extension
Environment* slow_environment = nullptr; Environment* slow_environment = nullptr;
// We only need to check up to the last-but-one depth, because the an eval // We only need to check up to the last-but-one depth, because the an eval in
// in the same scope as the variable itself has no way of shadowing it. // the same scope as the variable itself has no way of shadowing it.
for (uint32_t d = 0; d < depth; d++) { for (uint32_t d = 0; d < depth; d++) {
Node* extension_slot = Node* extension_slot =
NewNode(javascript()->LoadContext(d, Context::EXTENSION_INDEX, false)); NewNode(javascript()->LoadContext(d, Context::EXTENSION_INDEX, false));
...@@ -1088,8 +897,8 @@ BytecodeGraphBuilder::Environment* BytecodeGraphBuilder::CheckContextExtensions( ...@@ -1088,8 +897,8 @@ BytecodeGraphBuilder::Environment* BytecodeGraphBuilder::CheckContextExtensions(
// the fast path. // the fast path.
} }
// The depth can be zero, in which case no slow-path checks are built, and // The depth can be zero, in which case no slow-path checks are built, and the
// the slow path environment can be null. // slow path environment can be null.
DCHECK(depth == 0 || slow_environment != nullptr); DCHECK(depth == 0 || slow_environment != nullptr);
return slow_environment; return slow_environment;
...@@ -2600,6 +2409,8 @@ void BytecodeGraphBuilder::BuildLoopHeaderEnvironment(int current_offset) { ...@@ -2600,6 +2409,8 @@ void BytecodeGraphBuilder::BuildLoopHeaderEnvironment(int current_offset) {
// Add loop header. // Add loop header.
environment()->PrepareForLoop(loop_info.assignments()); environment()->PrepareForLoop(loop_info.assignments());
BuildOSRLoopEntryPoint(current_offset);
// Store a copy of the environment so we can connect merged back edge inputs // Store a copy of the environment so we can connect merged back edge inputs
// to the loop header. // to the loop header.
merge_environments_[current_offset] = environment()->Copy(); merge_environments_[current_offset] = environment()->Copy();
...@@ -2609,7 +2420,6 @@ void BytecodeGraphBuilder::BuildLoopHeaderEnvironment(int current_offset) { ...@@ -2609,7 +2420,6 @@ void BytecodeGraphBuilder::BuildLoopHeaderEnvironment(int current_offset) {
void BytecodeGraphBuilder::MergeIntoSuccessorEnvironment(int target_offset) { void BytecodeGraphBuilder::MergeIntoSuccessorEnvironment(int target_offset) {
BuildLoopExitsForBranch(target_offset); BuildLoopExitsForBranch(target_offset);
Environment*& merge_environment = merge_environments_[target_offset]; Environment*& merge_environment = merge_environments_[target_offset];
if (merge_environment == nullptr) { if (merge_environment == nullptr) {
// Append merge nodes to the environment. We may merge here with another // Append merge nodes to the environment. We may merge here with another
// environment. So add a place holder for merge nodes. We may add redundant // environment. So add a place holder for merge nodes. We may add redundant
...@@ -2628,6 +2438,26 @@ void BytecodeGraphBuilder::MergeControlToLeaveFunction(Node* exit) { ...@@ -2628,6 +2438,26 @@ void BytecodeGraphBuilder::MergeControlToLeaveFunction(Node* exit) {
set_environment(nullptr); set_environment(nullptr);
} }
void BytecodeGraphBuilder::BuildOSRLoopEntryPoint(int current_offset) {
DCHECK(bytecode_analysis()->IsLoopHeader(current_offset));
if (bytecode_analysis()->IsOSREntryPoint(current_offset)) {
// For OSR add a special {OsrLoopEntry} node into the current loop header.
// It will be turned into a usable entry by the OSR deconstruction.
Environment* osr_env = environment()->Copy();
osr_env->PrepareForOsrEntry();
environment()->Merge(osr_env);
}
}
void BytecodeGraphBuilder::BuildOSRNormalEntryPoint() {
if (bytecode_analysis()->HasOSREntryPoint()) {
// For OSR add an {OsrNormalEntry} as the the top-level environment start.
// It will be replaced with {Dead} by the OSR deconstruction.
NewNode(common()->OsrNormalEntry());
}
}
void BytecodeGraphBuilder::BuildLoopExitsForBranch(int target_offset) { void BytecodeGraphBuilder::BuildLoopExitsForBranch(int target_offset) {
int origin_offset = bytecode_iterator().current_offset(); int origin_offset = bytecode_iterator().current_offset();
// Only build loop exits for forward edges. // Only build loop exits for forward edges.
...@@ -2640,10 +2470,6 @@ void BytecodeGraphBuilder::BuildLoopExitsForBranch(int target_offset) { ...@@ -2640,10 +2470,6 @@ void BytecodeGraphBuilder::BuildLoopExitsForBranch(int target_offset) {
void BytecodeGraphBuilder::BuildLoopExitsUntilLoop(int loop_offset) { void BytecodeGraphBuilder::BuildLoopExitsUntilLoop(int loop_offset) {
int origin_offset = bytecode_iterator().current_offset(); int origin_offset = bytecode_iterator().current_offset();
int current_loop = bytecode_analysis()->GetLoopOffsetFor(origin_offset); int current_loop = bytecode_analysis()->GetLoopOffsetFor(origin_offset);
// The limit_offset is the stop offset for building loop exists, used for OSR.
// It prevents the creations of loopexits for loops which do not exist.
loop_offset = std::max(loop_offset, currently_peeled_loop_offset_);
while (loop_offset < current_loop) { while (loop_offset < current_loop) {
Node* loop_node = merge_environments_[current_loop]->GetControlDependency(); Node* loop_node = merge_environments_[current_loop]->GetControlDependency();
const LoopInfo& loop_info = const LoopInfo& loop_info =
...@@ -2777,6 +2603,10 @@ Node* BytecodeGraphBuilder::TryBuildSimplifiedCall(const Operator* op, ...@@ -2777,6 +2603,10 @@ Node* BytecodeGraphBuilder::TryBuildSimplifiedCall(const Operator* op,
Node* const* args, Node* const* args,
int arg_count, int arg_count,
FeedbackSlot slot) { FeedbackSlot slot) {
// TODO(mstarzinger,6112): This is a workaround for OSR loop entries being
// pruned from the graph by a soft-deopt. It can happen that a CallIC that
// control-dominates the OSR entry is still in "uninitialized" state.
if (!osr_ast_id_.IsNone()) return nullptr;
Node* effect = environment()->GetEffectDependency(); Node* effect = environment()->GetEffectDependency();
Node* control = environment()->GetControlDependency(); Node* control = environment()->GetControlDependency();
Reduction early_reduction = type_hint_lowering().ReduceCallOperation( Reduction early_reduction = type_hint_lowering().ReduceCallOperation(
...@@ -2792,6 +2622,10 @@ Node* BytecodeGraphBuilder::TryBuildSimplifiedConstruct(const Operator* op, ...@@ -2792,6 +2622,10 @@ Node* BytecodeGraphBuilder::TryBuildSimplifiedConstruct(const Operator* op,
Node* const* args, Node* const* args,
int arg_count, int arg_count,
FeedbackSlot slot) { FeedbackSlot slot) {
// TODO(mstarzinger,6112): This is a workaround for OSR loop entries being
// pruned from the graph by a soft-deopt. It can happen that a CallIC that
// control-dominates the OSR entry is still in "uninitialized" state.
if (!osr_ast_id_.IsNone()) return nullptr;
Node* effect = environment()->GetEffectDependency(); Node* effect = environment()->GetEffectDependency();
Node* control = environment()->GetControlDependency(); Node* control = environment()->GetControlDependency();
Reduction early_reduction = type_hint_lowering().ReduceConstructOperation( Reduction early_reduction = type_hint_lowering().ReduceConstructOperation(
...@@ -2806,6 +2640,10 @@ Node* BytecodeGraphBuilder::TryBuildSimplifiedConstruct(const Operator* op, ...@@ -2806,6 +2640,10 @@ Node* BytecodeGraphBuilder::TryBuildSimplifiedConstruct(const Operator* op,
Node* BytecodeGraphBuilder::TryBuildSimplifiedLoadNamed(const Operator* op, Node* BytecodeGraphBuilder::TryBuildSimplifiedLoadNamed(const Operator* op,
Node* receiver, Node* receiver,
FeedbackSlot slot) { FeedbackSlot slot) {
// TODO(mstarzinger,6112): This is a workaround for OSR loop entries being
// pruned from the graph by a soft-deopt. It can happen that a LoadIC that
// control-dominates the OSR entry is still in "uninitialized" state.
if (bytecode_analysis()->HasOSREntryPoint()) return nullptr;
Node* effect = environment()->GetEffectDependency(); Node* effect = environment()->GetEffectDependency();
Node* control = environment()->GetControlDependency(); Node* control = environment()->GetControlDependency();
Reduction early_reduction = type_hint_lowering().ReduceLoadNamedOperation( Reduction early_reduction = type_hint_lowering().ReduceLoadNamedOperation(
...@@ -2821,6 +2659,10 @@ Node* BytecodeGraphBuilder::TryBuildSimplifiedLoadKeyed(const Operator* op, ...@@ -2821,6 +2659,10 @@ Node* BytecodeGraphBuilder::TryBuildSimplifiedLoadKeyed(const Operator* op,
Node* receiver, Node* receiver,
Node* key, Node* key,
FeedbackSlot slot) { FeedbackSlot slot) {
// TODO(mstarzinger,6112): This is a workaround for OSR loop entries being
// pruned from the graph by a soft-deopt. It can happen that a LoadIC that
// control-dominates the OSR entry is still in "uninitialized" state.
if (bytecode_analysis()->HasOSREntryPoint()) return nullptr;
Node* effect = environment()->GetEffectDependency(); Node* effect = environment()->GetEffectDependency();
Node* control = environment()->GetControlDependency(); Node* control = environment()->GetControlDependency();
Reduction early_reduction = type_hint_lowering().ReduceLoadKeyedOperation( Reduction early_reduction = type_hint_lowering().ReduceLoadKeyedOperation(
...@@ -2836,6 +2678,10 @@ Node* BytecodeGraphBuilder::TryBuildSimplifiedStoreNamed(const Operator* op, ...@@ -2836,6 +2678,10 @@ Node* BytecodeGraphBuilder::TryBuildSimplifiedStoreNamed(const Operator* op,
Node* receiver, Node* receiver,
Node* value, Node* value,
FeedbackSlot slot) { FeedbackSlot slot) {
// TODO(mstarzinger,6112): This is a workaround for OSR loop entries being
// pruned from the graph by a soft-deopt. It can happen that a LoadIC that
// control-dominates the OSR entry is still in "uninitialized" state.
if (bytecode_analysis()->HasOSREntryPoint()) return nullptr;
Node* effect = environment()->GetEffectDependency(); Node* effect = environment()->GetEffectDependency();
Node* control = environment()->GetControlDependency(); Node* control = environment()->GetControlDependency();
Reduction early_reduction = type_hint_lowering().ReduceStoreNamedOperation( Reduction early_reduction = type_hint_lowering().ReduceStoreNamedOperation(
...@@ -2851,6 +2697,10 @@ Node* BytecodeGraphBuilder::TryBuildSimplifiedStoreKeyed(const Operator* op, ...@@ -2851,6 +2697,10 @@ Node* BytecodeGraphBuilder::TryBuildSimplifiedStoreKeyed(const Operator* op,
Node* receiver, Node* receiver,
Node* key, Node* value, Node* key, Node* value,
FeedbackSlot slot) { FeedbackSlot slot) {
// TODO(mstarzinger,6112): This is a workaround for OSR loop entries being
// pruned from the graph by a soft-deopt. It can happen that a LoadIC that
// control-dominates the OSR entry is still in "uninitialized" state.
if (bytecode_analysis()->HasOSREntryPoint()) return nullptr;
Node* effect = environment()->GetEffectDependency(); Node* effect = environment()->GetEffectDependency();
Node* control = environment()->GetControlDependency(); Node* control = environment()->GetControlDependency();
Reduction early_reduction = type_hint_lowering().ReduceStoreKeyedOperation( Reduction early_reduction = type_hint_lowering().ReduceStoreKeyedOperation(
...@@ -2997,6 +2847,7 @@ Node* BytecodeGraphBuilder::NewPhi(int count, Node* input, Node* control) { ...@@ -2997,6 +2847,7 @@ Node* BytecodeGraphBuilder::NewPhi(int count, Node* input, Node* control) {
return graph()->NewNode(phi_op, count + 1, buffer, true); return graph()->NewNode(phi_op, count + 1, buffer, true);
} }
Node* BytecodeGraphBuilder::NewEffectPhi(int count, Node* input, Node* BytecodeGraphBuilder::NewEffectPhi(int count, Node* input,
Node* control) { Node* control) {
const Operator* phi_op = common()->EffectPhi(count); const Operator* phi_op = common()->EffectPhi(count);
...@@ -3028,6 +2879,7 @@ Node* BytecodeGraphBuilder::MergeControl(Node* control, Node* other) { ...@@ -3028,6 +2879,7 @@ Node* BytecodeGraphBuilder::MergeControl(Node* control, Node* other) {
return control; return control;
} }
Node* BytecodeGraphBuilder::MergeEffect(Node* value, Node* other, Node* BytecodeGraphBuilder::MergeEffect(Node* value, Node* other,
Node* control) { Node* control) {
int inputs = control->op()->ControlInputCount(); int inputs = control->op()->ControlInputCount();
...@@ -3044,6 +2896,7 @@ Node* BytecodeGraphBuilder::MergeEffect(Node* value, Node* other, ...@@ -3044,6 +2896,7 @@ Node* BytecodeGraphBuilder::MergeEffect(Node* value, Node* other,
return value; return value;
} }
Node* BytecodeGraphBuilder::MergeValue(Node* value, Node* other, Node* BytecodeGraphBuilder::MergeValue(Node* value, Node* other,
Node* control) { Node* control) {
int inputs = control->op()->ControlInputCount(); int inputs = control->op()->ControlInputCount();
...@@ -3061,9 +2914,10 @@ Node* BytecodeGraphBuilder::MergeValue(Node* value, Node* other, ...@@ -3061,9 +2914,10 @@ Node* BytecodeGraphBuilder::MergeValue(Node* value, Node* other,
return value; return value;
} }
void BytecodeGraphBuilder::UpdateSourcePosition(SourcePositionTableIterator* it, void BytecodeGraphBuilder::UpdateCurrentSourcePosition(
int offset) { SourcePositionTableIterator* it, int offset) {
if (it->done()) return; if (it->done()) return;
if (it->code_offset() == offset) { if (it->code_offset() == offset) {
source_positions_->SetCurrentPosition(SourcePosition( source_positions_->SetCurrentPosition(SourcePosition(
it->source_position().ScriptOffset(), start_position_.InliningId())); it->source_position().ScriptOffset(), start_position_.InliningId()));
......
...@@ -31,25 +31,16 @@ class BytecodeGraphBuilder { ...@@ -31,25 +31,16 @@ class BytecodeGraphBuilder {
JSGraph* jsgraph, CallFrequency invocation_frequency, JSGraph* jsgraph, CallFrequency invocation_frequency,
SourcePositionTable* source_positions, SourcePositionTable* source_positions,
int inlining_id = SourcePosition::kNotInlined, int inlining_id = SourcePosition::kNotInlined,
JSTypeHintLowering::Flags flags = JSTypeHintLowering::kNoFlags, JSTypeHintLowering::Flags flags = JSTypeHintLowering::kNoFlags);
bool stack_check = true);
// Creates a graph by visiting bytecodes. // Creates a graph by visiting bytecodes.
void CreateGraph(); void CreateGraph(bool stack_check = true);
private: private:
class Environment; class Environment;
class OsrIteratorState;
struct SubEnvironment; struct SubEnvironment;
void RemoveMergeEnvironmentsBeforeOffset(int limit_offset); void VisitBytecodes(bool stack_check);
void AdvanceToOsrEntryAndPeelLoops(
interpreter::BytecodeArrayIterator* iterator,
SourcePositionTableIterator* source_position_iterator);
void VisitSingleBytecode(
SourcePositionTableIterator* source_position_iterator);
void VisitBytecodes();
// Get or create the node that represents the outer function closure. // Get or create the node that represents the outer function closure.
Node* GetFunctionClosure(); Node* GetFunctionClosure();
...@@ -245,6 +236,10 @@ class BytecodeGraphBuilder { ...@@ -245,6 +236,10 @@ class BytecodeGraphBuilder {
// Simulates control flow that exits the function body. // Simulates control flow that exits the function body.
void MergeControlToLeaveFunction(Node* exit); void MergeControlToLeaveFunction(Node* exit);
// Builds entry points that are used by OSR deconstruction.
void BuildOSRLoopEntryPoint(int current_offset);
void BuildOSRNormalEntryPoint();
// Builds loop exit nodes for every exited loop between the current bytecode // Builds loop exit nodes for every exited loop between the current bytecode
// offset and {target_offset}. // offset and {target_offset}.
void BuildLoopExitsForBranch(int target_offset); void BuildLoopExitsForBranch(int target_offset);
...@@ -256,7 +251,7 @@ class BytecodeGraphBuilder { ...@@ -256,7 +251,7 @@ class BytecodeGraphBuilder {
// Update the current position of the {SourcePositionTable} to that of the // Update the current position of the {SourcePositionTable} to that of the
// bytecode at {offset}, if any. // bytecode at {offset}, if any.
void UpdateSourcePosition(SourcePositionTableIterator* it, int offset); void UpdateCurrentSourcePosition(SourcePositionTableIterator* it, int offset);
// Growth increment for the temporary buffer used to construct input lists to // Growth increment for the temporary buffer used to construct input lists to
// new nodes. // new nodes.
...@@ -304,7 +299,7 @@ class BytecodeGraphBuilder { ...@@ -304,7 +299,7 @@ class BytecodeGraphBuilder {
} }
void set_bytecode_iterator( void set_bytecode_iterator(
interpreter::BytecodeArrayIterator* bytecode_iterator) { const interpreter::BytecodeArrayIterator* bytecode_iterator) {
bytecode_iterator_ = bytecode_iterator; bytecode_iterator_ = bytecode_iterator;
} }
...@@ -316,24 +311,6 @@ class BytecodeGraphBuilder { ...@@ -316,24 +311,6 @@ class BytecodeGraphBuilder {
bytecode_analysis_ = bytecode_analysis; bytecode_analysis_ = bytecode_analysis;
} }
int currently_peeled_loop_offset() const {
return currently_peeled_loop_offset_;
}
void set_currently_peeled_loop_offset(int offset) {
currently_peeled_loop_offset_ = offset;
}
bool stack_check() const { return stack_check_; }
void set_stack_check(bool stack_check) { stack_check_ = stack_check; }
int current_exception_handler() { return current_exception_handler_; }
void set_current_exception_handler(int index) {
current_exception_handler_ = index;
}
bool needs_eager_checkpoint() const { return needs_eager_checkpoint_; } bool needs_eager_checkpoint() const { return needs_eager_checkpoint_; }
void mark_as_needing_eager_checkpoint(bool value) { void mark_as_needing_eager_checkpoint(bool value) {
needs_eager_checkpoint_ = value; needs_eager_checkpoint_ = value;
...@@ -355,8 +332,6 @@ class BytecodeGraphBuilder { ...@@ -355,8 +332,6 @@ class BytecodeGraphBuilder {
const BytecodeAnalysis* bytecode_analysis_; const BytecodeAnalysis* bytecode_analysis_;
Environment* environment_; Environment* environment_;
BailoutId osr_ast_id_; BailoutId osr_ast_id_;
int currently_peeled_loop_offset_;
bool stack_check_;
// Merge environments are snapshots of the environment at points where the // Merge environments are snapshots of the environment at points where the
// control flow merges. This models a forward data flow propagation of all // control flow merges. This models a forward data flow propagation of all
......
...@@ -552,9 +552,8 @@ Reduction JSInliner::ReduceJSCall(Node* node) { ...@@ -552,9 +552,8 @@ Reduction JSInliner::ReduceJSCall(Node* node) {
} }
BytecodeGraphBuilder graph_builder( BytecodeGraphBuilder graph_builder(
parse_info.zone(), shared_info, feedback_vector, BailoutId::None(), parse_info.zone(), shared_info, feedback_vector, BailoutId::None(),
jsgraph(), call.frequency(), source_positions_, inlining_id, flags, jsgraph(), call.frequency(), source_positions_, inlining_id, flags);
false); graph_builder.CreateGraph(false);
graph_builder.CreateGraph();
// Extract the inlinee start/end nodes. // Extract the inlinee start/end nodes.
start = graph()->start(); start = graph()->start();
......
...@@ -255,9 +255,8 @@ void PeelOuterLoopsForOsr(Graph* graph, CommonOperatorBuilder* common, ...@@ -255,9 +255,8 @@ void PeelOuterLoopsForOsr(Graph* graph, CommonOperatorBuilder* common,
} // namespace } // namespace
void OsrHelper::Deconstruct(CompilationInfo* info, JSGraph* jsgraph, void OsrHelper::Deconstruct(JSGraph* jsgraph, CommonOperatorBuilder* common,
CommonOperatorBuilder* common, Zone* tmp_zone) { Zone* tmp_zone) {
DCHECK(!info->is_optimizing_from_bytecode());
Graph* graph = jsgraph->graph(); Graph* graph = jsgraph->graph();
Node* osr_normal_entry = nullptr; Node* osr_normal_entry = nullptr;
Node* osr_loop_entry = nullptr; Node* osr_loop_entry = nullptr;
......
...@@ -6,9 +6,6 @@ ...@@ -6,9 +6,6 @@
#define V8_COMPILER_OSR_H_ #define V8_COMPILER_OSR_H_
#include "src/zone/zone.h" #include "src/zone/zone.h"
// TODO(6409) This phase (and then the below explanations) are now only used
// when osring from the ast graph builder. When using Ignition bytecode, the OSR
// implementation is integrated directly to the graph building phase.
// TurboFan structures OSR graphs in a way that separates almost all phases of // TurboFan structures OSR graphs in a way that separates almost all phases of
// compilation from OSR implementation details. This is accomplished with // compilation from OSR implementation details. This is accomplished with
...@@ -98,8 +95,8 @@ class OsrHelper { ...@@ -98,8 +95,8 @@ class OsrHelper {
// Deconstructs the artificial {OsrNormalEntry} and rewrites the graph so // Deconstructs the artificial {OsrNormalEntry} and rewrites the graph so
// that only the path corresponding to {OsrLoopEntry} remains. // that only the path corresponding to {OsrLoopEntry} remains.
void Deconstruct(CompilationInfo* info, JSGraph* jsgraph, void Deconstruct(JSGraph* jsgraph, CommonOperatorBuilder* common,
CommonOperatorBuilder* common, Zone* tmp_zone); Zone* tmp_zone);
// Prepares the frame w.r.t. OSR. // Prepares the frame w.r.t. OSR.
void SetupFrame(Frame* frame); void SetupFrame(Frame* frame);
......
...@@ -1085,20 +1085,14 @@ struct OsrDeconstructionPhase { ...@@ -1085,20 +1085,14 @@ struct OsrDeconstructionPhase {
static const char* phase_name() { return "OSR deconstruction"; } static const char* phase_name() { return "OSR deconstruction"; }
void Run(PipelineData* data, Zone* temp_zone) { void Run(PipelineData* data, Zone* temp_zone) {
// When the bytecode comes from Ignition, we do the OSR implementation
// during the graph building phase.
if (data->info()->is_optimizing_from_bytecode()) return;
GraphTrimmer trimmer(temp_zone, data->graph()); GraphTrimmer trimmer(temp_zone, data->graph());
NodeVector roots(temp_zone); NodeVector roots(temp_zone);
data->jsgraph()->GetCachedNodes(&roots); data->jsgraph()->GetCachedNodes(&roots);
trimmer.TrimGraph(roots.begin(), roots.end()); trimmer.TrimGraph(roots.begin(), roots.end());
// TODO(neis): Remove (the whole OsrDeconstructionPhase) when AST graph // TODO(neis): Use data->osr_helper() here once AST graph builder is gone.
// builder is gone.
OsrHelper osr_helper(data->info()); OsrHelper osr_helper(data->info());
osr_helper.Deconstruct(data->info(), data->jsgraph(), data->common(), osr_helper.Deconstruct(data->jsgraph(), data->common(), temp_zone);
temp_zone);
} }
}; };
......
...@@ -61,12 +61,6 @@ class V8_EXPORT_PRIVATE SourcePositionTableBuilder { ...@@ -61,12 +61,6 @@ class V8_EXPORT_PRIVATE SourcePositionTableBuilder {
class V8_EXPORT_PRIVATE SourcePositionTableIterator { class V8_EXPORT_PRIVATE SourcePositionTableIterator {
public: public:
// Used for saving/restoring the iterator.
struct IndexAndPosition {
int index_;
PositionTableEntry position_;
};
// We expose two flavours of the iterator, depending on the argument passed // We expose two flavours of the iterator, depending on the argument passed
// to the constructor: // to the constructor:
...@@ -95,13 +89,6 @@ class V8_EXPORT_PRIVATE SourcePositionTableIterator { ...@@ -95,13 +89,6 @@ class V8_EXPORT_PRIVATE SourcePositionTableIterator {
} }
bool done() const { return index_ == kDone; } bool done() const { return index_ == kDone; }
IndexAndPosition GetState() const { return {index_, current_}; }
void RestoreState(const IndexAndPosition& saved_state) {
index_ = saved_state.index_;
current_ = saved_state.position_;
}
private: private:
static const int kDone = -1; static const int kDone = -1;
......
// Copyright 2017 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.
// Flags: --allow-natives-syntax
// This tests checks some possible wrong exception handling due to,
// for instance, the OSR loop peeling. If exception handlers are not updated
// correctly, when we run the second iteration of the outermost loop, which
// is the OSR optimised version, the try-catch will fail... which should not
// fail on a correct code.
function toto() {
for (var a = 0; a < 2; a++) {
try { throw 'The exception should have been caught.'; }
catch(e) {}
for (var b = 0; b < 1; b++) {
%OptimizeOsr();
}
}
}
toto();
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment