OLD | NEW |
---|---|
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 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 5119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5130 } else if (!interceptor->getter()->IsUndefined()) { | 5130 } else if (!interceptor->getter()->IsUndefined()) { |
5131 v8::IndexedPropertyGetter getter = | 5131 v8::IndexedPropertyGetter getter = |
5132 v8::ToCData<v8::IndexedPropertyGetter>(interceptor->getter()); | 5132 v8::ToCData<v8::IndexedPropertyGetter>(interceptor->getter()); |
5133 LOG(ApiIndexedPropertyAccess("interceptor-indexed-has-get", this, index)); | 5133 LOG(ApiIndexedPropertyAccess("interceptor-indexed-has-get", this, index)); |
5134 v8::Handle<v8::Value> result; | 5134 v8::Handle<v8::Value> result; |
5135 { | 5135 { |
5136 // Leaving JavaScript. | 5136 // Leaving JavaScript. |
5137 VMState state(EXTERNAL); | 5137 VMState state(EXTERNAL); |
5138 result = getter(index, info); | 5138 result = getter(index, info); |
5139 } | 5139 } |
5140 if (!result.IsEmpty()) return !result->IsUndefined(); | 5140 if (!result.IsEmpty()) return true; |
Mads Ager (chromium)
2009/04/16 11:14:56
I have no idea why we treated an undefined result
| |
5141 } | 5141 } |
5142 return holder_handle->HasElementPostInterceptor(*receiver_handle, index); | 5142 return holder_handle->HasElementPostInterceptor(*receiver_handle, index); |
5143 } | 5143 } |
5144 | 5144 |
5145 | 5145 |
5146 bool JSObject::HasLocalElement(uint32_t index) { | 5146 bool JSObject::HasLocalElement(uint32_t index) { |
5147 // Check access rights if needed. | 5147 // Check access rights if needed. |
5148 if (IsAccessCheckNeeded() && | 5148 if (IsAccessCheckNeeded() && |
5149 !Top::MayIndexedAccess(this, index, v8::ACCESS_HAS)) { | 5149 !Top::MayIndexedAccess(this, index, v8::ACCESS_HAS)) { |
5150 Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS); | 5150 Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS); |
(...skipping 706 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5857 return property_dictionary()->NumberOfElementsFilterAttributes(filter); | 5857 return property_dictionary()->NumberOfElementsFilterAttributes(filter); |
5858 } | 5858 } |
5859 } | 5859 } |
5860 | 5860 |
5861 | 5861 |
5862 int JSObject::NumberOfEnumProperties() { | 5862 int JSObject::NumberOfEnumProperties() { |
5863 return NumberOfLocalProperties(static_cast<PropertyAttributes>(DONT_ENUM)); | 5863 return NumberOfLocalProperties(static_cast<PropertyAttributes>(DONT_ENUM)); |
5864 } | 5864 } |
5865 | 5865 |
5866 | 5866 |
5867 void FixedArray::Swap(int i, int j) { | 5867 void FixedArray::SwapPairs(FixedArray* numbers, int i, int j) { |
5868 Object* temp = get(i); | 5868 Object* temp = get(i); |
5869 set(i, get(j)); | 5869 set(i, get(j)); |
5870 set(j, temp); | 5870 set(j, temp); |
5871 if (this != numbers) { | |
5872 temp = numbers->get(i); | |
5873 numbers->set(i, numbers->get(j)); | |
5874 numbers->set(j, temp); | |
5875 } | |
5871 } | 5876 } |
5872 | 5877 |
5873 | 5878 |
5874 static void InsertionSortPairs(FixedArray* content, FixedArray* smis) { | 5879 static void InsertionSortPairs(FixedArray* content, |
5875 int len = smis->length(); | 5880 FixedArray* numbers, |
5881 int len) { | |
5876 for (int i = 1; i < len; i++) { | 5882 for (int i = 1; i < len; i++) { |
5877 int j = i; | 5883 int j = i; |
5878 while (j > 0 && | 5884 while (j > 0 && |
5879 Smi::cast(smis->get(j-1))->value() > | 5885 (NumberToUint32(numbers->get(j-1)) > |
Kasper Lund
2009/04/16 11:22:04
j-1 -> j - 1
| |
5880 Smi::cast(smis->get(j))->value()) { | 5886 NumberToUint32(numbers->get(j)))) { |
5881 smis->Swap(j-1, j); | 5887 content->SwapPairs(numbers, j-1, j); |
5882 content->Swap(j-1, j); | |
5883 j--; | 5888 j--; |
5884 } | 5889 } |
5885 } | 5890 } |
5886 } | 5891 } |
5887 | 5892 |
5888 | 5893 |
5889 void HeapSortPairs(FixedArray* content, FixedArray* smis) { | 5894 void HeapSortPairs(FixedArray* content, FixedArray* numbers, int len) { |
5890 // In-place heap sort. | 5895 // In-place heap sort. |
5891 ASSERT(content->length() == smis->length()); | 5896 ASSERT(content->length() == numbers->length()); |
5892 int len = smis->length(); | |
5893 | 5897 |
5894 // Bottom-up max-heap construction. | 5898 // Bottom-up max-heap construction. |
5895 for (int i = 1; i < len; ++i) { | 5899 for (int i = 1; i < len; ++i) { |
5896 int child_index = i; | 5900 int child_index = i; |
5897 while (child_index > 0) { | 5901 while (child_index > 0) { |
5898 int parent_index = ((child_index + 1) >> 1) - 1; | 5902 int parent_index = ((child_index + 1) >> 1) - 1; |
5899 int parent_value = Smi::cast(smis->get(parent_index))->value(); | 5903 uint32_t parent_value = NumberToUint32(numbers->get(parent_index)); |
5900 int child_value = Smi::cast(smis->get(child_index))->value(); | 5904 uint32_t child_value = NumberToUint32(numbers->get(child_index)); |
5901 if (parent_value < child_value) { | 5905 if (parent_value < child_value) { |
5902 content->Swap(parent_index, child_index); | 5906 content->SwapPairs(numbers, parent_index, child_index); |
5903 smis->Swap(parent_index, child_index); | |
5904 } else { | 5907 } else { |
5905 break; | 5908 break; |
5906 } | 5909 } |
5907 child_index = parent_index; | 5910 child_index = parent_index; |
5908 } | 5911 } |
5909 } | 5912 } |
5910 | 5913 |
5911 // Extract elements and create sorted array. | 5914 // Extract elements and create sorted array. |
5912 for (int i = len - 1; i > 0; --i) { | 5915 for (int i = len - 1; i > 0; --i) { |
5913 // Put max element at the back of the array. | 5916 // Put max element at the back of the array. |
5914 content->Swap(0, i); | 5917 content->SwapPairs(numbers, 0, i); |
5915 smis->Swap(0, i); | |
5916 // Sift down the new top element. | 5918 // Sift down the new top element. |
5917 int parent_index = 0; | 5919 int parent_index = 0; |
5918 while (true) { | 5920 while (true) { |
5919 int child_index = ((parent_index + 1) << 1) - 1; | 5921 int child_index = ((parent_index + 1) << 1) - 1; |
5920 if (child_index >= i) break; | 5922 if (child_index >= i) break; |
5921 uint32_t child1_value = Smi::cast(smis->get(child_index))->value(); | 5923 uint32_t child1_value = NumberToUint32(numbers->get(child_index)); |
5922 uint32_t child2_value = Smi::cast(smis->get(child_index + 1))->value(); | 5924 uint32_t child2_value = NumberToUint32(numbers->get(child_index + 1)); |
5923 uint32_t parent_value = Smi::cast(smis->get(parent_index))->value(); | 5925 uint32_t parent_value = NumberToUint32(numbers->get(parent_index)); |
5924 if (child_index + 1 >= i || child1_value > child2_value) { | 5926 if (child_index + 1 >= i || child1_value > child2_value) { |
5925 if (parent_value > child1_value) break; | 5927 if (parent_value > child1_value) break; |
5926 content->Swap(parent_index, child_index); | 5928 content->SwapPairs(numbers, parent_index, child_index); |
5927 smis->Swap(parent_index, child_index); | |
5928 parent_index = child_index; | 5929 parent_index = child_index; |
5929 } else { | 5930 } else { |
5930 if (parent_value > child2_value) break; | 5931 if (parent_value > child2_value) break; |
5931 content->Swap(parent_index, child_index + 1); | 5932 content->SwapPairs(numbers, parent_index, child_index + 1); |
5932 smis->Swap(parent_index, child_index + 1); | |
5933 parent_index = child_index + 1; | 5933 parent_index = child_index + 1; |
5934 } | 5934 } |
5935 } | 5935 } |
5936 } | 5936 } |
5937 } | 5937 } |
5938 | 5938 |
5939 | 5939 |
5940 // Sort this array and the smis as pairs wrt. the (distinct) smis. | 5940 // Sort this array and the numbers as pairs wrt. the (distinct) numbers. |
5941 void FixedArray::SortPairs(FixedArray* smis) { | 5941 void FixedArray::SortPairs(FixedArray* numbers, uint32_t len) { |
5942 ASSERT(this->length() == smis->length()); | 5942 ASSERT(this->length() == numbers->length()); |
5943 int len = smis->length(); | |
5944 // For small arrays, simply use insertion sort. | 5943 // For small arrays, simply use insertion sort. |
5945 if (len <= 10) { | 5944 if (len <= 10) { |
5946 InsertionSortPairs(this, smis); | 5945 InsertionSortPairs(this, numbers, len); |
5947 return; | 5946 return; |
5948 } | 5947 } |
5949 // Check the range of indices. | 5948 // Check the range of indices. |
5950 int min_index = Smi::cast(smis->get(0))->value(); | 5949 uint32_t min_index = NumberToUint32(numbers->get(0)); |
5951 int max_index = min_index; | 5950 uint32_t max_index = min_index; |
5952 int i; | 5951 uint32_t i; |
5953 for (i = 1; i < len; i++) { | 5952 for (i = 1; i < len; i++) { |
5954 if (Smi::cast(smis->get(i))->value() < min_index) { | 5953 if (NumberToUint32(numbers->get(i)) < min_index) { |
5955 min_index = Smi::cast(smis->get(i))->value(); | 5954 min_index = NumberToUint32(numbers->get(i)); |
5956 } else if (Smi::cast(smis->get(i))->value() > max_index) { | 5955 } else if (NumberToUint32(numbers->get(i)) > max_index) { |
5957 max_index = Smi::cast(smis->get(i))->value(); | 5956 max_index = NumberToUint32(numbers->get(i)); |
5958 } | 5957 } |
5959 } | 5958 } |
5960 if (max_index - min_index + 1 == len) { | 5959 if (max_index - min_index + 1 == len) { |
5961 // Indices form a contiguous range, unless there are duplicates. | 5960 // Indices form a contiguous range, unless there are duplicates. |
5962 // Do an in-place linear time sort assuming distinct smis, but | 5961 // Do an in-place linear time sort assuming distinct numbers, but |
5963 // avoid hanging in case they are not. | 5962 // avoid hanging in case they are not. |
5964 for (i = 0; i < len; i++) { | 5963 for (i = 0; i < len; i++) { |
5965 int p; | 5964 uint32_t p; |
5966 int j = 0; | 5965 uint32_t j = 0; |
5967 // While the current element at i is not at its correct position p, | 5966 // While the current element at i is not at its correct position p, |
5968 // swap the elements at these two positions. | 5967 // swap the elements at these two positions. |
5969 while ((p = Smi::cast(smis->get(i))->value() - min_index) != i && | 5968 while ((p = NumberToUint32(numbers->get(i)) - min_index) != i && |
5970 j++ < len) { | 5969 j++ < len) { |
5971 this->Swap(i, p); | 5970 SwapPairs(numbers, i, p); |
5972 smis->Swap(i, p); | |
5973 } | 5971 } |
5974 } | 5972 } |
5975 } else { | 5973 } else { |
5976 HeapSortPairs(this, smis); | 5974 HeapSortPairs(this, numbers, len); |
5977 return; | 5975 return; |
5978 } | 5976 } |
5979 } | 5977 } |
5980 | 5978 |
5981 | 5979 |
5982 // Fill in the names of local properties into the supplied storage. The main | 5980 // Fill in the names of local properties into the supplied storage. The main |
5983 // purpose of this function is to provide reflection information for the object | 5981 // purpose of this function is to provide reflection information for the object |
5984 // mirrors. | 5982 // mirrors. |
5985 void JSObject::GetLocalPropertyNames(FixedArray* storage, int index) { | 5983 void JSObject::GetLocalPropertyNames(FixedArray* storage, int index) { |
5986 ASSERT(storage->length() >= | 5984 ASSERT(storage->length() >= |
(...skipping 767 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6754 int pos = 0; | 6752 int pos = 0; |
6755 for (int i = 0; i < capacity; i++) { | 6753 for (int i = 0; i < capacity; i++) { |
6756 if (IsKey(KeyAt(i))) { | 6754 if (IsKey(KeyAt(i))) { |
6757 enumeration_order->set(pos++, | 6755 enumeration_order->set(pos++, |
6758 Smi::FromInt(DetailsAt(i).index()), | 6756 Smi::FromInt(DetailsAt(i).index()), |
6759 SKIP_WRITE_BARRIER); | 6757 SKIP_WRITE_BARRIER); |
6760 } | 6758 } |
6761 } | 6759 } |
6762 | 6760 |
6763 // Sort the arrays wrt. enumeration order. | 6761 // Sort the arrays wrt. enumeration order. |
6764 iteration_order->SortPairs(enumeration_order); | 6762 iteration_order->SortPairs(enumeration_order, enumeration_order->length()); |
6765 | 6763 |
6766 // Overwrite the enumeration_order with the enumeration indices. | 6764 // Overwrite the enumeration_order with the enumeration indices. |
6767 for (int i = 0; i < length; i++) { | 6765 for (int i = 0; i < length; i++) { |
6768 int index = Smi::cast(iteration_order->get(i))->value(); | 6766 int index = Smi::cast(iteration_order->get(i))->value(); |
6769 int enum_index = PropertyDetails::kInitialIndex + i; | 6767 int enum_index = PropertyDetails::kInitialIndex + i; |
6770 enumeration_order->set(index, | 6768 enumeration_order->set(index, |
6771 Smi::FromInt(enum_index), | 6769 Smi::FromInt(enum_index), |
6772 SKIP_WRITE_BARRIER); | 6770 SKIP_WRITE_BARRIER); |
6773 } | 6771 } |
6774 | 6772 |
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
7006 ASSERT(storage->length() >= NumberOfEnumElements()); | 7004 ASSERT(storage->length() >= NumberOfEnumElements()); |
7007 int capacity = Capacity(); | 7005 int capacity = Capacity(); |
7008 int index = 0; | 7006 int index = 0; |
7009 for (int i = 0; i < capacity; i++) { | 7007 for (int i = 0; i < capacity; i++) { |
7010 Object* k = KeyAt(i); | 7008 Object* k = KeyAt(i); |
7011 if (IsKey(k)) { | 7009 if (IsKey(k)) { |
7012 PropertyAttributes attr = DetailsAt(i).attributes(); | 7010 PropertyAttributes attr = DetailsAt(i).attributes(); |
7013 if ((attr & filter) == 0) storage->set(index++, k); | 7011 if ((attr & filter) == 0) storage->set(index++, k); |
7014 } | 7012 } |
7015 } | 7013 } |
7014 storage->SortPairs(storage, index); | |
7016 ASSERT(storage->length() >= index); | 7015 ASSERT(storage->length() >= index); |
7017 } | 7016 } |
7018 | 7017 |
7019 | 7018 |
7020 void Dictionary::CopyEnumKeysTo(FixedArray* storage, FixedArray* sort_array) { | 7019 void Dictionary::CopyEnumKeysTo(FixedArray* storage, FixedArray* sort_array) { |
7021 ASSERT(storage->length() >= NumberOfEnumElements()); | 7020 ASSERT(storage->length() >= NumberOfEnumElements()); |
7022 int capacity = Capacity(); | 7021 int capacity = Capacity(); |
7023 int index = 0; | 7022 int index = 0; |
7024 for (int i = 0; i < capacity; i++) { | 7023 for (int i = 0; i < capacity; i++) { |
7025 Object* k = KeyAt(i); | 7024 Object* k = KeyAt(i); |
7026 if (IsKey(k)) { | 7025 if (IsKey(k)) { |
7027 PropertyDetails details = DetailsAt(i); | 7026 PropertyDetails details = DetailsAt(i); |
7028 if (!details.IsDontEnum()) { | 7027 if (!details.IsDontEnum()) { |
7029 storage->set(index, k); | 7028 storage->set(index, k); |
7030 sort_array->set(index, | 7029 sort_array->set(index, |
7031 Smi::FromInt(details.index()), | 7030 Smi::FromInt(details.index()), |
7032 SKIP_WRITE_BARRIER); | 7031 SKIP_WRITE_BARRIER); |
7033 index++; | 7032 index++; |
7034 } | 7033 } |
7035 } | 7034 } |
7036 } | 7035 } |
7037 storage->SortPairs(sort_array); | 7036 storage->SortPairs(sort_array, sort_array->length()); |
7038 ASSERT(storage->length() >= index); | 7037 ASSERT(storage->length() >= index); |
7039 } | 7038 } |
7040 | 7039 |
7041 | 7040 |
7042 void Dictionary::CopyKeysTo(FixedArray* storage) { | 7041 void Dictionary::CopyKeysTo(FixedArray* storage) { |
7043 ASSERT(storage->length() >= NumberOfElementsFilterAttributes( | 7042 ASSERT(storage->length() >= NumberOfElementsFilterAttributes( |
7044 static_cast<PropertyAttributes>(NONE))); | 7043 static_cast<PropertyAttributes>(NONE))); |
7045 int capacity = Capacity(); | 7044 int capacity = Capacity(); |
7046 int index = 0; | 7045 int index = 0; |
7047 for (int i = 0; i < capacity; i++) { | 7046 for (int i = 0; i < capacity; i++) { |
(...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
7418 // No break point. | 7417 // No break point. |
7419 if (break_point_objects()->IsUndefined()) return 0; | 7418 if (break_point_objects()->IsUndefined()) return 0; |
7420 // Single beak point. | 7419 // Single beak point. |
7421 if (!break_point_objects()->IsFixedArray()) return 1; | 7420 if (!break_point_objects()->IsFixedArray()) return 1; |
7422 // Multiple break points. | 7421 // Multiple break points. |
7423 return FixedArray::cast(break_point_objects())->length(); | 7422 return FixedArray::cast(break_point_objects())->length(); |
7424 } | 7423 } |
7425 | 7424 |
7426 | 7425 |
7427 } } // namespace v8::internal | 7426 } } // namespace v8::internal |
OLD | NEW |