1f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch// Copyright 2010 the V8 project authors. All rights reserved.
2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without
3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are
4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met:
5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions of source code must retain the above copyright
7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       notice, this list of conditions and the following disclaimer.
8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions in binary form must reproduce the above
9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       copyright notice, this list of conditions and the following
10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       disclaimer in the documentation and/or other materials provided
11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       with the distribution.
12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Neither the name of Google Inc. nor the names of its
13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       contributors may be used to endorse or promote products derived
14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       from this software without specific prior written permission.
15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "v8.h"
29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
30f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch#include "scopes.h"
31f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
32f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch#include "bootstrapper.h"
33f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch#include "compiler.h"
34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "prettyprinter.h"
35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "scopeinfo.h"
36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 {
38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal {
39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ----------------------------------------------------------------------------
41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A Zone allocator for use with LocalsMap.
42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4344f0eee88ff00398ff7f715fab053374d808c90dSteve Block// TODO(isolates): It is probably worth it to change the Allocator class to
4444f0eee88ff00398ff7f715fab053374d808c90dSteve Block//                 take a pointer to an isolate.
45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass ZoneAllocator: public Allocator {
46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  /* nothing to do */
48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual ~ZoneAllocator()  {}
49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  virtual void* New(size_t size)  { return ZONE->New(static_cast<int>(size)); }
51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  /* ignored - Zone is freed in one fell swoop */
53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual void Delete(void* p)  {}
54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic ZoneAllocator LocalsMapAllocator;
58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ----------------------------------------------------------------------------
61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Implementation of LocalsMap
62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Note: We are storing the handle locations as key values in the hash map.
64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       When inserting a new variable via Declare(), we rely on the fact that
65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       the handle location remains alive for the duration of that variable
66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       use. Because a Variable holding a handle with the same location exists
67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       this is ensured.
68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic bool Match(void* key1, void* key2) {
70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  String* name1 = *reinterpret_cast<String**>(key1);
71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  String* name2 = *reinterpret_cast<String**>(key2);
72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(name1->IsSymbol());
73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(name2->IsSymbol());
74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return name1 == name2;
75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Dummy constructor
79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockVariableMap::VariableMap(bool gotta_love_static_overloading) : HashMap() {}
80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockVariableMap::VariableMap() : HashMap(Match, &LocalsMapAllocator, 8) {}
82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockVariableMap::~VariableMap() {}
83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockVariable* VariableMap::Declare(Scope* scope,
86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                               Handle<String> name,
87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                               Variable::Mode mode,
88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                               bool is_valid_lhs,
89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                               Variable::Kind kind) {
90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  HashMap::Entry* p = HashMap::Lookup(name.location(), name->Hash(), true);
91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (p->value == NULL) {
92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // The variable has not been declared yet -> insert it.
93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(p->key == name.location());
94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    p->value = new Variable(scope, name, mode, is_valid_lhs, kind);
95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return reinterpret_cast<Variable*>(p->value);
97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockVariable* VariableMap::Lookup(Handle<String> name) {
101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  HashMap::Entry* p = HashMap::Lookup(name.location(), name->Hash(), false);
102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (p != NULL) {
103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(*reinterpret_cast<String**>(p->key) == *name);
104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(p->value != NULL);
105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return reinterpret_cast<Variable*>(p->value);
106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return NULL;
108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ----------------------------------------------------------------------------
112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Implementation of Scope
113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Dummy constructor
116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockScope::Scope(Type type)
117b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  : inner_scopes_(0),
118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    variables_(false),
119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    temps_(0),
120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    params_(0),
121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    unresolved_(0),
122b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    decls_(0) {
1238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  SetDefaults(type, NULL, Handle<SerializedScopeInfo>::null());
124b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  ASSERT(!resolved());
125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockScope::Scope(Scope* outer_scope, Type type)
129b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  : inner_scopes_(4),
130b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    variables_(),
131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    temps_(4),
132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    params_(4),
133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    unresolved_(16),
134b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    decls_(4) {
1358b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  SetDefaults(type, outer_scope, Handle<SerializedScopeInfo>::null());
136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // At some point we might want to provide outer scopes to
137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // eval scopes (by walking the stack and reading the scope info).
138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // In that case, the ASSERT below needs to be adjusted.
139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT((type == GLOBAL_SCOPE || type == EVAL_SCOPE) == (outer_scope == NULL));
140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!HasIllegalRedeclaration());
141b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  ASSERT(!resolved());
142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1458b112d2025046f85ef7f6be087c6129c872ebad2Ben MurdochScope::Scope(Scope* inner_scope, Handle<SerializedScopeInfo> scope_info)
146b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  : inner_scopes_(4),
147b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    variables_(),
148b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    temps_(4),
149b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    params_(4),
150b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    unresolved_(16),
151b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    decls_(4) {
1528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(!scope_info.is_null());
15344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  SetDefaults(FUNCTION_SCOPE, NULL, scope_info);
154b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  ASSERT(resolved());
155b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  if (scope_info->HasHeapAllocatedLocals()) {
156b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    num_heap_slots_ = scope_info_->NumberOfContextSlots();
157b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
158b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
15944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  AddInnerScope(inner_scope);
16044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
161b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // This scope's arguments shadow (if present) is context-allocated if an inner
162b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // scope accesses this one's parameters.  Allocate the arguments_shadow_
163b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // variable if necessary.
16444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Isolate* isolate = Isolate::Current();
165b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Variable::Mode mode;
166b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  int arguments_shadow_index =
16744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      scope_info_->ContextSlotIndex(
16844f0eee88ff00398ff7f715fab053374d808c90dSteve Block          isolate->heap()->arguments_shadow_symbol(), &mode);
169b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  if (arguments_shadow_index >= 0) {
170b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    ASSERT(mode == Variable::INTERNAL);
17144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    arguments_shadow_ = new Variable(
17244f0eee88ff00398ff7f715fab053374d808c90dSteve Block        this,
17344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        isolate->factory()->arguments_shadow_symbol(),
17444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        Variable::INTERNAL,
17544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        true,
17644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        Variable::ARGUMENTS);
177b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    arguments_shadow_->set_rewrite(
178b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch        new Slot(arguments_shadow_, Slot::CONTEXT, arguments_shadow_index));
179b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    arguments_shadow_->set_is_used(true);
180b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
181b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch}
182b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
183b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochvoid Scope::SetDefaults(Type type,
1858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                        Scope* outer_scope,
1868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                        Handle<SerializedScopeInfo> scope_info) {
1878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  outer_scope_ = outer_scope;
1888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  type_ = type;
1898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  scope_name_ = FACTORY->empty_symbol();
1908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  dynamics_ = NULL;
1918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  receiver_ = NULL;
1928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  function_ = NULL;
1938b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  arguments_ = NULL;
1948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  arguments_shadow_ = NULL;
1958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  illegal_redecl_ = NULL;
1968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  scope_inside_with_ = false;
1978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  scope_contains_with_ = false;
1988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  scope_calls_eval_ = false;
1998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // Inherit the strict mode from the parent scope.
2008b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  strict_mode_ = (outer_scope != NULL) && outer_scope->strict_mode_;
2018b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  outer_scope_calls_eval_ = false;
2028b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  inner_scope_calls_eval_ = false;
2038b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  outer_scope_is_eval_scope_ = false;
2048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  force_eager_compilation_ = false;
205053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  num_var_or_const_ = 0;
2068b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  num_stack_slots_ = 0;
2078b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  num_heap_slots_ = 0;
2088b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  scope_info_ = scope_info;
2098b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch}
2108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
2118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
21244f0eee88ff00398ff7f715fab053374d808c90dSteve BlockScope* Scope::DeserializeScopeChain(CompilationInfo* info,
21344f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                    Scope* global_scope) {
21444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(!info->closure().is_null());
21544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // If we have a serialized scope info, reuse it.
21644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Scope* innermost_scope = NULL;
21744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Scope* scope = NULL;
21844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
21944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  SerializedScopeInfo* scope_info = info->closure()->shared()->scope_info();
22044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (scope_info != SerializedScopeInfo::Empty()) {
22144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    JSFunction* current = *info->closure();
22244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    do {
22344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      current = current->context()->closure();
2248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      Handle<SerializedScopeInfo> scope_info(current->shared()->scope_info());
2258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      if (*scope_info != SerializedScopeInfo::Empty()) {
22644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        scope = new Scope(scope, scope_info);
22744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        if (innermost_scope == NULL) innermost_scope = scope;
22844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      } else {
22944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        ASSERT(current->context()->IsGlobalContext());
23044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      }
23144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    } while (!current->context()->IsGlobalContext());
23244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
23344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
23444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  global_scope->AddInnerScope(scope);
23544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (innermost_scope == NULL) innermost_scope = global_scope;
23644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
23744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return innermost_scope;
23844f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
23944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
240b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
241f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdochbool Scope::Analyze(CompilationInfo* info) {
242f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  ASSERT(info->function() != NULL);
243f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  Scope* top = info->function()->scope();
244b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
245f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  while (top->outer_scope() != NULL) top = top->outer_scope();
246f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  top->AllocateVariables(info->calling_context());
247f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
248f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch#ifdef DEBUG
24944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (info->isolate()->bootstrapper()->IsActive()
250f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch          ? FLAG_print_builtin_scopes
251f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch          : FLAG_print_scopes) {
252f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    info->function()->scope()->Print();
253f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  }
254f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch#endif
255f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
256f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  info->SetScope(info->function()->scope());
257f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  return true;  // Can not fail.
258f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch}
259f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
260f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Scope::Initialize(bool inside_with) {
262b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  ASSERT(!resolved());
263b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Add this scope as a new inner scope of the outer scope.
265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (outer_scope_ != NULL) {
266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    outer_scope_->inner_scopes_.Add(this);
267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    scope_inside_with_ = outer_scope_->scope_inside_with_ || inside_with;
268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    scope_inside_with_ = inside_with;
270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Declare convenience variables.
273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Declare and allocate receiver (even for the global scope, and even
274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // if naccesses_ == 0).
275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // NOTE: When loading parameters in the global scope, we must take
276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // care not to access them as properties of the global object, but
277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // instead load them directly from the stack. Currently, the only
278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // such parameter is 'this' which is passed on the stack when
279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // invoking scripts
280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Variable* var =
28144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      variables_.Declare(this, FACTORY->this_symbol(), Variable::VAR,
282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         false, Variable::THIS);
283b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  var->set_rewrite(new Slot(var, Slot::PARAMETER, -1));
284e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  receiver_ = var;
285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (is_function_scope()) {
287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Declare 'arguments' variable which exists in all functions.
288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Note that it might never be accessed, in which case it won't be
289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // allocated during variable allocation.
29044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    variables_.Declare(this, FACTORY->arguments_symbol(), Variable::VAR,
291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       true, Variable::ARGUMENTS);
292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockVariable* Scope::LocalLookup(Handle<String> name) {
297b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Variable* result = variables_.Lookup(name);
298b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  if (result != NULL || !resolved()) {
299b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    return result;
300b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
301b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // If the scope is resolved, we can find a variable in serialized scope info.
302b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
303b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // We should never lookup 'arguments' in this scope
304b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // as it is implicitly present in any scope.
30544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(*name != *FACTORY->arguments_symbol());
306b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
307b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Assert that there is no local slot with the given name.
308b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  ASSERT(scope_info_->StackSlotIndex(*name) < 0);
309b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
310b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Check context slot lookup.
311b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  Variable::Mode mode;
312b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  int index = scope_info_->ContextSlotIndex(*name, &mode);
313b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  if (index >= 0) {
314b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    Variable* var =
315b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch        variables_.Declare(this, name, mode, true, Variable::NORMAL);
316b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    var->set_rewrite(new Slot(var, Slot::CONTEXT, index));
317b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    return var;
318b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
319b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
320b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  index = scope_info_->ParameterIndex(*name);
321b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  if (index >= 0) {
322b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    // ".arguments" must be present in context slots.
323b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    ASSERT(arguments_shadow_ != NULL);
324b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    Variable* var =
325b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch        variables_.Declare(this, name, Variable::VAR, true, Variable::NORMAL);
326b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    Property* rewrite =
327b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch        new Property(new VariableProxy(arguments_shadow_),
328b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                     new Literal(Handle<Object>(Smi::FromInt(index))),
329b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                     RelocInfo::kNoPosition,
330b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                     Property::SYNTHETIC);
331b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    rewrite->set_is_arguments_access(true);
332b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    var->set_rewrite(rewrite);
333b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    return var;
334b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
335b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
336b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  index = scope_info_->FunctionContextSlotIndex(*name);
337b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  if (index >= 0) {
338b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    // Check that there is no local slot with the given name.
339b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    ASSERT(scope_info_->StackSlotIndex(*name) < 0);
340b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    Variable* var =
341b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch        variables_.Declare(this, name, Variable::VAR, true, Variable::NORMAL);
342b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    var->set_rewrite(new Slot(var, Slot::CONTEXT, index));
343b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    return var;
344b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
345b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
346b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  return NULL;
347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockVariable* Scope::Lookup(Handle<String> name) {
351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (Scope* scope = this;
352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       scope != NULL;
353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       scope = scope->outer_scope()) {
354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Variable* var = scope->LocalLookup(name);
355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (var != NULL) return var;
356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return NULL;
358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockVariable* Scope::DeclareFunctionVar(Handle<String> name) {
362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(is_function_scope() && function_ == NULL);
363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  function_ = new Variable(this, name, Variable::CONST, true, Variable::NORMAL);
364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return function_;
365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
368053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve BlockVariable* Scope::DeclareLocal(Handle<String> name,
369053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block                              Variable::Mode mode,
370053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block                              LocalType type) {
371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // DYNAMIC variables are introduces during variable allocation,
372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // INTERNAL variables are allocated explicitly, and TEMPORARY
373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // variables are allocated via NewTemporary().
374b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  ASSERT(!resolved());
375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(mode == Variable::VAR || mode == Variable::CONST);
376053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  if (type == VAR_OR_CONST) {
377053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block    num_var_or_const_++;
378053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  }
379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return variables_.Declare(this, name, mode, true, Variable::NORMAL);
380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockVariable* Scope::DeclareGlobal(Handle<String> name) {
384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(is_global_scope());
385e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  return variables_.Declare(this, name, Variable::DYNAMIC_GLOBAL, true,
386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            Variable::NORMAL);
387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Scope::AddParameter(Variable* var) {
391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(is_function_scope());
392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(LocalLookup(var->name()) == var);
393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  params_.Add(var);
394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3978b112d2025046f85ef7f6be087c6129c872ebad2Ben MurdochVariableProxy* Scope::NewUnresolved(Handle<String> name,
3988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                    bool inside_with,
3998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                    int position) {
400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Note that we must not share the unresolved variables with
401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the same name because they may be removed selectively via
402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // RemoveUnresolved().
403b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  ASSERT(!resolved());
4048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  VariableProxy* proxy = new VariableProxy(name, false, inside_with, position);
405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  unresolved_.Add(proxy);
406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return proxy;
407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Scope::RemoveUnresolved(VariableProxy* var) {
411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Most likely (always?) any variable we want to remove
412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // was just added before, so we search backwards.
413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = unresolved_.length(); i-- > 0;) {
414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (unresolved_[i] == var) {
415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      unresolved_.Remove(i);
416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return;
417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
422b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochVariable* Scope::NewTemporary(Handle<String> name) {
423b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  ASSERT(!resolved());
424b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Variable* var =
425b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      new Variable(this, name, Variable::TEMPORARY, true, Variable::NORMAL);
426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  temps_.Add(var);
427b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return var;
428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Scope::AddDeclaration(Declaration* declaration) {
432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  decls_.Add(declaration);
433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Scope::SetIllegalRedeclaration(Expression* expression) {
4371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Record only the first illegal redeclaration.
438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!HasIllegalRedeclaration()) {
439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    illegal_redecl_ = expression;
440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(HasIllegalRedeclaration());
442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Scope::VisitIllegalRedeclaration(AstVisitor* visitor) {
446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(HasIllegalRedeclaration());
447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  illegal_redecl_->Accept(visitor);
448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocktemplate<class Allocator>
452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Scope::CollectUsedVariables(List<Variable*, Allocator>* locals) {
453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Collect variables in this scope.
454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Note that the function_ variable - if present - is not
455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // collected here but handled separately in ScopeInfo
456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // which is the current user of this function).
457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < temps_.length(); i++) {
458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Variable* var = temps_[i];
4596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (var->is_used()) {
460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      locals->Add(var);
461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (VariableMap::Entry* p = variables_.Start();
464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       p != NULL;
465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       p = variables_.Next(p)) {
466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Variable* var = reinterpret_cast<Variable*>(p->value);
4676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (var->is_used()) {
468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      locals->Add(var);
469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Make sure the method gets instantiated by the template system.
475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocktemplate void Scope::CollectUsedVariables(
476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    List<Variable*, FreeStoreAllocationPolicy>* locals);
477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocktemplate void Scope::CollectUsedVariables(
478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    List<Variable*, PreallocatedStorage>* locals);
479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocktemplate void Scope::CollectUsedVariables(
480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    List<Variable*, ZoneListAllocationPolicy>* locals);
481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Scope::AllocateVariables(Handle<Context> context) {
484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(outer_scope_ == NULL);  // eval or global scopes only
485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // 1) Propagate scope information.
487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If we are in an eval scope, we may have other outer scopes about
488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // which we don't know anything at this point. Thus we must be conservative
489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // and assume they may invoke eval themselves. Eventually we could capture
490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // this information in the ScopeInfo and then use it here (by traversing
491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the call chain stack, at compile time).
492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool eval_scope = is_eval_scope();
493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  PropagateScopeInfo(eval_scope, eval_scope);
494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // 2) Resolve variables.
496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Scope* global_scope = NULL;
497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (is_global_scope()) global_scope = this;
498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ResolveVariablesRecursively(global_scope, context);
499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // 3) Allocate variables.
501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  AllocateVariablesRecursively();
502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool Scope::AllowsLazyCompilation() const {
506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return !force_eager_compilation_ && HasTrivialOuterContext();
507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool Scope::HasTrivialContext() const {
511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // A function scope has a trivial context if it always is the global
512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // context. We iteratively scan out the context chain to see if
513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // there is anything that makes this scope non-trivial; otherwise we
514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // return true.
515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (const Scope* scope = this; scope != NULL; scope = scope->outer_scope_) {
516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (scope->is_eval_scope()) return false;
517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (scope->scope_inside_with_) return false;
518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (scope->num_heap_slots_ > 0) return false;
519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return true;
521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool Scope::HasTrivialOuterContext() const {
525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Scope* outer = outer_scope_;
526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (outer == NULL) return true;
527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Note that the outer context may be trivial in general, but the current
528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // scope may be inside a 'with' statement in which case the outer context
529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // for this scope is not trivial.
530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return !scope_inside_with_ && outer->HasTrivialContext();
531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint Scope::ContextChainLength(Scope* scope) {
535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int n = 0;
536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (Scope* s = this; s != scope; s = s->outer_scope_) {
537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(s != NULL);  // scope must be in the scope chain
538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (s->num_heap_slots() > 0) n++;
539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return n;
541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const char* Header(Scope::Type type) {
546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  switch (type) {
547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case Scope::EVAL_SCOPE: return "eval";
548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case Scope::FUNCTION_SCOPE: return "function";
549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case Scope::GLOBAL_SCOPE: return "global";
550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  UNREACHABLE();
552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return NULL;
553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void Indent(int n, const char* str) {
557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  PrintF("%*s%s", n, "", str);
558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void PrintName(Handle<String> name) {
562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  SmartPointer<char> s = name->ToCString(DISALLOW_NULLS);
563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  PrintF("%s", *s);
564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void PrintVar(PrettyPrinter* printer, int indent, Variable* var) {
5686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (var->is_used() || var->rewrite() != NULL) {
569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Indent(indent, Variable::Mode2String(var->mode()));
570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    PrintF(" ");
571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    PrintName(var->name());
572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    PrintF(";  // ");
5736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (var->rewrite() != NULL) {
5746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      PrintF("%s, ", printer->Print(var->rewrite()));
5756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (var->is_accessed_from_inner_scope()) PrintF(", ");
5766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
5776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (var->is_accessed_from_inner_scope()) PrintF("inner scope access");
578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    PrintF("\n");
579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void PrintMap(PrettyPrinter* printer, int indent, VariableMap* map) {
584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (VariableMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) {
585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Variable* var = reinterpret_cast<Variable*>(p->value);
586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    PrintVar(printer, indent, var);
587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Scope::Print(int n) {
592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int n0 = (n > 0 ? n : 0);
593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int n1 = n0 + 2;  // indentation
594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Print header.
596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Indent(n0, Header(type_));
597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (scope_name_->length() > 0) {
598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    PrintF(" ");
599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    PrintName(scope_name_);
600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Print parameters, if any.
603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (is_function_scope()) {
604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    PrintF(" (");
605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    for (int i = 0; i < params_.length(); i++) {
606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (i > 0) PrintF(", ");
607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      PrintName(params_[i]->name());
608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    PrintF(")");
610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  PrintF(" {\n");
613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Function name, if any (named function literals, only).
615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (function_ != NULL) {
616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Indent(n1, "// (local) function name: ");
617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    PrintName(function_->name());
618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    PrintF("\n");
619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Scope info.
622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (HasTrivialOuterContext()) {
623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Indent(n1, "// scope has trivial outer context\n");
624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (scope_inside_with_) Indent(n1, "// scope inside 'with'\n");
626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (scope_contains_with_) Indent(n1, "// scope contains 'with'\n");
627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (scope_calls_eval_) Indent(n1, "// scope calls 'eval'\n");
628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (outer_scope_calls_eval_) Indent(n1, "// outer scope calls 'eval'\n");
629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (inner_scope_calls_eval_) Indent(n1, "// inner scope calls 'eval'\n");
630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (outer_scope_is_eval_scope_) {
631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Indent(n1, "// outer scope is 'eval' scope\n");
632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (num_stack_slots_ > 0) { Indent(n1, "// ");
634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  PrintF("%d stack slots\n", num_stack_slots_); }
635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (num_heap_slots_ > 0) { Indent(n1, "// ");
636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  PrintF("%d heap slots\n", num_heap_slots_); }
637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Print locals.
639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  PrettyPrinter printer;
640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Indent(n1, "// function var\n");
641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (function_ != NULL) {
642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    PrintVar(&printer, n1, function_);
643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Indent(n1, "// temporary vars\n");
646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < temps_.length(); i++) {
647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    PrintVar(&printer, n1, temps_[i]);
648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Indent(n1, "// local vars\n");
651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  PrintMap(&printer, n1, &variables_);
652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Indent(n1, "// dynamic vars\n");
654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (dynamics_ != NULL) {
655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    PrintMap(&printer, n1, dynamics_->GetMap(Variable::DYNAMIC));
656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    PrintMap(&printer, n1, dynamics_->GetMap(Variable::DYNAMIC_LOCAL));
657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    PrintMap(&printer, n1, dynamics_->GetMap(Variable::DYNAMIC_GLOBAL));
658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Print inner scopes (disable by providing negative n).
661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (n >= 0) {
662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    for (int i = 0; i < inner_scopes_.length(); i++) {
663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      PrintF("\n");
664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      inner_scopes_[i]->Print(n1);
665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Indent(n0, "}\n");
669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif  // DEBUG
671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockVariable* Scope::NonLocal(Handle<String> name, Variable::Mode mode) {
674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (dynamics_ == NULL) dynamics_ = new DynamicScopePart();
675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  VariableMap* map = dynamics_->GetMap(mode);
676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Variable* var = map->Lookup(name);
677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (var == NULL) {
678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Declare a new non-local.
679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    var = map->Declare(NULL, name, mode, true, Variable::NORMAL);
680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Allocate it by giving it a dynamic lookup.
681b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    var->set_rewrite(new Slot(var, Slot::LOOKUP, -1));
682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return var;
684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Lookup a variable starting with this scope. The result is either
688d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// the statically resolved variable belonging to an outer scope, or
689d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// NULL. It may be NULL because a) we couldn't find a variable, or b)
690d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// because the variable is just a guess (and may be shadowed by
691d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// another variable that is introduced dynamically via an 'eval' call
692d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// or a 'with' statement).
693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockVariable* Scope::LookupRecursive(Handle<String> name,
694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 bool inner_lookup,
695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                 Variable** invalidated_local) {
696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If we find a variable, but the current scope calls 'eval', the found
697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // variable may not be the correct one (the 'eval' may introduce a
698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // property with the same name). In that case, remember that the variable
699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // found is just a guess.
700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool guess = scope_calls_eval_;
701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Try to find the variable in this scope.
703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Variable* var = LocalLookup(name);
704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (var != NULL) {
706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // We found a variable. If this is not an inner lookup, we are done.
707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // (Even if there is an 'eval' in this scope which introduces the
708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // same variable again, the resulting variable remains the same.
709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Note that enclosing 'with' statements are handled at the call site.)
710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (!inner_lookup)
711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return var;
712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // We did not find a variable locally. Check against the function variable,
715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // if any. We can do this for all scopes, since the function variable is
716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // only present - if at all - for function scopes.
717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    //
718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // This lookup corresponds to a lookup in the "intermediate" scope sitting
719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // between this scope and the outer scope. (ECMA-262, 3rd., requires that
720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // the name of named function literal is kept in an intermediate scope
721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // in between this scope and the next outer scope.)
722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (function_ != NULL && function_->name().is_identical_to(name)) {
723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      var = function_;
724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else if (outer_scope_ != NULL) {
726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      var = outer_scope_->LookupRecursive(name, true, invalidated_local);
727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // We may have found a variable in an outer scope. However, if
728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // the current scope is inside a 'with', the actual variable may
729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // be a property introduced via the 'with' statement. Then, the
730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // variable we may have found is just a guess.
731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (scope_inside_with_)
732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        guess = true;
733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // If we did not find a variable, we are done.
736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (var == NULL)
737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return NULL;
738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(var != NULL);
741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If this is a lookup from an inner scope, mark the variable.
743b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  if (inner_lookup) {
744b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    var->MarkAsAccessedFromInnerScope();
745b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
747d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // If the variable we have found is just a guess, invalidate the
748d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // result. If the found variable is local, record that fact so we
749d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // can generate fast code to get it if it is not shadowed by eval.
750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (guess) {
751d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block    if (!var->is_global()) *invalidated_local = var;
752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    var = NULL;
753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return var;
756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Scope::ResolveVariable(Scope* global_scope,
760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            Handle<Context> context,
761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            VariableProxy* proxy) {
762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(global_scope == NULL || global_scope->is_global_scope());
763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If the proxy is already resolved there's nothing to do
765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // (functions and consts may be resolved by the parser).
766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (proxy->var() != NULL) return;
767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Otherwise, try to resolve the variable.
769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Variable* invalidated_local = NULL;
770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Variable* var = LookupRecursive(proxy->name(), false, &invalidated_local);
771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (proxy->inside_with()) {
773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // If we are inside a local 'with' statement, all bets are off
774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // and we cannot resolve the proxy to a local variable even if
775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // we found an outer matching variable.
776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Note that we must do a lookup anyway, because if we find one,
777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // we must mark that variable as potentially accessed from this
778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // inner scope (the property may not be in the 'with' object).
779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    var = NonLocal(proxy->name(), Variable::DYNAMIC);
780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // We are not inside a local 'with' statement.
783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (var == NULL) {
785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // We did not find the variable. We have a global variable
786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // if we are in the global scope (we know already that we
787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // are outside a 'with' statement) or if there is no way
788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // that the variable might be introduced dynamically (through
789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // a local or outer eval() call, or an outer 'with' statement),
790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // or we don't know about the outer scope (because we are
791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      // in an eval scope).
792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (is_global_scope() ||
793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          !(scope_inside_with_ || outer_scope_is_eval_scope_ ||
794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            scope_calls_eval_ || outer_scope_calls_eval_)) {
795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // We must have a global variable.
796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        ASSERT(global_scope != NULL);
797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        var = global_scope->DeclareGlobal(proxy->name());
798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else if (scope_inside_with_) {
800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // If we are inside a with statement we give up and look up
801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // the variable at runtime.
802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        var = NonLocal(proxy->name(), Variable::DYNAMIC);
803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else if (invalidated_local != NULL) {
805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // No with statements are involved and we found a local
806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // variable that might be shadowed by eval introduced
807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // variables.
808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        var = NonLocal(proxy->name(), Variable::DYNAMIC_LOCAL);
809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        var->set_local_if_not_shadowed(invalidated_local);
810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else if (outer_scope_is_eval_scope_) {
812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // No with statements and we did not find a local and the code
813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // is executed with a call to eval.  The context contains
814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // scope information that we can use to determine if the
815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // variable is global if it is not shadowed by eval-introduced
816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // variables.
817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (context->GlobalIfNotShadowedByEval(proxy->name())) {
818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          var = NonLocal(proxy->name(), Variable::DYNAMIC_GLOBAL);
819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          var = NonLocal(proxy->name(), Variable::DYNAMIC);
822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else {
825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // No with statements and we did not find a local and the code
826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // is not executed with a call to eval.  We know that this
827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // variable is global unless it is shadowed by eval-introduced
828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // variables.
829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        var = NonLocal(proxy->name(), Variable::DYNAMIC_GLOBAL);
830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  proxy->BindTo(var);
835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Scope::ResolveVariablesRecursively(Scope* global_scope,
839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                        Handle<Context> context) {
840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(global_scope == NULL || global_scope->is_global_scope());
841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
842a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Resolve unresolved variables for this scope.
843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < unresolved_.length(); i++) {
844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ResolveVariable(global_scope, context, unresolved_[i]);
845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Resolve unresolved variables for inner scopes.
848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < inner_scopes_.length(); i++) {
849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    inner_scopes_[i]->ResolveVariablesRecursively(global_scope, context);
850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool Scope::PropagateScopeInfo(bool outer_scope_calls_eval,
855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                               bool outer_scope_is_eval_scope) {
856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (outer_scope_calls_eval) {
857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    outer_scope_calls_eval_ = true;
858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (outer_scope_is_eval_scope) {
861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    outer_scope_is_eval_scope_ = true;
862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool calls_eval = scope_calls_eval_ || outer_scope_calls_eval_;
865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool is_eval = is_eval_scope() || outer_scope_is_eval_scope_;
866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < inner_scopes_.length(); i++) {
867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Scope* inner_scope = inner_scopes_[i];
868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (inner_scope->PropagateScopeInfo(calls_eval, is_eval)) {
869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      inner_scope_calls_eval_ = true;
870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (inner_scope->force_eager_compilation_) {
872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      force_eager_compilation_ = true;
873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return scope_calls_eval_ || inner_scope_calls_eval_;
877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool Scope::MustAllocate(Variable* var) {
881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Give var a read/write use if there is a chance it might be accessed
882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // via an eval() call.  This is only possible if the variable has a
883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // visible name.
884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if ((var->is_this() || var->name()->length() > 0) &&
885b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      (var->is_accessed_from_inner_scope() ||
886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       scope_calls_eval_ || inner_scope_calls_eval_ ||
887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       scope_contains_with_)) {
8886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    var->set_is_used(true);
889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Global variables do not need to be allocated.
8916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return !var->is_global() && var->is_used();
892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool Scope::MustAllocateInContext(Variable* var) {
896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If var is accessed from an inner scope, or if there is a
897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // possibility that it might be accessed from the current or an inner
898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // scope (through an eval() call), it must be allocated in the
899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // context.  Exception: temporary variables are not allocated in the
900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // context.
901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return
902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    var->mode() != Variable::TEMPORARY &&
903b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    (var->is_accessed_from_inner_scope() ||
904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     scope_calls_eval_ || inner_scope_calls_eval_ ||
905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block     scope_contains_with_ || var->is_global());
906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool Scope::HasArgumentsParameter() {
910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < params_.length(); i++) {
91144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (params_[i]->name().is_identical_to(FACTORY->arguments_symbol()))
912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return true;
913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return false;
915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Scope::AllocateStackSlot(Variable* var) {
919b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  var->set_rewrite(new Slot(var, Slot::LOCAL, num_stack_slots_++));
920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Scope::AllocateHeapSlot(Variable* var) {
924b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  var->set_rewrite(new Slot(var, Slot::CONTEXT, num_heap_slots_++));
925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Scope::AllocateParameterLocals() {
929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(is_function_scope());
93044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Variable* arguments = LocalLookup(FACTORY->arguments_symbol());
931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(arguments != NULL);  // functions have 'arguments' declared implicitly
93244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
93344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Parameters are rewritten to arguments[i] if 'arguments' is used in
93444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // a non-strict mode function. Strict mode code doesn't alias arguments.
93544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  bool rewrite_parameters = false;
93644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (MustAllocate(arguments) && !HasArgumentsParameter()) {
938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // 'arguments' is used. Unless there is also a parameter called
939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // 'arguments', we must be conservative and access all parameters via
940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // the arguments object: The i'th parameter is rewritten into
941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // '.arguments[i]' (*). If we have a parameter named 'arguments', a
942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // (new) value is always assigned to it via the function
943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // invocation. Then 'arguments' denotes that specific parameter value
944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // and cannot be used to access the parameters, which is why we don't
945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // need to rewrite in that case.
946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    //
947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // (*) Instead of having a parameter called 'arguments', we may have an
948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // assignment to 'arguments' in the function body, at some arbitrary
949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // point in time (possibly through an 'eval()' call!). After that
950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // assignment any re-write of parameters would be invalid (was bug
951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // 881452). Thus, we introduce a shadow '.arguments'
952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // variable which also points to the arguments object. For rewrites we
953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // use '.arguments' which remains valid even if we assign to
954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // 'arguments'. To summarize: If we need to rewrite, we allocate an
955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // 'arguments' object dynamically upon function invocation. The compiler
956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // introduces 2 local variables 'arguments' and '.arguments', both of
957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // which originally point to the arguments object that was
958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // allocated. All parameters are rewritten into property accesses via
959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // the '.arguments' variable. Thus, any changes to properties of
960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // 'arguments' are reflected in the variables and vice versa. If the
961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // 'arguments' variable is changed, '.arguments' still points to the
962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // correct arguments object and the rewrites still work.
963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // We are using 'arguments'. Tell the code generator that is needs to
965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // allocate the arguments object by setting 'arguments_'.
9660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    arguments_ = arguments;
967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
96844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // In strict mode 'arguments' does not alias formal parameters.
96944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Therefore in strict mode we allocate parameters as if 'arguments'
97044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // were not used.
97144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    rewrite_parameters = !is_strict_mode();
97244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
97344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
97444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (rewrite_parameters) {
975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // We also need the '.arguments' shadow variable. Declare it and create
976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // and bind the corresponding proxy. It's ok to declare it only now
977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // because it's a local variable that is allocated after the parameters
978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // have been allocated.
979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    //
980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Note: This is "almost" at temporary variable but we cannot use
981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // NewTemporary() because the mode needs to be INTERNAL since this
982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // variable may be allocated in the heap-allocated context (temporaries
983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // are never allocated in the context).
9840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    arguments_shadow_ = new Variable(this,
98544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                     FACTORY->arguments_shadow_symbol(),
9860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                     Variable::INTERNAL,
9870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                     true,
9880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                     Variable::ARGUMENTS);
9890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    arguments_shadow_->set_is_used(true);
9900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    temps_.Add(arguments_shadow_);
991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Allocate the parameters by rewriting them into '.arguments[i]' accesses.
993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    for (int i = 0; i < params_.length(); i++) {
994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Variable* var = params_[i];
995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ASSERT(var->scope() == this);
996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (MustAllocate(var)) {
997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (MustAllocateInContext(var)) {
998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          // It is ok to set this only now, because arguments is a local
999a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          // variable that is allocated after the parameters have been
1000a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          // allocated.
1001b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch          arguments_shadow_->MarkAsAccessedFromInnerScope();
1002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
1003b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        Property* rewrite =
10040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen            new Property(new VariableProxy(arguments_shadow_),
10050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         new Literal(Handle<Object>(Smi::FromInt(i))),
10060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         RelocInfo::kNoPosition,
10070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                         Property::SYNTHETIC);
1008b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        rewrite->set_is_arguments_access(true);
1009b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch        var->set_rewrite(rewrite);
1010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
1011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
1014a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // The arguments object is not used, so we can access parameters directly.
1015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // The same parameter may occur multiple times in the parameters_ list.
1016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // If it does, and if it is not copied into the context object, it must
1017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // receive the highest parameter index for that parameter; thus iteration
1018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // order is relevant!
1019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    for (int i = 0; i < params_.length(); i++) {
1020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Variable* var = params_[i];
1021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ASSERT(var->scope() == this);
1022a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (MustAllocate(var)) {
1023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (MustAllocateInContext(var)) {
1024b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch          ASSERT(var->rewrite() == NULL ||
10250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                 (var->AsSlot() != NULL &&
10260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                  var->AsSlot()->type() == Slot::CONTEXT));
1027b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch          if (var->rewrite() == NULL) {
1028a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            // Only set the heap allocation if the parameter has not
1029a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            // been allocated yet.
1030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            AllocateHeapSlot(var);
1031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          }
1032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        } else {
1033b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch          ASSERT(var->rewrite() == NULL ||
10340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                 (var->AsSlot() != NULL &&
10350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                  var->AsSlot()->type() == Slot::PARAMETER));
1036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          // Set the parameter index always, even if the parameter
1037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          // was seen before! (We need to access the actual parameter
1038a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          // supplied for the last occurrence of a multiply declared
1039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          // parameter.)
1040b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch          var->set_rewrite(new Slot(var, Slot::PARAMETER, i));
1041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        }
1042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
1043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1044a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1045a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Scope::AllocateNonParameterLocal(Variable* var) {
1049a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(var->scope() == this);
1050b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  ASSERT(var->rewrite() == NULL ||
105144f0eee88ff00398ff7f715fab053374d808c90dSteve Block         (!var->IsVariable(FACTORY->result_symbol())) ||
10520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen         (var->AsSlot() == NULL || var->AsSlot()->type() != Slot::LOCAL));
1053b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  if (var->rewrite() == NULL && MustAllocate(var)) {
1054a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (MustAllocateInContext(var)) {
1055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      AllocateHeapSlot(var);
1056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
1057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      AllocateStackSlot(var);
1058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1060a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1061a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Scope::AllocateNonParameterLocals() {
1064a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // All variables that have no rewrite yet are non-parameter locals.
1065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < temps_.length(); i++) {
1066a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    AllocateNonParameterLocal(temps_[i]);
1067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (VariableMap::Entry* p = variables_.Start();
1070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       p != NULL;
1071a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block       p = variables_.Next(p)) {
1072a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Variable* var = reinterpret_cast<Variable*>(p->value);
1073a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    AllocateNonParameterLocal(var);
1074a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1076a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // For now, function_ must be allocated at the very end.  If it gets
1077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // allocated in the context, it must be the last slot in the context,
1078a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // because of the current ScopeInfo implementation (see
1079a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ScopeInfo::ScopeInfo(FunctionScope* scope) constructor).
1080a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (function_ != NULL) {
1081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    AllocateNonParameterLocal(function_);
1082a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1083a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1084a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1085a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1086a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Scope::AllocateVariablesRecursively() {
1087a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Allocate variables for inner scopes.
1088a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < inner_scopes_.length(); i++) {
1089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    inner_scopes_[i]->AllocateVariablesRecursively();
1090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1092b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // If scope is already resolved, we still need to allocate
1093b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // variables in inner scopes which might not had been resolved yet.
1094b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  if (resolved()) return;
1095b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // The number of slots required for variables.
1096b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  num_stack_slots_ = 0;
1097b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  num_heap_slots_ = Context::MIN_CONTEXT_SLOTS;
1098b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
1099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Allocate variables for this scope.
1100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Parameters must be allocated first, if any.
1101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (is_function_scope()) AllocateParameterLocals();
1102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  AllocateNonParameterLocals();
1103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Allocate context if necessary.
1105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool must_have_local_context = false;
1106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (scope_calls_eval_ || scope_contains_with_) {
1107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // The context for the eval() call or 'with' statement in this scope.
1108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Unless we are in the global or an eval scope, we need a local
1109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // context even if we didn't statically allocate any locals in it,
1110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // and the compiler will access the context variable. If we are
1111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // not in an inner scope, the scope is provided from the outside.
1112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    must_have_local_context = is_function_scope();
1113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If we didn't allocate any locals in the local context, then we only
1116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // need the minimal number of slots if we must have a local context.
1117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS &&
1118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      !must_have_local_context) {
1119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    num_heap_slots_ = 0;
1120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Allocation done.
1123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(num_heap_slots_ == 0 || num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS);
1124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} }  // namespace v8::internal
1127