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

Generated by: LCOV version 1.10