| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #include "src/arguments.h" | 7 #include "src/arguments.h" |
| 8 #include "src/conversions.h" | 8 #include "src/conversions.h" |
| 9 #include "src/elements.h" | 9 #include "src/elements.h" |
| 10 #include "src/messages.h" | 10 #include "src/messages.h" |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 48 // - DictionaryElementsAccessor | 48 // - DictionaryElementsAccessor |
| 49 // - SloppyArgumentsElementsAccessor | 49 // - SloppyArgumentsElementsAccessor |
| 50 // - FastSloppyArgumentsElementsAccessor | 50 // - FastSloppyArgumentsElementsAccessor |
| 51 // - SlowSloppyArgumentsElementsAccessor | 51 // - SlowSloppyArgumentsElementsAccessor |
| 52 | 52 |
| 53 | 53 |
| 54 namespace v8 { | 54 namespace v8 { |
| 55 namespace internal { | 55 namespace internal { |
| 56 | 56 |
| 57 | 57 |
| 58 namespace { |
| 59 |
| 60 |
| 58 static const int kPackedSizeNotKnown = -1; | 61 static const int kPackedSizeNotKnown = -1; |
| 59 | 62 |
| 60 | 63 |
| 61 // First argument in list is the accessor class, the second argument is the | 64 // First argument in list is the accessor class, the second argument is the |
| 62 // accessor ElementsKind, and the third is the backing store class. Use the | 65 // accessor ElementsKind, and the third is the backing store class. Use the |
| 63 // fast element handler for smi-only arrays. The implementation is currently | 66 // fast element handler for smi-only arrays. The implementation is currently |
| 64 // identical. Note that the order must match that of the ElementsKind enum for | 67 // identical. Note that the order must match that of the ElementsKind enum for |
| 65 // the |accessor_array[]| below to work. | 68 // the |accessor_array[]| below to work. |
| 66 #define ELEMENTS_LIST(V) \ | 69 #define ELEMENTS_LIST(V) \ |
| 67 V(FastPackedSmiElementsAccessor, FAST_SMI_ELEMENTS, FixedArray) \ | 70 V(FastPackedSmiElementsAccessor, FAST_SMI_ELEMENTS, FixedArray) \ |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 113 #define ELEMENTS_TRAITS(Class, KindParam, Store) \ | 116 #define ELEMENTS_TRAITS(Class, KindParam, Store) \ |
| 114 template<> class ElementsKindTraits<KindParam> { \ | 117 template<> class ElementsKindTraits<KindParam> { \ |
| 115 public: /* NOLINT */ \ | 118 public: /* NOLINT */ \ |
| 116 static const ElementsKind Kind = KindParam; \ | 119 static const ElementsKind Kind = KindParam; \ |
| 117 typedef Store BackingStore; \ | 120 typedef Store BackingStore; \ |
| 118 }; | 121 }; |
| 119 ELEMENTS_LIST(ELEMENTS_TRAITS) | 122 ELEMENTS_LIST(ELEMENTS_TRAITS) |
| 120 #undef ELEMENTS_TRAITS | 123 #undef ELEMENTS_TRAITS |
| 121 | 124 |
| 122 | 125 |
| 123 ElementsAccessor** ElementsAccessor::elements_accessors_ = NULL; | |
| 124 | |
| 125 | |
| 126 static bool HasKey(Handle<FixedArray> array, Handle<Object> key_handle) { | 126 static bool HasKey(Handle<FixedArray> array, Handle<Object> key_handle) { |
| 127 DisallowHeapAllocation no_gc; | 127 DisallowHeapAllocation no_gc; |
| 128 Object* key = *key_handle; | 128 Object* key = *key_handle; |
| 129 int len0 = array->length(); | 129 int len0 = array->length(); |
| 130 for (int i = 0; i < len0; i++) { | 130 for (int i = 0; i < len0; i++) { |
| 131 Object* element = array->get(i); | 131 Object* element = array->get(i); |
| 132 if (key->KeyEquals(element)) return true; | 132 if (key->KeyEquals(element)) return true; |
| 133 } | 133 } |
| 134 return false; | 134 return false; |
| 135 } | 135 } |
| (...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 481 if (raw_frame->unchecked_code() == apply_builtin) { | 481 if (raw_frame->unchecked_code() == apply_builtin) { |
| 482 PrintF("apply from "); | 482 PrintF("apply from "); |
| 483 it.Advance(); | 483 it.Advance(); |
| 484 raw_frame = it.frame(); | 484 raw_frame = it.frame(); |
| 485 } | 485 } |
| 486 } | 486 } |
| 487 JavaScriptFrame::PrintTop(isolate, stdout, false, true); | 487 JavaScriptFrame::PrintTop(isolate, stdout, false, true); |
| 488 } | 488 } |
| 489 | 489 |
| 490 | 490 |
| 491 void CheckArrayAbuse(Handle<JSObject> obj, const char* op, uint32_t key, | |
| 492 bool allow_appending) { | |
| 493 DisallowHeapAllocation no_allocation; | |
| 494 Object* raw_length = NULL; | |
| 495 const char* elements_type = "array"; | |
| 496 if (obj->IsJSArray()) { | |
| 497 JSArray* array = JSArray::cast(*obj); | |
| 498 raw_length = array->length(); | |
| 499 } else { | |
| 500 raw_length = Smi::FromInt(obj->elements()->length()); | |
| 501 elements_type = "object"; | |
| 502 } | |
| 503 | |
| 504 if (raw_length->IsNumber()) { | |
| 505 double n = raw_length->Number(); | |
| 506 if (FastI2D(FastD2UI(n)) == n) { | |
| 507 int32_t int32_length = DoubleToInt32(n); | |
| 508 uint32_t compare_length = static_cast<uint32_t>(int32_length); | |
| 509 if (allow_appending) compare_length++; | |
| 510 if (key >= compare_length) { | |
| 511 PrintF("[OOB %s %s (%s length = %d, element accessed = %d) in ", | |
| 512 elements_type, op, elements_type, | |
| 513 static_cast<int>(int32_length), | |
| 514 static_cast<int>(key)); | |
| 515 TraceTopFrame(obj->GetIsolate()); | |
| 516 PrintF("]\n"); | |
| 517 } | |
| 518 } else { | |
| 519 PrintF("[%s elements length not integer value in ", elements_type); | |
| 520 TraceTopFrame(obj->GetIsolate()); | |
| 521 PrintF("]\n"); | |
| 522 } | |
| 523 } else { | |
| 524 PrintF("[%s elements length not a number in ", elements_type); | |
| 525 TraceTopFrame(obj->GetIsolate()); | |
| 526 PrintF("]\n"); | |
| 527 } | |
| 528 } | |
| 529 | |
| 530 | |
| 531 // Base class for element handler implementations. Contains the | 491 // Base class for element handler implementations. Contains the |
| 532 // the common logic for objects with different ElementsKinds. | 492 // the common logic for objects with different ElementsKinds. |
| 533 // Subclasses must specialize method for which the element | 493 // Subclasses must specialize method for which the element |
| 534 // implementation differs from the base class implementation. | 494 // implementation differs from the base class implementation. |
| 535 // | 495 // |
| 536 // This class is intended to be used in the following way: | 496 // This class is intended to be used in the following way: |
| 537 // | 497 // |
| 538 // class SomeElementsAccessor : | 498 // class SomeElementsAccessor : |
| 539 // public ElementsAccessorBase<SomeElementsAccessor, | 499 // public ElementsAccessorBase<SomeElementsAccessor, |
| 540 // BackingStoreClass> { | 500 // BackingStoreClass> { |
| (...skipping 1194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1735 ConvertElementsWithCapacity(object, old_elements, from_kind, capacity); | 1695 ConvertElementsWithCapacity(object, old_elements, from_kind, capacity); |
| 1736 Handle<Map> new_map = JSObject::GetElementsTransitionMap( | 1696 Handle<Map> new_map = JSObject::GetElementsTransitionMap( |
| 1737 object, FAST_SLOPPY_ARGUMENTS_ELEMENTS); | 1697 object, FAST_SLOPPY_ARGUMENTS_ELEMENTS); |
| 1738 JSObject::MigrateToMap(object, new_map); | 1698 JSObject::MigrateToMap(object, new_map); |
| 1739 parameter_map->set(1, *elements); | 1699 parameter_map->set(1, *elements); |
| 1740 JSObject::ValidateElements(object); | 1700 JSObject::ValidateElements(object); |
| 1741 } | 1701 } |
| 1742 }; | 1702 }; |
| 1743 | 1703 |
| 1744 | 1704 |
| 1745 void ElementsAccessor::InitializeOncePerProcess() { | |
| 1746 static ElementsAccessor* accessor_array[] = { | |
| 1747 #define ACCESSOR_ARRAY(Class, Kind, Store) new Class(#Kind), | |
| 1748 ELEMENTS_LIST(ACCESSOR_ARRAY) | |
| 1749 #undef ACCESSOR_ARRAY | |
| 1750 }; | |
| 1751 | |
| 1752 STATIC_ASSERT((sizeof(accessor_array) / sizeof(*accessor_array)) == | |
| 1753 kElementsKindCount); | |
| 1754 | |
| 1755 elements_accessors_ = accessor_array; | |
| 1756 } | |
| 1757 | |
| 1758 | |
| 1759 void ElementsAccessor::TearDown() { | |
| 1760 if (elements_accessors_ == NULL) return; | |
| 1761 #define ACCESSOR_DELETE(Class, Kind, Store) delete elements_accessors_[Kind]; | |
| 1762 ELEMENTS_LIST(ACCESSOR_DELETE) | |
| 1763 #undef ACCESSOR_DELETE | |
| 1764 elements_accessors_ = NULL; | |
| 1765 } | |
| 1766 | |
| 1767 | |
| 1768 template <typename ElementsAccessorSubclass, typename ElementsKindTraits> | 1705 template <typename ElementsAccessorSubclass, typename ElementsKindTraits> |
| 1769 void ElementsAccessorBase<ElementsAccessorSubclass, ElementsKindTraits>:: | 1706 void ElementsAccessorBase<ElementsAccessorSubclass, ElementsKindTraits>:: |
| 1770 SetLengthImpl(Handle<JSArray> array, uint32_t length, | 1707 SetLengthImpl(Handle<JSArray> array, uint32_t length, |
| 1771 Handle<FixedArrayBase> backing_store) { | 1708 Handle<FixedArrayBase> backing_store) { |
| 1772 DCHECK(!array->SetLengthWouldNormalize(length)); | 1709 DCHECK(!array->SetLengthWouldNormalize(length)); |
| 1773 DCHECK(IsFastElementsKind(array->GetElementsKind())); | 1710 DCHECK(IsFastElementsKind(array->GetElementsKind())); |
| 1774 uint32_t old_length = 0; | 1711 uint32_t old_length = 0; |
| 1775 CHECK(array->length()->ToArrayIndex(&old_length)); | 1712 CHECK(array->length()->ToArrayIndex(&old_length)); |
| 1776 | 1713 |
| 1777 if (old_length < length) { | 1714 if (old_length < length) { |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1802 } | 1739 } |
| 1803 } else { | 1740 } else { |
| 1804 // Check whether the backing store should be expanded. | 1741 // Check whether the backing store should be expanded. |
| 1805 capacity = Max(length, JSObject::NewElementsCapacity(capacity)); | 1742 capacity = Max(length, JSObject::NewElementsCapacity(capacity)); |
| 1806 ElementsAccessorSubclass::GrowCapacityAndConvertImpl(array, capacity); | 1743 ElementsAccessorSubclass::GrowCapacityAndConvertImpl(array, capacity); |
| 1807 } | 1744 } |
| 1808 | 1745 |
| 1809 array->set_length(Smi::FromInt(length)); | 1746 array->set_length(Smi::FromInt(length)); |
| 1810 JSObject::ValidateElements(array); | 1747 JSObject::ValidateElements(array); |
| 1811 } | 1748 } |
| 1749 } // namespace |
| 1750 |
| 1751 |
| 1752 void CheckArrayAbuse(Handle<JSObject> obj, const char* op, uint32_t key, |
| 1753 bool allow_appending) { |
| 1754 DisallowHeapAllocation no_allocation; |
| 1755 Object* raw_length = NULL; |
| 1756 const char* elements_type = "array"; |
| 1757 if (obj->IsJSArray()) { |
| 1758 JSArray* array = JSArray::cast(*obj); |
| 1759 raw_length = array->length(); |
| 1760 } else { |
| 1761 raw_length = Smi::FromInt(obj->elements()->length()); |
| 1762 elements_type = "object"; |
| 1763 } |
| 1764 |
| 1765 if (raw_length->IsNumber()) { |
| 1766 double n = raw_length->Number(); |
| 1767 if (FastI2D(FastD2UI(n)) == n) { |
| 1768 int32_t int32_length = DoubleToInt32(n); |
| 1769 uint32_t compare_length = static_cast<uint32_t>(int32_length); |
| 1770 if (allow_appending) compare_length++; |
| 1771 if (key >= compare_length) { |
| 1772 PrintF("[OOB %s %s (%s length = %d, element accessed = %d) in ", |
| 1773 elements_type, op, elements_type, static_cast<int>(int32_length), |
| 1774 static_cast<int>(key)); |
| 1775 TraceTopFrame(obj->GetIsolate()); |
| 1776 PrintF("]\n"); |
| 1777 } |
| 1778 } else { |
| 1779 PrintF("[%s elements length not integer value in ", elements_type); |
| 1780 TraceTopFrame(obj->GetIsolate()); |
| 1781 PrintF("]\n"); |
| 1782 } |
| 1783 } else { |
| 1784 PrintF("[%s elements length not a number in ", elements_type); |
| 1785 TraceTopFrame(obj->GetIsolate()); |
| 1786 PrintF("]\n"); |
| 1787 } |
| 1788 } |
| 1812 | 1789 |
| 1813 | 1790 |
| 1814 MaybeHandle<Object> ArrayConstructInitializeElements(Handle<JSArray> array, | 1791 MaybeHandle<Object> ArrayConstructInitializeElements(Handle<JSArray> array, |
| 1815 Arguments* args) { | 1792 Arguments* args) { |
| 1816 if (args->length() == 0) { | 1793 if (args->length() == 0) { |
| 1817 // Optimize the case where there are no parameters passed. | 1794 // Optimize the case where there are no parameters passed. |
| 1818 JSArray::Initialize(array, JSArray::kPreallocatedArrayElements); | 1795 JSArray::Initialize(array, JSArray::kPreallocatedArrayElements); |
| 1819 return array; | 1796 return array; |
| 1820 | 1797 |
| 1821 } else if (args->length() == 1 && args->at<Object>(0)->IsNumber()) { | 1798 } else if (args->length() == 1 && args->at<Object>(0)->IsNumber()) { |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1894 default: | 1871 default: |
| 1895 UNREACHABLE(); | 1872 UNREACHABLE(); |
| 1896 break; | 1873 break; |
| 1897 } | 1874 } |
| 1898 | 1875 |
| 1899 array->set_elements(*elms); | 1876 array->set_elements(*elms); |
| 1900 array->set_length(Smi::FromInt(number_of_elements)); | 1877 array->set_length(Smi::FromInt(number_of_elements)); |
| 1901 return array; | 1878 return array; |
| 1902 } | 1879 } |
| 1903 | 1880 |
| 1881 |
| 1882 void ElementsAccessor::InitializeOncePerProcess() { |
| 1883 static ElementsAccessor* accessor_array[] = { |
| 1884 #define ACCESSOR_ARRAY(Class, Kind, Store) new Class(#Kind), |
| 1885 ELEMENTS_LIST(ACCESSOR_ARRAY) |
| 1886 #undef ACCESSOR_ARRAY |
| 1887 }; |
| 1888 |
| 1889 STATIC_ASSERT((sizeof(accessor_array) / sizeof(*accessor_array)) == |
| 1890 kElementsKindCount); |
| 1891 |
| 1892 elements_accessors_ = accessor_array; |
| 1893 } |
| 1894 |
| 1895 |
| 1896 void ElementsAccessor::TearDown() { |
| 1897 if (elements_accessors_ == NULL) return; |
| 1898 #define ACCESSOR_DELETE(Class, Kind, Store) delete elements_accessors_[Kind]; |
| 1899 ELEMENTS_LIST(ACCESSOR_DELETE) |
| 1900 #undef ACCESSOR_DELETE |
| 1901 elements_accessors_ = NULL; |
| 1902 } |
| 1903 |
| 1904 |
| 1905 ElementsAccessor** ElementsAccessor::elements_accessors_ = NULL; |
| 1904 } // namespace internal | 1906 } // namespace internal |
| 1905 } // namespace v8 | 1907 } // namespace v8 |
| OLD | NEW |