Commit dea67cf0 authored by mstarzinger's avatar mstarzinger Committed by Commit bot

[compiler] Make OptimizedCompileJob agnostic from backend.

This refactors the OptimizedCompileJob class to be agnostic from the
actual underlying compiler. Instead it represents a base class for all
compilation jobs. The implementation is provided by the backend by just
overriding the phase methods.

Also note that this contains the semantics change of not falling back to
Crankshaft when TurboFan optimization fails. This fallback is no longer
needed and will not be supported going forward.

R=bmeurer@chromium.org

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

Cr-Commit-Position: refs/heads/master@{#35377}
parent 8764f87a
......@@ -88,6 +88,7 @@ namespace internal {
V(kGenerator, "Generator") \
V(kGlobalFunctionsMustHaveInitialMap, \
"Global functions must have initial map") \
V(kGraphBuildingFailed, "Optimized graph construction failed") \
V(kHeapNumberMapRegisterClobbered, "HeapNumberMap register clobbered") \
V(kHydrogenFilter, "Optimization disabled by filter") \
V(kImportDeclaration, "Import declaration") \
......
This diff is collapsed.
......@@ -569,20 +569,21 @@ class CompilationInfo {
DISALLOW_COPY_AND_ASSIGN(CompilationInfo);
};
class HGraph;
class LChunk;
// A helper class that calls the three compilation phases in
// Crankshaft and keeps track of its state. The three phases
// CreateGraph, OptimizeGraph and GenerateAndInstallCode can either
// fail, bail-out to the full code generator or succeed. Apart from
// their return value, the status of the phase last run can be checked
// using last_status().
// A base class for compilation jobs intended to run concurrent to the main
// thread. The job is split into three phases which are called in sequence on
// different threads and with different limitations:
// 1) CreateGraph: Runs on main thread. No major limitations.
// 2) OptimizeGraph: Runs concurrently. No heap allocation or handle derefs.
// 3) GenerateCode: Runs on main thread. No dependency changes.
//
// Each of the three phases can either fail, bail-out to full code generator or
// succeed. Apart from their return value, the status of the phase last run can
// be checked using {last_status()} as well.
class OptimizedCompileJob: public ZoneObject {
public:
explicit OptimizedCompileJob(CompilationInfo* info)
: info_(info), graph_(NULL), chunk_(NULL), last_status_(FAILED) {}
: info_(info), last_status_(SUCCEEDED) {}
virtual ~OptimizedCompileJob() {}
enum Status {
FAILED, BAILED_OUT, SUCCEEDED
......@@ -606,10 +607,18 @@ class OptimizedCompileJob: public ZoneObject {
return SetLastStatus(BAILED_OUT);
}
void RecordOptimizationStats();
protected:
void RegisterWeakObjectsInOptimizedCode(Handle<Code> code);
// Overridden by the actual implementation.
virtual Status CreateGraphImpl() = 0;
virtual Status OptimizeGraphImpl() = 0;
virtual Status GenerateCodeImpl() = 0;
private:
CompilationInfo* info_;
HGraph* graph_;
LChunk* chunk_;
base::TimeDelta time_taken_to_create_graph_;
base::TimeDelta time_taken_to_optimize_;
base::TimeDelta time_taken_to_codegen_;
......@@ -619,23 +628,6 @@ class OptimizedCompileJob: public ZoneObject {
last_status_ = status;
return last_status_;
}
void RecordOptimizationStats();
struct Timer {
Timer(OptimizedCompileJob* job, base::TimeDelta* location)
: job_(job), location_(location) {
DCHECK(location_ != NULL);
timer_.Start();
}
~Timer() {
*location_ += timer_.Elapsed();
}
OptimizedCompileJob* job_;
base::ElapsedTimer timer_;
base::TimeDelta* location_;
};
};
} // namespace internal
......
......@@ -19,15 +19,15 @@
#include "src/compiler/common-operator-reducer.h"
#include "src/compiler/control-flow-optimizer.h"
#include "src/compiler/dead-code-elimination.h"
#include "src/compiler/escape-analysis.h"
#include "src/compiler/escape-analysis-reducer.h"
#include "src/compiler/escape-analysis.h"
#include "src/compiler/frame-elider.h"
#include "src/compiler/graph-replay.h"
#include "src/compiler/graph-trimmer.h"
#include "src/compiler/graph-visualizer.h"
#include "src/compiler/greedy-allocator.h"
#include "src/compiler/instruction.h"
#include "src/compiler/instruction-selector.h"
#include "src/compiler/instruction.h"
#include "src/compiler/js-builtin-reducer.h"
#include "src/compiler/js-call-reducer.h"
#include "src/compiler/js-context-specialization.h"
......@@ -48,20 +48,21 @@
#include "src/compiler/move-optimizer.h"
#include "src/compiler/osr.h"
#include "src/compiler/pipeline-statistics.h"
#include "src/compiler/register-allocator.h"
#include "src/compiler/register-allocator-verifier.h"
#include "src/compiler/register-allocator.h"
#include "src/compiler/schedule.h"
#include "src/compiler/scheduler.h"
#include "src/compiler/select-lowering.h"
#include "src/compiler/simplified-lowering.h"
#include "src/compiler/simplified-operator.h"
#include "src/compiler/simplified-operator-reducer.h"
#include "src/compiler/simplified-operator.h"
#include "src/compiler/tail-call-optimization.h"
#include "src/compiler/type-hint-analyzer.h"
#include "src/compiler/typer.h"
#include "src/compiler/value-numbering-reducer.h"
#include "src/compiler/verifier.h"
#include "src/compiler/zone-pool.h"
#include "src/isolate-inl.h"
#include "src/ostreams.h"
#include "src/register-configuration.h"
#include "src/type-info.h"
......@@ -476,6 +477,67 @@ class PipelineRunScope {
ZonePool::Scope zone_scope_;
};
class PipelineCompilationJob : public OptimizedCompileJob {
public:
explicit PipelineCompilationJob(CompilationInfo* info)
: OptimizedCompileJob(info) {}
protected:
virtual Status CreateGraphImpl();
virtual Status OptimizeGraphImpl();
virtual Status GenerateCodeImpl();
};
PipelineCompilationJob::Status PipelineCompilationJob::CreateGraphImpl() {
if (FLAG_trace_opt) {
OFStream os(stdout);
os << "[compiling method " << Brief(*info()->closure())
<< " using TurboFan";
if (info()->is_osr()) os << " OSR";
os << "]" << std::endl;
}
if (info()->shared_info()->asm_function()) {
if (info()->osr_frame()) info()->MarkAsFrameSpecializing();
info()->MarkAsFunctionContextSpecializing();
} else {
if (!FLAG_always_opt) {
info()->MarkAsBailoutOnUninitialized();
}
if (FLAG_native_context_specialization) {
info()->MarkAsNativeContextSpecializing();
info()->MarkAsTypingEnabled();
}
}
if (!info()->shared_info()->asm_function() || FLAG_turbo_asm_deoptimization) {
info()->MarkAsDeoptimizationEnabled();
}
Pipeline pipeline(info());
pipeline.GenerateCode();
if (isolate()->has_pending_exception()) return FAILED; // Stack overflowed.
if (info()->code().is_null()) return AbortOptimization(kGraphBuildingFailed);
return SUCCEEDED;
}
PipelineCompilationJob::Status PipelineCompilationJob::OptimizeGraphImpl() {
// TODO(turbofan): Currently everything is done in the first phase.
DCHECK(!info()->code().is_null());
return SUCCEEDED;
}
PipelineCompilationJob::Status PipelineCompilationJob::GenerateCodeImpl() {
// TODO(turbofan): Currently everything is done in the first phase.
DCHECK(!info()->code().is_null());
info()->dependencies()->Commit(info()->code());
if (info()->is_deoptimization_enabled()) {
info()->context()->native_context()->AddOptimizedCode(*info()->code());
RegisterWeakObjectsInOptimizedCode(info()->code());
}
return SUCCEEDED;
}
} // namespace
......@@ -1313,6 +1375,9 @@ Handle<Code> Pipeline::GenerateCodeForTesting(CompilationInfo* info,
return pipeline.ScheduleAndGenerateCode(call_descriptor);
}
OptimizedCompileJob* Pipeline::NewCompilationJob(CompilationInfo* info) {
return new (info->zone()) PipelineCompilationJob(info);
}
bool Pipeline::AllocateRegistersForTesting(const RegisterConfiguration* config,
InstructionSequence* sequence,
......
......@@ -13,6 +13,7 @@ namespace v8 {
namespace internal {
class CompilationInfo;
class OptimizedCompileJob;
class RegisterConfiguration;
namespace compiler {
......@@ -26,7 +27,7 @@ class Schedule;
class Pipeline {
public:
explicit Pipeline(CompilationInfo* info) : info_(info) {}
explicit Pipeline(CompilationInfo* info) : info_(info), data_(nullptr) {}
// Run the entire pipeline and generate a handle to a code object.
Handle<Code> GenerateCode();
......@@ -57,6 +58,9 @@ class Pipeline {
Graph* graph,
Schedule* schedule = nullptr);
// Returns a new compilation job for the given compilation info.
static OptimizedCompileJob* NewCompilationJob(CompilationInfo* info);
private:
// Helpers for executing pipeline phases.
template <typename Phase>
......
......@@ -68,6 +68,153 @@
namespace v8 {
namespace internal {
class HOptimizedGraphBuilderWithPositions : public HOptimizedGraphBuilder {
public:
explicit HOptimizedGraphBuilderWithPositions(CompilationInfo* info)
: HOptimizedGraphBuilder(info) {}
#define DEF_VISIT(type) \
void Visit##type(type* node) override { \
SourcePosition old_position = SourcePosition::Unknown(); \
if (node->position() != RelocInfo::kNoPosition) { \
old_position = source_position(); \
SetSourcePosition(node->position()); \
} \
HOptimizedGraphBuilder::Visit##type(node); \
if (!old_position.IsUnknown()) { \
set_source_position(old_position); \
} \
}
EXPRESSION_NODE_LIST(DEF_VISIT)
#undef DEF_VISIT
#define DEF_VISIT(type) \
void Visit##type(type* node) override { \
SourcePosition old_position = SourcePosition::Unknown(); \
if (node->position() != RelocInfo::kNoPosition) { \
old_position = source_position(); \
SetSourcePosition(node->position()); \
} \
HOptimizedGraphBuilder::Visit##type(node); \
if (!old_position.IsUnknown()) { \
set_source_position(old_position); \
} \
}
STATEMENT_NODE_LIST(DEF_VISIT)
#undef DEF_VISIT
#define DEF_VISIT(type) \
void Visit##type(type* node) override { \
HOptimizedGraphBuilder::Visit##type(node); \
}
DECLARATION_NODE_LIST(DEF_VISIT)
#undef DEF_VISIT
};
HCompilationJob::Status HCompilationJob::CreateGraphImpl() {
bool dont_crankshaft = info()->shared_info()->dont_crankshaft();
if (!isolate()->use_crankshaft() || dont_crankshaft) {
// Crankshaft is entirely disabled.
return FAILED;
}
Scope* scope = info()->scope();
if (LUnallocated::TooManyParameters(scope->num_parameters())) {
// Crankshaft would require too many Lithium operands.
return AbortOptimization(kTooManyParameters);
}
if (info()->is_osr() &&
LUnallocated::TooManyParametersOrStackSlots(scope->num_parameters(),
scope->num_stack_slots())) {
// Crankshaft would require too many Lithium operands.
return AbortOptimization(kTooManyParametersLocals);
}
if (FLAG_trace_opt) {
OFStream os(stdout);
os << "[compiling method " << Brief(*info()->closure())
<< " using Crankshaft";
if (info()->is_osr()) os << " OSR";
os << "]" << std::endl;
}
if (FLAG_trace_hydrogen) {
isolate()->GetHTracer()->TraceCompilation(info());
}
// Type-check the function.
AstTyper(info()->isolate(), info()->zone(), info()->closure(),
info()->scope(), info()->osr_ast_id(), info()->literal())
.Run();
// Optimization could have been disabled by the parser. Note that this check
// is only needed because the Hydrogen graph builder is missing some bailouts.
if (info()->shared_info()->optimization_disabled()) {
return AbortOptimization(
info()->shared_info()->disable_optimization_reason());
}
HOptimizedGraphBuilder* graph_builder =
(info()->is_tracking_positions() || FLAG_trace_ic)
? new (info()->zone()) HOptimizedGraphBuilderWithPositions(info())
: new (info()->zone()) HOptimizedGraphBuilder(info());
graph_ = graph_builder->CreateGraph();
if (isolate()->has_pending_exception()) {
return FAILED;
}
if (graph_ == NULL) return BAILED_OUT;
if (info()->dependencies()->HasAborted()) {
// Dependency has changed during graph creation. Let's try again later.
return RetryOptimization(kBailedOutDueToDependencyChange);
}
return SUCCEEDED;
}
HCompilationJob::Status HCompilationJob::OptimizeGraphImpl() {
DCHECK(graph_ != NULL);
BailoutReason bailout_reason = kNoReason;
if (graph_->Optimize(&bailout_reason)) {
chunk_ = LChunk::NewChunk(graph_);
if (chunk_ != NULL) return SUCCEEDED;
} else if (bailout_reason != kNoReason) {
info()->AbortOptimization(bailout_reason);
}
return BAILED_OUT;
}
HCompilationJob::Status HCompilationJob::GenerateCodeImpl() {
DCHECK(chunk_ != NULL);
DCHECK(graph_ != NULL);
{
// Deferred handles reference objects that were accessible during
// graph creation. To make sure that we don't encounter inconsistencies
// between graph creation and code generation, we disallow accessing
// objects through deferred handles during the latter, with exceptions.
DisallowDeferredHandleDereference no_deferred_handle_deref;
Handle<Code> optimized_code = chunk_->Codegen();
if (optimized_code.is_null()) {
if (info()->bailout_reason() == kNoReason) {
return AbortOptimization(kCodeGenerationFailed);
}
return BAILED_OUT;
}
RegisterWeakObjectsInOptimizedCode(optimized_code);
info()->SetCode(optimized_code);
}
// Add to the weak list of optimized code objects.
info()->context()->native_context()->AddOptimizedCode(*info()->code());
return SUCCEEDED;
}
HBasicBlock::HBasicBlock(HGraph* graph)
: block_id_(graph->GetNextBlockID()),
graph_(graph),
......
......@@ -30,6 +30,20 @@ class LAllocator;
class LChunk;
class LiveRange;
class HCompilationJob final : public OptimizedCompileJob {
public:
explicit HCompilationJob(CompilationInfo* info)
: OptimizedCompileJob(info), graph_(nullptr), chunk_(nullptr) {}
protected:
virtual Status CreateGraphImpl();
virtual Status OptimizeGraphImpl();
virtual Status GenerateCodeImpl();
private:
HGraph* graph_;
LChunk* chunk_;
};
class HBasicBlock final : public ZoneObject {
public:
......
......@@ -12,6 +12,8 @@
namespace v8 {
namespace internal {
class HGraph;
class LChunk;
class LEnvironment;
class LInstruction;
class LPlatformChunk;
......
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