LCOV - code coverage report
Current view: top level - src - compiler.h (source / functions) Hit Total Coverage
Test: app.info Lines: 14 14 100.0 %
Date: 2019-04-17 Functions: 2 4 50.0 %

          Line data    Source code
       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 <forward_list>
       9             : #include <memory>
      10             : 
      11             : #include "src/allocation.h"
      12             : #include "src/bailout-reason.h"
      13             : #include "src/base/platform/elapsed-timer.h"
      14             : #include "src/code-events.h"
      15             : #include "src/contexts.h"
      16             : #include "src/isolate.h"
      17             : #include "src/zone/zone.h"
      18             : 
      19             : namespace v8 {
      20             : namespace internal {
      21             : 
      22             : // Forward declarations.
      23             : class AstRawString;
      24             : class BackgroundCompileTask;
      25             : class IsCompiledScope;
      26             : class JavaScriptFrame;
      27             : class OptimizedCompilationInfo;
      28             : class OptimizedCompilationJob;
      29             : class ParseInfo;
      30             : class Parser;
      31             : class ScriptData;
      32             : struct ScriptStreamingData;
      33             : class TimedHistogram;
      34             : class UnoptimizedCompilationInfo;
      35             : class UnoptimizedCompilationJob;
      36             : class WorkerThreadRuntimeCallStats;
      37             : 
      38             : typedef std::forward_list<std::unique_ptr<UnoptimizedCompilationJob>>
      39             :     UnoptimizedCompilationJobList;
      40             : 
      41             : // The V8 compiler API.
      42             : //
      43             : // This is the central hub for dispatching to the various compilers within V8.
      44             : // Logic for which compiler to choose and how to wire compilation results into
      45             : // the object heap should be kept inside this class.
      46             : //
      47             : // General strategy: Scripts are translated into anonymous functions w/o
      48             : // parameters which then can be executed. If the source code contains other
      49             : // functions, they might be compiled and allocated as part of the compilation
      50             : // of the source code or deferred for lazy compilation at a later point.
      51             : class V8_EXPORT_PRIVATE Compiler : public AllStatic {
      52             :  public:
      53             :   enum ClearExceptionFlag { KEEP_EXCEPTION, CLEAR_EXCEPTION };
      54             : 
      55             :   // ===========================================================================
      56             :   // The following family of methods ensures a given function is compiled. The
      57             :   // general contract is that failures will be reported by returning {false},
      58             :   // whereas successful compilation ensures the {is_compiled} predicate on the
      59             :   // given function holds (except for live-edit, which compiles the world).
      60             : 
      61             :   static bool Compile(Handle<SharedFunctionInfo> shared,
      62             :                       ClearExceptionFlag flag,
      63             :                       IsCompiledScope* is_compiled_scope);
      64             :   static bool Compile(Handle<JSFunction> function, ClearExceptionFlag flag,
      65             :                       IsCompiledScope* is_compiled_scope);
      66             :   static bool CompileOptimized(Handle<JSFunction> function, ConcurrencyMode);
      67             : 
      68             :   // Collect source positions for a function that has already been compiled to
      69             :   // bytecode, but for which source positions were not collected (e.g. because
      70             :   // they were not immediately needed).
      71             :   static bool CollectSourcePositions(Isolate* isolate,
      72             :                                      Handle<SharedFunctionInfo> shared);
      73             : 
      74             :   V8_WARN_UNUSED_RESULT static MaybeHandle<SharedFunctionInfo>
      75             :   CompileForLiveEdit(ParseInfo* parse_info, Isolate* isolate);
      76             : 
      77             :   // Finalize and install code from previously run background compile task.
      78             :   static bool FinalizeBackgroundCompileTask(
      79             :       BackgroundCompileTask* task, Handle<SharedFunctionInfo> shared_info,
      80             :       Isolate* isolate, ClearExceptionFlag flag);
      81             : 
      82             :   // Finalize and install optimized code from previously run job.
      83             :   static bool FinalizeOptimizedCompilationJob(OptimizedCompilationJob* job,
      84             :                                               Isolate* isolate);
      85             : 
      86             :   // Give the compiler a chance to perform low-latency initialization tasks of
      87             :   // the given {function} on its instantiation. Note that only the runtime will
      88             :   // offer this chance, optimized closure instantiation will not call this.
      89             :   static void PostInstantiation(Handle<JSFunction> function, AllocationType);
      90             : 
      91             :   // Parser::Parse, then Compiler::Analyze.
      92             :   static bool ParseAndAnalyze(ParseInfo* parse_info,
      93             :                               Handle<SharedFunctionInfo> shared_info,
      94             :                               Isolate* isolate);
      95             :   // Rewrite and analyze scopes.
      96             :   static bool Analyze(ParseInfo* parse_info);
      97             : 
      98             :   // ===========================================================================
      99             :   // The following family of methods instantiates new functions for scripts or
     100             :   // function literals. The decision whether those functions will be compiled,
     101             :   // is left to the discretion of the compiler.
     102             :   //
     103             :   // Please note this interface returns shared function infos.  This means you
     104             :   // need to call Factory::NewFunctionFromSharedFunctionInfo before you have a
     105             :   // real function with a context.
     106             : 
     107             :   // Create a (bound) function for a String source within a context for eval.
     108             :   V8_WARN_UNUSED_RESULT static MaybeHandle<JSFunction> GetFunctionFromEval(
     109             :       Handle<String> source, Handle<SharedFunctionInfo> outer_info,
     110             :       Handle<Context> context, LanguageMode language_mode,
     111             :       ParseRestriction restriction, int parameters_end_pos,
     112             :       int eval_scope_position, int eval_position);
     113             : 
     114             :   struct ScriptDetails {
     115      275758 :     ScriptDetails() : line_offset(0), column_offset(0) {}
     116             :     explicit ScriptDetails(Handle<Object> script_name)
     117       12792 :         : line_offset(0), column_offset(0), name_obj(script_name) {}
     118             : 
     119             :     int line_offset;
     120             :     int column_offset;
     121             :     i::MaybeHandle<i::Object> name_obj;
     122             :     i::MaybeHandle<i::Object> source_map_url;
     123             :     i::MaybeHandle<i::FixedArray> host_defined_options;
     124             :   };
     125             : 
     126             :   // Create a function that results from wrapping |source| in a function,
     127             :   // with |arguments| being a list of parameters for that function.
     128             :   V8_WARN_UNUSED_RESULT static MaybeHandle<JSFunction> GetWrappedFunction(
     129             :       Handle<String> source, Handle<FixedArray> arguments,
     130             :       Handle<Context> context, const ScriptDetails& script_details,
     131             :       ScriptOriginOptions origin_options, ScriptData* cached_data,
     132             :       v8::ScriptCompiler::CompileOptions compile_options,
     133             :       v8::ScriptCompiler::NoCacheReason no_cache_reason);
     134             : 
     135             :   // Returns true if the embedder permits compiling the given source string in
     136             :   // the given context.
     137             :   static bool CodeGenerationFromStringsAllowed(Isolate* isolate,
     138             :                                                Handle<Context> context,
     139             :                                                Handle<String> source);
     140             : 
     141             :   // Create a (bound) function for a String source within a context for eval.
     142             :   V8_WARN_UNUSED_RESULT static MaybeHandle<JSFunction> GetFunctionFromString(
     143             :       Handle<Context> context, Handle<String> source,
     144             :       ParseRestriction restriction, int parameters_end_pos);
     145             : 
     146             :   // Create a shared function info object for a String source.
     147             :   static MaybeHandle<SharedFunctionInfo> GetSharedFunctionInfoForScript(
     148             :       Isolate* isolate, Handle<String> source,
     149             :       const ScriptDetails& script_details, ScriptOriginOptions origin_options,
     150             :       v8::Extension* extension, ScriptData* cached_data,
     151             :       ScriptCompiler::CompileOptions compile_options,
     152             :       ScriptCompiler::NoCacheReason no_cache_reason,
     153             :       NativesFlag is_natives_code);
     154             : 
     155             :   // Create a shared function info object for a Script source that has already
     156             :   // been parsed and possibly compiled on a background thread while being loaded
     157             :   // from a streamed source. On return, the data held by |streaming_data| will
     158             :   // have been released, however the object itself isn't freed and is still
     159             :   // owned by the caller.
     160             :   static MaybeHandle<SharedFunctionInfo> GetSharedFunctionInfoForStreamedScript(
     161             :       Isolate* isolate, Handle<String> source,
     162             :       const ScriptDetails& script_details, ScriptOriginOptions origin_options,
     163             :       ScriptStreamingData* streaming_data);
     164             : 
     165             :   // Create a shared function info object for the given function literal
     166             :   // node (the code may be lazily compiled).
     167             :   static Handle<SharedFunctionInfo> GetSharedFunctionInfo(FunctionLiteral* node,
     168             :                                                           Handle<Script> script,
     169             :                                                           Isolate* isolate);
     170             : 
     171             :   // ===========================================================================
     172             :   // The following family of methods provides support for OSR. Code generated
     173             :   // for entry via OSR might not be suitable for normal entry, hence will be
     174             :   // returned directly to the caller.
     175             :   //
     176             :   // Please note this interface is the only part dealing with {Code} objects
     177             :   // directly. Other methods are agnostic to {Code} and can use an interpreter
     178             :   // instead of generating JIT code for a function at all.
     179             : 
     180             :   // Generate and return optimized code for OSR, or empty handle on failure.
     181             :   V8_WARN_UNUSED_RESULT static MaybeHandle<Code> GetOptimizedCodeForOSR(
     182             :       Handle<JSFunction> function, BailoutId osr_offset,
     183             :       JavaScriptFrame* osr_frame);
     184             : };
     185             : 
     186             : // A base class for compilation jobs intended to run concurrent to the main
     187             : // thread. The current state of the job can be checked using {state()}.
     188             : class V8_EXPORT_PRIVATE CompilationJob {
     189             :  public:
     190             :   enum Status { SUCCEEDED, FAILED };
     191             :   enum class State {
     192             :     kReadyToPrepare,
     193             :     kReadyToExecute,
     194             :     kReadyToFinalize,
     195             :     kSucceeded,
     196             :     kFailed,
     197             :   };
     198             : 
     199             :   CompilationJob(uintptr_t stack_limit, State initial_state)
     200     2599890 :       : state_(initial_state), stack_limit_(stack_limit) {
     201             :     timer_.Start();
     202             :   }
     203     2599921 :   virtual ~CompilationJob() = default;
     204             : 
     205             :   void set_stack_limit(uintptr_t stack_limit) { stack_limit_ = stack_limit; }
     206             :   uintptr_t stack_limit() const { return stack_limit_; }
     207             : 
     208             :   State state() const { return state_; }
     209             : 
     210             :  protected:
     211             :   V8_WARN_UNUSED_RESULT base::TimeDelta ElapsedTime() const {
     212             :     return timer_.Elapsed();
     213             :   }
     214             : 
     215             :   V8_WARN_UNUSED_RESULT Status UpdateState(Status status, State next_state) {
     216     5596526 :     if (status == SUCCEEDED) {
     217     5595158 :       state_ = next_state;
     218             :     } else {
     219        1463 :       state_ = State::kFailed;
     220             :     }
     221             :     return status;
     222             :   }
     223             : 
     224             :  private:
     225             :   State state_;
     226             :   uintptr_t stack_limit_;
     227             :   base::ElapsedTimer timer_;
     228             : };
     229             : 
     230             : // A base class for unoptimized compilation jobs.
     231             : //
     232             : // The job is split into two phases which are called in sequence on
     233             : // different threads and with different limitations:
     234             : //  1) ExecuteJob:   Runs concurrently. No heap allocation or handle derefs.
     235             : //  2) FinalizeJob:  Runs on main thread. No dependency changes.
     236             : //
     237             : // Either of phases can either fail or succeed.
     238     4240182 : class UnoptimizedCompilationJob : public CompilationJob {
     239             :  public:
     240             :   UnoptimizedCompilationJob(intptr_t stack_limit, ParseInfo* parse_info,
     241             :                             UnoptimizedCompilationInfo* compilation_info)
     242             :       : CompilationJob(stack_limit, State::kReadyToExecute),
     243             :         parse_info_(parse_info),
     244     2120074 :         compilation_info_(compilation_info) {}
     245             : 
     246             :   // Executes the compile job. Can be called on a background thread.
     247             :   V8_WARN_UNUSED_RESULT Status ExecuteJob();
     248             : 
     249             :   // Finalizes the compile job. Must be called on the main thread.
     250             :   V8_WARN_UNUSED_RESULT Status
     251             :   FinalizeJob(Handle<SharedFunctionInfo> shared_info, Isolate* isolate);
     252             : 
     253             :   void RecordCompilationStats(Isolate* isolate) const;
     254             :   void RecordFunctionCompilation(CodeEventListener::LogEventsAndTags tag,
     255             :                                  Handle<SharedFunctionInfo> shared,
     256             :                                  Isolate* isolate) const;
     257             : 
     258             :   ParseInfo* parse_info() const { return parse_info_; }
     259             :   UnoptimizedCompilationInfo* compilation_info() const {
     260             :     return compilation_info_;
     261             :   }
     262             : 
     263             :  protected:
     264             :   // Overridden by the actual implementation.
     265             :   virtual Status ExecuteJobImpl() = 0;
     266             :   virtual Status FinalizeJobImpl(Handle<SharedFunctionInfo> shared_info,
     267             :                                  Isolate* isolate) = 0;
     268             : 
     269             :  private:
     270             :   ParseInfo* parse_info_;
     271             :   UnoptimizedCompilationInfo* compilation_info_;
     272             :   base::TimeDelta time_taken_to_execute_;
     273             :   base::TimeDelta time_taken_to_finalize_;
     274             : };
     275             : 
     276             : // A base class for optimized compilation jobs.
     277             : //
     278             : // The job is split into three phases which are called in sequence on
     279             : // different threads and with different limitations:
     280             : //  1) PrepareJob:   Runs on main thread. No major limitations.
     281             : //  2) ExecuteJob:   Runs concurrently. No heap allocation or handle derefs.
     282             : //  3) FinalizeJob:  Runs on main thread. No dependency changes.
     283             : //
     284             : // Each of the three phases can either fail or succeed.
     285      959660 : class OptimizedCompilationJob : public CompilationJob {
     286             :  public:
     287             :   OptimizedCompilationJob(uintptr_t stack_limit,
     288             :                           OptimizedCompilationInfo* compilation_info,
     289             :                           const char* compiler_name,
     290             :                           State initial_state = State::kReadyToPrepare)
     291             :       : CompilationJob(stack_limit, initial_state),
     292             :         compilation_info_(compilation_info),
     293      959658 :         compiler_name_(compiler_name) {}
     294             : 
     295             :   // Prepare the compile job. Must be called on the main thread.
     296             :   V8_WARN_UNUSED_RESULT Status PrepareJob(Isolate* isolate);
     297             : 
     298             :   // Executes the compile job. Can be called on a background thread if
     299             :   // can_execute_on_background_thread() returns true.
     300             :   V8_WARN_UNUSED_RESULT Status ExecuteJob();
     301             : 
     302             :   // Finalizes the compile job. Must be called on the main thread.
     303             :   V8_WARN_UNUSED_RESULT Status FinalizeJob(Isolate* isolate);
     304             : 
     305             :   // Report a transient failure, try again next time. Should only be called on
     306             :   // optimization compilation jobs.
     307             :   Status RetryOptimization(BailoutReason reason);
     308             : 
     309             :   // Report a persistent failure, disable future optimization on the function.
     310             :   // Should only be called on optimization compilation jobs.
     311             :   Status AbortOptimization(BailoutReason reason);
     312             : 
     313             :   enum CompilationMode { kConcurrent, kSynchronous };
     314             :   void RecordCompilationStats(CompilationMode mode, Isolate* isolate) const;
     315             :   void RecordFunctionCompilation(CodeEventListener::LogEventsAndTags tag,
     316             :                                  Isolate* isolate) const;
     317             : 
     318             :   OptimizedCompilationInfo* compilation_info() const {
     319             :     return compilation_info_;
     320             :   }
     321             : 
     322             :  protected:
     323             :   // Overridden by the actual implementation.
     324             :   virtual Status PrepareJobImpl(Isolate* isolate) = 0;
     325             :   virtual Status ExecuteJobImpl() = 0;
     326             :   virtual Status FinalizeJobImpl(Isolate* isolate) = 0;
     327             : 
     328             :  private:
     329             :   OptimizedCompilationInfo* compilation_info_;
     330             :   base::TimeDelta time_taken_to_prepare_;
     331             :   base::TimeDelta time_taken_to_execute_;
     332             :   base::TimeDelta time_taken_to_finalize_;
     333             :   const char* compiler_name_;
     334             : };
     335             : 
     336       26950 : class V8_EXPORT_PRIVATE BackgroundCompileTask {
     337             :  public:
     338             :   // Creates a new task that when run will parse and compile the streamed
     339             :   // script associated with |data| and can be finalized with
     340             :   // Compiler::GetSharedFunctionInfoForStreamedScript.
     341             :   // Note: does not take ownership of |data|.
     342             :   BackgroundCompileTask(ScriptStreamingData* data, Isolate* isolate);
     343             :   ~BackgroundCompileTask();
     344             : 
     345             :   // Creates a new task that when run will parse and compile the
     346             :   // |function_literal| and can be finalized with
     347             :   // Compiler::FinalizeBackgroundCompileTask.
     348             :   BackgroundCompileTask(
     349             :       AccountingAllocator* allocator, const ParseInfo* outer_parse_info,
     350             :       const AstRawString* function_name,
     351             :       const FunctionLiteral* function_literal,
     352             :       WorkerThreadRuntimeCallStats* worker_thread_runtime_stats,
     353             :       TimedHistogram* timer, int max_stack_size);
     354             : 
     355             :   void Run();
     356             : 
     357             :   ParseInfo* info() { return info_.get(); }
     358             :   Parser* parser() { return parser_.get(); }
     359             :   UnoptimizedCompilationJob* outer_function_job() {
     360             :     return outer_function_job_.get();
     361             :   }
     362             :   UnoptimizedCompilationJobList* inner_function_jobs() {
     363         203 :     return &inner_function_jobs_;
     364             :   }
     365             : 
     366             :  private:
     367             :   // Data needed for parsing, and data needed to to be passed between thread
     368             :   // between parsing and compilation. These need to be initialized before the
     369             :   // compilation starts.
     370             :   std::unique_ptr<ParseInfo> info_;
     371             :   std::unique_ptr<Parser> parser_;
     372             : 
     373             :   // Data needed for finalizing compilation after background compilation.
     374             :   std::unique_ptr<UnoptimizedCompilationJob> outer_function_job_;
     375             :   UnoptimizedCompilationJobList inner_function_jobs_;
     376             : 
     377             :   int stack_size_;
     378             :   WorkerThreadRuntimeCallStats* worker_thread_runtime_call_stats_;
     379             :   AccountingAllocator* allocator_;
     380             :   TimedHistogram* timer_;
     381             : 
     382             :   DISALLOW_COPY_AND_ASSIGN(BackgroundCompileTask);
     383             : };
     384             : 
     385             : // Contains all data which needs to be transmitted between threads for
     386             : // background parsing and compiling and finalizing it on the main thread.
     387       26790 : struct ScriptStreamingData {
     388             :   ScriptStreamingData(
     389             :       std::unique_ptr<ScriptCompiler::ExternalSourceStream> source_stream,
     390             :       ScriptCompiler::StreamedSource::Encoding encoding);
     391             :   ~ScriptStreamingData();
     392             : 
     393             :   void Release();
     394             : 
     395             :   // Internal implementation of v8::ScriptCompiler::StreamedSource.
     396             :   std::unique_ptr<ScriptCompiler::ExternalSourceStream> source_stream;
     397             :   ScriptCompiler::StreamedSource::Encoding encoding;
     398             : 
     399             :   // Task that performs background parsing and compilation.
     400             :   std::unique_ptr<BackgroundCompileTask> task;
     401             : 
     402             :   DISALLOW_COPY_AND_ASSIGN(ScriptStreamingData);
     403             : };
     404             : 
     405             : }  // namespace internal
     406             : }  // namespace v8
     407             : 
     408             : #endif  // V8_COMPILER_H_

Generated by: LCOV version 1.10