a704cc7932
Refactors CompileUnoptimizedCode to do all the finalization for both inner and the outermost function after having prepared and executed their compile jobs. This will enable the function to be split into an off-thread phase and a finalization main thread phase. BUG=v8:5203 Change-Id: I400933c27b7aa52f9a7318b721adecfc94c80981 Reviewed-on: https://chromium-review.googlesource.com/602236 Commit-Queue: Ross McIlroy <rmcilroy@chromium.org> Reviewed-by: Andreas Haas <ahaas@chromium.org> Reviewed-by: Michael Starzinger <mstarzinger@chromium.org> Cr-Commit-Position: refs/heads/master@{#47199}
244 lines
10 KiB
C++
244 lines
10 KiB
C++
// Copyright 2012 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_H_
|
|
#define V8_COMPILER_H_
|
|
|
|
#include <memory>
|
|
|
|
#include "src/allocation.h"
|
|
#include "src/bailout-reason.h"
|
|
#include "src/contexts.h"
|
|
#include "src/isolate.h"
|
|
#include "src/zone/zone.h"
|
|
|
|
namespace v8 {
|
|
namespace internal {
|
|
|
|
// Forward declarations.
|
|
class CompilationInfo;
|
|
class CompilationJob;
|
|
class JavaScriptFrame;
|
|
class ParseInfo;
|
|
class ScriptData;
|
|
template <typename T>
|
|
class ThreadedList;
|
|
template <typename T>
|
|
class ThreadedListZoneEntry;
|
|
|
|
// 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: Scripts are translated into anonymous functions w/o
|
|
// parameters which then can be executed. If the source code contains other
|
|
// 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 V8_EXPORT_PRIVATE Compiler : public AllStatic {
|
|
public:
|
|
enum ClearExceptionFlag { KEEP_EXCEPTION, CLEAR_EXCEPTION };
|
|
|
|
// ===========================================================================
|
|
// 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 (except for live-edit, which compiles the world).
|
|
|
|
static bool Compile(Handle<JSFunction> function, ClearExceptionFlag flag);
|
|
static bool CompileOptimized(Handle<JSFunction> function, ConcurrencyMode);
|
|
static bool CompileDebugCode(Handle<SharedFunctionInfo> shared);
|
|
static MaybeHandle<JSArray> CompileForLiveEdit(Handle<Script> script);
|
|
|
|
// Prepare a compilation job for unoptimized code. Requires ParseAndAnalyse.
|
|
static CompilationJob* PrepareUnoptimizedCompilationJob(ParseInfo* parse_info,
|
|
Isolate* isolate);
|
|
|
|
// Generate and install code from previously queued compilation job.
|
|
static bool FinalizeCompilationJob(CompilationJob* job);
|
|
|
|
// Give the compiler a chance to perform low-latency initialization tasks of
|
|
// the given {function} on its instantiation. Note that only the runtime will
|
|
// offer this chance, optimized closure instantiation will not call this.
|
|
static void PostInstantiation(Handle<JSFunction> function, PretenureFlag);
|
|
|
|
typedef ThreadedList<ThreadedListZoneEntry<FunctionLiteral*>>
|
|
EagerInnerFunctionLiterals;
|
|
|
|
// Parser::Parse, then Compiler::Analyze.
|
|
static bool ParseAndAnalyze(ParseInfo* parse_info,
|
|
Handle<SharedFunctionInfo> shared_info,
|
|
Isolate* isolate);
|
|
// Rewrite, analyze scopes, and renumber. If |eager_literals| is non-null, it
|
|
// is appended with inner function literals which should be eagerly compiled.
|
|
static bool Analyze(ParseInfo* parse_info, Isolate* isolate,
|
|
EagerInnerFunctionLiterals* eager_literals = nullptr);
|
|
// Ensures that bytecode is generated, calls ParseAndAnalyze internally.
|
|
static bool EnsureBytecode(ParseInfo* parse_info, Isolate* isolate,
|
|
Handle<SharedFunctionInfo> shared_info);
|
|
|
|
// ===========================================================================
|
|
// The following family of methods instantiates new functions for scripts or
|
|
// function literals. The decision whether those functions will be 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.
|
|
|
|
// Create a (bound) function for a String source within a context for eval.
|
|
MUST_USE_RESULT static MaybeHandle<JSFunction> GetFunctionFromEval(
|
|
Handle<String> source, Handle<SharedFunctionInfo> outer_info,
|
|
Handle<Context> context, LanguageMode language_mode,
|
|
ParseRestriction restriction, int parameters_end_pos,
|
|
int eval_scope_position, int eval_position, int line_offset = 0,
|
|
int column_offset = 0, Handle<Object> script_name = Handle<Object>(),
|
|
ScriptOriginOptions options = ScriptOriginOptions());
|
|
|
|
// Returns true if the embedder permits compiling the given source string in
|
|
// the given context.
|
|
static bool CodeGenerationFromStringsAllowed(Isolate* isolate,
|
|
Handle<Context> context,
|
|
Handle<String> source);
|
|
|
|
// Create a (bound) function for a String source within a context for eval.
|
|
MUST_USE_RESULT static MaybeHandle<JSFunction> GetFunctionFromString(
|
|
Handle<Context> context, Handle<String> source,
|
|
ParseRestriction restriction, int parameters_end_pos);
|
|
|
|
// Create a shared function info object for a String source within a context.
|
|
static Handle<SharedFunctionInfo> GetSharedFunctionInfoForScript(
|
|
Handle<String> source, Handle<Object> script_name, int line_offset,
|
|
int column_offset, ScriptOriginOptions resource_options,
|
|
Handle<Object> source_map_url, Handle<Context> context,
|
|
v8::Extension* extension, ScriptData** cached_data,
|
|
ScriptCompiler::CompileOptions compile_options,
|
|
NativesFlag is_natives_code);
|
|
|
|
// Create a shared function info object for a Script that has already been
|
|
// parsed while the script was being loaded from a streamed source.
|
|
static Handle<SharedFunctionInfo> GetSharedFunctionInfoForStreamedScript(
|
|
Handle<Script> script, ParseInfo* info, int source_length);
|
|
|
|
// Create a shared function info object (the code may be lazily compiled).
|
|
static Handle<SharedFunctionInfo> GetSharedFunctionInfo(FunctionLiteral* node,
|
|
Handle<Script> script,
|
|
Isolate* isolate);
|
|
|
|
// Create a shared function info object for a native function literal.
|
|
static Handle<SharedFunctionInfo> GetSharedFunctionInfoForNative(
|
|
v8::Extension* extension, Handle<String> name);
|
|
|
|
// ===========================================================================
|
|
// 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, BailoutId osr_ast_id,
|
|
JavaScriptFrame* osr_frame);
|
|
};
|
|
|
|
// 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) PrepareJob: Runs on main thread. No major limitations.
|
|
// 2) ExecuteJob: Runs concurrently. No heap allocation or handle derefs.
|
|
// 3) FinalizeJob: Runs on main thread. No dependency changes.
|
|
//
|
|
// Each of the three phases can either fail or succeed. The current state of
|
|
// the job can be checked using {state()}.
|
|
class V8_EXPORT_PRIVATE CompilationJob {
|
|
public:
|
|
enum Status { SUCCEEDED, FAILED };
|
|
enum class State {
|
|
kReadyToPrepare,
|
|
kReadyToExecute,
|
|
kReadyToFinalize,
|
|
kSucceeded,
|
|
kFailed,
|
|
};
|
|
|
|
CompilationJob(Isolate* isolate, ParseInfo* parse_info, CompilationInfo* info,
|
|
const char* compiler_name,
|
|
State initial_state = State::kReadyToPrepare);
|
|
virtual ~CompilationJob() {}
|
|
|
|
// Prepare the compile job. Must be called on the main thread.
|
|
MUST_USE_RESULT Status PrepareJob();
|
|
|
|
// Executes the compile job. Can be called on a background thread if
|
|
// can_execute_on_background_thread() returns true.
|
|
MUST_USE_RESULT Status ExecuteJob();
|
|
|
|
// Finalizes the compile job. Must be called on the main thread.
|
|
MUST_USE_RESULT Status FinalizeJob();
|
|
|
|
// Report a transient failure, try again next time. Should only be called on
|
|
// optimization compilation jobs.
|
|
Status RetryOptimization(BailoutReason reason);
|
|
|
|
// Report a persistent failure, disable future optimization on the function.
|
|
// Should only be called on optimization compilation jobs.
|
|
Status AbortOptimization(BailoutReason reason);
|
|
|
|
void RecordOptimizedCompilationStats() const;
|
|
void RecordUnoptimizedCompilationStats() const;
|
|
|
|
virtual bool can_execute_on_background_thread() const { return true; }
|
|
|
|
void set_stack_limit(uintptr_t stack_limit) { stack_limit_ = stack_limit; }
|
|
uintptr_t stack_limit() const { return stack_limit_; }
|
|
|
|
bool executed_on_background_thread() const {
|
|
DCHECK_IMPLIES(!can_execute_on_background_thread(),
|
|
!executed_on_background_thread_);
|
|
return executed_on_background_thread_;
|
|
}
|
|
State state() const { return state_; }
|
|
ParseInfo* parse_info() const { return parse_info_; }
|
|
CompilationInfo* compilation_info() const { return compilation_info_; }
|
|
Isolate* isolate() const;
|
|
virtual size_t AllocatedMemory() const { return 0; }
|
|
|
|
protected:
|
|
// Overridden by the actual implementation.
|
|
virtual Status PrepareJobImpl() = 0;
|
|
virtual Status ExecuteJobImpl() = 0;
|
|
virtual Status FinalizeJobImpl() = 0;
|
|
|
|
private:
|
|
// TODO(6409): Remove parse_info once Fullcode and AstGraphBuilder are gone.
|
|
ParseInfo* parse_info_;
|
|
CompilationInfo* compilation_info_;
|
|
ThreadId isolate_thread_id_;
|
|
base::TimeDelta time_taken_to_prepare_;
|
|
base::TimeDelta time_taken_to_execute_;
|
|
base::TimeDelta time_taken_to_finalize_;
|
|
const char* compiler_name_;
|
|
State state_;
|
|
uintptr_t stack_limit_;
|
|
bool executed_on_background_thread_;
|
|
|
|
MUST_USE_RESULT Status UpdateState(Status status, State next_state) {
|
|
if (status == SUCCEEDED) {
|
|
state_ = next_state;
|
|
} else {
|
|
state_ = State::kFailed;
|
|
}
|
|
return status;
|
|
}
|
|
};
|
|
|
|
} // namespace internal
|
|
} // namespace v8
|
|
|
|
#endif // V8_COMPILER_H_
|