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 29 matching lines...) Expand all Loading... |
40 #include "contexts.h" | 40 #include "contexts.h" |
41 #include "conversions-inl.h" | 41 #include "conversions-inl.h" |
42 #include "heap.h" | 42 #include "heap.h" |
43 #include "isolate.h" | 43 #include "isolate.h" |
44 #include "property.h" | 44 #include "property.h" |
45 #include "spaces.h" | 45 #include "spaces.h" |
46 #include "store-buffer.h" | 46 #include "store-buffer.h" |
47 #include "v8memory.h" | 47 #include "v8memory.h" |
48 #include "factory.h" | 48 #include "factory.h" |
49 #include "incremental-marking.h" | 49 #include "incremental-marking.h" |
| 50 #include "transitions-inl.h" |
50 | 51 |
51 namespace v8 { | 52 namespace v8 { |
52 namespace internal { | 53 namespace internal { |
53 | 54 |
54 PropertyDetails::PropertyDetails(Smi* smi) { | 55 PropertyDetails::PropertyDetails(Smi* smi) { |
55 value_ = smi->value(); | 56 value_ = smi->value(); |
56 } | 57 } |
57 | 58 |
58 | 59 |
59 Smi* PropertyDetails::AsSmi() { | 60 Smi* PropertyDetails::AsSmi() { |
(...skipping 457 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
517 TYPE_CHECKER(Map, MAP_TYPE) | 518 TYPE_CHECKER(Map, MAP_TYPE) |
518 TYPE_CHECKER(FixedArray, FIXED_ARRAY_TYPE) | 519 TYPE_CHECKER(FixedArray, FIXED_ARRAY_TYPE) |
519 TYPE_CHECKER(FixedDoubleArray, FIXED_DOUBLE_ARRAY_TYPE) | 520 TYPE_CHECKER(FixedDoubleArray, FIXED_DOUBLE_ARRAY_TYPE) |
520 | 521 |
521 | 522 |
522 bool Object::IsDescriptorArray() { | 523 bool Object::IsDescriptorArray() { |
523 return IsFixedArray(); | 524 return IsFixedArray(); |
524 } | 525 } |
525 | 526 |
526 | 527 |
| 528 bool Object::IsTransitionArray() { |
| 529 return IsFixedArray(); |
| 530 } |
| 531 |
| 532 |
527 bool Object::IsDeoptimizationInputData() { | 533 bool Object::IsDeoptimizationInputData() { |
528 // Must be a fixed array. | 534 // Must be a fixed array. |
529 if (!IsFixedArray()) return false; | 535 if (!IsFixedArray()) return false; |
530 | 536 |
531 // There's no sure way to detect the difference between a fixed array and | 537 // There's no sure way to detect the difference between a fixed array and |
532 // a deoptimization data array. Since this is used for asserts we can | 538 // a deoptimization data array. Since this is used for asserts we can |
533 // check that the length is zero or else the fixed size plus a multiple of | 539 // check that the length is zero or else the fixed size plus a multiple of |
534 // the entry size. | 540 // the entry size. |
535 int length = FixedArray::cast(this)->length(); | 541 int length = FixedArray::cast(this)->length(); |
536 if (length == 0) return true; | 542 if (length == 0) return true; |
(...skipping 1341 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1878 this == HEAP->empty_descriptor_array()); | 1884 this == HEAP->empty_descriptor_array()); |
1879 return length() < kFirstIndex; | 1885 return length() < kFirstIndex; |
1880 } | 1886 } |
1881 | 1887 |
1882 | 1888 |
1883 bool DescriptorArray::MayContainTransitions() { | 1889 bool DescriptorArray::MayContainTransitions() { |
1884 return !IsEmpty(); | 1890 return !IsEmpty(); |
1885 } | 1891 } |
1886 | 1892 |
1887 | 1893 |
| 1894 bool DescriptorArray::HasTransitionArray() { |
| 1895 return MayContainTransitions() && !get(kTransitionsIndex)->IsSmi(); |
| 1896 } |
| 1897 |
| 1898 |
1888 int DescriptorArray::bit_field3_storage() { | 1899 int DescriptorArray::bit_field3_storage() { |
1889 Object* storage = READ_FIELD(this, kBitField3StorageOffset); | 1900 Object* storage = READ_FIELD(this, kBitField3StorageOffset); |
1890 return Smi::cast(storage)->value(); | 1901 return Smi::cast(storage)->value(); |
1891 } | 1902 } |
1892 | 1903 |
1893 void DescriptorArray::set_bit_field3_storage(int value) { | 1904 void DescriptorArray::set_bit_field3_storage(int value) { |
1894 ASSERT(this->MayContainTransitions()); | 1905 ASSERT(length() > kBitField3StorageIndex); |
1895 WRITE_FIELD(this, kBitField3StorageOffset, Smi::FromInt(value)); | 1906 WRITE_FIELD(this, kBitField3StorageOffset, Smi::FromInt(value)); |
1896 } | 1907 } |
1897 | 1908 |
1898 | 1909 |
1899 void DescriptorArray::NoIncrementalWriteBarrierSwap(FixedArray* array, | 1910 void DescriptorArray::NoIncrementalWriteBarrierSwap(FixedArray* array, |
1900 int first, | 1911 int first, |
1901 int second) { | 1912 int second) { |
1902 Object* tmp = array->get(first); | 1913 Object* tmp = array->get(first); |
1903 NoIncrementalWriteBarrierSet(array, first, array->get(second)); | 1914 NoIncrementalWriteBarrierSet(array, first, array->get(second)); |
1904 NoIncrementalWriteBarrierSet(array, second, tmp); | 1915 NoIncrementalWriteBarrierSet(array, second, tmp); |
1905 } | 1916 } |
1906 | 1917 |
1907 | 1918 |
| 1919 // Perform a binary search in a fixed array. Low and high are entry indices. If |
| 1920 // there are three entries in this array it should be called with low=0 and |
| 1921 // high=2. |
| 1922 template<typename T> |
| 1923 int BinarySearch(T* array, String* name, int low, int high) { |
| 1924 uint32_t hash = name->Hash(); |
| 1925 int limit = high; |
| 1926 |
| 1927 ASSERT(low <= high); |
| 1928 |
| 1929 while (low != high) { |
| 1930 int mid = (low + high) / 2; |
| 1931 String* mid_name = array->GetKey(mid); |
| 1932 uint32_t mid_hash = mid_name->Hash(); |
| 1933 |
| 1934 if (mid_hash >= hash) { |
| 1935 high = mid; |
| 1936 } else { |
| 1937 low = mid + 1; |
| 1938 } |
| 1939 } |
| 1940 |
| 1941 for (; low <= limit && array->GetKey(low)->Hash() == hash; ++low) { |
| 1942 if (array->GetKey(low)->Equals(name)) return low; |
| 1943 } |
| 1944 |
| 1945 return T::kNotFound; |
| 1946 } |
| 1947 |
| 1948 |
| 1949 // Perform a linear search in this fixed array. len is the number of entry |
| 1950 // indices that are valid. |
| 1951 template<typename T> |
| 1952 int LinearSearch(T* array, SearchMode mode, String* name, int len) { |
| 1953 uint32_t hash = name->Hash(); |
| 1954 for (int number = 0; number < len; number++) { |
| 1955 String* entry = array->GetKey(number); |
| 1956 uint32_t current_hash = entry->Hash(); |
| 1957 if (mode == EXPECT_SORTED && current_hash > hash) break; |
| 1958 if (current_hash == hash && name->Equals(entry)) return number; |
| 1959 } |
| 1960 return T::kNotFound; |
| 1961 } |
| 1962 |
| 1963 |
| 1964 template<typename T> |
| 1965 int Search(T* array, String* name) { |
| 1966 SLOW_ASSERT(array->IsSortedNoDuplicates()); |
| 1967 |
| 1968 // Check for empty descriptor array. |
| 1969 int nof = array->number_of_entries(); |
| 1970 if (nof == 0) return T::kNotFound; |
| 1971 |
| 1972 // Fast case: do linear search for small arrays. |
| 1973 const int kMaxElementsForLinearSearch = 8; |
| 1974 if (StringShape(name).IsSymbol() && nof < kMaxElementsForLinearSearch) { |
| 1975 return LinearSearch(array, EXPECT_SORTED, name, nof); |
| 1976 } |
| 1977 |
| 1978 // Slow case: perform binary search. |
| 1979 return BinarySearch(array, name, 0, nof - 1); |
| 1980 } |
| 1981 |
| 1982 |
1908 int DescriptorArray::Search(String* name) { | 1983 int DescriptorArray::Search(String* name) { |
1909 SLOW_ASSERT(IsSortedNoDuplicates()); | 1984 return internal::Search(this, name); |
1910 | |
1911 // Check for empty descriptor array. | |
1912 int nof = number_of_descriptors(); | |
1913 if (nof == 0) return kNotFound; | |
1914 | |
1915 // Fast case: do linear search for small arrays. | |
1916 const int kMaxElementsForLinearSearch = 8; | |
1917 if (StringShape(name).IsSymbol() && nof < kMaxElementsForLinearSearch) { | |
1918 return LinearSearch(EXPECT_SORTED, name, nof); | |
1919 } | |
1920 | |
1921 // Slow case: perform binary search. | |
1922 return BinarySearch(name, 0, nof - 1); | |
1923 } | 1985 } |
1924 | 1986 |
1925 | 1987 |
1926 int DescriptorArray::SearchWithCache(String* name) { | 1988 int DescriptorArray::SearchWithCache(String* name) { |
1927 int number = GetIsolate()->descriptor_lookup_cache()->Lookup(this, name); | 1989 DescriptorLookupCache* cache = GetIsolate()->descriptor_lookup_cache(); |
| 1990 int number = cache->Lookup(this, name); |
1928 if (number == DescriptorLookupCache::kAbsent) { | 1991 if (number == DescriptorLookupCache::kAbsent) { |
1929 number = Search(name); | 1992 number = internal::Search(this, name); |
1930 GetIsolate()->descriptor_lookup_cache()->Update(this, name, number); | 1993 cache->Update(this, name, number); |
1931 } | 1994 } |
1932 return number; | 1995 return number; |
1933 } | 1996 } |
1934 | 1997 |
1935 | 1998 |
1936 Map* DescriptorArray::elements_transition_map() { | 1999 TransitionArray* DescriptorArray::transitions() { |
1937 if (!this->MayContainTransitions()) { | 2000 if (!this->MayContainTransitions()) return NULL; |
1938 return NULL; | 2001 Object* array = get(kTransitionsIndex); |
1939 } | 2002 return TransitionArray::cast(array); |
1940 Object* transition_map = get(kTransitionsIndex); | |
1941 if (transition_map == Smi::FromInt(0)) { | |
1942 return NULL; | |
1943 } else { | |
1944 return Map::cast(transition_map); | |
1945 } | |
1946 } | 2003 } |
1947 | 2004 |
1948 | 2005 |
1949 void DescriptorArray::set_elements_transition_map( | 2006 void DescriptorArray::ClearTransitions() { |
1950 Map* transition_map, WriteBarrierMode mode) { | |
1951 ASSERT(this->length() > kTransitionsIndex); | |
1952 Heap* heap = GetHeap(); | |
1953 WRITE_FIELD(this, kTransitionsOffset, transition_map); | |
1954 CONDITIONAL_WRITE_BARRIER( | |
1955 heap, this, kTransitionsOffset, transition_map, mode); | |
1956 ASSERT(DescriptorArray::cast(this)); | |
1957 } | |
1958 | |
1959 | |
1960 void DescriptorArray::ClearElementsTransition() { | |
1961 WRITE_FIELD(this, kTransitionsOffset, Smi::FromInt(0)); | 2007 WRITE_FIELD(this, kTransitionsOffset, Smi::FromInt(0)); |
1962 } | 2008 } |
1963 | 2009 |
1964 | 2010 |
| 2011 void DescriptorArray::set_transitions(TransitionArray* transitions_array, |
| 2012 WriteBarrierMode mode) { |
| 2013 Heap* heap = GetHeap(); |
| 2014 WRITE_FIELD(this, kTransitionsOffset, transitions_array); |
| 2015 CONDITIONAL_WRITE_BARRIER( |
| 2016 heap, this, kTransitionsOffset, transitions_array, mode); |
| 2017 } |
| 2018 |
| 2019 |
1965 Object** DescriptorArray::GetKeySlot(int descriptor_number) { | 2020 Object** DescriptorArray::GetKeySlot(int descriptor_number) { |
1966 ASSERT(descriptor_number < number_of_descriptors()); | 2021 ASSERT(descriptor_number < number_of_descriptors()); |
1967 return HeapObject::RawField( | 2022 return HeapObject::RawField( |
1968 reinterpret_cast<HeapObject*>(this), | 2023 reinterpret_cast<HeapObject*>(this), |
1969 OffsetOfElementAt(ToKeyIndex(descriptor_number))); | 2024 OffsetOfElementAt(ToKeyIndex(descriptor_number))); |
1970 } | 2025 } |
1971 | 2026 |
1972 | 2027 |
1973 String* DescriptorArray::GetKey(int descriptor_number) { | 2028 String* DescriptorArray::GetKey(int descriptor_number) { |
1974 ASSERT(descriptor_number < number_of_descriptors()); | 2029 ASSERT(descriptor_number < number_of_descriptors()); |
1975 return String::cast(get(ToKeyIndex(descriptor_number))); | 2030 return String::cast(get(ToKeyIndex(descriptor_number))); |
1976 } | 2031 } |
1977 | 2032 |
1978 | 2033 |
1979 void DescriptorArray::SetKeyUnchecked(Heap* heap, | |
1980 int descriptor_number, | |
1981 String* key) { | |
1982 ASSERT(descriptor_number < number_of_descriptors()); | |
1983 set_unchecked(heap, | |
1984 ToKeyIndex(descriptor_number), | |
1985 key, | |
1986 UPDATE_WRITE_BARRIER); | |
1987 } | |
1988 | |
1989 | |
1990 Object** DescriptorArray::GetValueSlot(int descriptor_number) { | 2034 Object** DescriptorArray::GetValueSlot(int descriptor_number) { |
1991 ASSERT(descriptor_number < number_of_descriptors()); | 2035 ASSERT(descriptor_number < number_of_descriptors()); |
1992 return HeapObject::RawField( | 2036 return HeapObject::RawField( |
1993 reinterpret_cast<HeapObject*>(this), | 2037 reinterpret_cast<HeapObject*>(this), |
1994 OffsetOfElementAt(ToValueIndex(descriptor_number))); | 2038 OffsetOfElementAt(ToValueIndex(descriptor_number))); |
1995 } | 2039 } |
1996 | 2040 |
1997 | 2041 |
1998 Object* DescriptorArray::GetValue(int descriptor_number) { | 2042 Object* DescriptorArray::GetValue(int descriptor_number) { |
1999 ASSERT(descriptor_number < number_of_descriptors()); | 2043 ASSERT(descriptor_number < number_of_descriptors()); |
2000 return get(ToValueIndex(descriptor_number)); | 2044 return get(ToValueIndex(descriptor_number)); |
2001 } | 2045 } |
2002 | 2046 |
2003 | 2047 |
2004 void DescriptorArray::SetNullValueUnchecked(Heap* heap, int descriptor_number) { | |
2005 ASSERT(descriptor_number < number_of_descriptors()); | |
2006 set_null_unchecked(heap, ToValueIndex(descriptor_number)); | |
2007 } | |
2008 | |
2009 | |
2010 | |
2011 void DescriptorArray::SetValueUnchecked(Heap* heap, | |
2012 int descriptor_number, | |
2013 Object* value) { | |
2014 ASSERT(descriptor_number < number_of_descriptors()); | |
2015 set_unchecked(heap, | |
2016 ToValueIndex(descriptor_number), | |
2017 value, | |
2018 UPDATE_WRITE_BARRIER); | |
2019 } | |
2020 | |
2021 | |
2022 PropertyDetails DescriptorArray::GetDetails(int descriptor_number) { | 2048 PropertyDetails DescriptorArray::GetDetails(int descriptor_number) { |
2023 ASSERT(descriptor_number < number_of_descriptors()); | 2049 ASSERT(descriptor_number < number_of_descriptors()); |
2024 Object* details = get(ToDetailsIndex(descriptor_number)); | 2050 Object* details = get(ToDetailsIndex(descriptor_number)); |
2025 return PropertyDetails(Smi::cast(details)); | 2051 return PropertyDetails(Smi::cast(details)); |
2026 } | 2052 } |
2027 | 2053 |
2028 | 2054 |
2029 void DescriptorArray::SetDetailsUnchecked(int descriptor_number, Smi* value) { | |
2030 ASSERT(descriptor_number < number_of_descriptors()); | |
2031 set_unchecked(ToDetailsIndex(descriptor_number), value); | |
2032 } | |
2033 | |
2034 | |
2035 PropertyType DescriptorArray::GetType(int descriptor_number) { | 2055 PropertyType DescriptorArray::GetType(int descriptor_number) { |
2036 return GetDetails(descriptor_number).type(); | 2056 return GetDetails(descriptor_number).type(); |
2037 } | 2057 } |
2038 | 2058 |
2039 | 2059 |
2040 int DescriptorArray::GetFieldIndex(int descriptor_number) { | 2060 int DescriptorArray::GetFieldIndex(int descriptor_number) { |
2041 return Descriptor::IndexFromValue(GetValue(descriptor_number)); | 2061 return Descriptor::IndexFromValue(GetValue(descriptor_number)); |
2042 } | 2062 } |
2043 | 2063 |
2044 | 2064 |
2045 JSFunction* DescriptorArray::GetConstantFunction(int descriptor_number) { | 2065 JSFunction* DescriptorArray::GetConstantFunction(int descriptor_number) { |
2046 return JSFunction::cast(GetValue(descriptor_number)); | 2066 return JSFunction::cast(GetValue(descriptor_number)); |
2047 } | 2067 } |
2048 | 2068 |
2049 | 2069 |
2050 Object* DescriptorArray::GetCallbacksObject(int descriptor_number) { | 2070 Object* DescriptorArray::GetCallbacksObject(int descriptor_number) { |
2051 ASSERT(GetType(descriptor_number) == CALLBACKS); | 2071 ASSERT(GetType(descriptor_number) == CALLBACKS); |
2052 return GetValue(descriptor_number); | 2072 return GetValue(descriptor_number); |
2053 } | 2073 } |
2054 | 2074 |
2055 | 2075 |
2056 AccessorDescriptor* DescriptorArray::GetCallbacks(int descriptor_number) { | 2076 AccessorDescriptor* DescriptorArray::GetCallbacks(int descriptor_number) { |
2057 ASSERT(GetType(descriptor_number) == CALLBACKS); | 2077 ASSERT(GetType(descriptor_number) == CALLBACKS); |
2058 Foreign* p = Foreign::cast(GetCallbacksObject(descriptor_number)); | 2078 Foreign* p = Foreign::cast(GetCallbacksObject(descriptor_number)); |
2059 return reinterpret_cast<AccessorDescriptor*>(p->foreign_address()); | 2079 return reinterpret_cast<AccessorDescriptor*>(p->foreign_address()); |
2060 } | 2080 } |
2061 | 2081 |
2062 | 2082 |
2063 bool DescriptorArray::IsProperty(int descriptor_number) { | |
2064 Entry entry(this, descriptor_number); | |
2065 return IsPropertyDescriptor(&entry); | |
2066 } | |
2067 | |
2068 | |
2069 bool DescriptorArray::IsTransitionOnly(int descriptor_number) { | |
2070 switch (GetType(descriptor_number)) { | |
2071 case MAP_TRANSITION: | |
2072 case CONSTANT_TRANSITION: | |
2073 return true; | |
2074 case CALLBACKS: { | |
2075 Object* value = GetValue(descriptor_number); | |
2076 if (!value->IsAccessorPair()) return false; | |
2077 AccessorPair* accessors = AccessorPair::cast(value); | |
2078 return accessors->getter()->IsMap() && accessors->setter()->IsMap(); | |
2079 } | |
2080 case NORMAL: | |
2081 case FIELD: | |
2082 case CONSTANT_FUNCTION: | |
2083 case HANDLER: | |
2084 case INTERCEPTOR: | |
2085 return false; | |
2086 case NONEXISTENT: | |
2087 UNREACHABLE(); | |
2088 break; | |
2089 } | |
2090 UNREACHABLE(); // Keep the compiler happy. | |
2091 return false; | |
2092 } | |
2093 | |
2094 | |
2095 void DescriptorArray::Get(int descriptor_number, Descriptor* desc) { | 2083 void DescriptorArray::Get(int descriptor_number, Descriptor* desc) { |
2096 desc->Init(GetKey(descriptor_number), | 2084 desc->Init(GetKey(descriptor_number), |
2097 GetValue(descriptor_number), | 2085 GetValue(descriptor_number), |
2098 GetDetails(descriptor_number)); | 2086 GetDetails(descriptor_number)); |
2099 } | 2087 } |
2100 | 2088 |
2101 | 2089 |
2102 void DescriptorArray::Set(int descriptor_number, | 2090 void DescriptorArray::Set(int descriptor_number, |
2103 Descriptor* desc, | 2091 Descriptor* desc, |
2104 const WhitenessWitness&) { | 2092 const WhitenessWitness&) { |
(...skipping 17 matching lines...) Expand all Loading... |
2122 NoIncrementalWriteBarrierSwap(this, ToKeyIndex(first), ToKeyIndex(second)); | 2110 NoIncrementalWriteBarrierSwap(this, ToKeyIndex(first), ToKeyIndex(second)); |
2123 NoIncrementalWriteBarrierSwap(this, | 2111 NoIncrementalWriteBarrierSwap(this, |
2124 ToValueIndex(first), | 2112 ToValueIndex(first), |
2125 ToValueIndex(second)); | 2113 ToValueIndex(second)); |
2126 NoIncrementalWriteBarrierSwap(this, | 2114 NoIncrementalWriteBarrierSwap(this, |
2127 ToDetailsIndex(first), | 2115 ToDetailsIndex(first), |
2128 ToDetailsIndex(second)); | 2116 ToDetailsIndex(second)); |
2129 } | 2117 } |
2130 | 2118 |
2131 | 2119 |
2132 DescriptorArray::WhitenessWitness::WhitenessWitness(DescriptorArray* array) | 2120 FixedArray::WhitenessWitness::WhitenessWitness(FixedArray* array) |
2133 : marking_(array->GetHeap()->incremental_marking()) { | 2121 : marking_(array->GetHeap()->incremental_marking()) { |
2134 marking_->EnterNoMarkingScope(); | 2122 marking_->EnterNoMarkingScope(); |
2135 if (array->number_of_descriptors() > 0) { | 2123 ASSERT(Marking::Color(array) == Marking::WHITE_OBJECT); |
2136 ASSERT(Marking::Color(array) == Marking::WHITE_OBJECT); | |
2137 } | |
2138 } | 2124 } |
2139 | 2125 |
2140 | 2126 |
2141 DescriptorArray::WhitenessWitness::~WhitenessWitness() { | 2127 FixedArray::WhitenessWitness::~WhitenessWitness() { |
2142 marking_->LeaveNoMarkingScope(); | 2128 marking_->LeaveNoMarkingScope(); |
2143 } | 2129 } |
2144 | 2130 |
2145 | 2131 |
2146 template<typename Shape, typename Key> | 2132 template<typename Shape, typename Key> |
2147 int HashTable<Shape, Key>::ComputeCapacity(int at_least_space_for) { | 2133 int HashTable<Shape, Key>::ComputeCapacity(int at_least_space_for) { |
2148 const int kMinCapacity = 32; | 2134 const int kMinCapacity = 32; |
2149 int capacity = RoundUpToPowerOf2(at_least_space_for * 2); | 2135 int capacity = RoundUpToPowerOf2(at_least_space_for * 2); |
2150 if (capacity < kMinCapacity) { | 2136 if (capacity < kMinCapacity) { |
2151 capacity = kMinCapacity; // Guarantee min capacity. | 2137 capacity = kMinCapacity; // Guarantee min capacity. |
(...skipping 1272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3424 } | 3410 } |
3425 } | 3411 } |
3426 | 3412 |
3427 | 3413 |
3428 void Map::init_instance_descriptors() { | 3414 void Map::init_instance_descriptors() { |
3429 WRITE_FIELD(this, kInstanceDescriptorsOrBitField3Offset, Smi::FromInt(0)); | 3415 WRITE_FIELD(this, kInstanceDescriptorsOrBitField3Offset, Smi::FromInt(0)); |
3430 } | 3416 } |
3431 | 3417 |
3432 | 3418 |
3433 void Map::clear_instance_descriptors() { | 3419 void Map::clear_instance_descriptors() { |
3434 Object* object = READ_FIELD(this, | 3420 Object* object = READ_FIELD(this, kInstanceDescriptorsOrBitField3Offset); |
3435 kInstanceDescriptorsOrBitField3Offset); | |
3436 if (!object->IsSmi()) { | 3421 if (!object->IsSmi()) { |
3437 #ifdef DEBUG | |
3438 ZapInstanceDescriptors(); | |
3439 #endif | |
3440 WRITE_FIELD( | 3422 WRITE_FIELD( |
3441 this, | 3423 this, |
3442 kInstanceDescriptorsOrBitField3Offset, | 3424 kInstanceDescriptorsOrBitField3Offset, |
3443 Smi::FromInt(DescriptorArray::cast(object)->bit_field3_storage())); | 3425 Smi::FromInt(DescriptorArray::cast(object)->bit_field3_storage())); |
3444 } | 3426 } |
3445 } | 3427 } |
3446 | 3428 |
3447 | 3429 |
3448 void Map::set_instance_descriptors(DescriptorArray* value, | 3430 void Map::set_instance_descriptors(DescriptorArray* value, |
3449 WriteBarrierMode mode) { | 3431 WriteBarrierMode mode) { |
3450 Object* object = READ_FIELD(this, | 3432 Object* object = READ_FIELD(this, |
3451 kInstanceDescriptorsOrBitField3Offset); | 3433 kInstanceDescriptorsOrBitField3Offset); |
3452 Heap* heap = GetHeap(); | 3434 Heap* heap = GetHeap(); |
3453 if (value == heap->empty_descriptor_array()) { | 3435 if (value == heap->empty_descriptor_array()) { |
3454 clear_instance_descriptors(); | 3436 clear_instance_descriptors(); |
3455 return; | 3437 return; |
3456 } else { | 3438 } else { |
3457 if (object->IsSmi()) { | 3439 if (object->IsSmi()) { |
3458 value->set_bit_field3_storage(Smi::cast(object)->value()); | 3440 value->set_bit_field3_storage(Smi::cast(object)->value()); |
3459 } else { | 3441 } else { |
3460 value->set_bit_field3_storage( | 3442 value->set_bit_field3_storage( |
3461 DescriptorArray::cast(object)->bit_field3_storage()); | 3443 DescriptorArray::cast(object)->bit_field3_storage()); |
3462 } | 3444 } |
3463 } | 3445 } |
3464 ASSERT(!is_shared()); | 3446 ASSERT(!is_shared()); |
3465 #ifdef DEBUG | |
3466 if (value != instance_descriptors()) { | |
3467 ZapInstanceDescriptors(); | |
3468 } | |
3469 #endif | |
3470 WRITE_FIELD(this, kInstanceDescriptorsOrBitField3Offset, value); | 3447 WRITE_FIELD(this, kInstanceDescriptorsOrBitField3Offset, value); |
3471 CONDITIONAL_WRITE_BARRIER( | 3448 CONDITIONAL_WRITE_BARRIER( |
3472 heap, this, kInstanceDescriptorsOrBitField3Offset, value, mode); | 3449 heap, this, kInstanceDescriptorsOrBitField3Offset, value, mode); |
3473 } | 3450 } |
3474 | 3451 |
3475 | 3452 |
3476 int Map::bit_field3() { | 3453 int Map::bit_field3() { |
3477 Object* object = READ_FIELD(this, | 3454 Object* object = READ_FIELD(this, |
3478 kInstanceDescriptorsOrBitField3Offset); | 3455 kInstanceDescriptorsOrBitField3Offset); |
3479 if (object->IsSmi()) { | 3456 if (object->IsSmi()) { |
3480 return Smi::cast(object)->value(); | 3457 return Smi::cast(object)->value(); |
3481 } else { | 3458 } else { |
3482 return DescriptorArray::cast(object)->bit_field3_storage(); | 3459 return DescriptorArray::cast(object)->bit_field3_storage(); |
3483 } | 3460 } |
3484 } | 3461 } |
3485 | 3462 |
3486 | 3463 |
3487 void Map::ClearDescriptorArray() { | 3464 void Map::ClearDescriptorArray() { |
3488 int bitfield3 = bit_field3(); | 3465 int bitfield3 = bit_field3(); |
3489 #ifdef DEBUG | 3466 #ifdef DEBUG |
3490 Object* object = READ_FIELD(this, kInstanceDescriptorsOrBitField3Offset); | 3467 Object* object = READ_FIELD(this, kInstanceDescriptorsOrBitField3Offset); |
3491 if (!object->IsSmi()) { | 3468 if (!object->IsSmi()) { |
3492 ZapInstanceDescriptors(); | 3469 ZapTransitions(); |
3493 } | 3470 } |
3494 #endif | 3471 #endif |
3495 WRITE_FIELD(this, | 3472 WRITE_FIELD(this, |
3496 kInstanceDescriptorsOrBitField3Offset, | 3473 kInstanceDescriptorsOrBitField3Offset, |
3497 Smi::FromInt(bitfield3)); | 3474 Smi::FromInt(bitfield3)); |
3498 } | 3475 } |
3499 | 3476 |
3500 | 3477 |
3501 void Map::set_bit_field3(int value) { | 3478 void Map::set_bit_field3(int value) { |
3502 ASSERT(Smi::IsValid(value)); | 3479 ASSERT(Smi::IsValid(value)); |
(...skipping 11 matching lines...) Expand all Loading... |
3514 Object* Map::GetBackPointer() { | 3491 Object* Map::GetBackPointer() { |
3515 Object* object = READ_FIELD(this, kPrototypeTransitionsOrBackPointerOffset); | 3492 Object* object = READ_FIELD(this, kPrototypeTransitionsOrBackPointerOffset); |
3516 if (object->IsFixedArray()) { | 3493 if (object->IsFixedArray()) { |
3517 return FixedArray::cast(object)->get(kProtoTransitionBackPointerOffset); | 3494 return FixedArray::cast(object)->get(kProtoTransitionBackPointerOffset); |
3518 } else { | 3495 } else { |
3519 return object; | 3496 return object; |
3520 } | 3497 } |
3521 } | 3498 } |
3522 | 3499 |
3523 | 3500 |
| 3501 bool Map::HasElementsTransition() { |
| 3502 return HasTransitionArray() && transitions()->HasElementsTransition(); |
| 3503 } |
| 3504 |
| 3505 |
| 3506 bool Map::HasTransitionArray() { |
| 3507 return instance_descriptors()->HasTransitionArray(); |
| 3508 } |
| 3509 |
| 3510 |
3524 Map* Map::elements_transition_map() { | 3511 Map* Map::elements_transition_map() { |
3525 return instance_descriptors()->elements_transition_map(); | 3512 return transitions()->elements_transition(); |
3526 } | 3513 } |
3527 | 3514 |
3528 | 3515 |
3529 void Map::set_elements_transition_map(Map* transitioned_map) { | 3516 MaybeObject* Map::AddTransition(String* key, Object* value) { |
3530 return instance_descriptors()->set_elements_transition_map(transitioned_map); | 3517 if (HasTransitionArray()) return transitions()->CopyInsert(key, value); |
| 3518 return TransitionArray::NewWith(key, value); |
3531 } | 3519 } |
3532 | 3520 |
3533 | 3521 |
| 3522 // If the map does not have a descriptor array, install a new empty |
| 3523 // descriptor array that has room for a transition array. |
| 3524 static MaybeObject* AllowTransitions(Map* map) { |
| 3525 if (map->instance_descriptors()->MayContainTransitions()) return map; |
| 3526 DescriptorArray* descriptors; |
| 3527 MaybeObject* maybe_descriptors = |
| 3528 DescriptorArray::Allocate(0, DescriptorArray::CANNOT_BE_SHARED); |
| 3529 if (!maybe_descriptors->To(&descriptors)) return maybe_descriptors; |
| 3530 map->set_instance_descriptors(descriptors); |
| 3531 return descriptors; |
| 3532 } |
| 3533 |
| 3534 |
| 3535 // If the descriptor does not have a transition array, install a new |
| 3536 // transition array that has room for an element transition. |
| 3537 static MaybeObject* AllowElementsTransition(Map* map) { |
| 3538 if (map->HasTransitionArray()) return map; |
| 3539 |
| 3540 AllowTransitions(map); |
| 3541 |
| 3542 TransitionArray* transitions; |
| 3543 MaybeObject* maybe_transitions = TransitionArray::Allocate(0); |
| 3544 if (!maybe_transitions->To(&transitions)) return maybe_transitions; |
| 3545 MaybeObject* added_transitions = map->set_transitions(transitions); |
| 3546 if (added_transitions->IsFailure()) return added_transitions; |
| 3547 return transitions; |
| 3548 } |
| 3549 |
| 3550 |
| 3551 MaybeObject* Map::set_elements_transition_map(Map* transitioned_map) { |
| 3552 MaybeObject* allow_elements = AllowElementsTransition(this); |
| 3553 if (allow_elements->IsFailure()) return allow_elements; |
| 3554 transitions()->set_elements_transition(transitioned_map); |
| 3555 return this; |
| 3556 } |
| 3557 |
| 3558 |
| 3559 TransitionArray* Map::transitions() { |
| 3560 return instance_descriptors()->transitions(); |
| 3561 } |
| 3562 |
| 3563 |
| 3564 void Map::ClearTransitions() { |
| 3565 #ifdef DEBUG |
| 3566 ZapTransitions(); |
| 3567 #endif |
| 3568 DescriptorArray* descriptors = instance_descriptors(); |
| 3569 if (descriptors->number_of_descriptors() == 0) { |
| 3570 ClearDescriptorArray(); |
| 3571 } else { |
| 3572 descriptors->ClearTransitions(); |
| 3573 } |
| 3574 } |
| 3575 |
| 3576 |
| 3577 MaybeObject* Map::set_transitions(TransitionArray* transitions_array) { |
| 3578 MaybeObject* allow_transitions = AllowTransitions(this); |
| 3579 if (allow_transitions->IsFailure()) return allow_transitions; |
| 3580 #ifdef DEBUG |
| 3581 if (HasTransitionArray()) { |
| 3582 ASSERT(transitions() != transitions_array); |
| 3583 ZapTransitions(); |
| 3584 } |
| 3585 #endif |
| 3586 instance_descriptors()->set_transitions(transitions_array); |
| 3587 return this; |
| 3588 } |
| 3589 |
| 3590 |
3534 void Map::SetBackPointer(Object* value, WriteBarrierMode mode) { | 3591 void Map::SetBackPointer(Object* value, WriteBarrierMode mode) { |
3535 Heap* heap = GetHeap(); | 3592 Heap* heap = GetHeap(); |
3536 ASSERT(instance_type() >= FIRST_JS_RECEIVER_TYPE); | 3593 ASSERT(instance_type() >= FIRST_JS_RECEIVER_TYPE); |
3537 ASSERT((value->IsUndefined() && GetBackPointer()->IsMap()) || | 3594 ASSERT((value->IsUndefined() && GetBackPointer()->IsMap()) || |
3538 (value->IsMap() && GetBackPointer()->IsUndefined())); | 3595 (value->IsMap() && GetBackPointer()->IsUndefined())); |
3539 Object* object = READ_FIELD(this, kPrototypeTransitionsOrBackPointerOffset); | 3596 Object* object = READ_FIELD(this, kPrototypeTransitionsOrBackPointerOffset); |
3540 if (object->IsFixedArray()) { | 3597 if (object->IsFixedArray()) { |
3541 FixedArray::cast(object)->set( | 3598 FixedArray::cast(object)->set( |
3542 kProtoTransitionBackPointerOffset, value, mode); | 3599 kProtoTransitionBackPointerOffset, value, mode); |
3543 } else { | 3600 } else { |
(...skipping 1674 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5218 #undef WRITE_UINT32_FIELD | 5275 #undef WRITE_UINT32_FIELD |
5219 #undef READ_SHORT_FIELD | 5276 #undef READ_SHORT_FIELD |
5220 #undef WRITE_SHORT_FIELD | 5277 #undef WRITE_SHORT_FIELD |
5221 #undef READ_BYTE_FIELD | 5278 #undef READ_BYTE_FIELD |
5222 #undef WRITE_BYTE_FIELD | 5279 #undef WRITE_BYTE_FIELD |
5223 | 5280 |
5224 | 5281 |
5225 } } // namespace v8::internal | 5282 } } // namespace v8::internal |
5226 | 5283 |
5227 #endif // V8_OBJECTS_INL_H_ | 5284 #endif // V8_OBJECTS_INL_H_ |
OLD | NEW |