Home | History | Annotate | Download | only in src
      1 // Copyright 2010 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 class CompilationInfo;
     38 
     39 
     40 // A hash map to support fast variable declaration and lookup.
     41 class VariableMap: public HashMap {
     42  public:
     43   VariableMap();
     44 
     45   // Dummy constructor.  This constructor doesn't set up the map
     46   // properly so don't use it unless you have a good reason.
     47   explicit VariableMap(bool gotta_love_static_overloading);
     48 
     49   virtual ~VariableMap();
     50 
     51   Variable* Declare(Scope* scope,
     52                     Handle<String> name,
     53                     Variable::Mode mode,
     54                     bool is_valid_lhs,
     55                     Variable::Kind kind);
     56 
     57   Variable* Lookup(Handle<String> name);
     58 };
     59 
     60 
     61 // The dynamic scope part holds hash maps for the variables that will
     62 // be looked up dynamically from within eval and with scopes. The objects
     63 // are allocated on-demand from Scope::NonLocal to avoid wasting memory
     64 // and setup time for scopes that don't need them.
     65 class DynamicScopePart : public ZoneObject {
     66  public:
     67   VariableMap* GetMap(Variable::Mode mode) {
     68     int index = mode - Variable::DYNAMIC;
     69     ASSERT(index >= 0 && index < 3);
     70     return &maps_[index];
     71   }
     72 
     73  private:
     74   VariableMap maps_[3];
     75 };
     76 
     77 
     78 // Global invariants after AST construction: Each reference (i.e. identifier)
     79 // to a JavaScript variable (including global properties) is represented by a
     80 // VariableProxy node. Immediately after AST construction and before variable
     81 // allocation, most VariableProxy nodes are "unresolved", i.e. not bound to a
     82 // corresponding variable (though some are bound during parse time). Variable
     83 // allocation binds each unresolved VariableProxy to one Variable and assigns
     84 // a location. Note that many VariableProxy nodes may refer to the same Java-
     85 // Script variable.
     86 
     87 class Scope: public ZoneObject {
     88  public:
     89   // ---------------------------------------------------------------------------
     90   // Construction
     91 
     92   enum Type {
     93     EVAL_SCOPE,     // the top-level scope for an 'eval' source
     94     FUNCTION_SCOPE,  // the top-level scope for a function
     95     GLOBAL_SCOPE    // the top-level scope for a program or a top-level eval
     96   };
     97 
     98   enum LocalType {
     99     PARAMETER,
    100     VAR_OR_CONST
    101   };
    102 
    103   Scope(Scope* outer_scope, Type type);
    104 
    105   virtual ~Scope() { }
    106 
    107   // Compute top scope and allocate variables. For lazy compilation the top
    108   // scope only contains the single lazily compiled function, so this
    109   // doesn't re-allocate variables repeatedly.
    110   static bool Analyze(CompilationInfo* info);
    111 
    112   static Scope* DeserializeScopeChain(CompilationInfo* info,
    113                                       Scope* innermost_scope);
    114 
    115   // The scope name is only used for printing/debugging.
    116   void SetScopeName(Handle<String> scope_name) { scope_name_ = scope_name; }
    117 
    118   virtual void Initialize(bool inside_with);
    119 
    120   // Called just before leaving a scope.
    121   virtual void Leave() {
    122     // No cleanup or fixup necessary.
    123   }
    124 
    125   // ---------------------------------------------------------------------------
    126   // Declarations
    127 
    128   // Lookup a variable in this scope. Returns the variable or NULL if not found.
    129   virtual Variable* LocalLookup(Handle<String> name);
    130 
    131   // Lookup a variable in this scope or outer scopes.
    132   // Returns the variable or NULL if not found.
    133   virtual Variable* Lookup(Handle<String> name);
    134 
    135   // Declare the function variable for a function literal. This variable
    136   // is in an intermediate scope between this function scope and the the
    137   // outer scope. Only possible for function scopes; at most one variable.
    138   Variable* DeclareFunctionVar(Handle<String> name);
    139 
    140   // Declare a local variable in this scope. If the variable has been
    141   // declared before, the previously declared variable is returned.
    142   virtual Variable* DeclareLocal(Handle<String> name,
    143                                  Variable::Mode mode,
    144                                  LocalType type);
    145 
    146   // Declare an implicit global variable in this scope which must be a
    147   // global scope.  The variable was introduced (possibly from an inner
    148   // scope) by a reference to an unresolved variable with no intervening
    149   // with statements or eval calls.
    150   Variable* DeclareGlobal(Handle<String> name);
    151 
    152   // Add a parameter to the parameter list. The parameter must have been
    153   // declared via Declare. The same parameter may occur more than once in
    154   // the parameter list; they must be added in source order, from left to
    155   // right.
    156   void AddParameter(Variable* var);
    157 
    158   // Create a new unresolved variable.
    159   virtual VariableProxy* NewUnresolved(Handle<String> name,
    160                                        bool inside_with,
    161                                        int position = RelocInfo::kNoPosition);
    162 
    163   // Remove a unresolved variable. During parsing, an unresolved variable
    164   // may have been added optimistically, but then only the variable name
    165   // was used (typically for labels). If the variable was not declared, the
    166   // addition introduced a new unresolved variable which may end up being
    167   // allocated globally as a "ghost" variable. RemoveUnresolved removes
    168   // such a variable again if it was added; otherwise this is a no-op.
    169   void RemoveUnresolved(VariableProxy* var);
    170 
    171   // Creates a new temporary variable in this scope.  The name is only used
    172   // for printing and cannot be used to find the variable.  In particular,
    173   // the only way to get hold of the temporary is by keeping the Variable*
    174   // around.
    175   virtual Variable* NewTemporary(Handle<String> name);
    176 
    177   // Adds the specific declaration node to the list of declarations in
    178   // this scope. The declarations are processed as part of entering
    179   // the scope; see codegen.cc:ProcessDeclarations.
    180   void AddDeclaration(Declaration* declaration);
    181 
    182   // ---------------------------------------------------------------------------
    183   // Illegal redeclaration support.
    184 
    185   // Set an expression node that will be executed when the scope is
    186   // entered. We only keep track of one illegal redeclaration node per
    187   // scope - the first one - so if you try to set it multiple times
    188   // the additional requests will be silently ignored.
    189   void SetIllegalRedeclaration(Expression* expression);
    190 
    191   // Visit the illegal redeclaration expression. Do not call if the
    192   // scope doesn't have an illegal redeclaration node.
    193   void VisitIllegalRedeclaration(AstVisitor* visitor);
    194 
    195   // Check if the scope has (at least) one illegal redeclaration.
    196   bool HasIllegalRedeclaration() const { return illegal_redecl_ != NULL; }
    197 
    198 
    199   // ---------------------------------------------------------------------------
    200   // Scope-specific info.
    201 
    202   // Inform the scope that the corresponding code contains a with statement.
    203   void RecordWithStatement() { scope_contains_with_ = true; }
    204 
    205   // Inform the scope that the corresponding code contains an eval call.
    206   void RecordEvalCall() { scope_calls_eval_ = true; }
    207 
    208   // Enable strict mode for the scope (unless disabled by a global flag).
    209   void EnableStrictMode() {
    210     strict_mode_ = FLAG_strict_mode;
    211   }
    212 
    213   // ---------------------------------------------------------------------------
    214   // Predicates.
    215 
    216   // Specific scope types.
    217   bool is_eval_scope() const { return type_ == EVAL_SCOPE; }
    218   bool is_function_scope() const { return type_ == FUNCTION_SCOPE; }
    219   bool is_global_scope() const { return type_ == GLOBAL_SCOPE; }
    220   bool is_strict_mode() const { return strict_mode_; }
    221 
    222   // Information about which scopes calls eval.
    223   bool calls_eval() const { return scope_calls_eval_; }
    224   bool outer_scope_calls_eval() const { return outer_scope_calls_eval_; }
    225 
    226   // Is this scope inside a with statement.
    227   bool inside_with() const { return scope_inside_with_; }
    228   // Does this scope contain a with statement.
    229   bool contains_with() const { return scope_contains_with_; }
    230 
    231   // The scope immediately surrounding this scope, or NULL.
    232   Scope* outer_scope() const { return outer_scope_; }
    233 
    234   // ---------------------------------------------------------------------------
    235   // Accessors.
    236 
    237   // A new variable proxy corresponding to the (function) receiver.
    238   VariableProxy* receiver() const {
    239     VariableProxy* proxy =
    240         new VariableProxy(FACTORY->this_symbol(), true, false);
    241     proxy->BindTo(receiver_);
    242     return proxy;
    243   }
    244 
    245   // The variable holding the function literal for named function
    246   // literals, or NULL.
    247   // Only valid for function scopes.
    248   Variable* function() const {
    249     ASSERT(is_function_scope());
    250     return function_;
    251   }
    252 
    253   // Parameters. The left-most parameter has index 0.
    254   // Only valid for function scopes.
    255   Variable* parameter(int index) const {
    256     ASSERT(is_function_scope());
    257     return params_[index];
    258   }
    259 
    260   int num_parameters() const { return params_.length(); }
    261 
    262   // The local variable 'arguments' if we need to allocate it; NULL otherwise.
    263   // If arguments() exist, arguments_shadow() exists, too.
    264   Variable* arguments() const { return arguments_; }
    265 
    266   // The '.arguments' shadow variable if we need to allocate it; NULL otherwise.
    267   // If arguments_shadow() exist, arguments() exists, too.
    268   Variable* arguments_shadow() const { return arguments_shadow_; }
    269 
    270   // Declarations list.
    271   ZoneList<Declaration*>* declarations() { return &decls_; }
    272 
    273 
    274 
    275   // ---------------------------------------------------------------------------
    276   // Variable allocation.
    277 
    278   // Collect all used locals in this scope.
    279   template<class Allocator>
    280   void CollectUsedVariables(List<Variable*, Allocator>* locals);
    281 
    282   // Resolve and fill in the allocation information for all variables
    283   // in this scopes. Must be called *after* all scopes have been
    284   // processed (parsed) to ensure that unresolved variables can be
    285   // resolved properly.
    286   //
    287   // In the case of code compiled and run using 'eval', the context
    288   // parameter is the context in which eval was called.  In all other
    289   // cases the context parameter is an empty handle.
    290   void AllocateVariables(Handle<Context> context);
    291 
    292   // Current number of var or const locals.
    293   int num_var_or_const() { return num_var_or_const_; }
    294 
    295   // Result of variable allocation.
    296   int num_stack_slots() const { return num_stack_slots_; }
    297   int num_heap_slots() const { return num_heap_slots_; }
    298 
    299   // Make sure this scope and all outer scopes are eagerly compiled.
    300   void ForceEagerCompilation()  { force_eager_compilation_ = true; }
    301 
    302   // Determine if we can use lazy compilation for this scope.
    303   bool AllowsLazyCompilation() const;
    304 
    305   // True if the outer context of this scope is always the global context.
    306   virtual bool HasTrivialOuterContext() const;
    307 
    308   // The number of contexts between this and scope; zero if this == scope.
    309   int ContextChainLength(Scope* scope);
    310 
    311   // ---------------------------------------------------------------------------
    312   // Strict mode support.
    313   bool IsDeclared(Handle<String> name) {
    314     // During formal parameter list parsing the scope only contains
    315     // two variables inserted at initialization: "this" and "arguments".
    316     // "this" is an invalid parameter name and "arguments" is invalid parameter
    317     // name in strict mode. Therefore looking up with the map which includes
    318     // "this" and "arguments" in addition to all formal parameters is safe.
    319     return variables_.Lookup(name) != NULL;
    320   }
    321 
    322   // ---------------------------------------------------------------------------
    323   // Debugging.
    324 
    325 #ifdef DEBUG
    326   void Print(int n = 0);  // n = indentation; n < 0 => don't print recursively
    327 #endif
    328 
    329   // ---------------------------------------------------------------------------
    330   // Implementation.
    331  protected:
    332   friend class ParserFactory;
    333 
    334   explicit Scope(Type type);
    335 
    336   // Scope tree.
    337   Scope* outer_scope_;  // the immediately enclosing outer scope, or NULL
    338   ZoneList<Scope*> inner_scopes_;  // the immediately enclosed inner scopes
    339 
    340   // The scope type.
    341   Type type_;
    342 
    343   // Debugging support.
    344   Handle<String> scope_name_;
    345 
    346   // The variables declared in this scope:
    347   //
    348   // All user-declared variables (incl. parameters).  For global scopes
    349   // variables may be implicitly 'declared' by being used (possibly in
    350   // an inner scope) with no intervening with statements or eval calls.
    351   VariableMap variables_;
    352   // Compiler-allocated (user-invisible) temporaries.
    353   ZoneList<Variable*> temps_;
    354   // Parameter list in source order.
    355   ZoneList<Variable*> params_;
    356   // Variables that must be looked up dynamically.
    357   DynamicScopePart* dynamics_;
    358   // Unresolved variables referred to from this scope.
    359   ZoneList<VariableProxy*> unresolved_;
    360   // Declarations.
    361   ZoneList<Declaration*> decls_;
    362   // Convenience variable.
    363   Variable* receiver_;
    364   // Function variable, if any; function scopes only.
    365   Variable* function_;
    366   // Convenience variable; function scopes only.
    367   Variable* arguments_;
    368   // Convenience variable; function scopes only.
    369   Variable* arguments_shadow_;
    370 
    371   // Illegal redeclaration.
    372   Expression* illegal_redecl_;
    373 
    374   // Scope-specific information.
    375   bool scope_inside_with_;  // this scope is inside a 'with' of some outer scope
    376   bool scope_contains_with_;  // this scope contains a 'with' statement
    377   bool scope_calls_eval_;  // this scope contains an 'eval' call
    378   bool strict_mode_;  // this scope is a strict mode scope
    379 
    380   // Computed via PropagateScopeInfo.
    381   bool outer_scope_calls_eval_;
    382   bool inner_scope_calls_eval_;
    383   bool outer_scope_is_eval_scope_;
    384   bool force_eager_compilation_;
    385 
    386   // Computed as variables are declared.
    387   int num_var_or_const_;
    388 
    389   // Computed via AllocateVariables; function scopes only.
    390   int num_stack_slots_;
    391   int num_heap_slots_;
    392 
    393   // Serialized scopes support.
    394   Handle<SerializedScopeInfo> scope_info_;
    395   bool resolved() { return !scope_info_.is_null(); }
    396 
    397   // Create a non-local variable with a given name.
    398   // These variables are looked up dynamically at runtime.
    399   Variable* NonLocal(Handle<String> name, Variable::Mode mode);
    400 
    401   // Variable resolution.
    402   Variable* LookupRecursive(Handle<String> name,
    403                             bool inner_lookup,
    404                             Variable** invalidated_local);
    405   void ResolveVariable(Scope* global_scope,
    406                        Handle<Context> context,
    407                        VariableProxy* proxy);
    408   void ResolveVariablesRecursively(Scope* global_scope,
    409                                    Handle<Context> context);
    410 
    411   // Scope analysis.
    412   bool PropagateScopeInfo(bool outer_scope_calls_eval,
    413                           bool outer_scope_is_eval_scope);
    414   bool HasTrivialContext() const;
    415 
    416   // Predicates.
    417   bool MustAllocate(Variable* var);
    418   bool MustAllocateInContext(Variable* var);
    419   bool HasArgumentsParameter();
    420 
    421   // Variable allocation.
    422   void AllocateStackSlot(Variable* var);
    423   void AllocateHeapSlot(Variable* var);
    424   void AllocateParameterLocals();
    425   void AllocateNonParameterLocal(Variable* var);
    426   void AllocateNonParameterLocals();
    427   void AllocateVariablesRecursively();
    428 
    429  private:
    430   Scope(Scope* inner_scope, Handle<SerializedScopeInfo> scope_info);
    431 
    432   void AddInnerScope(Scope* inner_scope) {
    433     if (inner_scope != NULL) {
    434       inner_scopes_.Add(inner_scope);
    435       inner_scope->outer_scope_ = this;
    436     }
    437   }
    438 
    439   void SetDefaults(Type type,
    440                    Scope* outer_scope,
    441                    Handle<SerializedScopeInfo> scope_info);
    442 };
    443 
    444 
    445 // Scope used during pre-parsing.
    446 class DummyScope : public Scope {
    447  public:
    448   DummyScope()
    449       : Scope(GLOBAL_SCOPE),
    450         nesting_level_(1),  // Allows us to Leave the initial scope.
    451         inside_with_level_(kNotInsideWith) {
    452     outer_scope_ = this;
    453     scope_inside_with_ = false;
    454   }
    455 
    456   virtual void Initialize(bool inside_with) {
    457     nesting_level_++;
    458     if (inside_with && inside_with_level_ == kNotInsideWith) {
    459       inside_with_level_ = nesting_level_;
    460     }
    461     ASSERT(inside_with_level_ <= nesting_level_);
    462   }
    463 
    464   virtual void Leave() {
    465     nesting_level_--;
    466     ASSERT(nesting_level_ >= 0);
    467     if (nesting_level_ < inside_with_level_) {
    468       inside_with_level_ = kNotInsideWith;
    469     }
    470     ASSERT(inside_with_level_ <= nesting_level_);
    471   }
    472 
    473   virtual Variable* Lookup(Handle<String> name)  { return NULL; }
    474 
    475   virtual VariableProxy* NewUnresolved(Handle<String> name,
    476                                        bool inside_with,
    477                                        int position = RelocInfo::kNoPosition) {
    478     return NULL;
    479   }
    480 
    481   virtual Variable* NewTemporary(Handle<String> name)  { return NULL; }
    482 
    483   virtual bool HasTrivialOuterContext() const {
    484     return (nesting_level_ == 0 || inside_with_level_ <= 0);
    485   }
    486 
    487  private:
    488   static const int kNotInsideWith = -1;
    489   // Number of surrounding scopes of the current scope.
    490   int nesting_level_;
    491   // Nesting level of outermost scope that is contained in a with statement,
    492   // or kNotInsideWith if there are no with's around the current scope.
    493   int inside_with_level_;
    494 };
    495 
    496 
    497 } }  // namespace v8::internal
    498 
    499 #endif  // V8_SCOPES_H_
    500