blob: e26484a4a6771c811e07e2595b70bb5086f9f217 [file] [log] [blame]
// 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 {
enum ClearExceptionFlag { KEEP_EXCEPTION, CLEAR_EXCEPTION };
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 (except for live-edit, which compiles the world).
static bool Compile(Handle<JSFunction> function, ClearExceptionFlag flag);
static bool CompileBaseline(Handle<JSFunction> function);
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(
CompilationInfo* info);
// 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*>>
// Parser::Parse, then Compiler::Analyze.
static bool ParseAndAnalyze(ParseInfo* info);
// 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* info,
EagerInnerFunctionLiterals* eager_literals = nullptr);
// Adds deoptimization support, requires ParseAndAnalyze.
static bool EnsureDeoptimizationSupport(CompilationInfo* info);
// Ensures that bytecode is generated, calls ParseAndAnalyze internally.
static bool EnsureBytecode(CompilationInfo* info);
// The next compilation tier which the function should be compiled to for
// optimization. This is used as a hint by the runtime profiler.
static CompilationTier NextCompilationTier(JSFunction* function);
// ===========================================================================
// 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());
// 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, CompilationInfo* outer);
// 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 {
enum Status { SUCCEEDED, FAILED };
enum class State {
CompilationJob(Isolate* isolate, 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 {
return executed_on_background_thread_;
State state() const { return state_; }
CompilationInfo* info() const { return info_; }
Isolate* isolate() const;
// Overridden by the actual implementation.
virtual Status PrepareJobImpl() = 0;
virtual Status ExecuteJobImpl() = 0;
virtual Status FinalizeJobImpl() = 0;
// Registers weak object to optimized code dependencies.
// TODO(turbofan): Move this to once Crankshaft dies.
void RegisterWeakObjectsInOptimizedCode(Handle<Code> code);
CompilationInfo* 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_