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 |