Home | History | Annotate | Download | only in src
      1 // Copyright 2006-2008 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 "parser.h"
     34 #include "register-allocator.h"
     35 #include "zone.h"
     36 
     37 namespace v8 {
     38 namespace internal {
     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   // Compilation mode.  Either the compiler is used as the primary
     45   // compiler and needs to setup everything or the compiler is used as
     46   // the secondary compiler for split compilation and has to handle
     47   // bailouts.
     48   enum Mode {
     49     PRIMARY,
     50     SECONDARY
     51   };
     52 
     53   // A description of the compilation state at a bailout to the secondary
     54   // code generator.
     55   //
     56   // The state is currently simple: there are no parameters or local
     57   // variables to worry about ('this' can be found in the stack frame).
     58   // There are at most two live values.
     59   //
     60   // There is a label that should be bound to the beginning of the bailout
     61   // stub code.
     62   class Bailout : public ZoneObject {
     63    public:
     64     Bailout(Register left, Register right) : left_(left), right_(right) {}
     65 
     66     Label* label() { return &label_; }
     67 
     68    private:
     69     Register left_;
     70     Register right_;
     71     Label label_;
     72   };
     73 
     74 
     75   // Lazy compilation of a JSFunction.
     76   CompilationInfo(Handle<JSFunction> closure,
     77                   int loop_nesting,
     78                   Handle<Object> receiver)
     79       : closure_(closure),
     80         function_(NULL),
     81         is_eval_(false),
     82         loop_nesting_(loop_nesting),
     83         receiver_(receiver) {
     84     Initialize();
     85     ASSERT(!closure_.is_null() &&
     86            shared_info_.is_null() &&
     87            script_.is_null());
     88   }
     89 
     90   // Lazy compilation based on SharedFunctionInfo.
     91   explicit CompilationInfo(Handle<SharedFunctionInfo> shared_info)
     92       : shared_info_(shared_info),
     93         function_(NULL),
     94         is_eval_(false),
     95         loop_nesting_(0) {
     96     Initialize();
     97     ASSERT(closure_.is_null() &&
     98            !shared_info_.is_null() &&
     99            script_.is_null());
    100   }
    101 
    102   // Eager compilation.
    103   CompilationInfo(FunctionLiteral* literal, Handle<Script> script, bool is_eval)
    104       : script_(script),
    105         function_(literal),
    106         is_eval_(is_eval),
    107         loop_nesting_(0) {
    108     Initialize();
    109     ASSERT(closure_.is_null() &&
    110            shared_info_.is_null() &&
    111            !script_.is_null());
    112   }
    113 
    114   // We can only get a JSFunction if we actually have one.
    115   Handle<JSFunction> closure() { return closure_; }
    116 
    117   // We can get a SharedFunctionInfo from a JSFunction or if we actually
    118   // have one.
    119   Handle<SharedFunctionInfo> shared_info() {
    120     if (!closure().is_null()) {
    121       return Handle<SharedFunctionInfo>(closure()->shared());
    122     } else {
    123       return shared_info_;
    124     }
    125   }
    126 
    127   // We can always get a script.  Either we have one or we can get a shared
    128   // function info.
    129   Handle<Script> script() {
    130     if (!script_.is_null()) {
    131       return script_;
    132     } else {
    133       ASSERT(shared_info()->script()->IsScript());
    134       return Handle<Script>(Script::cast(shared_info()->script()));
    135     }
    136   }
    137 
    138   // There should always be a function literal, but it may be set after
    139   // construction (for lazy compilation).
    140   FunctionLiteral* function() { return function_; }
    141   void set_function(FunctionLiteral* literal) {
    142     ASSERT(function_ == NULL);
    143     function_ = literal;
    144   }
    145 
    146   // Simple accessors.
    147   bool is_eval() { return is_eval_; }
    148   int loop_nesting() { return loop_nesting_; }
    149   bool has_receiver() { return !receiver_.is_null(); }
    150   Handle<Object> receiver() { return receiver_; }
    151   List<Bailout*>* bailouts() { return &bailouts_; }
    152 
    153   // Accessors for mutable fields (possibly set by analysis passes) with
    154   // default values given by Initialize.
    155   Mode mode() { return mode_; }
    156   void set_mode(Mode mode) { mode_ = mode; }
    157 
    158   bool has_this_properties() { return has_this_properties_; }
    159   void set_has_this_properties(bool flag) { has_this_properties_ = flag; }
    160 
    161   bool has_global_object() {
    162     return !closure().is_null() && (closure()->context()->global() != NULL);
    163   }
    164 
    165   GlobalObject* global_object() {
    166     return has_global_object() ? closure()->context()->global() : NULL;
    167   }
    168 
    169   bool has_globals() { return has_globals_; }
    170   void set_has_globals(bool flag) { has_globals_ = flag; }
    171 
    172   // Derived accessors.
    173   Scope* scope() { return function()->scope(); }
    174 
    175   // Add a bailout with two live values.
    176   Label* AddBailout(Register left, Register right) {
    177     Bailout* bailout = new Bailout(left, right);
    178     bailouts_.Add(bailout);
    179     return bailout->label();
    180   }
    181 
    182   // Add a bailout with no live values.
    183   Label* AddBailout() { return AddBailout(no_reg, no_reg); }
    184 
    185  private:
    186   void Initialize() {
    187     mode_ = PRIMARY;
    188     has_this_properties_ = false;
    189     has_globals_ = false;
    190   }
    191 
    192   Handle<JSFunction> closure_;
    193   Handle<SharedFunctionInfo> shared_info_;
    194   Handle<Script> script_;
    195 
    196   FunctionLiteral* function_;
    197   Mode mode_;
    198 
    199   bool is_eval_;
    200   int loop_nesting_;
    201 
    202   Handle<Object> receiver_;
    203 
    204   bool has_this_properties_;
    205   bool has_globals_;
    206 
    207   // An ordered list of bailout points encountered during fast-path
    208   // compilation.
    209   List<Bailout*> bailouts_;
    210 
    211   DISALLOW_COPY_AND_ASSIGN(CompilationInfo);
    212 };
    213 
    214 
    215 // The V8 compiler
    216 //
    217 // General strategy: Source code is translated into an anonymous function w/o
    218 // parameters which then can be executed. If the source code contains other
    219 // functions, they will be compiled and allocated as part of the compilation
    220 // of the source code.
    221 
    222 // Please note this interface returns function boilerplates.
    223 // This means you need to call Factory::NewFunctionFromBoilerplate
    224 // before you have a real function with context.
    225 
    226 class Compiler : public AllStatic {
    227  public:
    228   enum ValidationState { VALIDATE_JSON, DONT_VALIDATE_JSON };
    229 
    230   // All routines return a JSFunction.
    231   // If an error occurs an exception is raised and
    232   // the return handle contains NULL.
    233 
    234   // Compile a String source within a context.
    235   static Handle<JSFunction> Compile(Handle<String> source,
    236                                     Handle<Object> script_name,
    237                                     int line_offset, int column_offset,
    238                                     v8::Extension* extension,
    239                                     ScriptDataImpl* pre_data,
    240                                     Handle<Object> script_data,
    241                                     NativesFlag is_natives_code);
    242 
    243   // Compile a String source within a context for Eval.
    244   static Handle<JSFunction> CompileEval(Handle<String> source,
    245                                         Handle<Context> context,
    246                                         bool is_global,
    247                                         ValidationState validation);
    248 
    249   // Compile from function info (used for lazy compilation). Returns
    250   // true on success and false if the compilation resulted in a stack
    251   // overflow.
    252   static bool CompileLazy(CompilationInfo* info);
    253 
    254   // Compile a function boilerplate object (the function is possibly
    255   // lazily compiled). Called recursively from a backend code
    256   // generator 'caller' to build the boilerplate.
    257   static Handle<JSFunction> BuildBoilerplate(FunctionLiteral* node,
    258                                              Handle<Script> script,
    259                                              AstVisitor* caller);
    260 
    261   // Set the function info for a newly compiled function.
    262   static void SetFunctionInfo(Handle<JSFunction> fun,
    263                               FunctionLiteral* lit,
    264                               bool is_toplevel,
    265                               Handle<Script> script);
    266 
    267  private:
    268 
    269 #if defined ENABLE_LOGGING_AND_PROFILING || defined ENABLE_OPROFILE_AGENT
    270   static void LogCodeCreateEvent(Logger::LogEventsAndTags tag,
    271                                  Handle<String> name,
    272                                  Handle<String> inferred_name,
    273                                  int start_position,
    274                                  Handle<Script> script,
    275                                  Handle<Code> code);
    276 #endif
    277 };
    278 
    279 
    280 // During compilation we need a global list of handles to constants
    281 // for frame elements.  When the zone gets deleted, we make sure to
    282 // clear this list of handles as well.
    283 class CompilationZoneScope : public ZoneScope {
    284  public:
    285   explicit CompilationZoneScope(ZoneScopeMode mode) : ZoneScope(mode) { }
    286   virtual ~CompilationZoneScope() {
    287     if (ShouldDeleteOnExit()) {
    288       FrameElement::ClearConstantList();
    289       Result::ClearConstantList();
    290     }
    291   }
    292 };
    293 
    294 
    295 } }  // namespace v8::internal
    296 
    297 #endif  // V8_COMPILER_H_
    298