[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:
parent
12b196490f
commit
970f1ae610
156
src/compiler.cc
156
src/compiler.cc
@ -1030,6 +1030,79 @@ MaybeHandle<Code> GetUnoptimizedCode(Handle<JSFunction> function) {
|
|||||||
return result;
|
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(¤t_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) {
|
MaybeHandle<Code> GetLazyCode(Handle<JSFunction> function) {
|
||||||
Isolate* isolate = function->GetIsolate();
|
Isolate* isolate = function->GetIsolate();
|
||||||
DCHECK(!isolate->has_pending_exception());
|
DCHECK(!isolate->has_pending_exception());
|
||||||
@ -1069,7 +1142,7 @@ MaybeHandle<Code> GetLazyCode(Handle<JSFunction> function) {
|
|||||||
|
|
||||||
if (FLAG_always_opt) {
|
if (FLAG_always_opt) {
|
||||||
Handle<Code> opt_code;
|
Handle<Code> opt_code;
|
||||||
if (Compiler::GetOptimizedCode(function, Compiler::NOT_CONCURRENT)
|
if (GetOptimizedCode(function, Compiler::NOT_CONCURRENT)
|
||||||
.ToHandle(&opt_code)) {
|
.ToHandle(&opt_code)) {
|
||||||
result = opt_code;
|
result = opt_code;
|
||||||
}
|
}
|
||||||
@ -1099,7 +1172,7 @@ bool Compiler::Compile(Handle<JSFunction> function, ClearExceptionFlag flag) {
|
|||||||
bool Compiler::CompileOptimized(Handle<JSFunction> function,
|
bool Compiler::CompileOptimized(Handle<JSFunction> function,
|
||||||
ConcurrencyMode mode) {
|
ConcurrencyMode mode) {
|
||||||
Handle<Code> code;
|
Handle<Code> code;
|
||||||
if (Compiler::GetOptimizedCode(function, mode).ToHandle(&code)) {
|
if (GetOptimizedCode(function, mode).ToHandle(&code)) {
|
||||||
// Optimization succeeded, return optimized code.
|
// Optimization succeeded, return optimized code.
|
||||||
function->ReplaceCode(*code);
|
function->ReplaceCode(*code);
|
||||||
} else {
|
} else {
|
||||||
@ -1775,77 +1848,14 @@ Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfoForNative(
|
|||||||
return shared;
|
return shared;
|
||||||
}
|
}
|
||||||
|
|
||||||
MaybeHandle<Code> Compiler::GetOptimizedCode(Handle<JSFunction> function,
|
MaybeHandle<Code> Compiler::GetOptimizedCodeForOSR(
|
||||||
ConcurrencyMode mode,
|
Handle<JSFunction> function, Compiler::ConcurrencyMode mode,
|
||||||
BailoutId osr_ast_id,
|
BailoutId osr_ast_id, JavaScriptFrame* osr_frame) {
|
||||||
JavaScriptFrame* osr_frame) {
|
DCHECK(!osr_ast_id.IsNone());
|
||||||
Isolate* isolate = function->GetIsolate();
|
// TODO(mstarzinger): Once concurrent OSR is removed, the following check
|
||||||
Handle<SharedFunctionInfo> shared(function->shared(), isolate);
|
// should hold and can be enabled.
|
||||||
if (shared->HasDebugInfo()) return MaybeHandle<Code>();
|
// DCHECK_NOT_NULL(osr_frame);
|
||||||
|
return GetOptimizedCode(function, mode, osr_ast_id, osr_frame);
|
||||||
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(¤t_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::GetConcurrentlyOptimizedCode(
|
MaybeHandle<Code> Compiler::GetConcurrentlyOptimizedCode(
|
||||||
|
@ -571,22 +571,26 @@ class OptimizedCompileJob: public ZoneObject {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// The V8 compiler API.
|
||||||
// The V8 compiler
|
//
|
||||||
|
// 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
|
// General strategy: Source code is translated into an anonymous function w/o
|
||||||
// parameters which then can be executed. If the source code contains other
|
// parameters which then can be executed. If the source code contains other
|
||||||
// functions, they will be compiled and allocated as part of the compilation
|
// functions, they might be compiled and allocated as part of the compilation
|
||||||
// of the source code.
|
// of the source code or deferred for lazy compilation at a later point.
|
||||||
|
|
||||||
// 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.
|
|
||||||
|
|
||||||
class Compiler : public AllStatic {
|
class Compiler : public AllStatic {
|
||||||
public:
|
public:
|
||||||
enum ConcurrencyMode { NOT_CONCURRENT, CONCURRENT };
|
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 Compile(Handle<JSFunction> function, ClearExceptionFlag flag);
|
||||||
static bool CompileOptimized(Handle<JSFunction> function, ConcurrencyMode);
|
static bool CompileOptimized(Handle<JSFunction> function, ConcurrencyMode);
|
||||||
static bool CompileDebugCode(Handle<JSFunction> function);
|
static bool CompileDebugCode(Handle<JSFunction> function);
|
||||||
@ -600,6 +604,15 @@ class Compiler : public AllStatic {
|
|||||||
// Adds deoptimization support, requires ParseAndAnalyze.
|
// Adds deoptimization support, requires ParseAndAnalyze.
|
||||||
static bool EnsureDeoptimizationSupport(CompilationInfo* info);
|
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.
|
// Compile a String source within a context for eval.
|
||||||
MUST_USE_RESULT static MaybeHandle<JSFunction> GetFunctionFromEval(
|
MUST_USE_RESULT static MaybeHandle<JSFunction> GetFunctionFromEval(
|
||||||
Handle<String> source, Handle<SharedFunctionInfo> outer_info,
|
Handle<String> source, Handle<SharedFunctionInfo> outer_info,
|
||||||
@ -629,13 +642,19 @@ class Compiler : public AllStatic {
|
|||||||
static Handle<SharedFunctionInfo> GetSharedFunctionInfoForNative(
|
static Handle<SharedFunctionInfo> GetSharedFunctionInfoForNative(
|
||||||
v8::Extension* extension, Handle<String> name);
|
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,
|
// The following family of methods provides support for OSR. Code generated
|
||||||
// return the empty handle.
|
// for entry via OSR might not be suitable for normal entry, hence will be
|
||||||
MUST_USE_RESULT static MaybeHandle<Code> GetOptimizedCode(
|
// returned directly to the caller.
|
||||||
Handle<JSFunction> function, ConcurrencyMode mode,
|
//
|
||||||
BailoutId osr_ast_id = BailoutId::None(),
|
// Please note this interface is the only part dealing with {Code} objects
|
||||||
JavaScriptFrame* osr_frame = nullptr);
|
// 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.
|
// Generate and return code from previously queued optimization job.
|
||||||
// On failure, return the empty handle.
|
// On failure, return the empty handle.
|
||||||
|
@ -256,7 +256,7 @@ RUNTIME_FUNCTION(Runtime_CompileForOnStackReplacement) {
|
|||||||
function->PrintName();
|
function->PrintName();
|
||||||
PrintF(" at AST id %d]\n", ast_id.ToInt());
|
PrintF(" at AST id %d]\n", ast_id.ToInt());
|
||||||
}
|
}
|
||||||
maybe_result = Compiler::GetOptimizedCode(
|
maybe_result = Compiler::GetOptimizedCodeForOSR(
|
||||||
function, mode, ast_id,
|
function, mode, ast_id,
|
||||||
(mode == Compiler::NOT_CONCURRENT) ? frame : nullptr);
|
(mode == Compiler::NOT_CONCURRENT) ? frame : nullptr);
|
||||||
Handle<Code> result;
|
Handle<Code> result;
|
||||||
|
Loading…
Reference in New Issue
Block a user