Home | History | Annotate | Download | only in src
      1 // Copyright 2012 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef V8_COMPILER_H_
      6 #define V8_COMPILER_H_
      7 
      8 #include <memory>
      9 
     10 #include "src/allocation.h"
     11 #include "src/bailout-reason.h"
     12 #include "src/contexts.h"
     13 #include "src/isolate.h"
     14 #include "src/zone/zone.h"
     15 
     16 namespace v8 {
     17 namespace internal {
     18 
     19 // Forward declarations.
     20 class CompilationInfo;
     21 class CompilationJob;
     22 class JavaScriptFrame;
     23 class ParseInfo;
     24 class ScriptData;
     25 
     26 // The V8 compiler API.
     27 //
     28 // This is the central hub for dispatching to the various compilers within V8.
     29 // Logic for which compiler to choose and how to wire compilation results into
     30 // the object heap should be kept inside this class.
     31 //
     32 // General strategy: Scripts are translated into anonymous functions w/o
     33 // parameters which then can be executed. If the source code contains other
     34 // functions, they might be compiled and allocated as part of the compilation
     35 // of the source code or deferred for lazy compilation at a later point.
     36 class Compiler : public AllStatic {
     37  public:
     38   enum ClearExceptionFlag { KEEP_EXCEPTION, CLEAR_EXCEPTION };
     39   enum ConcurrencyMode { NOT_CONCURRENT, CONCURRENT };
     40   enum CompilationTier { INTERPRETED, BASELINE, OPTIMIZED };
     41 
     42   // ===========================================================================
     43   // The following family of methods ensures a given function is compiled. The
     44   // general contract is that failures will be reported by returning {false},
     45   // whereas successful compilation ensures the {is_compiled} predicate on the
     46   // given function holds (except for live-edit, which compiles the world).
     47 
     48   static bool Compile(Handle<JSFunction> function, ClearExceptionFlag flag);
     49   static bool CompileBaseline(Handle<JSFunction> function);
     50   static bool CompileOptimized(Handle<JSFunction> function, ConcurrencyMode);
     51   static bool CompileDebugCode(Handle<SharedFunctionInfo> shared);
     52   static MaybeHandle<JSArray> CompileForLiveEdit(Handle<Script> script);
     53 
     54   // Prepare a compilation job for unoptimized code. Requires ParseAndAnalyse.
     55   static CompilationJob* PrepareUnoptimizedCompilationJob(
     56       CompilationInfo* info);
     57 
     58   // Generate and install code from previously queued compilation job.
     59   static bool FinalizeCompilationJob(CompilationJob* job);
     60 
     61   // Give the compiler a chance to perform low-latency initialization tasks of
     62   // the given {function} on its instantiation. Note that only the runtime will
     63   // offer this chance, optimized closure instantiation will not call this.
     64   static void PostInstantiation(Handle<JSFunction> function, PretenureFlag);
     65 
     66   // Parser::Parse, then Compiler::Analyze.
     67   static bool ParseAndAnalyze(ParseInfo* info);
     68   // Rewrite, analyze scopes, and renumber.
     69   static bool Analyze(ParseInfo* info);
     70   // Adds deoptimization support, requires ParseAndAnalyze.
     71   static bool EnsureDeoptimizationSupport(CompilationInfo* info);
     72   // Ensures that bytecode is generated, calls ParseAndAnalyze internally.
     73   static bool EnsureBytecode(CompilationInfo* info);
     74 
     75   // The next compilation tier which the function should  be compiled to for
     76   // optimization. This is used as a hint by the runtime profiler.
     77   static CompilationTier NextCompilationTier(JSFunction* function);
     78 
     79   // ===========================================================================
     80   // The following family of methods instantiates new functions for scripts or
     81   // function literals. The decision whether those functions will be compiled,
     82   // is left to the discretion of the compiler.
     83   //
     84   // Please note this interface returns shared function infos.  This means you
     85   // need to call Factory::NewFunctionFromSharedFunctionInfo before you have a
     86   // real function with a context.
     87 
     88   // Create a (bound) function for a String source within a context for eval.
     89   MUST_USE_RESULT static MaybeHandle<JSFunction> GetFunctionFromEval(
     90       Handle<String> source, Handle<SharedFunctionInfo> outer_info,
     91       Handle<Context> context, LanguageMode language_mode,
     92       ParseRestriction restriction, int eval_scope_position, int eval_position,
     93       int line_offset = 0, int column_offset = 0,
     94       Handle<Object> script_name = Handle<Object>(),
     95       ScriptOriginOptions options = ScriptOriginOptions());
     96 
     97   // Create a (bound) function for a String source within a context for eval.
     98   MUST_USE_RESULT static MaybeHandle<JSFunction> GetFunctionFromString(
     99       Handle<Context> context, Handle<String> source,
    100       ParseRestriction restriction);
    101 
    102   // Create a shared function info object for a String source within a context.
    103   static Handle<SharedFunctionInfo> GetSharedFunctionInfoForScript(
    104       Handle<String> source, Handle<Object> script_name, int line_offset,
    105       int column_offset, ScriptOriginOptions resource_options,
    106       Handle<Object> source_map_url, Handle<Context> context,
    107       v8::Extension* extension, ScriptData** cached_data,
    108       ScriptCompiler::CompileOptions compile_options,
    109       NativesFlag is_natives_code, bool is_module);
    110 
    111   // Create a shared function info object for a Script that has already been
    112   // parsed while the script was being loaded from a streamed source.
    113   static Handle<SharedFunctionInfo> GetSharedFunctionInfoForStreamedScript(
    114       Handle<Script> script, ParseInfo* info, int source_length);
    115 
    116   // Create a shared function info object (the code may be lazily compiled).
    117   static Handle<SharedFunctionInfo> GetSharedFunctionInfo(
    118       FunctionLiteral* node, Handle<Script> script, CompilationInfo* outer);
    119 
    120   // Create a shared function info object for a native function literal.
    121   static Handle<SharedFunctionInfo> GetSharedFunctionInfoForNative(
    122       v8::Extension* extension, Handle<String> name);
    123 
    124   // ===========================================================================
    125   // The following family of methods provides support for OSR. Code generated
    126   // for entry via OSR might not be suitable for normal entry, hence will be
    127   // returned directly to the caller.
    128   //
    129   // Please note this interface is the only part dealing with {Code} objects
    130   // directly. Other methods are agnostic to {Code} and can use an interpreter
    131   // instead of generating JIT code for a function at all.
    132 
    133   // Generate and return optimized code for OSR, or empty handle on failure.
    134   MUST_USE_RESULT static MaybeHandle<Code> GetOptimizedCodeForOSR(
    135       Handle<JSFunction> function, BailoutId osr_ast_id,
    136       JavaScriptFrame* osr_frame);
    137 };
    138 
    139 // A base class for compilation jobs intended to run concurrent to the main
    140 // thread. The job is split into three phases which are called in sequence on
    141 // different threads and with different limitations:
    142 //  1) PrepareJob:   Runs on main thread. No major limitations.
    143 //  2) ExecuteJob:   Runs concurrently. No heap allocation or handle derefs.
    144 //  3) FinalizeJob:  Runs on main thread. No dependency changes.
    145 //
    146 // Each of the three phases can either fail or succeed. The current state of
    147 // the job can be checked using {state()}.
    148 class CompilationJob {
    149  public:
    150   enum Status { SUCCEEDED, FAILED };
    151   enum class State {
    152     kReadyToPrepare,
    153     kReadyToExecute,
    154     kReadyToFinalize,
    155     kSucceeded,
    156     kFailed,
    157   };
    158 
    159   CompilationJob(Isolate* isolate, CompilationInfo* info,
    160                  const char* compiler_name,
    161                  State initial_state = State::kReadyToPrepare)
    162       : info_(info),
    163         compiler_name_(compiler_name),
    164         state_(initial_state),
    165         stack_limit_(isolate->stack_guard()->real_climit()) {}
    166   virtual ~CompilationJob() {}
    167 
    168   // Prepare the compile job. Must be called on the main thread.
    169   MUST_USE_RESULT Status PrepareJob();
    170 
    171   // Executes the compile job. Can be called on a background thread if
    172   // can_execute_on_background_thread() returns true.
    173   MUST_USE_RESULT Status ExecuteJob();
    174 
    175   // Finalizes the compile job. Must be called on the main thread.
    176   MUST_USE_RESULT Status FinalizeJob();
    177 
    178   // Report a transient failure, try again next time. Should only be called on
    179   // optimization compilation jobs.
    180   Status RetryOptimization(BailoutReason reason);
    181 
    182   // Report a persistent failure, disable future optimization on the function.
    183   // Should only be called on optimization compilation jobs.
    184   Status AbortOptimization(BailoutReason reason);
    185 
    186   void RecordOptimizedCompilationStats() const;
    187   void RecordUnoptimizedCompilationStats() const;
    188 
    189   virtual bool can_execute_on_background_thread() const { return true; }
    190 
    191   void set_stack_limit(uintptr_t stack_limit) { stack_limit_ = stack_limit; }
    192   uintptr_t stack_limit() const { return stack_limit_; }
    193 
    194   State state() const { return state_; }
    195   CompilationInfo* info() const { return info_; }
    196   Isolate* isolate() const;
    197 
    198  protected:
    199   // Overridden by the actual implementation.
    200   virtual Status PrepareJobImpl() = 0;
    201   virtual Status ExecuteJobImpl() = 0;
    202   virtual Status FinalizeJobImpl() = 0;
    203 
    204   // Registers weak object to optimized code dependencies.
    205   // TODO(turbofan): Move this to pipeline.cc once Crankshaft dies.
    206   void RegisterWeakObjectsInOptimizedCode(Handle<Code> code);
    207 
    208  private:
    209   CompilationInfo* info_;
    210   base::TimeDelta time_taken_to_prepare_;
    211   base::TimeDelta time_taken_to_execute_;
    212   base::TimeDelta time_taken_to_finalize_;
    213   const char* compiler_name_;
    214   State state_;
    215   uintptr_t stack_limit_;
    216 
    217   MUST_USE_RESULT Status UpdateState(Status status, State next_state) {
    218     if (status == SUCCEEDED) {
    219       state_ = next_state;
    220     } else {
    221       state_ = State::kFailed;
    222     }
    223     return status;
    224   }
    225 };
    226 
    227 }  // namespace internal
    228 }  // namespace v8
    229 
    230 #endif  // V8_COMPILER_H_
    231