2993e48463
Bug: Change-Id: Ic72ebff8c106ef200875de352972c5b324dcb5a0 Reviewed-on: https://chromium-review.googlesource.com/781466 Commit-Queue: Toon Verwaest <verwaest@chromium.org> Reviewed-by: Ross McIlroy <rmcilroy@chromium.org> Cr-Commit-Position: refs/heads/master@{#49537}
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 <forward_list>
|
|
#include <memory>
|
|
|
|
#include "src/allocation.h"
|
|
#include "src/bailout-reason.h"
|
|
#include "src/code-events.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;
|
|
|
|
typedef std::forward_list<std::unique_ptr<CompilationJob>> CompilationJobList;
|
|
|
|
// 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<SharedFunctionInfo> shared,
|
|
ClearExceptionFlag flag);
|
|
static bool Compile(Handle<JSFunction> function, ClearExceptionFlag flag);
|
|
static bool CompileOptimized(Handle<JSFunction> function, ConcurrencyMode);
|
|
static MaybeHandle<JSArray> CompileForLiveEdit(Handle<Script> script);
|
|
|
|
// Compile top level code on a background thread. Should be finalized by
|
|
// GetSharedFunctionInfoForBackgroundCompile.
|
|
static std::unique_ptr<CompilationJob> CompileTopLevelOnBackgroundThread(
|
|
ParseInfo* parse_info, AccountingAllocator* allocator,
|
|
CompilationJobList* inner_function_jobs);
|
|
|
|
// Generate and install code from previously queued compilation job.
|
|
static bool FinalizeCompilationJob(CompilationJob* job, Isolate* isolate);
|
|
|
|
// 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,
|
|
EagerInnerFunctionLiterals* eager_literals = nullptr);
|
|
|
|
// ===========================================================================
|
|
// 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 MaybeHandle<SharedFunctionInfo> GetSharedFunctionInfoForScript(
|
|
Handle<String> source, MaybeHandle<Object> maybe_script_name,
|
|
int line_offset, int column_offset, ScriptOriginOptions resource_options,
|
|
MaybeHandle<Object> maybe_source_map_url, Handle<Context> context,
|
|
v8::Extension* extension, ScriptData** cached_data,
|
|
ScriptCompiler::CompileOptions compile_options,
|
|
ScriptCompiler::NoCacheReason no_cache_reason,
|
|
NativesFlag is_natives_code,
|
|
MaybeHandle<FixedArray> maybe_host_defined_options);
|
|
|
|
// 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 Script that has already been
|
|
// compiled on a background thread.
|
|
static Handle<SharedFunctionInfo> GetSharedFunctionInfoForBackgroundCompile(
|
|
Handle<Script> script, ParseInfo* parse_info, int source_length,
|
|
CompilationJob* outer_function_job,
|
|
CompilationJobList* inner_function_jobs);
|
|
|
|
// ===========================================================================
|
|
// 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_offset,
|
|
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(uintptr_t stack_limit, ParseInfo* parse_info,
|
|
CompilationInfo* compilation_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(Isolate* isolate);
|
|
|
|
// 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(Isolate* isolate);
|
|
|
|
// 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(Isolate* isolate) const;
|
|
void RecordFunctionCompilation(CodeEventListener::LogEventsAndTags tag,
|
|
Isolate* isolate) const;
|
|
|
|
void set_stack_limit(uintptr_t stack_limit) { stack_limit_ = stack_limit; }
|
|
uintptr_t stack_limit() const { return stack_limit_; }
|
|
|
|
State state() const { return state_; }
|
|
ParseInfo* parse_info() const { return parse_info_; }
|
|
CompilationInfo* compilation_info() const { return compilation_info_; }
|
|
virtual size_t AllocatedMemory() const { return 0; }
|
|
|
|
protected:
|
|
// Overridden by the actual implementation.
|
|
virtual Status PrepareJobImpl(Isolate* isolate) = 0;
|
|
virtual Status ExecuteJobImpl() = 0;
|
|
virtual Status FinalizeJobImpl(Isolate* isolate) = 0;
|
|
|
|
private:
|
|
// TODO(6409): Remove parse_info once Fullcode and AstGraphBuilder are gone.
|
|
ParseInfo* parse_info_;
|
|
CompilationInfo* compilation_info_;
|
|
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_;
|
|
|
|
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_
|