Home | History | Annotate | Download | only in ast
      1 // Copyright 2011 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef V8_AST_VARIABLES_H_
      6 #define V8_AST_VARIABLES_H_
      7 
      8 #include "src/ast/ast-value-factory.h"
      9 #include "src/globals.h"
     10 #include "src/zone/zone.h"
     11 
     12 namespace v8 {
     13 namespace internal {
     14 
     15 // The AST refers to variables via VariableProxies - placeholders for the actual
     16 // variables. Variables themselves are never directly referred to from the AST,
     17 // they are maintained by scopes, and referred to from VariableProxies and Slots
     18 // after binding and variable allocation.
     19 class Variable final : public ZoneObject {
     20  public:
     21   Variable(Scope* scope, const AstRawString* name, VariableMode mode,
     22            VariableKind kind, InitializationFlag initialization_flag,
     23            MaybeAssignedFlag maybe_assigned_flag = kNotAssigned);
     24 
     25   // The source code for an eval() call may refer to a variable that is
     26   // in an outer scope about which we don't know anything (it may not
     27   // be the script scope). scope() is NULL in that case. Currently the
     28   // scope is only used to follow the context chain length.
     29   Scope* scope() const { return scope_; }
     30 
     31   // This is for adjusting the scope of temporaries used when desugaring
     32   // parameter initializers.
     33   void set_scope(Scope* scope) { scope_ = scope; }
     34 
     35   Handle<String> name() const { return name_->string(); }
     36   const AstRawString* raw_name() const { return name_; }
     37   VariableMode mode() const { return VariableModeField::decode(bit_field_); }
     38   bool has_forced_context_allocation() const {
     39     return ForceContextAllocationField::decode(bit_field_);
     40   }
     41   void ForceContextAllocation() {
     42     DCHECK(IsUnallocated() || IsContextSlot() ||
     43            location() == VariableLocation::MODULE);
     44     bit_field_ = ForceContextAllocationField::update(bit_field_, true);
     45   }
     46   bool is_used() { return IsUsedField::decode(bit_field_); }
     47   void set_is_used() { bit_field_ = IsUsedField::update(bit_field_, true); }
     48   MaybeAssignedFlag maybe_assigned() const {
     49     return MaybeAssignedFlagField::decode(bit_field_);
     50   }
     51   void set_maybe_assigned() {
     52     bit_field_ = MaybeAssignedFlagField::update(bit_field_, kMaybeAssigned);
     53   }
     54 
     55   int initializer_position() { return initializer_position_; }
     56   void set_initializer_position(int pos) { initializer_position_ = pos; }
     57 
     58   bool IsUnallocated() const {
     59     return location() == VariableLocation::UNALLOCATED;
     60   }
     61   bool IsParameter() const { return location() == VariableLocation::PARAMETER; }
     62   bool IsStackLocal() const { return location() == VariableLocation::LOCAL; }
     63   bool IsStackAllocated() const { return IsParameter() || IsStackLocal(); }
     64   bool IsContextSlot() const { return location() == VariableLocation::CONTEXT; }
     65   bool IsLookupSlot() const { return location() == VariableLocation::LOOKUP; }
     66   bool IsGlobalObjectProperty() const;
     67 
     68   bool is_dynamic() const { return IsDynamicVariableMode(mode()); }
     69   bool binding_needs_init() const {
     70     DCHECK(initialization_flag() != kNeedsInitialization ||
     71            IsLexicalVariableMode(mode()));
     72     return initialization_flag() == kNeedsInitialization;
     73   }
     74   bool throw_on_const_assignment(LanguageMode language_mode) const {
     75     return kind() != SLOPPY_FUNCTION_NAME_VARIABLE || is_strict(language_mode);
     76   }
     77 
     78   bool is_function() const { return kind() == FUNCTION_VARIABLE; }
     79   bool is_this() const { return kind() == THIS_VARIABLE; }
     80   bool is_sloppy_function_name() const {
     81     return kind() == SLOPPY_FUNCTION_NAME_VARIABLE;
     82   }
     83 
     84   Variable* local_if_not_shadowed() const {
     85     DCHECK(mode() == DYNAMIC_LOCAL && local_if_not_shadowed_ != NULL);
     86     return local_if_not_shadowed_;
     87   }
     88 
     89   void set_local_if_not_shadowed(Variable* local) {
     90     local_if_not_shadowed_ = local;
     91   }
     92 
     93   VariableLocation location() const {
     94     return LocationField::decode(bit_field_);
     95   }
     96   VariableKind kind() const { return VariableKindField::decode(bit_field_); }
     97   InitializationFlag initialization_flag() const {
     98     return InitializationFlagField::decode(bit_field_);
     99   }
    100 
    101   int index() const { return index_; }
    102 
    103   bool IsExport() const {
    104     DCHECK_EQ(location(), VariableLocation::MODULE);
    105     DCHECK_NE(index(), 0);
    106     return index() > 0;
    107   }
    108 
    109   void AllocateTo(VariableLocation location, int index) {
    110     DCHECK(IsUnallocated() ||
    111            (this->location() == location && this->index() == index));
    112     DCHECK_IMPLIES(location == VariableLocation::MODULE, index != 0);
    113     bit_field_ = LocationField::update(bit_field_, location);
    114     DCHECK_EQ(location, this->location());
    115     index_ = index;
    116   }
    117 
    118   static InitializationFlag DefaultInitializationFlag(VariableMode mode) {
    119     DCHECK(IsDeclaredVariableMode(mode));
    120     return mode == VAR ? kCreatedInitialized : kNeedsInitialization;
    121   }
    122 
    123   typedef ThreadedList<Variable> List;
    124 
    125  private:
    126   Scope* scope_;
    127   const AstRawString* name_;
    128 
    129   // If this field is set, this variable references the stored locally bound
    130   // variable, but it might be shadowed by variable bindings introduced by
    131   // sloppy 'eval' calls between the reference scope (inclusive) and the
    132   // binding scope (exclusive).
    133   Variable* local_if_not_shadowed_;
    134   Variable* next_;
    135   int index_;
    136   int initializer_position_;
    137   uint16_t bit_field_;
    138 
    139   class VariableModeField : public BitField16<VariableMode, 0, 3> {};
    140   class VariableKindField
    141       : public BitField16<VariableKind, VariableModeField::kNext, 3> {};
    142   class LocationField
    143       : public BitField16<VariableLocation, VariableKindField::kNext, 3> {};
    144   class ForceContextAllocationField
    145       : public BitField16<bool, LocationField::kNext, 1> {};
    146   class IsUsedField
    147       : public BitField16<bool, ForceContextAllocationField::kNext, 1> {};
    148   class InitializationFlagField
    149       : public BitField16<InitializationFlag, IsUsedField::kNext, 2> {};
    150   class MaybeAssignedFlagField
    151       : public BitField16<MaybeAssignedFlag, InitializationFlagField::kNext,
    152                           2> {};
    153   Variable** next() { return &next_; }
    154   friend List;
    155 };
    156 }  // namespace internal
    157 }  // namespace v8
    158 
    159 #endif  // V8_AST_VARIABLES_H_
    160