Home | History | Annotate | Download | only in src
      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:
     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 
     98   virtual ~Scope() { }
     99 
    100   // The scope name is only used for printing/debugging.
    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.
    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.
    180   void RecordWithStatement()  { scope_contains_with_ = true; }
    181 
    182   // Inform the scope that the corresponding code contains an eval call.
    183   void RecordEvalCall()  { scope_calls_eval_ = true; }
    184 
    185 
    186   // ---------------------------------------------------------------------------
    187   // Predicates.
    188 
    189   // Specific scope types.
    190   bool is_eval_scope() const  { return type_ == EVAL_SCOPE; }
    191   bool is_function_scope() const  { return type_ == FUNCTION_SCOPE; }
    192   bool is_global_scope() const  { return type_ == GLOBAL_SCOPE; }
    193 
    194   // Information about which scopes calls eval.
    195   bool calls_eval() const  { return scope_calls_eval_; }
    196   bool outer_scope_calls_eval() const  { return outer_scope_calls_eval_; }
    197 
    198   // Is this scope inside a with statement.
    199   bool inside_with() const  { return scope_inside_with_; }
    200   // Does this scope contain a with statement.
    201   bool contains_with() const  { return scope_contains_with_; }
    202 
    203   // The scope immediately surrounding this scope, or NULL.
    204   Scope* outer_scope() const  { return outer_scope_; }
    205 
    206   // ---------------------------------------------------------------------------
    207   // Accessors.
    208 
    209   // A new variable proxy corresponding to the (function) 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.
    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.
    227   Variable* parameter(int index) const  {
    228     ASSERT(is_function_scope());
    229     return params_[index];
    230   }
    231 
    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.
    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.
    240   VariableProxy* arguments_shadow()  const  { return arguments_shadow_; }
    241 
    242   // Declarations list.
    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.
    265   int num_stack_slots() const  { return num_stack_slots_; }
    266   int num_heap_slots() const  { return num_heap_slots_; }
    267 
    268   // Make sure this scope and all outer scopes are eagerly compiled.
    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:
    384   DummyScope() : Scope(GLOBAL_SCOPE) {
    385     outer_scope_ = this;
    386   }
    387 
    388   virtual Variable* Lookup(Handle<String> name)  { return NULL; }
    389   virtual Variable* Declare(Handle<String> name, Variable::Mode mode) {
    390     return NULL;
    391   }
    392   virtual VariableProxy* NewUnresolved(Handle<String> name, bool inside_with) {
    393     return NULL;
    394   }
    395   virtual VariableProxy* NewTemporary(Handle<String> name)  { return NULL; }
    396 };
    397 
    398 
    399 } }  // namespace v8::internal
    400 
    401 #endif  // V8_SCOPES_H_
    402