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