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