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 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 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 754 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |