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