Revert "[turbofan] Add new JSFrameSpecialization reducer."

Also revert "[turbofan] Perform OSR deconstruction early and remove type propagation."

This reverts commit b0a852e8c2.

This reverts commit cdbb6c485b.

NOTRY=true
NOTREECHECKS=true
BUG=v8:4273
LOG=n
TBR=bmeurer@chromium.org

Review URL: https://codereview.chromium.org/1225743002

Cr-Commit-Position: refs/heads/master@{#29480}
This commit is contained in:
machenbach 2015-07-06 03:01:27 -07:00 committed by Commit bot
parent aaa457b26f
commit 9e71cdba48
11 changed files with 103 additions and 167 deletions

View File

@ -672,8 +672,6 @@ source_set("v8_base") {
"src/compiler/js-builtin-reducer.h",
"src/compiler/js-context-specialization.cc",
"src/compiler/js-context-specialization.h",
"src/compiler/js-frame-specialization.cc",
"src/compiler/js-frame-specialization.h",
"src/compiler/js-generic-lowering.cc",
"src/compiler/js-generic-lowering.h",
"src/compiler/js-graph.cc",

View File

@ -394,7 +394,6 @@ OptimizedCompileJob::Status OptimizedCompileJob::CreateGraph() {
}
if (info()->shared_info()->asm_function()) {
if (info()->osr_frame()) info()->MarkAsFrameSpecializing();
info()->MarkAsContextSpecializing();
} else if (FLAG_turbo_type_feedback) {
info()->MarkAsTypeFeedbackEnabled();
@ -713,9 +712,7 @@ static void InsertCodeIntoOptimizedCodeMap(CompilationInfo* info) {
if (code->kind() != Code::OPTIMIZED_FUNCTION) return; // Nothing to do.
// Context specialization folds-in the context, so no sharing can occur.
if (info->is_context_specializing()) return;
// Frame specialization implies context specialization.
DCHECK(!info->is_frame_specializing());
if (code->is_turbofanned() && info->is_context_specializing()) return;
// Do not cache bound functions.
Handle<JSFunction> function = info->closure();
@ -1472,8 +1469,7 @@ Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfo(
MaybeHandle<Code> Compiler::GetOptimizedCode(Handle<JSFunction> function,
Handle<Code> current_code,
ConcurrencyMode mode,
BailoutId osr_ast_id,
JavaScriptFrame* osr_frame) {
BailoutId osr_ast_id) {
Handle<Code> cached_code;
if (GetCodeFromOptimizedCodeMap(
function, osr_ast_id).ToHandle(&cached_code)) {
@ -1531,7 +1527,6 @@ MaybeHandle<Code> Compiler::GetOptimizedCode(Handle<JSFunction> function,
return isolate->builtins()->InOptimizationQueue();
}
} else {
info->set_osr_frame(osr_frame);
if (GetOptimizedCodeNow(info.get())) return info->code();
}

View File

@ -17,7 +17,6 @@ namespace internal {
class AstValueFactory;
class HydrogenCodeStub;
class JavaScriptFrame;
class ParseInfo;
class ScriptData;
@ -123,15 +122,14 @@ class CompilationInfo {
kCompilingForDebugging = 1 << 7,
kSerializing = 1 << 8,
kContextSpecializing = 1 << 9,
kFrameSpecializing = 1 << 10,
kInliningEnabled = 1 << 11,
kTypingEnabled = 1 << 12,
kDisableFutureOptimization = 1 << 13,
kSplittingEnabled = 1 << 14,
kTypeFeedbackEnabled = 1 << 15,
kDeoptimizationEnabled = 1 << 16,
kSourcePositionsEnabled = 1 << 17,
kFirstCompile = 1 << 18,
kInliningEnabled = 1 << 10,
kTypingEnabled = 1 << 11,
kDisableFutureOptimization = 1 << 12,
kSplittingEnabled = 1 << 13,
kTypeFeedbackEnabled = 1 << 14,
kDeoptimizationEnabled = 1 << 15,
kSourcePositionsEnabled = 1 << 16,
kFirstCompile = 1 << 17,
};
explicit CompilationInfo(ParseInfo* parse_info);
@ -219,10 +217,6 @@ class CompilationInfo {
bool is_context_specializing() const { return GetFlag(kContextSpecializing); }
void MarkAsFrameSpecializing() { SetFlag(kFrameSpecializing); }
bool is_frame_specializing() const { return GetFlag(kFrameSpecializing); }
void MarkAsTypeFeedbackEnabled() { SetFlag(kTypeFeedbackEnabled); }
bool is_type_feedback_enabled() const {
@ -394,8 +388,6 @@ class CompilationInfo {
DCHECK(height >= 0);
osr_expr_stack_height_ = height;
}
JavaScriptFrame* osr_frame() const { return osr_frame_; }
void set_osr_frame(JavaScriptFrame* osr_frame) { osr_frame_ = osr_frame; }
#if DEBUG
void PrintAstForTesting();
@ -500,9 +492,6 @@ class CompilationInfo {
int osr_expr_stack_height_;
// The current OSR frame for specialization or {nullptr}.
JavaScriptFrame* osr_frame_ = nullptr;
Type::FunctionType* function_type_;
DISALLOW_COPY_AND_ASSIGN(CompilationInfo);
@ -673,9 +662,10 @@ class Compiler : public AllStatic {
// In the latter case, return the InOptimizationQueue builtin. On failure,
// return the empty handle.
MUST_USE_RESULT static MaybeHandle<Code> GetOptimizedCode(
Handle<JSFunction> function, Handle<Code> current_code,
ConcurrencyMode mode, BailoutId osr_ast_id = BailoutId::None(),
JavaScriptFrame* osr_frame = nullptr);
Handle<JSFunction> function,
Handle<Code> current_code,
ConcurrencyMode mode,
BailoutId osr_ast_id = BailoutId::None());
// Generate and return code from previously queued optimization job.
// On failure, return the empty handle.

View File

@ -1,69 +0,0 @@
// Copyright 2015 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/js-frame-specialization.h"
#include "src/compiler/js-graph.h"
#include "src/compiler/linkage.h"
#include "src/frames-inl.h"
namespace v8 {
namespace internal {
namespace compiler {
Reduction JSFrameSpecialization::Reduce(Node* node) {
switch (node->opcode()) {
case IrOpcode::kOsrValue:
return ReduceOsrValue(node);
case IrOpcode::kParameter:
return ReduceParameter(node);
default:
break;
}
return NoChange();
}
Reduction JSFrameSpecialization::ReduceOsrValue(Node* node) {
DCHECK_EQ(IrOpcode::kOsrValue, node->opcode());
DisallowHeapAllocation no_gc;
Object* object;
int const index = OpParameter<int>(node);
int const parameters_count = frame()->ComputeParametersCount() + 1;
if (index == Linkage::kOsrContextSpillSlotIndex) {
object = frame()->context();
} else if (index >= parameters_count) {
object = frame()->GetExpression(index - parameters_count);
} else {
// The OsrValue index 0 is the receiver.
object = index ? frame()->GetParameter(index - 1) : frame()->receiver();
}
return Replace(jsgraph()->Constant(handle(object, isolate())));
}
Reduction JSFrameSpecialization::ReduceParameter(Node* node) {
DCHECK_EQ(IrOpcode::kParameter, node->opcode());
DisallowHeapAllocation no_gc;
Object* object;
int const index = ParameterIndexOf(node->op());
int const parameters_count = frame()->ComputeParametersCount() + 1;
if (index == Linkage::kJSFunctionCallClosureParamIndex) {
object = frame()->function();
} else if (index == parameters_count) {
// The Parameter index (arity + 1) is the context.
object = frame()->context();
} else {
// The Parameter index 0 is the receiver.
object = index ? frame()->GetParameter(index - 1) : frame()->receiver();
}
return Replace(jsgraph()->Constant(handle(object, isolate())));
}
Isolate* JSFrameSpecialization::isolate() const { return jsgraph()->isolate(); }
} // namespace compiler
} // namespace internal
} // namespace v8

View File

@ -1,44 +0,0 @@
// Copyright 2015 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.
#ifndef V8_COMPILER_JS_FRAME_SPECIALIZATION_H_
#define V8_COMPILER_JS_FRAME_SPECIALIZATION_H_
#include "src/compiler/graph-reducer.h"
namespace v8 {
namespace internal {
namespace compiler {
// Forward declarations.
class JSGraph;
class JSFrameSpecialization final : public Reducer {
public:
JSFrameSpecialization(JavaScriptFrame const* frame, JSGraph* jsgraph)
: frame_(frame), jsgraph_(jsgraph) {}
~JSFrameSpecialization() final {}
Reduction Reduce(Node* node) final;
private:
Reduction ReduceOsrValue(Node* node);
Reduction ReduceParameter(Node* node);
Isolate* isolate() const;
JavaScriptFrame const* frame() const { return frame_; }
JSGraph* jsgraph() const { return jsgraph_; }
JavaScriptFrame const* const frame_;
JSGraph* const jsgraph_;
DISALLOW_COPY_AND_ASSIGN(JSFrameSpecialization);
};
} // namespace compiler
} // namespace internal
} // namespace v8
#endif // V8_COMPILER_JS_FRAME_SPECIALIZATION_H_

View File

@ -249,6 +249,40 @@ static void PeelOuterLoopsForOsr(Graph* graph, CommonOperatorBuilder* common,
}
static void TransferOsrValueTypesFromLoopPhis(Zone* zone, Node* osr_loop_entry,
Node* osr_loop) {
// Find the index of the osr loop entry into the loop.
int index = 0;
for (index = 0; index < osr_loop->InputCount(); index++) {
if (osr_loop->InputAt(index) == osr_loop_entry) break;
}
if (index == osr_loop->InputCount()) return;
for (Node* osr_value : osr_loop_entry->uses()) {
if (osr_value->opcode() != IrOpcode::kOsrValue) continue;
bool unknown = true;
for (Node* phi : osr_value->uses()) {
if (phi->opcode() != IrOpcode::kPhi) continue;
if (NodeProperties::GetControlInput(phi) != osr_loop) continue;
if (phi->InputAt(index) != osr_value) continue;
if (NodeProperties::IsTyped(phi)) {
// Transfer the type from the phi to the OSR value itself.
Bounds phi_bounds = NodeProperties::GetBounds(phi);
if (unknown) {
NodeProperties::SetBounds(osr_value, phi_bounds);
} else {
Bounds osr_bounds = NodeProperties::GetBounds(osr_value);
NodeProperties::SetBounds(osr_value,
Bounds::Both(phi_bounds, osr_bounds, zone));
}
unknown = false;
}
}
if (unknown) NodeProperties::SetBounds(osr_value, Bounds::Unbounded(zone));
}
}
void OsrHelper::Deconstruct(JSGraph* jsgraph, CommonOperatorBuilder* common,
Zone* tmp_zone) {
Graph* graph = jsgraph->graph();
@ -279,6 +313,9 @@ void OsrHelper::Deconstruct(JSGraph* jsgraph, CommonOperatorBuilder* common,
CHECK(osr_loop); // Should have found the OSR loop.
// Transfer the types from loop phis to the OSR values which flow into them.
TransferOsrValueTypesFromLoopPhis(graph->zone(), osr_loop_entry, osr_loop);
// Analyze the graph to determine how deeply nested the OSR loop is.
LoopTree* loop_tree = LoopFinder::BuildLoopTree(graph, tmp_zone);

View File

@ -26,7 +26,6 @@
#include "src/compiler/instruction-selector.h"
#include "src/compiler/js-builtin-reducer.h"
#include "src/compiler/js-context-specialization.h"
#include "src/compiler/js-frame-specialization.h"
#include "src/compiler/js-generic-lowering.h"
#include "src/compiler/js-inlining.h"
#include "src/compiler/js-intrinsic-lowering.h"
@ -497,17 +496,12 @@ struct InliningPhase {
CommonOperatorReducer common_reducer(&graph_reducer, data->graph(),
data->common(), data->machine());
JSContextSpecializer context_specializer(&graph_reducer, data->jsgraph());
JSFrameSpecialization frame_specialization(data->info()->osr_frame(),
data->jsgraph());
JSInliner inliner(&graph_reducer, data->info()->is_inlining_enabled()
? JSInliner::kGeneralInlining
: JSInliner::kRestrictedInlining,
temp_zone, data->info(), data->jsgraph());
AddReducer(data, &graph_reducer, &dead_code_elimination);
AddReducer(data, &graph_reducer, &common_reducer);
if (data->info()->is_frame_specializing()) {
AddReducer(data, &graph_reducer, &frame_specialization);
}
if (data->info()->is_context_specializing()) {
AddReducer(data, &graph_reducer, &context_specializer);
}
@ -1041,12 +1035,6 @@ Handle<Code> Pipeline::GenerateCode() {
if (data.compilation_failed()) return Handle<Code>::null();
RunPrintAndVerify("Initial untyped", true);
// Perform OSR deconstruction.
if (info()->is_osr()) {
Run<OsrDeconstructionPhase>();
RunPrintAndVerify("OSR deconstruction", true);
}
// Perform context specialization and inlining (if enabled).
Run<InliningPhase>();
RunPrintAndVerify("Inlined", true);
@ -1083,6 +1071,11 @@ Handle<Code> Pipeline::GenerateCode() {
RunPrintAndVerify("Loop peeled");
}
if (info()->is_osr()) {
Run<OsrDeconstructionPhase>();
RunPrintAndVerify("OSR deconstruction");
}
if (info()->is_type_feedback_enabled()) {
Run<JSTypeFeedbackPhase>();
RunPrintAndVerify("JSType feedback");
@ -1102,6 +1095,12 @@ Handle<Code> Pipeline::GenerateCode() {
Run<ChangeLoweringPhase>();
// TODO(jarin, rossberg): Remove UNTYPED once machine typing works.
RunPrintAndVerify("Lowered changes", true);
} else {
if (info()->is_osr()) {
Run<OsrDeconstructionPhase>();
if (info()->bailout_reason() != kNoReason) return Handle<Code>::null();
RunPrintAndVerify("OSR deconstruction", true);
}
}
// Lower any remaining generic JSOperators.

View File

@ -582,6 +582,16 @@ Bounds Typer::Visitor::TypeParameter(Node* node) {
Bounds Typer::Visitor::TypeOsrValue(Node* node) {
if (node->InputAt(0)->opcode() == IrOpcode::kOsrLoopEntry) {
// Before deconstruction, OSR values have type {None} to avoid polluting
// the types of phis and other nodes in the graph.
return Bounds(Type::None(), Type::None());
}
if (NodeProperties::IsTyped(node)) {
// After deconstruction, OSR values may have had a type explicitly set.
return NodeProperties::GetBounds(node);
}
// Otherwise, be conservative.
return Bounds::Unbounded(zone());
}

View File

@ -219,12 +219,11 @@ RUNTIME_FUNCTION(Runtime_CompileForOnStackReplacement) {
BailoutId ast_id = caller_code->TranslatePcOffsetToAstId(pc_offset);
DCHECK(!ast_id.IsNone());
// Disable concurrent OSR for asm.js, to enable frame specialization.
Compiler::ConcurrencyMode mode = (isolate->concurrent_osr_enabled() &&
!function->shared()->asm_function() &&
function->shared()->ast_node_count() > 512)
? Compiler::CONCURRENT
: Compiler::NOT_CONCURRENT;
Compiler::ConcurrencyMode mode =
isolate->concurrent_osr_enabled() &&
(function->shared()->ast_node_count() > 512)
? Compiler::CONCURRENT
: Compiler::NOT_CONCURRENT;
Handle<Code> result = Handle<Code>::null();
OptimizedCompileJob* job = NULL;
@ -259,9 +258,8 @@ RUNTIME_FUNCTION(Runtime_CompileForOnStackReplacement) {
function->PrintName();
PrintF(" at AST id %d]\n", ast_id.ToInt());
}
MaybeHandle<Code> maybe_result = Compiler::GetOptimizedCode(
function, caller_code, mode, ast_id,
(mode == Compiler::NOT_CONCURRENT) ? frame : nullptr);
MaybeHandle<Code> maybe_result =
Compiler::GetOptimizedCode(function, caller_code, mode, ast_id);
if (maybe_result.ToHandle(&result) &&
result.is_identical_to(isolate->builtins()->InOptimizationQueue())) {
// Optimization is queued. Return to check later.

View File

@ -165,6 +165,30 @@ TEST(Deconstruct_osr1) {
}
TEST(Deconstruct_osr1_type) {
OsrDeconstructorTester T(1);
Node* loop = T.NewOsrLoop(1);
Node* osr_phi =
T.NewOsrPhi(loop, T.jsgraph.OneConstant(), 0, T.jsgraph.ZeroConstant());
Type* type = Type::Signed32();
NodeProperties::SetBounds(osr_phi, Bounds(type, type));
Node* ret = T.graph.NewNode(T.common.Return(), osr_phi, T.start, loop);
T.graph.SetEnd(ret);
OsrHelper helper(0, 0);
helper.Deconstruct(&T.jsgraph, &T.common, T.main_zone());
CHECK_EQ(type, NodeProperties::GetBounds(T.osr_values[0]).lower);
CHECK_EQ(type, NodeProperties::GetBounds(T.osr_values[0]).upper);
CheckInputs(loop, T.start, loop);
CheckInputs(osr_phi, T.osr_values[0], T.jsgraph.ZeroConstant(), loop);
CheckInputs(ret, osr_phi, T.start, loop);
}
TEST(Deconstruct_osr_remove_prologue) {
OsrDeconstructorTester T(1);
Diamond d(&T.graph, &T.common, T.p0);

View File

@ -505,8 +505,6 @@
'../../src/compiler/js-builtin-reducer.h',
'../../src/compiler/js-context-specialization.cc',
'../../src/compiler/js-context-specialization.h',
'../../src/compiler/js-frame-specialization.cc',
'../../src/compiler/js-frame-specialization.h',
'../../src/compiler/js-generic-lowering.cc',
'../../src/compiler/js-generic-lowering.h',
'../../src/compiler/js-graph.cc',