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

Generated by: LCOV version 1.10