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