📄 scopeinfo.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 <stdlib.h>#include "v8.h"#include "scopeinfo.h"#include "scopes.h"namespace v8 { namespace internal {static int CompareLocal(Variable* const* v, Variable* const* w) { Slot* s = (*v)->slot(); Slot* t = (*w)->slot(); // We may have rewritten parameters (that are in the arguments object) // and which may have a NULL slot... - find a better solution... int x = (s != NULL ? s->index() : 0); int y = (t != NULL ? t->index() : 0); // Consider sorting them according to type as well? return x - y;}template<class Allocator>ScopeInfo<Allocator>::ScopeInfo(Scope* scope) : function_name_(Factory::empty_symbol()), supports_eval_(scope->SupportsEval()), parameters_(scope->num_parameters()), stack_slots_(scope->num_stack_slots()), context_slots_(scope->num_heap_slots()), context_modes_(scope->num_heap_slots()) { // Add parameters. for (int i = 0; i < scope->num_parameters(); i++) { ASSERT(parameters_.length() == i); parameters_.Add(scope->parameter(i)->name()); } // Add stack locals and collect heap locals. // We are assuming that the locals' slots are allocated in // increasing order, so we can simply add them to the // ScopeInfo lists. However, due to usage analysis, this is // not true for context-allocated locals: Some of them // may be parameters which are allocated before the // non-parameter locals. When the non-parameter locals are // sorted according to usage, the allocated slot indices may // not be in increasing order with the variable list anymore. // Thus, we first collect the context-allocated locals, and then // sort them by context slot index before adding them to the // ScopeInfo list. List<Variable*, Allocator> locals(32); // 32 is a wild guess ASSERT(locals.is_empty()); scope->CollectUsedVariables(&locals); locals.Sort(&CompareLocal); List<Variable*, Allocator> heap_locals(locals.length()); for (int i = 0; i < locals.length(); i++) { Variable* var = locals[i]; if (var->var_uses()->is_used()) { Slot* slot = var->slot(); if (slot != NULL) { switch (slot->type()) { case Slot::PARAMETER: // explicitly added to parameters_ above - ignore break; case Slot::LOCAL: ASSERT(stack_slots_.length() == slot->index()); stack_slots_.Add(var->name()); break; case Slot::CONTEXT: heap_locals.Add(var); break; case Slot::LOOKUP: case Slot::GLOBAL: // these are currently not used UNREACHABLE(); break; } } } } // Add heap locals. if (scope->num_heap_slots() > 0) { // Add user-defined slots. for (int i = 0; i < heap_locals.length(); i++) { ASSERT(heap_locals[i]->slot()->index() - Context::MIN_CONTEXT_SLOTS == context_slots_.length()); ASSERT(heap_locals[i]->slot()->index() - Context::MIN_CONTEXT_SLOTS == context_modes_.length()); context_slots_.Add(heap_locals[i]->name()); context_modes_.Add(heap_locals[i]->mode()); } } else { ASSERT(heap_locals.length() == 0); } // Add the function context slot, if present. // For now, this must happen at the very end because of the // ordering of the scope info slots and the respective slot indices. if (scope->is_function_scope()) { Variable* var = scope->function(); if (var != NULL && var->var_uses()->is_used() && var->slot()->type() == Slot::CONTEXT) { function_name_ = var->name(); // Note that we must not find the function name in the context slot // list - instead it must be handled separately in the // Contexts::Lookup() function. Thus record an empty symbol here so we // get the correct number of context slots. ASSERT(var->slot()->index() - Context::MIN_CONTEXT_SLOTS == context_slots_.length()); ASSERT(var->slot()->index() - Context::MIN_CONTEXT_SLOTS == context_modes_.length()); context_slots_.Add(Factory::empty_symbol()); context_modes_.Add(Variable::INTERNAL); } }}// Encoding format in the Code object://// - function name// - supports eval info//// - number of variables in the context object (smi) (= function context// slot index + 1)// - list of pairs (name, Var mode) of context-allocated variables (starting// with context slot 0)// - NULL (sentinel)//// - number of parameters (smi)// - list of parameter names (starting with parameter 0 first)// - NULL (sentinel)//// - number of variables on the stack (smi)// - list of names of stack-allocated variables (starting with stack slot 0)// - NULL (sentinel)// The ScopeInfo representation could be simplified and the ScopeInfo// re-implemented (with almost the same interface). Here is a// suggestion for the new format://// - have a single list with all variable names (parameters, stack locals,// context locals), followed by a list of non-Object* values containing// the variables information (what kind, index, attributes)// - searching the linear list of names is fast and yields an index into the// list if the variable name is found// - that list index is then used to find the variable information in the// subsequent list// - the list entries don't have to be in any particular order, so all the// current sorting business can go away// - the ScopeInfo lookup routines can be reduced to perhaps a single lookup// which returns all information at once// - when gathering the information from a Scope, we only need to iterate// through the local variables (parameters and context info is already// present)static inline Object** ReadInt(Object** p, int* x) { *x = (reinterpret_cast<Smi*>(*p++))->value(); return p;}static inline Object** ReadBool(Object** p, bool* x) { *x = (reinterpret_cast<Smi*>(*p++))->value() != 0; return p;}static inline Object** ReadSymbol(Object** p, Handle<String>* s) { *s = Handle<String>(reinterpret_cast<String*>(*p++)); return p;}static inline Object** ReadSentinel(Object** p) { ASSERT(*p == NULL); return p + 1;}template <class Allocator>static Object** ReadList(Object** p, List<Handle<String>, Allocator >* list) { ASSERT(list->is_empty()); int n; p = ReadInt(p, &n); while (n-- > 0) { Handle<String> s; p = ReadSymbol(p, &s); list->Add(s); } return ReadSentinel(p);}template <class Allocator>static Object** ReadList(Object** p, List<Handle<String>, Allocator>* list, List<Variable::Mode, Allocator>* modes) { ASSERT(list->is_empty()); int n; p = ReadInt(p, &n); while (n-- > 0) { Handle<String> s; int m; p = ReadSymbol(p, &s); p = ReadInt(p, &m); list->Add(s); modes->Add(static_cast<Variable::Mode>(m)); } return ReadSentinel(p);}template<class Allocator>ScopeInfo<Allocator>::ScopeInfo(Code* code) : function_name_(Factory::empty_symbol()), supports_eval_(false), parameters_(4), stack_slots_(8), context_slots_(8), context_modes_(8) { if (code == NULL || code->sinfo_size() == 0) return; Object** p0 = &Memory::Object_at(code->sinfo_start()); Object** p = p0; p = ReadSymbol(p, &function_name_); p = ReadBool(p, &supports_eval_); p = ReadList<Allocator>(p, &context_slots_, &context_modes_); p = ReadList<Allocator>(p, ¶meters_); p = ReadList<Allocator>(p, &stack_slots_); ASSERT((p - p0) * kPointerSize == code->sinfo_size());}static inline Object** WriteInt(Object** p, int x) { *p++ = Smi::FromInt(x); return p;}static inline Object** WriteSymbol(Object** p, Handle<String> s) { *p++ = *s; return p;}static inline Object** WriteSentinel(Object** p) { *p++ = NULL; return p;}template <class Allocator>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -