📄 scopes.cc.svn-base
字号:
// Copyright 2006-2008 the V8 project authors. All rights reserved.// Redistribution and use in source and binary forms, with or without// modification, are permitted provided that the following conditions are// met://// * Redistributions of source code must retain the above copyright// notice, this list of conditions and the following disclaimer.// * Redistributions in binary form must reproduce the above// copyright notice, this list of conditions and the following// disclaimer in the documentation and/or other materials provided// with the distribution.// * Neither the name of Google Inc. nor the names of its// contributors may be used to endorse or promote products derived// from this software without specific prior written permission.//// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.#include "v8.h"#include "prettyprinter.h"#include "scopeinfo.h"#include "scopes.h"namespace v8 { namespace internal {// ----------------------------------------------------------------------------// A Zone allocator for use with LocalsMap.class ZoneAllocator: public Allocator { public: /* nothing to do */ virtual ~ZoneAllocator() {} virtual void* New(size_t size) { return Zone::New(size); } /* ignored - Zone is freed in one fell swoop */ virtual void Delete(void* p) {}};static ZoneAllocator LocalsMapAllocator;// ----------------------------------------------------------------------------// Implementation of LocalsMap//// Note: We are storing the handle locations as key values in the hash map.// When inserting a new variable via Declare(), we rely on the fact that// the handle location remains alive for the duration of that variable// use. Because a Variable holding a handle with the same location exists// this is ensured.static bool Match(void* key1, void* key2) { String* name1 = *reinterpret_cast<String**>(key1); String* name2 = *reinterpret_cast<String**>(key2); ASSERT(name1->IsSymbol()); ASSERT(name2->IsSymbol()); return name1 == name2;}// Dummy constructorLocalsMap::LocalsMap(bool gotta_love_static_overloading) : HashMap() {}LocalsMap::LocalsMap() : HashMap(Match, &LocalsMapAllocator, 8) {}LocalsMap::~LocalsMap() {}Variable* LocalsMap::Declare(Scope* scope, Handle<String> name, Variable::Mode mode, bool is_valid_LHS, bool is_this) { HashMap::Entry* p = HashMap::Lookup(name.location(), name->Hash(), true); if (p->value == NULL) { // The variable has not been declared yet -> insert it. ASSERT(p->key == name.location()); p->value = new Variable(scope, name, mode, is_valid_LHS, is_this); } return reinterpret_cast<Variable*>(p->value);}Variable* LocalsMap::Lookup(Handle<String> name) { HashMap::Entry* p = HashMap::Lookup(name.location(), name->Hash(), false); if (p != NULL) { ASSERT(*reinterpret_cast<String**>(p->key) == *name); ASSERT(p->value != NULL); return reinterpret_cast<Variable*>(p->value); } return NULL;}// ----------------------------------------------------------------------------// Implementation of Scope// Dummy constructorScope::Scope() : inner_scopes_(0), locals_(false), temps_(0), params_(0), nonlocals_(0), unresolved_(0), decls_(0) {}Scope::Scope(Scope* outer_scope, Type type) : outer_scope_(outer_scope), inner_scopes_(4), type_(type), scope_name_(Factory::empty_symbol()), locals_(), temps_(4), params_(4), nonlocals_(4), unresolved_(16), decls_(4), receiver_(NULL), function_(NULL), arguments_(NULL), arguments_shadow_(NULL), illegal_redecl_(NULL), scope_inside_with_(false), scope_contains_with_(false), scope_calls_eval_(false), outer_scope_calls_eval_(false), inner_scope_calls_eval_(false), force_eager_compilation_(false), num_stack_slots_(0), num_heap_slots_(0) { // At some point we might want to provide outer scopes to // eval scopes (by walking the stack and reading the scope info). // In that case, the ASSERT below needs to be adjusted. ASSERT((type == GLOBAL_SCOPE || type == EVAL_SCOPE) == (outer_scope == NULL)); ASSERT(!HasIllegalRedeclaration());}void Scope::Initialize(bool inside_with) { // Add this scope as a new inner scope of the outer scope. if (outer_scope_ != NULL) { outer_scope_->inner_scopes_.Add(this); scope_inside_with_ = outer_scope_->scope_inside_with_ || inside_with; } else { scope_inside_with_ = inside_with; } // Declare convenience variables. // Declare and allocate receiver (even for the global scope, and even // if naccesses_ == 0). // NOTE: When loading parameters in the global scope, we must take // care not to access them as properties of the global object, but // instead load them directly from the stack. Currently, the only // such parameter is 'this' which is passed on the stack when // invoking scripts { Variable* var = locals_.Declare(this, Factory::this_symbol(), Variable::VAR, false, true); var->rewrite_ = new Slot(var, Slot::PARAMETER, -1); receiver_ = new VariableProxy(Factory::this_symbol(), true, false); receiver_->BindTo(var); } if (is_function_scope()) { // Declare 'arguments' variable which exists in all functions. // Note that it may never be accessed, in which case it won't // be allocated during variable allocation. Declare(Factory::arguments_symbol(), Variable::VAR); }}Variable* Scope::Lookup(Handle<String> name) { return locals_.Lookup(name);}Variable* Scope::DeclareFunctionVar(Handle<String> name) { ASSERT(is_function_scope() && function_ == NULL); function_ = new Variable(this, name, Variable::CONST, true, false); return function_;}Variable* Scope::Declare(Handle<String> name, Variable::Mode mode) { // DYNAMIC variables are introduces during variable allocation, // INTERNAL variables are allocated explicitly, and TEMPORARY // variables are allocated via NewTemporary(). ASSERT(mode == Variable::VAR || mode == Variable::CONST); return locals_.Declare(this, name, mode, true, false);}void Scope::AddParameter(Variable* var) { ASSERT(is_function_scope()); ASSERT(Lookup(var->name()) == var); params_.Add(var);}VariableProxy* Scope::NewUnresolved(Handle<String> name, bool inside_with) { // Note that we must not share the unresolved variables with // the same name because they may be removed selectively via // RemoveUnresolved(). VariableProxy* proxy = new VariableProxy(name, false, inside_with); unresolved_.Add(proxy); return proxy;}void Scope::RemoveUnresolved(VariableProxy* var) { // Most likely (always?) any variable we want to remove // was just added before, so we search backwards. for (int i = unresolved_.length(); i-- > 0;) { if (unresolved_[i] == var) { unresolved_.Remove(i); return; } }}VariableProxy* Scope::NewTemporary(Handle<String> name) { Variable* var = new Variable(this, name, Variable::TEMPORARY, true, false); VariableProxy* tmp = new VariableProxy(name, false, false); tmp->BindTo(var); temps_.Add(var); return tmp;}void Scope::AddDeclaration(Declaration* declaration) { decls_.Add(declaration);}void Scope::SetIllegalRedeclaration(Expression* expression) { // Only set the illegal redeclaration expression the // first time the function is called. if (!HasIllegalRedeclaration()) { illegal_redecl_ = expression; } ASSERT(HasIllegalRedeclaration());}void Scope::VisitIllegalRedeclaration(Visitor* visitor) { ASSERT(HasIllegalRedeclaration()); illegal_redecl_->Accept(visitor);}template<class Allocator>void Scope::CollectUsedVariables(List<Variable*, Allocator>* locals) { // Collect variables in this scope. // Note that the function_ variable - if present - is not // collected here but handled separately in ScopeInfo // which is the current user of this function). for (int i = 0; i < temps_.length(); i++) { Variable* var = temps_[i]; if (var->var_uses()->is_used()) { locals->Add(var); } } for (LocalsMap::Entry* p = locals_.Start(); p != NULL; p = locals_.Next(p)) { Variable* var = reinterpret_cast<Variable*>(p->value); if (var->var_uses()->is_used()) { locals->Add(var); } }}// Make sure the method gets instantiated by the template system.template void Scope::CollectUsedVariables( List<Variable*, FreeStoreAllocationPolicy>* locals);template void Scope::CollectUsedVariables( List<Variable*, PreallocatedStorage>* locals);void Scope::AllocateVariables() { ASSERT(outer_scope_ == NULL); // eval or global scopes only // 1) Propagate scope information. // If we are in an eval scope, we may have other outer scopes about
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -