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 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()}. 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, CompilationInfo* info, 169 const char* compiler_name, 170 State initial_state = State::kReadyToPrepare); ~CompilationJob()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 can_execute_on_background_thread()194 virtual bool can_execute_on_background_thread() const { return true; } 195 set_stack_limit(uintptr_t stack_limit)196 void set_stack_limit(uintptr_t stack_limit) { stack_limit_ = stack_limit; } stack_limit()197 uintptr_t stack_limit() const { return stack_limit_; } 198 executed_on_background_thread()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 } state()204 State state() const { return state_; } info()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 UpdateState(Status status,State next_state)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