[compiler] Better description of compiler API.

This adds more comments to the V8 compiler API explaining the entry
methods within that API. It also establishes a separate method for OSR
compilation since {Compiler::GetOptimizedCode} is only used for OSR by
now.

R=danno@chromium.org

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

Cr-Commit-Position: refs/heads/master@{#34503}
This commit is contained in:
mstarzinger 2016-03-04 08:10:55 -08:00 committed by Commit bot
parent 12b196490f
commit 970f1ae610
3 changed files with 119 additions and 90 deletions

View File

@ -1030,6 +1030,79 @@ MaybeHandle<Code> GetUnoptimizedCode(Handle<JSFunction> function) {
return result;
}
MaybeHandle<Code> GetOptimizedCode(Handle<JSFunction> function,
Compiler::ConcurrencyMode mode,
BailoutId osr_ast_id = BailoutId::None(),
JavaScriptFrame* osr_frame = nullptr) {
Isolate* isolate = function->GetIsolate();
Handle<SharedFunctionInfo> shared(function->shared(), isolate);
if (shared->HasDebugInfo()) return MaybeHandle<Code>();
Handle<Code> cached_code;
if (GetCodeFromOptimizedCodeMap(function, osr_ast_id)
.ToHandle(&cached_code)) {
if (FLAG_trace_opt) {
PrintF("[found optimized code for ");
function->ShortPrint();
if (!osr_ast_id.IsNone()) {
PrintF(" at OSR AST id %d", osr_ast_id.ToInt());
}
PrintF("]\n");
}
return cached_code;
}
DCHECK(AllowCompilation::IsAllowed(isolate));
Handle<Code> current_code(shared->code());
if (!shared->is_compiled() ||
shared->scope_info() == ScopeInfo::Empty(isolate)) {
// The function was never compiled. Compile it unoptimized first.
// TODO(titzer): reuse the AST and scope info from this compile.
CompilationInfoWithZone unoptimized(function);
unoptimized.EnableDeoptimizationSupport();
if (!GetUnoptimizedCodeCommon(&unoptimized).ToHandle(&current_code)) {
return MaybeHandle<Code>();
}
shared->ReplaceCode(*current_code);
}
current_code->set_profiler_ticks(0);
// TODO(mstarzinger): We cannot properly deserialize a scope chain containing
// an eval scope and hence would fail at parsing the eval source again.
if (shared->disable_optimization_reason() == kEval) {
return MaybeHandle<Code>();
}
// TODO(mstarzinger): We cannot properly deserialize a scope chain for the
// builtin context, hence Genesis::InstallExperimentalNatives would fail.
if (shared->is_toplevel() && isolate->bootstrapper()->IsActive()) {
return MaybeHandle<Code>();
}
base::SmartPointer<CompilationInfo> info(
new CompilationInfoWithZone(function));
VMState<COMPILER> state(isolate);
DCHECK(!isolate->has_pending_exception());
PostponeInterruptsScope postpone(isolate);
info->SetOptimizingForOsr(osr_ast_id, current_code);
if (mode == Compiler::CONCURRENT) {
if (GetOptimizedCodeLater(info.get())) {
info.Detach(); // The background recompile job owns this now.
return isolate->builtins()->InOptimizationQueue();
}
} else {
info->set_osr_frame(osr_frame);
if (GetOptimizedCodeNow(info.get())) return info->code();
}
if (isolate->has_pending_exception()) isolate->clear_pending_exception();
return MaybeHandle<Code>();
}
MaybeHandle<Code> GetLazyCode(Handle<JSFunction> function) {
Isolate* isolate = function->GetIsolate();
DCHECK(!isolate->has_pending_exception());
@ -1069,7 +1142,7 @@ MaybeHandle<Code> GetLazyCode(Handle<JSFunction> function) {
if (FLAG_always_opt) {
Handle<Code> opt_code;
if (Compiler::GetOptimizedCode(function, Compiler::NOT_CONCURRENT)
if (GetOptimizedCode(function, Compiler::NOT_CONCURRENT)
.ToHandle(&opt_code)) {
result = opt_code;
}
@ -1099,7 +1172,7 @@ bool Compiler::Compile(Handle<JSFunction> function, ClearExceptionFlag flag) {
bool Compiler::CompileOptimized(Handle<JSFunction> function,
ConcurrencyMode mode) {
Handle<Code> code;
if (Compiler::GetOptimizedCode(function, mode).ToHandle(&code)) {
if (GetOptimizedCode(function, mode).ToHandle(&code)) {
// Optimization succeeded, return optimized code.
function->ReplaceCode(*code);
} else {
@ -1775,77 +1848,14 @@ Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfoForNative(
return shared;
}
MaybeHandle<Code> Compiler::GetOptimizedCode(Handle<JSFunction> function,
ConcurrencyMode mode,
BailoutId osr_ast_id,
JavaScriptFrame* osr_frame) {
Isolate* isolate = function->GetIsolate();
Handle<SharedFunctionInfo> shared(function->shared(), isolate);
if (shared->HasDebugInfo()) return MaybeHandle<Code>();
Handle<Code> cached_code;
if (GetCodeFromOptimizedCodeMap(
function, osr_ast_id).ToHandle(&cached_code)) {
if (FLAG_trace_opt) {
PrintF("[found optimized code for ");
function->ShortPrint();
if (!osr_ast_id.IsNone()) {
PrintF(" at OSR AST id %d", osr_ast_id.ToInt());
}
PrintF("]\n");
}
return cached_code;
}
DCHECK(AllowCompilation::IsAllowed(isolate));
Handle<Code> current_code(shared->code());
if (!shared->is_compiled() ||
shared->scope_info() == ScopeInfo::Empty(isolate)) {
// The function was never compiled. Compile it unoptimized first.
// TODO(titzer): reuse the AST and scope info from this compile.
CompilationInfoWithZone unoptimized(function);
unoptimized.EnableDeoptimizationSupport();
if (!GetUnoptimizedCodeCommon(&unoptimized).ToHandle(&current_code)) {
return MaybeHandle<Code>();
}
shared->ReplaceCode(*current_code);
}
current_code->set_profiler_ticks(0);
// TODO(mstarzinger): We cannot properly deserialize a scope chain containing
// an eval scope and hence would fail at parsing the eval source again.
if (shared->disable_optimization_reason() == kEval) {
return MaybeHandle<Code>();
}
// TODO(mstarzinger): We cannot properly deserialize a scope chain for the
// builtin context, hence Genesis::InstallExperimentalNatives would fail.
if (shared->is_toplevel() && isolate->bootstrapper()->IsActive()) {
return MaybeHandle<Code>();
}
base::SmartPointer<CompilationInfo> info(
new CompilationInfoWithZone(function));
VMState<COMPILER> state(isolate);
DCHECK(!isolate->has_pending_exception());
PostponeInterruptsScope postpone(isolate);
info->SetOptimizingForOsr(osr_ast_id, current_code);
if (mode == CONCURRENT) {
if (GetOptimizedCodeLater(info.get())) {
info.Detach(); // The background recompile job owns this now.
return isolate->builtins()->InOptimizationQueue();
}
} else {
info->set_osr_frame(osr_frame);
if (GetOptimizedCodeNow(info.get())) return info->code();
}
if (isolate->has_pending_exception()) isolate->clear_pending_exception();
return MaybeHandle<Code>();
MaybeHandle<Code> Compiler::GetOptimizedCodeForOSR(
Handle<JSFunction> function, Compiler::ConcurrencyMode mode,
BailoutId osr_ast_id, JavaScriptFrame* osr_frame) {
DCHECK(!osr_ast_id.IsNone());
// TODO(mstarzinger): Once concurrent OSR is removed, the following check
// should hold and can be enabled.
// DCHECK_NOT_NULL(osr_frame);
return GetOptimizedCode(function, mode, osr_ast_id, osr_frame);
}
MaybeHandle<Code> Compiler::GetConcurrentlyOptimizedCode(

View File

@ -571,22 +571,26 @@ class OptimizedCompileJob: public ZoneObject {
};
};
// The V8 compiler
// The V8 compiler API.
//
// This is the central hub for dispatching to the various compilers within V8.
// Logic for which compiler to choose and how to wire compilation results into
// the object heap should be kept inside this class.
//
// General strategy: Source code is translated into an anonymous function w/o
// parameters which then can be executed. If the source code contains other
// functions, they will be compiled and allocated as part of the compilation
// of the source code.
// Please note this interface returns shared function infos. This means you
// need to call Factory::NewFunctionFromSharedFunctionInfo before you have a
// real function with a context.
// functions, they might be compiled and allocated as part of the compilation
// of the source code or deferred for lazy compilation at a later point.
class Compiler : public AllStatic {
public:
enum ConcurrencyMode { NOT_CONCURRENT, CONCURRENT };
// ===========================================================================
// The following family of methods ensures a given function is compiled. The
// general contract is that failures will be reported by returning {false},
// whereas successful compilation ensures the {is_compiled} predicate on the
// given function holds.
static bool Compile(Handle<JSFunction> function, ClearExceptionFlag flag);
static bool CompileOptimized(Handle<JSFunction> function, ConcurrencyMode);
static bool CompileDebugCode(Handle<JSFunction> function);
@ -600,6 +604,15 @@ class Compiler : public AllStatic {
// Adds deoptimization support, requires ParseAndAnalyze.
static bool EnsureDeoptimizationSupport(CompilationInfo* info);
// ===========================================================================
// The following family of methods instantiates new functions for script or
// function literals. The decision whether those functions have been compiled
// is left to the discretion of the compiler.
//
// Please note this interface returns shared function infos. This means you
// need to call Factory::NewFunctionFromSharedFunctionInfo before you have a
// real function with a context.
// Compile a String source within a context for eval.
MUST_USE_RESULT static MaybeHandle<JSFunction> GetFunctionFromEval(
Handle<String> source, Handle<SharedFunctionInfo> outer_info,
@ -629,13 +642,19 @@ class Compiler : public AllStatic {
static Handle<SharedFunctionInfo> GetSharedFunctionInfoForNative(
v8::Extension* extension, Handle<String> name);
// Generate and return optimized code or start a concurrent optimization job.
// In the latter case, return the InOptimizationQueue builtin. On failure,
// return the empty handle.
MUST_USE_RESULT static MaybeHandle<Code> GetOptimizedCode(
Handle<JSFunction> function, ConcurrencyMode mode,
BailoutId osr_ast_id = BailoutId::None(),
JavaScriptFrame* osr_frame = nullptr);
// ===========================================================================
// The following family of methods provides support for OSR. Code generated
// for entry via OSR might not be suitable for normal entry, hence will be
// returned directly to the caller.
//
// Please note this interface is the only part dealing with {Code} objects
// directly. Other methods are agnostic to {Code} and can use an interpreter
// instead of generating JIT code for a function at all.
// Generate and return optimized code for OSR, or empty handle on failure.
MUST_USE_RESULT static MaybeHandle<Code> GetOptimizedCodeForOSR(
Handle<JSFunction> function, ConcurrencyMode mode, BailoutId osr_ast_id,
JavaScriptFrame* osr_frame);
// Generate and return code from previously queued optimization job.
// On failure, return the empty handle.

View File

@ -256,7 +256,7 @@ RUNTIME_FUNCTION(Runtime_CompileForOnStackReplacement) {
function->PrintName();
PrintF(" at AST id %d]\n", ast_id.ToInt());
}
maybe_result = Compiler::GetOptimizedCode(
maybe_result = Compiler::GetOptimizedCodeForOSR(
function, mode, ast_id,
(mode == Compiler::NOT_CONCURRENT) ? frame : nullptr);
Handle<Code> result;