diff options
Diffstat (limited to 'deps/v8/src/scopeinfo.cc')
-rw-r--r-- | deps/v8/src/scopeinfo.cc | 689 |
1 files changed, 278 insertions, 411 deletions
diff --git a/deps/v8/src/scopeinfo.cc b/deps/v8/src/scopeinfo.cc index ad31ca47c..0f3623470 100644 --- a/deps/v8/src/scopeinfo.cc +++ b/deps/v8/src/scopeinfo.cc @@ -38,456 +38,297 @@ namespace v8 { namespace internal { -static int CompareLocal(Variable* const* v, Variable* const* w) { - int x = (*v)->index(); - int y = (*w)->index(); - // Consider sorting them according to type as well? - return x - y; -} - - -template<class Allocator> -ScopeInfo<Allocator>::ScopeInfo(Scope* scope) - : function_name_(FACTORY->empty_symbol()), - calls_eval_(scope->calls_eval()), - is_strict_mode_(scope->is_strict_mode()), - 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->is_used()) { - switch (var->location()) { - case Variable::UNALLOCATED: - case Variable::PARAMETER: - break; - - case Variable::LOCAL: - ASSERT(stack_slots_.length() == var->index()); - stack_slots_.Add(var->name()); - break; - - case Variable::CONTEXT: - heap_locals.Add(var); - break; - - case Variable::LOOKUP: - // We don't expect lookup variables in the locals list. - 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]->index() - Context::MIN_CONTEXT_SLOTS == - context_slots_.length()); - ASSERT(heap_locals[i]->index() - Context::MIN_CONTEXT_SLOTS == - context_modes_.length()); - context_slots_.Add(heap_locals[i]->name()); - context_modes_.Add(heap_locals[i]->mode()); +Handle<ScopeInfo> ScopeInfo::Create(Scope* scope) { + // Collect stack and context locals. + ZoneList<Variable*> stack_locals(scope->StackLocalCount()); + ZoneList<Variable*> context_locals(scope->ContextLocalCount()); + scope->CollectStackAndContextLocals(&stack_locals, &context_locals); + const int stack_local_count = stack_locals.length(); + const int context_local_count = context_locals.length(); + // Make sure we allocate the correct amount. + ASSERT(scope->StackLocalCount() == stack_local_count); + ASSERT(scope->ContextLocalCount() == context_local_count); + + // Determine use and location of the function variable if it is present. + FunctionVariableInfo function_name_info; + VariableMode function_variable_mode; + if (scope->is_function_scope() && scope->function() != NULL) { + Variable* var = scope->function()->var(); + if (!var->is_used()) { + function_name_info = UNUSED; + } else if (var->IsContextSlot()) { + function_name_info = CONTEXT; + } else { + ASSERT(var->IsStackLocal()); + function_name_info = STACK; } - + function_variable_mode = var->mode(); } else { - ASSERT(heap_locals.length() == 0); + function_name_info = NONE; + function_variable_mode = VAR; } - // 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()) { - VariableProxy* proxy = scope->function(); - if (proxy != NULL && - proxy->var()->is_used() && - proxy->var()->IsContextSlot()) { - function_name_ = proxy->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(proxy->var()->index() - Context::MIN_CONTEXT_SLOTS == - context_slots_.length()); - ASSERT(proxy->var()->index() - Context::MIN_CONTEXT_SLOTS == - context_modes_.length()); - context_slots_.Add(FACTORY->empty_symbol()); - context_modes_.Add(Variable::INTERNAL); - } + const bool has_function_name = function_name_info != NONE; + const int parameter_count = scope->num_parameters(); + const int length = kVariablePartIndex + + parameter_count + stack_local_count + 2 * context_local_count + + (has_function_name ? 2 : 0); + + Handle<ScopeInfo> scope_info = FACTORY->NewScopeInfo(length); + + // Encode the flags. + int flags = TypeField::encode(scope->type()) | + CallsEvalField::encode(scope->calls_eval()) | + LanguageModeField::encode(scope->language_mode()) | + FunctionVariableField::encode(function_name_info) | + FunctionVariableMode::encode(function_variable_mode); + scope_info->SetFlags(flags); + scope_info->SetParameterCount(parameter_count); + scope_info->SetStackLocalCount(stack_local_count); + scope_info->SetContextLocalCount(context_local_count); + + int index = kVariablePartIndex; + // Add parameters. + ASSERT(index == scope_info->ParameterEntriesIndex()); + for (int i = 0; i < parameter_count; ++i) { + scope_info->set(index++, *scope->parameter(i)->name()); } -} - -// Encoding format in a FixedArray object: -// -// - function name -// -// - calls eval boolean flag -// -// - 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) -// -// - number of parameters (smi) -// - list of parameter names (starting with parameter 0 first) -// -// - number of variables on the stack (smi) -// - list of names of stack-allocated variables (starting with stack slot 0) - -// 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) + // Add stack locals' names. We are assuming that the stack locals' + // slots are allocated in increasing order, so we can simply add + // them to the ScopeInfo object. + ASSERT(index == scope_info->StackLocalEntriesIndex()); + for (int i = 0; i < stack_local_count; ++i) { + ASSERT(stack_locals[i]->index() == i); + scope_info->set(index++, *stack_locals[i]->name()); + } + // Due to usage analysis, context-allocated locals are not necessarily in + // increasing order: 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 need to sort them by + // context slot index before adding them to the ScopeInfo object. + context_locals.Sort(&Variable::CompareIndex); + + // Add context locals' names. + ASSERT(index == scope_info->ContextLocalNameEntriesIndex()); + for (int i = 0; i < context_local_count; ++i) { + scope_info->set(index++, *context_locals[i]->name()); + } -static inline Object** ReadInt(Object** p, int* x) { - *x = (reinterpret_cast<Smi*>(*p++))->value(); - return p; -} + // Add context locals' info. + ASSERT(index == scope_info->ContextLocalInfoEntriesIndex()); + for (int i = 0; i < context_local_count; ++i) { + Variable* var = context_locals[i]; + uint32_t value = ContextLocalMode::encode(var->mode()) | + ContextLocalInitFlag::encode(var->initialization_flag()); + scope_info->set(index++, Smi::FromInt(value)); + } + // If present, add the function variable name and its index. + ASSERT(index == scope_info->FunctionNameEntryIndex()); + if (has_function_name) { + int var_index = scope->function()->var()->index(); + scope_info->set(index++, *scope->function()->name()); + scope_info->set(index++, Smi::FromInt(var_index)); + ASSERT(function_name_info != STACK || + (var_index == scope_info->StackLocalCount() && + var_index == scope_info->StackSlotCount() - 1)); + ASSERT(function_name_info != CONTEXT || + var_index == scope_info->ContextLength() - 1); + } -static inline Object** ReadBool(Object** p, bool* x) { - *x = (reinterpret_cast<Smi*>(*p++))->value() != 0; - return p; + ASSERT(index == scope_info->length()); + ASSERT(scope->num_parameters() == scope_info->ParameterCount()); + ASSERT(scope->num_stack_slots() == scope_info->StackSlotCount()); + ASSERT(scope->num_heap_slots() == scope_info->ContextLength()); + return scope_info; } -static inline Object** ReadSymbol(Object** p, Handle<String>* s) { - *s = Handle<String>(reinterpret_cast<String*>(*p++)); - return p; +ScopeInfo* ScopeInfo::Empty() { + return reinterpret_cast<ScopeInfo*>(HEAP->empty_fixed_array()); } -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 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 p; -} - - -template<class Allocator> -ScopeInfo<Allocator>::ScopeInfo(SerializedScopeInfo* data) - : function_name_(FACTORY->empty_symbol()), - parameters_(4), - stack_slots_(8), - context_slots_(8), - context_modes_(8) { - if (data->length() > 0) { - Object** p0 = data->data_start(); - Object** p = p0; - p = ReadSymbol(p, &function_name_); - p = ReadBool(p, &calls_eval_); - p = ReadBool(p, &is_strict_mode_); - p = ReadList<Allocator>(p, &context_slots_, &context_modes_); - p = ReadList<Allocator>(p, ¶meters_); - p = ReadList<Allocator>(p, &stack_slots_); - ASSERT((p - p0) == FixedArray::cast(data)->length()); - } +ScopeType ScopeInfo::Type() { + ASSERT(length() > 0); + return TypeField::decode(Flags()); } -static inline Object** WriteInt(Object** p, int x) { - *p++ = Smi::FromInt(x); - return p; +bool ScopeInfo::CallsEval() { + return length() > 0 && CallsEvalField::decode(Flags()); } -static inline Object** WriteBool(Object** p, bool b) { - *p++ = Smi::FromInt(b ? 1 : 0); - return p; +LanguageMode ScopeInfo::language_mode() { + return length() > 0 ? LanguageModeField::decode(Flags()) : CLASSIC_MODE; } -static inline Object** WriteSymbol(Object** p, Handle<String> s) { - *p++ = *s; - return p; +int ScopeInfo::LocalCount() { + return StackLocalCount() + ContextLocalCount(); } -template <class Allocator> -static Object** WriteList(Object** p, List<Handle<String>, Allocator >* list) { - const int n = list->length(); - p = WriteInt(p, n); - for (int i = 0; i < n; i++) { - p = WriteSymbol(p, list->at(i)); +int ScopeInfo::StackSlotCount() { + if (length() > 0) { + bool function_name_stack_slot = + FunctionVariableField::decode(Flags()) == STACK; + return StackLocalCount() + (function_name_stack_slot ? 1 : 0); } - return p; + return 0; } -template <class Allocator> -static Object** WriteList(Object** p, - List<Handle<String>, Allocator>* list, - List<Variable::Mode, Allocator>* modes) { - const int n = list->length(); - p = WriteInt(p, n); - for (int i = 0; i < n; i++) { - p = WriteSymbol(p, list->at(i)); - p = WriteInt(p, modes->at(i)); +int ScopeInfo::ContextLength() { + if (length() > 0) { + int context_locals = ContextLocalCount(); + bool function_name_context_slot = + FunctionVariableField::decode(Flags()) == CONTEXT; + bool has_context = context_locals > 0 || + function_name_context_slot || + Type() == WITH_SCOPE || + (Type() == FUNCTION_SCOPE && CallsEval()); + if (has_context) { + return Context::MIN_CONTEXT_SLOTS + context_locals + + (function_name_context_slot ? 1 : 0); + } } - return p; -} - - -template<class Allocator> -Handle<SerializedScopeInfo> ScopeInfo<Allocator>::Serialize() { - // function name, calls eval, is_strict_mode, length for 3 tables: - const int extra_slots = 1 + 1 + 1 + 3; - int length = extra_slots + - context_slots_.length() * 2 + - parameters_.length() + - stack_slots_.length(); - - Handle<SerializedScopeInfo> data( - SerializedScopeInfo::cast(*FACTORY->NewSerializedScopeInfo(length))); - AssertNoAllocation nogc; - - Object** p0 = data->data_start(); - Object** p = p0; - p = WriteSymbol(p, function_name_); - p = WriteBool(p, calls_eval_); - p = WriteBool(p, is_strict_mode_); - p = WriteList(p, &context_slots_, &context_modes_); - p = WriteList(p, ¶meters_); - p = WriteList(p, &stack_slots_); - ASSERT((p - p0) == length); - - return data; + return 0; } -template<class Allocator> -Handle<String> ScopeInfo<Allocator>::LocalName(int i) const { - // A local variable can be allocated either on the stack or in the context. - // For variables allocated in the context they are always preceded by - // Context::MIN_CONTEXT_SLOTS of fixed allocated slots in the context. - if (i < number_of_stack_slots()) { - return stack_slot_name(i); +bool ScopeInfo::HasFunctionName() { + if (length() > 0) { + return NONE != FunctionVariableField::decode(Flags()); } else { - return context_slot_name(i - number_of_stack_slots() + - Context::MIN_CONTEXT_SLOTS); + return false; } } -template<class Allocator> -int ScopeInfo<Allocator>::NumberOfLocals() const { - int number_of_locals = number_of_stack_slots(); - if (number_of_context_slots() > 0) { - ASSERT(number_of_context_slots() >= Context::MIN_CONTEXT_SLOTS); - number_of_locals += number_of_context_slots() - Context::MIN_CONTEXT_SLOTS; +bool ScopeInfo::HasHeapAllocatedLocals() { + if (length() > 0) { + return ContextLocalCount() > 0; + } else { + return false; } - return number_of_locals; } -Handle<SerializedScopeInfo> SerializedScopeInfo::Create(Scope* scope) { - ScopeInfo<ZoneListAllocationPolicy> sinfo(scope); - return sinfo.Serialize(); -} - - -SerializedScopeInfo* SerializedScopeInfo::Empty() { - return reinterpret_cast<SerializedScopeInfo*>(HEAP->empty_fixed_array()); -} - - -Object** SerializedScopeInfo::ContextEntriesAddr() { - ASSERT(length() > 0); - // +3 for function name, calls eval, strict mode. - return data_start() + 3; +bool ScopeInfo::HasContext() { + if (length() > 0) { + return ContextLength() > 0; + } else { + return false; + } } -Object** SerializedScopeInfo::ParameterEntriesAddr() { - ASSERT(length() > 0); - Object** p = ContextEntriesAddr(); - int number_of_context_slots; - p = ReadInt(p, &number_of_context_slots); - return p + number_of_context_slots*2; // *2 for pairs +String* ScopeInfo::FunctionName() { + ASSERT(HasFunctionName()); + return String::cast(get(FunctionNameEntryIndex())); } -Object** SerializedScopeInfo::StackSlotEntriesAddr() { - ASSERT(length() > 0); - Object** p = ParameterEntriesAddr(); - int number_of_parameter_slots; - p = ReadInt(p, &number_of_parameter_slots); - return p + number_of_parameter_slots; +String* ScopeInfo::ParameterName(int var) { + ASSERT(0 <= var && var < ParameterCount()); + int info_index = ParameterEntriesIndex() + var; + return String::cast(get(info_index)); } -bool SerializedScopeInfo::CallsEval() { - if (length() > 0) { - Object** p = data_start() + 1; // +1 for function name. - bool calls_eval; - p = ReadBool(p, &calls_eval); - return calls_eval; - } - return false; +String* ScopeInfo::LocalName(int var) { + ASSERT(0 <= var && var < LocalCount()); + ASSERT(StackLocalEntriesIndex() + StackLocalCount() == + ContextLocalNameEntriesIndex()); + int info_index = StackLocalEntriesIndex() + var; + return String::cast(get(info_index)); } -bool SerializedScopeInfo::IsStrictMode() { - if (length() > 0) { - Object** p = data_start() + 2; // +2 for function name, calls eval. - bool strict_mode; - p = ReadBool(p, &strict_mode); - return strict_mode; - } - return false; +String* ScopeInfo::StackLocalName(int var) { + ASSERT(0 <= var && var < StackLocalCount()); + int info_index = StackLocalEntriesIndex() + var; + return String::cast(get(info_index)); } -int SerializedScopeInfo::NumberOfStackSlots() { - if (length() > 0) { - Object** p = StackSlotEntriesAddr(); - int number_of_stack_slots; - ReadInt(p, &number_of_stack_slots); - return number_of_stack_slots; - } - return 0; +String* ScopeInfo::ContextLocalName(int var) { + ASSERT(0 <= var && var < ContextLocalCount()); + int info_index = ContextLocalNameEntriesIndex() + var; + return String::cast(get(info_index)); } -int SerializedScopeInfo::NumberOfContextSlots() { - if (length() > 0) { - Object** p = ContextEntriesAddr(); - int number_of_context_slots; - ReadInt(p, &number_of_context_slots); - return number_of_context_slots + Context::MIN_CONTEXT_SLOTS; - } - return 0; +VariableMode ScopeInfo::ContextLocalMode(int var) { + ASSERT(0 <= var && var < ContextLocalCount()); + int info_index = ContextLocalInfoEntriesIndex() + var; + int value = Smi::cast(get(info_index))->value(); + return ContextLocalMode::decode(value); } -bool SerializedScopeInfo::HasHeapAllocatedLocals() { - if (length() > 0) { - Object** p = ContextEntriesAddr(); - int number_of_context_slots; - ReadInt(p, &number_of_context_slots); - return number_of_context_slots > 0; - } - return false; +InitializationFlag ScopeInfo::ContextLocalInitFlag(int var) { + ASSERT(0 <= var && var < ContextLocalCount()); + int info_index = ContextLocalInfoEntriesIndex() + var; + int value = Smi::cast(get(info_index))->value(); + return ContextLocalInitFlag::decode(value); } -int SerializedScopeInfo::StackSlotIndex(String* name) { +int ScopeInfo::StackSlotIndex(String* name) { ASSERT(name->IsSymbol()); if (length() > 0) { - // Slots start after length entry. - Object** p0 = StackSlotEntriesAddr(); - int number_of_stack_slots; - p0 = ReadInt(p0, &number_of_stack_slots); - Object** p = p0; - Object** end = p0 + number_of_stack_slots; - while (p != end) { - if (*p == name) return static_cast<int>(p - p0); - p++; + int start = StackLocalEntriesIndex(); + int end = StackLocalEntriesIndex() + StackLocalCount(); + for (int i = start; i < end; ++i) { + if (name == get(i)) { + return i - start; + } } } return -1; } -int SerializedScopeInfo::ContextSlotIndex(String* name, Variable::Mode* mode) { + +int ScopeInfo::ContextSlotIndex(String* name, + VariableMode* mode, + InitializationFlag* init_flag) { ASSERT(name->IsSymbol()); - Isolate* isolate = GetIsolate(); - int result = isolate->context_slot_cache()->Lookup(this, name, mode); - if (result != ContextSlotCache::kNotFound) return result; + ASSERT(mode != NULL); + ASSERT(init_flag != NULL); if (length() > 0) { - // Slots start after length entry. - Object** p0 = ContextEntriesAddr(); - int number_of_context_slots; - p0 = ReadInt(p0, &number_of_context_slots); - Object** p = p0; - Object** end = p0 + number_of_context_slots * 2; - while (p != end) { - if (*p == name) { - ASSERT(((p - p0) & 1) == 0); - int v; - ReadInt(p + 1, &v); - Variable::Mode mode_value = static_cast<Variable::Mode>(v); - if (mode != NULL) *mode = mode_value; - result = static_cast<int>((p - p0) >> 1) + Context::MIN_CONTEXT_SLOTS; - isolate->context_slot_cache()->Update(this, name, mode_value, result); + ContextSlotCache* context_slot_cache = GetIsolate()->context_slot_cache(); + int result = context_slot_cache->Lookup(this, name, mode, init_flag); + if (result != ContextSlotCache::kNotFound) { + ASSERT(result < ContextLength()); + return result; + } + + int start = ContextLocalNameEntriesIndex(); + int end = ContextLocalNameEntriesIndex() + ContextLocalCount(); + for (int i = start; i < end; ++i) { + if (name == get(i)) { + int var = i - start; + *mode = ContextLocalMode(var); + *init_flag = ContextLocalInitFlag(var); + result = Context::MIN_CONTEXT_SLOTS + var; + context_slot_cache->Update(this, name, *mode, *init_flag, result); + ASSERT(result < ContextLength()); return result; } - p += 2; } + context_slot_cache->Update(this, name, INTERNAL, kNeedsInitialization, -1); } - isolate->context_slot_cache()->Update(this, name, Variable::INTERNAL, -1); return -1; } -int SerializedScopeInfo::ParameterIndex(String* name) { +int ScopeInfo::ParameterIndex(String* name) { ASSERT(name->IsSymbol()); if (length() > 0) { // We must read parameters from the end since for @@ -495,41 +336,58 @@ int SerializedScopeInfo::ParameterIndex(String* name) { // last declaration of that parameter is used // inside a function (and thus we need to look // at the last index). Was bug# 1110337. - // - // Eventually, we should only register such parameters - // once, with corresponding index. This requires a new - // implementation of the ScopeInfo code. See also other - // comments in this file regarding this. - Object** p = ParameterEntriesAddr(); - int number_of_parameter_slots; - Object** p0 = ReadInt(p, &number_of_parameter_slots); - p = p0 + number_of_parameter_slots; - while (p > p0) { - p--; - if (*p == name) return static_cast<int>(p - p0); + int start = ParameterEntriesIndex(); + int end = ParameterEntriesIndex() + ParameterCount(); + for (int i = end - 1; i >= start; --i) { + if (name == get(i)) { + return i - start; + } } } return -1; } -int SerializedScopeInfo::FunctionContextSlotIndex(String* name) { +int ScopeInfo::FunctionContextSlotIndex(String* name, VariableMode* mode) { ASSERT(name->IsSymbol()); + ASSERT(mode != NULL); if (length() > 0) { - Object** p = data_start(); - if (*p == name) { - p = ContextEntriesAddr(); - int number_of_context_slots; - ReadInt(p, &number_of_context_slots); - ASSERT(number_of_context_slots != 0); - // The function context slot is the last entry. - return number_of_context_slots + Context::MIN_CONTEXT_SLOTS - 1; + if (FunctionVariableField::decode(Flags()) == CONTEXT && + FunctionName() == name) { + *mode = FunctionVariableMode::decode(Flags()); + return Smi::cast(get(FunctionNameEntryIndex() + 1))->value(); } } return -1; } +int ScopeInfo::ParameterEntriesIndex() { + ASSERT(length() > 0); + return kVariablePartIndex; +} + + +int ScopeInfo::StackLocalEntriesIndex() { + return ParameterEntriesIndex() + ParameterCount(); +} + + +int ScopeInfo::ContextLocalNameEntriesIndex() { + return StackLocalEntriesIndex() + StackLocalCount(); +} + + +int ScopeInfo::ContextLocalInfoEntriesIndex() { + return ContextLocalNameEntriesIndex() + ContextLocalCount(); +} + + +int ScopeInfo::FunctionNameEntryIndex() { + return ContextLocalInfoEntriesIndex() + ContextLocalCount(); +} + + int ContextSlotCache::Hash(Object* data, String* name) { // Uses only lower 32 bits if pointers are larger. uintptr_t addr_hash = @@ -540,12 +398,14 @@ int ContextSlotCache::Hash(Object* data, String* name) { int ContextSlotCache::Lookup(Object* data, String* name, - Variable::Mode* mode) { + VariableMode* mode, + InitializationFlag* init_flag) { int index = Hash(data, name); Key& key = keys_[index]; if ((key.data == data) && key.name->Equals(name)) { Value result(values_[index]); if (mode != NULL) *mode = result.mode(); + if (init_flag != NULL) *init_flag = result.initialization_flag(); return result.index() + kNotFound; } return kNotFound; @@ -554,7 +414,8 @@ int ContextSlotCache::Lookup(Object* data, void ContextSlotCache::Update(Object* data, String* name, - Variable::Mode mode, + VariableMode mode, + InitializationFlag init_flag, int slot_index) { String* symbol; ASSERT(slot_index > kNotFound); @@ -564,9 +425,9 @@ void ContextSlotCache::Update(Object* data, key.data = data; key.name = symbol; // Please note value only takes a uint as index. - values_[index] = Value(mode, slot_index - kNotFound).raw(); + values_[index] = Value(mode, init_flag, slot_index - kNotFound).raw(); #ifdef DEBUG - ValidateEntry(data, name, mode, slot_index); + ValidateEntry(data, name, mode, init_flag, slot_index); #endif } } @@ -581,7 +442,8 @@ void ContextSlotCache::Clear() { void ContextSlotCache::ValidateEntry(Object* data, String* name, - Variable::Mode mode, + VariableMode mode, + InitializationFlag init_flag, int slot_index) { String* symbol; if (HEAP->LookupSymbolIfExists(name, &symbol)) { @@ -591,51 +453,56 @@ void ContextSlotCache::ValidateEntry(Object* data, ASSERT(key.name->Equals(name)); Value result(values_[index]); ASSERT(result.mode() == mode); + ASSERT(result.initialization_flag() == init_flag); ASSERT(result.index() + kNotFound == slot_index); } } -template <class Allocator> static void PrintList(const char* list_name, int nof_internal_slots, - List<Handle<String>, Allocator>& list) { - if (list.length() > 0) { + int start, + int end, + ScopeInfo* scope_info) { + if (start < end) { PrintF("\n // %s\n", list_name); if (nof_internal_slots > 0) { PrintF(" %2d - %2d [internal slots]\n", 0 , nof_internal_slots - 1); } - for (int i = 0; i < list.length(); i++) { - PrintF(" %2d ", i + nof_internal_slots); - list[i]->ShortPrint(); + for (int i = nof_internal_slots; start < end; ++i, ++start) { + PrintF(" %2d ", i); + String::cast(scope_info->get(start))->ShortPrint(); PrintF("\n"); } } } -template<class Allocator> -void ScopeInfo<Allocator>::Print() { +void ScopeInfo::Print() { PrintF("ScopeInfo "); - if (function_name_->length() > 0) - function_name_->ShortPrint(); - else + if (HasFunctionName()) { + FunctionName()->ShortPrint(); + } else { PrintF("/* no function name */"); + } PrintF("{"); - PrintList<Allocator>("parameters", 0, parameters_); - PrintList<Allocator>("stack slots", 0, stack_slots_); - PrintList<Allocator>("context slots", Context::MIN_CONTEXT_SLOTS, - context_slots_); + PrintList("parameters", 0, + ParameterEntriesIndex(), + ParameterEntriesIndex() + ParameterCount(), + this); + PrintList("stack slots", 0, + StackLocalEntriesIndex(), + StackLocalEntriesIndex() + StackLocalCount(), + this); + PrintList("context slots", + Context::MIN_CONTEXT_SLOTS, + ContextLocalNameEntriesIndex(), + ContextLocalNameEntriesIndex() + ContextLocalCount(), + this); PrintF("}\n"); } #endif // DEBUG - -// Make sure the classes get instantiated by the template system. -template class ScopeInfo<FreeStoreAllocationPolicy>; -template class ScopeInfo<PreallocatedStorage>; -template class ScopeInfo<ZoneListAllocationPolicy>; - } } // namespace v8::internal |