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