| Index: src/scopeinfo.cc
|
| ===================================================================
|
| --- src/scopeinfo.cc (revision 5059)
|
| +++ src/scopeinfo.cc (working copy)
|
| @@ -204,12 +204,6 @@
|
| }
|
|
|
|
|
| -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());
|
| @@ -220,7 +214,7 @@
|
| p = ReadSymbol(p, &s);
|
| list->Add(s);
|
| }
|
| - return ReadSentinel(p);
|
| + return p;
|
| }
|
|
|
|
|
| @@ -239,42 +233,19 @@
|
| list->Add(s);
|
| modes->Add(static_cast<Variable::Mode>(m));
|
| }
|
| - return ReadSentinel(p);
|
| + return p;
|
| }
|
|
|
|
|
| template<class Allocator>
|
| -Handle<Object> ScopeInfo<Allocator>::CreateHeapObject(Scope* scope) {
|
| - ScopeInfo<ZoneListAllocationPolicy> sinfo(scope);
|
| - return sinfo.Serialize();
|
| -}
|
| -
|
| -
|
| -template<class Allocator>
|
| -Object* ScopeInfo<Allocator>::EmptyHeapObject() {
|
| - return Heap::empty_fixed_array();
|
| -}
|
| -
|
| -
|
| -inline bool IsNotEmpty(Object* data) {
|
| - return FixedArray::cast(data)->length() != 0;
|
| -}
|
| -
|
| -
|
| -inline Object** GetDataStart(Object* data) {
|
| - return FixedArray::cast(data)->data_start();
|
| -}
|
| -
|
| -
|
| -template<class Allocator>
|
| -ScopeInfo<Allocator>::ScopeInfo(Object* data)
|
| +ScopeInfo<Allocator>::ScopeInfo(SerializedScopeInfo* data)
|
| : function_name_(Factory::empty_symbol()),
|
| parameters_(4),
|
| stack_slots_(8),
|
| context_slots_(8),
|
| context_modes_(8) {
|
| - if (IsNotEmpty(data)) {
|
| - Object** p0 = GetDataStart(data);
|
| + if (data->length() > 0) {
|
| + Object** p0 = data->data_start();
|
| Object** p = p0;
|
| p = ReadSymbol(p, &function_name_);
|
| p = ReadBool(p, &calls_eval_);
|
| @@ -304,12 +275,6 @@
|
| }
|
|
|
|
|
| -static inline Object** WriteSentinel(Object** p) {
|
| - *p++ = NULL;
|
| - return p;
|
| -}
|
| -
|
| -
|
| template <class Allocator>
|
| static Object** WriteList(Object** p, List<Handle<String>, Allocator >* list) {
|
| const int n = list->length();
|
| @@ -317,7 +282,7 @@
|
| for (int i = 0; i < n; i++) {
|
| p = WriteSymbol(p, list->at(i));
|
| }
|
| - return WriteSentinel(p);
|
| + return p;
|
| }
|
|
|
|
|
| @@ -331,23 +296,24 @@
|
| p = WriteSymbol(p, list->at(i));
|
| p = WriteInt(p, modes->at(i));
|
| }
|
| - return WriteSentinel(p);
|
| + return p;
|
| }
|
|
|
|
|
| template<class Allocator>
|
| -Handle<Object> ScopeInfo<Allocator>::Serialize() {
|
| - // function name, calls eval, length & sentinel for 3 tables:
|
| - const int extra_slots = 1 + 1 + 2 * 3;
|
| +Handle<SerializedScopeInfo> ScopeInfo<Allocator>::Serialize() {
|
| + // function name, calls eval, length for 3 tables:
|
| + const int extra_slots = 1 + 1 + 3;
|
| int length = extra_slots +
|
| context_slots_.length() * 2 +
|
| parameters_.length() +
|
| stack_slots_.length();
|
|
|
| - Handle<Object> data(Factory::NewFixedArray(length, TENURED));
|
| + Handle<SerializedScopeInfo> data(
|
| + SerializedScopeInfo::cast(*Factory::NewFixedArray(length, TENURED)));
|
| AssertNoAllocation nogc;
|
|
|
| - Object** p0 = GetDataStart(*data);
|
| + Object** p0 = data->data_start();
|
| Object** p = p0;
|
| p = WriteSymbol(p, function_name_);
|
| p = WriteBool(p, calls_eval_);
|
| @@ -360,36 +326,69 @@
|
| }
|
|
|
|
|
| -static Object** ContextEntriesAddr(Object* data) {
|
| - ASSERT(IsNotEmpty(data));
|
| - // +2 for function name and calls eval:
|
| - return GetDataStart(data) + 2;
|
| +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);
|
| + } else {
|
| + return context_slot_name(i - number_of_stack_slots() +
|
| + Context::MIN_CONTEXT_SLOTS);
|
| + }
|
| }
|
|
|
|
|
| -static Object** ParameterEntriesAddr(Object* data) {
|
| - ASSERT(IsNotEmpty(data));
|
| - Object** p = ContextEntriesAddr(data);
|
| - int n; // number of context slots;
|
| - p = ReadInt(p, &n);
|
| - return p + n*2 + 1; // *2 for pairs, +1 for sentinel
|
| +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;
|
| + }
|
| + return number_of_locals;
|
| }
|
|
|
|
|
| -static Object** StackSlotEntriesAddr(Object* data) {
|
| - ASSERT(IsNotEmpty(data));
|
| - Object** p = ParameterEntriesAddr(data);
|
| - int n; // number of parameter slots;
|
| - p = ReadInt(p, &n);
|
| - return p + n + 1; // +1 for sentinel
|
| +Handle<SerializedScopeInfo> SerializedScopeInfo::Create(Scope* scope) {
|
| + ScopeInfo<ZoneListAllocationPolicy> sinfo(scope);
|
| + return sinfo.Serialize();
|
| }
|
|
|
|
|
| -template<class Allocator>
|
| -bool ScopeInfo<Allocator>::CallsEval(Object* data) {
|
| - if (IsNotEmpty(data)) {
|
| - // +1 for function name:
|
| - Object** p = GetDataStart(data) + 1;
|
| +SerializedScopeInfo* SerializedScopeInfo::Empty() {
|
| + return reinterpret_cast<SerializedScopeInfo*>(Heap::empty_fixed_array());
|
| +}
|
| +
|
| +
|
| +Object** SerializedScopeInfo::ContextEntriesAddr() {
|
| + ASSERT(length() > 0);
|
| + return data_start() + 2; // +2 for function name and calls eval.
|
| +}
|
| +
|
| +
|
| +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
|
| +}
|
| +
|
| +
|
| +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;
|
| +}
|
| +
|
| +
|
| +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;
|
| @@ -398,53 +397,49 @@
|
| }
|
|
|
|
|
| -template<class Allocator>
|
| -int ScopeInfo<Allocator>::NumberOfStackSlots(Object* data) {
|
| - if (IsNotEmpty(data)) {
|
| - Object** p = StackSlotEntriesAddr(data);
|
| - int n; // number of stack slots;
|
| - ReadInt(p, &n);
|
| - return n;
|
| +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;
|
| }
|
|
|
|
|
| -template<class Allocator>
|
| -int ScopeInfo<Allocator>::NumberOfContextSlots(Object* data) {
|
| - if (IsNotEmpty(data)) {
|
| - Object** p = ContextEntriesAddr(data);
|
| - int n; // number of context slots;
|
| - ReadInt(p, &n);
|
| - return n + Context::MIN_CONTEXT_SLOTS;
|
| +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;
|
| }
|
|
|
|
|
| -template<class Allocator>
|
| -bool ScopeInfo<Allocator>::HasHeapAllocatedLocals(Object* data) {
|
| - if (IsNotEmpty(data)) {
|
| - Object** p = ContextEntriesAddr(data);
|
| - int n; // number of context slots;
|
| - ReadInt(p, &n);
|
| - return n > 0;
|
| +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;
|
| }
|
|
|
|
|
| -template<class Allocator>
|
| -int ScopeInfo<Allocator>::StackSlotIndex(Object* data, String* name) {
|
| +int SerializedScopeInfo::StackSlotIndex(String* name) {
|
| ASSERT(name->IsSymbol());
|
| - if (IsNotEmpty(data)) {
|
| - // Loop below depends on the NULL sentinel after the stack slot names.
|
| - ASSERT(NumberOfStackSlots(data) > 0 ||
|
| - *(StackSlotEntriesAddr(data) + 1) == NULL);
|
| - // slots start after length entry
|
| - Object** p0 = StackSlotEntriesAddr(data) + 1;
|
| + 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;
|
| - while (*p != NULL) {
|
| + Object** end = p0 + number_of_stack_slots;
|
| + while (p != end) {
|
| if (*p == name) return static_cast<int>(p - p0);
|
| p++;
|
| }
|
| @@ -452,24 +447,18 @@
|
| return -1;
|
| }
|
|
|
| -
|
| -template<class Allocator>
|
| -int ScopeInfo<Allocator>::ContextSlotIndex(Object* data,
|
| - String* name,
|
| - Variable::Mode* mode) {
|
| +int SerializedScopeInfo::ContextSlotIndex(String* name, Variable::Mode* mode) {
|
| ASSERT(name->IsSymbol());
|
| - int result = ContextSlotCache::Lookup(data, name, mode);
|
| + int result = ContextSlotCache::Lookup(this, name, mode);
|
| if (result != ContextSlotCache::kNotFound) return result;
|
| - if (IsNotEmpty(data)) {
|
| - // Loop below depends on the NULL sentinel after the context slot names.
|
| - ASSERT(NumberOfContextSlots(data) >= Context::MIN_CONTEXT_SLOTS ||
|
| - *(ContextEntriesAddr(data) + 1) == NULL);
|
| -
|
| - // slots start after length entry
|
| - Object** p0 = ContextEntriesAddr(data) + 1;
|
| + 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;
|
| - // contexts may have no variable slots (in the presence of eval()).
|
| - while (*p != NULL) {
|
| + Object** end = p0 + number_of_context_slots * 2;
|
| + while (p != end) {
|
| if (*p == name) {
|
| ASSERT(((p - p0) & 1) == 0);
|
| int v;
|
| @@ -477,21 +466,20 @@
|
| 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;
|
| - ContextSlotCache::Update(data, name, mode_value, result);
|
| + ContextSlotCache::Update(this, name, mode_value, result);
|
| return result;
|
| }
|
| p += 2;
|
| }
|
| }
|
| - ContextSlotCache::Update(data, name, Variable::INTERNAL, -1);
|
| + ContextSlotCache::Update(this, name, Variable::INTERNAL, -1);
|
| return -1;
|
| }
|
|
|
|
|
| -template<class Allocator>
|
| -int ScopeInfo<Allocator>::ParameterIndex(Object* data, String* name) {
|
| +int SerializedScopeInfo::ParameterIndex(String* name) {
|
| ASSERT(name->IsSymbol());
|
| - if (IsNotEmpty(data)) {
|
| + if (length() > 0) {
|
| // We must read parameters from the end since for
|
| // multiply declared parameters the value of the
|
| // last declaration of that parameter is used
|
| @@ -502,10 +490,10 @@
|
| // 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(data);
|
| - int n; // number of parameters
|
| - Object** p0 = ReadInt(p, &n);
|
| - p = p0 + n;
|
| + 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);
|
| @@ -515,50 +503,23 @@
|
| }
|
|
|
|
|
| -template<class Allocator>
|
| -int ScopeInfo<Allocator>::FunctionContextSlotIndex(Object* data, String* name) {
|
| +int SerializedScopeInfo::FunctionContextSlotIndex(String* name) {
|
| ASSERT(name->IsSymbol());
|
| - if (IsNotEmpty(data)) {
|
| - Object** p = GetDataStart(data);
|
| + if (length() > 0) {
|
| + Object** p = data_start();
|
| if (*p == name) {
|
| - p = ContextEntriesAddr(data);
|
| - int n; // number of context slots
|
| - ReadInt(p, &n);
|
| - ASSERT(n != 0);
|
| + 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 n + Context::MIN_CONTEXT_SLOTS - 1;
|
| + return number_of_context_slots + Context::MIN_CONTEXT_SLOTS - 1;
|
| }
|
| }
|
| return -1;
|
| }
|
|
|
|
|
| -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 the
|
| - // number Context::MIN_CONTEXT_SLOTS number of fixed allocated slots in the
|
| - // context.
|
| - if (i < number_of_stack_slots()) {
|
| - return stack_slot_name(i);
|
| - } else {
|
| - return context_slot_name(i - number_of_stack_slots() +
|
| - Context::MIN_CONTEXT_SLOTS);
|
| - }
|
| -}
|
| -
|
| -
|
| -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;
|
| - }
|
| - return number_of_locals;
|
| -}
|
| -
|
| -
|
| int ContextSlotCache::Hash(Object* data, String* name) {
|
| // Uses only lower 32 bits if pointers are larger.
|
| uintptr_t addr_hash =
|
|
|