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