| // Copyright 2012 the V8 project authors. All rights reserved. |
| // Redistribution and use in source and binary forms, with or without |
| // modification, are permitted provided that the following conditions are |
| // met: |
| // |
| // * Redistributions of source code must retain the above copyright |
| // notice, this list of conditions and the following disclaimer. |
| // * Redistributions in binary form must reproduce the above |
| // copyright notice, this list of conditions and the following |
| // disclaimer in the documentation and/or other materials provided |
| // with the distribution. |
| // * Neither the name of Google Inc. nor the names of its |
| // contributors may be used to endorse or promote products derived |
| // from this software without specific prior written permission. |
| // |
| // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| |
| #ifndef V8_COMPILER_H_ |
| #define V8_COMPILER_H_ |
| |
| #include "allocation.h" |
| #include "ast.h" |
| #include "zone.h" |
| |
| namespace v8 { |
| namespace internal { |
| |
| class ScriptDataImpl; |
| |
| // CompilationInfo encapsulates some information known at compile time. It |
| // is constructed based on the resources available at compile-time. |
| class CompilationInfo BASE_EMBEDDED { |
| public: |
| explicit CompilationInfo(Handle<Script> script); |
| explicit CompilationInfo(Handle<SharedFunctionInfo> shared_info); |
| explicit CompilationInfo(Handle<JSFunction> closure); |
| |
| Isolate* isolate() { |
| ASSERT(Isolate::Current() == isolate_); |
| return isolate_; |
| } |
| bool is_lazy() const { return IsLazy::decode(flags_); } |
| bool is_eval() const { return IsEval::decode(flags_); } |
| bool is_global() const { return IsGlobal::decode(flags_); } |
| bool is_classic_mode() const { return language_mode() == CLASSIC_MODE; } |
| bool is_extended_mode() const { return language_mode() == EXTENDED_MODE; } |
| LanguageMode language_mode() const { |
| return LanguageModeField::decode(flags_); |
| } |
| bool is_in_loop() const { return IsInLoop::decode(flags_); } |
| FunctionLiteral* function() const { return function_; } |
| Scope* scope() const { return scope_; } |
| Scope* global_scope() const { return global_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_; } |
| v8::Extension* extension() const { return extension_; } |
| ScriptDataImpl* pre_parse_data() const { return pre_parse_data_; } |
| Handle<Context> calling_context() const { return calling_context_; } |
| int osr_ast_id() const { return osr_ast_id_; } |
| |
| void MarkAsEval() { |
| ASSERT(!is_lazy()); |
| flags_ |= IsEval::encode(true); |
| } |
| void MarkAsGlobal() { |
| ASSERT(!is_lazy()); |
| flags_ |= IsGlobal::encode(true); |
| } |
| void SetLanguageMode(LanguageMode language_mode) { |
| ASSERT(this->language_mode() == CLASSIC_MODE || |
| this->language_mode() == language_mode || |
| language_mode == EXTENDED_MODE); |
| flags_ = LanguageModeField::update(flags_, language_mode); |
| } |
| void MarkAsInLoop() { |
| ASSERT(is_lazy()); |
| flags_ |= IsInLoop::encode(true); |
| } |
| void MarkAsNative() { |
| flags_ |= IsNative::encode(true); |
| } |
| bool is_native() const { |
| return IsNative::decode(flags_); |
| } |
| void SetFunction(FunctionLiteral* literal) { |
| ASSERT(function_ == NULL); |
| function_ = literal; |
| } |
| void SetScope(Scope* scope) { |
| ASSERT(scope_ == NULL); |
| scope_ = scope; |
| } |
| void SetGlobalScope(Scope* global_scope) { |
| ASSERT(global_scope_ == NULL); |
| global_scope_ = global_scope; |
| } |
| void SetCode(Handle<Code> code) { code_ = code; } |
| void SetExtension(v8::Extension* extension) { |
| ASSERT(!is_lazy()); |
| extension_ = extension; |
| } |
| void SetPreParseData(ScriptDataImpl* pre_parse_data) { |
| ASSERT(!is_lazy()); |
| pre_parse_data_ = pre_parse_data; |
| } |
| void SetCallingContext(Handle<Context> context) { |
| ASSERT(is_eval()); |
| calling_context_ = context; |
| } |
| void SetOsrAstId(int osr_ast_id) { |
| ASSERT(IsOptimizing()); |
| osr_ast_id_ = osr_ast_id; |
| } |
| void MarkCompilingForDebugging(Handle<Code> current_code) { |
| ASSERT(mode_ != OPTIMIZE); |
| ASSERT(current_code->kind() == Code::FUNCTION); |
| flags_ |= IsCompilingForDebugging::encode(true); |
| if (current_code->is_compiled_optimizable()) { |
| EnableDeoptimizationSupport(); |
| } else { |
| mode_ = CompilationInfo::NONOPT; |
| } |
| } |
| bool IsCompilingForDebugging() { |
| return IsCompilingForDebugging::decode(flags_); |
| } |
| |
| bool has_global_object() const { |
| return !closure().is_null() && (closure()->context()->global() != NULL); |
| } |
| |
| GlobalObject* global_object() const { |
| return has_global_object() ? closure()->context()->global() : NULL; |
| } |
| |
| // Accessors for the different compilation modes. |
| bool IsOptimizing() const { return mode_ == OPTIMIZE; } |
| bool IsOptimizable() const { return mode_ == BASE; } |
| void SetOptimizing(int osr_ast_id) { |
| SetMode(OPTIMIZE); |
| osr_ast_id_ = osr_ast_id; |
| } |
| void DisableOptimization(); |
| |
| // Deoptimization support. |
| bool HasDeoptimizationSupport() const { |
| return SupportsDeoptimization::decode(flags_); |
| } |
| void EnableDeoptimizationSupport() { |
| ASSERT(IsOptimizable()); |
| flags_ |= SupportsDeoptimization::encode(true); |
| } |
| |
| // Determines whether or not to insert a self-optimization header. |
| bool ShouldSelfOptimize(); |
| |
| // Disable all optimization attempts of this info for the rest of the |
| // current compilation pipeline. |
| void AbortOptimization(); |
| |
| 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 |
| }; |
| |
| CompilationInfo() : function_(NULL) {} |
| |
| void Initialize(Mode mode) { |
| mode_ = V8::UseCrankshaft() ? mode : NONOPT; |
| ASSERT(!script_.is_null()); |
| if (script_->type()->value() == Script::TYPE_NATIVE) { |
| MarkAsNative(); |
| } |
| if (!shared_info_.is_null()) { |
| ASSERT(language_mode() == CLASSIC_MODE); |
| SetLanguageMode(shared_info_->language_mode()); |
| } |
| } |
| |
| void SetMode(Mode mode) { |
| ASSERT(V8::UseCrankshaft()); |
| mode_ = mode; |
| } |
| |
| // Flags using template class BitField<type, start, length>. All are |
| // false by default. |
| // |
| // Compilation is either eager or lazy. |
| class IsLazy: public BitField<bool, 0, 1> {}; |
| // Flags that can be set for eager compilation. |
| class IsEval: public BitField<bool, 1, 1> {}; |
| class IsGlobal: public BitField<bool, 2, 1> {}; |
| // Flags that can be set for lazy compilation. |
| class IsInLoop: public BitField<bool, 3, 1> {}; |
| // Strict mode - used in eager compilation. |
| class LanguageModeField: public BitField<LanguageMode, 4, 2> {}; |
| // Is this a function from our natives. |
| class IsNative: public BitField<bool, 6, 1> {}; |
| // Is this code being compiled with support for deoptimization.. |
| class SupportsDeoptimization: public BitField<bool, 7, 1> {}; |
| // If compiling for debugging produce just full code matching the |
| // initial mode setting. |
| class IsCompilingForDebugging: public BitField<bool, 8, 1> {}; |
| |
| |
| 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 global scope provided as a convenience. |
| Scope* global_scope_; |
| // The compiled code. |
| Handle<Code> code_; |
| |
| // Possible initial inputs to the compilation process. |
| Handle<JSFunction> closure_; |
| Handle<SharedFunctionInfo> shared_info_; |
| Handle<Script> script_; |
| |
| // Fields possibly needed for eager compilation, NULL by default. |
| v8::Extension* extension_; |
| ScriptDataImpl* pre_parse_data_; |
| |
| // The context of the caller is needed for eval code, and will be a null |
| // handle otherwise. |
| Handle<Context> calling_context_; |
| |
| // Compilation mode flag and whether deoptimization is allowed. |
| Mode mode_; |
| int osr_ast_id_; |
| |
| DISALLOW_COPY_AND_ASSIGN(CompilationInfo); |
| }; |
| |
| |
| // 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: |
| // Default maximum number of function optimization attempts before we |
| // give up. |
| static const int kDefaultMaxOptCount = 10; |
| |
| static const int kMaxInliningLevels = 3; |
| |
| // Call count before primitive functions trigger their own optimization. |
| static const int kCallsUntilPrimitiveOpt = 200; |
| |
| // All routines return a SharedFunctionInfo. |
| // If an error occurs an exception is raised and the return handle |
| // contains NULL. |
| |
| // Compile a String source within a context. |
| static Handle<SharedFunctionInfo> Compile(Handle<String> source, |
| Handle<Object> script_name, |
| int line_offset, |
| int column_offset, |
| v8::Extension* extension, |
| ScriptDataImpl* pre_data, |
| Handle<Object> script_data, |
| NativesFlag is_natives_code); |
| |
| // Compile a String source within a context for Eval. |
| static Handle<SharedFunctionInfo> CompileEval(Handle<String> source, |
| Handle<Context> context, |
| bool is_global, |
| LanguageMode language_mode, |
| int scope_position); |
| |
| // Compile from function info (used for lazy compilation). Returns true on |
| // success and false if the compilation resulted in a stack overflow. |
| static bool CompileLazy(CompilationInfo* info); |
| |
| // Compile a shared function info object (the function is possibly lazily |
| // compiled). |
| static Handle<SharedFunctionInfo> BuildFunctionInfo(FunctionLiteral* node, |
| Handle<Script> script); |
| |
| // Set the function info for a newly compiled function. |
| static void SetFunctionInfo(Handle<SharedFunctionInfo> function_info, |
| FunctionLiteral* lit, |
| bool is_toplevel, |
| Handle<Script> script); |
| |
| #ifdef ENABLE_DEBUGGER_SUPPORT |
| static bool MakeCodeForLiveEdit(CompilationInfo* info); |
| #endif |
| |
| static void RecordFunctionCompilation(Logger::LogEventsAndTags tag, |
| CompilationInfo* info, |
| Handle<SharedFunctionInfo> shared); |
| }; |
| |
| |
| } } // namespace v8::internal |
| |
| #endif // V8_COMPILER_H_ |