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/zone.h" 10 11 namespace v8 { 12 namespace internal { 13 14 // The AST refers to variables via VariableProxies - placeholders for the actual 15 // variables. Variables themselves are never directly referred to from the AST, 16 // they are maintained by scopes, and referred to from VariableProxies and Slots 17 // after binding and variable allocation. 18 class Variable: public ZoneObject { 19 public: 20 enum Kind { NORMAL, FUNCTION, THIS, ARGUMENTS }; 21 22 Variable(Scope* scope, const AstRawString* name, VariableMode mode, Kind kind, 23 InitializationFlag initialization_flag, 24 MaybeAssignedFlag maybe_assigned_flag = kNotAssigned); 25 26 virtual ~Variable() {} 27 28 // Printing support 29 static const char* Mode2String(VariableMode mode); 30 31 // The source code for an eval() call may refer to a variable that is 32 // in an outer scope about which we don't know anything (it may not 33 // be the script scope). scope() is NULL in that case. Currently the 34 // scope is only used to follow the context chain length. 35 Scope* scope() const { return scope_; } 36 37 // This is for adjusting the scope of temporaries used when desugaring 38 // parameter initializers. 39 void set_scope(Scope* scope) { scope_ = scope; } 40 41 Handle<String> name() const { return name_->string(); } 42 const AstRawString* raw_name() const { return name_; } 43 VariableMode mode() const { return mode_; } 44 bool has_forced_context_allocation() const { 45 return force_context_allocation_; 46 } 47 void ForceContextAllocation() { 48 force_context_allocation_ = true; 49 } 50 bool is_used() { return is_used_; } 51 void set_is_used() { is_used_ = true; } 52 MaybeAssignedFlag maybe_assigned() const { return maybe_assigned_; } 53 void set_maybe_assigned() { maybe_assigned_ = kMaybeAssigned; } 54 55 int initializer_position() { return initializer_position_; } 56 void set_initializer_position(int pos) { initializer_position_ = pos; } 57 58 bool IsVariable(Handle<String> n) const { 59 return !is_this() && name().is_identical_to(n); 60 } 61 62 bool IsUnallocated() const { 63 return location_ == VariableLocation::UNALLOCATED; 64 } 65 bool IsParameter() const { return location_ == VariableLocation::PARAMETER; } 66 bool IsStackLocal() const { return location_ == VariableLocation::LOCAL; } 67 bool IsStackAllocated() const { return IsParameter() || IsStackLocal(); } 68 bool IsContextSlot() const { return location_ == VariableLocation::CONTEXT; } 69 bool IsGlobalSlot() const { return location_ == VariableLocation::GLOBAL; } 70 bool IsUnallocatedOrGlobalSlot() const { 71 return IsUnallocated() || IsGlobalSlot(); 72 } 73 bool IsLookupSlot() const { return location_ == VariableLocation::LOOKUP; } 74 bool IsGlobalObjectProperty() const; 75 bool IsStaticGlobalObjectProperty() const; 76 77 bool is_dynamic() const { return IsDynamicVariableMode(mode_); } 78 bool is_const_mode() const { return IsImmutableVariableMode(mode_); } 79 bool binding_needs_init() const { 80 return initialization_flag_ == kNeedsInitialization; 81 } 82 83 bool is_function() const { return kind_ == FUNCTION; } 84 bool is_this() const { return kind_ == THIS; } 85 bool is_arguments() const { return kind_ == ARGUMENTS; } 86 87 // For script scopes, the "this" binding is provided by a ScriptContext added 88 // to the global's ScriptContextTable. This binding might not statically 89 // resolve to a Variable::THIS binding, instead being DYNAMIC_LOCAL. However 90 // any variable named "this" does indeed refer to a Variable::THIS binding; 91 // the grammar ensures this to be the case. So wherever a "this" binding 92 // might be provided by the global, use HasThisName instead of is_this(). 93 bool HasThisName(Isolate* isolate) const { 94 return is_this() || *name() == *isolate->factory()->this_string(); 95 } 96 97 // True if the variable is named eval and not known to be shadowed. 98 bool is_possibly_eval(Isolate* isolate) const { 99 return IsVariable(isolate->factory()->eval_string()); 100 } 101 102 Variable* local_if_not_shadowed() const { 103 DCHECK(mode_ == DYNAMIC_LOCAL && local_if_not_shadowed_ != NULL); 104 return local_if_not_shadowed_; 105 } 106 107 void set_local_if_not_shadowed(Variable* local) { 108 local_if_not_shadowed_ = local; 109 } 110 111 VariableLocation location() const { return location_; } 112 int index() const { return index_; } 113 InitializationFlag initialization_flag() const { 114 return initialization_flag_; 115 } 116 117 void AllocateTo(VariableLocation location, int index) { 118 location_ = location; 119 index_ = index; 120 } 121 122 static int CompareIndex(Variable* const* v, Variable* const* w); 123 124 private: 125 Scope* scope_; 126 const AstRawString* name_; 127 VariableMode mode_; 128 Kind kind_; 129 VariableLocation location_; 130 int index_; 131 int initializer_position_; 132 133 // If this field is set, this variable references the stored locally bound 134 // variable, but it might be shadowed by variable bindings introduced by 135 // sloppy 'eval' calls between the reference scope (inclusive) and the 136 // binding scope (exclusive). 137 Variable* local_if_not_shadowed_; 138 139 // Usage info. 140 bool force_context_allocation_; // set by variable resolver 141 bool is_used_; 142 InitializationFlag initialization_flag_; 143 MaybeAssignedFlag maybe_assigned_; 144 }; 145 } // namespace internal 146 } // namespace v8 147 148 #endif // V8_AST_VARIABLES_H_ 149