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/signature.h"
13 #include "src/zone.h"
14 
15 namespace v8 {
16 namespace internal {
17 
18 class AstValueFactory;
19 class HydrogenCodeStub;
20 class JavaScriptFrame;
21 class ParseInfo;
22 class ScriptData;
23 
24 
25 // This class encapsulates encoding and decoding of sources positions from
26 // which hydrogen values originated.
27 // When FLAG_track_hydrogen_positions is set this object encodes the
28 // identifier of the inlining and absolute offset from the start of the
29 // inlined function.
30 // When the flag is not set we simply track absolute offset from the
31 // script start.
32 class SourcePosition {
33  public:
Unknown()34   static SourcePosition Unknown() {
35     return SourcePosition::FromRaw(kNoPosition);
36   }
37 
IsUnknown()38   bool IsUnknown() const { return value_ == kNoPosition; }
39 
position()40   uint32_t position() const { return PositionField::decode(value_); }
set_position(uint32_t position)41   void set_position(uint32_t position) {
42     if (FLAG_hydrogen_track_positions) {
43       value_ = static_cast<uint32_t>(PositionField::update(value_, position));
44     } else {
45       value_ = position;
46     }
47   }
48 
inlining_id()49   uint32_t inlining_id() const { return InliningIdField::decode(value_); }
set_inlining_id(uint32_t inlining_id)50   void set_inlining_id(uint32_t inlining_id) {
51     if (FLAG_hydrogen_track_positions) {
52       value_ =
53           static_cast<uint32_t>(InliningIdField::update(value_, inlining_id));
54     }
55   }
56 
raw()57   uint32_t raw() const { return value_; }
58 
59  private:
60   static const uint32_t kNoPosition =
61       static_cast<uint32_t>(RelocInfo::kNoPosition);
62   typedef BitField<uint32_t, 0, 9> InliningIdField;
63 
64   // Offset from the start of the inlined function.
65   typedef BitField<uint32_t, 9, 23> PositionField;
66 
67   friend class HPositionInfo;
68   friend class Deoptimizer;
69 
FromRaw(uint32_t raw_position)70   static SourcePosition FromRaw(uint32_t raw_position) {
71     SourcePosition position;
72     position.value_ = raw_position;
73     return position;
74   }
75 
76   // If FLAG_hydrogen_track_positions is set contains bitfields InliningIdField
77   // and PositionField.
78   // Otherwise contains absolute offset from the script start.
79   uint32_t value_;
80 };
81 
82 
83 std::ostream& operator<<(std::ostream& os, const SourcePosition& p);
84 
85 
86 struct InlinedFunctionInfo {
InlinedFunctionInfoInlinedFunctionInfo87   InlinedFunctionInfo(int parent_id, SourcePosition inline_position,
88                       int script_id, int start_position)
89       : parent_id(parent_id),
90         inline_position(inline_position),
91         script_id(script_id),
92         start_position(start_position) {}
93   int parent_id;
94   SourcePosition inline_position;
95   int script_id;
96   int start_position;
97   std::vector<size_t> deopt_pc_offsets;
98 
99   static const int kNoParentId = -1;
100 };
101 
102 
103 // CompilationInfo encapsulates some information known at compile time.  It
104 // is constructed based on the resources available at compile-time.
105 class CompilationInfo {
106  public:
107   // Various configuration flags for a compilation, as well as some properties
108   // of the compiled code produced by a compilation.
109   enum Flag {
110     kDeferredCalling = 1 << 0,
111     kNonDeferredCalling = 1 << 1,
112     kSavesCallerDoubles = 1 << 2,
113     kRequiresFrame = 1 << 3,
114     kMustNotHaveEagerFrame = 1 << 4,
115     kDeoptimizationSupport = 1 << 5,
116     kDebug = 1 << 6,
117     kSerializing = 1 << 7,
118     kFunctionContextSpecializing = 1 << 8,
119     kFrameSpecializing = 1 << 9,
120     kNativeContextSpecializing = 1 << 10,
121     kInliningEnabled = 1 << 11,
122     kTypingEnabled = 1 << 12,
123     kDisableFutureOptimization = 1 << 13,
124     kSplittingEnabled = 1 << 14,
125     kDeoptimizationEnabled = 1 << 16,
126     kSourcePositionsEnabled = 1 << 17,
127     kFirstCompile = 1 << 18,
128   };
129 
130   explicit CompilationInfo(ParseInfo* parse_info);
131   CompilationInfo(CodeStub* stub, Isolate* isolate, Zone* zone);
132   CompilationInfo(const char* debug_name, Isolate* isolate, Zone* zone);
133   virtual ~CompilationInfo();
134 
parse_info()135   ParseInfo* parse_info() const { return parse_info_; }
136 
137   // -----------------------------------------------------------
138   // TODO(titzer): inline and delete accessors of ParseInfo
139   // -----------------------------------------------------------
140   Handle<Script> script() const;
141   bool is_eval() const;
142   bool is_native() const;
143   bool is_module() const;
144   LanguageMode language_mode() const;
145   Handle<JSFunction> closure() const;
146   FunctionLiteral* literal() const;
147   Scope* scope() const;
148   Handle<Context> context() const;
149   Handle<SharedFunctionInfo> shared_info() const;
150   bool has_shared_info() const;
151   bool has_context() const;
152   bool has_literal() const;
153   bool has_scope() const;
154   // -----------------------------------------------------------
155 
isolate()156   Isolate* isolate() const {
157     return isolate_;
158   }
zone()159   Zone* zone() { return zone_; }
is_osr()160   bool is_osr() const { return !osr_ast_id_.IsNone(); }
code()161   Handle<Code> code() const { return code_; }
code_stub()162   CodeStub* code_stub() const { return code_stub_; }
osr_ast_id()163   BailoutId osr_ast_id() const { return osr_ast_id_; }
unoptimized_code()164   Handle<Code> unoptimized_code() const { return unoptimized_code_; }
opt_count()165   int opt_count() const { return opt_count_; }
166   int num_parameters() const;
167   int num_parameters_including_this() const;
168   bool is_this_defined() const;
169   int num_heap_slots() const;
170 
set_parameter_count(int parameter_count)171   void set_parameter_count(int parameter_count) {
172     DCHECK(IsStub());
173     parameter_count_ = parameter_count;
174   }
175 
has_bytecode_array()176   bool has_bytecode_array() const { return !bytecode_array_.is_null(); }
bytecode_array()177   Handle<BytecodeArray> bytecode_array() const { return bytecode_array_; }
178 
is_tracking_positions()179   bool is_tracking_positions() const { return track_positions_; }
180 
is_calling()181   bool is_calling() const {
182     return GetFlag(kDeferredCalling) || GetFlag(kNonDeferredCalling);
183   }
184 
MarkAsDeferredCalling()185   void MarkAsDeferredCalling() { SetFlag(kDeferredCalling); }
186 
is_deferred_calling()187   bool is_deferred_calling() const { return GetFlag(kDeferredCalling); }
188 
MarkAsNonDeferredCalling()189   void MarkAsNonDeferredCalling() { SetFlag(kNonDeferredCalling); }
190 
is_non_deferred_calling()191   bool is_non_deferred_calling() const { return GetFlag(kNonDeferredCalling); }
192 
MarkAsSavesCallerDoubles()193   void MarkAsSavesCallerDoubles() { SetFlag(kSavesCallerDoubles); }
194 
saves_caller_doubles()195   bool saves_caller_doubles() const { return GetFlag(kSavesCallerDoubles); }
196 
MarkAsRequiresFrame()197   void MarkAsRequiresFrame() { SetFlag(kRequiresFrame); }
198 
requires_frame()199   bool requires_frame() const { return GetFlag(kRequiresFrame); }
200 
MarkMustNotHaveEagerFrame()201   void MarkMustNotHaveEagerFrame() { SetFlag(kMustNotHaveEagerFrame); }
202 
GetMustNotHaveEagerFrame()203   bool GetMustNotHaveEagerFrame() const {
204     return GetFlag(kMustNotHaveEagerFrame);
205   }
206 
207   // Compiles marked as debug produce unoptimized code with debug break slots.
208   // Inner functions that cannot be compiled w/o context are compiled eagerly.
209   // Always include deoptimization support to avoid having to recompile again.
MarkAsDebug()210   void MarkAsDebug() {
211     SetFlag(kDebug);
212     SetFlag(kDeoptimizationSupport);
213   }
214 
is_debug()215   bool is_debug() const { return GetFlag(kDebug); }
216 
PrepareForSerializing()217   void PrepareForSerializing() { SetFlag(kSerializing); }
218 
will_serialize()219   bool will_serialize() const { return GetFlag(kSerializing); }
220 
MarkAsFunctionContextSpecializing()221   void MarkAsFunctionContextSpecializing() {
222     SetFlag(kFunctionContextSpecializing);
223   }
224 
is_function_context_specializing()225   bool is_function_context_specializing() const {
226     return GetFlag(kFunctionContextSpecializing);
227   }
228 
MarkAsFrameSpecializing()229   void MarkAsFrameSpecializing() { SetFlag(kFrameSpecializing); }
230 
is_frame_specializing()231   bool is_frame_specializing() const { return GetFlag(kFrameSpecializing); }
232 
MarkAsNativeContextSpecializing()233   void MarkAsNativeContextSpecializing() {
234     SetFlag(kNativeContextSpecializing);
235   }
236 
is_native_context_specializing()237   bool is_native_context_specializing() const {
238     return GetFlag(kNativeContextSpecializing);
239   }
240 
MarkAsDeoptimizationEnabled()241   void MarkAsDeoptimizationEnabled() { SetFlag(kDeoptimizationEnabled); }
242 
is_deoptimization_enabled()243   bool is_deoptimization_enabled() const {
244     return GetFlag(kDeoptimizationEnabled);
245   }
246 
MarkAsSourcePositionsEnabled()247   void MarkAsSourcePositionsEnabled() { SetFlag(kSourcePositionsEnabled); }
248 
is_source_positions_enabled()249   bool is_source_positions_enabled() const {
250     return GetFlag(kSourcePositionsEnabled);
251   }
252 
MarkAsInliningEnabled()253   void MarkAsInliningEnabled() { SetFlag(kInliningEnabled); }
254 
is_inlining_enabled()255   bool is_inlining_enabled() const { return GetFlag(kInliningEnabled); }
256 
MarkAsTypingEnabled()257   void MarkAsTypingEnabled() { SetFlag(kTypingEnabled); }
258 
is_typing_enabled()259   bool is_typing_enabled() const { return GetFlag(kTypingEnabled); }
260 
MarkAsSplittingEnabled()261   void MarkAsSplittingEnabled() { SetFlag(kSplittingEnabled); }
262 
is_splitting_enabled()263   bool is_splitting_enabled() const { return GetFlag(kSplittingEnabled); }
264 
MarkAsFirstCompile()265   void MarkAsFirstCompile() { SetFlag(kFirstCompile); }
266 
MarkAsCompiled()267   void MarkAsCompiled() { SetFlag(kFirstCompile, false); }
268 
is_first_compile()269   bool is_first_compile() const { return GetFlag(kFirstCompile); }
270 
GeneratePreagedPrologue()271   bool GeneratePreagedPrologue() const {
272     // Generate a pre-aged prologue if we are optimizing for size, which
273     // will make code flushing more aggressive. Only apply to Code::FUNCTION,
274     // since StaticMarkingVisitor::IsFlushable only flushes proper functions.
275     return FLAG_optimize_for_size && FLAG_age_code && !will_serialize() &&
276            !is_debug() && output_code_kind_ == Code::FUNCTION;
277   }
278 
279   void EnsureFeedbackVector();
feedback_vector()280   Handle<TypeFeedbackVector> feedback_vector() const {
281     return feedback_vector_;
282   }
SetCode(Handle<Code> code)283   void SetCode(Handle<Code> code) { code_ = code; }
284 
SetBytecodeArray(Handle<BytecodeArray> bytecode_array)285   void SetBytecodeArray(Handle<BytecodeArray> bytecode_array) {
286     bytecode_array_ = bytecode_array;
287   }
288 
ShouldTrapOnDeopt()289   bool ShouldTrapOnDeopt() const {
290     return (FLAG_trap_on_deopt && IsOptimizing()) ||
291         (FLAG_trap_on_stub_deopt && IsStub());
292   }
293 
has_native_context()294   bool has_native_context() const {
295     return !closure().is_null() && (closure()->native_context() != nullptr);
296   }
297 
native_context()298   Context* native_context() const {
299     return has_native_context() ? closure()->native_context() : nullptr;
300   }
301 
has_global_object()302   bool has_global_object() const { return has_native_context(); }
303 
global_object()304   JSGlobalObject* global_object() const {
305     return has_global_object() ? native_context()->global_object() : nullptr;
306   }
307 
308   // Accessors for the different compilation modes.
IsOptimizing()309   bool IsOptimizing() const { return mode_ == OPTIMIZE; }
IsStub()310   bool IsStub() const { return mode_ == STUB; }
SetOptimizing(BailoutId osr_ast_id,Handle<Code> unoptimized)311   void SetOptimizing(BailoutId osr_ast_id, Handle<Code> unoptimized) {
312     DCHECK(has_shared_info());
313     SetMode(OPTIMIZE);
314     osr_ast_id_ = osr_ast_id;
315     unoptimized_code_ = unoptimized;
316     optimization_id_ = isolate()->NextOptimizationId();
317     set_output_code_kind(Code::OPTIMIZED_FUNCTION);
318   }
319 
320   // Deoptimization support.
HasDeoptimizationSupport()321   bool HasDeoptimizationSupport() const {
322     return GetFlag(kDeoptimizationSupport);
323   }
EnableDeoptimizationSupport()324   void EnableDeoptimizationSupport() {
325     DCHECK_EQ(BASE, mode_);
326     SetFlag(kDeoptimizationSupport);
327   }
ShouldEnsureSpaceForLazyDeopt()328   bool ShouldEnsureSpaceForLazyDeopt() { return !IsStub(); }
329 
330   bool ExpectsJSReceiverAsReceiver();
331 
332   // Determines whether or not to insert a self-optimization header.
333   bool ShouldSelfOptimize();
334 
set_deferred_handles(DeferredHandles * deferred_handles)335   void set_deferred_handles(DeferredHandles* deferred_handles) {
336     DCHECK(deferred_handles_ == NULL);
337     deferred_handles_ = deferred_handles;
338   }
339 
ReopenHandlesInNewHandleScope()340   void ReopenHandlesInNewHandleScope() {
341     unoptimized_code_ = Handle<Code>(*unoptimized_code_);
342   }
343 
AbortOptimization(BailoutReason reason)344   void AbortOptimization(BailoutReason reason) {
345     DCHECK(reason != kNoReason);
346     if (bailout_reason_ == kNoReason) bailout_reason_ = reason;
347     SetFlag(kDisableFutureOptimization);
348   }
349 
RetryOptimization(BailoutReason reason)350   void RetryOptimization(BailoutReason reason) {
351     DCHECK(reason != kNoReason);
352     if (GetFlag(kDisableFutureOptimization)) return;
353     bailout_reason_ = reason;
354   }
355 
bailout_reason()356   BailoutReason bailout_reason() const { return bailout_reason_; }
357 
prologue_offset()358   int prologue_offset() const {
359     DCHECK_NE(Code::kPrologueOffsetNotSet, prologue_offset_);
360     return prologue_offset_;
361   }
362 
set_prologue_offset(int prologue_offset)363   void set_prologue_offset(int prologue_offset) {
364     DCHECK_EQ(Code::kPrologueOffsetNotSet, prologue_offset_);
365     prologue_offset_ = prologue_offset;
366   }
367 
start_position_for(uint32_t inlining_id)368   int start_position_for(uint32_t inlining_id) {
369     return inlined_function_infos_.at(inlining_id).start_position;
370   }
inlined_function_infos()371   const std::vector<InlinedFunctionInfo>& inlined_function_infos() {
372     return inlined_function_infos_;
373   }
374 
375   void LogDeoptCallPosition(int pc_offset, int inlining_id);
376   int TraceInlinedFunction(Handle<SharedFunctionInfo> shared,
377                            SourcePosition position, int pareint_id);
378 
dependencies()379   CompilationDependencies* dependencies() { return &dependencies_; }
380 
HasSameOsrEntry(Handle<JSFunction> function,BailoutId osr_ast_id)381   bool HasSameOsrEntry(Handle<JSFunction> function, BailoutId osr_ast_id) {
382     return osr_ast_id_ == osr_ast_id && function.is_identical_to(closure());
383   }
384 
optimization_id()385   int optimization_id() const { return optimization_id_; }
386 
osr_expr_stack_height()387   int osr_expr_stack_height() { return osr_expr_stack_height_; }
set_osr_expr_stack_height(int height)388   void set_osr_expr_stack_height(int height) {
389     DCHECK(height >= 0);
390     osr_expr_stack_height_ = height;
391   }
osr_frame()392   JavaScriptFrame* osr_frame() const { return osr_frame_; }
set_osr_frame(JavaScriptFrame * osr_frame)393   void set_osr_frame(JavaScriptFrame* osr_frame) { osr_frame_ = osr_frame; }
394 
395 #if DEBUG
396   void PrintAstForTesting();
397 #endif
398 
399   bool has_simple_parameters();
400 
401   struct InlinedFunctionHolder {
402     Handle<SharedFunctionInfo> shared_info;
403 
404     // Root that holds the unoptimized code of the inlined function alive
405     // (and out of reach of code flushing) until we finish compilation.
406     // Do not remove.
407     Handle<Code> inlined_code_object_root;
408 
InlinedFunctionHolderInlinedFunctionHolder409     explicit InlinedFunctionHolder(
410         Handle<SharedFunctionInfo> inlined_shared_info)
411         : shared_info(inlined_shared_info),
412           inlined_code_object_root(inlined_shared_info->code()) {}
413   };
414 
415   typedef std::vector<InlinedFunctionHolder> InlinedFunctionList;
inlined_functions()416   InlinedFunctionList const& inlined_functions() const {
417     return inlined_functions_;
418   }
419 
AddInlinedFunction(Handle<SharedFunctionInfo> inlined_function)420   void AddInlinedFunction(Handle<SharedFunctionInfo> inlined_function) {
421     inlined_functions_.push_back(InlinedFunctionHolder(inlined_function));
422   }
423 
424   base::SmartArrayPointer<char> GetDebugName() const;
425 
output_code_kind()426   Code::Kind output_code_kind() const { return output_code_kind_; }
427 
set_output_code_kind(Code::Kind kind)428   void set_output_code_kind(Code::Kind kind) { output_code_kind_ = kind; }
429 
430  protected:
431   ParseInfo* parse_info_;
432 
DisableFutureOptimization()433   void DisableFutureOptimization() {
434     if (GetFlag(kDisableFutureOptimization) && has_shared_info()) {
435       shared_info()->DisableOptimization(bailout_reason());
436     }
437   }
438 
439  private:
440   // Compilation mode.
441   // BASE is generated by the full codegen, optionally prepared for bailouts.
442   // OPTIMIZE is optimized code generated by the Hydrogen-based backend.
443   enum Mode {
444     BASE,
445     OPTIMIZE,
446     STUB
447   };
448 
449   CompilationInfo(ParseInfo* parse_info, CodeStub* code_stub,
450                   const char* debug_name, Mode mode, Isolate* isolate,
451                   Zone* zone);
452 
453   Isolate* isolate_;
454 
SetMode(Mode mode)455   void SetMode(Mode mode) {
456     mode_ = mode;
457   }
458 
SetFlag(Flag flag)459   void SetFlag(Flag flag) { flags_ |= flag; }
460 
SetFlag(Flag flag,bool value)461   void SetFlag(Flag flag, bool value) {
462     flags_ = value ? flags_ | flag : flags_ & ~flag;
463   }
464 
GetFlag(Flag flag)465   bool GetFlag(Flag flag) const { return (flags_ & flag) != 0; }
466 
467   unsigned flags_;
468 
469   Code::Kind output_code_kind_;
470 
471   // For compiled stubs, the stub object
472   CodeStub* code_stub_;
473   // The compiled code.
474   Handle<Code> code_;
475 
476   // Used by codegen, ultimately kept rooted by the SharedFunctionInfo.
477   Handle<TypeFeedbackVector> feedback_vector_;
478 
479   // Compilation mode flag and whether deoptimization is allowed.
480   Mode mode_;
481   BailoutId osr_ast_id_;
482   // The unoptimized code we patched for OSR may not be the shared code
483   // afterwards, since we may need to compile it again to include deoptimization
484   // data.  Keep track which code we patched.
485   Handle<Code> unoptimized_code_;
486 
487   // Holds the bytecode array generated by the interpreter.
488   // TODO(rmcilroy/mstarzinger): Temporary work-around until compiler.cc is
489   // refactored to avoid us needing to carry the BytcodeArray around.
490   Handle<BytecodeArray> bytecode_array_;
491 
492   // The zone from which the compilation pipeline working on this
493   // CompilationInfo allocates.
494   Zone* zone_;
495 
496   DeferredHandles* deferred_handles_;
497 
498   // Dependencies for this compilation, e.g. stable maps.
499   CompilationDependencies dependencies_;
500 
501   BailoutReason bailout_reason_;
502 
503   int prologue_offset_;
504 
505   std::vector<InlinedFunctionInfo> inlined_function_infos_;
506   bool track_positions_;
507 
508   InlinedFunctionList inlined_functions_;
509 
510   // A copy of shared_info()->opt_count() to avoid handle deref
511   // during graph optimization.
512   int opt_count_;
513 
514   // Number of parameters used for compilation of stubs that require arguments.
515   int parameter_count_;
516 
517   int optimization_id_;
518 
519   int osr_expr_stack_height_;
520 
521   // The current OSR frame for specialization or {nullptr}.
522   JavaScriptFrame* osr_frame_ = nullptr;
523 
524   const char* debug_name_;
525 
526   DISALLOW_COPY_AND_ASSIGN(CompilationInfo);
527 };
528 
529 
530 // A wrapper around a CompilationInfo that detaches the Handles from
531 // the underlying DeferredHandleScope and stores them in info_ on
532 // destruction.
533 class CompilationHandleScope BASE_EMBEDDED {
534  public:
CompilationHandleScope(CompilationInfo * info)535   explicit CompilationHandleScope(CompilationInfo* info)
536       : deferred_(info->isolate()), info_(info) {}
~CompilationHandleScope()537   ~CompilationHandleScope() {
538     info_->set_deferred_handles(deferred_.Detach());
539   }
540 
541  private:
542   DeferredHandleScope deferred_;
543   CompilationInfo* info_;
544 };
545 
546 
547 class HGraph;
548 class HOptimizedGraphBuilder;
549 class LChunk;
550 
551 // A helper class that calls the three compilation phases in
552 // Crankshaft and keeps track of its state.  The three phases
553 // CreateGraph, OptimizeGraph and GenerateAndInstallCode can either
554 // fail, bail-out to the full code generator or succeed.  Apart from
555 // their return value, the status of the phase last run can be checked
556 // using last_status().
557 class OptimizedCompileJob: public ZoneObject {
558  public:
OptimizedCompileJob(CompilationInfo * info)559   explicit OptimizedCompileJob(CompilationInfo* info)
560       : info_(info),
561         graph_builder_(NULL),
562         graph_(NULL),
563         chunk_(NULL),
564         last_status_(FAILED),
565         awaiting_install_(false) { }
566 
567   enum Status {
568     FAILED, BAILED_OUT, SUCCEEDED
569   };
570 
571   MUST_USE_RESULT Status CreateGraph();
572   MUST_USE_RESULT Status OptimizeGraph();
573   MUST_USE_RESULT Status GenerateCode();
574 
last_status()575   Status last_status() const { return last_status_; }
info()576   CompilationInfo* info() const { return info_; }
isolate()577   Isolate* isolate() const { return info()->isolate(); }
578 
RetryOptimization(BailoutReason reason)579   Status RetryOptimization(BailoutReason reason) {
580     info_->RetryOptimization(reason);
581     return SetLastStatus(BAILED_OUT);
582   }
583 
AbortOptimization(BailoutReason reason)584   Status AbortOptimization(BailoutReason reason) {
585     info_->AbortOptimization(reason);
586     return SetLastStatus(BAILED_OUT);
587   }
588 
WaitForInstall()589   void WaitForInstall() {
590     DCHECK(info_->is_osr());
591     awaiting_install_ = true;
592   }
593 
IsWaitingForInstall()594   bool IsWaitingForInstall() { return awaiting_install_; }
595 
596  private:
597   CompilationInfo* info_;
598   HOptimizedGraphBuilder* graph_builder_;
599   HGraph* graph_;
600   LChunk* chunk_;
601   base::TimeDelta time_taken_to_create_graph_;
602   base::TimeDelta time_taken_to_optimize_;
603   base::TimeDelta time_taken_to_codegen_;
604   Status last_status_;
605   bool awaiting_install_;
606 
SetLastStatus(Status status)607   MUST_USE_RESULT Status SetLastStatus(Status status) {
608     last_status_ = status;
609     return last_status_;
610   }
611   void RecordOptimizationStats();
612 
613   struct Timer {
TimerTimer614     Timer(OptimizedCompileJob* job, base::TimeDelta* location)
615         : job_(job), location_(location) {
616       DCHECK(location_ != NULL);
617       timer_.Start();
618     }
619 
~TimerTimer620     ~Timer() {
621       *location_ += timer_.Elapsed();
622     }
623 
624     OptimizedCompileJob* job_;
625     base::ElapsedTimer timer_;
626     base::TimeDelta* location_;
627   };
628 };
629 
630 
631 // The V8 compiler
632 //
633 // General strategy: Source code is translated into an anonymous function w/o
634 // parameters which then can be executed. If the source code contains other
635 // functions, they will be compiled and allocated as part of the compilation
636 // of the source code.
637 
638 // Please note this interface returns shared function infos.  This means you
639 // need to call Factory::NewFunctionFromSharedFunctionInfo before you have a
640 // real function with a context.
641 
642 class Compiler : public AllStatic {
643  public:
644   MUST_USE_RESULT static MaybeHandle<Code> GetUnoptimizedCode(
645       Handle<JSFunction> function);
646   MUST_USE_RESULT static MaybeHandle<Code> GetLazyCode(
647       Handle<JSFunction> function);
648 
649   static bool Compile(Handle<JSFunction> function, ClearExceptionFlag flag);
650   static bool CompileDebugCode(Handle<JSFunction> function);
651   static bool CompileDebugCode(Handle<SharedFunctionInfo> shared);
652   static void CompileForLiveEdit(Handle<Script> script);
653 
654   // Parser::Parse, then Compiler::Analyze.
655   static bool ParseAndAnalyze(ParseInfo* info);
656   // Rewrite, analyze scopes, and renumber.
657   static bool Analyze(ParseInfo* info);
658   // Adds deoptimization support, requires ParseAndAnalyze.
659   static bool EnsureDeoptimizationSupport(CompilationInfo* info);
660 
661   // Compile a String source within a context for eval.
662   MUST_USE_RESULT static MaybeHandle<JSFunction> GetFunctionFromEval(
663       Handle<String> source, Handle<SharedFunctionInfo> outer_info,
664       Handle<Context> context, LanguageMode language_mode,
665       ParseRestriction restriction, int line_offset, int column_offset = 0,
666       Handle<Object> script_name = Handle<Object>(),
667       ScriptOriginOptions options = ScriptOriginOptions());
668 
669   // Compile a String source within a context.
670   static Handle<SharedFunctionInfo> CompileScript(
671       Handle<String> source, Handle<Object> script_name, int line_offset,
672       int column_offset, ScriptOriginOptions resource_options,
673       Handle<Object> source_map_url, Handle<Context> context,
674       v8::Extension* extension, ScriptData** cached_data,
675       ScriptCompiler::CompileOptions compile_options,
676       NativesFlag is_natives_code, bool is_module);
677 
678   static Handle<SharedFunctionInfo> CompileStreamedScript(Handle<Script> script,
679                                                           ParseInfo* info,
680                                                           int source_length);
681 
682   // Create a shared function info object (the code may be lazily compiled).
683   static Handle<SharedFunctionInfo> GetSharedFunctionInfo(
684       FunctionLiteral* node, Handle<Script> script, CompilationInfo* outer);
685 
686   enum ConcurrencyMode { NOT_CONCURRENT, CONCURRENT };
687 
688   // Generate and return optimized code or start a concurrent optimization job.
689   // In the latter case, return the InOptimizationQueue builtin.  On failure,
690   // return the empty handle.
691   MUST_USE_RESULT static MaybeHandle<Code> GetOptimizedCode(
692       Handle<JSFunction> function, Handle<Code> current_code,
693       ConcurrencyMode mode, BailoutId osr_ast_id = BailoutId::None(),
694       JavaScriptFrame* osr_frame = nullptr);
695 
696   // Generate and return code from previously queued optimization job.
697   // On failure, return the empty handle.
698   static Handle<Code> GetConcurrentlyOptimizedCode(OptimizedCompileJob* job);
699 };
700 
701 
702 class CompilationPhase BASE_EMBEDDED {
703  public:
704   CompilationPhase(const char* name, CompilationInfo* info);
705   ~CompilationPhase();
706 
707  protected:
708   bool ShouldProduceTraceOutput() const;
709 
name()710   const char* name() const { return name_; }
info()711   CompilationInfo* info() const { return info_; }
isolate()712   Isolate* isolate() const { return info()->isolate(); }
zone()713   Zone* zone() { return &zone_; }
714 
715  private:
716   const char* name_;
717   CompilationInfo* info_;
718   Zone zone_;
719   size_t info_zone_start_allocation_size_;
720   base::ElapsedTimer timer_;
721 
722   DISALLOW_COPY_AND_ASSIGN(CompilationPhase);
723 };
724 
725 }  // namespace internal
726 }  // namespace v8
727 
728 #endif  // V8_COMPILER_H_
729