| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef V8_AST_VARIABLES_H_ | 5 #ifndef V8_AST_VARIABLES_H_ |
| 6 #define V8_AST_VARIABLES_H_ | 6 #define V8_AST_VARIABLES_H_ |
| 7 | 7 |
| 8 #include "src/ast/ast-value-factory.h" | 8 #include "src/ast/ast-value-factory.h" |
| 9 #include "src/zone.h" | 9 #include "src/zone.h" |
| 10 | 10 |
| 11 namespace v8 { | 11 namespace v8 { |
| 12 namespace internal { | 12 namespace internal { |
| 13 | 13 |
| 14 // The AST refers to variables via VariableProxies - placeholders for the actual | 14 // The AST refers to variables via VariableProxies - placeholders for the actual |
| 15 // variables. Variables themselves are never directly referred to from the AST, | 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 | 16 // they are maintained by scopes, and referred to from VariableProxies and Slots |
| 17 // after binding and variable allocation. | 17 // after binding and variable allocation. |
| 18 | |
| 19 class ClassVariable; | |
| 20 | |
| 21 class Variable: public ZoneObject { | 18 class Variable: public ZoneObject { |
| 22 public: | 19 public: |
| 23 enum Kind { NORMAL, FUNCTION, CLASS, THIS, ARGUMENTS }; | 20 enum Kind { NORMAL, FUNCTION, THIS, ARGUMENTS }; |
| 24 | 21 |
| 25 Variable(Scope* scope, const AstRawString* name, VariableMode mode, Kind kind, | 22 Variable(Scope* scope, const AstRawString* name, VariableMode mode, Kind kind, |
| 26 InitializationFlag initialization_flag, | 23 InitializationFlag initialization_flag, |
| 27 MaybeAssignedFlag maybe_assigned_flag = kNotAssigned); | 24 MaybeAssignedFlag maybe_assigned_flag = kNotAssigned); |
| 28 | 25 |
| 29 virtual ~Variable() {} | 26 virtual ~Variable() {} |
| 30 | 27 |
| 31 // Printing support | 28 // Printing support |
| 32 static const char* Mode2String(VariableMode mode); | 29 static const char* Mode2String(VariableMode mode); |
| 33 | 30 |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 77 bool IsGlobalObjectProperty() const; | 74 bool IsGlobalObjectProperty() const; |
| 78 bool IsStaticGlobalObjectProperty() const; | 75 bool IsStaticGlobalObjectProperty() const; |
| 79 | 76 |
| 80 bool is_dynamic() const { return IsDynamicVariableMode(mode_); } | 77 bool is_dynamic() const { return IsDynamicVariableMode(mode_); } |
| 81 bool is_const_mode() const { return IsImmutableVariableMode(mode_); } | 78 bool is_const_mode() const { return IsImmutableVariableMode(mode_); } |
| 82 bool binding_needs_init() const { | 79 bool binding_needs_init() const { |
| 83 return initialization_flag_ == kNeedsInitialization; | 80 return initialization_flag_ == kNeedsInitialization; |
| 84 } | 81 } |
| 85 | 82 |
| 86 bool is_function() const { return kind_ == FUNCTION; } | 83 bool is_function() const { return kind_ == FUNCTION; } |
| 87 bool is_class() const { return kind_ == CLASS; } | |
| 88 bool is_this() const { return kind_ == THIS; } | 84 bool is_this() const { return kind_ == THIS; } |
| 89 bool is_arguments() const { return kind_ == ARGUMENTS; } | 85 bool is_arguments() const { return kind_ == ARGUMENTS; } |
| 90 | 86 |
| 91 // For script scopes, the "this" binding is provided by a ScriptContext added | 87 // For script scopes, the "this" binding is provided by a ScriptContext added |
| 92 // to the global's ScriptContextTable. This binding might not statically | 88 // to the global's ScriptContextTable. This binding might not statically |
| 93 // resolve to a Variable::THIS binding, instead being DYNAMIC_LOCAL. However | 89 // resolve to a Variable::THIS binding, instead being DYNAMIC_LOCAL. However |
| 94 // any variable named "this" does indeed refer to a Variable::THIS binding; | 90 // any variable named "this" does indeed refer to a Variable::THIS binding; |
| 95 // the grammar ensures this to be the case. So wherever a "this" binding | 91 // the grammar ensures this to be the case. So wherever a "this" binding |
| 96 // might be provided by the global, use HasThisName instead of is_this(). | 92 // might be provided by the global, use HasThisName instead of is_this(). |
| 97 bool HasThisName(Isolate* isolate) const { | 93 bool HasThisName(Isolate* isolate) const { |
| 98 return is_this() || *name() == *isolate->factory()->this_string(); | 94 return is_this() || *name() == *isolate->factory()->this_string(); |
| 99 } | 95 } |
| 100 | 96 |
| 101 ClassVariable* AsClassVariable() { | |
| 102 DCHECK(is_class()); | |
| 103 return reinterpret_cast<ClassVariable*>(this); | |
| 104 } | |
| 105 | |
| 106 // True if the variable is named eval and not known to be shadowed. | 97 // True if the variable is named eval and not known to be shadowed. |
| 107 bool is_possibly_eval(Isolate* isolate) const { | 98 bool is_possibly_eval(Isolate* isolate) const { |
| 108 return IsVariable(isolate->factory()->eval_string()); | 99 return IsVariable(isolate->factory()->eval_string()); |
| 109 } | 100 } |
| 110 | 101 |
| 111 Variable* local_if_not_shadowed() const { | 102 Variable* local_if_not_shadowed() const { |
| 112 DCHECK(mode_ == DYNAMIC_LOCAL && local_if_not_shadowed_ != NULL); | 103 DCHECK(mode_ == DYNAMIC_LOCAL && local_if_not_shadowed_ != NULL); |
| 113 return local_if_not_shadowed_; | 104 return local_if_not_shadowed_; |
| 114 } | 105 } |
| 115 | 106 |
| 116 void set_local_if_not_shadowed(Variable* local) { | 107 void set_local_if_not_shadowed(Variable* local) { |
| 117 local_if_not_shadowed_ = local; | 108 local_if_not_shadowed_ = local; |
| 118 } | 109 } |
| 119 | 110 |
| 120 VariableLocation location() const { return location_; } | 111 VariableLocation location() const { return location_; } |
| 121 int index() const { return index_; } | 112 int index() const { return index_; } |
| 122 InitializationFlag initialization_flag() const { | 113 InitializationFlag initialization_flag() const { |
| 123 return initialization_flag_; | 114 return initialization_flag_; |
| 124 } | 115 } |
| 125 | 116 |
| 126 void AllocateTo(VariableLocation location, int index) { | 117 void AllocateTo(VariableLocation location, int index) { |
| 127 location_ = location; | 118 location_ = location; |
| 128 index_ = index; | 119 index_ = index; |
| 129 } | 120 } |
| 130 | 121 |
| 131 void SetFromEval() { is_from_eval_ = true; } | 122 void SetFromEval() { is_from_eval_ = true; } |
| 132 | 123 |
| 133 static int CompareIndex(Variable* const* v, Variable* const* w); | 124 static int CompareIndex(Variable* const* v, Variable* const* w); |
| 134 | 125 |
| 135 void RecordStrongModeReference(int start_position, int end_position) { | |
| 136 // Record the earliest reference to the variable. Used in error messages for | |
| 137 // strong mode references to undeclared variables. | |
| 138 if (has_strong_mode_reference_ && | |
| 139 strong_mode_reference_start_position_ < start_position) | |
| 140 return; | |
| 141 has_strong_mode_reference_ = true; | |
| 142 strong_mode_reference_start_position_ = start_position; | |
| 143 strong_mode_reference_end_position_ = end_position; | |
| 144 } | |
| 145 | |
| 146 bool has_strong_mode_reference() const { return has_strong_mode_reference_; } | |
| 147 int strong_mode_reference_start_position() const { | |
| 148 return strong_mode_reference_start_position_; | |
| 149 } | |
| 150 int strong_mode_reference_end_position() const { | |
| 151 return strong_mode_reference_end_position_; | |
| 152 } | |
| 153 PropertyAttributes DeclarationPropertyAttributes() const { | 126 PropertyAttributes DeclarationPropertyAttributes() const { |
| 154 int property_attributes = NONE; | 127 int property_attributes = NONE; |
| 155 if (IsImmutableVariableMode(mode_)) { | 128 if (IsImmutableVariableMode(mode_)) { |
| 156 property_attributes |= READ_ONLY; | 129 property_attributes |= READ_ONLY; |
| 157 } | 130 } |
| 158 if (is_from_eval_) { | 131 if (is_from_eval_) { |
| 159 property_attributes |= EVAL_DECLARED; | 132 property_attributes |= EVAL_DECLARED; |
| 160 } | 133 } |
| 161 return static_cast<PropertyAttributes>(property_attributes); | 134 return static_cast<PropertyAttributes>(property_attributes); |
| 162 } | 135 } |
| 163 | 136 |
| 164 private: | 137 private: |
| 165 Scope* scope_; | 138 Scope* scope_; |
| 166 const AstRawString* name_; | 139 const AstRawString* name_; |
| 167 VariableMode mode_; | 140 VariableMode mode_; |
| 168 Kind kind_; | 141 Kind kind_; |
| 169 VariableLocation location_; | 142 VariableLocation location_; |
| 170 int index_; | 143 int index_; |
| 171 int initializer_position_; | 144 int initializer_position_; |
| 172 // Tracks whether the variable is bound to a VariableProxy which is in strong | |
| 173 // mode, and if yes, the source location of the reference. | |
| 174 bool has_strong_mode_reference_; | |
| 175 int strong_mode_reference_start_position_; | |
| 176 int strong_mode_reference_end_position_; | |
| 177 | 145 |
| 178 // If this field is set, this variable references the stored locally bound | 146 // If this field is set, this variable references the stored locally bound |
| 179 // variable, but it might be shadowed by variable bindings introduced by | 147 // variable, but it might be shadowed by variable bindings introduced by |
| 180 // sloppy 'eval' calls between the reference scope (inclusive) and the | 148 // sloppy 'eval' calls between the reference scope (inclusive) and the |
| 181 // binding scope (exclusive). | 149 // binding scope (exclusive). |
| 182 Variable* local_if_not_shadowed_; | 150 Variable* local_if_not_shadowed_; |
| 183 | 151 |
| 184 // True if this variable is introduced by a sloppy eval | 152 // True if this variable is introduced by a sloppy eval |
| 185 bool is_from_eval_; | 153 bool is_from_eval_; |
| 186 | 154 |
| 187 // Usage info. | 155 // Usage info. |
| 188 bool force_context_allocation_; // set by variable resolver | 156 bool force_context_allocation_; // set by variable resolver |
| 189 bool is_used_; | 157 bool is_used_; |
| 190 InitializationFlag initialization_flag_; | 158 InitializationFlag initialization_flag_; |
| 191 MaybeAssignedFlag maybe_assigned_; | 159 MaybeAssignedFlag maybe_assigned_; |
| 192 }; | 160 }; |
| 193 | |
| 194 class ClassVariable : public Variable { | |
| 195 public: | |
| 196 ClassVariable(Scope* scope, const AstRawString* name, VariableMode mode, | |
| 197 InitializationFlag initialization_flag, | |
| 198 MaybeAssignedFlag maybe_assigned_flag = kNotAssigned, | |
| 199 int declaration_group_start = -1) | |
| 200 : Variable(scope, name, mode, Variable::CLASS, initialization_flag, | |
| 201 maybe_assigned_flag), | |
| 202 declaration_group_start_(declaration_group_start) {} | |
| 203 | |
| 204 int declaration_group_start() const { return declaration_group_start_; } | |
| 205 void set_declaration_group_start(int declaration_group_start) { | |
| 206 declaration_group_start_ = declaration_group_start; | |
| 207 } | |
| 208 | |
| 209 private: | |
| 210 // For classes we keep track of consecutive groups of delcarations. They are | |
| 211 // needed for strong mode scoping checks. TODO(marja, rossberg): Implement | |
| 212 // checks for functions too. | |
| 213 int declaration_group_start_; | |
| 214 }; | |
| 215 } // namespace internal | 161 } // namespace internal |
| 216 } // namespace v8 | 162 } // namespace v8 |
| 217 | 163 |
| 218 #endif // V8_AST_VARIABLES_H_ | 164 #endif // V8_AST_VARIABLES_H_ |
| OLD | NEW |