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 |