Chromium Code Reviews| 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" | |
|
Jakob Kummerow
2012/06/29 16:31:36
As an exception from not relying on indirect #incl
Toon Verwaest
2012/07/05 12:56:11
Done.
| |
| 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 | |
|
Jakob Kummerow
2012/06/29 16:31:36
nit: missing space after '.'.
Toon Verwaest
2012/07/05 12:56:11
Done.
| |
| 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()); | |
|
Jakob Kummerow
2012/06/29 16:31:36
Please either (fix and) enable this or remove it.
Toon Verwaest
2012/07/05 12:56:11
Done.
| |
| 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; |
|
Michael Starzinger
2012/06/28 16:02:12
Somehow it feels wrong to return NULL here. Either
Toon Verwaest
2012/06/29 08:14:55
Done.
| |
| 1938 return NULL; | 2002 Object* array = get(kTransitionsIndex); |
| 1939 } | 2003 if (array->IsSmi()) return NULL; |
| 1940 Object* transition_map = get(kTransitionsIndex); | 2004 return TransitionArray::cast(array); |
| 1941 if (transition_map == Smi::FromInt(0)) { | |
| 1942 return NULL; | |
| 1943 } else { | |
| 1944 return Map::cast(transition_map); | |
| 1945 } | |
| 1946 } | 2005 } |
| 1947 | 2006 |
| 1948 | 2007 |
| 1949 void DescriptorArray::set_elements_transition_map( | 2008 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)); | 2009 WRITE_FIELD(this, kTransitionsOffset, Smi::FromInt(0)); |
| 1962 } | 2010 } |
| 1963 | 2011 |
| 1964 | 2012 |
| 2013 void DescriptorArray::set_transitions( | |
|
Jakob Kummerow
2012/06/29 16:31:36
nit: for declarations, each argument on its own li
Toon Verwaest
2012/07/05 12:56:11
Done.
| |
| 2014 TransitionArray* transitions_array, WriteBarrierMode mode) { | |
| 2015 Heap* heap = GetHeap(); | |
| 2016 WRITE_FIELD(this, kTransitionsOffset, transitions_array); | |
| 2017 CONDITIONAL_WRITE_BARRIER( | |
| 2018 heap, this, kTransitionsOffset, transitions_array, mode); | |
| 2019 } | |
| 2020 | |
| 2021 | |
| 1965 Object** DescriptorArray::GetKeySlot(int descriptor_number) { | 2022 Object** DescriptorArray::GetKeySlot(int descriptor_number) { |
| 1966 ASSERT(descriptor_number < number_of_descriptors()); | 2023 ASSERT(descriptor_number < number_of_descriptors()); |
| 1967 return HeapObject::RawField( | 2024 return HeapObject::RawField( |
| 1968 reinterpret_cast<HeapObject*>(this), | 2025 reinterpret_cast<HeapObject*>(this), |
| 1969 OffsetOfElementAt(ToKeyIndex(descriptor_number))); | 2026 OffsetOfElementAt(ToKeyIndex(descriptor_number))); |
| 1970 } | 2027 } |
| 1971 | 2028 |
| 1972 | 2029 |
| 1973 String* DescriptorArray::GetKey(int descriptor_number) { | 2030 String* DescriptorArray::GetKey(int descriptor_number) { |
| 1974 ASSERT(descriptor_number < number_of_descriptors()); | 2031 ASSERT(descriptor_number < number_of_descriptors()); |
| 1975 return String::cast(get(ToKeyIndex(descriptor_number))); | 2032 return String::cast(get(ToKeyIndex(descriptor_number))); |
| 1976 } | 2033 } |
| 1977 | 2034 |
| 1978 | 2035 |
| 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) { | 2036 Object** DescriptorArray::GetValueSlot(int descriptor_number) { |
| 1991 ASSERT(descriptor_number < number_of_descriptors()); | 2037 ASSERT(descriptor_number < number_of_descriptors()); |
| 1992 return HeapObject::RawField( | 2038 return HeapObject::RawField( |
| 1993 reinterpret_cast<HeapObject*>(this), | 2039 reinterpret_cast<HeapObject*>(this), |
| 1994 OffsetOfElementAt(ToValueIndex(descriptor_number))); | 2040 OffsetOfElementAt(ToValueIndex(descriptor_number))); |
| 1995 } | 2041 } |
| 1996 | 2042 |
| 1997 | 2043 |
| 1998 Object* DescriptorArray::GetValue(int descriptor_number) { | 2044 Object* DescriptorArray::GetValue(int descriptor_number) { |
| 1999 ASSERT(descriptor_number < number_of_descriptors()); | 2045 ASSERT(descriptor_number < number_of_descriptors()); |
| 2000 return get(ToValueIndex(descriptor_number)); | 2046 return get(ToValueIndex(descriptor_number)); |
| 2001 } | 2047 } |
| 2002 | 2048 |
| 2003 | 2049 |
| 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) { | 2050 PropertyDetails DescriptorArray::GetDetails(int descriptor_number) { |
| 2023 ASSERT(descriptor_number < number_of_descriptors()); | 2051 ASSERT(descriptor_number < number_of_descriptors()); |
| 2024 Object* details = get(ToDetailsIndex(descriptor_number)); | 2052 Object* details = get(ToDetailsIndex(descriptor_number)); |
| 2025 return PropertyDetails(Smi::cast(details)); | 2053 return PropertyDetails(Smi::cast(details)); |
| 2026 } | 2054 } |
| 2027 | 2055 |
| 2028 | 2056 |
| 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) { | 2057 PropertyType DescriptorArray::GetType(int descriptor_number) { |
| 2036 return GetDetails(descriptor_number).type(); | 2058 return GetDetails(descriptor_number).type(); |
| 2037 } | 2059 } |
| 2038 | 2060 |
| 2039 | 2061 |
| 2040 int DescriptorArray::GetFieldIndex(int descriptor_number) { | 2062 int DescriptorArray::GetFieldIndex(int descriptor_number) { |
| 2041 return Descriptor::IndexFromValue(GetValue(descriptor_number)); | 2063 return Descriptor::IndexFromValue(GetValue(descriptor_number)); |
| 2042 } | 2064 } |
| 2043 | 2065 |
| 2044 | 2066 |
| 2045 JSFunction* DescriptorArray::GetConstantFunction(int descriptor_number) { | 2067 JSFunction* DescriptorArray::GetConstantFunction(int descriptor_number) { |
| 2046 return JSFunction::cast(GetValue(descriptor_number)); | 2068 return JSFunction::cast(GetValue(descriptor_number)); |
| 2047 } | 2069 } |
| 2048 | 2070 |
| 2049 | 2071 |
| 2050 Object* DescriptorArray::GetCallbacksObject(int descriptor_number) { | 2072 Object* DescriptorArray::GetCallbacksObject(int descriptor_number) { |
| 2051 ASSERT(GetType(descriptor_number) == CALLBACKS); | 2073 ASSERT(GetType(descriptor_number) == CALLBACKS); |
| 2052 return GetValue(descriptor_number); | 2074 return GetValue(descriptor_number); |
| 2053 } | 2075 } |
| 2054 | 2076 |
| 2055 | 2077 |
| 2056 AccessorDescriptor* DescriptorArray::GetCallbacks(int descriptor_number) { | 2078 AccessorDescriptor* DescriptorArray::GetCallbacks(int descriptor_number) { |
| 2057 ASSERT(GetType(descriptor_number) == CALLBACKS); | 2079 ASSERT(GetType(descriptor_number) == CALLBACKS); |
| 2058 Foreign* p = Foreign::cast(GetCallbacksObject(descriptor_number)); | 2080 Foreign* p = Foreign::cast(GetCallbacksObject(descriptor_number)); |
| 2059 return reinterpret_cast<AccessorDescriptor*>(p->foreign_address()); | 2081 return reinterpret_cast<AccessorDescriptor*>(p->foreign_address()); |
| 2060 } | 2082 } |
| 2061 | 2083 |
| 2062 | 2084 |
| 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) { | 2085 void DescriptorArray::Get(int descriptor_number, Descriptor* desc) { |
| 2096 desc->Init(GetKey(descriptor_number), | 2086 desc->Init(GetKey(descriptor_number), |
| 2097 GetValue(descriptor_number), | 2087 GetValue(descriptor_number), |
| 2098 GetDetails(descriptor_number)); | 2088 GetDetails(descriptor_number)); |
| 2099 } | 2089 } |
| 2100 | 2090 |
| 2101 | 2091 |
| 2102 void DescriptorArray::Set(int descriptor_number, | 2092 void DescriptorArray::Set(int descriptor_number, |
| 2103 Descriptor* desc, | 2093 Descriptor* desc, |
| 2104 const WhitenessWitness&) { | 2094 const WhitenessWitness&) { |
| (...skipping 1319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3424 } | 3414 } |
| 3425 } | 3415 } |
| 3426 | 3416 |
| 3427 | 3417 |
| 3428 void Map::init_instance_descriptors() { | 3418 void Map::init_instance_descriptors() { |
| 3429 WRITE_FIELD(this, kInstanceDescriptorsOrBitField3Offset, Smi::FromInt(0)); | 3419 WRITE_FIELD(this, kInstanceDescriptorsOrBitField3Offset, Smi::FromInt(0)); |
| 3430 } | 3420 } |
| 3431 | 3421 |
| 3432 | 3422 |
| 3433 void Map::clear_instance_descriptors() { | 3423 void Map::clear_instance_descriptors() { |
| 3434 Object* object = READ_FIELD(this, | 3424 Object* object = READ_FIELD(this, kInstanceDescriptorsOrBitField3Offset); |
| 3435 kInstanceDescriptorsOrBitField3Offset); | |
| 3436 if (!object->IsSmi()) { | 3425 if (!object->IsSmi()) { |
| 3437 #ifdef DEBUG | |
| 3438 ZapInstanceDescriptors(); | |
| 3439 #endif | |
| 3440 WRITE_FIELD( | 3426 WRITE_FIELD( |
| 3441 this, | 3427 this, |
| 3442 kInstanceDescriptorsOrBitField3Offset, | 3428 kInstanceDescriptorsOrBitField3Offset, |
| 3443 Smi::FromInt(DescriptorArray::cast(object)->bit_field3_storage())); | 3429 Smi::FromInt(DescriptorArray::cast(object)->bit_field3_storage())); |
| 3444 } | 3430 } |
| 3445 } | 3431 } |
| 3446 | 3432 |
| 3447 | 3433 |
| 3448 void Map::set_instance_descriptors(DescriptorArray* value, | 3434 void Map::set_instance_descriptors(DescriptorArray* value, |
| 3449 WriteBarrierMode mode) { | 3435 WriteBarrierMode mode) { |
| 3450 Object* object = READ_FIELD(this, | 3436 Object* object = READ_FIELD(this, |
| 3451 kInstanceDescriptorsOrBitField3Offset); | 3437 kInstanceDescriptorsOrBitField3Offset); |
| 3452 Heap* heap = GetHeap(); | 3438 Heap* heap = GetHeap(); |
| 3453 if (value == heap->empty_descriptor_array()) { | 3439 if (value == heap->empty_descriptor_array()) { |
| 3454 clear_instance_descriptors(); | 3440 clear_instance_descriptors(); |
| 3455 return; | 3441 return; |
| 3456 } else { | 3442 } else { |
| 3457 if (object->IsSmi()) { | 3443 if (object->IsSmi()) { |
| 3458 value->set_bit_field3_storage(Smi::cast(object)->value()); | 3444 value->set_bit_field3_storage(Smi::cast(object)->value()); |
| 3459 } else { | 3445 } else { |
| 3460 value->set_bit_field3_storage( | 3446 value->set_bit_field3_storage( |
| 3461 DescriptorArray::cast(object)->bit_field3_storage()); | 3447 DescriptorArray::cast(object)->bit_field3_storage()); |
| 3462 } | 3448 } |
| 3463 } | 3449 } |
| 3464 ASSERT(!is_shared()); | 3450 ASSERT(!is_shared()); |
| 3465 #ifdef DEBUG | |
| 3466 if (value != instance_descriptors()) { | |
| 3467 ZapInstanceDescriptors(); | |
| 3468 } | |
| 3469 #endif | |
| 3470 WRITE_FIELD(this, kInstanceDescriptorsOrBitField3Offset, value); | 3451 WRITE_FIELD(this, kInstanceDescriptorsOrBitField3Offset, value); |
| 3471 CONDITIONAL_WRITE_BARRIER( | 3452 CONDITIONAL_WRITE_BARRIER( |
| 3472 heap, this, kInstanceDescriptorsOrBitField3Offset, value, mode); | 3453 heap, this, kInstanceDescriptorsOrBitField3Offset, value, mode); |
| 3473 } | 3454 } |
| 3474 | 3455 |
| 3475 | 3456 |
| 3476 int Map::bit_field3() { | 3457 int Map::bit_field3() { |
| 3477 Object* object = READ_FIELD(this, | 3458 Object* object = READ_FIELD(this, |
| 3478 kInstanceDescriptorsOrBitField3Offset); | 3459 kInstanceDescriptorsOrBitField3Offset); |
| 3479 if (object->IsSmi()) { | 3460 if (object->IsSmi()) { |
| 3480 return Smi::cast(object)->value(); | 3461 return Smi::cast(object)->value(); |
| 3481 } else { | 3462 } else { |
| 3482 return DescriptorArray::cast(object)->bit_field3_storage(); | 3463 return DescriptorArray::cast(object)->bit_field3_storage(); |
| 3483 } | 3464 } |
| 3484 } | 3465 } |
| 3485 | 3466 |
| 3486 | 3467 |
| 3487 void Map::ClearDescriptorArray() { | 3468 void Map::ClearDescriptorArray() { |
| 3488 int bitfield3 = bit_field3(); | 3469 int bitfield3 = bit_field3(); |
| 3489 #ifdef DEBUG | 3470 #ifdef DEBUG |
| 3490 Object* object = READ_FIELD(this, kInstanceDescriptorsOrBitField3Offset); | 3471 Object* object = READ_FIELD(this, kInstanceDescriptorsOrBitField3Offset); |
| 3491 if (!object->IsSmi()) { | 3472 if (!object->IsSmi()) { |
| 3492 ZapInstanceDescriptors(); | 3473 ZapTransitions(); |
| 3493 } | 3474 } |
| 3494 #endif | 3475 #endif |
| 3495 WRITE_FIELD(this, | 3476 WRITE_FIELD(this, |
| 3496 kInstanceDescriptorsOrBitField3Offset, | 3477 kInstanceDescriptorsOrBitField3Offset, |
| 3497 Smi::FromInt(bitfield3)); | 3478 Smi::FromInt(bitfield3)); |
| 3498 } | 3479 } |
| 3499 | 3480 |
| 3500 | 3481 |
| 3501 void Map::set_bit_field3(int value) { | 3482 void Map::set_bit_field3(int value) { |
| 3502 ASSERT(Smi::IsValid(value)); | 3483 ASSERT(Smi::IsValid(value)); |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 3514 Object* Map::GetBackPointer() { | 3495 Object* Map::GetBackPointer() { |
| 3515 Object* object = READ_FIELD(this, kPrototypeTransitionsOrBackPointerOffset); | 3496 Object* object = READ_FIELD(this, kPrototypeTransitionsOrBackPointerOffset); |
| 3516 if (object->IsFixedArray()) { | 3497 if (object->IsFixedArray()) { |
| 3517 return FixedArray::cast(object)->get(kProtoTransitionBackPointerOffset); | 3498 return FixedArray::cast(object)->get(kProtoTransitionBackPointerOffset); |
| 3518 } else { | 3499 } else { |
| 3519 return object; | 3500 return object; |
| 3520 } | 3501 } |
| 3521 } | 3502 } |
| 3522 | 3503 |
| 3523 | 3504 |
| 3505 bool Map::HasElementsTransition() { | |
| 3506 return HasTransitionArray() && transitions()->HasElementsTransition(); | |
| 3507 } | |
| 3508 | |
| 3509 | |
| 3510 bool Map::HasTransitionArray() { | |
| 3511 return instance_descriptors()->HasTransitionArray(); | |
| 3512 } | |
| 3513 | |
| 3514 | |
| 3524 Map* Map::elements_transition_map() { | 3515 Map* Map::elements_transition_map() { |
| 3525 return instance_descriptors()->elements_transition_map(); | 3516 return transitions()->elements(); |
| 3526 } | 3517 } |
| 3527 | 3518 |
| 3528 | 3519 |
| 3529 void Map::set_elements_transition_map(Map* transitioned_map) { | 3520 // If the descriptor is using the empty transition array, install a new empty |
| 3530 return instance_descriptors()->set_elements_transition_map(transitioned_map); | 3521 // transition array that will have place for an element transition. |
|
Jakob Kummerow
2012/06/29 16:31:36
nit:
// If the descriptor array does not have a t
Toon Verwaest
2012/07/05 12:56:11
Done.
| |
| 3522 static MaybeObject* AllowElementsTransition(Map* map) { | |
| 3523 if (map->HasTransitionArray()) return map; | |
| 3524 | |
| 3525 TransitionArray* transitions; | |
| 3526 MaybeObject* maybe_transitions = TransitionArray::Allocate(0); | |
| 3527 if (!maybe_transitions->To(&transitions)) return maybe_transitions; | |
| 3528 MaybeObject* added_transitions = map->set_transitions(transitions); | |
| 3529 if (added_transitions->IsFailure()) return added_transitions; | |
| 3530 return transitions; | |
| 3531 } | 3531 } |
| 3532 | 3532 |
| 3533 | 3533 |
| 3534 MaybeObject* Map::set_elements_transition_map(Map* transitioned_map) { | |
| 3535 MaybeObject* allow_elements = AllowElementsTransition(this); | |
| 3536 if (allow_elements->IsFailure()) return allow_elements; | |
| 3537 transitions()->set_elements(transitioned_map); | |
| 3538 return this; | |
| 3539 } | |
| 3540 | |
| 3541 | |
| 3542 TransitionArray* Map::transitions() { | |
| 3543 return instance_descriptors()->transitions(); | |
| 3544 } | |
| 3545 | |
| 3546 | |
| 3547 // If the map is using the empty descriptor array, install a new empty | |
|
Jakob Kummerow
2012/06/29 16:31:36
This comment is confusing. Maybe something like "I
Toon Verwaest
2012/07/05 12:56:11
Done.
| |
| 3548 // descriptor array that will contain an element transition. | |
| 3549 static MaybeObject* AllowTransitions(Map* map) { | |
| 3550 if (map->instance_descriptors()->MayContainTransitions()) return map; | |
| 3551 DescriptorArray* descriptors; | |
| 3552 MaybeObject* maybe_descriptors = | |
| 3553 DescriptorArray::Allocate(0, DescriptorArray::CANNOT_BE_SHARED); | |
| 3554 if (!maybe_descriptors->To(&descriptors)) return maybe_descriptors; | |
| 3555 map->set_instance_descriptors(descriptors); | |
| 3556 return descriptors; | |
| 3557 } | |
| 3558 | |
| 3559 | |
| 3560 void Map::ClearTransitions() { | |
| 3561 #ifdef DEBUG | |
| 3562 ZapTransitions(); | |
| 3563 #endif | |
| 3564 DescriptorArray* descriptors = instance_descriptors(); | |
| 3565 if (descriptors->number_of_descriptors() == 0) { | |
| 3566 ClearDescriptorArray(); | |
| 3567 } else { | |
| 3568 descriptors->ClearTransitions(); | |
| 3569 } | |
| 3570 } | |
| 3571 | |
| 3572 | |
| 3573 MaybeObject* Map::set_transitions(TransitionArray* transitions_array) { | |
| 3574 MaybeObject* allow_transitions = AllowTransitions(this); | |
| 3575 if (allow_transitions->IsFailure()) return allow_transitions; | |
| 3576 #ifdef DEBUG | |
| 3577 if (transitions_array == transitions()) { | |
|
Jakob Kummerow
2012/06/29 16:31:36
You can just do ASSERT(transitions_array != transi
Toon Verwaest
2012/07/05 12:56:11
Done.
| |
| 3578 UNREACHABLE(); | |
| 3579 } | |
| 3580 ZapTransitions(); | |
| 3581 #endif | |
| 3582 instance_descriptors()->set_transitions(transitions_array); | |
| 3583 return this; | |
| 3584 } | |
| 3585 | |
| 3586 | |
| 3534 void Map::SetBackPointer(Object* value, WriteBarrierMode mode) { | 3587 void Map::SetBackPointer(Object* value, WriteBarrierMode mode) { |
| 3535 Heap* heap = GetHeap(); | 3588 Heap* heap = GetHeap(); |
| 3536 ASSERT(instance_type() >= FIRST_JS_RECEIVER_TYPE); | 3589 ASSERT(instance_type() >= FIRST_JS_RECEIVER_TYPE); |
| 3537 ASSERT((value->IsUndefined() && GetBackPointer()->IsMap()) || | 3590 ASSERT((value->IsUndefined() && GetBackPointer()->IsMap()) || |
| 3538 (value->IsMap() && GetBackPointer()->IsUndefined())); | 3591 (value->IsMap() && GetBackPointer()->IsUndefined())); |
| 3539 Object* object = READ_FIELD(this, kPrototypeTransitionsOrBackPointerOffset); | 3592 Object* object = READ_FIELD(this, kPrototypeTransitionsOrBackPointerOffset); |
| 3540 if (object->IsFixedArray()) { | 3593 if (object->IsFixedArray()) { |
| 3541 FixedArray::cast(object)->set( | 3594 FixedArray::cast(object)->set( |
| 3542 kProtoTransitionBackPointerOffset, value, mode); | 3595 kProtoTransitionBackPointerOffset, value, mode); |
| 3543 } else { | 3596 } else { |
| (...skipping 1674 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5218 #undef WRITE_UINT32_FIELD | 5271 #undef WRITE_UINT32_FIELD |
| 5219 #undef READ_SHORT_FIELD | 5272 #undef READ_SHORT_FIELD |
| 5220 #undef WRITE_SHORT_FIELD | 5273 #undef WRITE_SHORT_FIELD |
| 5221 #undef READ_BYTE_FIELD | 5274 #undef READ_BYTE_FIELD |
| 5222 #undef WRITE_BYTE_FIELD | 5275 #undef WRITE_BYTE_FIELD |
| 5223 | 5276 |
| 5224 | 5277 |
| 5225 } } // namespace v8::internal | 5278 } } // namespace v8::internal |
| 5226 | 5279 |
| 5227 #endif // V8_OBJECTS_INL_H_ | 5280 #endif // V8_OBJECTS_INL_H_ |
| OLD | NEW |