Index: src/objects.cc |
diff --git a/src/objects.cc b/src/objects.cc |
index f66275a3ae46d1f802db1e313190d11a6b201698..6bd75fa2937d968a9c5e0a1c81fd5a722163c32e 100644 |
--- a/src/objects.cc |
+++ b/src/objects.cc |
@@ -4761,10 +4761,136 @@ void JSObject::TransformToFastProperties(Handle<JSObject> object, |
int unused_property_fields) { |
if (object->HasFastProperties()) return; |
ASSERT(!object->IsGlobalObject()); |
- CALL_HEAP_FUNCTION_VOID( |
- object->GetIsolate(), |
- object->property_dictionary()->TransformPropertiesToFastFor( |
- *object, unused_property_fields)); |
+ Isolate* isolate = object->GetIsolate(); |
+ Factory* factory = isolate->factory(); |
+ Handle<NameDictionary> dictionary(object->property_dictionary()); |
+ |
+ // Make sure we preserve dictionary representation if there are too many |
+ // descriptors. |
+ int number_of_elements = dictionary->NumberOfElements(); |
+ if (number_of_elements > kMaxNumberOfDescriptors) return; |
+ |
+ if (number_of_elements != dictionary->NextEnumerationIndex()) { |
+ NameDictionary::DoGenerateNewEnumerationIndices(dictionary); |
+ } |
+ |
+ int instance_descriptor_length = 0; |
+ int number_of_fields = 0; |
+ |
+ // Compute the length of the instance descriptor. |
+ int capacity = dictionary->Capacity(); |
+ for (int i = 0; i < capacity; i++) { |
+ Object* k = dictionary->KeyAt(i); |
+ if (dictionary->IsKey(k)) { |
+ Object* value = dictionary->ValueAt(i); |
+ PropertyType type = dictionary->DetailsAt(i).type(); |
+ ASSERT(type != FIELD); |
+ instance_descriptor_length++; |
+ if (type == NORMAL && !value->IsJSFunction()) { |
+ number_of_fields += 1; |
+ } |
+ } |
+ } |
+ |
+ int inobject_props = object->map()->inobject_properties(); |
+ |
+ // Allocate new map. |
+ Handle<Map> new_map = Map::CopyDropDescriptors(handle(object->map())); |
+ new_map->set_dictionary_map(false); |
+ |
+ if (instance_descriptor_length == 0) { |
+ DisallowHeapAllocation no_gc; |
+ ASSERT_LE(unused_property_fields, inobject_props); |
+ // Transform the object. |
+ new_map->set_unused_property_fields(inobject_props); |
+ object->set_map(*new_map); |
+ object->set_properties(isolate->heap()->empty_fixed_array()); |
+ // Check that it really works. |
+ ASSERT(object->HasFastProperties()); |
+ return; |
+ } |
+ |
+ // Allocate the instance descriptor. |
+ Handle<DescriptorArray> descriptors = DescriptorArray::Allocate( |
+ isolate, instance_descriptor_length); |
+ |
+ int number_of_allocated_fields = |
+ number_of_fields + unused_property_fields - inobject_props; |
+ if (number_of_allocated_fields < 0) { |
+ // There is enough inobject space for all fields (including unused). |
+ number_of_allocated_fields = 0; |
+ unused_property_fields = inobject_props - number_of_fields; |
+ } |
+ |
+ // Allocate the fixed array for the fields. |
+ Handle<FixedArray> fields = factory->NewFixedArray( |
+ number_of_allocated_fields); |
+ |
+ // Fill in the instance descriptor and the fields. |
+ int current_offset = 0; |
+ for (int i = 0; i < capacity; i++) { |
+ Object* k = dictionary->KeyAt(i); |
+ if (dictionary->IsKey(k)) { |
+ Object* value = dictionary->ValueAt(i); |
+ Handle<Name> key; |
+ if (k->IsSymbol()) { |
+ key = handle(Symbol::cast(k)); |
+ } else { |
+ // Ensure the key is a unique name before writing into the |
+ // instance descriptor. |
+ key = factory->InternalizeString(handle(String::cast(k))); |
+ } |
+ |
+ PropertyDetails details = dictionary->DetailsAt(i); |
+ int enumeration_index = details.dictionary_index(); |
+ PropertyType type = details.type(); |
+ |
+ if (value->IsJSFunction()) { |
+ ConstantDescriptor d(key, |
+ handle(value, isolate), |
+ details.attributes()); |
+ descriptors->Set(enumeration_index - 1, &d); |
+ } else if (type == NORMAL) { |
+ if (current_offset < inobject_props) { |
+ object->InObjectPropertyAtPut(current_offset, |
+ value, |
+ UPDATE_WRITE_BARRIER); |
+ } else { |
+ int offset = current_offset - inobject_props; |
+ fields->set(offset, value); |
+ } |
+ FieldDescriptor d(key, |
+ current_offset++, |
+ details.attributes(), |
+ // TODO(verwaest): value->OptimalRepresentation(); |
+ Representation::Tagged()); |
+ descriptors->Set(enumeration_index - 1, &d); |
+ } else if (type == CALLBACKS) { |
+ CallbacksDescriptor d(key, |
+ handle(value, isolate), |
+ details.attributes()); |
+ descriptors->Set(enumeration_index - 1, &d); |
+ } else { |
+ UNREACHABLE(); |
+ } |
+ } |
+ } |
+ ASSERT(current_offset == number_of_fields); |
+ |
+ descriptors->Sort(); |
+ |
+ DisallowHeapAllocation no_gc; |
+ new_map->InitializeDescriptors(*descriptors); |
+ new_map->set_unused_property_fields(unused_property_fields); |
+ |
+ // Transform the object. |
+ object->set_map(*new_map); |
+ |
+ object->set_properties(*fields); |
+ ASSERT(object->IsJSObject()); |
+ |
+ // Check that it really works. |
+ ASSERT(object->HasFastProperties()); |
} |
@@ -6830,23 +6956,17 @@ Handle<Map> Map::CopyNormalized(Handle<Map> map, |
Handle<Map> Map::CopyDropDescriptors(Handle<Map> map) { |
- CALL_HEAP_FUNCTION(map->GetIsolate(), map->CopyDropDescriptors(), Map); |
-} |
- |
- |
-MaybeObject* Map::CopyDropDescriptors() { |
- Map* result; |
- MaybeObject* maybe_result = RawCopy(instance_size()); |
- if (!maybe_result->To(&result)) return maybe_result; |
+ Handle<Map> result = RawCopy(map, map->instance_size()); |
// Please note instance_type and instance_size are set when allocated. |
- result->set_inobject_properties(inobject_properties()); |
- result->set_unused_property_fields(unused_property_fields()); |
+ result->set_inobject_properties(map->inobject_properties()); |
+ result->set_unused_property_fields(map->unused_property_fields()); |
- result->set_pre_allocated_property_fields(pre_allocated_property_fields()); |
+ result->set_pre_allocated_property_fields( |
+ map->pre_allocated_property_fields()); |
result->set_is_shared(false); |
- result->ClearCodeCache(GetHeap()); |
- NotifyLeafMapLayoutChange(); |
+ result->ClearCodeCache(map->GetHeap()); |
+ map->NotifyLeafMapLayoutChange(); |
return result; |
} |
@@ -6869,7 +6989,7 @@ Handle<Map> Map::ShareDescriptor(Handle<Map> map, |
if (descriptors->NumberOfSlackDescriptors() == 0) { |
int old_size = descriptors->number_of_descriptors(); |
if (old_size == 0) { |
- descriptors = map->GetIsolate()->factory()->NewDescriptorArray(0, 1); |
+ descriptors = DescriptorArray::Allocate(map->GetIsolate(), 0, 1); |
} else { |
Map::EnsureDescriptorSlack(map, old_size < 4 ? 1 : old_size / 2); |
descriptors = handle(map->instance_descriptors()); |
@@ -7137,7 +7257,7 @@ Handle<DescriptorArray> DescriptorArray::CopyUpToAddAttributes( |
int size = enumeration_index; |
Handle<DescriptorArray> descriptors = |
- desc->GetIsolate()->factory()->NewDescriptorArray(size, slack); |
+ DescriptorArray::Allocate(desc->GetIsolate(), size, slack); |
DescriptorArray::WhitenessWitness witness(*descriptors); |
if (attributes != NONE) { |
@@ -7996,21 +8116,20 @@ bool FixedArray::IsEqualTo(FixedArray* other) { |
#endif |
-MaybeObject* DescriptorArray::Allocate(Isolate* isolate, |
- int number_of_descriptors, |
- int slack) { |
- Heap* heap = isolate->heap(); |
+Handle<DescriptorArray> DescriptorArray::Allocate(Isolate* isolate, |
+ int number_of_descriptors, |
+ int slack) { |
+ ASSERT(0 <= number_of_descriptors); |
+ Factory* factory = isolate->factory(); |
// Do not use DescriptorArray::cast on incomplete object. |
int size = number_of_descriptors + slack; |
- if (size == 0) return heap->empty_descriptor_array(); |
- FixedArray* result; |
+ if (size == 0) return factory->empty_descriptor_array(); |
// Allocate the array of keys. |
- MaybeObject* maybe_array = heap->AllocateFixedArray(LengthFor(size)); |
- if (!maybe_array->To(&result)) return maybe_array; |
+ Handle<FixedArray> result = factory->NewFixedArray(LengthFor(size)); |
result->set(kDescriptorLengthIndex, Smi::FromInt(number_of_descriptors)); |
result->set(kEnumCacheIndex, Smi::FromInt(0)); |
- return result; |
+ return Handle<DescriptorArray>::cast(result); |
} |
@@ -8074,11 +8193,13 @@ Handle<DescriptorArray> DescriptorArray::Merge(Handle<Map> left_map, |
// Allocate a new descriptor array large enough to hold the required |
// descriptors, with minimally the exact same size as this descriptor array. |
- Factory* factory = left_map->GetIsolate()->factory(); |
+ Isolate* isolate = left_map->GetIsolate(); |
Handle<DescriptorArray> left(left_map->instance_descriptors()); |
Handle<DescriptorArray> right(right_map->instance_descriptors()); |
- Handle<DescriptorArray> result = factory->NewDescriptorArray( |
- new_size, Max(new_size, right->number_of_descriptors()) - new_size); |
+ Handle<DescriptorArray> result = DescriptorArray::Allocate( |
+ isolate, |
+ new_size, |
+ Max(new_size, right->number_of_descriptors()) - new_size); |
ASSERT(result->length() > left->length() || |
result->NumberOfSlackDescriptors() > 0 || |
result->number_of_descriptors() == right->number_of_descriptors()); |
@@ -11509,10 +11630,7 @@ Handle<Map> Map::PutPrototypeTransition(Handle<Map> map, |
Factory* factory = map->GetIsolate()->factory(); |
cache = factory->CopySizeFixedArray(cache, transitions * 2 * step + header); |
- CALL_AND_RETRY_OR_DIE(map->GetIsolate(), |
- map->SetPrototypeTransitions(*cache), |
- break, |
- return Handle<Map>()); |
+ Map::SetPrototypeTransitions(map, cache); |
} |
// Reload number of transitions as GC might shrink them. |
@@ -15591,151 +15709,6 @@ Object* Dictionary<Shape, Key>::SlowReverseLookup(Object* value) { |
} |
-MaybeObject* NameDictionary::TransformPropertiesToFastFor( |
- JSObject* obj, int unused_property_fields) { |
- // Make sure we preserve dictionary representation if there are too many |
- // descriptors. |
- int number_of_elements = NumberOfElements(); |
- if (number_of_elements > kMaxNumberOfDescriptors) return obj; |
- |
- if (number_of_elements != NextEnumerationIndex()) { |
- MaybeObject* maybe_result = GenerateNewEnumerationIndices(); |
- if (maybe_result->IsFailure()) return maybe_result; |
- } |
- |
- int instance_descriptor_length = 0; |
- int number_of_fields = 0; |
- |
- Heap* heap = GetHeap(); |
- |
- // Compute the length of the instance descriptor. |
- int capacity = Capacity(); |
- for (int i = 0; i < capacity; i++) { |
- Object* k = KeyAt(i); |
- if (IsKey(k)) { |
- Object* value = ValueAt(i); |
- PropertyType type = DetailsAt(i).type(); |
- ASSERT(type != FIELD); |
- instance_descriptor_length++; |
- if (type == NORMAL && !value->IsJSFunction()) { |
- number_of_fields += 1; |
- } |
- } |
- } |
- |
- int inobject_props = obj->map()->inobject_properties(); |
- |
- // Allocate new map. |
- Map* new_map; |
- MaybeObject* maybe_new_map = obj->map()->CopyDropDescriptors(); |
- if (!maybe_new_map->To(&new_map)) return maybe_new_map; |
- new_map->set_dictionary_map(false); |
- |
- if (instance_descriptor_length == 0) { |
- ASSERT_LE(unused_property_fields, inobject_props); |
- // Transform the object. |
- new_map->set_unused_property_fields(inobject_props); |
- obj->set_map(new_map); |
- obj->set_properties(heap->empty_fixed_array()); |
- // Check that it really works. |
- ASSERT(obj->HasFastProperties()); |
- return obj; |
- } |
- |
- // Allocate the instance descriptor. |
- DescriptorArray* descriptors; |
- MaybeObject* maybe_descriptors = |
- DescriptorArray::Allocate(GetIsolate(), instance_descriptor_length); |
- if (!maybe_descriptors->To(&descriptors)) { |
- return maybe_descriptors; |
- } |
- |
- DescriptorArray::WhitenessWitness witness(descriptors); |
- |
- int number_of_allocated_fields = |
- number_of_fields + unused_property_fields - inobject_props; |
- if (number_of_allocated_fields < 0) { |
- // There is enough inobject space for all fields (including unused). |
- number_of_allocated_fields = 0; |
- unused_property_fields = inobject_props - number_of_fields; |
- } |
- |
- // Allocate the fixed array for the fields. |
- FixedArray* fields; |
- MaybeObject* maybe_fields = |
- heap->AllocateFixedArray(number_of_allocated_fields); |
- if (!maybe_fields->To(&fields)) return maybe_fields; |
- |
- // Fill in the instance descriptor and the fields. |
- int current_offset = 0; |
- for (int i = 0; i < capacity; i++) { |
- Object* k = KeyAt(i); |
- if (IsKey(k)) { |
- Object* value = ValueAt(i); |
- Name* key; |
- if (k->IsSymbol()) { |
- key = Symbol::cast(k); |
- } else { |
- // Ensure the key is a unique name before writing into the |
- // instance descriptor. |
- MaybeObject* maybe_key = heap->InternalizeString(String::cast(k)); |
- if (!maybe_key->To(&key)) return maybe_key; |
- } |
- |
- PropertyDetails details = DetailsAt(i); |
- int enumeration_index = details.dictionary_index(); |
- PropertyType type = details.type(); |
- |
- if (value->IsJSFunction()) { |
- ConstantDescriptor d(handle(key), |
- handle(value, GetIsolate()), |
- details.attributes()); |
- descriptors->Set(enumeration_index - 1, &d, witness); |
- } else if (type == NORMAL) { |
- if (current_offset < inobject_props) { |
- obj->InObjectPropertyAtPut(current_offset, |
- value, |
- UPDATE_WRITE_BARRIER); |
- } else { |
- int offset = current_offset - inobject_props; |
- fields->set(offset, value); |
- } |
- FieldDescriptor d(handle(key), |
- current_offset++, |
- details.attributes(), |
- // TODO(verwaest): value->OptimalRepresentation(); |
- Representation::Tagged()); |
- descriptors->Set(enumeration_index - 1, &d, witness); |
- } else if (type == CALLBACKS) { |
- CallbacksDescriptor d(handle(key), |
- handle(value, GetIsolate()), |
- details.attributes()); |
- descriptors->Set(enumeration_index - 1, &d, witness); |
- } else { |
- UNREACHABLE(); |
- } |
- } |
- } |
- ASSERT(current_offset == number_of_fields); |
- |
- descriptors->Sort(); |
- |
- new_map->InitializeDescriptors(descriptors); |
- new_map->set_unused_property_fields(unused_property_fields); |
- |
- // Transform the object. |
- obj->set_map(new_map); |
- |
- obj->set_properties(fields); |
- ASSERT(obj->IsJSObject()); |
- |
- // Check that it really works. |
- ASSERT(obj->HasFastProperties()); |
- |
- return obj; |
-} |
- |
- |
Handle<ObjectHashTable> ObjectHashTable::EnsureCapacity( |
Handle<ObjectHashTable> table, |
int n, |