Home | History | Annotate | Download | only in src
      1 // Copyright 2011 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 "ast.h"
     32 #include "frame-element.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 (flags_ & IsLazy::mask()) != 0; }
     53   bool is_eval() const { return (flags_ & IsEval::mask()) != 0; }
     54   bool is_global() const { return (flags_ & IsGlobal::mask()) != 0; }
     55   bool is_strict_mode() const { return (flags_ & IsStrictMode::mask()) != 0; }
     56   bool is_in_loop() const { return (flags_ & IsInLoop::mask()) != 0; }
     57   FunctionLiteral* function() const { return function_; }
     58   Scope* scope() const { return scope_; }
     59   Handle<Code> code() const { return code_; }
     60   Handle<JSFunction> closure() const { return closure_; }
     61   Handle<SharedFunctionInfo> shared_info() const { return shared_info_; }
     62   Handle<Script> script() const { return script_; }
     63   v8::Extension* extension() const { return extension_; }
     64   ScriptDataImpl* pre_parse_data() const { return pre_parse_data_; }
     65   Handle<Context> calling_context() const { return calling_context_; }
     66   int osr_ast_id() const { return osr_ast_id_; }
     67 
     68   void MarkAsEval() {
     69     ASSERT(!is_lazy());
     70     flags_ |= IsEval::encode(true);
     71   }
     72   void MarkAsGlobal() {
     73     ASSERT(!is_lazy());
     74     flags_ |= IsGlobal::encode(true);
     75   }
     76   void MarkAsStrictMode() {
     77     flags_ |= IsStrictMode::encode(true);
     78   }
     79   StrictModeFlag StrictMode() {
     80     return is_strict_mode() ? kStrictMode : kNonStrictMode;
     81   }
     82   void MarkAsInLoop() {
     83     ASSERT(is_lazy());
     84     flags_ |= IsInLoop::encode(true);
     85   }
     86   void MarkAsNative() {
     87     flags_ |= IsNative::encode(true);
     88   }
     89   bool is_native() const {
     90     return IsNative::decode(flags_);
     91   }
     92   void SetFunction(FunctionLiteral* literal) {
     93     ASSERT(function_ == NULL);
     94     function_ = literal;
     95   }
     96   void SetScope(Scope* scope) {
     97     ASSERT(scope_ == NULL);
     98     scope_ = scope;
     99   }
    100   void SetCode(Handle<Code> code) { code_ = code; }
    101   void SetExtension(v8::Extension* extension) {
    102     ASSERT(!is_lazy());
    103     extension_ = extension;
    104   }
    105   void SetPreParseData(ScriptDataImpl* pre_parse_data) {
    106     ASSERT(!is_lazy());
    107     pre_parse_data_ = pre_parse_data;
    108   }
    109   void SetCallingContext(Handle<Context> context) {
    110     ASSERT(is_eval());
    111     calling_context_ = context;
    112   }
    113   void SetOsrAstId(int osr_ast_id) {
    114     ASSERT(IsOptimizing());
    115     osr_ast_id_ = osr_ast_id;
    116   }
    117 
    118   bool has_global_object() const {
    119     return !closure().is_null() && (closure()->context()->global() != NULL);
    120   }
    121 
    122   GlobalObject* global_object() const {
    123     return has_global_object() ? closure()->context()->global() : NULL;
    124   }
    125 
    126   // Accessors for the different compilation modes.
    127   bool IsOptimizing() const { return mode_ == OPTIMIZE; }
    128   bool IsOptimizable() const { return mode_ == BASE; }
    129   void SetOptimizing(int osr_ast_id) {
    130     SetMode(OPTIMIZE);
    131     osr_ast_id_ = osr_ast_id;
    132   }
    133   void DisableOptimization();
    134 
    135   // Deoptimization support.
    136   bool HasDeoptimizationSupport() const { return supports_deoptimization_; }
    137   void EnableDeoptimizationSupport() {
    138     ASSERT(IsOptimizable());
    139     supports_deoptimization_ = true;
    140   }
    141 
    142   // Determine whether or not we can adaptively optimize.
    143   bool AllowOptimize() {
    144     return V8::UseCrankshaft() && !closure_.is_null();
    145   }
    146 
    147  private:
    148   Isolate* isolate_;
    149 
    150   // Compilation mode.
    151   // BASE is generated by the full codegen, optionally prepared for bailouts.
    152   // OPTIMIZE is optimized code generated by the Hydrogen-based backend.
    153   // NONOPT is generated by the full codegen or the classic backend
    154   //   and is not prepared for recompilation/bailouts. These functions
    155   //   are never recompiled.
    156   enum Mode {
    157     BASE,
    158     OPTIMIZE,
    159     NONOPT
    160   };
    161 
    162   CompilationInfo() : function_(NULL) {}
    163 
    164   void Initialize(Mode mode) {
    165     mode_ = V8::UseCrankshaft() ? mode : NONOPT;
    166     if (script_->type()->value() == Script::TYPE_NATIVE) {
    167       MarkAsNative();
    168     }
    169     if (!shared_info_.is_null() && shared_info_->strict_mode()) {
    170       MarkAsStrictMode();
    171     }
    172   }
    173 
    174   void SetMode(Mode mode) {
    175     ASSERT(V8::UseCrankshaft());
    176     mode_ = mode;
    177   }
    178 
    179   // Flags using template class BitField<type, start, length>.  All are
    180   // false by default.
    181   //
    182   // Compilation is either eager or lazy.
    183   class IsLazy:   public BitField<bool, 0, 1> {};
    184   // Flags that can be set for eager compilation.
    185   class IsEval:   public BitField<bool, 1, 1> {};
    186   class IsGlobal: public BitField<bool, 2, 1> {};
    187   // Flags that can be set for lazy compilation.
    188   class IsInLoop: public BitField<bool, 3, 1> {};
    189   // Strict mode - used in eager compilation.
    190   class IsStrictMode: public BitField<bool, 4, 1> {};
    191   // Is this a function from our natives.
    192   class IsNative: public BitField<bool, 6, 1> {};
    193 
    194   unsigned flags_;
    195 
    196   // Fields filled in by the compilation pipeline.
    197   // AST filled in by the parser.
    198   FunctionLiteral* function_;
    199   // The scope of the function literal as a convenience.  Set to indicate
    200   // that scopes have been analyzed.
    201   Scope* scope_;
    202   // The compiled code.
    203   Handle<Code> code_;
    204 
    205   // Possible initial inputs to the compilation process.
    206   Handle<JSFunction> closure_;
    207   Handle<SharedFunctionInfo> shared_info_;
    208   Handle<Script> script_;
    209 
    210   // Fields possibly needed for eager compilation, NULL by default.
    211   v8::Extension* extension_;
    212   ScriptDataImpl* pre_parse_data_;
    213 
    214   // The context of the caller is needed for eval code, and will be a null
    215   // handle otherwise.
    216   Handle<Context> calling_context_;
    217 
    218   // Compilation mode flag and whether deoptimization is allowed.
    219   Mode mode_;
    220   bool supports_deoptimization_;
    221   int osr_ast_id_;
    222 
    223   DISALLOW_COPY_AND_ASSIGN(CompilationInfo);
    224 };
    225 
    226 
    227 // The V8 compiler
    228 //
    229 // General strategy: Source code is translated into an anonymous function w/o
    230 // parameters which then can be executed. If the source code contains other
    231 // functions, they will be compiled and allocated as part of the compilation
    232 // of the source code.
    233 
    234 // Please note this interface returns shared function infos.  This means you
    235 // need to call Factory::NewFunctionFromSharedFunctionInfo before you have a
    236 // real function with a context.
    237 
    238 class Compiler : public AllStatic {
    239  public:
    240   // Default maximum number of function optimization attempts before we
    241   // give up.
    242   static const int kDefaultMaxOptCount = 10;
    243 
    244   static const int kMaxInliningLevels = 3;
    245 
    246   // All routines return a SharedFunctionInfo.
    247   // If an error occurs an exception is raised and the return handle
    248   // contains NULL.
    249 
    250   // Compile a String source within a context.
    251   static Handle<SharedFunctionInfo> Compile(Handle<String> source,
    252                                             Handle<Object> script_name,
    253                                             int line_offset,
    254                                             int column_offset,
    255                                             v8::Extension* extension,
    256                                             ScriptDataImpl* pre_data,
    257                                             Handle<Object> script_data,
    258                                             NativesFlag is_natives_code);
    259 
    260   // Compile a String source within a context for Eval.
    261   static Handle<SharedFunctionInfo> CompileEval(Handle<String> source,
    262                                                 Handle<Context> context,
    263                                                 bool is_global,
    264                                                 StrictModeFlag strict_mode);
    265 
    266   // Compile from function info (used for lazy compilation). Returns true on
    267   // success and false if the compilation resulted in a stack overflow.
    268   static bool CompileLazy(CompilationInfo* info);
    269 
    270   // Compile a shared function info object (the function is possibly lazily
    271   // compiled).
    272   static Handle<SharedFunctionInfo> BuildFunctionInfo(FunctionLiteral* node,
    273                                                       Handle<Script> script);
    274 
    275   // Set the function info for a newly compiled function.
    276   static void SetFunctionInfo(Handle<SharedFunctionInfo> function_info,
    277                               FunctionLiteral* lit,
    278                               bool is_toplevel,
    279                               Handle<Script> script);
    280 
    281 #ifdef ENABLE_DEBUGGER_SUPPORT
    282   static bool MakeCodeForLiveEdit(CompilationInfo* info);
    283 #endif
    284 
    285   static void RecordFunctionCompilation(Logger::LogEventsAndTags tag,
    286                                         CompilationInfo* info,
    287                                         Handle<SharedFunctionInfo> shared);
    288 };
    289 
    290 
    291 // During compilation we need a global list of handles to constants
    292 // for frame elements.  When the zone gets deleted, we make sure to
    293 // clear this list of handles as well.
    294 class CompilationZoneScope : public ZoneScope {
    295  public:
    296   explicit CompilationZoneScope(ZoneScopeMode mode) : ZoneScope(mode) { }
    297   virtual ~CompilationZoneScope() {
    298     if (ShouldDeleteOnExit()) {
    299       Isolate* isolate = Isolate::Current();
    300       isolate->frame_element_constant_list()->Clear();
    301       isolate->result_constant_list()->Clear();
    302     }
    303   }
    304 };
    305 
    306 
    307 } }  // namespace v8::internal
    308 
    309 #endif  // V8_COMPILER_H_
    310