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