00001 // Copyright 2006-2008 the V8 project authors. All rights reserved. 00002 // Redistribution and use in source and binary forms, with or without 00003 // modification, are permitted provided that the following conditions are 00004 // met: 00005 // 00006 // * Redistributions of source code must retain the above copyright 00007 // notice, this list of conditions and the following disclaimer. 00008 // * Redistributions in binary form must reproduce the above 00009 // copyright notice, this list of conditions and the following 00010 // disclaimer in the documentation and/or other materials provided 00011 // with the distribution. 00012 // * Neither the name of Google Inc. nor the names of its 00013 // contributors may be used to endorse or promote products derived 00014 // from this software without specific prior written permission. 00015 // 00016 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00017 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00018 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 00019 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 00020 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00021 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 00022 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 00023 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 00024 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00025 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00026 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00027 00028 #ifndef V8_SCOPES_H_ 00029 #define V8_SCOPES_H_ 00030 00031 #include "ast.h" 00032 #include "hashmap.h" 00033 00034 namespace v8 { namespace internal { 00035 00036 00037 // A hash map to support fast local variable declaration and lookup. 00038 00039 class LocalsMap: public HashMap { 00040 public: 00041 LocalsMap(); 00042 00043 // Dummy constructor. This constructor doesn't set up the map 00044 // properly so don't use it unless you have a good reason. 00045 explicit LocalsMap(bool gotta_love_static_overloading); 00046 00047 virtual ~LocalsMap(); 00048 00049 Variable* Declare(Scope* scope, Handle<String> name, Variable::Mode mode, 00050 bool is_valid_LHS, bool is_this); 00051 00052 Variable* Lookup(Handle<String> name); 00053 }; 00054 00055 00056 // Global invariants after AST construction: Each reference (i.e. identifier) 00057 // to a JavaScript variable (including global properties) is represented by a 00058 // VariableProxy node. Immediately after AST construction and before variable 00059 // allocation, most VariableProxy nodes are "unresolved", i.e. not bound to a 00060 // corresponding variable (though some are bound during parse time). Variable 00061 // allocation binds each unresolved VariableProxy to one Variable and assigns 00062 // a location. Note that many VariableProxy nodes may refer to the same Java- 00063 // Script variable. 00064 00065 class Scope: public ZoneObject { 00066 public: 00067 // --------------------------------------------------------------------------- 00068 // Construction 00069 00070 enum Type { 00071 EVAL_SCOPE, // the top-level scope for an 'eval' source 00072 FUNCTION_SCOPE, // the top-level scope for a function 00073 GLOBAL_SCOPE // the top-level scope for a program or a top-level eval 00074 }; 00075 00076 Scope(); 00077 Scope(Scope* outer_scope, Type type); 00078 00079 virtual ~Scope() { } 00080 00081 // The scope name is only used for printing/debugging. 00082 void SetScopeName(Handle<String> scope_name) { scope_name_ = scope_name; } 00083 00084 void Initialize(bool inside_with); 00085 00086 00087 // --------------------------------------------------------------------------- 00088 // Declarations 00089 00090 // Lookup a variable in this scope. Returns the variable or NULL if not found. 00091 virtual Variable* Lookup(Handle<String> name); 00092 00093 // Declare the function variable for a function literal. This variable 00094 // is in an intermediate scope between this function scope and the the 00095 // outer scope. Only possible for function scopes; at most one variable. 00096 Variable* DeclareFunctionVar(Handle<String> name); 00097 00098 // Declare a variable in this scope. If the variable has been 00099 // declared before, the previously declared variable is returned. 00100 virtual Variable* Declare(Handle<String> name, Variable::Mode mode); 00101 00102 // Add a parameter to the parameter list. The parameter must have been 00103 // declared via Declare. The same parameter may occur more then once in 00104 // the parameter list; they must be added in source order, from left to 00105 // right. 00106 void AddParameter(Variable* var); 00107 00108 // Create a new unresolved variable. 00109 virtual VariableProxy* NewUnresolved(Handle<String> name, bool inside_with); 00110 00111 // Remove a unresolved variable. During parsing, an unresolved variable 00112 // may have been added optimistically, but then only the variable name 00113 // was used (typically for labels). If the variable was not declared, the 00114 // addition introduced a new unresolved variable which may end up being 00115 // allocated globally as a "ghost" variable. RemoveUnresolved removes 00116 // such a variable again if it was added; otherwise this is a no-op. 00117 void RemoveUnresolved(VariableProxy* var); 00118 00119 // Creates a new temporary variable in this scope and binds a proxy to it. 00120 // The name is only used for printing and cannot be used to find the variable. 00121 // In particular, the only way to get hold of the temporary is by keeping the 00122 // VariableProxy* around. 00123 virtual VariableProxy* NewTemporary(Handle<String> name); 00124 00125 // Adds the specific declaration node to the list of declarations in 00126 // this scope. The declarations are processed as part of entering 00127 // the scope; see codegen.cc:ProcessDeclarations. 00128 void AddDeclaration(Declaration* declaration); 00129 00130 // --------------------------------------------------------------------------- 00131 // Illegal redeclaration support. 00132 00133 // Set an expression node that will be executed when the scope is 00134 // entered. We only keep track of one illegal redeclaration node per 00135 // scope - the first one - so if you try to set it multiple times 00136 // the additional requests will be silently ignored. 00137 void SetIllegalRedeclaration(Expression* expression); 00138 00139 // Visit the illegal redeclaration expression. Do not call if the 00140 // scope doesn't have an illegal redeclaration node. 00141 void VisitIllegalRedeclaration(Visitor* visitor); 00142 00143 // Check if the scope has (at least) one illegal redeclaration. 00144 bool HasIllegalRedeclaration() const { return illegal_redecl_ != NULL; } 00145 00146 00147 // --------------------------------------------------------------------------- 00148 // Scope-specific info. 00149 00150 // Inform the scope that the corresponding code contains a with statement. 00151 void RecordWithStatement() { scope_contains_with_ = true; } 00152 00153 // Inform the scope that the corresponding code contains an eval call. 00154 void RecordEvalCall() { scope_calls_eval_ = true; } 00155 00156 00157 // --------------------------------------------------------------------------- 00158 // Predicates. 00159 00160 // Specific scope types. 00161 bool is_eval_scope() const { return type_ == EVAL_SCOPE; } 00162 bool is_function_scope() const { return type_ == FUNCTION_SCOPE; } 00163 bool is_global_scope() const { return type_ == GLOBAL_SCOPE; } 00164 00165 // The scope immediately surrounding this scope, or NULL. 00166 Scope* outer_scope() const { return outer_scope_; } 00167 00168 00169 // --------------------------------------------------------------------------- 00170 // Accessors. 00171 00172 // The variable corresponding to the (function) receiver. 00173 VariableProxy* receiver() const { return receiver_; } 00174 00175 // The variable holding the function literal for named function 00176 // literals, or NULL. 00177 // Only valid for function scopes. 00178 Variable* function() const { 00179 ASSERT(is_function_scope()); 00180 return function_; 00181 } 00182 00183 // Parameters. The left-most parameter has index 0. 00184 // Only valid for function scopes. 00185 Variable* parameter(int index) const { 00186 ASSERT(is_function_scope()); 00187 return params_[index]; 00188 } 00189 00190 int num_parameters() const { return params_.length(); } 00191 00192 // The local variable 'arguments' if we need to allocate it; NULL otherwise. 00193 // If arguments() exist, arguments_shadow() exists, too. 00194 VariableProxy* arguments() const { return arguments_; } 00195 00196 // The '.arguments' shadow variable if we need to allocate it; NULL otherwise. 00197 // If arguments_shadow() exist, arguments() exists, too. 00198 VariableProxy* arguments_shadow() const { return arguments_shadow_; } 00199 00200 // Declarations list. 00201 ZoneList<Declaration*>* declarations() { return &decls_; } 00202 00203 00204 00205 // --------------------------------------------------------------------------- 00206 // Variable allocation. 00207 00208 // Collect all used locals in this scope. 00209 template<class Allocator> 00210 void CollectUsedVariables(List<Variable*, Allocator>* locals); 00211 00212 // Resolve and fill in the allocation information for all variables in 00213 // this scopes. Must be called *after* all scopes have been processed 00214 // (parsed) to ensure that unresolved variables can be resolved properly. 00215 void AllocateVariables(); 00216 00217 // Result of variable allocation. 00218 int num_stack_slots() const { return num_stack_slots_; } 00219 int num_heap_slots() const { return num_heap_slots_; } 00220 00221 // True if this scope supports calling eval (has a properly 00222 // initialized context). 00223 bool SupportsEval() const; 00224 00225 // Make sure this scope and all outer scopes are eagerly compiled. 00226 void ForceEagerCompilation() { force_eager_compilation_ = true; } 00227 00228 // Determine if we can use lazy compilation for this scope. 00229 bool AllowsLazyCompilation() const; 00230 00231 // True if the outer context of this scope is always the global context. 00232 bool HasTrivialOuterContext() const; 00233 00234 // The number of contexts between this and scope; zero if this == scope. 00235 int ContextChainLength(Scope* scope); 00236 00237 00238 // --------------------------------------------------------------------------- 00239 // Debugging. 00240 00241 #ifdef DEBUG 00242 void Print(int n = 0); // n = indentation; n < 0 => don't print recursively 00243 #endif 00244 00245 // --------------------------------------------------------------------------- 00246 // Implementation. 00247 protected: 00248 friend class ParserFactory; 00249 00250 // Scope tree. 00251 Scope* outer_scope_; // the immediately enclosing outer scope, or NULL 00252 ZoneList<Scope*> inner_scopes_; // the immediately enclosed inner scopes 00253 00254 // The scope type. 00255 Type type_; 00256 00257 // Debugging support. 00258 Handle<String> scope_name_; 00259 00260 // The variables declared in this scope: 00261 // all user-declared variables (incl. parameters) 00262 LocalsMap locals_; 00263 // compiler-allocated (user-invisible) temporaries 00264 ZoneList<Variable*> temps_; 00265 // parameter list in source order 00266 ZoneList<Variable*> params_; 00267 // variables that must be looked up dynamically 00268 ZoneList<Variable*> nonlocals_; 00269 // unresolved variables referred to from this scope 00270 ZoneList<VariableProxy*> unresolved_; 00271 // declarations 00272 ZoneList<Declaration*> decls_; 00273 // convenience variable 00274 VariableProxy* receiver_; 00275 // function variable, if any; function scopes only 00276 Variable* function_; 00277 // convenience variable; function scopes only 00278 VariableProxy* arguments_; 00279 // convenience variable; function scopes only 00280 VariableProxy* arguments_shadow_; 00281 00282 // Illegal redeclaration. 00283 Expression* illegal_redecl_; 00284 00285 // Scope-specific information. 00286 bool scope_inside_with_; // this scope is inside a 'with' of some outer scope 00287 bool scope_contains_with_; // this scope contains a 'with' statement 00288 bool scope_calls_eval_; // this scope contains an 'eval' call 00289 00290 // Computed via PropagateScopeInfo. 00291 bool outer_scope_calls_eval_; 00292 bool inner_scope_calls_eval_; 00293 bool force_eager_compilation_; 00294 00295 // Computed via AllocateVariables; function scopes only. 00296 int num_stack_slots_; 00297 int num_heap_slots_; 00298 00299 // Create a non-local variable with a given name. 00300 // These variables are looked up dynamically at runtime. 00301 Variable* NonLocal(Handle<String> name); 00302 00303 // Variable resolution. 00304 Variable* LookupRecursive(Handle<String> name, bool inner_lookup); 00305 void ResolveVariable(Scope* global_scope, VariableProxy* proxy); 00306 void ResolveVariablesRecursively(Scope* global_scope); 00307 00308 // Scope analysis. 00309 bool PropagateScopeInfo(bool outer_scope_calls_eval); 00310 bool HasTrivialContext() const; 00311 00312 // Predicates. 00313 bool MustAllocate(Variable* var); 00314 bool MustAllocateInContext(Variable* var); 00315 bool HasArgumentsParameter(); 00316 00317 // Variable allocation. 00318 void AllocateStackSlot(Variable* var); 00319 void AllocateHeapSlot(Variable* var); 00320 void AllocateParameterLocals(); 00321 void AllocateNonParameterLocal(Variable* var); 00322 void AllocateNonParameterLocals(); 00323 void AllocateVariablesRecursively(); 00324 }; 00325 00326 00327 class DummyScope : public Scope { 00328 public: 00329 DummyScope() { 00330 outer_scope_ = this; 00331 } 00332 00333 virtual Variable* Lookup(Handle<String> name) { return NULL; } 00334 virtual Variable* Declare(Handle<String> name, Variable::Mode mode) { 00335 return NULL; 00336 } 00337 virtual VariableProxy* NewUnresolved(Handle<String> name, bool inside_with) { 00338 return NULL; 00339 } 00340 virtual VariableProxy* NewTemporary(Handle<String> name) { return NULL; } 00341 }; 00342 00343 00344 } } // namespace v8::internal 00345 00346 #endif // V8_SCOPES_H_