• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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