| // Copyright 2012 the V8 project authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef V8_COMPILER_H_ |
| #define V8_COMPILER_H_ |
| |
| #include "src/allocation.h" |
| #include "src/ast.h" |
| #include "src/bailout-reason.h" |
| #include "src/zone.h" |
| |
| namespace v8 { |
| namespace internal { |
| |
| class AstValueFactory; |
| class HydrogenCodeStub; |
| |
| // ParseRestriction is used to restrict the set of valid statements in a |
| // unit of compilation. Restriction violations cause a syntax error. |
| enum ParseRestriction { |
| NO_PARSE_RESTRICTION, // All expressions are allowed. |
| ONLY_SINGLE_FUNCTION_LITERAL // Only a single FunctionLiteral expression. |
| }; |
| |
| struct OffsetRange { |
| OffsetRange(int from, int to) : from(from), to(to) {} |
| int from; |
| int to; |
| }; |
| |
| |
| class ScriptData { |
| public: |
| ScriptData(const byte* data, int length); |
| ~ScriptData() { |
| if (owns_data_) DeleteArray(data_); |
| } |
| |
| const byte* data() const { return data_; } |
| int length() const { return length_; } |
| |
| void AcquireDataOwnership() { |
| DCHECK(!owns_data_); |
| owns_data_ = true; |
| } |
| |
| void ReleaseDataOwnership() { |
| DCHECK(owns_data_); |
| owns_data_ = false; |
| } |
| |
| private: |
| bool owns_data_; |
| const byte* data_; |
| int length_; |
| |
| DISALLOW_COPY_AND_ASSIGN(ScriptData); |
| }; |
| |
| // CompilationInfo encapsulates some information known at compile time. It |
| // is constructed based on the resources available at compile-time. |
| class CompilationInfo { |
| public: |
| // Various configuration flags for a compilation, as well as some properties |
| // of the compiled code produced by a compilation. |
| enum Flag { |
| kLazy = 1 << 0, |
| kEval = 1 << 1, |
| kGlobal = 1 << 2, |
| kStrictMode = 1 << 3, |
| kThisHasUses = 1 << 4, |
| kNative = 1 << 5, |
| kDeferredCalling = 1 << 6, |
| kNonDeferredCalling = 1 << 7, |
| kSavesCallerDoubles = 1 << 8, |
| kRequiresFrame = 1 << 9, |
| kMustNotHaveEagerFrame = 1 << 10, |
| kDeoptimizationSupport = 1 << 11, |
| kDebug = 1 << 12, |
| kCompilingForDebugging = 1 << 13, |
| kParseRestriction = 1 << 14, |
| kSerializing = 1 << 15, |
| kContextSpecializing = 1 << 16, |
| kInliningEnabled = 1 << 17, |
| kTypingEnabled = 1 << 18, |
| kDisableFutureOptimization = 1 << 19, |
| kToplevel = 1 << 20 |
| }; |
| |
| CompilationInfo(Handle<JSFunction> closure, Zone* zone); |
| CompilationInfo(Isolate* isolate, Zone* zone); |
| virtual ~CompilationInfo(); |
| |
| Isolate* isolate() const { |
| return isolate_; |
| } |
| Zone* zone() { return zone_; } |
| bool is_osr() const { return !osr_ast_id_.IsNone(); } |
| bool is_lazy() const { return GetFlag(kLazy); } |
| bool is_eval() const { return GetFlag(kEval); } |
| bool is_global() const { return GetFlag(kGlobal); } |
| StrictMode strict_mode() const { |
| return GetFlag(kStrictMode) ? STRICT : SLOPPY; |
| } |
| FunctionLiteral* function() const { return function_; } |
| Scope* scope() const { return scope_; } |
| Scope* script_scope() const { return script_scope_; } |
| Handle<Code> code() const { return code_; } |
| Handle<JSFunction> closure() const { return closure_; } |
| Handle<SharedFunctionInfo> shared_info() const { return shared_info_; } |
| Handle<Script> script() const { return script_; } |
| void set_script(Handle<Script> script) { script_ = script; } |
| HydrogenCodeStub* code_stub() const {return code_stub_; } |
| v8::Extension* extension() const { return extension_; } |
| ScriptData** cached_data() const { return cached_data_; } |
| ScriptCompiler::CompileOptions compile_options() const { |
| return compile_options_; |
| } |
| ScriptCompiler::ExternalSourceStream* source_stream() const { |
| return source_stream_; |
| } |
| ScriptCompiler::StreamedSource::Encoding source_stream_encoding() const { |
| return source_stream_encoding_; |
| } |
| Handle<Context> context() const { return context_; } |
| BailoutId osr_ast_id() const { return osr_ast_id_; } |
| Handle<Code> unoptimized_code() const { return unoptimized_code_; } |
| int opt_count() const { return opt_count_; } |
| int num_parameters() const; |
| int num_heap_slots() const; |
| Code::Flags flags() const; |
| |
| void MarkAsEval() { |
| DCHECK(!is_lazy()); |
| SetFlag(kEval); |
| } |
| |
| void MarkAsGlobal() { |
| DCHECK(!is_lazy()); |
| SetFlag(kGlobal); |
| } |
| |
| void set_parameter_count(int parameter_count) { |
| DCHECK(IsStub()); |
| parameter_count_ = parameter_count; |
| } |
| |
| void set_this_has_uses(bool has_no_uses) { |
| SetFlag(kThisHasUses, has_no_uses); |
| } |
| |
| bool this_has_uses() { return GetFlag(kThisHasUses); } |
| |
| void SetStrictMode(StrictMode strict_mode) { |
| SetFlag(kStrictMode, strict_mode == STRICT); |
| } |
| |
| void MarkAsNative() { SetFlag(kNative); } |
| |
| bool is_native() const { return GetFlag(kNative); } |
| |
| bool is_calling() const { |
| return GetFlag(kDeferredCalling) || GetFlag(kNonDeferredCalling); |
| } |
| |
| void MarkAsDeferredCalling() { SetFlag(kDeferredCalling); } |
| |
| bool is_deferred_calling() const { return GetFlag(kDeferredCalling); } |
| |
| void MarkAsNonDeferredCalling() { SetFlag(kNonDeferredCalling); } |
| |
| bool is_non_deferred_calling() const { return GetFlag(kNonDeferredCalling); } |
| |
| void MarkAsSavesCallerDoubles() { SetFlag(kSavesCallerDoubles); } |
| |
| bool saves_caller_doubles() const { return GetFlag(kSavesCallerDoubles); } |
| |
| void MarkAsRequiresFrame() { SetFlag(kRequiresFrame); } |
| |
| bool requires_frame() const { return GetFlag(kRequiresFrame); } |
| |
| void MarkMustNotHaveEagerFrame() { SetFlag(kMustNotHaveEagerFrame); } |
| |
| bool GetMustNotHaveEagerFrame() const { |
| return GetFlag(kMustNotHaveEagerFrame); |
| } |
| |
| void MarkAsDebug() { SetFlag(kDebug); } |
| |
| bool is_debug() const { return GetFlag(kDebug); } |
| |
| void PrepareForSerializing() { SetFlag(kSerializing); } |
| |
| bool will_serialize() const { return GetFlag(kSerializing); } |
| |
| void MarkAsContextSpecializing() { SetFlag(kContextSpecializing); } |
| |
| bool is_context_specializing() const { return GetFlag(kContextSpecializing); } |
| |
| void MarkAsInliningEnabled() { SetFlag(kInliningEnabled); } |
| |
| void MarkAsInliningDisabled() { SetFlag(kInliningEnabled, false); } |
| |
| bool is_inlining_enabled() const { return GetFlag(kInliningEnabled); } |
| |
| void MarkAsTypingEnabled() { SetFlag(kTypingEnabled); } |
| |
| bool is_typing_enabled() const { return GetFlag(kTypingEnabled); } |
| |
| void MarkAsToplevel() { SetFlag(kToplevel); } |
| |
| bool is_toplevel() const { return GetFlag(kToplevel); } |
| |
| bool IsCodePreAgingActive() const { |
| return FLAG_optimize_for_size && FLAG_age_code && !will_serialize() && |
| !is_debug(); |
| } |
| |
| void SetParseRestriction(ParseRestriction restriction) { |
| SetFlag(kParseRestriction, restriction != NO_PARSE_RESTRICTION); |
| } |
| |
| ParseRestriction parse_restriction() const { |
| return GetFlag(kParseRestriction) ? ONLY_SINGLE_FUNCTION_LITERAL |
| : NO_PARSE_RESTRICTION; |
| } |
| |
| void SetFunction(FunctionLiteral* literal) { |
| DCHECK(function_ == NULL); |
| function_ = literal; |
| } |
| void PrepareForCompilation(Scope* scope); |
| void SetScriptScope(Scope* script_scope) { |
| DCHECK(script_scope_ == NULL); |
| script_scope_ = script_scope; |
| } |
| Handle<TypeFeedbackVector> feedback_vector() const { |
| return feedback_vector_; |
| } |
| void SetCode(Handle<Code> code) { code_ = code; } |
| void SetExtension(v8::Extension* extension) { |
| DCHECK(!is_lazy()); |
| extension_ = extension; |
| } |
| void SetCachedData(ScriptData** cached_data, |
| ScriptCompiler::CompileOptions compile_options) { |
| compile_options_ = compile_options; |
| if (compile_options == ScriptCompiler::kNoCompileOptions) { |
| cached_data_ = NULL; |
| } else { |
| DCHECK(!is_lazy()); |
| cached_data_ = cached_data; |
| } |
| } |
| void SetContext(Handle<Context> context) { |
| context_ = context; |
| } |
| |
| void MarkCompilingForDebugging() { SetFlag(kCompilingForDebugging); } |
| bool IsCompilingForDebugging() { return GetFlag(kCompilingForDebugging); } |
| void MarkNonOptimizable() { |
| SetMode(CompilationInfo::NONOPT); |
| } |
| |
| bool ShouldTrapOnDeopt() const { |
| return (FLAG_trap_on_deopt && IsOptimizing()) || |
| (FLAG_trap_on_stub_deopt && IsStub()); |
| } |
| |
| bool has_global_object() const { |
| return !closure().is_null() && |
| (closure()->context()->global_object() != NULL); |
| } |
| |
| GlobalObject* global_object() const { |
| return has_global_object() ? closure()->context()->global_object() : NULL; |
| } |
| |
| // Accessors for the different compilation modes. |
| bool IsOptimizing() const { return mode_ == OPTIMIZE; } |
| bool IsOptimizable() const { return mode_ == BASE; } |
| bool IsStub() const { return mode_ == STUB; } |
| void SetOptimizing(BailoutId osr_ast_id, Handle<Code> unoptimized) { |
| DCHECK(!shared_info_.is_null()); |
| SetMode(OPTIMIZE); |
| osr_ast_id_ = osr_ast_id; |
| unoptimized_code_ = unoptimized; |
| optimization_id_ = isolate()->NextOptimizationId(); |
| } |
| |
| // Deoptimization support. |
| bool HasDeoptimizationSupport() const { |
| return GetFlag(kDeoptimizationSupport); |
| } |
| void EnableDeoptimizationSupport() { |
| DCHECK(IsOptimizable()); |
| SetFlag(kDeoptimizationSupport); |
| } |
| |
| // Determines whether or not to insert a self-optimization header. |
| bool ShouldSelfOptimize(); |
| |
| void set_deferred_handles(DeferredHandles* deferred_handles) { |
| DCHECK(deferred_handles_ == NULL); |
| deferred_handles_ = deferred_handles; |
| } |
| |
| ZoneList<Handle<HeapObject> >* dependencies( |
| DependentCode::DependencyGroup group) { |
| if (dependencies_[group] == NULL) { |
| dependencies_[group] = new(zone_) ZoneList<Handle<HeapObject> >(2, zone_); |
| } |
| return dependencies_[group]; |
| } |
| |
| void CommitDependencies(Handle<Code> code); |
| |
| void RollbackDependencies(); |
| |
| void SaveHandles() { |
| SaveHandle(&closure_); |
| SaveHandle(&shared_info_); |
| SaveHandle(&context_); |
| SaveHandle(&script_); |
| SaveHandle(&unoptimized_code_); |
| } |
| |
| void AbortOptimization(BailoutReason reason) { |
| if (bailout_reason_ != kNoReason) bailout_reason_ = reason; |
| SetFlag(kDisableFutureOptimization); |
| } |
| |
| void RetryOptimization(BailoutReason reason) { |
| if (bailout_reason_ != kNoReason) bailout_reason_ = reason; |
| } |
| |
| BailoutReason bailout_reason() const { return bailout_reason_; } |
| |
| int prologue_offset() const { |
| DCHECK_NE(Code::kPrologueOffsetNotSet, prologue_offset_); |
| return prologue_offset_; |
| } |
| |
| void set_prologue_offset(int prologue_offset) { |
| DCHECK_EQ(Code::kPrologueOffsetNotSet, prologue_offset_); |
| prologue_offset_ = prologue_offset; |
| } |
| |
| // Adds offset range [from, to) where fp register does not point |
| // to the current frame base. Used in CPU profiler to detect stack |
| // samples where top frame is not set up. |
| inline void AddNoFrameRange(int from, int to) { |
| if (no_frame_ranges_) no_frame_ranges_->Add(OffsetRange(from, to)); |
| } |
| |
| List<OffsetRange>* ReleaseNoFrameRanges() { |
| List<OffsetRange>* result = no_frame_ranges_; |
| no_frame_ranges_ = NULL; |
| return result; |
| } |
| |
| Handle<Foreign> object_wrapper() { |
| if (object_wrapper_.is_null()) { |
| object_wrapper_ = |
| isolate()->factory()->NewForeign(reinterpret_cast<Address>(this)); |
| } |
| return object_wrapper_; |
| } |
| |
| void AbortDueToDependencyChange() { |
| DCHECK(!OptimizingCompilerThread::IsOptimizerThread(isolate())); |
| aborted_due_to_dependency_change_ = true; |
| } |
| |
| bool HasAbortedDueToDependencyChange() const { |
| DCHECK(!OptimizingCompilerThread::IsOptimizerThread(isolate())); |
| return aborted_due_to_dependency_change_; |
| } |
| |
| bool HasSameOsrEntry(Handle<JSFunction> function, BailoutId osr_ast_id) { |
| return osr_ast_id_ == osr_ast_id && function.is_identical_to(closure_); |
| } |
| |
| int optimization_id() const { return optimization_id_; } |
| |
| AstValueFactory* ast_value_factory() const { return ast_value_factory_; } |
| void SetAstValueFactory(AstValueFactory* ast_value_factory, |
| bool owned = true) { |
| ast_value_factory_ = ast_value_factory; |
| ast_value_factory_owned_ = owned; |
| } |
| |
| protected: |
| CompilationInfo(Handle<Script> script, |
| Zone* zone); |
| CompilationInfo(Handle<SharedFunctionInfo> shared_info, |
| Zone* zone); |
| CompilationInfo(HydrogenCodeStub* stub, |
| Isolate* isolate, |
| Zone* zone); |
| CompilationInfo(ScriptCompiler::ExternalSourceStream* source_stream, |
| ScriptCompiler::StreamedSource::Encoding encoding, |
| Isolate* isolate, Zone* zone); |
| |
| |
| private: |
| Isolate* isolate_; |
| |
| // Compilation mode. |
| // BASE is generated by the full codegen, optionally prepared for bailouts. |
| // OPTIMIZE is optimized code generated by the Hydrogen-based backend. |
| // NONOPT is generated by the full codegen and is not prepared for |
| // recompilation/bailouts. These functions are never recompiled. |
| enum Mode { |
| BASE, |
| OPTIMIZE, |
| NONOPT, |
| STUB |
| }; |
| |
| void Initialize(Isolate* isolate, Mode mode, Zone* zone); |
| |
| void SetMode(Mode mode) { |
| mode_ = mode; |
| } |
| |
| void SetFlag(Flag flag) { flags_ |= flag; } |
| |
| void SetFlag(Flag flag, bool value) { |
| flags_ = value ? flags_ | flag : flags_ & ~flag; |
| } |
| |
| bool GetFlag(Flag flag) const { return (flags_ & flag) != 0; } |
| |
| unsigned flags_; |
| |
| // Fields filled in by the compilation pipeline. |
| // AST filled in by the parser. |
| FunctionLiteral* function_; |
| // The scope of the function literal as a convenience. Set to indicate |
| // that scopes have been analyzed. |
| Scope* scope_; |
| // The script scope provided as a convenience. |
| Scope* script_scope_; |
| // For compiled stubs, the stub object |
| HydrogenCodeStub* code_stub_; |
| // The compiled code. |
| Handle<Code> code_; |
| |
| // Possible initial inputs to the compilation process. |
| Handle<JSFunction> closure_; |
| Handle<SharedFunctionInfo> shared_info_; |
| Handle<Script> script_; |
| ScriptCompiler::ExternalSourceStream* source_stream_; // Not owned. |
| ScriptCompiler::StreamedSource::Encoding source_stream_encoding_; |
| |
| // Fields possibly needed for eager compilation, NULL by default. |
| v8::Extension* extension_; |
| ScriptData** cached_data_; |
| ScriptCompiler::CompileOptions compile_options_; |
| |
| // The context of the caller for eval code, and the script context for a |
| // global script. Will be a null handle otherwise. |
| Handle<Context> context_; |
| |
| // Used by codegen, ultimately kept rooted by the SharedFunctionInfo. |
| Handle<TypeFeedbackVector> feedback_vector_; |
| |
| // Compilation mode flag and whether deoptimization is allowed. |
| Mode mode_; |
| BailoutId osr_ast_id_; |
| // The unoptimized code we patched for OSR may not be the shared code |
| // afterwards, since we may need to compile it again to include deoptimization |
| // data. Keep track which code we patched. |
| Handle<Code> unoptimized_code_; |
| |
| // The zone from which the compilation pipeline working on this |
| // CompilationInfo allocates. |
| Zone* zone_; |
| |
| DeferredHandles* deferred_handles_; |
| |
| ZoneList<Handle<HeapObject> >* dependencies_[DependentCode::kGroupCount]; |
| |
| template<typename T> |
| void SaveHandle(Handle<T> *object) { |
| if (!object->is_null()) { |
| Handle<T> handle(*(*object)); |
| *object = handle; |
| } |
| } |
| |
| BailoutReason bailout_reason_; |
| |
| int prologue_offset_; |
| |
| List<OffsetRange>* no_frame_ranges_; |
| |
| // A copy of shared_info()->opt_count() to avoid handle deref |
| // during graph optimization. |
| int opt_count_; |
| |
| // Number of parameters used for compilation of stubs that require arguments. |
| int parameter_count_; |
| |
| Handle<Foreign> object_wrapper_; |
| |
| int optimization_id_; |
| |
| AstValueFactory* ast_value_factory_; |
| bool ast_value_factory_owned_; |
| |
| // This flag is used by the main thread to track whether this compilation |
| // should be abandoned due to dependency change. |
| bool aborted_due_to_dependency_change_; |
| |
| DISALLOW_COPY_AND_ASSIGN(CompilationInfo); |
| }; |
| |
| |
| // Exactly like a CompilationInfo, except also creates and enters a |
| // Zone on construction and deallocates it on exit. |
| class CompilationInfoWithZone: public CompilationInfo { |
| public: |
| explicit CompilationInfoWithZone(Handle<Script> script) |
| : CompilationInfo(script, &zone_), |
| zone_(script->GetIsolate()) {} |
| explicit CompilationInfoWithZone(Handle<SharedFunctionInfo> shared_info) |
| : CompilationInfo(shared_info, &zone_), |
| zone_(shared_info->GetIsolate()) {} |
| explicit CompilationInfoWithZone(Handle<JSFunction> closure) |
| : CompilationInfo(closure, &zone_), |
| zone_(closure->GetIsolate()) {} |
| CompilationInfoWithZone(HydrogenCodeStub* stub, Isolate* isolate) |
| : CompilationInfo(stub, isolate, &zone_), |
| zone_(isolate) {} |
| CompilationInfoWithZone(ScriptCompiler::ExternalSourceStream* stream, |
| ScriptCompiler::StreamedSource::Encoding encoding, |
| Isolate* isolate) |
| : CompilationInfo(stream, encoding, isolate, &zone_), zone_(isolate) {} |
| |
| // Virtual destructor because a CompilationInfoWithZone has to exit the |
| // zone scope and get rid of dependent maps even when the destructor is |
| // called when cast as a CompilationInfo. |
| virtual ~CompilationInfoWithZone() { |
| RollbackDependencies(); |
| } |
| |
| private: |
| Zone zone_; |
| }; |
| |
| |
| // A wrapper around a CompilationInfo that detaches the Handles from |
| // the underlying DeferredHandleScope and stores them in info_ on |
| // destruction. |
| class CompilationHandleScope BASE_EMBEDDED { |
| public: |
| explicit CompilationHandleScope(CompilationInfo* info) |
| : deferred_(info->isolate()), info_(info) {} |
| ~CompilationHandleScope() { |
| info_->set_deferred_handles(deferred_.Detach()); |
| } |
| |
| private: |
| DeferredHandleScope deferred_; |
| CompilationInfo* info_; |
| }; |
| |
| |
| class HGraph; |
| class HOptimizedGraphBuilder; |
| class LChunk; |
| |
| // A helper class that calls the three compilation phases in |
| // Crankshaft and keeps track of its state. The three phases |
| // CreateGraph, OptimizeGraph and GenerateAndInstallCode can either |
| // fail, bail-out to the full code generator or succeed. Apart from |
| // their return value, the status of the phase last run can be checked |
| // using last_status(). |
| class OptimizedCompileJob: public ZoneObject { |
| public: |
| explicit OptimizedCompileJob(CompilationInfo* info) |
| : info_(info), |
| graph_builder_(NULL), |
| graph_(NULL), |
| chunk_(NULL), |
| last_status_(FAILED), |
| awaiting_install_(false) { } |
| |
| enum Status { |
| FAILED, BAILED_OUT, SUCCEEDED |
| }; |
| |
| MUST_USE_RESULT Status CreateGraph(); |
| MUST_USE_RESULT Status OptimizeGraph(); |
| MUST_USE_RESULT Status GenerateCode(); |
| |
| Status last_status() const { return last_status_; } |
| CompilationInfo* info() const { return info_; } |
| Isolate* isolate() const { return info()->isolate(); } |
| |
| Status RetryOptimization(BailoutReason reason) { |
| info_->RetryOptimization(reason); |
| return SetLastStatus(BAILED_OUT); |
| } |
| |
| Status AbortOptimization(BailoutReason reason) { |
| info_->AbortOptimization(reason); |
| return SetLastStatus(BAILED_OUT); |
| } |
| |
| void WaitForInstall() { |
| DCHECK(info_->is_osr()); |
| awaiting_install_ = true; |
| } |
| |
| bool IsWaitingForInstall() { return awaiting_install_; } |
| |
| private: |
| CompilationInfo* info_; |
| HOptimizedGraphBuilder* graph_builder_; |
| HGraph* graph_; |
| LChunk* chunk_; |
| base::TimeDelta time_taken_to_create_graph_; |
| base::TimeDelta time_taken_to_optimize_; |
| base::TimeDelta time_taken_to_codegen_; |
| Status last_status_; |
| bool awaiting_install_; |
| |
| MUST_USE_RESULT Status SetLastStatus(Status status) { |
| last_status_ = status; |
| return last_status_; |
| } |
| void RecordOptimizationStats(); |
| |
| struct Timer { |
| Timer(OptimizedCompileJob* job, base::TimeDelta* location) |
| : job_(job), location_(location) { |
| DCHECK(location_ != NULL); |
| timer_.Start(); |
| } |
| |
| ~Timer() { |
| *location_ += timer_.Elapsed(); |
| } |
| |
| OptimizedCompileJob* job_; |
| base::ElapsedTimer timer_; |
| base::TimeDelta* location_; |
| }; |
| }; |
| |
| |
| // The V8 compiler |
| // |
| // General strategy: Source code is translated into an anonymous function w/o |
| // parameters which then can be executed. If the source code contains other |
| // functions, they will be compiled and allocated as part of the compilation |
| // of the source code. |
| |
| // Please note this interface returns shared function infos. This means you |
| // need to call Factory::NewFunctionFromSharedFunctionInfo before you have a |
| // real function with a context. |
| |
| class Compiler : public AllStatic { |
| public: |
| MUST_USE_RESULT static MaybeHandle<Code> GetUnoptimizedCode( |
| Handle<JSFunction> function); |
| MUST_USE_RESULT static MaybeHandle<Code> GetLazyCode( |
| Handle<JSFunction> function); |
| MUST_USE_RESULT static MaybeHandle<Code> GetUnoptimizedCode( |
| Handle<SharedFunctionInfo> shared); |
| MUST_USE_RESULT static MaybeHandle<Code> GetDebugCode( |
| Handle<JSFunction> function); |
| |
| // Parser::Parse, then Compiler::Analyze. |
| static bool ParseAndAnalyze(CompilationInfo* info); |
| // Rewrite, analyze scopes, and renumber. |
| static bool Analyze(CompilationInfo* info); |
| // Adds deoptimization support, requires ParseAndAnalyze. |
| static bool EnsureDeoptimizationSupport(CompilationInfo* info); |
| |
| static bool EnsureCompiled(Handle<JSFunction> function, |
| ClearExceptionFlag flag); |
| |
| static void CompileForLiveEdit(Handle<Script> script); |
| |
| // Compile a String source within a context for eval. |
| MUST_USE_RESULT static MaybeHandle<JSFunction> GetFunctionFromEval( |
| Handle<String> source, Handle<SharedFunctionInfo> outer_info, |
| Handle<Context> context, StrictMode strict_mode, |
| ParseRestriction restriction, int scope_position); |
| |
| // Compile a String source within a context. |
| static Handle<SharedFunctionInfo> CompileScript( |
| Handle<String> source, Handle<Object> script_name, int line_offset, |
| int column_offset, bool is_shared_cross_origin, Handle<Context> context, |
| v8::Extension* extension, ScriptData** cached_data, |
| ScriptCompiler::CompileOptions compile_options, |
| NativesFlag is_natives_code); |
| |
| static Handle<SharedFunctionInfo> CompileStreamedScript(CompilationInfo* info, |
| int source_length); |
| |
| // Create a shared function info object (the code may be lazily compiled). |
| static Handle<SharedFunctionInfo> BuildFunctionInfo(FunctionLiteral* node, |
| Handle<Script> script, |
| CompilationInfo* outer); |
| |
| enum ConcurrencyMode { NOT_CONCURRENT, CONCURRENT }; |
| |
| // Generate and return optimized code or start a concurrent optimization job. |
| // In the latter case, return the InOptimizationQueue builtin. On failure, |
| // return the empty handle. |
| MUST_USE_RESULT static MaybeHandle<Code> GetOptimizedCode( |
| Handle<JSFunction> function, |
| Handle<Code> current_code, |
| ConcurrencyMode mode, |
| BailoutId osr_ast_id = BailoutId::None()); |
| |
| // Generate and return code from previously queued optimization job. |
| // On failure, return the empty handle. |
| static Handle<Code> GetConcurrentlyOptimizedCode(OptimizedCompileJob* job); |
| |
| static bool DebuggerWantsEagerCompilation( |
| CompilationInfo* info, bool allow_lazy_without_ctx = false); |
| }; |
| |
| |
| class CompilationPhase BASE_EMBEDDED { |
| public: |
| CompilationPhase(const char* name, CompilationInfo* info); |
| ~CompilationPhase(); |
| |
| protected: |
| bool ShouldProduceTraceOutput() const; |
| |
| const char* name() const { return name_; } |
| CompilationInfo* info() const { return info_; } |
| Isolate* isolate() const { return info()->isolate(); } |
| Zone* zone() { return &zone_; } |
| |
| private: |
| const char* name_; |
| CompilationInfo* info_; |
| Zone zone_; |
| unsigned info_zone_start_allocation_size_; |
| base::ElapsedTimer timer_; |
| |
| DISALLOW_COPY_AND_ASSIGN(CompilationPhase); |
| }; |
| |
| } } // namespace v8::internal |
| |
| #endif // V8_COMPILER_H_ |