Commit efb53e14 authored by verwaest@chromium.org's avatar verwaest@chromium.org

Make order of addition the primary order of descriptor arrays.

The order by name is maintained as secondary order by using unused bits in the property details.

This is preliminary work towards sharing descriptors arrays.

The change allows us
- to get rid of the LastAdded bits in the map, binding it to the number of valid descriptors for the given map
- to avoid resorting by enumeration index to create the cache
- (maybe in the future, depending on performance) to get rid of the enumeration cache altogether.

Although generally the number_of_descriptors equals the NumberOfOwnDescriptors in the current version, this is preliminary work towards sharing    descriptors, where maps may have more descriptors than are valid for the map.

Review URL: https://chromiumcodereview.appspot.com/10879013

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@12385 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent cd585f26
...@@ -2221,8 +2221,9 @@ void Genesis::TransferNamedProperties(Handle<JSObject> from, ...@@ -2221,8 +2221,9 @@ void Genesis::TransferNamedProperties(Handle<JSObject> from,
// Add to dictionary. // Add to dictionary.
Handle<String> key = Handle<String>(descs->GetKey(i)); Handle<String> key = Handle<String>(descs->GetKey(i));
Handle<Object> callbacks(descs->GetCallbacksObject(i)); Handle<Object> callbacks(descs->GetCallbacksObject(i));
PropertyDetails d = PropertyDetails d = PropertyDetails(details.attributes(),
PropertyDetails(details.attributes(), CALLBACKS, details.index()); CALLBACKS,
details.descriptor_index());
JSObject::SetNormalizedProperty(to, key, callbacks, d); JSObject::SetNormalizedProperty(to, key, callbacks, d);
break; break;
} }
......
...@@ -701,7 +701,6 @@ Handle<JSArray> GetKeysFor(Handle<JSReceiver> object, bool* threw) { ...@@ -701,7 +701,6 @@ Handle<JSArray> GetKeysFor(Handle<JSReceiver> object, bool* threw) {
Handle<FixedArray> GetEnumPropertyKeys(Handle<JSObject> object, Handle<FixedArray> GetEnumPropertyKeys(Handle<JSObject> object,
bool cache_result) { bool cache_result) {
int index = 0;
Isolate* isolate = object->GetIsolate(); Isolate* isolate = object->GetIsolate();
if (object->HasFastProperties()) { if (object->HasFastProperties()) {
if (object->map()->instance_descriptors()->HasEnumCache()) { if (object->map()->instance_descriptors()->HasEnumCache()) {
...@@ -715,44 +714,34 @@ Handle<FixedArray> GetEnumPropertyKeys(Handle<JSObject> object, ...@@ -715,44 +714,34 @@ Handle<FixedArray> GetEnumPropertyKeys(Handle<JSObject> object,
int num_enum = object->NumberOfLocalProperties(DONT_ENUM); int num_enum = object->NumberOfLocalProperties(DONT_ENUM);
Handle<FixedArray> storage = isolate->factory()->NewFixedArray(num_enum); Handle<FixedArray> storage = isolate->factory()->NewFixedArray(num_enum);
Handle<FixedArray> sort_array = isolate->factory()->NewFixedArray(num_enum);
Handle<FixedArray> indices; Handle<FixedArray> indices;
Handle<FixedArray> sort_array2;
if (cache_result) { if (cache_result) {
indices = isolate->factory()->NewFixedArray(num_enum); indices = isolate->factory()->NewFixedArray(num_enum);
sort_array2 = isolate->factory()->NewFixedArray(num_enum);
} }
Handle<DescriptorArray> descs = Handle<DescriptorArray> descs =
Handle<DescriptorArray>(object->map()->instance_descriptors(), isolate); Handle<DescriptorArray>(object->map()->instance_descriptors(), isolate);
int index = 0;
for (int i = 0; i < descs->number_of_descriptors(); i++) { for (int i = 0; i < descs->number_of_descriptors(); i++) {
if (!descs->GetDetails(i).IsDontEnum()) { if (!descs->GetDetails(i).IsDontEnum()) {
storage->set(index, descs->GetKey(i)); storage->set(index, descs->GetKey(i));
PropertyDetails details = descs->GetDetails(i); PropertyDetails details = descs->GetDetails(i);
sort_array->set(index, Smi::FromInt(details.index()));
if (!indices.is_null()) { if (!indices.is_null()) {
if (details.type() != FIELD) { if (details.type() != FIELD) {
indices = Handle<FixedArray>(); indices = Handle<FixedArray>();
sort_array2 = Handle<FixedArray>();
} else { } else {
int field_index = Descriptor::IndexFromValue(descs->GetValue(i)); int field_index = Descriptor::IndexFromValue(descs->GetValue(i));
if (field_index >= map->inobject_properties()) { if (field_index >= map->inobject_properties()) {
field_index = -(field_index - map->inobject_properties() + 1); field_index = -(field_index - map->inobject_properties() + 1);
} }
indices->set(index, Smi::FromInt(field_index)); indices->set(index, Smi::FromInt(field_index));
sort_array2->set(index, Smi::FromInt(details.index()));
} }
} }
index++; index++;
} }
} }
storage->SortPairs(*sort_array, sort_array->length());
if (!indices.is_null()) {
indices->SortPairs(*sort_array2, sort_array2->length());
}
if (cache_result) { if (cache_result) {
Handle<FixedArray> bridge_storage = Handle<FixedArray> bridge_storage =
isolate->factory()->NewFixedArray( isolate->factory()->NewFixedArray(
......
...@@ -2050,9 +2050,8 @@ void Heap::ScavengeObjectSlow(HeapObject** p, HeapObject* object) { ...@@ -2050,9 +2050,8 @@ void Heap::ScavengeObjectSlow(HeapObject** p, HeapObject* object) {
MaybeObject* Heap::AllocatePartialMap(InstanceType instance_type, MaybeObject* Heap::AllocatePartialMap(InstanceType instance_type,
int instance_size) { int instance_size) {
Object* result; Object* result;
{ MaybeObject* maybe_result = AllocateRawMap(); MaybeObject* maybe_result = AllocateRawMap();
if (!maybe_result->ToObject(&result)) return maybe_result; if (!maybe_result->ToObject(&result)) return maybe_result;
}
// Map::cast cannot be used due to uninitialized map field. // Map::cast cannot be used due to uninitialized map field.
reinterpret_cast<Map*>(result)->set_map(raw_unchecked_meta_map()); reinterpret_cast<Map*>(result)->set_map(raw_unchecked_meta_map());
...@@ -2065,8 +2064,7 @@ MaybeObject* Heap::AllocatePartialMap(InstanceType instance_type, ...@@ -2065,8 +2064,7 @@ MaybeObject* Heap::AllocatePartialMap(InstanceType instance_type,
reinterpret_cast<Map*>(result)->set_unused_property_fields(0); reinterpret_cast<Map*>(result)->set_unused_property_fields(0);
reinterpret_cast<Map*>(result)->set_bit_field(0); reinterpret_cast<Map*>(result)->set_bit_field(0);
reinterpret_cast<Map*>(result)->set_bit_field2(0); reinterpret_cast<Map*>(result)->set_bit_field2(0);
reinterpret_cast<Map*>(result)->set_bit_field3( reinterpret_cast<Map*>(result)->set_bit_field3(0);
Map::LastAddedBits::encode(Map::kNoneAdded));
return result; return result;
} }
...@@ -2093,7 +2091,7 @@ MaybeObject* Heap::AllocateMap(InstanceType instance_type, ...@@ -2093,7 +2091,7 @@ MaybeObject* Heap::AllocateMap(InstanceType instance_type,
map->set_unused_property_fields(0); map->set_unused_property_fields(0);
map->set_bit_field(0); map->set_bit_field(0);
map->set_bit_field2(1 << Map::kIsExtensible); map->set_bit_field2(1 << Map::kIsExtensible);
map->set_bit_field3(Map::LastAddedBits::encode(Map::kNoneAdded)); map->set_bit_field3(0);
map->set_elements_kind(elements_kind); map->set_elements_kind(elements_kind);
// If the map object is aligned fill the padding area with Smi 0 objects. // If the map object is aligned fill the padding area with Smi 0 objects.
...@@ -3890,7 +3888,7 @@ MaybeObject* Heap::AllocateInitialMap(JSFunction* fun) { ...@@ -3890,7 +3888,7 @@ MaybeObject* Heap::AllocateInitialMap(JSFunction* fun) {
FieldDescriptor field(name, i, NONE, i + 1); FieldDescriptor field(name, i, NONE, i + 1);
descriptors->Set(i, &field, witness); descriptors->Set(i, &field, witness);
} }
descriptors->Sort(witness); descriptors->Sort();
// The descriptors may contain duplicates because the compiler does not // The descriptors may contain duplicates because the compiler does not
// guarantee the uniqueness of property names (it would have required // guarantee the uniqueness of property names (it would have required
...@@ -4162,8 +4160,9 @@ MaybeObject* Heap::AllocateGlobalObject(JSFunction* constructor) { ...@@ -4162,8 +4160,9 @@ MaybeObject* Heap::AllocateGlobalObject(JSFunction* constructor) {
for (int i = 0; i < descs->number_of_descriptors(); i++) { for (int i = 0; i < descs->number_of_descriptors(); i++) {
PropertyDetails details = descs->GetDetails(i); PropertyDetails details = descs->GetDetails(i);
ASSERT(details.type() == CALLBACKS); // Only accessors are expected. ASSERT(details.type() == CALLBACKS); // Only accessors are expected.
PropertyDetails d = PropertyDetails d = PropertyDetails(details.attributes(),
PropertyDetails(details.attributes(), CALLBACKS, details.index()); CALLBACKS,
details.descriptor_index());
Object* value = descs->GetCallbacksObject(i); Object* value = descs->GetCallbacksObject(i);
MaybeObject* maybe_value = AllocateJSGlobalPropertyCell(value); MaybeObject* maybe_value = AllocateJSGlobalPropertyCell(value);
if (!maybe_value->ToObject(&value)) return maybe_value; if (!maybe_value->ToObject(&value)) return maybe_value;
......
...@@ -302,11 +302,9 @@ void Map::MapVerify() { ...@@ -302,11 +302,9 @@ void Map::MapVerify() {
instance_size() < HEAP->Capacity())); instance_size() < HEAP->Capacity()));
VerifyHeapPointer(prototype()); VerifyHeapPointer(prototype());
VerifyHeapPointer(instance_descriptors()); VerifyHeapPointer(instance_descriptors());
if (instance_descriptors()->number_of_descriptors() == 0) { DescriptorArray* descriptors = instance_descriptors();
ASSERT(LastAdded() == kNoneAdded); for (int i = 0; i < NumberOfOwnDescriptors(); ++i) {
} else { ASSERT_EQ(i, descriptors->GetDetails(i).descriptor_index() - 1);
ASSERT(instance_descriptors()->GetDetails(LastAdded()).index() ==
instance_descriptors()->number_of_descriptors());
} }
SLOW_ASSERT(instance_descriptors()->IsSortedNoDuplicates()); SLOW_ASSERT(instance_descriptors()->IsSortedNoDuplicates());
if (HasTransitionArray()) { if (HasTransitionArray()) {
...@@ -907,13 +905,13 @@ bool DescriptorArray::IsSortedNoDuplicates() { ...@@ -907,13 +905,13 @@ bool DescriptorArray::IsSortedNoDuplicates() {
String* current_key = NULL; String* current_key = NULL;
uint32_t current = 0; uint32_t current = 0;
for (int i = 0; i < number_of_descriptors(); i++) { for (int i = 0; i < number_of_descriptors(); i++) {
String* key = GetKey(i); String* key = GetSortedKey(i);
if (key == current_key) { if (key == current_key) {
PrintDescriptors(); PrintDescriptors();
return false; return false;
} }
current_key = key; current_key = key;
uint32_t hash = GetKey(i)->Hash(); uint32_t hash = GetSortedKey(i)->Hash();
if (hash < current) { if (hash < current) {
PrintDescriptors(); PrintDescriptors();
return false; return false;
...@@ -928,13 +926,13 @@ bool TransitionArray::IsSortedNoDuplicates() { ...@@ -928,13 +926,13 @@ bool TransitionArray::IsSortedNoDuplicates() {
String* current_key = NULL; String* current_key = NULL;
uint32_t current = 0; uint32_t current = 0;
for (int i = 0; i < number_of_transitions(); i++) { for (int i = 0; i < number_of_transitions(); i++) {
String* key = GetKey(i); String* key = GetSortedKey(i);
if (key == current_key) { if (key == current_key) {
PrintTransitions(); PrintTransitions();
return false; return false;
} }
current_key = key; current_key = key;
uint32_t hash = GetKey(i)->Hash(); uint32_t hash = GetSortedKey(i)->Hash();
if (hash < current) { if (hash < current) {
PrintTransitions(); PrintTransitions();
return false; return false;
......
...@@ -1879,15 +1879,6 @@ bool DescriptorArray::IsEmpty() { ...@@ -1879,15 +1879,6 @@ bool DescriptorArray::IsEmpty() {
} }
void DescriptorArray::NoIncrementalWriteBarrierSwap(FixedArray* array,
int first,
int second) {
Object* tmp = array->get(first);
NoIncrementalWriteBarrierSet(array, first, array->get(second));
NoIncrementalWriteBarrierSet(array, second, tmp);
}
// Perform a binary search in a fixed array. Low and high are entry indices. If // Perform a binary search in a fixed array. Low and high are entry indices. If
// there are three entries in this array it should be called with low=0 and // there are three entries in this array it should be called with low=0 and
// high=2. // high=2.
...@@ -1900,7 +1891,7 @@ int BinarySearch(T* array, String* name, int low, int high) { ...@@ -1900,7 +1891,7 @@ int BinarySearch(T* array, String* name, int low, int high) {
while (low != high) { while (low != high) {
int mid = (low + high) / 2; int mid = (low + high) / 2;
String* mid_name = array->GetKey(mid); String* mid_name = array->GetSortedKey(mid);
uint32_t mid_hash = mid_name->Hash(); uint32_t mid_hash = mid_name->Hash();
if (mid_hash >= hash) { if (mid_hash >= hash) {
...@@ -1910,24 +1901,27 @@ int BinarySearch(T* array, String* name, int low, int high) { ...@@ -1910,24 +1901,27 @@ int BinarySearch(T* array, String* name, int low, int high) {
} }
} }
for (; low <= limit && array->GetKey(low)->Hash() == hash; ++low) { for (; low <= limit; ++low) {
if (array->GetKey(low)->Equals(name)) return low; int sort_index = array->GetSortedKeyIndex(low);
String* entry = array->GetKey(sort_index);
if (entry->Hash() != hash) break;
if (entry->Equals(name)) return sort_index;
} }
return T::kNotFound; return T::kNotFound;
} }
// Perform a linear search in this fixed array. len is the number of entry // Perform a linear search in this fixed array. len is the number of entry
// indices that are valid. // indices that are valid.
template<typename T> template<typename T>
int LinearSearch(T* array, String* name, int len) { int LinearSearch(T* array, String* name, int len) {
uint32_t hash = name->Hash(); uint32_t hash = name->Hash();
for (int number = 0; number < len; number++) { for (int number = 0; number < len; number++) {
String* entry = array->GetKey(number); int sorted_index = array->GetSortedKeyIndex(number);
String* entry = array->GetKey(sorted_index);
uint32_t current_hash = entry->Hash(); uint32_t current_hash = entry->Hash();
if (current_hash > hash) break; if (current_hash > hash) break;
if (current_hash == hash && name->Equals(entry)) return number; if (current_hash == hash && entry->Equals(name)) return sorted_index;
} }
return T::kNotFound; return T::kNotFound;
} }
...@@ -1937,13 +1931,12 @@ template<typename T> ...@@ -1937,13 +1931,12 @@ template<typename T>
int Search(T* array, String* name) { int Search(T* array, String* name) {
SLOW_ASSERT(array->IsSortedNoDuplicates()); SLOW_ASSERT(array->IsSortedNoDuplicates());
// Check for empty descriptor array.
int nof = array->number_of_entries(); int nof = array->number_of_entries();
if (nof == 0) return T::kNotFound; if (nof == 0) return T::kNotFound;
// Fast case: do linear search for small arrays. // Fast case: do linear search for small arrays.
const int kMaxElementsForLinearSearch = 8; const int kMaxElementsForLinearSearch = 8;
if (StringShape(name).IsSymbol() && nof < kMaxElementsForLinearSearch) { if (nof < kMaxElementsForLinearSearch) {
return LinearSearch(array, name, nof); return LinearSearch(array, name, nof);
} }
...@@ -1958,16 +1951,44 @@ int DescriptorArray::Search(String* name) { ...@@ -1958,16 +1951,44 @@ int DescriptorArray::Search(String* name) {
int DescriptorArray::SearchWithCache(String* name) { int DescriptorArray::SearchWithCache(String* name) {
if (number_of_descriptors() == 0) return kNotFound;
DescriptorLookupCache* cache = GetIsolate()->descriptor_lookup_cache(); DescriptorLookupCache* cache = GetIsolate()->descriptor_lookup_cache();
int number = cache->Lookup(this, name); int number = cache->Lookup(this, name);
if (number == DescriptorLookupCache::kAbsent) { if (number == DescriptorLookupCache::kAbsent) {
number = internal::Search(this, name); number = Search(name);
cache->Update(this, name, number); cache->Update(this, name, number);
} }
return number; return number;
} }
void Map::LookupDescriptor(JSObject* holder,
String* name,
LookupResult* result) {
DescriptorArray* descriptors = this->instance_descriptors();
int number = descriptors->SearchWithCache(name);
if (number == DescriptorArray::kNotFound) return result->NotFound();
result->DescriptorResult(holder, descriptors->GetDetails(number), number);
}
void Map::LookupTransition(JSObject* holder,
String* name,
LookupResult* result) {
if (HasTransitionArray()) {
TransitionArray* transition_array = transitions();
int number = transition_array->Search(name);
if (number != TransitionArray::kNotFound) {
return result->TransitionResult(holder, number);
}
}
result->NotFound();
}
Object** DescriptorArray::GetKeySlot(int descriptor_number) { Object** DescriptorArray::GetKeySlot(int descriptor_number) {
ASSERT(descriptor_number < number_of_descriptors()); ASSERT(descriptor_number < number_of_descriptors());
return HeapObject::RawField( return HeapObject::RawField(
...@@ -1982,6 +2003,23 @@ String* DescriptorArray::GetKey(int descriptor_number) { ...@@ -1982,6 +2003,23 @@ String* DescriptorArray::GetKey(int descriptor_number) {
} }
int DescriptorArray::GetSortedKeyIndex(int descriptor_number) {
return GetDetails(descriptor_number).pointer();
}
String* DescriptorArray::GetSortedKey(int descriptor_number) {
return GetKey(GetSortedKeyIndex(descriptor_number));
}
void DescriptorArray::SetSortedKey(int pointer, int descriptor_number) {
int details_index = ToDetailsIndex(pointer);
PropertyDetails details = PropertyDetails(Smi::cast(get(details_index)));
set_unchecked(details_index, details.set_pointer(descriptor_number).AsSmi());
}
Object** DescriptorArray::GetValueSlot(int descriptor_number) { Object** DescriptorArray::GetValueSlot(int descriptor_number) {
ASSERT(descriptor_number < number_of_descriptors()); ASSERT(descriptor_number < number_of_descriptors());
return HeapObject::RawField( return HeapObject::RawField(
...@@ -2043,8 +2081,9 @@ void DescriptorArray::Set(int descriptor_number, ...@@ -2043,8 +2081,9 @@ void DescriptorArray::Set(int descriptor_number,
const WhitenessWitness&) { const WhitenessWitness&) {
// Range check. // Range check.
ASSERT(descriptor_number < number_of_descriptors()); ASSERT(descriptor_number < number_of_descriptors());
ASSERT(desc->GetDetails().index() <= number_of_descriptors()); ASSERT(desc->GetDetails().descriptor_index() <=
ASSERT(desc->GetDetails().index() > 0); number_of_descriptors());
ASSERT(desc->GetDetails().descriptor_index() > 0);
NoIncrementalWriteBarrierSet(this, NoIncrementalWriteBarrierSet(this,
ToKeyIndex(descriptor_number), ToKeyIndex(descriptor_number),
...@@ -2058,38 +2097,31 @@ void DescriptorArray::Set(int descriptor_number, ...@@ -2058,38 +2097,31 @@ void DescriptorArray::Set(int descriptor_number,
} }
int DescriptorArray::Append(Descriptor* desc, void DescriptorArray::Append(Descriptor* desc,
const WhitenessWitness& witness, const WhitenessWitness& witness,
int number_of_set_descriptors) { int number_of_set_descriptors) {
int descriptor_number = number_of_set_descriptors; int enumeration_index = number_of_set_descriptors + 1;
int enumeration_index = descriptor_number + 1;
desc->SetEnumerationIndex(enumeration_index); desc->SetEnumerationIndex(enumeration_index);
Set(number_of_set_descriptors, desc, witness);
uint32_t hash = desc->GetKey()->Hash(); uint32_t hash = desc->GetKey()->Hash();
for (; descriptor_number > 0; --descriptor_number) { int insertion;
String* key = GetKey(descriptor_number - 1);
for (insertion = number_of_set_descriptors; insertion > 0; --insertion) {
String* key = GetSortedKey(insertion - 1);
if (key->Hash() <= hash) break; if (key->Hash() <= hash) break;
Object* value = GetValue(descriptor_number - 1); SetSortedKey(insertion, GetSortedKeyIndex(insertion - 1));
PropertyDetails details = GetDetails(descriptor_number - 1);
Descriptor moved_descriptor(key, value, details);
Set(descriptor_number, &moved_descriptor, witness);
} }
Set(descriptor_number, desc, witness); SetSortedKey(insertion, number_of_set_descriptors);
return descriptor_number;
} }
void DescriptorArray::NoIncrementalWriteBarrierSwapDescriptors( void DescriptorArray::SwapSortedKeys(int first, int second) {
int first, int second) { int first_key = GetSortedKeyIndex(first);
NoIncrementalWriteBarrierSwap(this, ToKeyIndex(first), ToKeyIndex(second)); SetSortedKey(first, GetSortedKeyIndex(second));
NoIncrementalWriteBarrierSwap(this, SetSortedKey(second, first_key);
ToValueIndex(first),
ToValueIndex(second));
NoIncrementalWriteBarrierSwap(this,
ToDetailsIndex(first),
ToDetailsIndex(second));
} }
...@@ -3447,18 +3479,18 @@ MaybeObject* Map::SetDescriptors(DescriptorArray* value, ...@@ -3447,18 +3479,18 @@ MaybeObject* Map::SetDescriptors(DescriptorArray* value,
MaybeObject* Map::InitializeDescriptors(DescriptorArray* descriptors) { MaybeObject* Map::InitializeDescriptors(DescriptorArray* descriptors) {
#ifdef DEBUG
int len = descriptors->number_of_descriptors(); int len = descriptors->number_of_descriptors();
ASSERT(len <= DescriptorArray::kMaxNumberOfDescriptors); ASSERT(len <= DescriptorArray::kMaxNumberOfDescriptors);
SLOW_ASSERT(descriptors->IsSortedNoDuplicates()); SLOW_ASSERT(descriptors->IsSortedNoDuplicates());
#ifdef DEBUG
bool used_indices[DescriptorArray::kMaxNumberOfDescriptors]; bool used_indices[DescriptorArray::kMaxNumberOfDescriptors];
for (int i = 0; i < len; ++i) used_indices[i] = false; for (int i = 0; i < len; ++i) used_indices[i] = false;
// Ensure that all enumeration indexes between 1 and length occur uniquely in // Ensure that all enumeration indexes between 1 and length occur uniquely in
// the descriptor array. // the descriptor array.
for (int i = 0; i < len; ++i) { for (int i = 0; i < len; ++i) {
int enum_index = descriptors->GetDetails(i).index() - int enum_index = descriptors->GetDetails(i).descriptor_index() -
PropertyDetails::kInitialIndex; PropertyDetails::kInitialIndex;
ASSERT(0 <= enum_index && enum_index < len); ASSERT(0 <= enum_index && enum_index < len);
ASSERT(!used_indices[enum_index]); ASSERT(!used_indices[enum_index]);
...@@ -3469,14 +3501,8 @@ MaybeObject* Map::InitializeDescriptors(DescriptorArray* descriptors) { ...@@ -3469,14 +3501,8 @@ MaybeObject* Map::InitializeDescriptors(DescriptorArray* descriptors) {
MaybeObject* maybe_failure = SetDescriptors(descriptors); MaybeObject* maybe_failure = SetDescriptors(descriptors);
if (maybe_failure->IsFailure()) return maybe_failure; if (maybe_failure->IsFailure()) return maybe_failure;
for (int i = 0; i < len; ++i) { SetNumberOfOwnDescriptors(descriptors->number_of_descriptors());
if (descriptors->GetDetails(i).index() == len) {
SetLastAdded(i);
return this;
}
}
ASSERT(len == 0 && LastAdded() == kNoneAdded);
return this; return this;
} }
...@@ -3503,9 +3529,10 @@ void Map::ClearTransitions(Heap* heap, WriteBarrierMode mode) { ...@@ -3503,9 +3529,10 @@ void Map::ClearTransitions(Heap* heap, WriteBarrierMode mode) {
void Map::AppendDescriptor(Descriptor* desc, void Map::AppendDescriptor(Descriptor* desc,
const DescriptorArray::WhitenessWitness& witness) { const DescriptorArray::WhitenessWitness& witness) {
DescriptorArray* descriptors = instance_descriptors(); DescriptorArray* descriptors = instance_descriptors();
int set_descriptors = NumberOfSetDescriptors(); int number_of_own_descriptors = NumberOfOwnDescriptors();
int new_last_added = descriptors->Append(desc, witness, set_descriptors); ASSERT(number_of_own_descriptors < descriptors->number_of_descriptors());
SetLastAdded(new_last_added); descriptors->Append(desc, witness, number_of_own_descriptors);
SetNumberOfOwnDescriptors(number_of_own_descriptors + 1);
} }
...@@ -4993,7 +5020,9 @@ void Dictionary<Shape, Key>::SetEntry(int entry, ...@@ -4993,7 +5020,9 @@ void Dictionary<Shape, Key>::SetEntry(int entry,
Object* key, Object* key,
Object* value, Object* value,
PropertyDetails details) { PropertyDetails details) {
ASSERT(!key->IsString() || details.IsDeleted() || details.index() > 0); ASSERT(!key->IsString() ||
details.IsDeleted() ||
details.dictionary_index() > 0);
int index = HashTable<Shape, Key>::EntryToIndex(entry); int index = HashTable<Shape, Key>::EntryToIndex(entry);
AssertNoAllocation no_gc; AssertNoAllocation no_gc;
WriteBarrierMode mode = FixedArray::GetWriteBarrierMode(no_gc); WriteBarrierMode mode = FixedArray::GetWriteBarrierMode(no_gc);
......
This diff is collapsed.
...@@ -2515,17 +2515,22 @@ class DescriptorArray: public FixedArray { ...@@ -2515,17 +2515,22 @@ class DescriptorArray: public FixedArray {
inline Object* GetCallbacksObject(int descriptor_number); inline Object* GetCallbacksObject(int descriptor_number);
inline AccessorDescriptor* GetCallbacks(int descriptor_number); inline AccessorDescriptor* GetCallbacks(int descriptor_number);
inline String* GetSortedKey(int descriptor_number);
inline int GetSortedKeyIndex(int descriptor_number);
inline void SetSortedKey(int pointer, int descriptor_number);
// Accessor for complete descriptor. // Accessor for complete descriptor.
inline void Get(int descriptor_number, Descriptor* desc); inline void Get(int descriptor_number, Descriptor* desc);
inline void Set(int descriptor_number, inline void Set(int descriptor_number,
Descriptor* desc, Descriptor* desc,
const WhitenessWitness&); const WhitenessWitness&);
// Append automatically sets the enumeration index. This should only be used // Append automatically sets the enumeration index. This should only be used
// to add descriptors in bulk at the end, followed by sorting the descriptor // to add descriptors in bulk at the end, followed by sorting the descriptor
// array. // array.
inline int Append(Descriptor* desc, inline void Append(Descriptor* desc,
const WhitenessWitness&, const WhitenessWitness&,
int number_of_set_descriptors); int number_of_set_descriptors);
// Transfer a complete descriptor from the src descriptor array to this // Transfer a complete descriptor from the src descriptor array to this
// descriptor array. // descriptor array.
...@@ -2535,7 +2540,8 @@ class DescriptorArray: public FixedArray { ...@@ -2535,7 +2540,8 @@ class DescriptorArray: public FixedArray {
const WhitenessWitness&); const WhitenessWitness&);
// Sort the instance descriptors by the hash codes of their keys. // Sort the instance descriptors by the hash codes of their keys.
void Sort(const WhitenessWitness&); void Sort();
inline void SwapSortedKeys(int first, int second);
// Search the instance descriptors for given name. // Search the instance descriptors for given name.
INLINE(int Search(String* name)); INLINE(int Search(String* name));
...@@ -4657,10 +4663,10 @@ class Map: public HeapObject { ...@@ -4657,10 +4663,10 @@ class Map: public HeapObject {
inline int bit_field3(); inline int bit_field3();
inline void set_bit_field3(int value); inline void set_bit_field3(int value);
class IsShared: public BitField<bool, 0, 1> {}; class NumberOfOwnDescriptorsBits: public BitField<int, 0, 11> {};
class FunctionWithPrototype: public BitField<bool, 1, 1> {}; class IsShared: public BitField<bool, 11, 1> {};
class DictionaryMap: public BitField<bool, 2, 1> {}; class FunctionWithPrototype: public BitField<bool, 12, 1> {};
class LastAddedBits: public BitField<int, 3, 11> {}; class DictionaryMap: public BitField<bool, 13, 1> {};
// Tells whether the object in the prototype property will be used // Tells whether the object in the prototype property will be used
// for instances created from this function. If the prototype // for instances created from this function. If the prototype
...@@ -4885,31 +4891,31 @@ class Map: public HeapObject { ...@@ -4885,31 +4891,31 @@ class Map: public HeapObject {
// Lookup in the map's instance descriptors and fill out the result // Lookup in the map's instance descriptors and fill out the result
// with the given holder if the name is found. The holder may be // with the given holder if the name is found. The holder may be
// NULL when this function is used from the compiler. // NULL when this function is used from the compiler.
void LookupDescriptor(JSObject* holder, inline void LookupDescriptor(JSObject* holder,
String* name, String* name,
LookupResult* result); LookupResult* result);
void LookupTransition(JSObject* holder, inline void LookupTransition(JSObject* holder,
String* name, String* name,
LookupResult* result); LookupResult* result);
// The size of transition arrays are limited so they do not end up in large // The size of transition arrays are limited so they do not end up in large
// object space. Otherwise ClearNonLiveTransitions would leak memory while // object space. Otherwise ClearNonLiveTransitions would leak memory while
// applying in-place right trimming. // applying in-place right trimming.
inline bool CanHaveMoreTransitions(); inline bool CanHaveMoreTransitions();
void SetLastAdded(int index) { int LastAdded() {
set_bit_field3(LastAddedBits::update(bit_field3(), index)); int number_of_own_descriptors = NumberOfOwnDescriptors();
ASSERT(number_of_own_descriptors > 0);
return number_of_own_descriptors - 1;
} }
int LastAdded() { int NumberOfOwnDescriptors() {
return LastAddedBits::decode(bit_field3()); return NumberOfOwnDescriptorsBits::decode(bit_field3());
} }
int NumberOfSetDescriptors() { void SetNumberOfOwnDescriptors(int number) {
ASSERT(!instance_descriptors()->IsEmpty()); set_bit_field3(NumberOfOwnDescriptorsBits::update(bit_field3(), number));
if (LastAdded() == kNoneAdded) return 0;
return instance_descriptors()->GetDetails(LastAdded()).index();
} }
MUST_USE_RESULT MaybeObject* RawCopy(int instance_size); MUST_USE_RESULT MaybeObject* RawCopy(int instance_size);
...@@ -4918,7 +4924,6 @@ class Map: public HeapObject { ...@@ -4918,7 +4924,6 @@ class Map: public HeapObject {
MUST_USE_RESULT MaybeObject* CopyReplaceDescriptors( MUST_USE_RESULT MaybeObject* CopyReplaceDescriptors(
DescriptorArray* descriptors, DescriptorArray* descriptors,
String* name, String* name,
int last_added,
TransitionFlag flag); TransitionFlag flag);
MUST_USE_RESULT MaybeObject* CopyAddDescriptor(Descriptor* descriptor, MUST_USE_RESULT MaybeObject* CopyAddDescriptor(Descriptor* descriptor,
TransitionFlag flag); TransitionFlag flag);
...@@ -5052,9 +5057,6 @@ class Map: public HeapObject { ...@@ -5052,9 +5057,6 @@ class Map: public HeapObject {
static const int kMaxPreAllocatedPropertyFields = 255; static const int kMaxPreAllocatedPropertyFields = 255;
// Constant for denoting that the LastAdded field was not yet set.
static const int kNoneAdded = LastAddedBits::kMax;
// Layout description. // Layout description.
static const int kInstanceSizesOffset = HeapObject::kHeaderSize; static const int kInstanceSizesOffset = HeapObject::kHeaderSize;
static const int kInstanceAttributesOffset = kInstanceSizesOffset + kIntSize; static const int kInstanceAttributesOffset = kInstanceSizesOffset + kIntSize;
...@@ -5130,11 +5132,6 @@ class Map: public HeapObject { ...@@ -5130,11 +5132,6 @@ class Map: public HeapObject {
static_cast<int8_t>((FAST_HOLEY_SMI_ELEMENTS + 1) << static_cast<int8_t>((FAST_HOLEY_SMI_ELEMENTS + 1) <<
Map::kElementsKindShift) - 1; Map::kElementsKindShift) - 1;
// Bit positions for bit field 3
static const int kIsShared = 0;
static const int kFunctionWithPrototype = 1;
static const int kDictionaryMap = 2;
typedef FixedBodyDescriptor<kPointerFieldsBeginOffset, typedef FixedBodyDescriptor<kPointerFieldsBeginOffset,
kPointerFieldsEndOffset, kPointerFieldsEndOffset,
kSize> BodyDescriptor; kSize> BodyDescriptor;
......
...@@ -77,19 +77,19 @@ class PropertyDetails BASE_EMBEDDED { ...@@ -77,19 +77,19 @@ class PropertyDetails BASE_EMBEDDED {
PropertyDetails(PropertyAttributes attributes, PropertyDetails(PropertyAttributes attributes,
PropertyType type, PropertyType type,
int index = 0) { int index = 0) {
ASSERT(TypeField::is_valid(type));
ASSERT(AttributesField::is_valid(attributes));
ASSERT(StorageField::is_valid(index));
value_ = TypeField::encode(type) value_ = TypeField::encode(type)
| AttributesField::encode(attributes) | AttributesField::encode(attributes)
| StorageField::encode(index); | DictionaryStorageField::encode(index);
ASSERT(type == this->type()); ASSERT(type == this->type());
ASSERT(attributes == this->attributes()); ASSERT(attributes == this->attributes());
ASSERT(index == this->index()); ASSERT(index == this->dictionary_index());
} }
int pointer() { return DescriptorPointer::decode(value_); }
PropertyDetails set_pointer(int i) { return PropertyDetails(value_, i); }
// Conversion for storing details as Object*. // Conversion for storing details as Object*.
explicit inline PropertyDetails(Smi* smi); explicit inline PropertyDetails(Smi* smi);
inline Smi* AsSmi(); inline Smi* AsSmi();
...@@ -98,12 +98,18 @@ class PropertyDetails BASE_EMBEDDED { ...@@ -98,12 +98,18 @@ class PropertyDetails BASE_EMBEDDED {
PropertyAttributes attributes() { return AttributesField::decode(value_); } PropertyAttributes attributes() { return AttributesField::decode(value_); }
int index() { return StorageField::decode(value_); } int dictionary_index() {
return DictionaryStorageField::decode(value_);
}
int descriptor_index() {
return DescriptorStorageField::decode(value_);
}
inline PropertyDetails AsDeleted(); inline PropertyDetails AsDeleted();
static bool IsValidIndex(int index) { static bool IsValidIndex(int index) {
return StorageField::is_valid(index); return DictionaryStorageField::is_valid(index);
} }
bool IsReadOnly() { return (attributes() & READ_ONLY) != 0; } bool IsReadOnly() { return (attributes() & READ_ONLY) != 0; }
...@@ -113,14 +119,20 @@ class PropertyDetails BASE_EMBEDDED { ...@@ -113,14 +119,20 @@ class PropertyDetails BASE_EMBEDDED {
// Bit fields in value_ (type, shift, size). Must be public so the // Bit fields in value_ (type, shift, size). Must be public so the
// constants can be embedded in generated code. // constants can be embedded in generated code.
class TypeField: public BitField<PropertyType, 0, 3> {}; class TypeField: public BitField<PropertyType, 0, 3> {};
class AttributesField: public BitField<PropertyAttributes, 3, 3> {}; class AttributesField: public BitField<PropertyAttributes, 3, 3> {};
class DeletedField: public BitField<uint32_t, 6, 1> {}; class DeletedField: public BitField<uint32_t, 6, 1> {};
class StorageField: public BitField<uint32_t, 7, 32-7> {}; class DictionaryStorageField: public BitField<uint32_t, 7, 24> {};
class DescriptorStorageField: public BitField<uint32_t, 7, 11> {};
class DescriptorPointer: public BitField<uint32_t, 18, 11> {};
static const int kInitialIndex = 1; static const int kInitialIndex = 1;
private: private:
PropertyDetails(int value, int pointer) {
value_ = DescriptorPointer::update(value, pointer);
}
uint32_t value_; uint32_t value_;
}; };
......
...@@ -112,7 +112,7 @@ void Descriptor::Print(FILE* out) { ...@@ -112,7 +112,7 @@ void Descriptor::Print(FILE* out) {
GetKey()->ShortPrint(out); GetKey()->ShortPrint(out);
PrintF(out, " @ "); PrintF(out, " @ ");
GetValue()->ShortPrint(out); GetValue()->ShortPrint(out);
PrintF(out, " %d\n", GetDetails().index()); PrintF(out, " %d\n", GetDetails().descriptor_index());
} }
......
...@@ -65,10 +65,11 @@ class Descriptor BASE_EMBEDDED { ...@@ -65,10 +65,11 @@ class Descriptor BASE_EMBEDDED {
#endif #endif
void SetEnumerationIndex(int index) { void SetEnumerationIndex(int index) {
ASSERT(PropertyDetails::IsValidIndex(index));
details_ = PropertyDetails(details_.attributes(), details_.type(), index); details_ = PropertyDetails(details_.attributes(), details_.type(), index);
} }
void SetSortedKey(int index) { details_ = details_.set_pointer(index); }
private: private:
String* key_; String* key_;
Object* value_; Object* value_;
......
...@@ -2166,14 +2166,14 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetReadOnlyPrototype) { ...@@ -2166,14 +2166,14 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetReadOnlyPrototype) {
// Construct a new field descriptor with updated attributes. // Construct a new field descriptor with updated attributes.
DescriptorArray* instance_desc = function->map()->instance_descriptors(); DescriptorArray* instance_desc = function->map()->instance_descriptors();
int index = instance_desc->Search(name); int index = instance_desc->SearchWithCache(name);
ASSERT(index != DescriptorArray::kNotFound); ASSERT(index != DescriptorArray::kNotFound);
PropertyDetails details = instance_desc->GetDetails(index); PropertyDetails details = instance_desc->GetDetails(index);
CallbacksDescriptor new_desc(name, CallbacksDescriptor new_desc(name,
instance_desc->GetValue(index), instance_desc->GetValue(index),
static_cast<PropertyAttributes>(details.attributes() | READ_ONLY), static_cast<PropertyAttributes>(details.attributes() | READ_ONLY),
details.index()); details.descriptor_index());
// Create a new map featuring the new field descriptors array. // Create a new map featuring the new field descriptors array.
Map* new_map; Map* new_map;
...@@ -2191,7 +2191,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetReadOnlyPrototype) { ...@@ -2191,7 +2191,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetReadOnlyPrototype) {
PropertyDetails new_details( PropertyDetails new_details(
static_cast<PropertyAttributes>(details.attributes() | READ_ONLY), static_cast<PropertyAttributes>(details.attributes() | READ_ONLY),
details.type(), details.type(),
details.index()); details.dictionary_index());
function->property_dictionary()->DetailsAtPut(entry, new_details); function->property_dictionary()->DetailsAtPut(entry, new_details);
} }
return function; return function;
...@@ -10530,7 +10530,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPropertyAttributesFromDetails) { ...@@ -10530,7 +10530,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPropertyAttributesFromDetails) {
RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPropertyIndexFromDetails) { RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPropertyIndexFromDetails) {
ASSERT(args.length() == 1); ASSERT(args.length() == 1);
CONVERT_PROPERTY_DETAILS_CHECKED(details, 0); CONVERT_PROPERTY_DETAILS_CHECKED(details, 0);
return Smi::FromInt(details.index()); // TODO(verwaest): Depends on the type of details.
return Smi::FromInt(details.dictionary_index());
} }
......
...@@ -187,7 +187,6 @@ PropertyDetails TransitionArray::GetTargetDetails(int transition_number) { ...@@ -187,7 +187,6 @@ PropertyDetails TransitionArray::GetTargetDetails(int transition_number) {
Map* map = GetTarget(transition_number); Map* map = GetTarget(transition_number);
DescriptorArray* descriptors = map->instance_descriptors(); DescriptorArray* descriptors = map->instance_descriptors();
int descriptor = map->LastAdded(); int descriptor = map->LastAdded();
ASSERT(descriptor != Map::kNoneAdded);
return descriptors->GetDetails(descriptor); return descriptors->GetDetails(descriptor);
} }
......
...@@ -53,6 +53,11 @@ class TransitionArray: public FixedArray { ...@@ -53,6 +53,11 @@ class TransitionArray: public FixedArray {
inline String* GetKey(int transition_number); inline String* GetKey(int transition_number);
inline void SetKey(int transition_number, String* value); inline void SetKey(int transition_number, String* value);
inline Object** GetKeySlot(int transition_number); inline Object** GetKeySlot(int transition_number);
int GetSortedKeyIndex(int transition_number) { return transition_number; }
String* GetSortedKey(int transition_number) {
return GetKey(transition_number);
}
inline Map* GetTarget(int transition_number); inline Map* GetTarget(int transition_number);
inline void SetTarget(int transition_number, Map* target); inline void SetTarget(int transition_number, Map* target);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment