| 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 |