| Index: src/scopeinfo.cc
|
| ===================================================================
|
| --- src/scopeinfo.cc (revision 5039)
|
| +++ src/scopeinfo.cc (working copy)
|
| @@ -148,7 +148,7 @@
|
| }
|
|
|
|
|
| -// Encoding format in the Code object:
|
| +// Encoding format in a FixedArray object:
|
| //
|
| // - function name
|
| //
|
| @@ -244,22 +244,45 @@
|
|
|
|
|
| template<class Allocator>
|
| -ScopeInfo<Allocator>::ScopeInfo(Code* code)
|
| +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)
|
| : function_name_(Factory::empty_symbol()),
|
| 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, &calls_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());
|
| + if (IsNotEmpty(data)) {
|
| + Object** p0 = GetDataStart(data);
|
| + Object** p = p0;
|
| + p = ReadSymbol(p, &function_name_);
|
| + p = ReadBool(p, &calls_eval_);
|
| + 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());
|
| + }
|
| }
|
|
|
|
|
| @@ -313,57 +336,49 @@
|
|
|
|
|
| template<class Allocator>
|
| -int ScopeInfo<Allocator>::Serialize(Code* code) {
|
| +Handle<Object> ScopeInfo<Allocator>::Serialize() {
|
| // function name, calls eval, length & sentinel for 3 tables:
|
| const int extra_slots = 1 + 1 + 2 * 3;
|
| - int size = (extra_slots +
|
| - context_slots_.length() * 2 +
|
| - parameters_.length() +
|
| - stack_slots_.length()) * kPointerSize;
|
| + int length = extra_slots +
|
| + context_slots_.length() * 2 +
|
| + parameters_.length() +
|
| + stack_slots_.length();
|
|
|
| - if (code != NULL) {
|
| - CHECK(code->sinfo_size() == size);
|
| - Object** p0 = &Memory::Object_at(code->sinfo_start());
|
| - Object** p = p0;
|
| - p = WriteSymbol(p, function_name_);
|
| - p = WriteBool(p, calls_eval_);
|
| - p = WriteList(p, &context_slots_, &context_modes_);
|
| - p = WriteList(p, ¶meters_);
|
| - p = WriteList(p, &stack_slots_);
|
| - ASSERT((p - p0) * kPointerSize == size);
|
| - }
|
| + Handle<Object> data(Factory::NewFixedArray(length, TENURED));
|
| + AssertNoAllocation nogc;
|
|
|
| - return size;
|
| -}
|
| + Object** p0 = GetDataStart(*data);
|
| + Object** p = p0;
|
| + p = WriteSymbol(p, function_name_);
|
| + p = WriteBool(p, calls_eval_);
|
| + p = WriteList(p, &context_slots_, &context_modes_);
|
| + p = WriteList(p, ¶meters_);
|
| + p = WriteList(p, &stack_slots_);
|
| + ASSERT((p - p0) == length);
|
|
|
| -
|
| -template<class Allocator>
|
| -void ScopeInfo<Allocator>::IterateScopeInfo(Code* code, ObjectVisitor* v) {
|
| - Object** start = &Memory::Object_at(code->sinfo_start());
|
| - Object** end = &Memory::Object_at(code->sinfo_start() + code->sinfo_size());
|
| - v->VisitPointers(start, end);
|
| + return data;
|
| }
|
|
|
|
|
| -static Object** ContextEntriesAddr(Code* code) {
|
| - ASSERT(code->sinfo_size() > 0);
|
| +static Object** ContextEntriesAddr(Object* data) {
|
| + ASSERT(IsNotEmpty(data));
|
| // +2 for function name and calls eval:
|
| - return &Memory::Object_at(code->sinfo_start()) + 2;
|
| + return GetDataStart(data) + 2;
|
| }
|
|
|
|
|
| -static Object** ParameterEntriesAddr(Code* code) {
|
| - ASSERT(code->sinfo_size() > 0);
|
| - Object** p = ContextEntriesAddr(code);
|
| +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
|
| }
|
|
|
|
|
| -static Object** StackSlotEntriesAddr(Code* code) {
|
| - ASSERT(code->sinfo_size() > 0);
|
| - Object** p = ParameterEntriesAddr(code);
|
| +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
|
| @@ -371,10 +386,10 @@
|
|
|
|
|
| template<class Allocator>
|
| -bool ScopeInfo<Allocator>::CallsEval(Code* code) {
|
| - if (code->sinfo_size() > 0) {
|
| +bool ScopeInfo<Allocator>::CallsEval(Object* data) {
|
| + if (IsNotEmpty(data)) {
|
| // +1 for function name:
|
| - Object** p = &Memory::Object_at(code->sinfo_start()) + 1;
|
| + Object** p = GetDataStart(data) + 1;
|
| bool calls_eval;
|
| p = ReadBool(p, &calls_eval);
|
| return calls_eval;
|
| @@ -384,9 +399,9 @@
|
|
|
|
|
| template<class Allocator>
|
| -int ScopeInfo<Allocator>::NumberOfStackSlots(Code* code) {
|
| - if (code->sinfo_size() > 0) {
|
| - Object** p = StackSlotEntriesAddr(code);
|
| +int ScopeInfo<Allocator>::NumberOfStackSlots(Object* data) {
|
| + if (IsNotEmpty(data)) {
|
| + Object** p = StackSlotEntriesAddr(data);
|
| int n; // number of stack slots;
|
| ReadInt(p, &n);
|
| return n;
|
| @@ -396,9 +411,9 @@
|
|
|
|
|
| template<class Allocator>
|
| -int ScopeInfo<Allocator>::NumberOfContextSlots(Code* code) {
|
| - if (code->sinfo_size() > 0) {
|
| - Object** p = ContextEntriesAddr(code);
|
| +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;
|
| @@ -408,9 +423,9 @@
|
|
|
|
|
| template<class Allocator>
|
| -bool ScopeInfo<Allocator>::HasHeapAllocatedLocals(Code* code) {
|
| - if (code->sinfo_size() > 0) {
|
| - Object** p = ContextEntriesAddr(code);
|
| +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;
|
| @@ -420,14 +435,14 @@
|
|
|
|
|
| template<class Allocator>
|
| -int ScopeInfo<Allocator>::StackSlotIndex(Code* code, String* name) {
|
| +int ScopeInfo<Allocator>::StackSlotIndex(Object* data, String* name) {
|
| ASSERT(name->IsSymbol());
|
| - if (code->sinfo_size() > 0) {
|
| + if (IsNotEmpty(data)) {
|
| // Loop below depends on the NULL sentinel after the stack slot names.
|
| - ASSERT(NumberOfStackSlots(code) > 0 ||
|
| - *(StackSlotEntriesAddr(code) + 1) == NULL);
|
| + ASSERT(NumberOfStackSlots(data) > 0 ||
|
| + *(StackSlotEntriesAddr(data) + 1) == NULL);
|
| // slots start after length entry
|
| - Object** p0 = StackSlotEntriesAddr(code) + 1;
|
| + Object** p0 = StackSlotEntriesAddr(data) + 1;
|
| Object** p = p0;
|
| while (*p != NULL) {
|
| if (*p == name) return static_cast<int>(p - p0);
|
| @@ -439,19 +454,19 @@
|
|
|
|
|
| template<class Allocator>
|
| -int ScopeInfo<Allocator>::ContextSlotIndex(Code* code,
|
| +int ScopeInfo<Allocator>::ContextSlotIndex(Object* data,
|
| String* name,
|
| Variable::Mode* mode) {
|
| ASSERT(name->IsSymbol());
|
| - int result = ContextSlotCache::Lookup(code, name, mode);
|
| + int result = ContextSlotCache::Lookup(data, name, mode);
|
| if (result != ContextSlotCache::kNotFound) return result;
|
| - if (code->sinfo_size() > 0) {
|
| + if (IsNotEmpty(data)) {
|
| // Loop below depends on the NULL sentinel after the context slot names.
|
| - ASSERT(NumberOfContextSlots(code) >= Context::MIN_CONTEXT_SLOTS ||
|
| - *(ContextEntriesAddr(code) + 1) == NULL);
|
| + ASSERT(NumberOfContextSlots(data) >= Context::MIN_CONTEXT_SLOTS ||
|
| + *(ContextEntriesAddr(data) + 1) == NULL);
|
|
|
| // slots start after length entry
|
| - Object** p0 = ContextEntriesAddr(code) + 1;
|
| + Object** p0 = ContextEntriesAddr(data) + 1;
|
| Object** p = p0;
|
| // contexts may have no variable slots (in the presence of eval()).
|
| while (*p != NULL) {
|
| @@ -462,21 +477,21 @@
|
| 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(code, name, mode_value, result);
|
| + ContextSlotCache::Update(data, name, mode_value, result);
|
| return result;
|
| }
|
| p += 2;
|
| }
|
| }
|
| - ContextSlotCache::Update(code, name, Variable::INTERNAL, -1);
|
| + ContextSlotCache::Update(data, name, Variable::INTERNAL, -1);
|
| return -1;
|
| }
|
|
|
|
|
| template<class Allocator>
|
| -int ScopeInfo<Allocator>::ParameterIndex(Code* code, String* name) {
|
| +int ScopeInfo<Allocator>::ParameterIndex(Object* data, String* name) {
|
| ASSERT(name->IsSymbol());
|
| - if (code->sinfo_size() > 0) {
|
| + if (IsNotEmpty(data)) {
|
| // We must read parameters from the end since for
|
| // multiply declared parameters the value of the
|
| // last declaration of that parameter is used
|
| @@ -487,7 +502,7 @@
|
| // 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(code);
|
| + Object** p = ParameterEntriesAddr(data);
|
| int n; // number of parameters
|
| Object** p0 = ReadInt(p, &n);
|
| p = p0 + n;
|
| @@ -501,12 +516,12 @@
|
|
|
|
|
| template<class Allocator>
|
| -int ScopeInfo<Allocator>::FunctionContextSlotIndex(Code* code, String* name) {
|
| +int ScopeInfo<Allocator>::FunctionContextSlotIndex(Object* data, String* name) {
|
| ASSERT(name->IsSymbol());
|
| - if (code->sinfo_size() > 0) {
|
| - Object** p = &Memory::Object_at(code->sinfo_start());
|
| + if (IsNotEmpty(data)) {
|
| + Object** p = GetDataStart(data);
|
| if (*p == name) {
|
| - p = ContextEntriesAddr(code);
|
| + p = ContextEntriesAddr(data);
|
| int n; // number of context slots
|
| ReadInt(p, &n);
|
| ASSERT(n != 0);
|
| @@ -544,20 +559,20 @@
|
| }
|
|
|
|
|
| -int ContextSlotCache::Hash(Code* code, String* name) {
|
| +int ContextSlotCache::Hash(Object* data, String* name) {
|
| // Uses only lower 32 bits if pointers are larger.
|
| uintptr_t addr_hash =
|
| - static_cast<uint32_t>(reinterpret_cast<uintptr_t>(code)) >> 2;
|
| + static_cast<uint32_t>(reinterpret_cast<uintptr_t>(data)) >> 2;
|
| return static_cast<int>((addr_hash ^ name->Hash()) % kLength);
|
| }
|
|
|
|
|
| -int ContextSlotCache::Lookup(Code* code,
|
| +int ContextSlotCache::Lookup(Object* data,
|
| String* name,
|
| Variable::Mode* mode) {
|
| - int index = Hash(code, name);
|
| + int index = Hash(data, name);
|
| Key& key = keys_[index];
|
| - if ((key.code == code) && key.name->Equals(name)) {
|
| + if ((key.data == data) && key.name->Equals(name)) {
|
| Value result(values_[index]);
|
| if (mode != NULL) *mode = result.mode();
|
| return result.index() + kNotFound;
|
| @@ -566,28 +581,28 @@
|
| }
|
|
|
|
|
| -void ContextSlotCache::Update(Code* code,
|
| +void ContextSlotCache::Update(Object* data,
|
| String* name,
|
| Variable::Mode mode,
|
| int slot_index) {
|
| String* symbol;
|
| ASSERT(slot_index > kNotFound);
|
| if (Heap::LookupSymbolIfExists(name, &symbol)) {
|
| - int index = Hash(code, symbol);
|
| + int index = Hash(data, symbol);
|
| Key& key = keys_[index];
|
| - key.code = code;
|
| + key.data = data;
|
| key.name = symbol;
|
| // Please note value only takes a uint as index.
|
| values_[index] = Value(mode, slot_index - kNotFound).raw();
|
| #ifdef DEBUG
|
| - ValidateEntry(code, name, mode, slot_index);
|
| + ValidateEntry(data, name, mode, slot_index);
|
| #endif
|
| }
|
| }
|
|
|
|
|
| void ContextSlotCache::Clear() {
|
| - for (int index = 0; index < kLength; index++) keys_[index].code = NULL;
|
| + for (int index = 0; index < kLength; index++) keys_[index].data = NULL;
|
| }
|
|
|
|
|
| @@ -599,15 +614,15 @@
|
|
|
| #ifdef DEBUG
|
|
|
| -void ContextSlotCache::ValidateEntry(Code* code,
|
| +void ContextSlotCache::ValidateEntry(Object* data,
|
| String* name,
|
| Variable::Mode mode,
|
| int slot_index) {
|
| String* symbol;
|
| if (Heap::LookupSymbolIfExists(name, &symbol)) {
|
| - int index = Hash(code, name);
|
| + int index = Hash(data, name);
|
| Key& key = keys_[index];
|
| - ASSERT(key.code == code);
|
| + ASSERT(key.data == data);
|
| ASSERT(key.name->Equals(name));
|
| Value result(values_[index]);
|
| ASSERT(result.mode() == mode);
|
|
|