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 |