Chromium Code Reviews| 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 |