[compiler] Untangle CompilationInfo allocated with new.

This removes the CompilationInfoWithZone class, which was used to
allocate a CompilationInfo on the C-heap. By now the CompilationJob is
the single object being allocated on the C-heap and passed between the
main thread and the compilation thread. Structs requiring destruction
can be embedded within that CompilationJob. This simplifies involved
lifetimes by coupling all lifetimes to one single object.

R=bmeurer@chromium.org

Review-Url: https://codereview.chromium.org/1930773003
Cr-Commit-Position: refs/heads/master@{#35936}
This commit is contained in:
mstarzinger 2016-05-02 07:44:29 -07:00 committed by Commit bot
parent 81db29dd10
commit 601ee4ebf4
6 changed files with 58 additions and 75 deletions

View File

@ -77,28 +77,6 @@ class CompilationHandleScope BASE_EMBEDDED {
CompilationInfo* info_;
};
// Exactly like a CompilationInfo, except being allocated via {new} and it also
// creates and enters a Zone on construction and deallocates it on destruction.
class CompilationInfoWithZone : public CompilationInfo {
public:
explicit CompilationInfoWithZone(Handle<JSFunction> function)
: CompilationInfo(new ParseInfo(&zone_, function), function),
zone_(function->GetIsolate()->allocator()) {}
// Virtual destructor because a CompilationInfoWithZone has to exit the
// zone scope and get rid of dependent maps even when the destructor is
// called when cast as a CompilationInfo.
virtual ~CompilationInfoWithZone() {
DisableFutureOptimization();
dependencies()->Rollback();
delete parse_info_;
parse_info_ = nullptr;
}
private:
Zone zone_;
};
// Helper that times a scoped region and records the elapsed time.
struct ScopedTimer {
explicit ScopedTimer(base::TimeDelta* location) : location_(location) {
@ -168,12 +146,8 @@ CompilationInfo::CompilationInfo(ParseInfo* parse_info,
CompilationInfo::~CompilationInfo() {
DisableFutureOptimization();
dependencies()->Rollback();
delete deferred_handles_;
#ifdef DEBUG
// Check that no dependent maps have been added or added dependent maps have
// been rolled back or committed.
DCHECK(dependencies()->IsEmpty());
#endif // DEBUG
}
@ -669,15 +643,14 @@ bool Renumber(ParseInfo* parse_info) {
return true;
}
bool UseTurboFan(CompilationInfo* info) {
bool optimization_disabled = info->shared_info()->optimization_disabled();
bool dont_crankshaft = info->shared_info()->dont_crankshaft();
bool UseTurboFan(Handle<SharedFunctionInfo> shared, BailoutId osr_ast_id) {
bool optimization_disabled = shared->optimization_disabled();
bool dont_crankshaft = shared->dont_crankshaft();
// Check the enabling conditions for Turbofan.
// 1. "use asm" code.
bool is_turbofanable_asm = FLAG_turbo_asm &&
info->shared_info()->asm_function() &&
!optimization_disabled;
bool is_turbofanable_asm =
FLAG_turbo_asm && shared->asm_function() && !optimization_disabled;
// 2. Fallback for features unsupported by Crankshaft.
bool is_unsupported_by_crankshaft_but_turbofanable =
@ -685,11 +658,10 @@ bool UseTurboFan(CompilationInfo* info) {
!optimization_disabled;
// 3. Explicitly enabled by the command-line filter.
bool passes_turbo_filter =
info->shared_info()->PassesFilter(FLAG_turbo_filter);
bool passes_turbo_filter = shared->PassesFilter(FLAG_turbo_filter);
// If this is OSR request, OSR must be enabled by Turbofan.
bool passes_osr_test = FLAG_turbo_osr || !info->is_osr();
bool passes_osr_test = FLAG_turbo_osr || osr_ast_id.IsNone();
return (is_turbofanable_asm ||
is_unsupported_by_crankshaft_but_turbofanable ||
@ -800,11 +772,14 @@ MaybeHandle<Code> GetOptimizedCode(Handle<JSFunction> function,
return MaybeHandle<Code>();
}
base::SmartPointer<CompilationInfo> info(
new CompilationInfoWithZone(function));
VMState<COMPILER> state(isolate);
DCHECK(!isolate->has_pending_exception());
PostponeInterruptsScope postpone(isolate);
bool use_turbofan = UseTurboFan(shared, osr_ast_id);
base::SmartPointer<CompilationJob> job(
use_turbofan ? compiler::Pipeline::NewCompilationJob(function)
: new HCompilationJob(function));
CompilationInfo* info = job->info();
info->SetOptimizingForOsr(osr_ast_id);
@ -833,12 +808,7 @@ MaybeHandle<Code> GetOptimizedCode(Handle<JSFunction> function,
TimerEventScope<TimerEventOptimizeCode> optimize_code_timer(isolate);
TRACE_EVENT0("v8", "V8.OptimizeCode");
bool use_turbofan = UseTurboFan(info.get());
base::SmartPointer<CompilationJob> job(
use_turbofan ? compiler::Pipeline::NewCompilationJob(info.get())
: new HCompilationJob(info.get()));
// TruboFan can optimize directly from existing bytecode.
// TurboFan can optimize directly from existing bytecode.
if (FLAG_turbo_from_bytecode && use_turbofan &&
info->shared_info()->HasBytecodeArray()) {
info->MarkAsOptimizeFromBytecode();
@ -846,7 +816,6 @@ MaybeHandle<Code> GetOptimizedCode(Handle<JSFunction> function,
if (mode == Compiler::CONCURRENT) {
if (GetOptimizedCodeLater(job.get())) {
info.Detach(); // The background recompile job owns this now.
job.Detach(); // The background recompile job owns this now.
return isolate->builtins()->InOptimizationQueue();
}
@ -1755,10 +1724,10 @@ MaybeHandle<Code> Compiler::GetOptimizedCodeForOSR(Handle<JSFunction> function,
return GetOptimizedCode(function, NOT_CONCURRENT, osr_ast_id, osr_frame);
}
void Compiler::FinalizeCompilationJob(CompilationJob* job) {
// Take ownership of compilation info. Deleting compilation info
// also tears down the zone.
base::SmartPointer<CompilationInfo> info(job->info());
void Compiler::FinalizeCompilationJob(CompilationJob* raw_job) {
// Take ownership of compilation job. Deleting job also tears down the zone.
base::SmartPointer<CompilationJob> job(raw_job);
CompilationInfo* info = job->info();
Isolate* isolate = info->isolate();
VMState<COMPILER> state(isolate);
@ -1782,10 +1751,10 @@ void Compiler::FinalizeCompilationJob(CompilationJob* job) {
job->RetryOptimization(kBailedOutDueToDependencyChange);
} else if (job->GenerateCode() == CompilationJob::SUCCEEDED) {
job->RecordOptimizationStats();
RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, info.get());
RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, info);
if (shared->SearchOptimizedCodeMap(info->context()->native_context(),
info->osr_ast_id()).code == nullptr) {
InsertCodeIntoOptimizedCodeMap(info.get());
InsertCodeIntoOptimizedCodeMap(info);
}
if (FLAG_trace_opt) {
PrintF("[completed optimizing ");
@ -1793,7 +1762,6 @@ void Compiler::FinalizeCompilationJob(CompilationJob* job) {
PrintF("]\n");
}
info->closure()->ReplaceCode(*info->code());
delete job;
return;
}
}
@ -1805,7 +1773,6 @@ void Compiler::FinalizeCompilationJob(CompilationJob* job) {
PrintF(" because: %s]\n", GetBailoutReason(info->bailout_reason()));
}
info->closure()->ReplaceCode(shared->code());
delete job;
}
void Compiler::PostInstantiation(Handle<JSFunction> function,

View File

@ -139,7 +139,7 @@ struct InlinedFunctionInfo {
// CompilationInfo encapsulates some information known at compile time. It
// is constructed based on the resources available at compile-time.
class CompilationInfo {
class CompilationInfo final {
public:
// Various configuration flags for a compilation, as well as some properties
// of the compiled code produced by a compilation.
@ -167,7 +167,7 @@ class CompilationInfo {
CompilationInfo(ParseInfo* parse_info, Handle<JSFunction> closure);
CompilationInfo(Vector<const char> debug_name, Isolate* isolate, Zone* zone,
Code::Flags code_flags = Code::ComputeFlags(Code::STUB));
virtual ~CompilationInfo();
~CompilationInfo();
ParseInfo* parse_info() const { return parse_info_; }
@ -573,7 +573,6 @@ class CompilationInfo {
// as well. When failing we distinguish between the following levels:
// a) AbortOptimization: Persistent failure, disable future optimization.
// b) RetryOptimzation: Transient failure, try again next time.
// TODO(mstarzinger): Make CompilationInfo base embedded.
class CompilationJob {
public:
explicit CompilationJob(CompilationInfo* info, const char* compiler_name)

View File

@ -65,6 +65,7 @@
#include "src/compiler/zone-pool.h"
#include "src/isolate-inl.h"
#include "src/ostreams.h"
#include "src/parsing/parser.h"
#include "src/register-configuration.h"
#include "src/type-info.h"
#include "src/utils.h"
@ -502,13 +503,18 @@ PipelineStatistics* CreatePipelineStatistics(CompilationInfo* info,
class PipelineCompilationJob final : public CompilationJob {
public:
explicit PipelineCompilationJob(CompilationInfo* info)
: CompilationJob(info, "TurboFan"),
zone_pool_(info->isolate()->allocator()),
pipeline_statistics_(CreatePipelineStatistics(info, &zone_pool_)),
data_(&zone_pool_, info, pipeline_statistics_.get()),
PipelineCompilationJob(Isolate* isolate, Handle<JSFunction> function)
// Note that the CompilationInfo is not initialized at the time we pass it
// to the CompilationJob constructor, but it is not dereferenced there.
: CompilationJob(&info_, "TurboFan"),
zone_(isolate->allocator()),
zone_pool_(isolate->allocator()),
parse_info_(&zone_, function),
info_(&parse_info_, function),
pipeline_statistics_(CreatePipelineStatistics(info(), &zone_pool_)),
data_(&zone_pool_, info(), pipeline_statistics_.get()),
pipeline_(&data_),
linkage_(Linkage::ComputeIncoming(info->zone(), info)) {}
linkage_(nullptr) {}
protected:
Status CreateGraphImpl() final;
@ -516,11 +522,14 @@ class PipelineCompilationJob final : public CompilationJob {
Status GenerateCodeImpl() final;
private:
Zone zone_;
ZonePool zone_pool_;
ParseInfo parse_info_;
CompilationInfo info_;
base::SmartPointer<PipelineStatistics> pipeline_statistics_;
PipelineData data_;
Pipeline pipeline_;
Linkage linkage_;
Linkage* linkage_;
};
PipelineCompilationJob::Status PipelineCompilationJob::CreateGraphImpl() {
@ -542,6 +551,8 @@ PipelineCompilationJob::Status PipelineCompilationJob::CreateGraphImpl() {
if (!Compiler::EnsureDeoptimizationSupport(info())) return FAILED;
}
linkage_ = new (&zone_) Linkage(Linkage::ComputeIncoming(&zone_, info()));
if (!pipeline_.CreateGraph()) {
if (isolate()->has_pending_exception()) return FAILED; // Stack overflowed.
return AbortOptimization(kGraphBuildingFailed);
@ -551,12 +562,12 @@ PipelineCompilationJob::Status PipelineCompilationJob::CreateGraphImpl() {
}
PipelineCompilationJob::Status PipelineCompilationJob::OptimizeGraphImpl() {
if (!pipeline_.OptimizeGraph(&linkage_)) return FAILED;
if (!pipeline_.OptimizeGraph(linkage_)) return FAILED;
return SUCCEEDED;
}
PipelineCompilationJob::Status PipelineCompilationJob::GenerateCodeImpl() {
Handle<Code> code = pipeline_.GenerateCode(&linkage_);
Handle<Code> code = pipeline_.GenerateCode(linkage_);
if (code.is_null()) {
if (info()->bailout_reason() == kNoReason) {
return AbortOptimization(kCodeGenerationFailed);
@ -1523,8 +1534,8 @@ Handle<Code> Pipeline::GenerateCodeForTesting(CompilationInfo* info,
}
// static
CompilationJob* Pipeline::NewCompilationJob(CompilationInfo* info) {
return new PipelineCompilationJob(info);
CompilationJob* Pipeline::NewCompilationJob(Handle<JSFunction> function) {
return new PipelineCompilationJob(function->GetIsolate(), function);
}
// static

View File

@ -72,8 +72,8 @@ class Pipeline {
Graph* graph,
Schedule* schedule = nullptr);
// Returns a new compilation job for the given compilation info.
static CompilationJob* NewCompilationJob(CompilationInfo* info);
// Returns a new compilation job for the given function.
static CompilationJob* NewCompilationJob(Handle<JSFunction> function);
// Returns a new compilation job for the WebAssembly compilation info.
static CompilationJob* NewWasmCompilationJob(

View File

@ -13,6 +13,7 @@
#include "src/compiler.h"
#include "src/crankshaft/compilation-phase.h"
#include "src/crankshaft/hydrogen-instructions.h"
#include "src/parsing/parser.h"
#include "src/zone.h"
namespace v8 {
@ -32,8 +33,13 @@ class LiveRange;
class HCompilationJob final : public CompilationJob {
public:
explicit HCompilationJob(CompilationInfo* info)
: CompilationJob(info, "Crankshaft"), graph_(nullptr), chunk_(nullptr) {}
explicit HCompilationJob(Handle<JSFunction> function)
: CompilationJob(&info_, "Crankshaft"),
zone_(function->GetIsolate()->allocator()),
parse_info_(&zone_, function),
info_(&parse_info_, function),
graph_(nullptr),
chunk_(nullptr) {}
protected:
virtual Status CreateGraphImpl();
@ -41,6 +47,9 @@ class HCompilationJob final : public CompilationJob {
virtual Status GenerateCodeImpl();
private:
Zone zone_;
ParseInfo parse_info_;
CompilationInfo info_;
HGraph* graph_;
LChunk* chunk_;
};

View File

@ -16,14 +16,11 @@ namespace internal {
namespace {
void DisposeCompilationJob(CompilationJob* job, bool restore_function_code) {
// The recompile job is allocated in the CompilationInfo's zone.
CompilationInfo* info = job->info();
if (restore_function_code) {
Handle<JSFunction> function = info->closure();
Handle<JSFunction> function = job->info()->closure();
function->ReplaceCode(function->shared()->code());
}
delete job;
delete info;
}
} // namespace