Chromium Code Reviews| Index: src/scopeinfo.cc |
| diff --git a/src/scopeinfo.cc b/src/scopeinfo.cc |
| index ad31ca47c613350f3293787df8a0eebe4a3c4705..919f97e5197c6b423c4551d7573320e6440cf8d6 100644 |
| --- a/src/scopeinfo.cc |
| +++ b/src/scopeinfo.cc |
| @@ -51,10 +51,14 @@ ScopeInfo<Allocator>::ScopeInfo(Scope* scope) |
| : function_name_(FACTORY->empty_symbol()), |
| calls_eval_(scope->calls_eval()), |
| is_strict_mode_(scope->is_strict_mode()), |
| + type_(scope->type()), |
| + source_beg_statement_pos_(scope->SourceBegStatementPos()), |
| + source_end_statement_pos_(scope->SourceEndStatementPos()), |
| parameters_(scope->num_parameters()), |
| stack_slots_(scope->num_stack_slots()), |
| context_slots_(scope->num_heap_slots()), |
| - context_modes_(scope->num_heap_slots()) { |
| + context_modes_(scope->num_heap_slots()), |
| + inner_scopeinfos_(scope->InnerScopes()->length()) { |
| // Add parameters. |
| for (int i = 0; i < scope->num_parameters(); i++) { |
| ASSERT(parameters_.length() == i); |
| @@ -141,6 +145,15 @@ ScopeInfo<Allocator>::ScopeInfo(Scope* scope) |
| context_modes_.Add(Variable::INTERNAL); |
| } |
| } |
| + |
| + // Add nested scope information. Only nested block, catch or with scopes are |
| + // tracked, but no inner function scopes. |
| + ZoneList<Scope*>* inner_scopes = scope->InnerScopes(); |
| + for (int i = 0; i < inner_scopes->length(); i++) { |
| + if (!inner_scopes->at(i)->is_declaration_scope()) { |
| + inner_scopeinfos_.Add(SerializedScopeInfo::Create(inner_scopes->at(i))); |
| + } |
| + } |
| } |
| @@ -150,6 +163,14 @@ ScopeInfo<Allocator>::ScopeInfo(Scope* scope) |
| // |
| // - calls eval boolean flag |
|
Kevin Millikin (Chromium)
2011/10/05 08:43:36
This is a separate change, but this class should b
Steven
2011/10/06 19:09:27
Yes I agree. We will talk about this cleanup later
|
| // |
| +// - is strict mode scope |
| +// |
| +// - scope type |
| +// |
| +// - start statement position |
| +// |
| +// - end statement position |
| +// |
| // - number of variables in the context object (smi) (= function context |
| // slot index + 1) |
| // - list of pairs (name, Var mode) of context-allocated variables (starting |
| @@ -160,6 +181,9 @@ ScopeInfo<Allocator>::ScopeInfo(Scope* scope) |
| // |
| // - number of variables on the stack (smi) |
| // - list of names of stack-allocated variables (starting with stack slot 0) |
| +// |
| +// - number of immediate nested scopes (smi) |
| +// - list of handles to serialized scope infos for nested scopes |
| // The ScopeInfo representation could be simplified and the ScopeInfo |
| // re-implemented (with almost the same interface). Here is a |
| @@ -181,8 +205,9 @@ ScopeInfo<Allocator>::ScopeInfo(Scope* scope) |
| // present) |
| -static inline Object** ReadInt(Object** p, int* x) { |
| - *x = (reinterpret_cast<Smi*>(*p++))->value(); |
| +template <class T> |
| +static inline Object** ReadInt(Object** p, T* x) { |
| + *x = static_cast<T>((reinterpret_cast<Smi*>(*p++))->value()); |
| return p; |
| } |
| @@ -193,20 +218,21 @@ static inline Object** ReadBool(Object** p, bool* x) { |
| } |
| -static inline Object** ReadSymbol(Object** p, Handle<String>* s) { |
| - *s = Handle<String>(reinterpret_cast<String*>(*p++)); |
| +template <class T> |
| +static inline Object** ReadObject(Object** p, Handle<T>* s) { |
| + *s = Handle<T>::cast(Handle<Object>(*p++)); |
| return p; |
| } |
| -template <class Allocator> |
| -static Object** ReadList(Object** p, List<Handle<String>, Allocator >* list) { |
| +template <class Allocator, class T> |
| +static Object** ReadList(Object** p, List<Handle<T>, Allocator >* list) { |
| ASSERT(list->is_empty()); |
| int n; |
| p = ReadInt(p, &n); |
| while (n-- > 0) { |
| - Handle<String> s; |
| - p = ReadSymbol(p, &s); |
| + Handle<T> s; |
| + p = ReadObject(p, &s); |
| list->Add(s); |
| } |
| return p; |
| @@ -223,7 +249,7 @@ static Object** ReadList(Object** p, |
| while (n-- > 0) { |
| Handle<String> s; |
| int m; |
| - p = ReadSymbol(p, &s); |
| + p = ReadObject(p, &s); |
| p = ReadInt(p, &m); |
| list->Add(s); |
| modes->Add(static_cast<Variable::Mode>(m)); |
| @@ -238,16 +264,21 @@ ScopeInfo<Allocator>::ScopeInfo(SerializedScopeInfo* data) |
| parameters_(4), |
| stack_slots_(8), |
| context_slots_(8), |
| - context_modes_(8) { |
| + context_modes_(8), |
| + inner_scopeinfos_(4) { |
| if (data->length() > 0) { |
| Object** p0 = data->data_start(); |
| Object** p = p0; |
| - p = ReadSymbol(p, &function_name_); |
| + p = ReadObject(p, &function_name_); |
| p = ReadBool(p, &calls_eval_); |
| p = ReadBool(p, &is_strict_mode_); |
| + p = ReadInt(p, &type_); |
| + p = ReadInt(p, &source_beg_statement_pos_); |
| + p = ReadInt(p, &source_end_statement_pos_); |
| p = ReadList<Allocator>(p, &context_slots_, &context_modes_); |
| p = ReadList<Allocator>(p, ¶meters_); |
| p = ReadList<Allocator>(p, &stack_slots_); |
| + p = ReadList<Allocator>(p, &inner_scopeinfos_); |
| ASSERT((p - p0) == FixedArray::cast(data)->length()); |
| } |
| } |
| @@ -265,18 +296,19 @@ static inline Object** WriteBool(Object** p, bool b) { |
| } |
| -static inline Object** WriteSymbol(Object** p, Handle<String> s) { |
| +template <class T> |
| +static inline Object** WriteObject(Object** p, Handle<T> s) { |
| *p++ = *s; |
| return p; |
| } |
| -template <class Allocator> |
| -static Object** WriteList(Object** p, List<Handle<String>, Allocator >* list) { |
| +template <class Allocator, class T> |
| +static Object** WriteList(Object** p, List<Handle<T>, Allocator >* list) { |
| const int n = list->length(); |
| p = WriteInt(p, n); |
| for (int i = 0; i < n; i++) { |
| - p = WriteSymbol(p, list->at(i)); |
| + p = WriteObject(p, list->at(i)); |
| } |
| return p; |
| } |
| @@ -289,7 +321,7 @@ static Object** WriteList(Object** p, |
| const int n = list->length(); |
| p = WriteInt(p, n); |
| for (int i = 0; i < n; i++) { |
| - p = WriteSymbol(p, list->at(i)); |
| + p = WriteObject(p, list->at(i)); |
| p = WriteInt(p, modes->at(i)); |
| } |
| return p; |
| @@ -298,12 +330,14 @@ static Object** WriteList(Object** 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; |
| + // function name, calls eval, is_strict_mode, scope type, source beg pos, |
| + // source end pos, length for 4 tables: |
| + const int extra_slots = 1 + 1 + 1 + 1 + 1 + 1 + 4; |
| int length = extra_slots + |
| context_slots_.length() * 2 + |
| parameters_.length() + |
| - stack_slots_.length(); |
| + stack_slots_.length() + |
| + inner_scopeinfos_.length(); |
| Handle<SerializedScopeInfo> data( |
| SerializedScopeInfo::cast(*FACTORY->NewSerializedScopeInfo(length))); |
| @@ -311,12 +345,16 @@ Handle<SerializedScopeInfo> ScopeInfo<Allocator>::Serialize() { |
| Object** p0 = data->data_start(); |
| Object** p = p0; |
| - p = WriteSymbol(p, function_name_); |
| + p = WriteObject(p, function_name_); |
| p = WriteBool(p, calls_eval_); |
| p = WriteBool(p, is_strict_mode_); |
| + p = WriteInt(p, type_); |
| + p = WriteInt(p, source_beg_statement_pos_); |
| + p = WriteInt(p, source_end_statement_pos_); |
| p = WriteList(p, &context_slots_, &context_modes_); |
| p = WriteList(p, ¶meters_); |
| p = WriteList(p, &stack_slots_); |
| + p = WriteList(p, &inner_scopeinfos_); |
| ASSERT((p - p0) == length); |
| return data; |
| @@ -361,8 +399,9 @@ SerializedScopeInfo* SerializedScopeInfo::Empty() { |
| Object** SerializedScopeInfo::ContextEntriesAddr() { |
| ASSERT(length() > 0); |
| - // +3 for function name, calls eval, strict mode. |
| - return data_start() + 3; |
| + // +6 for function name, calls eval, strict mode, scope type, source beg pos, |
| + // source end pos. |
| + return data_start() + 6; |
| } |
| @@ -384,6 +423,15 @@ Object** SerializedScopeInfo::StackSlotEntriesAddr() { |
| } |
| +Object** SerializedScopeInfo::NestedScopeEntriesAddr() { |
| + ASSERT(length() > 0); |
| + Object** p = StackSlotEntriesAddr(); |
| + int number_of_stack_slots; |
| + p = ReadInt(p, &number_of_stack_slots); |
| + return p + number_of_stack_slots; |
| +} |
| + |
| + |
| bool SerializedScopeInfo::CallsEval() { |
| if (length() > 0) { |
| Object** p = data_start() + 1; // +1 for function name. |
| @@ -406,6 +454,41 @@ bool SerializedScopeInfo::IsStrictMode() { |
| } |
| +Scope::Type SerializedScopeInfo::ScopeType() { |
| + ASSERT(length() > 0); |
| + // +3 for function name, calls eval, strict mode. |
| + Object** p = data_start() + 3; |
| + Scope::Type type; |
| + p = ReadInt(p, &type); |
|
Kevin Millikin (Chromium)
2011/10/05 08:43:36
Future refactoring: if you decide to keep the stre
|
| + return type; |
| +} |
| + |
| + |
| +int SerializedScopeInfo::SourceBegStatementPos() { |
| + if (length() > 0) { |
| + // +4 for function name, calls eval, strict mode, scope type. |
| + Object** p = data_start() + 4; |
| + int source_beg_statement_pos; |
| + p = ReadInt(p, &source_beg_statement_pos); |
| + return source_beg_statement_pos; |
| + } |
| + return -1; |
|
Kevin Millikin (Chromium)
2011/10/05 08:43:36
-1 is RelocInfo::kNoPosition?
Steven
2011/10/06 19:09:27
Yes it is. Using the named constant now.
On 2011/1
|
| +} |
| + |
| + |
| +int SerializedScopeInfo::SourceEndStatementPos() { |
| + if (length() > 0) { |
| + // +5 for function name, calls eval, strict mode, scope type, |
| + // source beg pos. |
| + Object** p = data_start() + 5; |
| + int source_end_statement_pos; |
| + p = ReadInt(p, &source_end_statement_pos); |
| + return source_end_statement_pos; |
| + } |
| + return -1; |
| +} |
| + |
| + |
| int SerializedScopeInfo::NumberOfStackSlots() { |
| if (length() > 0) { |
| Object** p = StackSlotEntriesAddr(); |
| @@ -428,6 +511,24 @@ int SerializedScopeInfo::NumberOfContextSlots() { |
| } |
| +int SerializedScopeInfo::NumberOfNestedScopes() { |
| + if (length() > 0) { |
| + Object** p = NestedScopeEntriesAddr(); |
| + int number_of_nested_scopes; |
| + ReadInt(p, &number_of_nested_scopes); |
| + return number_of_nested_scopes; |
| + } |
| + return 0; |
| +} |
| + |
| + |
| +Handle<SerializedScopeInfo> SerializedScopeInfo::NestedScope(int i) { |
| + ASSERT(0 <= i && i < NumberOfNestedScopes()); |
| + Object* p = *(NestedScopeEntriesAddr() + i + 1); |
| + return Handle<SerializedScopeInfo>(reinterpret_cast<SerializedScopeInfo*>(p)); |
| +} |
| + |
| + |
| bool SerializedScopeInfo::HasHeapAllocatedLocals() { |
| if (length() > 0) { |
| Object** p = ContextEntriesAddr(); |
| @@ -439,6 +540,12 @@ bool SerializedScopeInfo::HasHeapAllocatedLocals() { |
| } |
| +bool SerializedScopeInfo::HasContext() { |
| + return HasHeapAllocatedLocals() || |
| + ScopeType() == Scope::WITH_SCOPE; |
| +} |
| + |
| + |
| int SerializedScopeInfo::StackSlotIndex(String* name) { |
| ASSERT(name->IsSymbol()); |
| if (length() > 0) { |
| @@ -530,6 +637,24 @@ int SerializedScopeInfo::FunctionContextSlotIndex(String* name) { |
| } |
| +void SerializedScopeInfo::GetNestedScopeChain( |
| + List<Handle<SerializedScopeInfo> >* chain, |
| + int position) { |
| + chain->Add(Handle<SerializedScopeInfo>(this)); |
| + |
| + for (int i = 0; i < NumberOfNestedScopes(); i++) { |
| + Handle<SerializedScopeInfo> scope = NestedScope(i); |
| + int beg_pos = scope->SourceBegStatementPos(); |
| + int end_pos = scope->SourceEndStatementPos(); |
| + ASSERT(beg_pos >= 0 && end_pos >= 0); |
| + if (beg_pos <= position && position <= end_pos) { |
| + scope->GetNestedScopeChain(chain, position); |
| + return; |
| + } |
| + } |
| +} |
| + |
| + |
| int ContextSlotCache::Hash(Object* data, String* name) { |
| // Uses only lower 32 bits if pointers are larger. |
| uintptr_t addr_hash = |