OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |