Home | History | Annotate | Download | only in src
      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 
    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 
    170   Isolate* isolate() const {
    171     return isolate_;
    172   }
    173   Zone* zone() { return zone_; }
    174   bool is_osr() const { return !osr_ast_id_.IsNone(); }
    175   Handle<JSFunction> closure() const { return closure_; }
    176   Handle<Code> code() const { return code_; }
    177   Code::Flags code_flags() const { return code_flags_; }
    178   BailoutId osr_ast_id() const { return osr_ast_id_; }
    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 
    184   void set_parameter_count(int parameter_count) {
    185     DCHECK(IsStub());
    186     parameter_count_ = parameter_count;
    187   }
    188 
    189   bool has_bytecode_array() const { return !bytecode_array_.is_null(); }
    190   Handle<BytecodeArray> bytecode_array() const { return bytecode_array_; }
    191 
    192   bool is_tracking_positions() const { return track_positions_; }
    193 
    194   bool is_calling() const {
    195     return GetFlag(kDeferredCalling) || GetFlag(kNonDeferredCalling);
    196   }
    197 
    198   void MarkAsDeferredCalling() { SetFlag(kDeferredCalling); }
    199 
    200   bool is_deferred_calling() const { return GetFlag(kDeferredCalling); }
    201 
    202   void MarkAsNonDeferredCalling() { SetFlag(kNonDeferredCalling); }
    203 
    204   bool is_non_deferred_calling() const { return GetFlag(kNonDeferredCalling); }
    205 
    206   void MarkAsSavesCallerDoubles() { SetFlag(kSavesCallerDoubles); }
    207 
    208   bool saves_caller_doubles() const { return GetFlag(kSavesCallerDoubles); }
    209 
    210   void MarkAsRequiresFrame() { SetFlag(kRequiresFrame); }
    211 
    212   bool requires_frame() const { return GetFlag(kRequiresFrame); }
    213 
    214   void MarkMustNotHaveEagerFrame() { SetFlag(kMustNotHaveEagerFrame); }
    215 
    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.
    223   void MarkAsDebug() {
    224     SetFlag(kDebug);
    225     SetFlag(kDeoptimizationSupport);
    226   }
    227 
    228   bool is_debug() const { return GetFlag(kDebug); }
    229 
    230   void PrepareForSerializing() { SetFlag(kSerializing); }
    231 
    232   bool will_serialize() const { return GetFlag(kSerializing); }
    233 
    234   void MarkAsFunctionContextSpecializing() {
    235     SetFlag(kFunctionContextSpecializing);
    236   }
    237 
    238   bool is_function_context_specializing() const {
    239     return GetFlag(kFunctionContextSpecializing);
    240   }
    241 
    242   void MarkAsFrameSpecializing() { SetFlag(kFrameSpecializing); }
    243 
    244   bool is_frame_specializing() const { return GetFlag(kFrameSpecializing); }
    245 
    246   void MarkAsNativeContextSpecializing() {
    247     SetFlag(kNativeContextSpecializing);
    248   }
    249 
    250   bool is_native_context_specializing() const {
    251     return GetFlag(kNativeContextSpecializing);
    252   }
    253 
    254   void MarkAsDeoptimizationEnabled() { SetFlag(kDeoptimizationEnabled); }
    255 
    256   bool is_deoptimization_enabled() const {
    257     return GetFlag(kDeoptimizationEnabled);
    258   }
    259 
    260   void MarkAsTypeFeedbackEnabled() { SetFlag(kTypeFeedbackEnabled); }
    261 
    262   bool is_type_feedback_enabled() const {
    263     return GetFlag(kTypeFeedbackEnabled);
    264   }
    265 
    266   void MarkAsSourcePositionsEnabled() { SetFlag(kSourcePositionsEnabled); }
    267 
    268   bool is_source_positions_enabled() const {
    269     return GetFlag(kSourcePositionsEnabled);
    270   }
    271 
    272   void MarkAsInliningEnabled() { SetFlag(kInliningEnabled); }
    273 
    274   bool is_inlining_enabled() const { return GetFlag(kInliningEnabled); }
    275 
    276   void MarkAsSplittingEnabled() { SetFlag(kSplittingEnabled); }
    277 
    278   bool is_splitting_enabled() const { return GetFlag(kSplittingEnabled); }
    279 
    280   void MarkAsBailoutOnUninitialized() { SetFlag(kBailoutOnUninitialized); }
    281 
    282   bool is_bailout_on_uninitialized() const {
    283     return GetFlag(kBailoutOnUninitialized);
    284   }
    285 
    286   void MarkAsOptimizeFromBytecode() { SetFlag(kOptimizeFromBytecode); }
    287 
    288   bool is_optimizing_from_bytecode() const {
    289     return GetFlag(kOptimizeFromBytecode);
    290   }
    291 
    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 
    300   void SetCode(Handle<Code> code) { code_ = code; }
    301 
    302   void SetBytecodeArray(Handle<BytecodeArray> bytecode_array) {
    303     bytecode_array_ = bytecode_array;
    304   }
    305 
    306   bool ShouldTrapOnDeopt() const {
    307     return (FLAG_trap_on_deopt && IsOptimizing()) ||
    308         (FLAG_trap_on_stub_deopt && IsStub());
    309   }
    310 
    311   bool has_native_context() const {
    312     return !closure().is_null() && (closure()->native_context() != nullptr);
    313   }
    314 
    315   Context* native_context() const {
    316     return has_native_context() ? closure()->native_context() : nullptr;
    317   }
    318 
    319   bool has_global_object() const { return has_native_context(); }
    320 
    321   JSGlobalObject* global_object() const {
    322     return has_global_object() ? native_context()->global_object() : nullptr;
    323   }
    324 
    325   // Accessors for the different compilation modes.
    326   bool IsOptimizing() const { return mode_ == OPTIMIZE; }
    327   bool IsStub() const { return mode_ == STUB; }
    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   }
    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.
    342   bool HasDeoptimizationSupport() const {
    343     return GetFlag(kDeoptimizationSupport);
    344   }
    345   void EnableDeoptimizationSupport() {
    346     DCHECK_EQ(BASE, mode_);
    347     SetFlag(kDeoptimizationSupport);
    348   }
    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 
    356   void set_deferred_handles(DeferredHandles* deferred_handles) {
    357     DCHECK(deferred_handles_ == NULL);
    358     deferred_handles_ = deferred_handles;
    359   }
    360 
    361   void ReopenHandlesInNewHandleScope() {
    362     closure_ = Handle<JSFunction>(*closure_);
    363   }
    364 
    365   void AbortOptimization(BailoutReason reason) {
    366     DCHECK(reason != kNoReason);
    367     if (bailout_reason_ == kNoReason) bailout_reason_ = reason;
    368     SetFlag(kDisableFutureOptimization);
    369   }
    370 
    371   void RetryOptimization(BailoutReason reason) {
    372     DCHECK(reason != kNoReason);
    373     if (GetFlag(kDisableFutureOptimization)) return;
    374     bailout_reason_ = reason;
    375   }
    376 
    377   BailoutReason bailout_reason() const { return bailout_reason_; }
    378 
    379   int prologue_offset() const {
    380     DCHECK_NE(Code::kPrologueOffsetNotSet, prologue_offset_);
    381     return prologue_offset_;
    382   }
    383 
    384   void set_prologue_offset(int prologue_offset) {
    385     DCHECK_EQ(Code::kPrologueOffsetNotSet, prologue_offset_);
    386     prologue_offset_ = prologue_offset;
    387   }
    388 
    389   CompilationDependencies* dependencies() { return &dependencies_; }
    390 
    391   int optimization_id() const { return optimization_id_; }
    392 
    393   int osr_expr_stack_height() { return osr_expr_stack_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 
    413     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;
    420   InlinedFunctionList const& inlined_functions() const {
    421     return inlined_functions_;
    422   }
    423 
    424   void AddInlinedFunction(Handle<SharedFunctionInfo> inlined_function) {
    425     inlined_functions_.push_back(InlinedFunctionHolder(inlined_function));
    426   }
    427 
    428   base::SmartArrayPointer<char> GetDebugName() const;
    429 
    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 
    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 
    475   void SetMode(Mode mode) {
    476     mode_ = mode;
    477   }
    478 
    479   void SetFlag(Flag flag) { flags_ |= flag; }
    480 
    481   void SetFlag(Flag flag, bool value) {
    482     flags_ = value ? flags_ | flag : flags_ & ~flag;
    483   }
    484 
    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:
    551   explicit CompilationJob(CompilationInfo* info, const char* compiler_name)
    552       : info_(info), compiler_name_(compiler_name), last_status_(SUCCEEDED) {}
    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 
    561   Status last_status() const { return last_status_; }
    562   CompilationInfo* info() const { return info_; }
    563   Isolate* isolate() const { return info()->isolate(); }
    564 
    565   Status RetryOptimization(BailoutReason reason) {
    566     info_->RetryOptimization(reason);
    567     return SetLastStatus(FAILED);
    568   }
    569 
    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 
    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