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 :
44 : // ===========================================================================
45 : // The following family of methods ensures a given function is compiled. The
46 : // general contract is that failures will be reported by returning {false},
47 : // whereas successful compilation ensures the {is_compiled} predicate on the
48 : // given function holds (except for live-edit, which compiles the world).
49 :
50 : static bool Compile(Handle<SharedFunctionInfo> shared,
51 : ClearExceptionFlag flag);
52 : static bool Compile(Handle<JSFunction> function, ClearExceptionFlag flag);
53 : static bool CompileOptimized(Handle<JSFunction> function, ConcurrencyMode);
54 : static MaybeHandle<JSArray> CompileForLiveEdit(Handle<Script> script);
55 :
56 : // Prepare a compilation job for unoptimized code. Requires ParseAndAnalyse.
57 : static CompilationJob* PrepareUnoptimizedCompilationJob(ParseInfo* parse_info,
58 : Isolate* isolate);
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* parse_info,
73 : Handle<SharedFunctionInfo> shared_info,
74 : Isolate* isolate);
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* parse_info,
78 : EagerInnerFunctionLiterals* eager_literals = nullptr);
79 :
80 : // ===========================================================================
81 : // The following family of methods instantiates new functions for scripts or
82 : // function literals. The decision whether those functions will be compiled,
83 : // is left to the discretion of the compiler.
84 : //
85 : // Please note this interface returns shared function infos. This means you
86 : // need to call Factory::NewFunctionFromSharedFunctionInfo before you have a
87 : // real function with a context.
88 :
89 : // Create a (bound) function for a String source within a context for eval.
90 : MUST_USE_RESULT static MaybeHandle<JSFunction> GetFunctionFromEval(
91 : Handle<String> source, Handle<SharedFunctionInfo> outer_info,
92 : Handle<Context> context, LanguageMode language_mode,
93 : ParseRestriction restriction, int parameters_end_pos,
94 : int eval_scope_position, int eval_position, int line_offset = 0,
95 : int column_offset = 0, Handle<Object> script_name = Handle<Object>(),
96 : ScriptOriginOptions options = ScriptOriginOptions());
97 :
98 : // Returns true if the embedder permits compiling the given source string in
99 : // the given context.
100 : static bool CodeGenerationFromStringsAllowed(Isolate* isolate,
101 : Handle<Context> context,
102 : Handle<String> source);
103 :
104 : // Create a (bound) function for a String source within a context for eval.
105 : MUST_USE_RESULT static MaybeHandle<JSFunction> GetFunctionFromString(
106 : Handle<Context> context, Handle<String> source,
107 : ParseRestriction restriction, int parameters_end_pos);
108 :
109 : // Create a shared function info object for a String source within a context.
110 : static MaybeHandle<SharedFunctionInfo> GetSharedFunctionInfoForScript(
111 : Handle<String> source, MaybeHandle<Object> maybe_script_name,
112 : int line_offset, int column_offset, ScriptOriginOptions resource_options,
113 : MaybeHandle<Object> maybe_source_map_url, Handle<Context> context,
114 : v8::Extension* extension, ScriptData** cached_data,
115 : ScriptCompiler::CompileOptions compile_options,
116 : NativesFlag is_natives_code,
117 : MaybeHandle<FixedArray> maybe_host_defined_options);
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(FunctionLiteral* node,
126 : Handle<Script> script,
127 : Isolate* isolate);
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_offset,
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()}.
157 : class 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, ParseInfo* parse_info, CompilationInfo* info,
169 : const char* compiler_name,
170 : State initial_state = State::kReadyToPrepare);
171 3162390 : 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 3144320 : virtual bool can_execute_on_background_thread() const { return true; }
195 :
196 23 : 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 : ParseInfo* parse_info() const { return parse_info_; }
206 : CompilationInfo* compilation_info() const { return compilation_info_; }
207 : Isolate* isolate() const;
208 0 : virtual size_t AllocatedMemory() const { return 0; }
209 :
210 : protected:
211 : // Overridden by the actual implementation.
212 : virtual Status PrepareJobImpl() = 0;
213 : virtual Status ExecuteJobImpl() = 0;
214 : virtual Status FinalizeJobImpl() = 0;
215 :
216 : private:
217 : // TODO(6409): Remove parse_info once Fullcode and AstGraphBuilder are gone.
218 : ParseInfo* parse_info_;
219 : CompilationInfo* compilation_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 8861622 : if (status == SUCCEEDED) {
231 8519098 : state_ = next_state;
232 : } else {
233 342524 : state_ = State::kFailed;
234 : }
235 : return status;
236 : }
237 : };
238 :
239 : } // namespace internal
240 : } // namespace v8
241 :
242 : #endif // V8_COMPILER_H_
|