• 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.h"
10 #include "src/bailout-reason.h"
11 #include "src/zone.h"
12 
13 namespace v8 {
14 namespace internal {
15 
16 class AstValueFactory;
17 class HydrogenCodeStub;
18 
19 // ParseRestriction is used to restrict the set of valid statements in a
20 // unit of compilation.  Restriction violations cause a syntax error.
21 enum ParseRestriction {
22   NO_PARSE_RESTRICTION,         // All expressions are allowed.
23   ONLY_SINGLE_FUNCTION_LITERAL  // Only a single FunctionLiteral expression.
24 };
25 
26 struct OffsetRange {
OffsetRangeOffsetRange27   OffsetRange(int from, int to) : from(from), to(to) {}
28   int from;
29   int to;
30 };
31 
32 
33 class ScriptData {
34  public:
35   ScriptData(const byte* data, int length);
~ScriptData()36   ~ScriptData() {
37     if (owns_data_) DeleteArray(data_);
38   }
39 
data()40   const byte* data() const { return data_; }
length()41   int length() const { return length_; }
42 
AcquireDataOwnership()43   void AcquireDataOwnership() {
44     DCHECK(!owns_data_);
45     owns_data_ = true;
46   }
47 
ReleaseDataOwnership()48   void ReleaseDataOwnership() {
49     DCHECK(owns_data_);
50     owns_data_ = false;
51   }
52 
53  private:
54   bool owns_data_;
55   const byte* data_;
56   int length_;
57 
58   DISALLOW_COPY_AND_ASSIGN(ScriptData);
59 };
60 
61 // CompilationInfo encapsulates some information known at compile time.  It
62 // is constructed based on the resources available at compile-time.
63 class CompilationInfo {
64  public:
65   // Various configuration flags for a compilation, as well as some properties
66   // of the compiled code produced by a compilation.
67   enum Flag {
68     kLazy = 1 << 0,
69     kEval = 1 << 1,
70     kGlobal = 1 << 2,
71     kStrictMode = 1 << 3,
72     kThisHasUses = 1 << 4,
73     kNative = 1 << 5,
74     kDeferredCalling = 1 << 6,
75     kNonDeferredCalling = 1 << 7,
76     kSavesCallerDoubles = 1 << 8,
77     kRequiresFrame = 1 << 9,
78     kMustNotHaveEagerFrame = 1 << 10,
79     kDeoptimizationSupport = 1 << 11,
80     kDebug = 1 << 12,
81     kCompilingForDebugging = 1 << 13,
82     kParseRestriction = 1 << 14,
83     kSerializing = 1 << 15,
84     kContextSpecializing = 1 << 16,
85     kInliningEnabled = 1 << 17,
86     kTypingEnabled = 1 << 18,
87     kDisableFutureOptimization = 1 << 19
88   };
89 
90   CompilationInfo(Handle<JSFunction> closure, Zone* zone);
91   CompilationInfo(Isolate* isolate, Zone* zone);
92   virtual ~CompilationInfo();
93 
isolate()94   Isolate* isolate() const {
95     return isolate_;
96   }
zone()97   Zone* zone() { return zone_; }
is_osr()98   bool is_osr() const { return !osr_ast_id_.IsNone(); }
is_lazy()99   bool is_lazy() const { return GetFlag(kLazy); }
is_eval()100   bool is_eval() const { return GetFlag(kEval); }
is_global()101   bool is_global() const { return GetFlag(kGlobal); }
strict_mode()102   StrictMode strict_mode() const {
103     return GetFlag(kStrictMode) ? STRICT : SLOPPY;
104   }
function()105   FunctionLiteral* function() const { return function_; }
scope()106   Scope* scope() const { return scope_; }
global_scope()107   Scope* global_scope() const { return global_scope_; }
code()108   Handle<Code> code() const { return code_; }
closure()109   Handle<JSFunction> closure() const { return closure_; }
shared_info()110   Handle<SharedFunctionInfo> shared_info() const { return shared_info_; }
script()111   Handle<Script> script() const { return script_; }
set_script(Handle<Script> script)112   void set_script(Handle<Script> script) { script_ = script; }
code_stub()113   HydrogenCodeStub* code_stub() const {return code_stub_; }
extension()114   v8::Extension* extension() const { return extension_; }
cached_data()115   ScriptData** cached_data() const { return cached_data_; }
compile_options()116   ScriptCompiler::CompileOptions compile_options() const {
117     return compile_options_;
118   }
source_stream()119   ScriptCompiler::ExternalSourceStream* source_stream() const {
120     return source_stream_;
121   }
source_stream_encoding()122   ScriptCompiler::StreamedSource::Encoding source_stream_encoding() const {
123     return source_stream_encoding_;
124   }
context()125   Handle<Context> context() const { return context_; }
osr_ast_id()126   BailoutId osr_ast_id() const { return osr_ast_id_; }
unoptimized_code()127   Handle<Code> unoptimized_code() const { return unoptimized_code_; }
opt_count()128   int opt_count() const { return opt_count_; }
129   int num_parameters() const;
130   int num_heap_slots() const;
131   Code::Flags flags() const;
132 
MarkAsEval()133   void MarkAsEval() {
134     DCHECK(!is_lazy());
135     SetFlag(kEval);
136   }
137 
MarkAsGlobal()138   void MarkAsGlobal() {
139     DCHECK(!is_lazy());
140     SetFlag(kGlobal);
141   }
142 
set_parameter_count(int parameter_count)143   void set_parameter_count(int parameter_count) {
144     DCHECK(IsStub());
145     parameter_count_ = parameter_count;
146   }
147 
set_this_has_uses(bool has_no_uses)148   void set_this_has_uses(bool has_no_uses) {
149     SetFlag(kThisHasUses, has_no_uses);
150   }
151 
this_has_uses()152   bool this_has_uses() { return GetFlag(kThisHasUses); }
153 
SetStrictMode(StrictMode strict_mode)154   void SetStrictMode(StrictMode strict_mode) {
155     SetFlag(kStrictMode, strict_mode == STRICT);
156   }
157 
MarkAsNative()158   void MarkAsNative() { SetFlag(kNative); }
159 
is_native()160   bool is_native() const { return GetFlag(kNative); }
161 
is_calling()162   bool is_calling() const {
163     return GetFlag(kDeferredCalling) || GetFlag(kNonDeferredCalling);
164   }
165 
MarkAsDeferredCalling()166   void MarkAsDeferredCalling() { SetFlag(kDeferredCalling); }
167 
is_deferred_calling()168   bool is_deferred_calling() const { return GetFlag(kDeferredCalling); }
169 
MarkAsNonDeferredCalling()170   void MarkAsNonDeferredCalling() { SetFlag(kNonDeferredCalling); }
171 
is_non_deferred_calling()172   bool is_non_deferred_calling() const { return GetFlag(kNonDeferredCalling); }
173 
MarkAsSavesCallerDoubles()174   void MarkAsSavesCallerDoubles() { SetFlag(kSavesCallerDoubles); }
175 
saves_caller_doubles()176   bool saves_caller_doubles() const { return GetFlag(kSavesCallerDoubles); }
177 
MarkAsRequiresFrame()178   void MarkAsRequiresFrame() { SetFlag(kRequiresFrame); }
179 
requires_frame()180   bool requires_frame() const { return GetFlag(kRequiresFrame); }
181 
MarkMustNotHaveEagerFrame()182   void MarkMustNotHaveEagerFrame() { SetFlag(kMustNotHaveEagerFrame); }
183 
GetMustNotHaveEagerFrame()184   bool GetMustNotHaveEagerFrame() const {
185     return GetFlag(kMustNotHaveEagerFrame);
186   }
187 
MarkAsDebug()188   void MarkAsDebug() { SetFlag(kDebug); }
189 
is_debug()190   bool is_debug() const { return GetFlag(kDebug); }
191 
PrepareForSerializing()192   void PrepareForSerializing() { SetFlag(kSerializing); }
193 
will_serialize()194   bool will_serialize() const { return GetFlag(kSerializing); }
195 
MarkAsContextSpecializing()196   void MarkAsContextSpecializing() { SetFlag(kContextSpecializing); }
197 
is_context_specializing()198   bool is_context_specializing() const { return GetFlag(kContextSpecializing); }
199 
MarkAsInliningEnabled()200   void MarkAsInliningEnabled() { SetFlag(kInliningEnabled); }
201 
MarkAsInliningDisabled()202   void MarkAsInliningDisabled() { SetFlag(kInliningEnabled, false); }
203 
is_inlining_enabled()204   bool is_inlining_enabled() const { return GetFlag(kInliningEnabled); }
205 
MarkAsTypingEnabled()206   void MarkAsTypingEnabled() { SetFlag(kTypingEnabled); }
207 
is_typing_enabled()208   bool is_typing_enabled() const { return GetFlag(kTypingEnabled); }
209 
IsCodePreAgingActive()210   bool IsCodePreAgingActive() const {
211     return FLAG_optimize_for_size && FLAG_age_code && !will_serialize() &&
212            !is_debug();
213   }
214 
SetParseRestriction(ParseRestriction restriction)215   void SetParseRestriction(ParseRestriction restriction) {
216     SetFlag(kParseRestriction, restriction != NO_PARSE_RESTRICTION);
217   }
218 
parse_restriction()219   ParseRestriction parse_restriction() const {
220     return GetFlag(kParseRestriction) ? ONLY_SINGLE_FUNCTION_LITERAL
221                                       : NO_PARSE_RESTRICTION;
222   }
223 
SetFunction(FunctionLiteral * literal)224   void SetFunction(FunctionLiteral* literal) {
225     DCHECK(function_ == NULL);
226     function_ = literal;
227   }
228   void PrepareForCompilation(Scope* scope);
SetGlobalScope(Scope * global_scope)229   void SetGlobalScope(Scope* global_scope) {
230     DCHECK(global_scope_ == NULL);
231     global_scope_ = global_scope;
232   }
feedback_vector()233   Handle<TypeFeedbackVector> feedback_vector() const {
234     return feedback_vector_;
235   }
SetCode(Handle<Code> code)236   void SetCode(Handle<Code> code) { code_ = code; }
SetExtension(v8::Extension * extension)237   void SetExtension(v8::Extension* extension) {
238     DCHECK(!is_lazy());
239     extension_ = extension;
240   }
SetCachedData(ScriptData ** cached_data,ScriptCompiler::CompileOptions compile_options)241   void SetCachedData(ScriptData** cached_data,
242                      ScriptCompiler::CompileOptions compile_options) {
243     compile_options_ = compile_options;
244     if (compile_options == ScriptCompiler::kNoCompileOptions) {
245       cached_data_ = NULL;
246     } else {
247       DCHECK(!is_lazy());
248       cached_data_ = cached_data;
249     }
250   }
SetContext(Handle<Context> context)251   void SetContext(Handle<Context> context) {
252     context_ = context;
253   }
254 
MarkCompilingForDebugging()255   void MarkCompilingForDebugging() { SetFlag(kCompilingForDebugging); }
IsCompilingForDebugging()256   bool IsCompilingForDebugging() { return GetFlag(kCompilingForDebugging); }
MarkNonOptimizable()257   void MarkNonOptimizable() {
258     SetMode(CompilationInfo::NONOPT);
259   }
260 
ShouldTrapOnDeopt()261   bool ShouldTrapOnDeopt() const {
262     return (FLAG_trap_on_deopt && IsOptimizing()) ||
263         (FLAG_trap_on_stub_deopt && IsStub());
264   }
265 
has_global_object()266   bool has_global_object() const {
267     return !closure().is_null() &&
268         (closure()->context()->global_object() != NULL);
269   }
270 
global_object()271   GlobalObject* global_object() const {
272     return has_global_object() ? closure()->context()->global_object() : NULL;
273   }
274 
275   // Accessors for the different compilation modes.
IsOptimizing()276   bool IsOptimizing() const { return mode_ == OPTIMIZE; }
IsOptimizable()277   bool IsOptimizable() const { return mode_ == BASE; }
IsStub()278   bool IsStub() const { return mode_ == STUB; }
SetOptimizing(BailoutId osr_ast_id,Handle<Code> unoptimized)279   void SetOptimizing(BailoutId osr_ast_id, Handle<Code> unoptimized) {
280     DCHECK(!shared_info_.is_null());
281     SetMode(OPTIMIZE);
282     osr_ast_id_ = osr_ast_id;
283     unoptimized_code_ = unoptimized;
284     optimization_id_ = isolate()->NextOptimizationId();
285   }
286 
287   // Deoptimization support.
HasDeoptimizationSupport()288   bool HasDeoptimizationSupport() const {
289     return GetFlag(kDeoptimizationSupport);
290   }
EnableDeoptimizationSupport()291   void EnableDeoptimizationSupport() {
292     DCHECK(IsOptimizable());
293     SetFlag(kDeoptimizationSupport);
294   }
295 
296   // Determines whether or not to insert a self-optimization header.
297   bool ShouldSelfOptimize();
298 
set_deferred_handles(DeferredHandles * deferred_handles)299   void set_deferred_handles(DeferredHandles* deferred_handles) {
300     DCHECK(deferred_handles_ == NULL);
301     deferred_handles_ = deferred_handles;
302   }
303 
dependencies(DependentCode::DependencyGroup group)304   ZoneList<Handle<HeapObject> >* dependencies(
305       DependentCode::DependencyGroup group) {
306     if (dependencies_[group] == NULL) {
307       dependencies_[group] = new(zone_) ZoneList<Handle<HeapObject> >(2, zone_);
308     }
309     return dependencies_[group];
310   }
311 
312   void CommitDependencies(Handle<Code> code);
313 
314   void RollbackDependencies();
315 
SaveHandles()316   void SaveHandles() {
317     SaveHandle(&closure_);
318     SaveHandle(&shared_info_);
319     SaveHandle(&context_);
320     SaveHandle(&script_);
321     SaveHandle(&unoptimized_code_);
322   }
323 
AbortOptimization(BailoutReason reason)324   void AbortOptimization(BailoutReason reason) {
325     if (bailout_reason_ != kNoReason) bailout_reason_ = reason;
326     SetFlag(kDisableFutureOptimization);
327   }
328 
RetryOptimization(BailoutReason reason)329   void RetryOptimization(BailoutReason reason) {
330     if (bailout_reason_ != kNoReason) bailout_reason_ = reason;
331   }
332 
bailout_reason()333   BailoutReason bailout_reason() const { return bailout_reason_; }
334 
prologue_offset()335   int prologue_offset() const {
336     DCHECK_NE(Code::kPrologueOffsetNotSet, prologue_offset_);
337     return prologue_offset_;
338   }
339 
set_prologue_offset(int prologue_offset)340   void set_prologue_offset(int prologue_offset) {
341     DCHECK_EQ(Code::kPrologueOffsetNotSet, prologue_offset_);
342     prologue_offset_ = prologue_offset;
343   }
344 
345   // Adds offset range [from, to) where fp register does not point
346   // to the current frame base. Used in CPU profiler to detect stack
347   // samples where top frame is not set up.
AddNoFrameRange(int from,int to)348   inline void AddNoFrameRange(int from, int to) {
349     if (no_frame_ranges_) no_frame_ranges_->Add(OffsetRange(from, to));
350   }
351 
ReleaseNoFrameRanges()352   List<OffsetRange>* ReleaseNoFrameRanges() {
353     List<OffsetRange>* result = no_frame_ranges_;
354     no_frame_ranges_ = NULL;
355     return result;
356   }
357 
object_wrapper()358   Handle<Foreign> object_wrapper() {
359     if (object_wrapper_.is_null()) {
360       object_wrapper_ =
361           isolate()->factory()->NewForeign(reinterpret_cast<Address>(this));
362     }
363     return object_wrapper_;
364   }
365 
AbortDueToDependencyChange()366   void AbortDueToDependencyChange() {
367     DCHECK(!OptimizingCompilerThread::IsOptimizerThread(isolate()));
368     aborted_due_to_dependency_change_ = true;
369   }
370 
HasAbortedDueToDependencyChange()371   bool HasAbortedDueToDependencyChange() const {
372     DCHECK(!OptimizingCompilerThread::IsOptimizerThread(isolate()));
373     return aborted_due_to_dependency_change_;
374   }
375 
HasSameOsrEntry(Handle<JSFunction> function,BailoutId osr_ast_id)376   bool HasSameOsrEntry(Handle<JSFunction> function, BailoutId osr_ast_id) {
377     return osr_ast_id_ == osr_ast_id && function.is_identical_to(closure_);
378   }
379 
optimization_id()380   int optimization_id() const { return optimization_id_; }
381 
ast_value_factory()382   AstValueFactory* ast_value_factory() const { return ast_value_factory_; }
383   void SetAstValueFactory(AstValueFactory* ast_value_factory,
384                           bool owned = true) {
385     ast_value_factory_ = ast_value_factory;
386     ast_value_factory_owned_ = owned;
387   }
388 
ast_node_id_gen()389   AstNode::IdGen* ast_node_id_gen() { return &ast_node_id_gen_; }
390 
391  protected:
392   CompilationInfo(Handle<Script> script,
393                   Zone* zone);
394   CompilationInfo(Handle<SharedFunctionInfo> shared_info,
395                   Zone* zone);
396   CompilationInfo(HydrogenCodeStub* stub,
397                   Isolate* isolate,
398                   Zone* zone);
399   CompilationInfo(ScriptCompiler::ExternalSourceStream* source_stream,
400                   ScriptCompiler::StreamedSource::Encoding encoding,
401                   Isolate* isolate, Zone* zone);
402 
403 
404  private:
405   Isolate* isolate_;
406 
407   // Compilation mode.
408   // BASE is generated by the full codegen, optionally prepared for bailouts.
409   // OPTIMIZE is optimized code generated by the Hydrogen-based backend.
410   // NONOPT is generated by the full codegen and is not prepared for
411   //   recompilation/bailouts.  These functions are never recompiled.
412   enum Mode {
413     BASE,
414     OPTIMIZE,
415     NONOPT,
416     STUB
417   };
418 
419   void Initialize(Isolate* isolate, Mode mode, Zone* zone);
420 
SetMode(Mode mode)421   void SetMode(Mode mode) {
422     mode_ = mode;
423   }
424 
SetFlag(Flag flag)425   void SetFlag(Flag flag) { flags_ |= flag; }
426 
SetFlag(Flag flag,bool value)427   void SetFlag(Flag flag, bool value) {
428     flags_ = value ? flags_ | flag : flags_ & ~flag;
429   }
430 
GetFlag(Flag flag)431   bool GetFlag(Flag flag) const { return (flags_ & flag) != 0; }
432 
433   unsigned flags_;
434 
435   // Fields filled in by the compilation pipeline.
436   // AST filled in by the parser.
437   FunctionLiteral* function_;
438   // The scope of the function literal as a convenience.  Set to indicate
439   // that scopes have been analyzed.
440   Scope* scope_;
441   // The global scope provided as a convenience.
442   Scope* global_scope_;
443   // For compiled stubs, the stub object
444   HydrogenCodeStub* code_stub_;
445   // The compiled code.
446   Handle<Code> code_;
447 
448   // Possible initial inputs to the compilation process.
449   Handle<JSFunction> closure_;
450   Handle<SharedFunctionInfo> shared_info_;
451   Handle<Script> script_;
452   ScriptCompiler::ExternalSourceStream* source_stream_;  // Not owned.
453   ScriptCompiler::StreamedSource::Encoding source_stream_encoding_;
454 
455   // Fields possibly needed for eager compilation, NULL by default.
456   v8::Extension* extension_;
457   ScriptData** cached_data_;
458   ScriptCompiler::CompileOptions compile_options_;
459 
460   // The context of the caller for eval code, and the global context for a
461   // global script. Will be a null handle otherwise.
462   Handle<Context> context_;
463 
464   // Used by codegen, ultimately kept rooted by the SharedFunctionInfo.
465   Handle<TypeFeedbackVector> feedback_vector_;
466 
467   // Compilation mode flag and whether deoptimization is allowed.
468   Mode mode_;
469   BailoutId osr_ast_id_;
470   // The unoptimized code we patched for OSR may not be the shared code
471   // afterwards, since we may need to compile it again to include deoptimization
472   // data.  Keep track which code we patched.
473   Handle<Code> unoptimized_code_;
474 
475   // The zone from which the compilation pipeline working on this
476   // CompilationInfo allocates.
477   Zone* zone_;
478 
479   DeferredHandles* deferred_handles_;
480 
481   ZoneList<Handle<HeapObject> >* dependencies_[DependentCode::kGroupCount];
482 
483   template<typename T>
SaveHandle(Handle<T> * object)484   void SaveHandle(Handle<T> *object) {
485     if (!object->is_null()) {
486       Handle<T> handle(*(*object));
487       *object = handle;
488     }
489   }
490 
491   BailoutReason bailout_reason_;
492 
493   int prologue_offset_;
494 
495   List<OffsetRange>* no_frame_ranges_;
496 
497   // A copy of shared_info()->opt_count() to avoid handle deref
498   // during graph optimization.
499   int opt_count_;
500 
501   // Number of parameters used for compilation of stubs that require arguments.
502   int parameter_count_;
503 
504   Handle<Foreign> object_wrapper_;
505 
506   int optimization_id_;
507 
508   AstValueFactory* ast_value_factory_;
509   bool ast_value_factory_owned_;
510   AstNode::IdGen ast_node_id_gen_;
511 
512   // This flag is used by the main thread to track whether this compilation
513   // should be abandoned due to dependency change.
514   bool aborted_due_to_dependency_change_;
515 
516   DISALLOW_COPY_AND_ASSIGN(CompilationInfo);
517 };
518 
519 
520 // Exactly like a CompilationInfo, except also creates and enters a
521 // Zone on construction and deallocates it on exit.
522 class CompilationInfoWithZone: public CompilationInfo {
523  public:
CompilationInfoWithZone(Handle<Script> script)524   explicit CompilationInfoWithZone(Handle<Script> script)
525       : CompilationInfo(script, &zone_),
526         zone_(script->GetIsolate()) {}
CompilationInfoWithZone(Handle<SharedFunctionInfo> shared_info)527   explicit CompilationInfoWithZone(Handle<SharedFunctionInfo> shared_info)
528       : CompilationInfo(shared_info, &zone_),
529         zone_(shared_info->GetIsolate()) {}
CompilationInfoWithZone(Handle<JSFunction> closure)530   explicit CompilationInfoWithZone(Handle<JSFunction> closure)
531       : CompilationInfo(closure, &zone_),
532         zone_(closure->GetIsolate()) {}
CompilationInfoWithZone(HydrogenCodeStub * stub,Isolate * isolate)533   CompilationInfoWithZone(HydrogenCodeStub* stub, Isolate* isolate)
534       : CompilationInfo(stub, isolate, &zone_),
535         zone_(isolate) {}
CompilationInfoWithZone(ScriptCompiler::ExternalSourceStream * stream,ScriptCompiler::StreamedSource::Encoding encoding,Isolate * isolate)536   CompilationInfoWithZone(ScriptCompiler::ExternalSourceStream* stream,
537                           ScriptCompiler::StreamedSource::Encoding encoding,
538                           Isolate* isolate)
539       : CompilationInfo(stream, encoding, isolate, &zone_), zone_(isolate) {}
540 
541   // Virtual destructor because a CompilationInfoWithZone has to exit the
542   // zone scope and get rid of dependent maps even when the destructor is
543   // called when cast as a CompilationInfo.
~CompilationInfoWithZone()544   virtual ~CompilationInfoWithZone() {
545     RollbackDependencies();
546   }
547 
548  private:
549   Zone zone_;
550 };
551 
552 
553 // A wrapper around a CompilationInfo that detaches the Handles from
554 // the underlying DeferredHandleScope and stores them in info_ on
555 // destruction.
556 class CompilationHandleScope BASE_EMBEDDED {
557  public:
CompilationHandleScope(CompilationInfo * info)558   explicit CompilationHandleScope(CompilationInfo* info)
559       : deferred_(info->isolate()), info_(info) {}
~CompilationHandleScope()560   ~CompilationHandleScope() {
561     info_->set_deferred_handles(deferred_.Detach());
562   }
563 
564  private:
565   DeferredHandleScope deferred_;
566   CompilationInfo* info_;
567 };
568 
569 
570 class HGraph;
571 class HOptimizedGraphBuilder;
572 class LChunk;
573 
574 // A helper class that calls the three compilation phases in
575 // Crankshaft and keeps track of its state.  The three phases
576 // CreateGraph, OptimizeGraph and GenerateAndInstallCode can either
577 // fail, bail-out to the full code generator or succeed.  Apart from
578 // their return value, the status of the phase last run can be checked
579 // using last_status().
580 class OptimizedCompileJob: public ZoneObject {
581  public:
OptimizedCompileJob(CompilationInfo * info)582   explicit OptimizedCompileJob(CompilationInfo* info)
583       : info_(info),
584         graph_builder_(NULL),
585         graph_(NULL),
586         chunk_(NULL),
587         last_status_(FAILED),
588         awaiting_install_(false) { }
589 
590   enum Status {
591     FAILED, BAILED_OUT, SUCCEEDED
592   };
593 
594   MUST_USE_RESULT Status CreateGraph();
595   MUST_USE_RESULT Status OptimizeGraph();
596   MUST_USE_RESULT Status GenerateCode();
597 
last_status()598   Status last_status() const { return last_status_; }
info()599   CompilationInfo* info() const { return info_; }
isolate()600   Isolate* isolate() const { return info()->isolate(); }
601 
RetryOptimization(BailoutReason reason)602   Status RetryOptimization(BailoutReason reason) {
603     info_->RetryOptimization(reason);
604     return SetLastStatus(BAILED_OUT);
605   }
606 
AbortOptimization(BailoutReason reason)607   Status AbortOptimization(BailoutReason reason) {
608     info_->AbortOptimization(reason);
609     return SetLastStatus(BAILED_OUT);
610   }
611 
WaitForInstall()612   void WaitForInstall() {
613     DCHECK(info_->is_osr());
614     awaiting_install_ = true;
615   }
616 
IsWaitingForInstall()617   bool IsWaitingForInstall() { return awaiting_install_; }
618 
619  private:
620   CompilationInfo* info_;
621   HOptimizedGraphBuilder* graph_builder_;
622   HGraph* graph_;
623   LChunk* chunk_;
624   base::TimeDelta time_taken_to_create_graph_;
625   base::TimeDelta time_taken_to_optimize_;
626   base::TimeDelta time_taken_to_codegen_;
627   Status last_status_;
628   bool awaiting_install_;
629 
SetLastStatus(Status status)630   MUST_USE_RESULT Status SetLastStatus(Status status) {
631     last_status_ = status;
632     return last_status_;
633   }
634   void RecordOptimizationStats();
635 
636   struct Timer {
TimerTimer637     Timer(OptimizedCompileJob* job, base::TimeDelta* location)
638         : job_(job), location_(location) {
639       DCHECK(location_ != NULL);
640       timer_.Start();
641     }
642 
~TimerTimer643     ~Timer() {
644       *location_ += timer_.Elapsed();
645     }
646 
647     OptimizedCompileJob* job_;
648     base::ElapsedTimer timer_;
649     base::TimeDelta* location_;
650   };
651 };
652 
653 
654 // The V8 compiler
655 //
656 // General strategy: Source code is translated into an anonymous function w/o
657 // parameters which then can be executed. If the source code contains other
658 // functions, they will be compiled and allocated as part of the compilation
659 // of the source code.
660 
661 // Please note this interface returns shared function infos.  This means you
662 // need to call Factory::NewFunctionFromSharedFunctionInfo before you have a
663 // real function with a context.
664 
665 class Compiler : public AllStatic {
666  public:
667   MUST_USE_RESULT static MaybeHandle<Code> GetUnoptimizedCode(
668       Handle<JSFunction> function);
669   MUST_USE_RESULT static MaybeHandle<Code> GetLazyCode(
670       Handle<JSFunction> function);
671   MUST_USE_RESULT static MaybeHandle<Code> GetUnoptimizedCode(
672       Handle<SharedFunctionInfo> shared);
673   MUST_USE_RESULT static MaybeHandle<Code> GetDebugCode(
674       Handle<JSFunction> function);
675 
676   static bool EnsureCompiled(Handle<JSFunction> function,
677                              ClearExceptionFlag flag);
678 
679   static bool EnsureDeoptimizationSupport(CompilationInfo* info);
680 
681   static void CompileForLiveEdit(Handle<Script> script);
682 
683   // Compile a String source within a context for eval.
684   MUST_USE_RESULT static MaybeHandle<JSFunction> GetFunctionFromEval(
685       Handle<String> source, Handle<SharedFunctionInfo> outer_info,
686       Handle<Context> context, StrictMode strict_mode,
687       ParseRestriction restriction, int scope_position);
688 
689   // Compile a String source within a context.
690   static Handle<SharedFunctionInfo> CompileScript(
691       Handle<String> source, Handle<Object> script_name, int line_offset,
692       int column_offset, bool is_shared_cross_origin, Handle<Context> context,
693       v8::Extension* extension, ScriptData** cached_data,
694       ScriptCompiler::CompileOptions compile_options,
695       NativesFlag is_natives_code);
696 
697   static Handle<SharedFunctionInfo> CompileStreamedScript(CompilationInfo* info,
698                                                           int source_length);
699 
700   // Create a shared function info object (the code may be lazily compiled).
701   static Handle<SharedFunctionInfo> BuildFunctionInfo(FunctionLiteral* node,
702                                                       Handle<Script> script,
703                                                       CompilationInfo* outer);
704 
705   enum ConcurrencyMode { NOT_CONCURRENT, CONCURRENT };
706 
707   // Generate and return optimized code or start a concurrent optimization job.
708   // In the latter case, return the InOptimizationQueue builtin.  On failure,
709   // return the empty handle.
710   MUST_USE_RESULT static MaybeHandle<Code> GetOptimizedCode(
711       Handle<JSFunction> function,
712       Handle<Code> current_code,
713       ConcurrencyMode mode,
714       BailoutId osr_ast_id = BailoutId::None());
715 
716   // Generate and return code from previously queued optimization job.
717   // On failure, return the empty handle.
718   static Handle<Code> GetConcurrentlyOptimizedCode(OptimizedCompileJob* job);
719 
720   static bool DebuggerWantsEagerCompilation(
721       CompilationInfo* info, bool allow_lazy_without_ctx = false);
722 };
723 
724 
725 class CompilationPhase BASE_EMBEDDED {
726  public:
727   CompilationPhase(const char* name, CompilationInfo* info);
728   ~CompilationPhase();
729 
730  protected:
731   bool ShouldProduceTraceOutput() const;
732 
name()733   const char* name() const { return name_; }
info()734   CompilationInfo* info() const { return info_; }
isolate()735   Isolate* isolate() const { return info()->isolate(); }
zone()736   Zone* zone() { return &zone_; }
737 
738  private:
739   const char* name_;
740   CompilationInfo* info_;
741   Zone zone_;
742   unsigned info_zone_start_allocation_size_;
743   base::ElapsedTimer timer_;
744 
745   DISALLOW_COPY_AND_ASSIGN(CompilationPhase);
746 };
747 
748 } }  // namespace v8::internal
749 
750 #endif  // V8_COMPILER_H_
751