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 1853 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1864 } | 1864 } |
1865 | 1865 |
1866 | 1866 |
1867 Object** FixedArray::data_start() { | 1867 Object** FixedArray::data_start() { |
1868 return HeapObject::RawField(this, kHeaderSize); | 1868 return HeapObject::RawField(this, kHeaderSize); |
1869 } | 1869 } |
1870 | 1870 |
1871 | 1871 |
1872 bool DescriptorArray::IsEmpty() { | 1872 bool DescriptorArray::IsEmpty() { |
1873 ASSERT(this->IsSmi() || | 1873 ASSERT(this->IsSmi() || |
1874 this->length() > kFirstIndex || | 1874 this->MayContainTransitions() || |
1875 this == HEAP->empty_descriptor_array()); | 1875 this == HEAP->empty_descriptor_array()); |
1876 return this->IsSmi() || length() <= kFirstIndex; | 1876 return this->IsSmi() || length() < kFirstIndex; |
1877 } | 1877 } |
1878 | 1878 |
1879 | 1879 |
| 1880 bool DescriptorArray::MayContainTransitions() { |
| 1881 return length() >= kTransitionsIndex; |
| 1882 } |
| 1883 |
| 1884 |
1880 int DescriptorArray::bit_field3_storage() { | 1885 int DescriptorArray::bit_field3_storage() { |
1881 Object* storage = READ_FIELD(this, kBitField3StorageOffset); | 1886 Object* storage = READ_FIELD(this, kBitField3StorageOffset); |
1882 return Smi::cast(storage)->value(); | 1887 return Smi::cast(storage)->value(); |
1883 } | 1888 } |
1884 | 1889 |
1885 void DescriptorArray::set_bit_field3_storage(int value) { | 1890 void DescriptorArray::set_bit_field3_storage(int value) { |
1886 ASSERT(!IsEmpty()); | 1891 ASSERT(this->MayContainTransitions()); |
1887 WRITE_FIELD(this, kBitField3StorageOffset, Smi::FromInt(value)); | 1892 WRITE_FIELD(this, kBitField3StorageOffset, Smi::FromInt(value)); |
1888 } | 1893 } |
1889 | 1894 |
1890 | 1895 |
1891 void DescriptorArray::NoIncrementalWriteBarrierSwap(FixedArray* array, | 1896 void DescriptorArray::NoIncrementalWriteBarrierSwap(FixedArray* array, |
1892 int first, | 1897 int first, |
1893 int second) { | 1898 int second) { |
1894 Object* tmp = array->get(first); | 1899 Object* tmp = array->get(first); |
1895 NoIncrementalWriteBarrierSet(array, first, array->get(second)); | 1900 NoIncrementalWriteBarrierSet(array, first, array->get(second)); |
1896 NoIncrementalWriteBarrierSet(array, second, tmp); | 1901 NoIncrementalWriteBarrierSet(array, second, tmp); |
1897 } | 1902 } |
1898 | 1903 |
1899 | 1904 |
1900 int DescriptorArray::Search(String* name) { | 1905 int DescriptorArray::Search(String* name) { |
1901 SLOW_ASSERT(IsSortedNoDuplicates()); | 1906 SLOW_ASSERT(IsSortedNoDuplicates()); |
1902 | 1907 |
1903 // Check for empty descriptor array. | 1908 // Check for empty descriptor array. |
1904 int nof = number_of_descriptors(); | 1909 int nof = number_of_descriptors(); |
1905 if (nof == 0) return kNotFound; | 1910 if (nof == 0) return kNotFound; |
1906 | 1911 |
1907 // Fast case: do linear search for small arrays. | 1912 // Fast case: do linear search for small arrays. |
1908 const int kMaxElementsForLinearSearch = 8; | 1913 const int kMaxElementsForLinearSearch = 8; |
1909 if (StringShape(name).IsSymbol() && nof < kMaxElementsForLinearSearch) { | 1914 if (StringShape(name).IsSymbol() && nof < kMaxElementsForLinearSearch) { |
1910 return LinearSearch(name, nof); | 1915 return LinearSearch(EXPECT_SORTED, name, nof); |
1911 } | 1916 } |
1912 | 1917 |
1913 // Slow case: perform binary search. | 1918 // Slow case: perform binary search. |
1914 return BinarySearch(name, 0, nof - 1); | 1919 return BinarySearch(name, 0, nof - 1); |
1915 } | 1920 } |
1916 | 1921 |
1917 | 1922 |
1918 int DescriptorArray::SearchWithCache(String* name) { | 1923 int DescriptorArray::SearchWithCache(String* name) { |
1919 int number = GetIsolate()->descriptor_lookup_cache()->Lookup(this, name); | 1924 int number = GetIsolate()->descriptor_lookup_cache()->Lookup(this, name); |
1920 if (number == DescriptorLookupCache::kAbsent) { | 1925 if (number == DescriptorLookupCache::kAbsent) { |
1921 number = Search(name); | 1926 number = Search(name); |
1922 GetIsolate()->descriptor_lookup_cache()->Update(this, name, number); | 1927 GetIsolate()->descriptor_lookup_cache()->Update(this, name, number); |
1923 } | 1928 } |
1924 return number; | 1929 return number; |
1925 } | 1930 } |
1926 | 1931 |
1927 | 1932 |
| 1933 Map* DescriptorArray::elements_transition_map() { |
| 1934 if (!this->MayContainTransitions()) { |
| 1935 return NULL; |
| 1936 } |
| 1937 Object* transition_map = get(kTransitionsIndex); |
| 1938 if (transition_map == Smi::FromInt(0)) { |
| 1939 return NULL; |
| 1940 } else { |
| 1941 return Map::cast(transition_map); |
| 1942 } |
| 1943 } |
| 1944 |
| 1945 |
| 1946 void DescriptorArray::set_elements_transition_map( |
| 1947 Map* transition_map, WriteBarrierMode mode) { |
| 1948 ASSERT(this->length() > kTransitionsIndex); |
| 1949 Heap* heap = GetHeap(); |
| 1950 WRITE_FIELD(this, kTransitionsOffset, transition_map); |
| 1951 CONDITIONAL_WRITE_BARRIER( |
| 1952 heap, this, kTransitionsOffset, transition_map, mode); |
| 1953 ASSERT(DescriptorArray::cast(this)); |
| 1954 } |
| 1955 |
| 1956 |
1928 Object** DescriptorArray::GetKeySlot(int descriptor_number) { | 1957 Object** DescriptorArray::GetKeySlot(int descriptor_number) { |
1929 ASSERT(descriptor_number < number_of_descriptors()); | 1958 ASSERT(descriptor_number < number_of_descriptors()); |
1930 return HeapObject::RawField( | 1959 return HeapObject::RawField( |
1931 reinterpret_cast<HeapObject*>(this), | 1960 reinterpret_cast<HeapObject*>(this), |
1932 OffsetOfElementAt(ToKeyIndex(descriptor_number))); | 1961 OffsetOfElementAt(ToKeyIndex(descriptor_number))); |
1933 } | 1962 } |
1934 | 1963 |
1935 | 1964 |
1936 String* DescriptorArray::GetKey(int descriptor_number) { | 1965 String* DescriptorArray::GetKey(int descriptor_number) { |
1937 ASSERT(descriptor_number < number_of_descriptors()); | 1966 ASSERT(descriptor_number < number_of_descriptors()); |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2003 bool DescriptorArray::IsProperty(int descriptor_number) { | 2032 bool DescriptorArray::IsProperty(int descriptor_number) { |
2004 Entry entry(this, descriptor_number); | 2033 Entry entry(this, descriptor_number); |
2005 return IsPropertyDescriptor(&entry); | 2034 return IsPropertyDescriptor(&entry); |
2006 } | 2035 } |
2007 | 2036 |
2008 | 2037 |
2009 bool DescriptorArray::IsTransitionOnly(int descriptor_number) { | 2038 bool DescriptorArray::IsTransitionOnly(int descriptor_number) { |
2010 switch (GetType(descriptor_number)) { | 2039 switch (GetType(descriptor_number)) { |
2011 case MAP_TRANSITION: | 2040 case MAP_TRANSITION: |
2012 case CONSTANT_TRANSITION: | 2041 case CONSTANT_TRANSITION: |
2013 case ELEMENTS_TRANSITION: | |
2014 return true; | 2042 return true; |
2015 case CALLBACKS: { | 2043 case CALLBACKS: { |
2016 Object* value = GetValue(descriptor_number); | 2044 Object* value = GetValue(descriptor_number); |
2017 if (!value->IsAccessorPair()) return false; | 2045 if (!value->IsAccessorPair()) return false; |
2018 AccessorPair* accessors = AccessorPair::cast(value); | 2046 AccessorPair* accessors = AccessorPair::cast(value); |
2019 return accessors->getter()->IsMap() && accessors->setter()->IsMap(); | 2047 return accessors->getter()->IsMap() && accessors->setter()->IsMap(); |
2020 } | 2048 } |
2021 case NORMAL: | 2049 case NORMAL: |
2022 case FIELD: | 2050 case FIELD: |
2023 case CONSTANT_FUNCTION: | 2051 case CONSTANT_FUNCTION: |
(...skipping 1421 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3445 Object* Map::GetBackPointer() { | 3473 Object* Map::GetBackPointer() { |
3446 Object* object = READ_FIELD(this, kPrototypeTransitionsOrBackPointerOffset); | 3474 Object* object = READ_FIELD(this, kPrototypeTransitionsOrBackPointerOffset); |
3447 if (object->IsFixedArray()) { | 3475 if (object->IsFixedArray()) { |
3448 return FixedArray::cast(object)->get(kProtoTransitionBackPointerOffset); | 3476 return FixedArray::cast(object)->get(kProtoTransitionBackPointerOffset); |
3449 } else { | 3477 } else { |
3450 return object; | 3478 return object; |
3451 } | 3479 } |
3452 } | 3480 } |
3453 | 3481 |
3454 | 3482 |
| 3483 Map* Map::elements_transition_map() { |
| 3484 return instance_descriptors()->elements_transition_map(); |
| 3485 } |
| 3486 |
| 3487 |
| 3488 void Map::set_elements_transition_map(Map* transitioned_map) { |
| 3489 return instance_descriptors()->set_elements_transition_map(transitioned_map); |
| 3490 } |
| 3491 |
| 3492 |
3455 void Map::SetBackPointer(Object* value, WriteBarrierMode mode) { | 3493 void Map::SetBackPointer(Object* value, WriteBarrierMode mode) { |
3456 Heap* heap = GetHeap(); | 3494 Heap* heap = GetHeap(); |
3457 ASSERT(instance_type() >= FIRST_JS_RECEIVER_TYPE); | 3495 ASSERT(instance_type() >= FIRST_JS_RECEIVER_TYPE); |
3458 ASSERT((value->IsUndefined() && GetBackPointer()->IsMap()) || | 3496 ASSERT((value->IsUndefined() && GetBackPointer()->IsMap()) || |
3459 (value->IsMap() && GetBackPointer()->IsUndefined())); | 3497 (value->IsMap() && GetBackPointer()->IsUndefined())); |
3460 Object* object = READ_FIELD(this, kPrototypeTransitionsOrBackPointerOffset); | 3498 Object* object = READ_FIELD(this, kPrototypeTransitionsOrBackPointerOffset); |
3461 if (object->IsFixedArray()) { | 3499 if (object->IsFixedArray()) { |
3462 FixedArray::cast(object)->set( | 3500 FixedArray::cast(object)->set( |
3463 kProtoTransitionBackPointerOffset, value, mode); | 3501 kProtoTransitionBackPointerOffset, value, mode); |
3464 } else { | 3502 } else { |
(...skipping 577 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4042 heap->AllocateFixedArrayWithHoles(kElementsKindCount); | 4080 heap->AllocateFixedArrayWithHoles(kElementsKindCount); |
4043 FixedArray* maps; | 4081 FixedArray* maps; |
4044 if (!maybe_maps->To(&maps)) return maybe_maps; | 4082 if (!maybe_maps->To(&maps)) return maybe_maps; |
4045 | 4083 |
4046 Map* current_map = initial_map; | 4084 Map* current_map = initial_map; |
4047 ElementsKind kind = current_map->elements_kind(); | 4085 ElementsKind kind = current_map->elements_kind(); |
4048 ASSERT(kind == GetInitialFastElementsKind()); | 4086 ASSERT(kind == GetInitialFastElementsKind()); |
4049 maps->set(kind, current_map); | 4087 maps->set(kind, current_map); |
4050 for (int i = GetSequenceIndexFromFastElementsKind(kind) + 1; | 4088 for (int i = GetSequenceIndexFromFastElementsKind(kind) + 1; |
4051 i < kFastElementsKindCount; ++i) { | 4089 i < kFastElementsKindCount; ++i) { |
4052 ElementsKind transitioned_kind = GetFastElementsKindFromSequenceIndex(i); | 4090 Map* new_map; |
4053 MaybeObject* maybe_new_map = current_map->CopyDropTransitions(); | 4091 ElementsKind next_kind = GetFastElementsKindFromSequenceIndex(i); |
4054 Map* new_map = NULL; | 4092 MaybeObject* maybe_new_map = |
4055 if (!maybe_new_map->To<Map>(&new_map)) return maybe_new_map; | 4093 current_map->CreateNextElementsTransition(next_kind); |
4056 new_map->set_elements_kind(transitioned_kind); | 4094 if (!maybe_new_map->To(&new_map)) return maybe_new_map; |
4057 maybe_new_map = current_map->AddElementsTransition(transitioned_kind, | 4095 maps->set(next_kind, new_map); |
4058 new_map); | |
4059 if (maybe_new_map->IsFailure()) return maybe_new_map; | |
4060 maps->set(transitioned_kind, new_map); | |
4061 current_map = new_map; | 4096 current_map = new_map; |
4062 } | 4097 } |
4063 global_context->set_js_array_maps(maps); | 4098 global_context->set_js_array_maps(maps); |
4064 } | 4099 } |
4065 set_initial_map(initial_map); | 4100 set_initial_map(initial_map); |
4066 return this; | 4101 return this; |
4067 } | 4102 } |
4068 | 4103 |
4069 | 4104 |
4070 bool JSFunction::has_initial_map() { | 4105 bool JSFunction::has_initial_map() { |
(...skipping 991 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5062 #undef WRITE_UINT32_FIELD | 5097 #undef WRITE_UINT32_FIELD |
5063 #undef READ_SHORT_FIELD | 5098 #undef READ_SHORT_FIELD |
5064 #undef WRITE_SHORT_FIELD | 5099 #undef WRITE_SHORT_FIELD |
5065 #undef READ_BYTE_FIELD | 5100 #undef READ_BYTE_FIELD |
5066 #undef WRITE_BYTE_FIELD | 5101 #undef WRITE_BYTE_FIELD |
5067 | 5102 |
5068 | 5103 |
5069 } } // namespace v8::internal | 5104 } } // namespace v8::internal |
5070 | 5105 |
5071 #endif // V8_OBJECTS_INL_H_ | 5106 #endif // V8_OBJECTS_INL_H_ |
OLD | NEW |