• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2006-2008 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 //     * Redistributions of source code must retain the above copyright
7 //       notice, this list of conditions and the following disclaimer.
8 //     * Redistributions in binary form must reproduce the above
9 //       copyright notice, this list of conditions and the following
10 //       disclaimer in the documentation and/or other materials provided
11 //       with the distribution.
12 //     * Neither the name of Google Inc. nor the names of its
13 //       contributors may be used to endorse or promote products derived
14 //       from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 
28 #ifndef V8_SCOPES_H_
29 #define V8_SCOPES_H_
30 
31 #include "ast.h"
32 #include "hashmap.h"
33 
34 namespace v8 {
35 namespace internal {
36 
37 
38 // A hash map to support fast variable declaration and lookup.
39 class VariableMap: public HashMap {
40  public:
41   VariableMap();
42 
43   // Dummy constructor.  This constructor doesn't set up the map
44   // properly so don't use it unless you have a good reason.
45   explicit VariableMap(bool gotta_love_static_overloading);
46 
47   virtual ~VariableMap();
48 
49   Variable* Declare(Scope* scope,
50                     Handle<String> name,
51                     Variable::Mode mode,
52                     bool is_valid_lhs,
53                     Variable::Kind kind);
54 
55   Variable* Lookup(Handle<String> name);
56 };
57 
58 
59 // The dynamic scope part holds hash maps for the variables that will
60 // be looked up dynamically from within eval and with scopes. The objects
61 // are allocated on-demand from Scope::NonLocal to avoid wasting memory
62 // and setup time for scopes that don't need them.
63 class DynamicScopePart : public ZoneObject {
64  public:
GetMap(Variable::Mode mode)65   VariableMap* GetMap(Variable::Mode mode) {
66     int index = mode - Variable::DYNAMIC;
67     ASSERT(index >= 0 && index < 3);
68     return &maps_[index];
69   }
70 
71  private:
72   VariableMap maps_[3];
73 };
74 
75 
76 // Global invariants after AST construction: Each reference (i.e. identifier)
77 // to a JavaScript variable (including global properties) is represented by a
78 // VariableProxy node. Immediately after AST construction and before variable
79 // allocation, most VariableProxy nodes are "unresolved", i.e. not bound to a
80 // corresponding variable (though some are bound during parse time). Variable
81 // allocation binds each unresolved VariableProxy to one Variable and assigns
82 // a location. Note that many VariableProxy nodes may refer to the same Java-
83 // Script variable.
84 
85 class Scope: public ZoneObject {
86  public:
87   // ---------------------------------------------------------------------------
88   // Construction
89 
90   enum Type {
91     EVAL_SCOPE,     // the top-level scope for an 'eval' source
92     FUNCTION_SCOPE,  // the top-level scope for a function
93     GLOBAL_SCOPE    // the top-level scope for a program or a top-level eval
94   };
95 
96   Scope(Scope* outer_scope, Type type);
97 
~Scope()98   virtual ~Scope() { }
99 
100   // The scope name is only used for printing/debugging.
SetScopeName(Handle<String> scope_name)101   void SetScopeName(Handle<String> scope_name)  { scope_name_ = scope_name; }
102 
103   void Initialize(bool inside_with);
104 
105 
106   // ---------------------------------------------------------------------------
107   // Declarations
108 
109   // Lookup a variable in this scope. Returns the variable or NULL if not found.
110   virtual Variable* LocalLookup(Handle<String> name);
111 
112   // Lookup a variable in this scope or outer scopes.
113   // Returns the variable or NULL if not found.
114   virtual Variable* Lookup(Handle<String> name);
115 
116   // Declare the function variable for a function literal. This variable
117   // 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   Variable* DeclareFunctionVar(Handle<String> name);
120 
121   // Declare a local variable in this scope. If the variable has been
122   // declared before, the previously declared variable is returned.
123   virtual Variable* DeclareLocal(Handle<String> name, Variable::Mode mode);
124 
125   // Declare an implicit global variable in this scope which must be a
126   // global scope.  The variable was introduced (possibly from an inner
127   // scope) by a reference to an unresolved variable with no intervening
128   // with statements or eval calls.
129   Variable* DeclareGlobal(Handle<String> name);
130 
131   // Add a parameter to the parameter list. The parameter must have been
132   // declared via Declare. The same parameter may occur more than once in
133   // the parameter list; they must be added in source order, from left to
134   // right.
135   void AddParameter(Variable* var);
136 
137   // Create a new unresolved variable.
138   virtual VariableProxy* NewUnresolved(Handle<String> name, bool inside_with);
139 
140   // Remove a unresolved variable. During parsing, an unresolved variable
141   // may have been added optimistically, but then only the variable name
142   // was used (typically for labels). If the variable was not declared, the
143   // addition introduced a new unresolved variable which may end up being
144   // allocated globally as a "ghost" variable. RemoveUnresolved removes
145   // such a variable again if it was added; otherwise this is a no-op.
146   void RemoveUnresolved(VariableProxy* var);
147 
148   // Creates a new temporary variable in this scope and binds a proxy to it.
149   // The name is only used for printing and cannot be used to find the variable.
150   // In particular, the only way to get hold of the temporary is by keeping the
151   // VariableProxy* around.
152   virtual VariableProxy* NewTemporary(Handle<String> name);
153 
154   // Adds the specific declaration node to the list of declarations in
155   // this scope. The declarations are processed as part of entering
156   // the scope; see codegen.cc:ProcessDeclarations.
157   void AddDeclaration(Declaration* declaration);
158 
159   // ---------------------------------------------------------------------------
160   // Illegal redeclaration support.
161 
162   // Set an expression node that will be executed when the scope is
163   // entered. We only keep track of one illegal redeclaration node per
164   // scope - the first one - so if you try to set it multiple times
165   // the additional requests will be silently ignored.
166   void SetIllegalRedeclaration(Expression* expression);
167 
168   // Visit the illegal redeclaration expression. Do not call if the
169   // scope doesn't have an illegal redeclaration node.
170   void VisitIllegalRedeclaration(AstVisitor* visitor);
171 
172   // Check if the scope has (at least) one illegal redeclaration.
HasIllegalRedeclaration()173   bool HasIllegalRedeclaration() const { return illegal_redecl_ != NULL; }
174 
175 
176   // ---------------------------------------------------------------------------
177   // Scope-specific info.
178 
179   // Inform the scope that the corresponding code contains a with statement.
RecordWithStatement()180   void RecordWithStatement()  { scope_contains_with_ = true; }
181 
182   // Inform the scope that the corresponding code contains an eval call.
RecordEvalCall()183   void RecordEvalCall()  { scope_calls_eval_ = true; }
184 
185 
186   // ---------------------------------------------------------------------------
187   // Predicates.
188 
189   // Specific scope types.
is_eval_scope()190   bool is_eval_scope() const  { return type_ == EVAL_SCOPE; }
is_function_scope()191   bool is_function_scope() const  { return type_ == FUNCTION_SCOPE; }
is_global_scope()192   bool is_global_scope() const  { return type_ == GLOBAL_SCOPE; }
193 
194   // Information about which scopes calls eval.
calls_eval()195   bool calls_eval() const  { return scope_calls_eval_; }
outer_scope_calls_eval()196   bool outer_scope_calls_eval() const  { return outer_scope_calls_eval_; }
197 
198   // Is this scope inside a with statement.
inside_with()199   bool inside_with() const  { return scope_inside_with_; }
200   // Does this scope contain a with statement.
contains_with()201   bool contains_with() const  { return scope_contains_with_; }
202 
203   // The scope immediately surrounding this scope, or NULL.
outer_scope()204   Scope* outer_scope() const  { return outer_scope_; }
205 
206   // ---------------------------------------------------------------------------
207   // Accessors.
208 
209   // A new variable proxy corresponding to the (function) receiver.
receiver()210   VariableProxy* receiver() const {
211     VariableProxy* proxy =
212         new VariableProxy(Factory::this_symbol(), true, false);
213     proxy->BindTo(receiver_);
214     return proxy;
215   }
216 
217   // The variable holding the function literal for named function
218   // literals, or NULL.
219   // Only valid for function scopes.
function()220   Variable* function() const  {
221     ASSERT(is_function_scope());
222     return function_;
223   }
224 
225   // Parameters. The left-most parameter has index 0.
226   // Only valid for function scopes.
parameter(int index)227   Variable* parameter(int index) const  {
228     ASSERT(is_function_scope());
229     return params_[index];
230   }
231 
num_parameters()232   int num_parameters() const  { return params_.length(); }
233 
234   // The local variable 'arguments' if we need to allocate it; NULL otherwise.
235   // If arguments() exist, arguments_shadow() exists, too.
arguments()236   VariableProxy* arguments()  const  { return arguments_; }
237 
238   // The '.arguments' shadow variable if we need to allocate it; NULL otherwise.
239   // If arguments_shadow() exist, arguments() exists, too.
arguments_shadow()240   VariableProxy* arguments_shadow()  const  { return arguments_shadow_; }
241 
242   // Declarations list.
declarations()243   ZoneList<Declaration*>* declarations() { return &decls_; }
244 
245 
246 
247   // ---------------------------------------------------------------------------
248   // Variable allocation.
249 
250   // Collect all used locals in this scope.
251   template<class Allocator>
252   void CollectUsedVariables(List<Variable*, Allocator>* locals);
253 
254   // Resolve and fill in the allocation information for all variables
255   // in this scopes. Must be called *after* all scopes have been
256   // processed (parsed) to ensure that unresolved variables can be
257   // resolved properly.
258   //
259   // In the case of code compiled and run using 'eval', the context
260   // parameter is the context in which eval was called.  In all other
261   // cases the context parameter is an empty handle.
262   void AllocateVariables(Handle<Context> context);
263 
264   // Result of variable allocation.
num_stack_slots()265   int num_stack_slots() const  { return num_stack_slots_; }
num_heap_slots()266   int num_heap_slots() const  { return num_heap_slots_; }
267 
268   // Make sure this scope and all outer scopes are eagerly compiled.
ForceEagerCompilation()269   void ForceEagerCompilation()  { force_eager_compilation_ = true; }
270 
271   // Determine if we can use lazy compilation for this scope.
272   bool AllowsLazyCompilation() const;
273 
274   // True if the outer context of this scope is always the global context.
275   bool HasTrivialOuterContext() const;
276 
277   // The number of contexts between this and scope; zero if this == scope.
278   int ContextChainLength(Scope* scope);
279 
280 
281   // ---------------------------------------------------------------------------
282   // Debugging.
283 
284 #ifdef DEBUG
285   void Print(int n = 0);  // n = indentation; n < 0 => don't print recursively
286 #endif
287 
288   // ---------------------------------------------------------------------------
289   // Implementation.
290  protected:
291   friend class ParserFactory;
292 
293   explicit Scope(Type type);
294 
295   // Scope tree.
296   Scope* outer_scope_;  // the immediately enclosing outer scope, or NULL
297   ZoneList<Scope*> inner_scopes_;  // the immediately enclosed inner scopes
298 
299   // The scope type.
300   Type type_;
301 
302   // Debugging support.
303   Handle<String> scope_name_;
304 
305   // The variables declared in this scope:
306   //
307   // All user-declared variables (incl. parameters).  For global scopes
308   // variables may be implicitly 'declared' by being used (possibly in
309   // an inner scope) with no intervening with statements or eval calls.
310   VariableMap variables_;
311   // Compiler-allocated (user-invisible) temporaries.
312   ZoneList<Variable*> temps_;
313   // Parameter list in source order.
314   ZoneList<Variable*> params_;
315   // Variables that must be looked up dynamically.
316   DynamicScopePart* dynamics_;
317   // Unresolved variables referred to from this scope.
318   ZoneList<VariableProxy*> unresolved_;
319   // Declarations.
320   ZoneList<Declaration*> decls_;
321   // Convenience variable.
322   Variable* receiver_;
323   // Function variable, if any; function scopes only.
324   Variable* function_;
325   // Convenience variable; function scopes only.
326   VariableProxy* arguments_;
327   // Convenience variable; function scopes only.
328   VariableProxy* arguments_shadow_;
329 
330   // Illegal redeclaration.
331   Expression* illegal_redecl_;
332 
333   // Scope-specific information.
334   bool scope_inside_with_;  // this scope is inside a 'with' of some outer scope
335   bool scope_contains_with_;  // this scope contains a 'with' statement
336   bool scope_calls_eval_;  // this scope contains an 'eval' call
337 
338   // Computed via PropagateScopeInfo.
339   bool outer_scope_calls_eval_;
340   bool inner_scope_calls_eval_;
341   bool outer_scope_is_eval_scope_;
342   bool force_eager_compilation_;
343 
344   // Computed via AllocateVariables; function scopes only.
345   int num_stack_slots_;
346   int num_heap_slots_;
347 
348   // Create a non-local variable with a given name.
349   // These variables are looked up dynamically at runtime.
350   Variable* NonLocal(Handle<String> name, Variable::Mode mode);
351 
352   // Variable resolution.
353   Variable* LookupRecursive(Handle<String> name,
354                             bool inner_lookup,
355                             Variable** invalidated_local);
356   void ResolveVariable(Scope* global_scope,
357                        Handle<Context> context,
358                        VariableProxy* proxy);
359   void ResolveVariablesRecursively(Scope* global_scope,
360                                    Handle<Context> context);
361 
362   // Scope analysis.
363   bool PropagateScopeInfo(bool outer_scope_calls_eval,
364                           bool outer_scope_is_eval_scope);
365   bool HasTrivialContext() const;
366 
367   // Predicates.
368   bool MustAllocate(Variable* var);
369   bool MustAllocateInContext(Variable* var);
370   bool HasArgumentsParameter();
371 
372   // Variable allocation.
373   void AllocateStackSlot(Variable* var);
374   void AllocateHeapSlot(Variable* var);
375   void AllocateParameterLocals();
376   void AllocateNonParameterLocal(Variable* var);
377   void AllocateNonParameterLocals();
378   void AllocateVariablesRecursively();
379 };
380 
381 
382 class DummyScope : public Scope {
383  public:
DummyScope()384   DummyScope() : Scope(GLOBAL_SCOPE) {
385     outer_scope_ = this;
386   }
387 
Lookup(Handle<String> name)388   virtual Variable* Lookup(Handle<String> name)  { return NULL; }
Declare(Handle<String> name,Variable::Mode mode)389   virtual Variable* Declare(Handle<String> name, Variable::Mode mode) {
390     return NULL;
391   }
NewUnresolved(Handle<String> name,bool inside_with)392   virtual VariableProxy* NewUnresolved(Handle<String> name, bool inside_with) {
393     return NULL;
394   }
NewTemporary(Handle<String> name)395   virtual VariableProxy* NewTemporary(Handle<String> name)  { return NULL; }
396 };
397 
398 
399 } }  // namespace v8::internal
400 
401 #endif  // V8_SCOPES_H_
402