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

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: Addressed comments, and updated additional code comments. 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 Map::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 Map::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 16 matching lines...) Expand all
4132 if (curr != this) { 4132 if (curr != this) {
4133 FixedArray* curr_fixed_array = 4133 FixedArray* curr_fixed_array =
4134 FixedArray::cast(curr->map()->instance_descriptors()->GetEnumCache()); 4134 FixedArray::cast(curr->map()->instance_descriptors()->GetEnumCache());
4135 if (curr_fixed_array->length() > 0) return false; 4135 if (curr_fixed_array->length() > 0) return false;
4136 } 4136 }
4137 } 4137 }
4138 return true; 4138 return true;
4139 } 4139 }
4140 4140
4141 4141
4142 void Map::SetDescriptors(Handle<Map> map,
4143 Handle<DescriptorArray> descriptors) {
4144 Isolate* isolate = map->GetIsolate();
4145 CALL_HEAP_FUNCTION_VOID(isolate, map->SetDescriptors(*descriptors));
4146 }
4147
4148
4142 int Map::NumberOfDescribedProperties(PropertyAttributes filter) { 4149 int Map::NumberOfDescribedProperties(PropertyAttributes filter) {
4143 int result = 0; 4150 int result = 0;
4144 DescriptorArray* descs = instance_descriptors(); 4151 DescriptorArray* descs = instance_descriptors();
4145 for (int i = 0; i < descs->number_of_descriptors(); i++) { 4152 for (int i = 0; i < descs->number_of_descriptors(); i++) {
4146 PropertyDetails details = descs->GetDetails(i); 4153 PropertyDetails details = descs->GetDetails(i);
4147 if ((details.attributes() & filter) == 0) { 4154 if ((details.attributes() & filter) == 0) {
4148 result++; 4155 result++;
4149 } 4156 }
4150 } 4157 }
4151 return result; 4158 return result;
(...skipping 718 matching lines...) Expand 10 before | Expand all | Expand 10 after
4870 TransitionFlag flag) { 4877 TransitionFlag flag) {
4871 Map* result; 4878 Map* result;
4872 MaybeObject* maybe_result = CopyDropDescriptors(); 4879 MaybeObject* maybe_result = CopyDropDescriptors();
4873 if (!maybe_result->To(&result)) return maybe_result; 4880 if (!maybe_result->To(&result)) return maybe_result;
4874 4881
4875 if (last_added == kNoneAdded) { 4882 if (last_added == kNoneAdded) {
4876 ASSERT(descriptors->number_of_descriptors() == 0); 4883 ASSERT(descriptors->number_of_descriptors() == 0);
4877 } else { 4884 } else {
4878 ASSERT(descriptors->GetDetails(last_added).index() == 4885 ASSERT(descriptors->GetDetails(last_added).index() ==
4879 descriptors->number_of_descriptors()); 4886 descriptors->number_of_descriptors());
4880 result->set_instance_descriptors(descriptors); 4887 MaybeObject* maybe_failure = result->SetDescriptors(descriptors);
4888 if (maybe_failure->IsFailure()) return maybe_failure;
4881 result->SetLastAdded(last_added); 4889 result->SetLastAdded(last_added);
4882 } 4890 }
4883 4891
4884 if (flag == INSERT_TRANSITION && CanHaveMoreTransitions()) { 4892 if (flag == INSERT_TRANSITION && CanHaveMoreTransitions()) {
4885 TransitionArray* transitions; 4893 TransitionArray* transitions;
4886 MaybeObject* maybe_transitions = AddTransition(name, result); 4894 MaybeObject* maybe_transitions = AddTransition(name, result);
4887 if (!maybe_transitions->To(&transitions)) return maybe_transitions; 4895 if (!maybe_transitions->To(&transitions)) return maybe_transitions;
4888 4896
4889 MaybeObject* maybe_set = set_transitions(transitions); 4897 set_transitions(transitions);
4890 if (maybe_set->IsFailure()) return maybe_set;
4891
4892 result->SetBackPointer(this); 4898 result->SetBackPointer(this);
4893 } 4899 }
4894 4900
4895 return result; 4901 return result;
4896 } 4902 }
4897 4903
4898 4904
4899 MaybeObject* Map::CopyAsElementsKind(ElementsKind kind, TransitionFlag flag) { 4905 MaybeObject* Map::CopyAsElementsKind(ElementsKind kind, TransitionFlag flag) {
4900 // Create a new free-floating map only if we are not allowed to store it. 4906 // Create a new free-floating map only if we are not allowed to store it.
4901 Map* new_map = NULL; 4907 Map* new_map = NULL;
4902 MaybeObject* maybe_new_map = Copy(DescriptorArray::MAY_BE_SHARED); 4908 MaybeObject* maybe_new_map = Copy();
4903 if (!maybe_new_map->To(&new_map)) return maybe_new_map; 4909 if (!maybe_new_map->To(&new_map)) return maybe_new_map;
4904 new_map->set_elements_kind(kind); 4910 new_map->set_elements_kind(kind);
4905 4911
4906 if (flag == INSERT_TRANSITION) { 4912 if (flag == INSERT_TRANSITION) {
4907 ASSERT(!HasElementsTransition() || 4913 ASSERT(!HasElementsTransition() ||
4908 ((elements_transition_map()->elements_kind() == DICTIONARY_ELEMENTS || 4914 ((elements_transition_map()->elements_kind() == DICTIONARY_ELEMENTS ||
4909 IsExternalArrayElementsKind( 4915 IsExternalArrayElementsKind(
4910 elements_transition_map()->elements_kind())) && 4916 elements_transition_map()->elements_kind())) &&
4911 (kind == DICTIONARY_ELEMENTS || 4917 (kind == DICTIONARY_ELEMENTS ||
4912 IsExternalArrayElementsKind(kind)))); 4918 IsExternalArrayElementsKind(kind))));
(...skipping 11 matching lines...) Expand all
4924 } 4930 }
4925 4931
4926 4932
4927 MaybeObject* Map::CopyWithPreallocatedFieldDescriptors() { 4933 MaybeObject* Map::CopyWithPreallocatedFieldDescriptors() {
4928 if (pre_allocated_property_fields() == 0) return CopyDropDescriptors(); 4934 if (pre_allocated_property_fields() == 0) return CopyDropDescriptors();
4929 4935
4930 // If the map has pre-allocated properties always start out with a descriptor 4936 // If the map has pre-allocated properties always start out with a descriptor
4931 // array describing these properties. 4937 // array describing these properties.
4932 ASSERT(constructor()->IsJSFunction()); 4938 ASSERT(constructor()->IsJSFunction());
4933 JSFunction* ctor = JSFunction::cast(constructor()); 4939 JSFunction* ctor = JSFunction::cast(constructor());
4934 Map* initial_map = ctor->initial_map(); 4940 Map* map = ctor->initial_map();
4935 DescriptorArray* initial_descriptors = initial_map->instance_descriptors(); 4941 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 4942
4941 int last_added = initial_map->LastAdded(); 4943 int last_added = map->LastAdded();
4942 4944
4943 return CopyReplaceDescriptors(descriptors, NULL, last_added, OMIT_TRANSITION); 4945 return CopyReplaceDescriptors(descriptors, NULL, last_added, OMIT_TRANSITION);
4944 } 4946 }
4945 4947
4946 4948
4947 MaybeObject* Map::Copy(DescriptorArray::SharedMode shared_mode) { 4949 MaybeObject* Map::Copy() {
4948 DescriptorArray* source_descriptors = instance_descriptors(); 4950 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(); 4951 int last_added = LastAdded();
4954 4952
4955 return CopyReplaceDescriptors(descriptors, NULL, last_added, OMIT_TRANSITION); 4953 return CopyReplaceDescriptors(descriptors, NULL, last_added, OMIT_TRANSITION);
4956 } 4954 }
4957 4955
4958 4956
4959 static bool InsertionPointFound(String* key1, String* key2) { 4957 static bool InsertionPointFound(String* key1, String* key2) {
4960 return key1->Hash() > key2->Hash() || key1 == key2; 4958 return key1->Hash() > key2->Hash() || key1 == key2;
4961 } 4959 }
4962 4960
4963 4961
4964 MaybeObject* Map::CopyAddDescriptor(Descriptor* descriptor, 4962 MaybeObject* Map::CopyAddDescriptor(Descriptor* descriptor,
4965 TransitionFlag flag) { 4963 TransitionFlag flag) {
4966 DescriptorArray* descriptors = instance_descriptors(); 4964 DescriptorArray* descriptors = instance_descriptors();
4967 4965
4968 // Ensure the key is a symbol. 4966 // Ensure the key is a symbol.
4969 MaybeObject* maybe_failure = descriptor->KeyToSymbol(); 4967 MaybeObject* maybe_failure = descriptor->KeyToSymbol();
4970 if (maybe_failure->IsFailure()) return maybe_failure; 4968 if (maybe_failure->IsFailure()) return maybe_failure;
4971 4969
4972 String* key = descriptor->GetKey(); 4970 String* key = descriptor->GetKey();
4973 ASSERT(descriptors->Search(key) == DescriptorArray::kNotFound); 4971 ASSERT(descriptors->Search(key) == DescriptorArray::kNotFound);
4974 4972
4975 int old_size = descriptors->number_of_descriptors(); 4973 int old_size = descriptors->number_of_descriptors();
4976 int new_size = old_size + 1; 4974 int new_size = old_size + 1;
4977 4975
4978 DescriptorArray* new_descriptors; 4976 DescriptorArray* new_descriptors;
4979 MaybeObject* maybe_descriptors = 4977 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; 4978 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
4982 4979
4983 FixedArray::WhitenessWitness witness(new_descriptors); 4980 FixedArray::WhitenessWitness witness(new_descriptors);
4984 4981
4985 // Copy the descriptors, inserting a descriptor. 4982 // Copy the descriptors, inserting a descriptor.
4986 int insertion_index = -1; 4983 int insertion_index = -1;
4987 int to = 0; 4984 int to = 0;
4988 for (int from = 0; from < old_size; ++from) { 4985 for (int from = 0; from < old_size; ++from) {
4989 if (insertion_index < 0 && 4986 if (insertion_index < 0 &&
4990 InsertionPointFound(descriptors->GetKey(from), key)) { 4987 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); 5028 ASSERT(0 <= insertion_index && insertion_index < size);
5032 5029
5033 // Ensure the key is a symbol. 5030 // Ensure the key is a symbol.
5034 MaybeObject* maybe_failure = descriptor->KeyToSymbol(); 5031 MaybeObject* maybe_failure = descriptor->KeyToSymbol();
5035 if (maybe_failure->IsFailure()) return maybe_failure; 5032 if (maybe_failure->IsFailure()) return maybe_failure;
5036 5033
5037 String* key = descriptor->GetKey(); 5034 String* key = descriptor->GetKey();
5038 ASSERT(key == descriptors->GetKey(insertion_index)); 5035 ASSERT(key == descriptors->GetKey(insertion_index));
5039 5036
5040 DescriptorArray* new_descriptors; 5037 DescriptorArray* new_descriptors;
5041 MaybeObject* maybe_descriptors = 5038 MaybeObject* maybe_descriptors = DescriptorArray::Allocate(size);
5042 DescriptorArray::Allocate(size, DescriptorArray::MAY_BE_SHARED);
5043 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; 5039 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
5044 5040
5045 FixedArray::WhitenessWitness witness(new_descriptors); 5041 FixedArray::WhitenessWitness witness(new_descriptors);
5046 5042
5047 // Copy the descriptors, replacing a descriptor. 5043 // Copy the descriptors, replacing a descriptor.
5048 for (int index = 0; index < size; ++index) { 5044 for (int index = 0; index < size; ++index) {
5049 if (index == insertion_index) continue; 5045 if (index == insertion_index) continue;
5050 new_descriptors->CopyFrom(index, descriptors, index, witness); 5046 new_descriptors->CopyFrom(index, descriptors, index, witness);
5051 } 5047 }
5052 5048
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after
5253 IntrusivePrototypeTransitionIterator(GetPrototypeTransitions()).Start(); 5249 IntrusivePrototypeTransitionIterator(GetPrototypeTransitions()).Start();
5254 } 5250 }
5255 5251
5256 IntrusiveMapTransitionIterator(transitions()).Start(); 5252 IntrusiveMapTransitionIterator(transitions()).Start();
5257 } 5253 }
5258 } 5254 }
5259 5255
5260 // If we have an unvisited child map, return that one and advance. If we have 5256 // 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. 5257 // none, return NULL and reset any destroyed FixedArray maps.
5262 TraversableMap* ChildIteratorNext() { 5258 TraversableMap* ChildIteratorNext() {
5263 if (HasTransitionArray()) { 5259 TransitionArray* transition_array = unchecked_transition_array();
5264 TransitionArray* transition_array = unchecked_transition_array(); 5260 if (!transition_array->map()->IsSmi() &&
5261 !transition_array->IsTransitionArray()) {
5262 return NULL;
5263 }
5265 5264
5266 if (transition_array->HasPrototypeTransitions()) { 5265 if (transition_array->HasPrototypeTransitions()) {
5267 HeapObject* proto_transitions = 5266 HeapObject* proto_transitions =
5268 transition_array->UncheckedPrototypeTransitions(); 5267 transition_array->UncheckedPrototypeTransitions();
5269 IntrusivePrototypeTransitionIterator proto_iterator(proto_transitions); 5268 IntrusivePrototypeTransitionIterator proto_iterator(proto_transitions);
5270 if (proto_iterator.IsIterating()) { 5269 if (proto_iterator.IsIterating()) {
5271 Map* next = proto_iterator.Next(); 5270 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); 5271 if (next != NULL) return static_cast<TraversableMap*>(next);
5280 } 5272 }
5281 } 5273 }
5282 5274
5275 IntrusiveMapTransitionIterator transition_iterator(transition_array);
5276 if (transition_iterator.IsIterating()) {
5277 Map* next = transition_iterator.Next();
5278 if (next != NULL) return static_cast<TraversableMap*>(next);
5279 }
5280
5283 return NULL; 5281 return NULL;
5284 } 5282 }
5285 }; 5283 };
5286 5284
5287 5285
5288 // Traverse the transition tree in postorder without using the C++ stack by 5286 // Traverse the transition tree in postorder without using the C++ stack by
5289 // doing pointer reversal. 5287 // doing pointer reversal.
5290 void Map::TraverseTransitionTree(TraverseCallback callback, void* data) { 5288 void Map::TraverseTransitionTree(TraverseCallback callback, void* data) {
5291 TraversableMap* current = static_cast<TraversableMap*>(this); 5289 TraversableMap* current = static_cast<TraversableMap*>(this);
5292 current->ChildIteratorStart(); 5290 current->ChildIteratorStart();
(...skipping 529 matching lines...) Expand 10 before | Expand all | Expand 10 after
5822 bool FixedArray::IsEqualTo(FixedArray* other) { 5820 bool FixedArray::IsEqualTo(FixedArray* other) {
5823 if (length() != other->length()) return false; 5821 if (length() != other->length()) return false;
5824 for (int i = 0 ; i < length(); ++i) { 5822 for (int i = 0 ; i < length(); ++i) {
5825 if (get(i) != other->get(i)) return false; 5823 if (get(i) != other->get(i)) return false;
5826 } 5824 }
5827 return true; 5825 return true;
5828 } 5826 }
5829 #endif 5827 #endif
5830 5828
5831 5829
5832 MaybeObject* DescriptorArray::Allocate(int number_of_descriptors, 5830 MaybeObject* DescriptorArray::Allocate(int number_of_descriptors) {
5833 SharedMode shared_mode) {
5834 Heap* heap = Isolate::Current()->heap(); 5831 Heap* heap = Isolate::Current()->heap();
5835 // Do not use DescriptorArray::cast on incomplete object. 5832 // Do not use DescriptorArray::cast on incomplete object.
5836 FixedArray* result; 5833 FixedArray* result;
5837 if (number_of_descriptors == 0 && shared_mode == MAY_BE_SHARED) { 5834 if (number_of_descriptors == 0) return heap->empty_descriptor_array();
5838 return heap->empty_descriptor_array();
5839 }
5840 // Allocate the array of keys. 5835 // Allocate the array of keys.
5841 MaybeObject* maybe_array = 5836 MaybeObject* maybe_array =
5842 heap->AllocateFixedArray(LengthFor(number_of_descriptors)); 5837 heap->AllocateFixedArray(LengthFor(number_of_descriptors));
5843 if (!maybe_array->To(&result)) return maybe_array; 5838 if (!maybe_array->To(&result)) return maybe_array;
5844 5839
5845 result->set(kEnumCacheIndex, Smi::FromInt(0)); 5840 result->set(kEnumCacheIndex, Smi::FromInt(0));
5846 result->set(kTransitionsIndex, Smi::FromInt(0));
5847 return result; 5841 return result;
5848 } 5842 }
5849 5843
5850 5844
5851 void DescriptorArray::SetEnumCache(FixedArray* bridge_storage, 5845 void DescriptorArray::SetEnumCache(FixedArray* bridge_storage,
5852 FixedArray* new_cache, 5846 FixedArray* new_cache,
5853 Object* new_index_cache) { 5847 Object* new_index_cache) {
5854 ASSERT(bridge_storage->length() >= kEnumCacheBridgeLength); 5848 ASSERT(bridge_storage->length() >= kEnumCacheBridgeLength);
5855 ASSERT(new_index_cache->IsSmi() || new_index_cache->IsFixedArray()); 5849 ASSERT(new_index_cache->IsSmi() || new_index_cache->IsFixedArray());
5856 if (HasEnumCache()) { 5850 if (HasEnumCache()) {
(...skipping 16 matching lines...) Expand all
5873 DescriptorArray* src, 5867 DescriptorArray* src,
5874 int src_index, 5868 int src_index,
5875 const WhitenessWitness& witness) { 5869 const WhitenessWitness& witness) {
5876 Object* value = src->GetValue(src_index); 5870 Object* value = src->GetValue(src_index);
5877 PropertyDetails details = src->GetDetails(src_index); 5871 PropertyDetails details = src->GetDetails(src_index);
5878 Descriptor desc(src->GetKey(src_index), value, details); 5872 Descriptor desc(src->GetKey(src_index), value, details);
5879 Set(dst_index, &desc, witness); 5873 Set(dst_index, &desc, witness);
5880 } 5874 }
5881 5875
5882 5876
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 5877 // 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 5878 // 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 5879 // would move a slot that was already recorded as pointing into an evacuation
5905 // candidate. This would result in missing updates upon evacuation. 5880 // candidate. This would result in missing updates upon evacuation.
5906 void DescriptorArray::Sort(const WhitenessWitness& witness) { 5881 void DescriptorArray::Sort(const WhitenessWitness& witness) {
5907 // In-place heap sort. 5882 // In-place heap sort.
5908 int len = number_of_descriptors(); 5883 int len = number_of_descriptors();
5909 // Bottom-up max-heap construction. 5884 // Bottom-up max-heap construction.
5910 // Index of the last node with children 5885 // Index of the last node with children
5911 const int max_parent_index = (len / 2) - 1; 5886 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. 7219 // If there are no transitions to be cleared, return.
7245 // TODO(verwaest) Should be an assert, otherwise back pointers are not 7220 // TODO(verwaest) Should be an assert, otherwise back pointers are not
7246 // properly cleared. 7221 // properly cleared.
7247 if (transition_index == t->number_of_transitions()) return; 7222 if (transition_index == t->number_of_transitions()) return;
7248 } 7223 }
7249 7224
7250 // If the final transition array does not contain any live transitions, remove 7225 // If the final transition array does not contain any live transitions, remove
7251 // the transition array from the map. 7226 // the transition array from the map.
7252 if (transition_index == 0 && 7227 if (transition_index == 0 &&
7253 !t->HasElementsTransition() && 7228 !t->HasElementsTransition() &&
7254 !t->HasPrototypeTransitions()) { 7229 !t->HasPrototypeTransitions() &&
7230 t->descriptors()->IsEmpty()) {
7255 return ClearTransitions(heap); 7231 return ClearTransitions(heap);
7256 } 7232 }
7257 7233
7258 int trim = t->number_of_transitions() - transition_index; 7234 int trim = t->number_of_transitions() - transition_index;
7259 if (trim > 0) { 7235 if (trim > 0) {
7260 RightTrimFixedArray<FROM_GC>( 7236 RightTrimFixedArray<FROM_GC>(
7261 heap, t, trim * TransitionArray::kTransitionSize); 7237 heap, t, trim * TransitionArray::kTransitionSize);
7262 } 7238 }
7263 } 7239 }
7264 7240
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after
7485 MaybeObject* ok = JSObject::cast(value)->OptimizeAsPrototype(); 7461 MaybeObject* ok = JSObject::cast(value)->OptimizeAsPrototype();
7486 if (ok->IsFailure()) return ok; 7462 if (ok->IsFailure()) return ok;
7487 } 7463 }
7488 7464
7489 // Now some logic for the maps of the objects that are created by using this 7465 // Now some logic for the maps of the objects that are created by using this
7490 // function as a constructor. 7466 // function as a constructor.
7491 if (has_initial_map()) { 7467 if (has_initial_map()) {
7492 // If the function has allocated the initial map 7468 // If the function has allocated the initial map
7493 // replace it with a copy containing the new prototype. 7469 // replace it with a copy containing the new prototype.
7494 Map* new_map; 7470 Map* new_map;
7495 MaybeObject* maybe_new_map = 7471 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; 7472 if (!maybe_new_map->To(&new_map)) return maybe_new_map;
7498 new_map->set_prototype(value); 7473 new_map->set_prototype(value);
7499 MaybeObject* maybe_object = set_initial_map_and_cache_transitions(new_map); 7474 MaybeObject* maybe_object = set_initial_map_and_cache_transitions(new_map);
7500 if (maybe_object->IsFailure()) return maybe_object; 7475 if (maybe_object->IsFailure()) return maybe_object;
7501 } else { 7476 } else {
7502 // Put the value in the initial map field until an initial map is 7477 // 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 7478 // needed. At that point, a new initial map is created and the
7504 // prototype is put into the initial map where it belongs. 7479 // prototype is put into the initial map where it belongs.
7505 set_prototype_or_initial_map(value); 7480 set_prototype_or_initial_map(value);
7506 } 7481 }
7507 heap->ClearInstanceofCache(); 7482 heap->ClearInstanceofCache();
7508 return value; 7483 return value;
7509 } 7484 }
7510 7485
7511 7486
7512 MaybeObject* JSFunction::SetPrototype(Object* value) { 7487 MaybeObject* JSFunction::SetPrototype(Object* value) {
7513 ASSERT(should_have_prototype()); 7488 ASSERT(should_have_prototype());
7514 Object* construct_prototype = value; 7489 Object* construct_prototype = value;
7515 7490
7516 // If the value is not a JSReceiver, store the value in the map's 7491 // 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 7492 // constructor field so it can be accessed. Also, set the prototype
7518 // used for constructing objects to the original object prototype. 7493 // used for constructing objects to the original object prototype.
7519 // See ECMA-262 13.2.2. 7494 // See ECMA-262 13.2.2.
7520 if (!value->IsJSReceiver()) { 7495 if (!value->IsJSReceiver()) {
7521 // Copy the map so this does not affect unrelated functions. 7496 // Copy the map so this does not affect unrelated functions.
7522 // Remove map transitions because they point to maps with a 7497 // Remove map transitions because they point to maps with a
7523 // different prototype. 7498 // different prototype.
7524 Map* new_map; 7499 Map* new_map;
7525 MaybeObject* maybe_new_map = map()->Copy(DescriptorArray::MAY_BE_SHARED); 7500 MaybeObject* maybe_new_map = map()->Copy();
7526 if (!maybe_new_map->To(&new_map)) return maybe_new_map; 7501 if (!maybe_new_map->To(&new_map)) return maybe_new_map;
7527 7502
7528 Heap* heap = new_map->GetHeap(); 7503 Heap* heap = new_map->GetHeap();
7529 set_map(new_map); 7504 set_map(new_map);
7530 new_map->set_constructor(value); 7505 new_map->set_constructor(value);
7531 new_map->set_non_instance_prototype(true); 7506 new_map->set_non_instance_prototype(true);
7532 construct_prototype = 7507 construct_prototype =
7533 heap->isolate()->context()->global_context()-> 7508 heap->isolate()->context()->global_context()->
7534 initial_object_prototype(); 7509 initial_object_prototype();
7535 } else { 7510 } else {
(...skipping 1273 matching lines...) Expand 10 before | Expand all | Expand 10 after
8809 // Nothing to do if prototype is already set. 8784 // Nothing to do if prototype is already set.
8810 if (map->prototype() == value) return value; 8785 if (map->prototype() == value) return value;
8811 8786
8812 if (value->IsJSObject()) { 8787 if (value->IsJSObject()) {
8813 MaybeObject* ok = JSObject::cast(value)->OptimizeAsPrototype(); 8788 MaybeObject* ok = JSObject::cast(value)->OptimizeAsPrototype();
8814 if (ok->IsFailure()) return ok; 8789 if (ok->IsFailure()) return ok;
8815 } 8790 }
8816 8791
8817 Map* new_map = map->GetPrototypeTransition(value); 8792 Map* new_map = map->GetPrototypeTransition(value);
8818 if (new_map == NULL) { 8793 if (new_map == NULL) {
8819 MaybeObject* maybe_new_map = map->Copy(DescriptorArray::MAY_BE_SHARED); 8794 MaybeObject* maybe_new_map = map->Copy();
8820 if (!maybe_new_map->To(&new_map)) return maybe_new_map; 8795 if (!maybe_new_map->To(&new_map)) return maybe_new_map;
8821 8796
8822 MaybeObject* maybe_new_cache = 8797 MaybeObject* maybe_new_cache =
8823 map->PutPrototypeTransition(value, new_map); 8798 map->PutPrototypeTransition(value, new_map);
8824 if (maybe_new_cache->IsFailure()) return maybe_new_cache; 8799 if (maybe_new_cache->IsFailure()) return maybe_new_cache;
8825 8800
8826 new_map->set_prototype(value); 8801 new_map->set_prototype(value);
8827 } 8802 }
8828 ASSERT(new_map->prototype() == value); 8803 ASSERT(new_map->prototype() == value);
8829 real_receiver->set_map(new_map); 8804 real_receiver->set_map(new_map);
(...skipping 3705 matching lines...) Expand 10 before | Expand all | Expand 10 after
12535 obj->set_map(new_map); 12510 obj->set_map(new_map);
12536 obj->set_properties(heap->empty_fixed_array()); 12511 obj->set_properties(heap->empty_fixed_array());
12537 // Check that it really works. 12512 // Check that it really works.
12538 ASSERT(obj->HasFastProperties()); 12513 ASSERT(obj->HasFastProperties());
12539 return obj; 12514 return obj;
12540 } 12515 }
12541 12516
12542 // Allocate the instance descriptor. 12517 // Allocate the instance descriptor.
12543 DescriptorArray* descriptors; 12518 DescriptorArray* descriptors;
12544 MaybeObject* maybe_descriptors = 12519 MaybeObject* maybe_descriptors =
12545 DescriptorArray::Allocate(instance_descriptor_length, 12520 DescriptorArray::Allocate(instance_descriptor_length);
12546 DescriptorArray::MAY_BE_SHARED);
12547 if (!maybe_descriptors->To(&descriptors)) { 12521 if (!maybe_descriptors->To(&descriptors)) {
12548 return maybe_descriptors; 12522 return maybe_descriptors;
12549 } 12523 }
12550 12524
12551 FixedArray::WhitenessWitness witness(descriptors); 12525 FixedArray::WhitenessWitness witness(descriptors);
12552 12526
12553 int number_of_allocated_fields = 12527 int number_of_allocated_fields =
12554 number_of_fields + unused_property_fields - inobject_props; 12528 number_of_fields + unused_property_fields - inobject_props;
12555 if (number_of_allocated_fields < 0) { 12529 if (number_of_allocated_fields < 0) {
12556 // There is enough inobject space for all fields (including unused). 12530 // There is enough inobject space for all fields (including unused).
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
12608 } else { 12582 } else {
12609 UNREACHABLE(); 12583 UNREACHABLE();
12610 } 12584 }
12611 ++next_descriptor; 12585 ++next_descriptor;
12612 } 12586 }
12613 } 12587 }
12614 ASSERT(current_offset == number_of_fields); 12588 ASSERT(current_offset == number_of_fields);
12615 12589
12616 descriptors->Sort(witness); 12590 descriptors->Sort(witness);
12617 12591
12592 MaybeObject* maybe_failure = new_map->InitializeDescriptors(descriptors);
12593 if (maybe_failure->IsFailure()) return maybe_failure;
12618 new_map->set_unused_property_fields(unused_property_fields); 12594 new_map->set_unused_property_fields(unused_property_fields);
12619 new_map->InitializeDescriptors(descriptors);
12620 12595
12621 // Transform the object. 12596 // Transform the object.
12622 obj->set_map(new_map); 12597 obj->set_map(new_map);
12623 12598
12624 obj->set_properties(fields); 12599 obj->set_properties(fields);
12625 ASSERT(obj->IsJSObject()); 12600 ASSERT(obj->IsJSObject());
12626 12601
12627 // Check that it really works. 12602 // Check that it really works.
12628 ASSERT(obj->HasFastProperties()); 12603 ASSERT(obj->HasFastProperties());
12629 12604
(...skipping 498 matching lines...) Expand 10 before | Expand all | Expand 10 after
13128 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); 13103 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER);
13129 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); 13104 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER);
13130 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); 13105 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER);
13131 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); 13106 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER);
13132 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); 13107 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER);
13133 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); 13108 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER);
13134 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); 13109 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER);
13135 } 13110 }
13136 13111
13137 } } // namespace v8::internal 13112 } } // namespace v8::internal
OLDNEW
« src/bootstrapper.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