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