| 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 | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame^] | 25 | template <typename T> |
| 26 | class ThreadedList; |
| 27 | template <typename T> |
| 28 | class ThreadedListZoneEntry; |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 29 | |
| Ben Murdoch | 3b9bc31 | 2016-06-02 14:46:10 +0100 | [diff] [blame] | 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. |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame^] | 40 | class V8_EXPORT_PRIVATE Compiler : public AllStatic { |
| Ben Murdoch | 3b9bc31 | 2016-06-02 14:46:10 +0100 | [diff] [blame] | 41 | public: |
| 42 | enum ClearExceptionFlag { KEEP_EXCEPTION, CLEAR_EXCEPTION }; |
| 43 | enum ConcurrencyMode { NOT_CONCURRENT, CONCURRENT }; |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 44 | enum CompilationTier { INTERPRETED, BASELINE, OPTIMIZED }; |
| Ben Murdoch | 3b9bc31 | 2016-06-02 14:46:10 +0100 | [diff] [blame] | 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); |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 53 | static bool CompileBaseline(Handle<JSFunction> function); |
| Ben Murdoch | 3b9bc31 | 2016-06-02 14:46:10 +0100 | [diff] [blame] | 54 | static bool CompileOptimized(Handle<JSFunction> function, ConcurrencyMode); |
| Ben Murdoch | 3b9bc31 | 2016-06-02 14:46:10 +0100 | [diff] [blame] | 55 | static bool CompileDebugCode(Handle<SharedFunctionInfo> shared); |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 56 | static MaybeHandle<JSArray> CompileForLiveEdit(Handle<Script> script); |
| Ben Murdoch | 3b9bc31 | 2016-06-02 14:46:10 +0100 | [diff] [blame] | 57 | |
| Ben Murdoch | f3b273f | 2017-01-17 12:11:28 +0000 | [diff] [blame] | 58 | // Prepare a compilation job for unoptimized code. Requires ParseAndAnalyse. |
| 59 | static CompilationJob* PrepareUnoptimizedCompilationJob( |
| 60 | CompilationInfo* info); |
| 61 | |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 62 | // Generate and install code from previously queued compilation job. |
| Ben Murdoch | f3b273f | 2017-01-17 12:11:28 +0000 | [diff] [blame] | 63 | static bool FinalizeCompilationJob(CompilationJob* job); |
| Ben Murdoch | 3b9bc31 | 2016-06-02 14:46:10 +0100 | [diff] [blame] | 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 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame^] | 70 | typedef ThreadedList<ThreadedListZoneEntry<FunctionLiteral*>> |
| 71 | EagerInnerFunctionLiterals; |
| 72 | |
| Ben Murdoch | 3b9bc31 | 2016-06-02 14:46:10 +0100 | [diff] [blame] | 73 | // Parser::Parse, then Compiler::Analyze. |
| 74 | static bool ParseAndAnalyze(ParseInfo* info); |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame^] | 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); |
| Ben Murdoch | 3b9bc31 | 2016-06-02 14:46:10 +0100 | [diff] [blame] | 79 | // Adds deoptimization support, requires ParseAndAnalyze. |
| 80 | static bool EnsureDeoptimizationSupport(CompilationInfo* info); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 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); |
| Ben Murdoch | 3b9bc31 | 2016-06-02 14:46:10 +0100 | [diff] [blame] | 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, |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame^] | 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>(), |
| Ben Murdoch | 3b9bc31 | 2016-06-02 14:46:10 +0100 | [diff] [blame] | 104 | ScriptOriginOptions options = ScriptOriginOptions()); |
| 105 | |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 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, |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame^] | 109 | ParseRestriction restriction, int parameters_end_pos); |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 110 | |
| Ben Murdoch | 3b9bc31 | 2016-06-02 14:46:10 +0100 | [diff] [blame] | 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, |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame^] | 118 | NativesFlag is_natives_code); |
| Ben Murdoch | 3b9bc31 | 2016-06-02 14:46:10 +0100 | [diff] [blame] | 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 | }; |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 147 | |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 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: |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 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. |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 154 | // |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 155 | // Each of the three phases can either fail or succeed. The current state of |
| 156 | // the job can be checked using {state()}. |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame^] | 157 | class V8_EXPORT_PRIVATE CompilationJob { |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 158 | public: |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 159 | enum Status { SUCCEEDED, FAILED }; |
| 160 | enum class State { |
| 161 | kReadyToPrepare, |
| 162 | kReadyToExecute, |
| 163 | kReadyToFinalize, |
| 164 | kSucceeded, |
| 165 | kFailed, |
| 166 | }; |
| 167 | |
| Ben Murdoch | f3b273f | 2017-01-17 12:11:28 +0000 | [diff] [blame] | 168 | CompilationJob(Isolate* isolate, CompilationInfo* info, |
| 169 | const char* compiler_name, |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame^] | 170 | State initial_state = State::kReadyToPrepare); |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 171 | virtual ~CompilationJob() {} |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 172 | |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 173 | // Prepare the compile job. Must be called on the main thread. |
| 174 | MUST_USE_RESULT Status PrepareJob(); |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 175 | |
| Ben Murdoch | f3b273f | 2017-01-17 12:11:28 +0000 | [diff] [blame] | 176 | // Executes the compile job. Can be called on a background thread if |
| 177 | // can_execute_on_background_thread() returns true. |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 178 | MUST_USE_RESULT Status ExecuteJob(); |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 179 | |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 180 | // Finalizes the compile job. Must be called on the main thread. |
| 181 | MUST_USE_RESULT Status FinalizeJob(); |
| 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 transient failure, try again next time. Should only be called on |
| 184 | // optimization compilation jobs. |
| Ben Murdoch | f3b273f | 2017-01-17 12:11:28 +0000 | [diff] [blame] | 185 | Status RetryOptimization(BailoutReason reason); |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 186 | |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 187 | // Report a persistent failure, disable future optimization on the function. |
| 188 | // Should only be called on optimization compilation jobs. |
| Ben Murdoch | f3b273f | 2017-01-17 12:11:28 +0000 | [diff] [blame] | 189 | Status AbortOptimization(BailoutReason reason); |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 190 | |
| Ben Murdoch | f3b273f | 2017-01-17 12:11:28 +0000 | [diff] [blame] | 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_; } |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 198 | |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame^] | 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 | } |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 204 | State state() const { return state_; } |
| 205 | CompilationInfo* info() const { return info_; } |
| Ben Murdoch | f3b273f | 2017-01-17 12:11:28 +0000 | [diff] [blame] | 206 | Isolate* isolate() const; |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 207 | |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 208 | protected: |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 209 | // Overridden by the actual implementation. |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 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); |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 217 | |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 218 | private: |
| 219 | CompilationInfo* info_; |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame^] | 220 | ThreadId isolate_thread_id_; |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 221 | base::TimeDelta time_taken_to_prepare_; |
| 222 | base::TimeDelta time_taken_to_execute_; |
| 223 | base::TimeDelta time_taken_to_finalize_; |
| Ben Murdoch | bcf72ee | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 224 | const char* compiler_name_; |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 225 | State state_; |
| Ben Murdoch | f3b273f | 2017-01-17 12:11:28 +0000 | [diff] [blame] | 226 | uintptr_t stack_limit_; |
| Ben Murdoch | 62ed631 | 2017-06-06 11:06:27 +0100 | [diff] [blame^] | 227 | bool executed_on_background_thread_; |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 228 | |
| Ben Murdoch | f91f061 | 2016-11-29 16:50:11 +0000 | [diff] [blame] | 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; |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 236 | } |
| Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 237 | }; |
| 238 | |
| Ben Murdoch | 014dc51 | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 239 | } // namespace internal |
| 240 | } // namespace v8 |
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 241 | |
| 242 | #endif // V8_COMPILER_H_ |