• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
scope()29   Scope* scope() const { return scope_; }
30 
31   // This is for adjusting the scope of temporaries used when desugaring
32   // parameter initializers.
set_scope(Scope * scope)33   void set_scope(Scope* scope) { scope_ = scope; }
34 
name()35   Handle<String> name() const { return name_->string(); }
raw_name()36   const AstRawString* raw_name() const { return name_; }
mode()37   VariableMode mode() const { return VariableModeField::decode(bit_field_); }
has_forced_context_allocation()38   bool has_forced_context_allocation() const {
39     return ForceContextAllocationField::decode(bit_field_);
40   }
ForceContextAllocation()41   void ForceContextAllocation() {
42     DCHECK(IsUnallocated() || IsContextSlot() ||
43            location() == VariableLocation::MODULE);
44     bit_field_ = ForceContextAllocationField::update(bit_field_, true);
45   }
is_used()46   bool is_used() { return IsUsedField::decode(bit_field_); }
set_is_used()47   void set_is_used() { bit_field_ = IsUsedField::update(bit_field_, true); }
maybe_assigned()48   MaybeAssignedFlag maybe_assigned() const {
49     return MaybeAssignedFlagField::decode(bit_field_);
50   }
set_maybe_assigned()51   void set_maybe_assigned() {
52     bit_field_ = MaybeAssignedFlagField::update(bit_field_, kMaybeAssigned);
53   }
54 
initializer_position()55   int initializer_position() { return initializer_position_; }
set_initializer_position(int pos)56   void set_initializer_position(int pos) { initializer_position_ = pos; }
57 
IsUnallocated()58   bool IsUnallocated() const {
59     return location() == VariableLocation::UNALLOCATED;
60   }
IsParameter()61   bool IsParameter() const { return location() == VariableLocation::PARAMETER; }
IsStackLocal()62   bool IsStackLocal() const { return location() == VariableLocation::LOCAL; }
IsStackAllocated()63   bool IsStackAllocated() const { return IsParameter() || IsStackLocal(); }
IsContextSlot()64   bool IsContextSlot() const { return location() == VariableLocation::CONTEXT; }
IsLookupSlot()65   bool IsLookupSlot() const { return location() == VariableLocation::LOOKUP; }
66   bool IsGlobalObjectProperty() const;
67 
is_dynamic()68   bool is_dynamic() const { return IsDynamicVariableMode(mode()); }
binding_needs_init()69   bool binding_needs_init() const {
70     DCHECK(initialization_flag() != kNeedsInitialization ||
71            IsLexicalVariableMode(mode()));
72     return initialization_flag() == kNeedsInitialization;
73   }
throw_on_const_assignment(LanguageMode language_mode)74   bool throw_on_const_assignment(LanguageMode language_mode) const {
75     return kind() != SLOPPY_FUNCTION_NAME_VARIABLE || is_strict(language_mode);
76   }
77 
is_function()78   bool is_function() const { return kind() == FUNCTION_VARIABLE; }
is_this()79   bool is_this() const { return kind() == THIS_VARIABLE; }
is_sloppy_function_name()80   bool is_sloppy_function_name() const {
81     return kind() == SLOPPY_FUNCTION_NAME_VARIABLE;
82   }
83 
local_if_not_shadowed()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 
set_local_if_not_shadowed(Variable * local)89   void set_local_if_not_shadowed(Variable* local) {
90     local_if_not_shadowed_ = local;
91   }
92 
location()93   VariableLocation location() const {
94     return LocationField::decode(bit_field_);
95   }
kind()96   VariableKind kind() const { return VariableKindField::decode(bit_field_); }
initialization_flag()97   InitializationFlag initialization_flag() const {
98     return InitializationFlagField::decode(bit_field_);
99   }
100 
index()101   int index() const { return index_; }
102 
IsExport()103   bool IsExport() const {
104     DCHECK_EQ(location(), VariableLocation::MODULE);
105     DCHECK_NE(index(), 0);
106     return index() > 0;
107   }
108 
AllocateTo(VariableLocation location,int index)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 
DefaultInitializationFlag(VariableMode mode)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> {};
next()153   Variable** next() { return &next_; }
154   friend List;
155 };
156 }  // namespace internal
157 }  // namespace v8
158 
159 #endif  // V8_AST_VARIABLES_H_
160