OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <iomanip> | 5 #include <iomanip> |
6 #include <sstream> | 6 #include <sstream> |
7 | 7 |
8 #include "src/v8.h" | 8 #include "src/v8.h" |
9 | 9 |
10 #include "src/accessors.h" | 10 #include "src/accessors.h" |
(...skipping 1904 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1915 // For slow-to-fast migrations JSObject::TransformToFastProperties() | 1915 // For slow-to-fast migrations JSObject::TransformToFastProperties() |
1916 // must be used instead. | 1916 // must be used instead. |
1917 CHECK(new_map->is_dictionary_map()); | 1917 CHECK(new_map->is_dictionary_map()); |
1918 | 1918 |
1919 // Slow-to-slow migration is trivial. | 1919 // Slow-to-slow migration is trivial. |
1920 object->set_map(*new_map); | 1920 object->set_map(*new_map); |
1921 } | 1921 } |
1922 } | 1922 } |
1923 | 1923 |
1924 | 1924 |
| 1925 // Returns true if during migration from |old_map| to |new_map| "tagged" |
| 1926 // inobject fields are going to be replaced with unboxed double fields. |
| 1927 static bool ShouldClearSlotsRecorded(Map* old_map, Map* new_map, |
| 1928 int new_number_of_fields) { |
| 1929 DisallowHeapAllocation no_gc; |
| 1930 int inobject = new_map->inobject_properties(); |
| 1931 DCHECK(inobject <= old_map->inobject_properties()); |
| 1932 |
| 1933 int limit = Min(inobject, new_number_of_fields); |
| 1934 for (int i = 0; i < limit; i++) { |
| 1935 FieldIndex index = FieldIndex::ForPropertyIndex(new_map, i); |
| 1936 if (new_map->IsUnboxedDoubleField(index) && |
| 1937 !old_map->IsUnboxedDoubleField(index)) { |
| 1938 return true; |
| 1939 } |
| 1940 } |
| 1941 return false; |
| 1942 } |
| 1943 |
| 1944 |
| 1945 static void RemoveOldToOldSlotsRecorded(Heap* heap, JSObject* object, |
| 1946 FieldIndex index) { |
| 1947 DisallowHeapAllocation no_gc; |
| 1948 |
| 1949 Object* old_value = object->RawFastPropertyAt(index); |
| 1950 if (old_value->IsHeapObject()) { |
| 1951 HeapObject* ho = HeapObject::cast(old_value); |
| 1952 if (heap->InNewSpace(ho)) { |
| 1953 // At this point there must be no old-to-new slots recorded for this |
| 1954 // object. |
| 1955 SLOW_DCHECK( |
| 1956 !heap->store_buffer()->CellIsInStoreBuffer(reinterpret_cast<Address>( |
| 1957 HeapObject::RawField(object, index.offset())))); |
| 1958 } else { |
| 1959 Page* p = Page::FromAddress(reinterpret_cast<Address>(ho)); |
| 1960 if (p->IsEvacuationCandidate()) { |
| 1961 Object** slot = HeapObject::RawField(object, index.offset()); |
| 1962 SlotsBuffer::RemoveSlot(p->slots_buffer(), slot); |
| 1963 } |
| 1964 } |
| 1965 } |
| 1966 } |
| 1967 |
| 1968 |
1925 // To migrate a fast instance to a fast map: | 1969 // To migrate a fast instance to a fast map: |
1926 // - First check whether the instance needs to be rewritten. If not, simply | 1970 // - First check whether the instance needs to be rewritten. If not, simply |
1927 // change the map. | 1971 // change the map. |
1928 // - Otherwise, allocate a fixed array large enough to hold all fields, in | 1972 // - Otherwise, allocate a fixed array large enough to hold all fields, in |
1929 // addition to unused space. | 1973 // addition to unused space. |
1930 // - Copy all existing properties in, in the following order: backing store | 1974 // - Copy all existing properties in, in the following order: backing store |
1931 // properties, unused fields, inobject properties. | 1975 // properties, unused fields, inobject properties. |
1932 // - If all allocation succeeded, commit the state atomically: | 1976 // - If all allocation succeeded, commit the state atomically: |
1933 // * Copy inobject properties from the backing store back into the object. | 1977 // * Copy inobject properties from the backing store back into the object. |
1934 // * Trim the difference in instance size of the object. This also cleanly | 1978 // * Trim the difference in instance size of the object. This also cleanly |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2068 value = isolate->factory()->uninitialized_value(); | 2112 value = isolate->factory()->uninitialized_value(); |
2069 } | 2113 } |
2070 int target_index = new_descriptors->GetFieldIndex(i) - inobject; | 2114 int target_index = new_descriptors->GetFieldIndex(i) - inobject; |
2071 if (target_index < 0) target_index += total_size; | 2115 if (target_index < 0) target_index += total_size; |
2072 array->set(target_index, *value); | 2116 array->set(target_index, *value); |
2073 } | 2117 } |
2074 | 2118 |
2075 // From here on we cannot fail and we shouldn't GC anymore. | 2119 // From here on we cannot fail and we shouldn't GC anymore. |
2076 DisallowHeapAllocation no_allocation; | 2120 DisallowHeapAllocation no_allocation; |
2077 | 2121 |
| 2122 Heap* heap = isolate->heap(); |
| 2123 |
| 2124 // If we are going to put an unboxed double to the field that used to |
| 2125 // contain HeapObject we should ensure that this slot is removed from |
| 2126 // both StoreBuffer and respective SlotsBuffer. |
| 2127 bool clear_slots_recorded = |
| 2128 FLAG_unbox_double_fields && !heap->InNewSpace(object->address()) && |
| 2129 ShouldClearSlotsRecorded(*old_map, *new_map, number_of_fields); |
| 2130 if (clear_slots_recorded) { |
| 2131 Address obj_address = object->address(); |
| 2132 Address start_address = obj_address + JSObject::kHeaderSize; |
| 2133 Address end_address = obj_address + old_map->instance_size(); |
| 2134 heap->store_buffer()->RemoveSlots(start_address, end_address); |
| 2135 } |
| 2136 |
2078 // Copy (real) inobject properties. If necessary, stop at number_of_fields to | 2137 // Copy (real) inobject properties. If necessary, stop at number_of_fields to |
2079 // avoid overwriting |one_pointer_filler_map|. | 2138 // avoid overwriting |one_pointer_filler_map|. |
2080 int limit = Min(inobject, number_of_fields); | 2139 int limit = Min(inobject, number_of_fields); |
2081 for (int i = 0; i < limit; i++) { | 2140 for (int i = 0; i < limit; i++) { |
2082 FieldIndex index = FieldIndex::ForPropertyIndex(*new_map, i); | 2141 FieldIndex index = FieldIndex::ForPropertyIndex(*new_map, i); |
2083 Object* value = array->get(external + i); | 2142 Object* value = array->get(external + i); |
2084 // Can't use JSObject::FastPropertyAtPut() because proper map was not set | |
2085 // yet. | |
2086 if (new_map->IsUnboxedDoubleField(index)) { | 2143 if (new_map->IsUnboxedDoubleField(index)) { |
2087 DCHECK(value->IsMutableHeapNumber()); | 2144 DCHECK(value->IsMutableHeapNumber()); |
| 2145 if (clear_slots_recorded && !old_map->IsUnboxedDoubleField(index)) { |
| 2146 RemoveOldToOldSlotsRecorded(heap, *object, index); |
| 2147 } |
2088 object->RawFastDoublePropertyAtPut(index, | 2148 object->RawFastDoublePropertyAtPut(index, |
2089 HeapNumber::cast(value)->value()); | 2149 HeapNumber::cast(value)->value()); |
2090 } else { | 2150 } else { |
2091 object->RawFastPropertyAtPut(index, value); | 2151 object->RawFastPropertyAtPut(index, value); |
2092 } | 2152 } |
2093 } | 2153 } |
2094 | 2154 |
2095 Heap* heap = isolate->heap(); | |
2096 | |
2097 // If there are properties in the new backing store, trim it to the correct | 2155 // If there are properties in the new backing store, trim it to the correct |
2098 // size and install the backing store into the object. | 2156 // size and install the backing store into the object. |
2099 if (external > 0) { | 2157 if (external > 0) { |
2100 heap->RightTrimFixedArray<Heap::FROM_MUTATOR>(*array, inobject); | 2158 heap->RightTrimFixedArray<Heap::FROM_MUTATOR>(*array, inobject); |
2101 object->set_properties(*array); | 2159 object->set_properties(*array); |
2102 } | 2160 } |
2103 | 2161 |
2104 // Create filler object past the new instance size. | 2162 // Create filler object past the new instance size. |
2105 int new_instance_size = new_map->instance_size(); | 2163 int new_instance_size = new_map->instance_size(); |
2106 int instance_size_delta = old_map->instance_size() - new_instance_size; | 2164 int instance_size_delta = old_map->instance_size() - new_instance_size; |
(...skipping 14986 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
17093 CompilationInfo* info) { | 17151 CompilationInfo* info) { |
17094 Handle<DependentCode> codes = DependentCode::InsertCompilationInfo( | 17152 Handle<DependentCode> codes = DependentCode::InsertCompilationInfo( |
17095 handle(cell->dependent_code(), info->isolate()), | 17153 handle(cell->dependent_code(), info->isolate()), |
17096 DependentCode::kPropertyCellChangedGroup, info->object_wrapper()); | 17154 DependentCode::kPropertyCellChangedGroup, info->object_wrapper()); |
17097 if (*codes != cell->dependent_code()) cell->set_dependent_code(*codes); | 17155 if (*codes != cell->dependent_code()) cell->set_dependent_code(*codes); |
17098 info->dependencies(DependentCode::kPropertyCellChangedGroup)->Add( | 17156 info->dependencies(DependentCode::kPropertyCellChangedGroup)->Add( |
17099 cell, info->zone()); | 17157 cell, info->zone()); |
17100 } | 17158 } |
17101 | 17159 |
17102 } } // namespace v8::internal | 17160 } } // namespace v8::internal |
OLD | NEW |