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_VARIABLES_H_
     29 #define V8_VARIABLES_H_
     30 
     31 #include "zone.h"
     32 
     33 namespace v8 {
     34 namespace internal {
     35 
     36 class UseCount BASE_EMBEDDED {
     37  public:
     38   UseCount();
     39 
     40   // Inform the node of a "use". The weight can be used to indicate
     41   // heavier use, for instance if the variable is accessed inside a loop.
     42   void RecordRead(int weight);
     43   void RecordWrite(int weight);
     44   void RecordAccess(int weight);  // records a read & write
     45   void RecordUses(UseCount* uses);
     46 
     47   int nreads() const  { return nreads_; }
     48   int nwrites() const  { return nwrites_; }
     49   int nuses() const  { return nreads_ + nwrites_; }
     50 
     51   bool is_read() const  { return nreads() > 0; }
     52   bool is_written() const  { return nwrites() > 0; }
     53   bool is_used() const  { return nuses() > 0; }
     54 
     55 #ifdef DEBUG
     56   void Print();
     57 #endif
     58 
     59  private:
     60   int nreads_;
     61   int nwrites_;
     62 };
     63 
     64 
     65 // Variables and AST expression nodes can track their "type" to enable
     66 // optimizations and removal of redundant checks when generating code.
     67 
     68 class StaticType {
     69  public:
     70   enum Kind {
     71     UNKNOWN,
     72     LIKELY_SMI
     73   };
     74 
     75   StaticType() : kind_(UNKNOWN) {}
     76 
     77   bool Is(Kind kind) const { return kind_ == kind; }
     78 
     79   bool IsKnown() const { return !Is(UNKNOWN); }
     80   bool IsUnknown() const { return Is(UNKNOWN); }
     81   bool IsLikelySmi() const { return Is(LIKELY_SMI); }
     82 
     83   void CopyFrom(StaticType* other) {
     84     kind_ = other->kind_;
     85   }
     86 
     87   static const char* Type2String(StaticType* type);
     88 
     89   // LIKELY_SMI accessors
     90   void SetAsLikelySmi() {
     91     kind_ = LIKELY_SMI;
     92   }
     93 
     94   void SetAsLikelySmiIfUnknown() {
     95     if (IsUnknown()) {
     96       SetAsLikelySmi();
     97     }
     98   }
     99 
    100  private:
    101   Kind kind_;
    102 
    103   DISALLOW_COPY_AND_ASSIGN(StaticType);
    104 };
    105 
    106 
    107 // The AST refers to variables via VariableProxies - placeholders for the actual
    108 // variables. Variables themselves are never directly referred to from the AST,
    109 // they are maintained by scopes, and referred to from VariableProxies and Slots
    110 // after binding and variable allocation.
    111 
    112 class Variable: public ZoneObject {
    113  public:
    114   enum Mode {
    115     // User declared variables:
    116     VAR,       // declared via 'var', and 'function' declarations
    117 
    118     CONST,     // declared via 'const' declarations
    119 
    120     // Variables introduced by the compiler:
    121     DYNAMIC,         // always require dynamic lookup (we don't know
    122                      // the declaration)
    123 
    124     DYNAMIC_GLOBAL,  // requires dynamic lookup, but we know that the
    125                      // variable is global unless it has been shadowed
    126                      // by an eval-introduced variable
    127 
    128     DYNAMIC_LOCAL,   // requires dynamic lookup, but we know that the
    129                      // variable is local and where it is unless it
    130                      // has been shadowed by an eval-introduced
    131                      // variable
    132 
    133     INTERNAL,        // like VAR, but not user-visible (may or may not
    134                      // be in a context)
    135 
    136     TEMPORARY        // temporary variables (not user-visible), never
    137                      // in a context
    138   };
    139 
    140   enum Kind {
    141     NORMAL,
    142     THIS,
    143     ARGUMENTS
    144   };
    145 
    146   Variable(Scope* scope,
    147            Handle<String> name,
    148            Mode mode,
    149            bool is_valid_lhs,
    150            Kind kind);
    151 
    152   // Printing support
    153   static const char* Mode2String(Mode mode);
    154 
    155   // Type testing & conversion
    156   Property* AsProperty();
    157   Variable* AsVariable();
    158   bool IsValidLeftHandSide() { return is_valid_LHS_; }
    159 
    160   // The source code for an eval() call may refer to a variable that is
    161   // in an outer scope about which we don't know anything (it may not
    162   // be the global scope). scope() is NULL in that case. Currently the
    163   // scope is only used to follow the context chain length.
    164   Scope* scope() const  { return scope_; }
    165 
    166   Handle<String> name() const  { return name_; }
    167   Mode mode() const  { return mode_; }
    168   bool is_accessed_from_inner_scope() const  {
    169     return is_accessed_from_inner_scope_;
    170   }
    171   UseCount* var_uses()  { return &var_uses_; }
    172   UseCount* obj_uses()  { return &obj_uses_; }
    173 
    174   bool IsVariable(Handle<String> n) const {
    175     return !is_this() && name().is_identical_to(n);
    176   }
    177 
    178   bool is_dynamic() const {
    179     return (mode_ == DYNAMIC ||
    180             mode_ == DYNAMIC_GLOBAL ||
    181             mode_ == DYNAMIC_LOCAL);
    182   }
    183 
    184   bool is_global() const;
    185   bool is_this() const { return kind_ == THIS; }
    186   bool is_arguments() const { return kind_ == ARGUMENTS; }
    187 
    188   // True if the variable is named eval and not known to be shadowed.
    189   bool is_possibly_eval() const {
    190     return IsVariable(Factory::eval_symbol()) &&
    191         (mode_ == DYNAMIC || mode_ == DYNAMIC_GLOBAL);
    192   }
    193 
    194   Variable* local_if_not_shadowed() const {
    195     ASSERT(mode_ == DYNAMIC_LOCAL && local_if_not_shadowed_ != NULL);
    196     return local_if_not_shadowed_;
    197   }
    198 
    199   void set_local_if_not_shadowed(Variable* local) {
    200     local_if_not_shadowed_ = local;
    201   }
    202 
    203   Expression* rewrite() const  { return rewrite_; }
    204   Slot* slot() const;
    205 
    206   StaticType* type() { return &type_; }
    207 
    208  private:
    209   Scope* scope_;
    210   Handle<String> name_;
    211   Mode mode_;
    212   bool is_valid_LHS_;
    213   Kind kind_;
    214 
    215   Variable* local_if_not_shadowed_;
    216 
    217   // Usage info.
    218   bool is_accessed_from_inner_scope_;  // set by variable resolver
    219   UseCount var_uses_;  // uses of the variable value
    220   UseCount obj_uses_;  // uses of the object the variable points to
    221 
    222   // Static type information
    223   StaticType type_;
    224 
    225   // Code generation.
    226   // rewrite_ is usually a Slot or a Property, but may be any expression.
    227   Expression* rewrite_;
    228 
    229   friend class Scope;  // Has explicit access to rewrite_.
    230 };
    231 
    232 
    233 } }  // namespace v8::internal
    234 
    235 #endif  // V8_VARIABLES_H_
    236