OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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_SCOPES_H_ | 5 #ifndef V8_SCOPES_H_ |
6 #define V8_SCOPES_H_ | 6 #define V8_SCOPES_H_ |
7 | 7 |
8 #include "ast.h" | 8 #include "ast.h" |
9 #include "zone.h" | 9 #include "zone.h" |
10 | 10 |
11 namespace v8 { | 11 namespace v8 { |
12 namespace internal { | 12 namespace internal { |
13 | 13 |
14 class CompilationInfo; | 14 class CompilationInfo; |
15 | 15 |
16 | 16 |
17 // A hash map to support fast variable declaration and lookup. | 17 // A hash map to support fast variable declaration and lookup. |
18 class VariableMap: public ZoneHashMap { | 18 class VariableMap: public ZoneHashMap { |
19 public: | 19 public: |
20 explicit VariableMap(Zone* zone); | 20 explicit VariableMap(Zone* zone); |
21 | 21 |
22 virtual ~VariableMap(); | 22 virtual ~VariableMap(); |
23 | 23 |
24 Variable* Declare(Scope* scope, | 24 Variable* Declare(Scope* scope, |
25 Handle<String> name, | 25 const AstString* name, |
26 VariableMode mode, | 26 VariableMode mode, |
27 bool is_valid_lhs, | 27 bool is_valid_lhs, |
28 Variable::Kind kind, | 28 Variable::Kind kind, |
29 InitializationFlag initialization_flag, | 29 InitializationFlag initialization_flag, |
30 Interface* interface = Interface::NewValue()); | 30 Interface* interface = Interface::NewValue()); |
31 | 31 |
32 Variable* Lookup(Handle<String> name); | 32 Variable* Lookup(const AstString* name); |
33 | 33 |
34 Zone* zone() const { return zone_; } | 34 Zone* zone() const { return zone_; } |
35 | 35 |
36 private: | 36 private: |
37 Zone* zone_; | 37 Zone* zone_; |
38 }; | 38 }; |
39 | 39 |
40 | 40 |
41 // The dynamic scope part holds hash maps for the variables that will | 41 // The dynamic scope part holds hash maps for the variables that will |
42 // be looked up dynamically from within eval and with scopes. The objects | 42 // be looked up dynamically from within eval and with scopes. The objects |
(...skipping 24 matching lines...) Expand all Loading... |
67 // corresponding variable (though some are bound during parse time). Variable | 67 // corresponding variable (though some are bound during parse time). Variable |
68 // allocation binds each unresolved VariableProxy to one Variable and assigns | 68 // allocation binds each unresolved VariableProxy to one Variable and assigns |
69 // a location. Note that many VariableProxy nodes may refer to the same Java- | 69 // a location. Note that many VariableProxy nodes may refer to the same Java- |
70 // Script variable. | 70 // Script variable. |
71 | 71 |
72 class Scope: public ZoneObject { | 72 class Scope: public ZoneObject { |
73 public: | 73 public: |
74 // --------------------------------------------------------------------------- | 74 // --------------------------------------------------------------------------- |
75 // Construction | 75 // Construction |
76 | 76 |
77 Scope(Scope* outer_scope, ScopeType scope_type, Zone* zone); | 77 Scope(Scope* outer_scope, ScopeType scope_type, |
| 78 AstStringTable* string_table, Zone* zone); |
78 | 79 |
79 // Compute top scope and allocate variables. For lazy compilation the top | 80 // Compute top scope and allocate variables. For lazy compilation the top |
80 // scope only contains the single lazily compiled function, so this | 81 // scope only contains the single lazily compiled function, so this |
81 // doesn't re-allocate variables repeatedly. | 82 // doesn't re-allocate variables repeatedly. |
82 static bool Analyze(CompilationInfo* info); | 83 static bool Analyze(CompilationInfo* info); |
83 | 84 |
84 static Scope* DeserializeScopeChain(Context* context, Scope* global_scope, | 85 static Scope* DeserializeScopeChain(Context* context, Scope* global_scope, |
85 Zone* zone); | 86 Zone* zone); |
86 | 87 |
87 // The scope name is only used for printing/debugging. | 88 // The scope name is only used for printing/debugging. |
88 void SetScopeName(Handle<String> scope_name) { scope_name_ = scope_name; } | 89 void SetScopeName(const AstString* scope_name) { scope_name_ = scope_name; } |
89 | 90 |
90 void Initialize(); | 91 void Initialize(); |
91 | 92 |
92 // Checks if the block scope is redundant, i.e. it does not contain any | 93 // Checks if the block scope is redundant, i.e. it does not contain any |
93 // block scoped declarations. In that case it is removed from the scope | 94 // block scoped declarations. In that case it is removed from the scope |
94 // tree and its children are reparented. | 95 // tree and its children are reparented. |
95 Scope* FinalizeBlockScope(); | 96 Scope* FinalizeBlockScope(); |
96 | 97 |
97 Zone* zone() const { return zone_; } | 98 Zone* zone() const { return zone_; } |
98 | 99 |
99 // --------------------------------------------------------------------------- | 100 // --------------------------------------------------------------------------- |
100 // Declarations | 101 // Declarations |
101 | 102 |
102 // Lookup a variable in this scope. Returns the variable or NULL if not found. | 103 // Lookup a variable in this scope. Returns the variable or NULL if not found. |
103 Variable* LookupLocal(Handle<String> name); | 104 Variable* LookupLocal(const AstString* name); |
104 | 105 |
105 // This lookup corresponds to a lookup in the "intermediate" scope sitting | 106 // This lookup corresponds to a lookup in the "intermediate" scope sitting |
106 // between this scope and the outer scope. (ECMA-262, 3rd., requires that | 107 // between this scope and the outer scope. (ECMA-262, 3rd., requires that |
107 // the name of named function literal is kept in an intermediate scope | 108 // the name of named function literal is kept in an intermediate scope |
108 // in between this scope and the next outer scope.) | 109 // in between this scope and the next outer scope.) |
109 Variable* LookupFunctionVar(Handle<String> name, | 110 Variable* LookupFunctionVar(const AstString* name, |
110 AstNodeFactory<AstNullVisitor>* factory); | 111 AstNodeFactory<AstNullVisitor>* factory); |
111 | 112 |
112 // Lookup a variable in this scope or outer scopes. | 113 // Lookup a variable in this scope or outer scopes. |
113 // Returns the variable or NULL if not found. | 114 // Returns the variable or NULL if not found. |
114 Variable* Lookup(Handle<String> name); | 115 Variable* Lookup(const AstString* name); |
115 | 116 |
116 // Declare the function variable for a function literal. This variable | 117 // Declare the function variable for a function literal. This variable |
117 // is in an intermediate scope between this function scope and the the | 118 // is in an intermediate scope between this function scope and the the |
118 // outer scope. Only possible for function scopes; at most one variable. | 119 // outer scope. Only possible for function scopes; at most one variable. |
119 void DeclareFunctionVar(VariableDeclaration* declaration) { | 120 void DeclareFunctionVar(VariableDeclaration* declaration) { |
120 ASSERT(is_function_scope()); | 121 ASSERT(is_function_scope()); |
121 function_ = declaration; | 122 function_ = declaration; |
122 } | 123 } |
123 | 124 |
124 // Declare a parameter in this scope. When there are duplicated | 125 // Declare a parameter in this scope. When there are duplicated |
125 // parameters the rightmost one 'wins'. However, the implementation | 126 // parameters the rightmost one 'wins'. However, the implementation |
126 // expects all parameters to be declared and from left to right. | 127 // expects all parameters to be declared and from left to right. |
127 void DeclareParameter(Handle<String> name, VariableMode mode); | 128 void DeclareParameter(const AstString* name, VariableMode mode); |
128 | 129 |
129 // Declare a local variable in this scope. If the variable has been | 130 // Declare a local variable in this scope. If the variable has been |
130 // declared before, the previously declared variable is returned. | 131 // declared before, the previously declared variable is returned. |
131 Variable* DeclareLocal(Handle<String> name, | 132 Variable* DeclareLocal(const AstString* name, |
132 VariableMode mode, | 133 VariableMode mode, |
133 InitializationFlag init_flag, | 134 InitializationFlag init_flag, |
134 Interface* interface = Interface::NewValue()); | 135 Interface* interface = Interface::NewValue()); |
135 | 136 |
136 // Declare an implicit global variable in this scope which must be a | 137 // Declare an implicit global variable in this scope which must be a |
137 // global scope. The variable was introduced (possibly from an inner | 138 // global scope. The variable was introduced (possibly from an inner |
138 // scope) by a reference to an unresolved variable with no intervening | 139 // scope) by a reference to an unresolved variable with no intervening |
139 // with statements or eval calls. | 140 // with statements or eval calls. |
140 Variable* DeclareDynamicGlobal(Handle<String> name); | 141 Variable* DeclareDynamicGlobal(const AstString* name); |
141 | 142 |
142 // Create a new unresolved variable. | 143 // Create a new unresolved variable. |
143 template<class Visitor> | 144 template<class Visitor> |
144 VariableProxy* NewUnresolved(AstNodeFactory<Visitor>* factory, | 145 VariableProxy* NewUnresolved(AstNodeFactory<Visitor>* factory, |
145 Handle<String> name, | 146 const AstString* name, |
146 Interface* interface = Interface::NewValue(), | 147 Interface* interface = Interface::NewValue(), |
147 int position = RelocInfo::kNoPosition) { | 148 int position = RelocInfo::kNoPosition) { |
148 // Note that we must not share the unresolved variables with | 149 // Note that we must not share the unresolved variables with |
149 // the same name because they may be removed selectively via | 150 // the same name because they may be removed selectively via |
150 // RemoveUnresolved(). | 151 // RemoveUnresolved(). |
151 ASSERT(!already_resolved()); | 152 ASSERT(!already_resolved()); |
152 VariableProxy* proxy = | 153 VariableProxy* proxy = |
153 factory->NewVariableProxy(name, false, interface, position); | 154 factory->NewVariableProxy(name, false, interface, position); |
154 unresolved_.Add(proxy, zone_); | 155 unresolved_.Add(proxy, zone_); |
155 return proxy; | 156 return proxy; |
156 } | 157 } |
157 | 158 |
158 // Remove a unresolved variable. During parsing, an unresolved variable | 159 // Remove a unresolved variable. During parsing, an unresolved variable |
159 // may have been added optimistically, but then only the variable name | 160 // may have been added optimistically, but then only the variable name |
160 // was used (typically for labels). If the variable was not declared, the | 161 // was used (typically for labels). If the variable was not declared, the |
161 // addition introduced a new unresolved variable which may end up being | 162 // addition introduced a new unresolved variable which may end up being |
162 // allocated globally as a "ghost" variable. RemoveUnresolved removes | 163 // allocated globally as a "ghost" variable. RemoveUnresolved removes |
163 // such a variable again if it was added; otherwise this is a no-op. | 164 // such a variable again if it was added; otherwise this is a no-op. |
164 void RemoveUnresolved(VariableProxy* var); | 165 void RemoveUnresolved(VariableProxy* var); |
165 | 166 |
166 // Creates a new internal variable in this scope. The name is only used | 167 // Creates a new internal variable in this scope. The name is only used |
167 // for printing and cannot be used to find the variable. In particular, | 168 // for printing and cannot be used to find the variable. In particular, |
168 // the only way to get hold of the temporary is by keeping the Variable* | 169 // the only way to get hold of the temporary is by keeping the Variable* |
169 // around. | 170 // around. |
170 Variable* NewInternal(Handle<String> name); | 171 Variable* NewInternal(const AstString* name); |
171 | 172 |
172 // Creates a new temporary variable in this scope. The name is only used | 173 // Creates a new temporary variable in this scope. The name is only used |
173 // for printing and cannot be used to find the variable. In particular, | 174 // for printing and cannot be used to find the variable. In particular, |
174 // the only way to get hold of the temporary is by keeping the Variable* | 175 // the only way to get hold of the temporary is by keeping the Variable* |
175 // around. The name should not clash with a legitimate variable names. | 176 // around. The name should not clash with a legitimate variable names. |
176 Variable* NewTemporary(Handle<String> name); | 177 Variable* NewTemporary(const AstString* name); |
177 | 178 |
178 // Adds the specific declaration node to the list of declarations in | 179 // Adds the specific declaration node to the list of declarations in |
179 // this scope. The declarations are processed as part of entering | 180 // this scope. The declarations are processed as part of entering |
180 // the scope; see codegen.cc:ProcessDeclarations. | 181 // the scope; see codegen.cc:ProcessDeclarations. |
181 void AddDeclaration(Declaration* declaration); | 182 void AddDeclaration(Declaration* declaration); |
182 | 183 |
183 // --------------------------------------------------------------------------- | 184 // --------------------------------------------------------------------------- |
184 // Illegal redeclaration support. | 185 // Illegal redeclaration support. |
185 | 186 |
186 // Set an expression node that will be executed when the scope is | 187 // Set an expression node that will be executed when the scope is |
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
383 | 384 |
384 // Get the chain of nested scopes within this scope for the source statement | 385 // Get the chain of nested scopes within this scope for the source statement |
385 // position. The scopes will be added to the list from the outermost scope to | 386 // position. The scopes will be added to the list from the outermost scope to |
386 // the innermost scope. Only nested block, catch or with scopes are tracked | 387 // the innermost scope. Only nested block, catch or with scopes are tracked |
387 // and will be returned, but no inner function scopes. | 388 // and will be returned, but no inner function scopes. |
388 void GetNestedScopeChain(List<Handle<ScopeInfo> >* chain, | 389 void GetNestedScopeChain(List<Handle<ScopeInfo> >* chain, |
389 int statement_position); | 390 int statement_position); |
390 | 391 |
391 // --------------------------------------------------------------------------- | 392 // --------------------------------------------------------------------------- |
392 // Strict mode support. | 393 // Strict mode support. |
393 bool IsDeclared(Handle<String> name) { | 394 bool IsDeclared(const AstString* name) { |
394 // During formal parameter list parsing the scope only contains | 395 // During formal parameter list parsing the scope only contains |
395 // two variables inserted at initialization: "this" and "arguments". | 396 // two variables inserted at initialization: "this" and "arguments". |
396 // "this" is an invalid parameter name and "arguments" is invalid parameter | 397 // "this" is an invalid parameter name and "arguments" is invalid parameter |
397 // name in strict mode. Therefore looking up with the map which includes | 398 // name in strict mode. Therefore looking up with the map which includes |
398 // "this" and "arguments" in addition to all formal parameters is safe. | 399 // "this" and "arguments" in addition to all formal parameters is safe. |
399 return variables_.Lookup(name) != NULL; | 400 return variables_.Lookup(name) != NULL; |
400 } | 401 } |
401 | 402 |
402 // --------------------------------------------------------------------------- | 403 // --------------------------------------------------------------------------- |
403 // Debugging. | 404 // Debugging. |
(...skipping 10 matching lines...) Expand all Loading... |
414 Isolate* const isolate_; | 415 Isolate* const isolate_; |
415 | 416 |
416 // Scope tree. | 417 // Scope tree. |
417 Scope* outer_scope_; // the immediately enclosing outer scope, or NULL | 418 Scope* outer_scope_; // the immediately enclosing outer scope, or NULL |
418 ZoneList<Scope*> inner_scopes_; // the immediately enclosed inner scopes | 419 ZoneList<Scope*> inner_scopes_; // the immediately enclosed inner scopes |
419 | 420 |
420 // The scope type. | 421 // The scope type. |
421 ScopeType scope_type_; | 422 ScopeType scope_type_; |
422 | 423 |
423 // Debugging support. | 424 // Debugging support. |
424 Handle<String> scope_name_; | 425 const AstString* scope_name_; |
425 | 426 |
426 // The variables declared in this scope: | 427 // The variables declared in this scope: |
427 // | 428 // |
428 // All user-declared variables (incl. parameters). For global scopes | 429 // All user-declared variables (incl. parameters). For global scopes |
429 // variables may be implicitly 'declared' by being used (possibly in | 430 // variables may be implicitly 'declared' by being used (possibly in |
430 // an inner scope) with no intervening with statements or eval calls. | 431 // an inner scope) with no intervening with statements or eval calls. |
431 VariableMap variables_; | 432 VariableMap variables_; |
432 // Compiler-allocated (user-invisible) internals. | 433 // Compiler-allocated (user-invisible) internals. |
433 ZoneList<Variable*> internals_; | 434 ZoneList<Variable*> internals_; |
434 // Compiler-allocated (user-invisible) temporaries. | 435 // Compiler-allocated (user-invisible) temporaries. |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
490 | 491 |
491 // For module scopes, the host scope's internal variable binding this module. | 492 // For module scopes, the host scope's internal variable binding this module. |
492 Variable* module_var_; | 493 Variable* module_var_; |
493 | 494 |
494 // Serialized scope info support. | 495 // Serialized scope info support. |
495 Handle<ScopeInfo> scope_info_; | 496 Handle<ScopeInfo> scope_info_; |
496 bool already_resolved() { return already_resolved_; } | 497 bool already_resolved() { return already_resolved_; } |
497 | 498 |
498 // Create a non-local variable with a given name. | 499 // Create a non-local variable with a given name. |
499 // These variables are looked up dynamically at runtime. | 500 // These variables are looked up dynamically at runtime. |
500 Variable* NonLocal(Handle<String> name, VariableMode mode); | 501 Variable* NonLocal(const AstString* name, VariableMode mode); |
501 | 502 |
502 // Variable resolution. | 503 // Variable resolution. |
503 // Possible results of a recursive variable lookup telling if and how a | 504 // Possible results of a recursive variable lookup telling if and how a |
504 // variable is bound. These are returned in the output parameter *binding_kind | 505 // variable is bound. These are returned in the output parameter *binding_kind |
505 // of the LookupRecursive function. | 506 // of the LookupRecursive function. |
506 enum BindingKind { | 507 enum BindingKind { |
507 // The variable reference could be statically resolved to a variable binding | 508 // The variable reference could be statically resolved to a variable binding |
508 // which is returned. There is no 'with' statement between the reference and | 509 // which is returned. There is no 'with' statement between the reference and |
509 // the binding and no scope between the reference scope (inclusive) and | 510 // the binding and no scope between the reference scope (inclusive) and |
510 // binding scope (exclusive) makes a sloppy 'eval' call. | 511 // binding scope (exclusive) makes a sloppy 'eval' call. |
(...skipping 30 matching lines...) Expand all Loading... |
541 // The variable potentially references a property of the 'with' object. | 542 // The variable potentially references a property of the 'with' object. |
542 // * The code is being executed as part of a call to 'eval' and the calling | 543 // * The code is being executed as part of a call to 'eval' and the calling |
543 // context chain contains either a variable binding for the name or it | 544 // context chain contains either a variable binding for the name or it |
544 // contains a 'with' context. | 545 // contains a 'with' context. |
545 DYNAMIC_LOOKUP | 546 DYNAMIC_LOOKUP |
546 }; | 547 }; |
547 | 548 |
548 // Lookup a variable reference given by name recursively starting with this | 549 // Lookup a variable reference given by name recursively starting with this |
549 // scope. If the code is executed because of a call to 'eval', the context | 550 // scope. If the code is executed because of a call to 'eval', the context |
550 // parameter should be set to the calling context of 'eval'. | 551 // parameter should be set to the calling context of 'eval'. |
551 Variable* LookupRecursive(Handle<String> name, | 552 Variable* LookupRecursive(const AstString* name, |
552 BindingKind* binding_kind, | 553 BindingKind* binding_kind, |
553 AstNodeFactory<AstNullVisitor>* factory); | 554 AstNodeFactory<AstNullVisitor>* factory); |
554 MUST_USE_RESULT | 555 MUST_USE_RESULT |
555 bool ResolveVariable(CompilationInfo* info, | 556 bool ResolveVariable(CompilationInfo* info, |
556 VariableProxy* proxy, | 557 VariableProxy* proxy, |
557 AstNodeFactory<AstNullVisitor>* factory); | 558 AstNodeFactory<AstNullVisitor>* factory); |
558 MUST_USE_RESULT | 559 MUST_USE_RESULT |
559 bool ResolveVariablesRecursively(CompilationInfo* info, | 560 bool ResolveVariablesRecursively(CompilationInfo* info, |
560 AstNodeFactory<AstNullVisitor>* factory); | 561 AstNodeFactory<AstNullVisitor>* factory); |
561 | 562 |
(...skipping 23 matching lines...) Expand all Loading... |
585 // In the case of code compiled and run using 'eval', the context | 586 // In the case of code compiled and run using 'eval', the context |
586 // parameter is the context in which eval was called. In all other | 587 // parameter is the context in which eval was called. In all other |
587 // cases the context parameter is an empty handle. | 588 // cases the context parameter is an empty handle. |
588 MUST_USE_RESULT | 589 MUST_USE_RESULT |
589 bool AllocateVariables(CompilationInfo* info, | 590 bool AllocateVariables(CompilationInfo* info, |
590 AstNodeFactory<AstNullVisitor>* factory); | 591 AstNodeFactory<AstNullVisitor>* factory); |
591 | 592 |
592 private: | 593 private: |
593 // Construct a scope based on the scope info. | 594 // Construct a scope based on the scope info. |
594 Scope(Scope* inner_scope, ScopeType type, Handle<ScopeInfo> scope_info, | 595 Scope(Scope* inner_scope, ScopeType type, Handle<ScopeInfo> scope_info, |
595 Zone* zone); | 596 AstStringTable* string_table, Zone* zone); |
596 | 597 |
597 // Construct a catch scope with a binding for the name. | 598 // Construct a catch scope with a binding for the name. |
598 Scope(Scope* inner_scope, Handle<String> catch_variable_name, Zone* zone); | 599 Scope(Scope* inner_scope, |
| 600 const AstString* catch_variable_name, |
| 601 AstStringTable* string_table, Zone* zone); |
599 | 602 |
600 void AddInnerScope(Scope* inner_scope) { | 603 void AddInnerScope(Scope* inner_scope) { |
601 if (inner_scope != NULL) { | 604 if (inner_scope != NULL) { |
602 inner_scopes_.Add(inner_scope, zone_); | 605 inner_scopes_.Add(inner_scope, zone_); |
603 inner_scope->outer_scope_ = this; | 606 inner_scope->outer_scope_ = this; |
604 } | 607 } |
605 } | 608 } |
606 | 609 |
607 void SetDefaults(ScopeType type, | 610 void SetDefaults(ScopeType type, |
608 Scope* outer_scope, | 611 Scope* outer_scope, |
609 Handle<ScopeInfo> scope_info); | 612 Handle<ScopeInfo> scope_info); |
610 | 613 |
| 614 AstStringTable* string_table_; |
611 Zone* zone_; | 615 Zone* zone_; |
612 }; | 616 }; |
613 | 617 |
614 } } // namespace v8::internal | 618 } } // namespace v8::internal |
615 | 619 |
616 #endif // V8_SCOPES_H_ | 620 #endif // V8_SCOPES_H_ |
OLD | NEW |