Index: src/objects.cc |
diff --git a/src/objects.cc b/src/objects.cc |
index 46e691a73553117cd1e4f13c40563f42706266a7..765d4d06f4e86a92a6f251f475685ef0647ae6a5 100644 |
--- a/src/objects.cc |
+++ b/src/objects.cc |
@@ -2191,7 +2191,7 @@ void Map::CopyAppendCallbackDescriptors(Handle<Map> map, |
// After this point the GC is not allowed to run anymore until the map is in a |
// consistent state again, i.e., all the descriptors are appended and the |
// descriptor array is trimmed to the right size. |
- map->set_instance_descriptors(*result); |
+ Map::SetDescriptors(map, result); |
// Fill in new callback descriptors. Process the callbacks from |
// back to front so that the last callback with a given name takes |
@@ -2210,7 +2210,7 @@ void Map::CopyAppendCallbackDescriptors(Handle<Map> map, |
int new_number_of_descriptors = map->NumberOfSetDescriptors(); |
// Reinstall the original descriptor array if no new elements were added. |
if (new_number_of_descriptors == descriptor_count) { |
- map->set_instance_descriptors(*array); |
+ Map::SetDescriptors(map, array); |
return; |
} |
@@ -4102,7 +4102,7 @@ MaybeObject* JSObject::PreventExtensions() { |
// Do a map transition, other objects with this map may still |
// be extensible. |
Map* new_map; |
- MaybeObject* maybe = map()->Copy(DescriptorArray::MAY_BE_SHARED); |
+ MaybeObject* maybe = map()->Copy(); |
if (!maybe->To(&new_map)) return maybe; |
new_map->set_is_extensible(false); |
@@ -4139,6 +4139,13 @@ bool JSReceiver::IsSimpleEnum() { |
} |
+void Map::SetDescriptors(Handle<Map> map, |
+ Handle<DescriptorArray> descriptors) { |
+ Isolate* isolate = map->GetIsolate(); |
+ CALL_HEAP_FUNCTION_VOID(isolate, map->SetDescriptors(*descriptors)); |
+} |
+ |
+ |
int Map::NumberOfDescribedProperties(PropertyAttributes filter) { |
int result = 0; |
DescriptorArray* descs = instance_descriptors(); |
@@ -4877,7 +4884,8 @@ MaybeObject* Map::CopyReplaceDescriptors(DescriptorArray* descriptors, |
} else { |
ASSERT(descriptors->GetDetails(last_added).index() == |
descriptors->number_of_descriptors()); |
- result->set_instance_descriptors(descriptors); |
+ MaybeObject* maybe_failure = result->SetDescriptors(descriptors); |
+ if (maybe_failure->IsFailure()) return maybe_failure; |
result->SetLastAdded(last_added); |
} |
@@ -4886,9 +4894,7 @@ MaybeObject* Map::CopyReplaceDescriptors(DescriptorArray* descriptors, |
MaybeObject* maybe_transitions = AddTransition(name, result); |
if (!maybe_transitions->To(&transitions)) return maybe_transitions; |
- MaybeObject* maybe_set = set_transitions(transitions); |
- if (maybe_set->IsFailure()) return maybe_set; |
- |
+ set_transitions(transitions); |
result->SetBackPointer(this); |
} |
@@ -4899,7 +4905,7 @@ MaybeObject* Map::CopyReplaceDescriptors(DescriptorArray* descriptors, |
MaybeObject* Map::CopyAsElementsKind(ElementsKind kind, TransitionFlag flag) { |
// Create a new free-floating map only if we are not allowed to store it. |
Map* new_map = NULL; |
- MaybeObject* maybe_new_map = Copy(DescriptorArray::MAY_BE_SHARED); |
+ MaybeObject* maybe_new_map = Copy(); |
if (!maybe_new_map->To(&new_map)) return maybe_new_map; |
new_map->set_elements_kind(kind); |
@@ -4931,25 +4937,17 @@ MaybeObject* Map::CopyWithPreallocatedFieldDescriptors() { |
// array describing these properties. |
ASSERT(constructor()->IsJSFunction()); |
JSFunction* ctor = JSFunction::cast(constructor()); |
- Map* initial_map = ctor->initial_map(); |
- DescriptorArray* initial_descriptors = initial_map->instance_descriptors(); |
- DescriptorArray* descriptors; |
- MaybeObject* maybe_descriptors = |
- initial_descriptors->Copy(DescriptorArray::MAY_BE_SHARED); |
- if (!maybe_descriptors->To(&descriptors)) return maybe_descriptors; |
+ Map* map = ctor->initial_map(); |
+ DescriptorArray* descriptors = map->instance_descriptors(); |
- int last_added = initial_map->LastAdded(); |
+ int last_added = map->LastAdded(); |
return CopyReplaceDescriptors(descriptors, NULL, last_added, OMIT_TRANSITION); |
} |
-MaybeObject* Map::Copy(DescriptorArray::SharedMode shared_mode) { |
- DescriptorArray* source_descriptors = instance_descriptors(); |
- DescriptorArray* descriptors; |
- MaybeObject* maybe_descriptors = source_descriptors->Copy(shared_mode); |
- if (!maybe_descriptors->To(&descriptors)) return maybe_descriptors; |
- |
+MaybeObject* Map::Copy() { |
+ DescriptorArray* descriptors = instance_descriptors(); |
int last_added = LastAdded(); |
return CopyReplaceDescriptors(descriptors, NULL, last_added, OMIT_TRANSITION); |
@@ -4976,8 +4974,7 @@ MaybeObject* Map::CopyAddDescriptor(Descriptor* descriptor, |
int new_size = old_size + 1; |
DescriptorArray* new_descriptors; |
- MaybeObject* maybe_descriptors = |
- DescriptorArray::Allocate(new_size, DescriptorArray::MAY_BE_SHARED); |
+ MaybeObject* maybe_descriptors = DescriptorArray::Allocate(new_size); |
if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; |
FixedArray::WhitenessWitness witness(new_descriptors); |
@@ -5038,8 +5035,7 @@ MaybeObject* Map::CopyReplaceDescriptor(Descriptor* descriptor, |
ASSERT(key == descriptors->GetKey(insertion_index)); |
DescriptorArray* new_descriptors; |
- MaybeObject* maybe_descriptors = |
- DescriptorArray::Allocate(size, DescriptorArray::MAY_BE_SHARED); |
+ MaybeObject* maybe_descriptors = DescriptorArray::Allocate(size); |
if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; |
FixedArray::WhitenessWitness witness(new_descriptors); |
@@ -5260,26 +5256,28 @@ class TraversableMap : public Map { |
// If we have an unvisited child map, return that one and advance. If we have |
// none, return NULL and reset any destroyed FixedArray maps. |
TraversableMap* ChildIteratorNext() { |
- if (HasTransitionArray()) { |
- TransitionArray* transition_array = unchecked_transition_array(); |
- |
- if (transition_array->HasPrototypeTransitions()) { |
- HeapObject* proto_transitions = |
- transition_array->UncheckedPrototypeTransitions(); |
- IntrusivePrototypeTransitionIterator proto_iterator(proto_transitions); |
- if (proto_iterator.IsIterating()) { |
- Map* next = proto_iterator.Next(); |
- if (next != NULL) return static_cast<TraversableMap*>(next); |
- } |
- } |
+ TransitionArray* transition_array = unchecked_transition_array(); |
+ if (!transition_array->map()->IsSmi() && |
+ !transition_array->IsTransitionArray()) { |
+ return NULL; |
+ } |
- IntrusiveMapTransitionIterator transition_iterator(transition_array); |
- if (transition_iterator.IsIterating()) { |
- Map* next = transition_iterator.Next(); |
+ if (transition_array->HasPrototypeTransitions()) { |
+ HeapObject* proto_transitions = |
+ transition_array->UncheckedPrototypeTransitions(); |
+ IntrusivePrototypeTransitionIterator proto_iterator(proto_transitions); |
+ if (proto_iterator.IsIterating()) { |
+ Map* next = proto_iterator.Next(); |
if (next != NULL) return static_cast<TraversableMap*>(next); |
} |
} |
+ IntrusiveMapTransitionIterator transition_iterator(transition_array); |
+ if (transition_iterator.IsIterating()) { |
+ Map* next = transition_iterator.Next(); |
+ if (next != NULL) return static_cast<TraversableMap*>(next); |
+ } |
+ |
return NULL; |
} |
}; |
@@ -5829,21 +5827,17 @@ bool FixedArray::IsEqualTo(FixedArray* other) { |
#endif |
-MaybeObject* DescriptorArray::Allocate(int number_of_descriptors, |
- SharedMode shared_mode) { |
+MaybeObject* DescriptorArray::Allocate(int number_of_descriptors) { |
Heap* heap = Isolate::Current()->heap(); |
// Do not use DescriptorArray::cast on incomplete object. |
FixedArray* result; |
- if (number_of_descriptors == 0 && shared_mode == MAY_BE_SHARED) { |
- return heap->empty_descriptor_array(); |
- } |
+ if (number_of_descriptors == 0) return heap->empty_descriptor_array(); |
// Allocate the array of keys. |
MaybeObject* maybe_array = |
heap->AllocateFixedArray(LengthFor(number_of_descriptors)); |
if (!maybe_array->To(&result)) return maybe_array; |
result->set(kEnumCacheIndex, Smi::FromInt(0)); |
- result->set(kTransitionsIndex, Smi::FromInt(0)); |
return result; |
} |
@@ -5880,25 +5874,6 @@ void DescriptorArray::CopyFrom(int dst_index, |
} |
-MaybeObject* DescriptorArray::Copy(SharedMode shared_mode) { |
- // Allocate the new descriptor array. |
- int number_of_descriptors = this->number_of_descriptors(); |
- DescriptorArray* new_descriptors; |
- MaybeObject* maybe_result = Allocate(number_of_descriptors, shared_mode); |
- if (!maybe_result->To(&new_descriptors)) return maybe_result; |
- |
- // Copy the content. |
- if (number_of_descriptors > 0) { |
- FixedArray::WhitenessWitness witness(new_descriptors); |
- for (int i = 0; i < number_of_descriptors; i++) { |
- new_descriptors->CopyFrom(i, this, i, witness); |
- } |
- } |
- |
- return new_descriptors; |
-} |
- |
- |
// We need the whiteness witness since sort will reshuffle the entries in the |
// descriptor array. If the descriptor array were to be black, the shuffling |
// would move a slot that was already recorded as pointing into an evacuation |
@@ -7251,7 +7226,8 @@ void Map::ClearNonLiveTransitions(Heap* heap) { |
// the transition array from the map. |
if (transition_index == 0 && |
!t->HasElementsTransition() && |
- !t->HasPrototypeTransitions()) { |
+ !t->HasPrototypeTransitions() && |
+ t->descriptors()->IsEmpty()) { |
return ClearTransitions(heap); |
} |
@@ -7492,8 +7468,7 @@ MaybeObject* JSFunction::SetInstancePrototype(Object* value) { |
// If the function has allocated the initial map |
// replace it with a copy containing the new prototype. |
Map* new_map; |
- MaybeObject* maybe_new_map = |
- initial_map()->Copy(DescriptorArray::MAY_BE_SHARED); |
+ MaybeObject* maybe_new_map = initial_map()->Copy(); |
if (!maybe_new_map->To(&new_map)) return maybe_new_map; |
new_map->set_prototype(value); |
MaybeObject* maybe_object = set_initial_map_and_cache_transitions(new_map); |
@@ -7522,7 +7497,7 @@ MaybeObject* JSFunction::SetPrototype(Object* value) { |
// Remove map transitions because they point to maps with a |
// different prototype. |
Map* new_map; |
- MaybeObject* maybe_new_map = map()->Copy(DescriptorArray::MAY_BE_SHARED); |
+ MaybeObject* maybe_new_map = map()->Copy(); |
if (!maybe_new_map->To(&new_map)) return maybe_new_map; |
Heap* heap = new_map->GetHeap(); |
@@ -8816,7 +8791,7 @@ MaybeObject* JSReceiver::SetPrototype(Object* value, |
Map* new_map = map->GetPrototypeTransition(value); |
if (new_map == NULL) { |
- MaybeObject* maybe_new_map = map->Copy(DescriptorArray::MAY_BE_SHARED); |
+ MaybeObject* maybe_new_map = map->Copy(); |
if (!maybe_new_map->To(&new_map)) return maybe_new_map; |
MaybeObject* maybe_new_cache = |
@@ -12542,8 +12517,7 @@ MaybeObject* StringDictionary::TransformPropertiesToFastFor( |
// Allocate the instance descriptor. |
DescriptorArray* descriptors; |
MaybeObject* maybe_descriptors = |
- DescriptorArray::Allocate(instance_descriptor_length, |
- DescriptorArray::MAY_BE_SHARED); |
+ DescriptorArray::Allocate(instance_descriptor_length); |
if (!maybe_descriptors->To(&descriptors)) { |
return maybe_descriptors; |
} |
@@ -12615,8 +12589,9 @@ MaybeObject* StringDictionary::TransformPropertiesToFastFor( |
descriptors->Sort(witness); |
+ MaybeObject* maybe_failure = new_map->InitializeDescriptors(descriptors); |
+ if (maybe_failure->IsFailure()) return maybe_failure; |
new_map->set_unused_property_fields(unused_property_fields); |
- new_map->InitializeDescriptors(descriptors); |
// Transform the object. |
obj->set_map(new_map); |