Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(89)

Side by Side Diff: src/objects.cc

Issue 10816005: Swapped transition array and descriptor array. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: u Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 2173 matching lines...) Expand 10 before | Expand all | Expand 10 after
2184 // Copy the descriptors from the array. 2184 // Copy the descriptors from the array.
2185 if (0 < descriptor_count) { 2185 if (0 < descriptor_count) {
2186 for (int i = 0; i < descriptor_count; i++) { 2186 for (int i = 0; i < descriptor_count; i++) {
2187 result->CopyFrom(i, *array, i, witness); 2187 result->CopyFrom(i, *array, i, witness);
2188 } 2188 }
2189 } 2189 }
2190 2190
2191 // After this point the GC is not allowed to run anymore until the map is in a 2191 // After this point the GC is not allowed to run anymore until the map is in a
2192 // consistent state again, i.e., all the descriptors are appended and the 2192 // consistent state again, i.e., all the descriptors are appended and the
2193 // descriptor array is trimmed to the right size. 2193 // descriptor array is trimmed to the right size.
2194 map->set_instance_descriptors(*result); 2194 isolate->factory()->SetDescriptors(map, result);
2195 2195
2196 // Fill in new callback descriptors. Process the callbacks from 2196 // Fill in new callback descriptors. Process the callbacks from
2197 // back to front so that the last callback with a given name takes 2197 // back to front so that the last callback with a given name takes
2198 // precedence over previously added callbacks with that name. 2198 // precedence over previously added callbacks with that name.
2199 for (int i = nof_callbacks - 1; i >= 0; i--) { 2199 for (int i = nof_callbacks - 1; i >= 0; i--) {
2200 AccessorInfo* entry = AccessorInfo::cast(callbacks.get(i)); 2200 AccessorInfo* entry = AccessorInfo::cast(callbacks.get(i));
2201 String* key = String::cast(entry->name()); 2201 String* key = String::cast(entry->name());
2202 // Check if a descriptor with this name already exists before writing. 2202 // Check if a descriptor with this name already exists before writing.
2203 if (LinearSearch(*result, key, map->NumberOfSetDescriptors()) == 2203 if (LinearSearch(*result, key, map->NumberOfSetDescriptors()) ==
2204 DescriptorArray::kNotFound) { 2204 DescriptorArray::kNotFound) {
2205 CallbacksDescriptor desc(key, entry, entry->property_attributes()); 2205 CallbacksDescriptor desc(key, entry, entry->property_attributes());
2206 map->AppendDescriptor(&desc, witness); 2206 map->AppendDescriptor(&desc, witness);
2207 } 2207 }
2208 } 2208 }
2209 2209
2210 int new_number_of_descriptors = map->NumberOfSetDescriptors(); 2210 int new_number_of_descriptors = map->NumberOfSetDescriptors();
2211 // Reinstall the original descriptor array if no new elements were added. 2211 // Reinstall the original descriptor array if no new elements were added.
2212 if (new_number_of_descriptors == descriptor_count) { 2212 if (new_number_of_descriptors == descriptor_count) {
2213 map->set_instance_descriptors(*array); 2213 isolate->factory()->SetDescriptors(map, array);
2214 return; 2214 return;
2215 } 2215 }
2216 2216
2217 // If duplicates were detected, trim the descriptor array to the right size. 2217 // If duplicates were detected, trim the descriptor array to the right size.
2218 int new_array_size = DescriptorArray::LengthFor(new_number_of_descriptors); 2218 int new_array_size = DescriptorArray::LengthFor(new_number_of_descriptors);
2219 if (new_array_size < result->length()) { 2219 if (new_array_size < result->length()) {
2220 RightTrimFixedArray<FROM_MUTATOR>( 2220 RightTrimFixedArray<FROM_MUTATOR>(
2221 isolate->heap(), *result, result->length() - new_array_size); 2221 isolate->heap(), *result, result->length() - new_array_size);
2222 } 2222 }
2223 } 2223 }
(...skipping 1871 matching lines...) Expand 10 before | Expand all | Expand 10 after
4095 { MaybeObject* maybe = NormalizeElements(); 4095 { MaybeObject* maybe = NormalizeElements();
4096 if (!maybe->To<SeededNumberDictionary>(&dictionary)) return maybe; 4096 if (!maybe->To<SeededNumberDictionary>(&dictionary)) return maybe;
4097 } 4097 }
4098 ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements()); 4098 ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements());
4099 // Make sure that we never go back to fast case. 4099 // Make sure that we never go back to fast case.
4100 dictionary->set_requires_slow_elements(); 4100 dictionary->set_requires_slow_elements();
4101 4101
4102 // Do a map transition, other objects with this map may still 4102 // Do a map transition, other objects with this map may still
4103 // be extensible. 4103 // be extensible.
4104 Map* new_map; 4104 Map* new_map;
4105 MaybeObject* maybe = map()->Copy(DescriptorArray::MAY_BE_SHARED); 4105 MaybeObject* maybe = map()->Copy();
4106 if (!maybe->To(&new_map)) return maybe; 4106 if (!maybe->To(&new_map)) return maybe;
4107 4107
4108 new_map->set_is_extensible(false); 4108 new_map->set_is_extensible(false);
4109 set_map(new_map); 4109 set_map(new_map);
4110 ASSERT(!map()->is_extensible()); 4110 ASSERT(!map()->is_extensible());
4111 return new_map; 4111 return new_map;
4112 } 4112 }
4113 4113
4114 4114
4115 // Tests for the fast common case for property enumeration: 4115 // Tests for the fast common case for property enumeration:
(...skipping 754 matching lines...) Expand 10 before | Expand all | Expand 10 after
4870 TransitionFlag flag) { 4870 TransitionFlag flag) {
4871 Map* result; 4871 Map* result;
4872 MaybeObject* maybe_result = CopyDropDescriptors(); 4872 MaybeObject* maybe_result = CopyDropDescriptors();
4873 if (!maybe_result->To(&result)) return maybe_result; 4873 if (!maybe_result->To(&result)) return maybe_result;
4874 4874
4875 if (last_added == kNoneAdded) { 4875 if (last_added == kNoneAdded) {
4876 ASSERT(descriptors->number_of_descriptors() == 0); 4876 ASSERT(descriptors->number_of_descriptors() == 0);
4877 } else { 4877 } else {
4878 ASSERT(descriptors->GetDetails(last_added).index() == 4878 ASSERT(descriptors->GetDetails(last_added).index() ==
4879 descriptors->number_of_descriptors()); 4879 descriptors->number_of_descriptors());
4880 result->set_instance_descriptors(descriptors); 4880 MaybeObject* maybe_failure = result->SetDescriptors(descriptors);
4881 if (maybe_failure->IsFailure()) return maybe_failure;
4881 result->SetLastAdded(last_added); 4882 result->SetLastAdded(last_added);
4882 } 4883 }
4883 4884
4884 if (flag == INSERT_TRANSITION && CanHaveMoreTransitions()) { 4885 if (flag == INSERT_TRANSITION && CanHaveMoreTransitions()) {
4885 TransitionArray* transitions; 4886 TransitionArray* transitions;
4886 MaybeObject* maybe_transitions = AddTransition(name, result); 4887 MaybeObject* maybe_transitions = AddTransition(name, result);
4887 if (!maybe_transitions->To(&transitions)) return maybe_transitions; 4888 if (!maybe_transitions->To(&transitions)) return maybe_transitions;
4888 4889
4889 MaybeObject* maybe_set = set_transitions(transitions); 4890 set_transitions(transitions);
4890 if (maybe_set->IsFailure()) return maybe_set;
4891
4892 result->SetBackPointer(this); 4891 result->SetBackPointer(this);
4893 } 4892 }
4894 4893
4895 return result; 4894 return result;
4896 } 4895 }
4897 4896
4898 4897
4899 MaybeObject* Map::CopyAsElementsKind(ElementsKind kind, TransitionFlag flag) { 4898 MaybeObject* Map::CopyAsElementsKind(ElementsKind kind, TransitionFlag flag) {
4900 // Create a new free-floating map only if we are not allowed to store it. 4899 // Create a new free-floating map only if we are not allowed to store it.
4901 Map* new_map = NULL; 4900 Map* new_map = NULL;
4902 MaybeObject* maybe_new_map = Copy(DescriptorArray::MAY_BE_SHARED); 4901 MaybeObject* maybe_new_map = Copy();
4903 if (!maybe_new_map->To(&new_map)) return maybe_new_map; 4902 if (!maybe_new_map->To(&new_map)) return maybe_new_map;
4904 new_map->set_elements_kind(kind); 4903 new_map->set_elements_kind(kind);
4905 4904
4906 if (flag == INSERT_TRANSITION) { 4905 if (flag == INSERT_TRANSITION) {
4907 ASSERT(!HasElementsTransition() || 4906 ASSERT(!HasElementsTransition() ||
4908 ((elements_transition_map()->elements_kind() == DICTIONARY_ELEMENTS || 4907 ((elements_transition_map()->elements_kind() == DICTIONARY_ELEMENTS ||
4909 IsExternalArrayElementsKind( 4908 IsExternalArrayElementsKind(
4910 elements_transition_map()->elements_kind())) && 4909 elements_transition_map()->elements_kind())) &&
4911 (kind == DICTIONARY_ELEMENTS || 4910 (kind == DICTIONARY_ELEMENTS ||
4912 IsExternalArrayElementsKind(kind)))); 4911 IsExternalArrayElementsKind(kind))));
(...skipping 11 matching lines...) Expand all
4924 } 4923 }
4925 4924
4926 4925
4927 MaybeObject* Map::CopyWithPreallocatedFieldDescriptors() { 4926 MaybeObject* Map::CopyWithPreallocatedFieldDescriptors() {
4928 if (pre_allocated_property_fields() == 0) return CopyDropDescriptors(); 4927 if (pre_allocated_property_fields() == 0) return CopyDropDescriptors();
4929 4928
4930 // If the map has pre-allocated properties always start out with a descriptor 4929 // If the map has pre-allocated properties always start out with a descriptor
4931 // array describing these properties. 4930 // array describing these properties.
4932 ASSERT(constructor()->IsJSFunction()); 4931 ASSERT(constructor()->IsJSFunction());
4933 JSFunction* ctor = JSFunction::cast(constructor()); 4932 JSFunction* ctor = JSFunction::cast(constructor());
4934 Map* initial_map = ctor->initial_map(); 4933 Map* map = ctor->initial_map();
4935 DescriptorArray* initial_descriptors = initial_map->instance_descriptors(); 4934 DescriptorArray* descriptors = map->instance_descriptors();
4936 DescriptorArray* descriptors;
4937 MaybeObject* maybe_descriptors =
4938 initial_descriptors->Copy(DescriptorArray::MAY_BE_SHARED);
4939 if (!maybe_descriptors->To(&descriptors)) return maybe_descriptors;
4940 4935
4941 int last_added = initial_map->LastAdded(); 4936 int last_added = map->LastAdded();
4942 4937
4943 return CopyReplaceDescriptors(descriptors, NULL, last_added, OMIT_TRANSITION); 4938 return CopyReplaceDescriptors(descriptors, NULL, last_added, OMIT_TRANSITION);
4944 } 4939 }
4945 4940
4946 4941
4947 MaybeObject* Map::Copy(DescriptorArray::SharedMode shared_mode) { 4942 MaybeObject* Map::Copy() {
4948 DescriptorArray* source_descriptors = instance_descriptors(); 4943 DescriptorArray* descriptors = instance_descriptors();
4949 DescriptorArray* descriptors;
4950 MaybeObject* maybe_descriptors = source_descriptors->Copy(shared_mode);
4951 if (!maybe_descriptors->To(&descriptors)) return maybe_descriptors;
4952
4953 int last_added = LastAdded(); 4944 int last_added = LastAdded();
4954 4945
4955 return CopyReplaceDescriptors(descriptors, NULL, last_added, OMIT_TRANSITION); 4946 return CopyReplaceDescriptors(descriptors, NULL, last_added, OMIT_TRANSITION);
4956 } 4947 }
4957 4948
4958 4949
4959 static bool InsertionPointFound(String* key1, String* key2) { 4950 static bool InsertionPointFound(String* key1, String* key2) {
4960 return key1->Hash() > key2->Hash() || key1 == key2; 4951 return key1->Hash() > key2->Hash() || key1 == key2;
4961 } 4952 }
4962 4953
4963 4954
4964 MaybeObject* Map::CopyAddDescriptor(Descriptor* descriptor, 4955 MaybeObject* Map::CopyAddDescriptor(Descriptor* descriptor,
4965 TransitionFlag flag) { 4956 TransitionFlag flag) {
4966 DescriptorArray* descriptors = instance_descriptors(); 4957 DescriptorArray* descriptors = instance_descriptors();
4967 4958
4968 // Ensure the key is a symbol. 4959 // Ensure the key is a symbol.
4969 MaybeObject* maybe_failure = descriptor->KeyToSymbol(); 4960 MaybeObject* maybe_failure = descriptor->KeyToSymbol();
4970 if (maybe_failure->IsFailure()) return maybe_failure; 4961 if (maybe_failure->IsFailure()) return maybe_failure;
4971 4962
4972 String* key = descriptor->GetKey(); 4963 String* key = descriptor->GetKey();
4973 ASSERT(descriptors->Search(key) == DescriptorArray::kNotFound); 4964 ASSERT(descriptors->Search(key) == DescriptorArray::kNotFound);
4974 4965
4975 int old_size = descriptors->number_of_descriptors(); 4966 int old_size = descriptors->number_of_descriptors();
4976 int new_size = old_size + 1; 4967 int new_size = old_size + 1;
4977 4968
4978 DescriptorArray* new_descriptors; 4969 DescriptorArray* new_descriptors;
4979 MaybeObject* maybe_descriptors = 4970 MaybeObject* maybe_descriptors = DescriptorArray::Allocate(new_size);
4980 DescriptorArray::Allocate(new_size, DescriptorArray::MAY_BE_SHARED);
4981 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; 4971 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
4982 4972
4983 FixedArray::WhitenessWitness witness(new_descriptors); 4973 FixedArray::WhitenessWitness witness(new_descriptors);
4984 4974
4985 // Copy the descriptors, inserting a descriptor. 4975 // Copy the descriptors, inserting a descriptor.
4986 int insertion_index = -1; 4976 int insertion_index = -1;
4987 int to = 0; 4977 int to = 0;
4988 for (int from = 0; from < old_size; ++from) { 4978 for (int from = 0; from < old_size; ++from) {
4989 if (insertion_index < 0 && 4979 if (insertion_index < 0 &&
4990 InsertionPointFound(descriptors->GetKey(from), key)) { 4980 InsertionPointFound(descriptors->GetKey(from), key)) {
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
5031 ASSERT(0 <= insertion_index && insertion_index < size); 5021 ASSERT(0 <= insertion_index && insertion_index < size);
5032 5022
5033 // Ensure the key is a symbol. 5023 // Ensure the key is a symbol.
5034 MaybeObject* maybe_failure = descriptor->KeyToSymbol(); 5024 MaybeObject* maybe_failure = descriptor->KeyToSymbol();
5035 if (maybe_failure->IsFailure()) return maybe_failure; 5025 if (maybe_failure->IsFailure()) return maybe_failure;
5036 5026
5037 String* key = descriptor->GetKey(); 5027 String* key = descriptor->GetKey();
5038 ASSERT(key == descriptors->GetKey(insertion_index)); 5028 ASSERT(key == descriptors->GetKey(insertion_index));
5039 5029
5040 DescriptorArray* new_descriptors; 5030 DescriptorArray* new_descriptors;
5041 MaybeObject* maybe_descriptors = 5031 MaybeObject* maybe_descriptors = DescriptorArray::Allocate(size);
5042 DescriptorArray::Allocate(size, DescriptorArray::MAY_BE_SHARED);
5043 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; 5032 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
5044 5033
5045 FixedArray::WhitenessWitness witness(new_descriptors); 5034 FixedArray::WhitenessWitness witness(new_descriptors);
5046 5035
5047 // Copy the descriptors, replacing a descriptor. 5036 // Copy the descriptors, replacing a descriptor.
5048 for (int index = 0; index < size; ++index) { 5037 for (int index = 0; index < size; ++index) {
5049 if (index == insertion_index) continue; 5038 if (index == insertion_index) continue;
5050 new_descriptors->CopyFrom(index, descriptors, index, witness); 5039 new_descriptors->CopyFrom(index, descriptors, index, witness);
5051 } 5040 }
5052 5041
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after
5253 IntrusivePrototypeTransitionIterator(GetPrototypeTransitions()).Start(); 5242 IntrusivePrototypeTransitionIterator(GetPrototypeTransitions()).Start();
5254 } 5243 }
5255 5244
5256 IntrusiveMapTransitionIterator(transitions()).Start(); 5245 IntrusiveMapTransitionIterator(transitions()).Start();
5257 } 5246 }
5258 } 5247 }
5259 5248
5260 // If we have an unvisited child map, return that one and advance. If we have 5249 // If we have an unvisited child map, return that one and advance. If we have
5261 // none, return NULL and reset any destroyed FixedArray maps. 5250 // none, return NULL and reset any destroyed FixedArray maps.
5262 TraversableMap* ChildIteratorNext() { 5251 TraversableMap* ChildIteratorNext() {
5263 if (HasTransitionArray()) { 5252 TransitionArray* transition_array = unchecked_transition_array();
5264 TransitionArray* transition_array = unchecked_transition_array(); 5253 if (!(*HeapObject::RawField(transition_array,
Michael Starzinger 2012/08/06 14:15:52 The HeapObject::map() method should still work her
Toon Verwaest 2012/08/07 08:33:04 Done.
5254 TransitionArray::kMapOffset))->IsSmi()) {
5255 if (!transition_array->IsTransitionArray()) return NULL;
5256 }
5265 5257
5266 if (transition_array->HasPrototypeTransitions()) { 5258 if (transition_array->HasPrototypeTransitions()) {
5267 HeapObject* proto_transitions = 5259 HeapObject* proto_transitions =
5268 transition_array->UncheckedPrototypeTransitions(); 5260 transition_array->UncheckedPrototypeTransitions();
5269 IntrusivePrototypeTransitionIterator proto_iterator(proto_transitions); 5261 IntrusivePrototypeTransitionIterator proto_iterator(proto_transitions);
5270 if (proto_iterator.IsIterating()) { 5262 if (proto_iterator.IsIterating()) {
5271 Map* next = proto_iterator.Next(); 5263 Map* next = proto_iterator.Next();
5272 if (next != NULL) return static_cast<TraversableMap*>(next);
5273 }
5274 }
5275
5276 IntrusiveMapTransitionIterator transition_iterator(transition_array);
5277 if (transition_iterator.IsIterating()) {
5278 Map* next = transition_iterator.Next();
5279 if (next != NULL) return static_cast<TraversableMap*>(next); 5264 if (next != NULL) return static_cast<TraversableMap*>(next);
5280 } 5265 }
5281 } 5266 }
5282 5267
5268 IntrusiveMapTransitionIterator transition_iterator(transition_array);
5269 if (transition_iterator.IsIterating()) {
5270 Map* next = transition_iterator.Next();
5271 if (next != NULL) return static_cast<TraversableMap*>(next);
5272 }
5273
5283 return NULL; 5274 return NULL;
5284 } 5275 }
5285 }; 5276 };
5286 5277
5287 5278
5288 // Traverse the transition tree in postorder without using the C++ stack by 5279 // Traverse the transition tree in postorder without using the C++ stack by
5289 // doing pointer reversal. 5280 // doing pointer reversal.
5290 void Map::TraverseTransitionTree(TraverseCallback callback, void* data) { 5281 void Map::TraverseTransitionTree(TraverseCallback callback, void* data) {
5291 TraversableMap* current = static_cast<TraversableMap*>(this); 5282 TraversableMap* current = static_cast<TraversableMap*>(this);
5292 current->ChildIteratorStart(); 5283 current->ChildIteratorStart();
(...skipping 529 matching lines...) Expand 10 before | Expand all | Expand 10 after
5822 bool FixedArray::IsEqualTo(FixedArray* other) { 5813 bool FixedArray::IsEqualTo(FixedArray* other) {
5823 if (length() != other->length()) return false; 5814 if (length() != other->length()) return false;
5824 for (int i = 0 ; i < length(); ++i) { 5815 for (int i = 0 ; i < length(); ++i) {
5825 if (get(i) != other->get(i)) return false; 5816 if (get(i) != other->get(i)) return false;
5826 } 5817 }
5827 return true; 5818 return true;
5828 } 5819 }
5829 #endif 5820 #endif
5830 5821
5831 5822
5832 MaybeObject* DescriptorArray::Allocate(int number_of_descriptors, 5823 MaybeObject* DescriptorArray::Allocate(int number_of_descriptors) {
5833 SharedMode shared_mode) {
5834 Heap* heap = Isolate::Current()->heap(); 5824 Heap* heap = Isolate::Current()->heap();
5835 // Do not use DescriptorArray::cast on incomplete object. 5825 // Do not use DescriptorArray::cast on incomplete object.
5836 FixedArray* result; 5826 FixedArray* result;
5837 if (number_of_descriptors == 0 && shared_mode == MAY_BE_SHARED) { 5827 if (number_of_descriptors == 0) return heap->empty_descriptor_array();
5838 return heap->empty_descriptor_array();
5839 }
5840 // Allocate the array of keys. 5828 // Allocate the array of keys.
5841 MaybeObject* maybe_array = 5829 MaybeObject* maybe_array =
5842 heap->AllocateFixedArray(LengthFor(number_of_descriptors)); 5830 heap->AllocateFixedArray(LengthFor(number_of_descriptors));
5843 if (!maybe_array->To(&result)) return maybe_array; 5831 if (!maybe_array->To(&result)) return maybe_array;
5844 5832
5845 result->set(kEnumCacheIndex, Smi::FromInt(0)); 5833 result->set(kEnumCacheIndex, Smi::FromInt(0));
5846 result->set(kTransitionsIndex, Smi::FromInt(0));
5847 return result; 5834 return result;
5848 } 5835 }
5849 5836
5850 5837
5851 void DescriptorArray::SetEnumCache(FixedArray* bridge_storage, 5838 void DescriptorArray::SetEnumCache(FixedArray* bridge_storage,
5852 FixedArray* new_cache, 5839 FixedArray* new_cache,
5853 Object* new_index_cache) { 5840 Object* new_index_cache) {
5854 ASSERT(bridge_storage->length() >= kEnumCacheBridgeLength); 5841 ASSERT(bridge_storage->length() >= kEnumCacheBridgeLength);
5855 ASSERT(new_index_cache->IsSmi() || new_index_cache->IsFixedArray()); 5842 ASSERT(new_index_cache->IsSmi() || new_index_cache->IsFixedArray());
5856 if (HasEnumCache()) { 5843 if (HasEnumCache()) {
(...skipping 16 matching lines...) Expand all
5873 DescriptorArray* src, 5860 DescriptorArray* src,
5874 int src_index, 5861 int src_index,
5875 const WhitenessWitness& witness) { 5862 const WhitenessWitness& witness) {
5876 Object* value = src->GetValue(src_index); 5863 Object* value = src->GetValue(src_index);
5877 PropertyDetails details = src->GetDetails(src_index); 5864 PropertyDetails details = src->GetDetails(src_index);
5878 Descriptor desc(src->GetKey(src_index), value, details); 5865 Descriptor desc(src->GetKey(src_index), value, details);
5879 Set(dst_index, &desc, witness); 5866 Set(dst_index, &desc, witness);
5880 } 5867 }
5881 5868
5882 5869
5883 MaybeObject* DescriptorArray::Copy(SharedMode shared_mode) {
5884 // Allocate the new descriptor array.
5885 int number_of_descriptors = this->number_of_descriptors();
5886 DescriptorArray* new_descriptors;
5887 MaybeObject* maybe_result = Allocate(number_of_descriptors, shared_mode);
5888 if (!maybe_result->To(&new_descriptors)) return maybe_result;
5889
5890 // Copy the content.
5891 if (number_of_descriptors > 0) {
5892 FixedArray::WhitenessWitness witness(new_descriptors);
5893 for (int i = 0; i < number_of_descriptors; i++) {
5894 new_descriptors->CopyFrom(i, this, i, witness);
5895 }
5896 }
5897
5898 return new_descriptors;
5899 }
5900
5901
5902 // We need the whiteness witness since sort will reshuffle the entries in the 5870 // We need the whiteness witness since sort will reshuffle the entries in the
5903 // descriptor array. If the descriptor array were to be black, the shuffling 5871 // descriptor array. If the descriptor array were to be black, the shuffling
5904 // would move a slot that was already recorded as pointing into an evacuation 5872 // would move a slot that was already recorded as pointing into an evacuation
5905 // candidate. This would result in missing updates upon evacuation. 5873 // candidate. This would result in missing updates upon evacuation.
5906 void DescriptorArray::Sort(const WhitenessWitness& witness) { 5874 void DescriptorArray::Sort(const WhitenessWitness& witness) {
5907 // In-place heap sort. 5875 // In-place heap sort.
5908 int len = number_of_descriptors(); 5876 int len = number_of_descriptors();
5909 // Bottom-up max-heap construction. 5877 // Bottom-up max-heap construction.
5910 // Index of the last node with children 5878 // Index of the last node with children
5911 const int max_parent_index = (len / 2) - 1; 5879 const int max_parent_index = (len / 2) - 1;
(...skipping 1332 matching lines...) Expand 10 before | Expand all | Expand 10 after
7244 // If there are no transitions to be cleared, return. 7212 // If there are no transitions to be cleared, return.
7245 // TODO(verwaest) Should be an assert, otherwise back pointers are not 7213 // TODO(verwaest) Should be an assert, otherwise back pointers are not
7246 // properly cleared. 7214 // properly cleared.
7247 if (transition_index == t->number_of_transitions()) return; 7215 if (transition_index == t->number_of_transitions()) return;
7248 } 7216 }
7249 7217
7250 // If the final transition array does not contain any live transitions, remove 7218 // If the final transition array does not contain any live transitions, remove
7251 // the transition array from the map. 7219 // the transition array from the map.
7252 if (transition_index == 0 && 7220 if (transition_index == 0 &&
7253 !t->HasElementsTransition() && 7221 !t->HasElementsTransition() &&
7254 !t->HasPrototypeTransitions()) { 7222 !t->HasPrototypeTransitions() &&
7223 t->descriptors()->IsEmpty()) {
7255 return ClearTransitions(heap); 7224 return ClearTransitions(heap);
7256 } 7225 }
7257 7226
7258 int trim = t->number_of_transitions() - transition_index; 7227 int trim = t->number_of_transitions() - transition_index;
7259 if (trim > 0) { 7228 if (trim > 0) {
7260 RightTrimFixedArray<FROM_GC>( 7229 RightTrimFixedArray<FROM_GC>(
7261 heap, t, trim * TransitionArray::kTransitionSize); 7230 heap, t, trim * TransitionArray::kTransitionSize);
7262 } 7231 }
7263 } 7232 }
7264 7233
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after
7485 MaybeObject* ok = JSObject::cast(value)->OptimizeAsPrototype(); 7454 MaybeObject* ok = JSObject::cast(value)->OptimizeAsPrototype();
7486 if (ok->IsFailure()) return ok; 7455 if (ok->IsFailure()) return ok;
7487 } 7456 }
7488 7457
7489 // Now some logic for the maps of the objects that are created by using this 7458 // Now some logic for the maps of the objects that are created by using this
7490 // function as a constructor. 7459 // function as a constructor.
7491 if (has_initial_map()) { 7460 if (has_initial_map()) {
7492 // If the function has allocated the initial map 7461 // If the function has allocated the initial map
7493 // replace it with a copy containing the new prototype. 7462 // replace it with a copy containing the new prototype.
7494 Map* new_map; 7463 Map* new_map;
7495 MaybeObject* maybe_new_map = 7464 MaybeObject* maybe_new_map = initial_map()->Copy();
7496 initial_map()->Copy(DescriptorArray::MAY_BE_SHARED);
7497 if (!maybe_new_map->To(&new_map)) return maybe_new_map; 7465 if (!maybe_new_map->To(&new_map)) return maybe_new_map;
7498 new_map->set_prototype(value); 7466 new_map->set_prototype(value);
7499 MaybeObject* maybe_object = set_initial_map_and_cache_transitions(new_map); 7467 MaybeObject* maybe_object = set_initial_map_and_cache_transitions(new_map);
7500 if (maybe_object->IsFailure()) return maybe_object; 7468 if (maybe_object->IsFailure()) return maybe_object;
7501 } else { 7469 } else {
7502 // Put the value in the initial map field until an initial map is 7470 // Put the value in the initial map field until an initial map is
7503 // needed. At that point, a new initial map is created and the 7471 // needed. At that point, a new initial map is created and the
7504 // prototype is put into the initial map where it belongs. 7472 // prototype is put into the initial map where it belongs.
7505 set_prototype_or_initial_map(value); 7473 set_prototype_or_initial_map(value);
7506 } 7474 }
7507 heap->ClearInstanceofCache(); 7475 heap->ClearInstanceofCache();
7508 return value; 7476 return value;
7509 } 7477 }
7510 7478
7511 7479
7512 MaybeObject* JSFunction::SetPrototype(Object* value) { 7480 MaybeObject* JSFunction::SetPrototype(Object* value) {
7513 ASSERT(should_have_prototype()); 7481 ASSERT(should_have_prototype());
7514 Object* construct_prototype = value; 7482 Object* construct_prototype = value;
7515 7483
7516 // If the value is not a JSReceiver, store the value in the map's 7484 // If the value is not a JSReceiver, store the value in the map's
7517 // constructor field so it can be accessed. Also, set the prototype 7485 // constructor field so it can be accessed. Also, set the prototype
7518 // used for constructing objects to the original object prototype. 7486 // used for constructing objects to the original object prototype.
7519 // See ECMA-262 13.2.2. 7487 // See ECMA-262 13.2.2.
7520 if (!value->IsJSReceiver()) { 7488 if (!value->IsJSReceiver()) {
7521 // Copy the map so this does not affect unrelated functions. 7489 // Copy the map so this does not affect unrelated functions.
7522 // Remove map transitions because they point to maps with a 7490 // Remove map transitions because they point to maps with a
7523 // different prototype. 7491 // different prototype.
7524 Map* new_map; 7492 Map* new_map;
7525 MaybeObject* maybe_new_map = map()->Copy(DescriptorArray::MAY_BE_SHARED); 7493 MaybeObject* maybe_new_map = map()->Copy();
7526 if (!maybe_new_map->To(&new_map)) return maybe_new_map; 7494 if (!maybe_new_map->To(&new_map)) return maybe_new_map;
7527 7495
7528 Heap* heap = new_map->GetHeap(); 7496 Heap* heap = new_map->GetHeap();
7529 set_map(new_map); 7497 set_map(new_map);
7530 new_map->set_constructor(value); 7498 new_map->set_constructor(value);
7531 new_map->set_non_instance_prototype(true); 7499 new_map->set_non_instance_prototype(true);
7532 construct_prototype = 7500 construct_prototype =
7533 heap->isolate()->context()->global_context()-> 7501 heap->isolate()->context()->global_context()->
7534 initial_object_prototype(); 7502 initial_object_prototype();
7535 } else { 7503 } else {
(...skipping 1273 matching lines...) Expand 10 before | Expand all | Expand 10 after
8809 // Nothing to do if prototype is already set. 8777 // Nothing to do if prototype is already set.
8810 if (map->prototype() == value) return value; 8778 if (map->prototype() == value) return value;
8811 8779
8812 if (value->IsJSObject()) { 8780 if (value->IsJSObject()) {
8813 MaybeObject* ok = JSObject::cast(value)->OptimizeAsPrototype(); 8781 MaybeObject* ok = JSObject::cast(value)->OptimizeAsPrototype();
8814 if (ok->IsFailure()) return ok; 8782 if (ok->IsFailure()) return ok;
8815 } 8783 }
8816 8784
8817 Map* new_map = map->GetPrototypeTransition(value); 8785 Map* new_map = map->GetPrototypeTransition(value);
8818 if (new_map == NULL) { 8786 if (new_map == NULL) {
8819 MaybeObject* maybe_new_map = map->Copy(DescriptorArray::MAY_BE_SHARED); 8787 MaybeObject* maybe_new_map = map->Copy();
8820 if (!maybe_new_map->To(&new_map)) return maybe_new_map; 8788 if (!maybe_new_map->To(&new_map)) return maybe_new_map;
8821 8789
8822 MaybeObject* maybe_new_cache = 8790 MaybeObject* maybe_new_cache =
8823 map->PutPrototypeTransition(value, new_map); 8791 map->PutPrototypeTransition(value, new_map);
8824 if (maybe_new_cache->IsFailure()) return maybe_new_cache; 8792 if (maybe_new_cache->IsFailure()) return maybe_new_cache;
8825 8793
8826 new_map->set_prototype(value); 8794 new_map->set_prototype(value);
8827 } 8795 }
8828 ASSERT(new_map->prototype() == value); 8796 ASSERT(new_map->prototype() == value);
8829 real_receiver->set_map(new_map); 8797 real_receiver->set_map(new_map);
(...skipping 3705 matching lines...) Expand 10 before | Expand all | Expand 10 after
12535 obj->set_map(new_map); 12503 obj->set_map(new_map);
12536 obj->set_properties(heap->empty_fixed_array()); 12504 obj->set_properties(heap->empty_fixed_array());
12537 // Check that it really works. 12505 // Check that it really works.
12538 ASSERT(obj->HasFastProperties()); 12506 ASSERT(obj->HasFastProperties());
12539 return obj; 12507 return obj;
12540 } 12508 }
12541 12509
12542 // Allocate the instance descriptor. 12510 // Allocate the instance descriptor.
12543 DescriptorArray* descriptors; 12511 DescriptorArray* descriptors;
12544 MaybeObject* maybe_descriptors = 12512 MaybeObject* maybe_descriptors =
12545 DescriptorArray::Allocate(instance_descriptor_length, 12513 DescriptorArray::Allocate(instance_descriptor_length);
12546 DescriptorArray::MAY_BE_SHARED);
12547 if (!maybe_descriptors->To(&descriptors)) { 12514 if (!maybe_descriptors->To(&descriptors)) {
12548 return maybe_descriptors; 12515 return maybe_descriptors;
12549 } 12516 }
12550 12517
12551 FixedArray::WhitenessWitness witness(descriptors); 12518 FixedArray::WhitenessWitness witness(descriptors);
12552 12519
12553 int number_of_allocated_fields = 12520 int number_of_allocated_fields =
12554 number_of_fields + unused_property_fields - inobject_props; 12521 number_of_fields + unused_property_fields - inobject_props;
12555 if (number_of_allocated_fields < 0) { 12522 if (number_of_allocated_fields < 0) {
12556 // There is enough inobject space for all fields (including unused). 12523 // There is enough inobject space for all fields (including unused).
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
12608 } else { 12575 } else {
12609 UNREACHABLE(); 12576 UNREACHABLE();
12610 } 12577 }
12611 ++next_descriptor; 12578 ++next_descriptor;
12612 } 12579 }
12613 } 12580 }
12614 ASSERT(current_offset == number_of_fields); 12581 ASSERT(current_offset == number_of_fields);
12615 12582
12616 descriptors->Sort(witness); 12583 descriptors->Sort(witness);
12617 12584
12585 MaybeObject* maybe_failure = new_map->InitializeDescriptors(descriptors);
12586 if (maybe_failure->IsFailure()) return maybe_failure;
12618 new_map->set_unused_property_fields(unused_property_fields); 12587 new_map->set_unused_property_fields(unused_property_fields);
12619 new_map->InitializeDescriptors(descriptors);
12620 12588
12621 // Transform the object. 12589 // Transform the object.
12622 obj->set_map(new_map); 12590 obj->set_map(new_map);
12623 12591
12624 obj->set_properties(fields); 12592 obj->set_properties(fields);
12625 ASSERT(obj->IsJSObject()); 12593 ASSERT(obj->IsJSObject());
12626 12594
12627 // Check that it really works. 12595 // Check that it really works.
12628 ASSERT(obj->HasFastProperties()); 12596 ASSERT(obj->HasFastProperties());
12629 12597
(...skipping 498 matching lines...) Expand 10 before | Expand all | Expand 10 after
13128 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); 13096 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER);
13129 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); 13097 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER);
13130 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); 13098 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER);
13131 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); 13099 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER);
13132 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); 13100 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER);
13133 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); 13101 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER);
13134 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); 13102 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER);
13135 } 13103 }
13136 13104
13137 } } // namespace v8::internal 13105 } } // namespace v8::internal
OLDNEW
« src/mark-compact.cc ('K') | « src/objects.h ('k') | src/objects-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698