Home | History | Annotate | Download | only in src
      1 // Copyright 2012 the V8 project authors. All rights reserved.
      2 // Redistribution and use in source and binary forms, with or without
      3 // modification, are permitted provided that the following conditions are
      4 // met:
      5 //
      6 //     * Redistributions of source code must retain the above copyright
      7 //       notice, this list of conditions and the following disclaimer.
      8 //     * Redistributions in binary form must reproduce the above
      9 //       copyright notice, this list of conditions and the following
     10 //       disclaimer in the documentation and/or other materials provided
     11 //       with the distribution.
     12 //     * Neither the name of Google Inc. nor the names of its
     13 //       contributors may be used to endorse or promote products derived
     14 //       from this software without specific prior written permission.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 
     28 #ifndef V8_COMPILER_H_
     29 #define V8_COMPILER_H_
     30 
     31 #include "allocation.h"
     32 #include "ast.h"
     33 #include "zone.h"
     34 
     35 namespace v8 {
     36 namespace internal {
     37 
     38 class ScriptDataImpl;
     39 
     40 // CompilationInfo encapsulates some information known at compile time.  It
     41 // is constructed based on the resources available at compile-time.
     42 class CompilationInfo BASE_EMBEDDED {
     43  public:
     44   explicit CompilationInfo(Handle<Script> script);
     45   explicit CompilationInfo(Handle<SharedFunctionInfo> shared_info);
     46   explicit CompilationInfo(Handle<JSFunction> closure);
     47 
     48   Isolate* isolate() {
     49     ASSERT(Isolate::Current() == isolate_);
     50     return isolate_;
     51   }
     52   bool is_lazy() const { return IsLazy::decode(flags_); }
     53   bool is_eval() const { return IsEval::decode(flags_); }
     54   bool is_global() const { return IsGlobal::decode(flags_); }
     55   bool is_classic_mode() const { return language_mode() == CLASSIC_MODE; }
     56   bool is_extended_mode() const { return language_mode() == EXTENDED_MODE; }
     57   LanguageMode language_mode() const {
     58     return LanguageModeField::decode(flags_);
     59   }
     60   bool is_in_loop() const { return IsInLoop::decode(flags_); }
     61   FunctionLiteral* function() const { return function_; }
     62   Scope* scope() const { return scope_; }
     63   Scope* global_scope() const { return global_scope_; }
     64   Handle<Code> code() const { return code_; }
     65   Handle<JSFunction> closure() const { return closure_; }
     66   Handle<SharedFunctionInfo> shared_info() const { return shared_info_; }
     67   Handle<Script> script() const { return script_; }
     68   v8::Extension* extension() const { return extension_; }
     69   ScriptDataImpl* pre_parse_data() const { return pre_parse_data_; }
     70   Handle<Context> calling_context() const { return calling_context_; }
     71   int osr_ast_id() const { return osr_ast_id_; }
     72 
     73   void MarkAsEval() {
     74     ASSERT(!is_lazy());
     75     flags_ |= IsEval::encode(true);
     76   }
     77   void MarkAsGlobal() {
     78     ASSERT(!is_lazy());
     79     flags_ |= IsGlobal::encode(true);
     80   }
     81   void SetLanguageMode(LanguageMode language_mode) {
     82     ASSERT(this->language_mode() == CLASSIC_MODE ||
     83            this->language_mode() == language_mode ||
     84            language_mode == EXTENDED_MODE);
     85     flags_ = LanguageModeField::update(flags_, language_mode);
     86   }
     87   void MarkAsInLoop() {
     88     ASSERT(is_lazy());
     89     flags_ |= IsInLoop::encode(true);
     90   }
     91   void MarkAsNative() {
     92     flags_ |= IsNative::encode(true);
     93   }
     94   bool is_native() const {
     95     return IsNative::decode(flags_);
     96   }
     97   void SetFunction(FunctionLiteral* literal) {
     98     ASSERT(function_ == NULL);
     99     function_ = literal;
    100   }
    101   void SetScope(Scope* scope) {
    102     ASSERT(scope_ == NULL);
    103     scope_ = scope;
    104   }
    105   void SetGlobalScope(Scope* global_scope) {
    106     ASSERT(global_scope_ == NULL);
    107     global_scope_ = global_scope;
    108   }
    109   void SetCode(Handle<Code> code) { code_ = code; }
    110   void SetExtension(v8::Extension* extension) {
    111     ASSERT(!is_lazy());
    112     extension_ = extension;
    113   }
    114   void SetPreParseData(ScriptDataImpl* pre_parse_data) {
    115     ASSERT(!is_lazy());
    116     pre_parse_data_ = pre_parse_data;
    117   }
    118   void SetCallingContext(Handle<Context> context) {
    119     ASSERT(is_eval());
    120     calling_context_ = context;
    121   }
    122   void SetOsrAstId(int osr_ast_id) {
    123     ASSERT(IsOptimizing());
    124     osr_ast_id_ = osr_ast_id;
    125   }
    126   void MarkCompilingForDebugging(Handle<Code> current_code) {
    127     ASSERT(mode_ != OPTIMIZE);
    128     ASSERT(current_code->kind() == Code::FUNCTION);
    129     flags_ |= IsCompilingForDebugging::encode(true);
    130     if (current_code->is_compiled_optimizable()) {
    131       EnableDeoptimizationSupport();
    132     } else {
    133       mode_ = CompilationInfo::NONOPT;
    134     }
    135   }
    136   bool IsCompilingForDebugging() {
    137     return IsCompilingForDebugging::decode(flags_);
    138   }
    139 
    140   bool has_global_object() const {
    141     return !closure().is_null() && (closure()->context()->global() != NULL);
    142   }
    143 
    144   GlobalObject* global_object() const {
    145     return has_global_object() ? closure()->context()->global() : NULL;
    146   }
    147 
    148   // Accessors for the different compilation modes.
    149   bool IsOptimizing() const { return mode_ == OPTIMIZE; }
    150   bool IsOptimizable() const { return mode_ == BASE; }
    151   void SetOptimizing(int osr_ast_id) {
    152     SetMode(OPTIMIZE);
    153     osr_ast_id_ = osr_ast_id;
    154   }
    155   void DisableOptimization();
    156 
    157   // Deoptimization support.
    158   bool HasDeoptimizationSupport() const {
    159     return SupportsDeoptimization::decode(flags_);
    160   }
    161   void EnableDeoptimizationSupport() {
    162     ASSERT(IsOptimizable());
    163     flags_ |= SupportsDeoptimization::encode(true);
    164   }
    165 
    166   // Determines whether or not to insert a self-optimization header.
    167   bool ShouldSelfOptimize();
    168 
    169   // Disable all optimization attempts of this info for the rest of the
    170   // current compilation pipeline.
    171   void AbortOptimization();
    172 
    173  private:
    174   Isolate* isolate_;
    175 
    176   // Compilation mode.
    177   // BASE is generated by the full codegen, optionally prepared for bailouts.
    178   // OPTIMIZE is optimized code generated by the Hydrogen-based backend.
    179   // NONOPT is generated by the full codegen and is not prepared for
    180   //   recompilation/bailouts.  These functions are never recompiled.
    181   enum Mode {
    182     BASE,
    183     OPTIMIZE,
    184     NONOPT
    185   };
    186 
    187   CompilationInfo() : function_(NULL) {}
    188 
    189   void Initialize(Mode mode) {
    190     mode_ = V8::UseCrankshaft() ? mode : NONOPT;
    191     ASSERT(!script_.is_null());
    192     if (script_->type()->value() == Script::TYPE_NATIVE) {
    193       MarkAsNative();
    194     }
    195     if (!shared_info_.is_null()) {
    196       ASSERT(language_mode() == CLASSIC_MODE);
    197       SetLanguageMode(shared_info_->language_mode());
    198     }
    199   }
    200 
    201   void SetMode(Mode mode) {
    202     ASSERT(V8::UseCrankshaft());
    203     mode_ = mode;
    204   }
    205 
    206   // Flags using template class BitField<type, start, length>.  All are
    207   // false by default.
    208   //
    209   // Compilation is either eager or lazy.
    210   class IsLazy:   public BitField<bool, 0, 1> {};
    211   // Flags that can be set for eager compilation.
    212   class IsEval:   public BitField<bool, 1, 1> {};
    213   class IsGlobal: public BitField<bool, 2, 1> {};
    214   // Flags that can be set for lazy compilation.
    215   class IsInLoop: public BitField<bool, 3, 1> {};
    216   // Strict mode - used in eager compilation.
    217   class LanguageModeField: public BitField<LanguageMode, 4, 2> {};
    218   // Is this a function from our natives.
    219   class IsNative: public BitField<bool, 6, 1> {};
    220   // Is this code being compiled with support for deoptimization..
    221   class SupportsDeoptimization: public BitField<bool, 7, 1> {};
    222   // If compiling for debugging produce just full code matching the
    223   // initial mode setting.
    224   class IsCompilingForDebugging: public BitField<bool, 8, 1> {};
    225 
    226 
    227   unsigned flags_;
    228 
    229   // Fields filled in by the compilation pipeline.
    230   // AST filled in by the parser.
    231   FunctionLiteral* function_;
    232   // The scope of the function literal as a convenience.  Set to indicate
    233   // that scopes have been analyzed.
    234   Scope* scope_;
    235   // The global scope provided as a convenience.
    236   Scope* global_scope_;
    237   // The compiled code.
    238   Handle<Code> code_;
    239 
    240   // Possible initial inputs to the compilation process.
    241   Handle<JSFunction> closure_;
    242   Handle<SharedFunctionInfo> shared_info_;
    243   Handle<Script> script_;
    244 
    245   // Fields possibly needed for eager compilation, NULL by default.
    246   v8::Extension* extension_;
    247   ScriptDataImpl* pre_parse_data_;
    248 
    249   // The context of the caller is needed for eval code, and will be a null
    250   // handle otherwise.
    251   Handle<Context> calling_context_;
    252 
    253   // Compilation mode flag and whether deoptimization is allowed.
    254   Mode mode_;
    255   int osr_ast_id_;
    256 
    257   DISALLOW_COPY_AND_ASSIGN(CompilationInfo);
    258 };
    259 
    260 
    261 // The V8 compiler
    262 //
    263 // General strategy: Source code is translated into an anonymous function w/o
    264 // parameters which then can be executed. If the source code contains other
    265 // functions, they will be compiled and allocated as part of the compilation
    266 // of the source code.
    267 
    268 // Please note this interface returns shared function infos.  This means you
    269 // need to call Factory::NewFunctionFromSharedFunctionInfo before you have a
    270 // real function with a context.
    271 
    272 class Compiler : public AllStatic {
    273  public:
    274   // Default maximum number of function optimization attempts before we
    275   // give up.
    276   static const int kDefaultMaxOptCount = 10;
    277 
    278   static const int kMaxInliningLevels = 3;
    279 
    280   // Call count before primitive functions trigger their own optimization.
    281   static const int kCallsUntilPrimitiveOpt = 200;
    282 
    283   // All routines return a SharedFunctionInfo.
    284   // If an error occurs an exception is raised and the return handle
    285   // contains NULL.
    286 
    287   // Compile a String source within a context.
    288   static Handle<SharedFunctionInfo> Compile(Handle<String> source,
    289                                             Handle<Object> script_name,
    290                                             int line_offset,
    291                                             int column_offset,
    292                                             v8::Extension* extension,
    293                                             ScriptDataImpl* pre_data,
    294                                             Handle<Object> script_data,
    295                                             NativesFlag is_natives_code);
    296 
    297   // Compile a String source within a context for Eval.
    298   static Handle<SharedFunctionInfo> CompileEval(Handle<String> source,
    299                                                 Handle<Context> context,
    300                                                 bool is_global,
    301                                                 LanguageMode language_mode,
    302                                                 int scope_position);
    303 
    304   // Compile from function info (used for lazy compilation). Returns true on
    305   // success and false if the compilation resulted in a stack overflow.
    306   static bool CompileLazy(CompilationInfo* info);
    307 
    308   // Compile a shared function info object (the function is possibly lazily
    309   // compiled).
    310   static Handle<SharedFunctionInfo> BuildFunctionInfo(FunctionLiteral* node,
    311                                                       Handle<Script> script);
    312 
    313   // Set the function info for a newly compiled function.
    314   static void SetFunctionInfo(Handle<SharedFunctionInfo> function_info,
    315                               FunctionLiteral* lit,
    316                               bool is_toplevel,
    317                               Handle<Script> script);
    318 
    319 #ifdef ENABLE_DEBUGGER_SUPPORT
    320   static bool MakeCodeForLiveEdit(CompilationInfo* info);
    321 #endif
    322 
    323   static void RecordFunctionCompilation(Logger::LogEventsAndTags tag,
    324                                         CompilationInfo* info,
    325                                         Handle<SharedFunctionInfo> shared);
    326 };
    327 
    328 
    329 } }  // namespace v8::internal
    330 
    331 #endif  // V8_COMPILER_H_
    332