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 "src/allocation.h" 9 #include "src/ast/ast.h" 10 #include "src/bailout-reason.h" 11 #include "src/compilation-dependencies.h" 12 #include "src/source-position.h" 13 #include "src/zone.h" 14 15 namespace v8 { 16 namespace internal { 17 18 // Forward declarations. 19 class CompilationInfo; 20 class CompilationJob; 21 class JavaScriptFrame; 22 class ParseInfo; 23 class ScriptData; 24 25 // The V8 compiler API. 26 // 27 // This is the central hub for dispatching to the various compilers within V8. 28 // Logic for which compiler to choose and how to wire compilation results into 29 // the object heap should be kept inside this class. 30 // 31 // General strategy: Scripts are translated into anonymous functions w/o 32 // parameters which then can be executed. If the source code contains other 33 // functions, they might be compiled and allocated as part of the compilation 34 // of the source code or deferred for lazy compilation at a later point. 35 class Compiler : public AllStatic { 36 public: 37 enum ClearExceptionFlag { KEEP_EXCEPTION, CLEAR_EXCEPTION }; 38 enum ConcurrencyMode { NOT_CONCURRENT, CONCURRENT }; 39 40 // =========================================================================== 41 // The following family of methods ensures a given function is compiled. The 42 // general contract is that failures will be reported by returning {false}, 43 // whereas successful compilation ensures the {is_compiled} predicate on the 44 // given function holds (except for live-edit, which compiles the world). 45 46 static bool Compile(Handle<JSFunction> function, ClearExceptionFlag flag); 47 static bool CompileBaseline(Handle<JSFunction> function); 48 static bool CompileOptimized(Handle<JSFunction> function, ConcurrencyMode); 49 static bool CompileDebugCode(Handle<JSFunction> function); 50 static bool CompileDebugCode(Handle<SharedFunctionInfo> shared); 51 static MaybeHandle<JSArray> CompileForLiveEdit(Handle<Script> script); 52 53 // Generate and install code from previously queued compilation job. 54 static void FinalizeCompilationJob(CompilationJob* job); 55 56 // Give the compiler a chance to perform low-latency initialization tasks of 57 // the given {function} on its instantiation. Note that only the runtime will 58 // offer this chance, optimized closure instantiation will not call this. 59 static void PostInstantiation(Handle<JSFunction> function, PretenureFlag); 60 61 // Parser::Parse, then Compiler::Analyze. 62 static bool ParseAndAnalyze(ParseInfo* info); 63 // Rewrite, analyze scopes, and renumber. 64 static bool Analyze(ParseInfo* info); 65 // Adds deoptimization support, requires ParseAndAnalyze. 66 static bool EnsureDeoptimizationSupport(CompilationInfo* info); 67 68 // =========================================================================== 69 // The following family of methods instantiates new functions for scripts or 70 // function literals. The decision whether those functions will be compiled, 71 // is left to the discretion of the compiler. 72 // 73 // Please note this interface returns shared function infos. This means you 74 // need to call Factory::NewFunctionFromSharedFunctionInfo before you have a 75 // real function with a context. 76 77 // Create a (bound) function for a String source within a context for eval. 78 MUST_USE_RESULT static MaybeHandle<JSFunction> GetFunctionFromEval( 79 Handle<String> source, Handle<SharedFunctionInfo> outer_info, 80 Handle<Context> context, LanguageMode language_mode, 81 ParseRestriction restriction, int eval_scope_position, int eval_position, 82 int line_offset = 0, int column_offset = 0, 83 Handle<Object> script_name = Handle<Object>(), 84 ScriptOriginOptions options = ScriptOriginOptions()); 85 86 // Create a shared function info object for a String source within a context. 87 static Handle<SharedFunctionInfo> GetSharedFunctionInfoForScript( 88 Handle<String> source, Handle<Object> script_name, int line_offset, 89 int column_offset, ScriptOriginOptions resource_options, 90 Handle<Object> source_map_url, Handle<Context> context, 91 v8::Extension* extension, ScriptData** cached_data, 92 ScriptCompiler::CompileOptions compile_options, 93 NativesFlag is_natives_code, bool is_module); 94 95 // Create a shared function info object for a Script that has already been 96 // parsed while the script was being loaded from a streamed source. 97 static Handle<SharedFunctionInfo> GetSharedFunctionInfoForStreamedScript( 98 Handle<Script> script, ParseInfo* info, int source_length); 99 100 // Create a shared function info object (the code may be lazily compiled). 101 static Handle<SharedFunctionInfo> GetSharedFunctionInfo( 102 FunctionLiteral* node, Handle<Script> script, CompilationInfo* outer); 103 104 // Create a shared function info object for a native function literal. 105 static Handle<SharedFunctionInfo> GetSharedFunctionInfoForNative( 106 v8::Extension* extension, Handle<String> name); 107 108 // =========================================================================== 109 // The following family of methods provides support for OSR. Code generated 110 // for entry via OSR might not be suitable for normal entry, hence will be 111 // returned directly to the caller. 112 // 113 // Please note this interface is the only part dealing with {Code} objects 114 // directly. Other methods are agnostic to {Code} and can use an interpreter 115 // instead of generating JIT code for a function at all. 116 117 // Generate and return optimized code for OSR, or empty handle on failure. 118 MUST_USE_RESULT static MaybeHandle<Code> GetOptimizedCodeForOSR( 119 Handle<JSFunction> function, BailoutId osr_ast_id, 120 JavaScriptFrame* osr_frame); 121 }; 122 123 124 // CompilationInfo encapsulates some information known at compile time. It 125 // is constructed based on the resources available at compile-time. 126 class CompilationInfo final { 127 public: 128 // Various configuration flags for a compilation, as well as some properties 129 // of the compiled code produced by a compilation. 130 enum Flag { 131 kDeferredCalling = 1 << 0, 132 kNonDeferredCalling = 1 << 1, 133 kSavesCallerDoubles = 1 << 2, 134 kRequiresFrame = 1 << 3, 135 kMustNotHaveEagerFrame = 1 << 4, 136 kDeoptimizationSupport = 1 << 5, 137 kDebug = 1 << 6, 138 kSerializing = 1 << 7, 139 kFunctionContextSpecializing = 1 << 8, 140 kFrameSpecializing = 1 << 9, 141 kNativeContextSpecializing = 1 << 10, 142 kInliningEnabled = 1 << 11, 143 kDisableFutureOptimization = 1 << 12, 144 kSplittingEnabled = 1 << 13, 145 kDeoptimizationEnabled = 1 << 14, 146 kSourcePositionsEnabled = 1 << 15, 147 kBailoutOnUninitialized = 1 << 16, 148 kOptimizeFromBytecode = 1 << 17, 149 kTypeFeedbackEnabled = 1 << 18, 150 }; 151 152 CompilationInfo(ParseInfo* parse_info, Handle<JSFunction> closure); 153 CompilationInfo(Vector<const char> debug_name, Isolate* isolate, Zone* zone, 154 Code::Flags code_flags = Code::ComputeFlags(Code::STUB)); 155 ~CompilationInfo(); 156 parse_info()157 ParseInfo* parse_info() const { return parse_info_; } 158 159 // ----------------------------------------------------------- 160 // TODO(titzer): inline and delete accessors of ParseInfo 161 // ----------------------------------------------------------- 162 Handle<Script> script() const; 163 FunctionLiteral* literal() const; 164 Scope* scope() const; 165 Handle<Context> context() const; 166 Handle<SharedFunctionInfo> shared_info() const; 167 bool has_shared_info() const; 168 // ----------------------------------------------------------- 169 isolate()170 Isolate* isolate() const { 171 return isolate_; 172 } zone()173 Zone* zone() { return zone_; } is_osr()174 bool is_osr() const { return !osr_ast_id_.IsNone(); } closure()175 Handle<JSFunction> closure() const { return closure_; } code()176 Handle<Code> code() const { return code_; } code_flags()177 Code::Flags code_flags() const { return code_flags_; } osr_ast_id()178 BailoutId osr_ast_id() const { return osr_ast_id_; } osr_frame()179 JavaScriptFrame* osr_frame() const { return osr_frame_; } 180 int num_parameters() const; 181 int num_parameters_including_this() const; 182 bool is_this_defined() const; 183 set_parameter_count(int parameter_count)184 void set_parameter_count(int parameter_count) { 185 DCHECK(IsStub()); 186 parameter_count_ = parameter_count; 187 } 188 has_bytecode_array()189 bool has_bytecode_array() const { return !bytecode_array_.is_null(); } bytecode_array()190 Handle<BytecodeArray> bytecode_array() const { return bytecode_array_; } 191 is_tracking_positions()192 bool is_tracking_positions() const { return track_positions_; } 193 is_calling()194 bool is_calling() const { 195 return GetFlag(kDeferredCalling) || GetFlag(kNonDeferredCalling); 196 } 197 MarkAsDeferredCalling()198 void MarkAsDeferredCalling() { SetFlag(kDeferredCalling); } 199 is_deferred_calling()200 bool is_deferred_calling() const { return GetFlag(kDeferredCalling); } 201 MarkAsNonDeferredCalling()202 void MarkAsNonDeferredCalling() { SetFlag(kNonDeferredCalling); } 203 is_non_deferred_calling()204 bool is_non_deferred_calling() const { return GetFlag(kNonDeferredCalling); } 205 MarkAsSavesCallerDoubles()206 void MarkAsSavesCallerDoubles() { SetFlag(kSavesCallerDoubles); } 207 saves_caller_doubles()208 bool saves_caller_doubles() const { return GetFlag(kSavesCallerDoubles); } 209 MarkAsRequiresFrame()210 void MarkAsRequiresFrame() { SetFlag(kRequiresFrame); } 211 requires_frame()212 bool requires_frame() const { return GetFlag(kRequiresFrame); } 213 MarkMustNotHaveEagerFrame()214 void MarkMustNotHaveEagerFrame() { SetFlag(kMustNotHaveEagerFrame); } 215 GetMustNotHaveEagerFrame()216 bool GetMustNotHaveEagerFrame() const { 217 return GetFlag(kMustNotHaveEagerFrame); 218 } 219 220 // Compiles marked as debug produce unoptimized code with debug break slots. 221 // Inner functions that cannot be compiled w/o context are compiled eagerly. 222 // Always include deoptimization support to avoid having to recompile again. MarkAsDebug()223 void MarkAsDebug() { 224 SetFlag(kDebug); 225 SetFlag(kDeoptimizationSupport); 226 } 227 is_debug()228 bool is_debug() const { return GetFlag(kDebug); } 229 PrepareForSerializing()230 void PrepareForSerializing() { SetFlag(kSerializing); } 231 will_serialize()232 bool will_serialize() const { return GetFlag(kSerializing); } 233 MarkAsFunctionContextSpecializing()234 void MarkAsFunctionContextSpecializing() { 235 SetFlag(kFunctionContextSpecializing); 236 } 237 is_function_context_specializing()238 bool is_function_context_specializing() const { 239 return GetFlag(kFunctionContextSpecializing); 240 } 241 MarkAsFrameSpecializing()242 void MarkAsFrameSpecializing() { SetFlag(kFrameSpecializing); } 243 is_frame_specializing()244 bool is_frame_specializing() const { return GetFlag(kFrameSpecializing); } 245 MarkAsNativeContextSpecializing()246 void MarkAsNativeContextSpecializing() { 247 SetFlag(kNativeContextSpecializing); 248 } 249 is_native_context_specializing()250 bool is_native_context_specializing() const { 251 return GetFlag(kNativeContextSpecializing); 252 } 253 MarkAsDeoptimizationEnabled()254 void MarkAsDeoptimizationEnabled() { SetFlag(kDeoptimizationEnabled); } 255 is_deoptimization_enabled()256 bool is_deoptimization_enabled() const { 257 return GetFlag(kDeoptimizationEnabled); 258 } 259 MarkAsTypeFeedbackEnabled()260 void MarkAsTypeFeedbackEnabled() { SetFlag(kTypeFeedbackEnabled); } 261 is_type_feedback_enabled()262 bool is_type_feedback_enabled() const { 263 return GetFlag(kTypeFeedbackEnabled); 264 } 265 MarkAsSourcePositionsEnabled()266 void MarkAsSourcePositionsEnabled() { SetFlag(kSourcePositionsEnabled); } 267 is_source_positions_enabled()268 bool is_source_positions_enabled() const { 269 return GetFlag(kSourcePositionsEnabled); 270 } 271 MarkAsInliningEnabled()272 void MarkAsInliningEnabled() { SetFlag(kInliningEnabled); } 273 is_inlining_enabled()274 bool is_inlining_enabled() const { return GetFlag(kInliningEnabled); } 275 MarkAsSplittingEnabled()276 void MarkAsSplittingEnabled() { SetFlag(kSplittingEnabled); } 277 is_splitting_enabled()278 bool is_splitting_enabled() const { return GetFlag(kSplittingEnabled); } 279 MarkAsBailoutOnUninitialized()280 void MarkAsBailoutOnUninitialized() { SetFlag(kBailoutOnUninitialized); } 281 is_bailout_on_uninitialized()282 bool is_bailout_on_uninitialized() const { 283 return GetFlag(kBailoutOnUninitialized); 284 } 285 MarkAsOptimizeFromBytecode()286 void MarkAsOptimizeFromBytecode() { SetFlag(kOptimizeFromBytecode); } 287 is_optimizing_from_bytecode()288 bool is_optimizing_from_bytecode() const { 289 return GetFlag(kOptimizeFromBytecode); 290 } 291 GeneratePreagedPrologue()292 bool GeneratePreagedPrologue() const { 293 // Generate a pre-aged prologue if we are optimizing for size, which 294 // will make code flushing more aggressive. Only apply to Code::FUNCTION, 295 // since StaticMarkingVisitor::IsFlushable only flushes proper functions. 296 return FLAG_optimize_for_size && FLAG_age_code && !is_debug() && 297 output_code_kind() == Code::FUNCTION; 298 } 299 SetCode(Handle<Code> code)300 void SetCode(Handle<Code> code) { code_ = code; } 301 SetBytecodeArray(Handle<BytecodeArray> bytecode_array)302 void SetBytecodeArray(Handle<BytecodeArray> bytecode_array) { 303 bytecode_array_ = bytecode_array; 304 } 305 ShouldTrapOnDeopt()306 bool ShouldTrapOnDeopt() const { 307 return (FLAG_trap_on_deopt && IsOptimizing()) || 308 (FLAG_trap_on_stub_deopt && IsStub()); 309 } 310 has_native_context()311 bool has_native_context() const { 312 return !closure().is_null() && (closure()->native_context() != nullptr); 313 } 314 native_context()315 Context* native_context() const { 316 return has_native_context() ? closure()->native_context() : nullptr; 317 } 318 has_global_object()319 bool has_global_object() const { return has_native_context(); } 320 global_object()321 JSGlobalObject* global_object() const { 322 return has_global_object() ? native_context()->global_object() : nullptr; 323 } 324 325 // Accessors for the different compilation modes. IsOptimizing()326 bool IsOptimizing() const { return mode_ == OPTIMIZE; } IsStub()327 bool IsStub() const { return mode_ == STUB; } SetOptimizing()328 void SetOptimizing() { 329 DCHECK(has_shared_info()); 330 SetMode(OPTIMIZE); 331 optimization_id_ = isolate()->NextOptimizationId(); 332 code_flags_ = 333 Code::KindField::update(code_flags_, Code::OPTIMIZED_FUNCTION); 334 } SetOptimizingForOsr(BailoutId osr_ast_id,JavaScriptFrame * osr_frame)335 void SetOptimizingForOsr(BailoutId osr_ast_id, JavaScriptFrame* osr_frame) { 336 SetOptimizing(); 337 osr_ast_id_ = osr_ast_id; 338 osr_frame_ = osr_frame; 339 } 340 341 // Deoptimization support. HasDeoptimizationSupport()342 bool HasDeoptimizationSupport() const { 343 return GetFlag(kDeoptimizationSupport); 344 } EnableDeoptimizationSupport()345 void EnableDeoptimizationSupport() { 346 DCHECK_EQ(BASE, mode_); 347 SetFlag(kDeoptimizationSupport); 348 } ShouldEnsureSpaceForLazyDeopt()349 bool ShouldEnsureSpaceForLazyDeopt() { return !IsStub(); } 350 351 bool ExpectsJSReceiverAsReceiver(); 352 353 // Determines whether or not to insert a self-optimization header. 354 bool ShouldSelfOptimize(); 355 set_deferred_handles(DeferredHandles * deferred_handles)356 void set_deferred_handles(DeferredHandles* deferred_handles) { 357 DCHECK(deferred_handles_ == NULL); 358 deferred_handles_ = deferred_handles; 359 } 360 ReopenHandlesInNewHandleScope()361 void ReopenHandlesInNewHandleScope() { 362 closure_ = Handle<JSFunction>(*closure_); 363 } 364 AbortOptimization(BailoutReason reason)365 void AbortOptimization(BailoutReason reason) { 366 DCHECK(reason != kNoReason); 367 if (bailout_reason_ == kNoReason) bailout_reason_ = reason; 368 SetFlag(kDisableFutureOptimization); 369 } 370 RetryOptimization(BailoutReason reason)371 void RetryOptimization(BailoutReason reason) { 372 DCHECK(reason != kNoReason); 373 if (GetFlag(kDisableFutureOptimization)) return; 374 bailout_reason_ = reason; 375 } 376 bailout_reason()377 BailoutReason bailout_reason() const { return bailout_reason_; } 378 prologue_offset()379 int prologue_offset() const { 380 DCHECK_NE(Code::kPrologueOffsetNotSet, prologue_offset_); 381 return prologue_offset_; 382 } 383 set_prologue_offset(int prologue_offset)384 void set_prologue_offset(int prologue_offset) { 385 DCHECK_EQ(Code::kPrologueOffsetNotSet, prologue_offset_); 386 prologue_offset_ = prologue_offset; 387 } 388 dependencies()389 CompilationDependencies* dependencies() { return &dependencies_; } 390 optimization_id()391 int optimization_id() const { return optimization_id_; } 392 osr_expr_stack_height()393 int osr_expr_stack_height() { return osr_expr_stack_height_; } set_osr_expr_stack_height(int height)394 void set_osr_expr_stack_height(int height) { 395 DCHECK(height >= 0); 396 osr_expr_stack_height_ = height; 397 } 398 399 #if DEBUG 400 void PrintAstForTesting(); 401 #endif 402 403 bool has_simple_parameters(); 404 405 struct InlinedFunctionHolder { 406 Handle<SharedFunctionInfo> shared_info; 407 408 // Root that holds the unoptimized code of the inlined function alive 409 // (and out of reach of code flushing) until we finish compilation. 410 // Do not remove. 411 Handle<Code> inlined_code_object_root; 412 InlinedFunctionHolderInlinedFunctionHolder413 explicit InlinedFunctionHolder( 414 Handle<SharedFunctionInfo> inlined_shared_info) 415 : shared_info(inlined_shared_info), 416 inlined_code_object_root(inlined_shared_info->code()) {} 417 }; 418 419 typedef std::vector<InlinedFunctionHolder> InlinedFunctionList; inlined_functions()420 InlinedFunctionList const& inlined_functions() const { 421 return inlined_functions_; 422 } 423 AddInlinedFunction(Handle<SharedFunctionInfo> inlined_function)424 void AddInlinedFunction(Handle<SharedFunctionInfo> inlined_function) { 425 inlined_functions_.push_back(InlinedFunctionHolder(inlined_function)); 426 } 427 428 base::SmartArrayPointer<char> GetDebugName() const; 429 output_code_kind()430 Code::Kind output_code_kind() const { 431 return Code::ExtractKindFromFlags(code_flags_); 432 } 433 434 StackFrame::Type GetOutputStackFrameType() const; 435 436 int GetDeclareGlobalsFlags() const; 437 438 protected: 439 ParseInfo* parse_info_; 440 DisableFutureOptimization()441 void DisableFutureOptimization() { 442 if (GetFlag(kDisableFutureOptimization) && has_shared_info()) { 443 // If Crankshaft tried to optimize this function, bailed out, and 444 // doesn't want to try again, then use TurboFan next time. 445 if (!shared_info()->dont_crankshaft() && 446 bailout_reason() != kOptimizedTooManyTimes) { 447 shared_info()->set_dont_crankshaft(true); 448 if (FLAG_trace_opt) { 449 PrintF("[disabled Crankshaft for "); 450 shared_info()->ShortPrint(); 451 PrintF(", reason: %s]\n", GetBailoutReason(bailout_reason())); 452 } 453 } else { 454 shared_info()->DisableOptimization(bailout_reason()); 455 } 456 } 457 } 458 459 private: 460 // Compilation mode. 461 // BASE is generated by the full codegen, optionally prepared for bailouts. 462 // OPTIMIZE is optimized code generated by the Hydrogen-based backend. 463 enum Mode { 464 BASE, 465 OPTIMIZE, 466 STUB 467 }; 468 469 CompilationInfo(ParseInfo* parse_info, Vector<const char> debug_name, 470 Code::Flags code_flags, Mode mode, Isolate* isolate, 471 Zone* zone); 472 473 Isolate* isolate_; 474 SetMode(Mode mode)475 void SetMode(Mode mode) { 476 mode_ = mode; 477 } 478 SetFlag(Flag flag)479 void SetFlag(Flag flag) { flags_ |= flag; } 480 SetFlag(Flag flag,bool value)481 void SetFlag(Flag flag, bool value) { 482 flags_ = value ? flags_ | flag : flags_ & ~flag; 483 } 484 GetFlag(Flag flag)485 bool GetFlag(Flag flag) const { return (flags_ & flag) != 0; } 486 487 unsigned flags_; 488 489 Code::Flags code_flags_; 490 491 Handle<JSFunction> closure_; 492 493 // The compiled code. 494 Handle<Code> code_; 495 496 // Compilation mode flag and whether deoptimization is allowed. 497 Mode mode_; 498 BailoutId osr_ast_id_; 499 500 // Holds the bytecode array generated by the interpreter. 501 // TODO(rmcilroy/mstarzinger): Temporary work-around until compiler.cc is 502 // refactored to avoid us needing to carry the BytcodeArray around. 503 Handle<BytecodeArray> bytecode_array_; 504 505 // The zone from which the compilation pipeline working on this 506 // CompilationInfo allocates. 507 Zone* zone_; 508 509 DeferredHandles* deferred_handles_; 510 511 // Dependencies for this compilation, e.g. stable maps. 512 CompilationDependencies dependencies_; 513 514 BailoutReason bailout_reason_; 515 516 int prologue_offset_; 517 518 bool track_positions_; 519 520 InlinedFunctionList inlined_functions_; 521 522 // Number of parameters used for compilation of stubs that require arguments. 523 int parameter_count_; 524 525 int optimization_id_; 526 527 int osr_expr_stack_height_; 528 529 // The current OSR frame for specialization or {nullptr}. 530 JavaScriptFrame* osr_frame_ = nullptr; 531 532 Vector<const char> debug_name_; 533 534 DISALLOW_COPY_AND_ASSIGN(CompilationInfo); 535 }; 536 537 // A base class for compilation jobs intended to run concurrent to the main 538 // thread. The job is split into three phases which are called in sequence on 539 // different threads and with different limitations: 540 // 1) CreateGraph: Runs on main thread. No major limitations. 541 // 2) OptimizeGraph: Runs concurrently. No heap allocation or handle derefs. 542 // 3) GenerateCode: Runs on main thread. No dependency changes. 543 // 544 // Each of the three phases can either fail or succeed. Apart from their return 545 // value, the status of the phase last run can be checked using {last_status()} 546 // as well. When failing we distinguish between the following levels: 547 // a) AbortOptimization: Persistent failure, disable future optimization. 548 // b) RetryOptimzation: Transient failure, try again next time. 549 class CompilationJob { 550 public: CompilationJob(CompilationInfo * info,const char * compiler_name)551 explicit CompilationJob(CompilationInfo* info, const char* compiler_name) 552 : info_(info), compiler_name_(compiler_name), last_status_(SUCCEEDED) {} ~CompilationJob()553 virtual ~CompilationJob() {} 554 555 enum Status { FAILED, SUCCEEDED }; 556 557 MUST_USE_RESULT Status CreateGraph(); 558 MUST_USE_RESULT Status OptimizeGraph(); 559 MUST_USE_RESULT Status GenerateCode(); 560 last_status()561 Status last_status() const { return last_status_; } info()562 CompilationInfo* info() const { return info_; } isolate()563 Isolate* isolate() const { return info()->isolate(); } 564 RetryOptimization(BailoutReason reason)565 Status RetryOptimization(BailoutReason reason) { 566 info_->RetryOptimization(reason); 567 return SetLastStatus(FAILED); 568 } 569 AbortOptimization(BailoutReason reason)570 Status AbortOptimization(BailoutReason reason) { 571 info_->AbortOptimization(reason); 572 return SetLastStatus(FAILED); 573 } 574 575 void RecordOptimizationStats(); 576 577 protected: 578 void RegisterWeakObjectsInOptimizedCode(Handle<Code> code); 579 580 // Overridden by the actual implementation. 581 virtual Status CreateGraphImpl() = 0; 582 virtual Status OptimizeGraphImpl() = 0; 583 virtual Status GenerateCodeImpl() = 0; 584 585 private: 586 CompilationInfo* info_; 587 base::TimeDelta time_taken_to_create_graph_; 588 base::TimeDelta time_taken_to_optimize_; 589 base::TimeDelta time_taken_to_codegen_; 590 const char* compiler_name_; 591 Status last_status_; 592 SetLastStatus(Status status)593 MUST_USE_RESULT Status SetLastStatus(Status status) { 594 last_status_ = status; 595 return last_status_; 596 } 597 }; 598 599 } // namespace internal 600 } // namespace v8 601 602 #endif // V8_COMPILER_H_ 603