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 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
153 if (element->IsSmi() && element == key) return true; | 153 if (element->IsSmi() && element == key) return true; |
154 if (element->IsString() && | 154 if (element->IsString() && |
155 key->IsString() && String::cast(element)->Equals(String::cast(key))) { | 155 key->IsString() && String::cast(element)->Equals(String::cast(key))) { |
156 return true; | 156 return true; |
157 } | 157 } |
158 } | 158 } |
159 return false; | 159 return false; |
160 } | 160 } |
161 | 161 |
162 | 162 |
163 static Failure* ThrowArrayLengthRangeError(Heap* heap) { | 163 static Handle<Object> ThrowArrayLengthRangeError(Isolate* isolate) { |
164 HandleScope scope(heap->isolate()); | 164 isolate->Throw( |
165 return heap->isolate()->Throw( | 165 *isolate->factory()->NewRangeError("invalid_array_length", |
166 *heap->isolate()->factory()->NewRangeError("invalid_array_length", | 166 HandleVector<Object>(NULL, 0))); |
167 HandleVector<Object>(NULL, 0))); | 167 return Handle<Object>(); |
168 } | 168 } |
169 | 169 |
170 | 170 |
171 static void CopyObjectToObjectElements(FixedArrayBase* from_base, | 171 static void CopyObjectToObjectElements(FixedArrayBase* from_base, |
172 ElementsKind from_kind, | 172 ElementsKind from_kind, |
173 uint32_t from_start, | 173 uint32_t from_start, |
174 FixedArrayBase* to_base, | 174 FixedArrayBase* to_base, |
175 ElementsKind to_kind, | 175 ElementsKind to_kind, |
176 uint32_t to_start, | 176 uint32_t to_start, |
177 int raw_copy_size) { | 177 int raw_copy_size) { |
(...skipping 552 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
730 } | 730 } |
731 | 731 |
732 MUST_USE_RESULT static AccessorPair* GetAccessorPairImpl( | 732 MUST_USE_RESULT static AccessorPair* GetAccessorPairImpl( |
733 Object* receiver, | 733 Object* receiver, |
734 JSObject* obj, | 734 JSObject* obj, |
735 uint32_t key, | 735 uint32_t key, |
736 FixedArrayBase* backing_store) { | 736 FixedArrayBase* backing_store) { |
737 return NULL; | 737 return NULL; |
738 } | 738 } |
739 | 739 |
740 // TODO(ishell): Temporary wrapper until handlified. | |
741 MUST_USE_RESULT virtual Handle<Object> SetLength( | 740 MUST_USE_RESULT virtual Handle<Object> SetLength( |
742 Handle<JSArray> array, | 741 Handle<JSArray> array, |
743 Handle<Object> length) { | 742 Handle<Object> length) { |
744 CALL_HEAP_FUNCTION(array->GetIsolate(), | 743 Isolate* isolate = array->GetIsolate(); |
745 SetLength(*array, *length), | 744 return ElementsAccessorSubclass::SetLengthImpl( |
746 Object); | 745 array, length, handle(array->elements(), isolate)); |
747 } | 746 } |
748 | 747 |
749 MUST_USE_RESULT virtual MaybeObject* SetLength(JSArray* array, | 748 MUST_USE_RESULT static Handle<Object> SetLengthImpl( |
750 Object* length) { | 749 Handle<JSObject> obj, |
751 return ElementsAccessorSubclass::SetLengthImpl( | 750 Handle<Object> length, |
752 array, length, array->elements()); | 751 Handle<FixedArrayBase> backing_store); |
753 } | |
754 | |
755 MUST_USE_RESULT static MaybeObject* SetLengthImpl( | |
756 JSObject* obj, | |
757 Object* length, | |
758 FixedArrayBase* backing_store); | |
759 | 752 |
760 MUST_USE_RESULT virtual MaybeObject* SetCapacityAndLength( | 753 MUST_USE_RESULT virtual MaybeObject* SetCapacityAndLength( |
761 JSArray* array, | 754 JSArray* array, |
762 int capacity, | 755 int capacity, |
763 int length) { | 756 int length) { |
764 return ElementsAccessorSubclass::SetFastElementsCapacityAndLength( | 757 return ElementsAccessorSubclass::SetFastElementsCapacityAndLength( |
765 array, | 758 array, |
766 capacity, | 759 capacity, |
767 length); | 760 length); |
768 } | 761 } |
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
987 SetFastElementsCapacityAndLength(array, new_capacity, length); | 980 SetFastElementsCapacityAndLength(array, new_capacity, length); |
988 if (result->IsFailure()) return result; | 981 if (result->IsFailure()) return result; |
989 array->ValidateElements(); | 982 array->ValidateElements(); |
990 return length_object; | 983 return length_object; |
991 } | 984 } |
992 | 985 |
993 // Request conversion to slow elements. | 986 // Request conversion to slow elements. |
994 return array->GetHeap()->undefined_value(); | 987 return array->GetHeap()->undefined_value(); |
995 } | 988 } |
996 | 989 |
| 990 // TODO(ishell): Temporary wrapper until handlified. |
| 991 static Handle<Object> SetLengthWithoutNormalize( |
| 992 Handle<FixedArrayBase> backing_store, |
| 993 Handle<JSArray> array, |
| 994 Handle<Object> length_object, |
| 995 uint32_t length) { |
| 996 CALL_HEAP_FUNCTION(array->GetIsolate(), |
| 997 SetLengthWithoutNormalize( |
| 998 *backing_store, *array, *length_object, length), |
| 999 Object); |
| 1000 } |
| 1001 |
997 static MaybeObject* DeleteCommon(JSObject* obj, | 1002 static MaybeObject* DeleteCommon(JSObject* obj, |
998 uint32_t key, | 1003 uint32_t key, |
999 JSReceiver::DeleteMode mode) { | 1004 JSReceiver::DeleteMode mode) { |
1000 ASSERT(obj->HasFastSmiOrObjectElements() || | 1005 ASSERT(obj->HasFastSmiOrObjectElements() || |
1001 obj->HasFastDoubleElements() || | 1006 obj->HasFastDoubleElements() || |
1002 obj->HasFastArgumentsElements()); | 1007 obj->HasFastArgumentsElements()); |
1003 Heap* heap = obj->GetHeap(); | 1008 Heap* heap = obj->GetHeap(); |
1004 Object* elements = obj->elements(); | 1009 Object* elements = obj->elements(); |
1005 if (elements == heap->empty_fixed_array()) { | 1010 if (elements == heap->empty_fixed_array()) { |
1006 return heap->true_value(); | 1011 return heap->true_value(); |
(...skipping 368 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1375 MUST_USE_RESULT static PropertyType GetTypeImpl( | 1380 MUST_USE_RESULT static PropertyType GetTypeImpl( |
1376 Object* receiver, | 1381 Object* receiver, |
1377 JSObject* obj, | 1382 JSObject* obj, |
1378 uint32_t key, | 1383 uint32_t key, |
1379 FixedArrayBase* backing_store) { | 1384 FixedArrayBase* backing_store) { |
1380 return | 1385 return |
1381 key < AccessorClass::GetCapacityImpl(backing_store) | 1386 key < AccessorClass::GetCapacityImpl(backing_store) |
1382 ? FIELD : NONEXISTENT; | 1387 ? FIELD : NONEXISTENT; |
1383 } | 1388 } |
1384 | 1389 |
1385 MUST_USE_RESULT static MaybeObject* SetLengthImpl( | 1390 MUST_USE_RESULT static Handle<Object> SetLengthImpl( |
1386 JSObject* obj, | 1391 Handle<JSObject> obj, |
1387 Object* length, | 1392 Handle<Object> length, |
1388 FixedArrayBase* backing_store) { | 1393 Handle<FixedArrayBase> backing_store) { |
1389 // External arrays do not support changing their length. | 1394 // External arrays do not support changing their length. |
1390 UNREACHABLE(); | 1395 UNREACHABLE(); |
1391 return obj; | 1396 return obj; |
1392 } | 1397 } |
1393 | 1398 |
1394 MUST_USE_RESULT virtual MaybeObject* Delete(JSObject* obj, | 1399 MUST_USE_RESULT virtual MaybeObject* Delete(JSObject* obj, |
1395 uint32_t key, | 1400 uint32_t key, |
1396 JSReceiver::DeleteMode mode) { | 1401 JSReceiver::DeleteMode mode) { |
1397 // External arrays always ignore deletes. | 1402 // External arrays always ignore deletes. |
1398 return obj->GetHeap()->true_value(); | 1403 return obj->GetHeap()->true_value(); |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1486 } | 1491 } |
1487 } | 1492 } |
1488 } | 1493 } |
1489 | 1494 |
1490 // Update the number of elements. | 1495 // Update the number of elements. |
1491 dict->ElementsRemoved(removed_entries); | 1496 dict->ElementsRemoved(removed_entries); |
1492 } | 1497 } |
1493 return length_object; | 1498 return length_object; |
1494 } | 1499 } |
1495 | 1500 |
| 1501 // TODO(ishell): Temporary wrapper until handlified. |
| 1502 MUST_USE_RESULT static Handle<Object> SetLengthWithoutNormalize( |
| 1503 Handle<FixedArrayBase> store, |
| 1504 Handle<JSArray> array, |
| 1505 Handle<Object> length_object, |
| 1506 uint32_t length) { |
| 1507 CALL_HEAP_FUNCTION(array->GetIsolate(), |
| 1508 SetLengthWithoutNormalize( |
| 1509 *store, *array, *length_object, length), |
| 1510 Object); |
| 1511 } |
| 1512 |
1496 MUST_USE_RESULT static MaybeObject* DeleteCommon( | 1513 MUST_USE_RESULT static MaybeObject* DeleteCommon( |
1497 JSObject* obj, | 1514 JSObject* obj, |
1498 uint32_t key, | 1515 uint32_t key, |
1499 JSReceiver::DeleteMode mode) { | 1516 JSReceiver::DeleteMode mode) { |
1500 Isolate* isolate = obj->GetIsolate(); | 1517 Isolate* isolate = obj->GetIsolate(); |
1501 Heap* heap = isolate->heap(); | 1518 Heap* heap = isolate->heap(); |
1502 FixedArray* backing_store = FixedArray::cast(obj->elements()); | 1519 FixedArray* backing_store = FixedArray::cast(obj->elements()); |
1503 bool is_arguments = | 1520 bool is_arguments = |
1504 (obj->GetElementsKind() == SLOPPY_ARGUMENTS_ELEMENTS); | 1521 (obj->GetElementsKind() == SLOPPY_ARGUMENTS_ELEMENTS); |
1505 if (is_arguments) { | 1522 if (is_arguments) { |
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1729 if (!probe->IsTheHole()) { | 1746 if (!probe->IsTheHole()) { |
1730 return NULL; | 1747 return NULL; |
1731 } else { | 1748 } else { |
1732 // If not aliased, check the arguments. | 1749 // If not aliased, check the arguments. |
1733 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | 1750 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
1734 return ElementsAccessor::ForArray(arguments)->GetAccessorPair( | 1751 return ElementsAccessor::ForArray(arguments)->GetAccessorPair( |
1735 receiver, obj, key, arguments); | 1752 receiver, obj, key, arguments); |
1736 } | 1753 } |
1737 } | 1754 } |
1738 | 1755 |
1739 MUST_USE_RESULT static MaybeObject* SetLengthImpl( | 1756 MUST_USE_RESULT static Handle<Object> SetLengthImpl( |
1740 JSObject* obj, | 1757 Handle<JSObject> obj, |
1741 Object* length, | 1758 Handle<Object> length, |
1742 FixedArrayBase* parameter_map) { | 1759 Handle<FixedArrayBase> parameter_map) { |
1743 // TODO(mstarzinger): This was never implemented but will be used once we | 1760 // TODO(mstarzinger): This was never implemented but will be used once we |
1744 // correctly implement [[DefineOwnProperty]] on arrays. | 1761 // correctly implement [[DefineOwnProperty]] on arrays. |
1745 UNIMPLEMENTED(); | 1762 UNIMPLEMENTED(); |
1746 return obj; | 1763 return obj; |
1747 } | 1764 } |
1748 | 1765 |
1749 MUST_USE_RESULT virtual MaybeObject* Delete(JSObject* obj, | 1766 MUST_USE_RESULT virtual MaybeObject* Delete(JSObject* obj, |
1750 uint32_t key, | 1767 uint32_t key, |
1751 JSReceiver::DeleteMode mode) { | 1768 JSReceiver::DeleteMode mode) { |
1752 FixedArray* parameter_map = FixedArray::cast(obj->elements()); | 1769 FixedArray* parameter_map = FixedArray::cast(obj->elements()); |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1844 | 1861 |
1845 void ElementsAccessor::TearDown() { | 1862 void ElementsAccessor::TearDown() { |
1846 #define ACCESSOR_DELETE(Class, Kind, Store) delete elements_accessors_[Kind]; | 1863 #define ACCESSOR_DELETE(Class, Kind, Store) delete elements_accessors_[Kind]; |
1847 ELEMENTS_LIST(ACCESSOR_DELETE) | 1864 ELEMENTS_LIST(ACCESSOR_DELETE) |
1848 #undef ACCESSOR_DELETE | 1865 #undef ACCESSOR_DELETE |
1849 elements_accessors_ = NULL; | 1866 elements_accessors_ = NULL; |
1850 } | 1867 } |
1851 | 1868 |
1852 | 1869 |
1853 template <typename ElementsAccessorSubclass, typename ElementsKindTraits> | 1870 template <typename ElementsAccessorSubclass, typename ElementsKindTraits> |
1854 MUST_USE_RESULT MaybeObject* ElementsAccessorBase<ElementsAccessorSubclass, | 1871 MUST_USE_RESULT Handle<Object> ElementsAccessorBase<ElementsAccessorSubclass, |
1855 ElementsKindTraits>:: | 1872 ElementsKindTraits>:: |
1856 SetLengthImpl(JSObject* obj, | 1873 SetLengthImpl(Handle<JSObject> obj, |
1857 Object* length, | 1874 Handle<Object> length, |
1858 FixedArrayBase* backing_store) { | 1875 Handle<FixedArrayBase> backing_store) { |
1859 JSArray* array = JSArray::cast(obj); | 1876 Isolate* isolate = obj->GetIsolate(); |
| 1877 Handle<JSArray> array = Handle<JSArray>::cast(obj); |
1860 | 1878 |
1861 // Fast case: The new length fits into a Smi. | 1879 // Fast case: The new length fits into a Smi. |
1862 MaybeObject* maybe_smi_length = length->ToSmi(); | 1880 Handle<Object> smi_length = Object::ToSmi(isolate, length); |
1863 Object* smi_length = Smi::FromInt(0); | 1881 |
1864 if (maybe_smi_length->ToObject(&smi_length) && smi_length->IsSmi()) { | 1882 if (!smi_length.is_null() && smi_length->IsSmi()) { |
1865 const int value = Smi::cast(smi_length)->value(); | 1883 const int value = Handle<Smi>::cast(smi_length)->value(); |
1866 if (value >= 0) { | 1884 if (value >= 0) { |
1867 Object* new_length; | 1885 Handle<Object> new_length = ElementsAccessorSubclass:: |
1868 MaybeObject* result = ElementsAccessorSubclass:: | |
1869 SetLengthWithoutNormalize(backing_store, array, smi_length, value); | 1886 SetLengthWithoutNormalize(backing_store, array, smi_length, value); |
1870 if (!result->ToObject(&new_length)) return result; | 1887 RETURN_IF_EMPTY_HANDLE_VALUE(isolate, new_length, new_length); |
| 1888 |
1871 // even though the proposed length was a smi, new_length could | 1889 // even though the proposed length was a smi, new_length could |
1872 // still be a heap number because SetLengthWithoutNormalize doesn't | 1890 // still be a heap number because SetLengthWithoutNormalize doesn't |
1873 // allow the array length property to drop below the index of | 1891 // allow the array length property to drop below the index of |
1874 // non-deletable elements. | 1892 // non-deletable elements. |
1875 ASSERT(new_length->IsSmi() || new_length->IsHeapNumber() || | 1893 ASSERT(new_length->IsSmi() || new_length->IsHeapNumber() || |
1876 new_length->IsUndefined()); | 1894 new_length->IsUndefined()); |
1877 if (new_length->IsSmi()) { | 1895 if (new_length->IsSmi()) { |
1878 array->set_length(Smi::cast(new_length)); | 1896 array->set_length(*Handle<Smi>::cast(new_length)); |
1879 return array; | 1897 return array; |
1880 } else if (new_length->IsHeapNumber()) { | 1898 } else if (new_length->IsHeapNumber()) { |
1881 array->set_length(new_length); | 1899 array->set_length(*new_length); |
1882 return array; | 1900 return array; |
1883 } | 1901 } |
1884 } else { | 1902 } else { |
1885 return ThrowArrayLengthRangeError(array->GetHeap()); | 1903 return ThrowArrayLengthRangeError(isolate); |
1886 } | 1904 } |
1887 } | 1905 } |
1888 | 1906 |
1889 // Slow case: The new length does not fit into a Smi or conversion | 1907 // Slow case: The new length does not fit into a Smi or conversion |
1890 // to slow elements is needed for other reasons. | 1908 // to slow elements is needed for other reasons. |
1891 if (length->IsNumber()) { | 1909 if (length->IsNumber()) { |
1892 uint32_t value; | 1910 uint32_t value; |
1893 if (length->ToArrayIndex(&value)) { | 1911 if (length->ToArrayIndex(&value)) { |
1894 SeededNumberDictionary* dictionary; | 1912 Handle<SeededNumberDictionary> dictionary = |
1895 MaybeObject* maybe_object = array->NormalizeElements(); | 1913 JSObject::NormalizeElements(array); |
1896 if (!maybe_object->To(&dictionary)) return maybe_object; | 1914 RETURN_IF_EMPTY_HANDLE_VALUE(isolate, dictionary, dictionary); |
1897 Object* new_length; | 1915 |
1898 MaybeObject* result = DictionaryElementsAccessor:: | 1916 Handle<Object> new_length = DictionaryElementsAccessor:: |
1899 SetLengthWithoutNormalize(dictionary, array, length, value); | 1917 SetLengthWithoutNormalize(dictionary, array, length, value); |
1900 if (!result->ToObject(&new_length)) return result; | 1918 RETURN_IF_EMPTY_HANDLE_VALUE(isolate, new_length, new_length); |
| 1919 |
1901 ASSERT(new_length->IsNumber()); | 1920 ASSERT(new_length->IsNumber()); |
1902 array->set_length(new_length); | 1921 array->set_length(*new_length); |
1903 return array; | 1922 return array; |
1904 } else { | 1923 } else { |
1905 return ThrowArrayLengthRangeError(array->GetHeap()); | 1924 return ThrowArrayLengthRangeError(isolate); |
1906 } | 1925 } |
1907 } | 1926 } |
1908 | 1927 |
| 1928 Factory* factory = isolate->factory(); |
1909 // Fall-back case: The new length is not a number so make the array | 1929 // Fall-back case: The new length is not a number so make the array |
1910 // size one and set only element to length. | 1930 // size one and set only element to length. |
1911 FixedArray* new_backing_store; | 1931 Handle<FixedArray> new_backing_store = factory->NewFixedArray(1); |
1912 MaybeObject* maybe_obj = array->GetHeap()->AllocateFixedArray(1); | 1932 new_backing_store->set(0, *length); |
1913 if (!maybe_obj->To(&new_backing_store)) return maybe_obj; | 1933 factory->SetContent(array, new_backing_store); |
1914 new_backing_store->set(0, length); | |
1915 { MaybeObject* result = array->SetContent(new_backing_store); | |
1916 if (result->IsFailure()) return result; | |
1917 } | |
1918 return array; | 1934 return array; |
1919 } | 1935 } |
1920 | 1936 |
1921 | 1937 |
1922 Handle<Object> ArrayConstructInitializeElements(Handle<JSArray> array, | 1938 Handle<Object> ArrayConstructInitializeElements(Handle<JSArray> array, |
1923 Arguments* args) { | 1939 Arguments* args) { |
1924 // Optimize the case where there is one argument and the argument is a | 1940 // Optimize the case where there is one argument and the argument is a |
1925 // small smi. | 1941 // small smi. |
1926 if (args->length() == 1) { | 1942 if (args->length() == 1) { |
1927 Handle<Object> obj = args->at<Object>(0); | 1943 Handle<Object> obj = args->at<Object>(0); |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2005 UNREACHABLE(); | 2021 UNREACHABLE(); |
2006 break; | 2022 break; |
2007 } | 2023 } |
2008 | 2024 |
2009 array->set_elements(*elms); | 2025 array->set_elements(*elms); |
2010 array->set_length(Smi::FromInt(number_of_elements)); | 2026 array->set_length(Smi::FromInt(number_of_elements)); |
2011 return array; | 2027 return array; |
2012 } | 2028 } |
2013 | 2029 |
2014 } } // namespace v8::internal | 2030 } } // namespace v8::internal |
OLD | NEW |