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