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 1900 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1911 // For slow-to-fast migrations JSObject::TransformToFastProperties() | 1911 // For slow-to-fast migrations JSObject::TransformToFastProperties() |
1912 // must be used instead. | 1912 // must be used instead. |
1913 CHECK(new_map->is_dictionary_map()); | 1913 CHECK(new_map->is_dictionary_map()); |
1914 | 1914 |
1915 // Slow-to-slow migration is trivial. | 1915 // Slow-to-slow migration is trivial. |
1916 object->set_map(*new_map); | 1916 object->set_map(*new_map); |
1917 } | 1917 } |
1918 } | 1918 } |
1919 | 1919 |
1920 | 1920 |
1921 // Returns true if during migration from |old_map| to |new_map| "tagged" | |
1922 // inobject fields are going to be replaced with unboxed double fields. | |
1923 static bool ShouldClearSlotsRecorded(Map* old_map, Map* new_map, | |
1924 int new_number_of_fields) { | |
1925 DisallowHeapAllocation no_gc; | |
1926 int inobject = new_map->inobject_properties(); | |
1927 DCHECK(inobject <= old_map->inobject_properties()); | |
1928 | |
1929 int limit = Min(inobject, new_number_of_fields); | |
1930 for (int i = 0; i < limit; i++) { | |
1931 FieldIndex index = FieldIndex::ForPropertyIndex(new_map, i); | |
1932 if (new_map->IsUnboxedDoubleField(index) && | |
1933 !old_map->IsUnboxedDoubleField(index)) { | |
1934 return true; | |
1935 } | |
1936 } | |
1937 return false; | |
1938 } | |
1939 | |
1940 | |
1941 static void RemoveOldToOldSlotsRecorded(Heap* heap, JSObject* object, | |
1942 FieldIndex index) { | |
1943 DisallowHeapAllocation no_gc; | |
1944 | |
1945 Object* old_value = object->RawFastPropertyAt(index); | |
1946 if (old_value->IsHeapObject()) { | |
1947 HeapObject* ho = HeapObject::cast(old_value); | |
1948 if (heap->InNewSpace(ho)) { | |
1949 // At this point there must be no old-to-new slots recorded for this | |
1950 // object. | |
1951 SLOW_DCHECK( | |
1952 !heap->store_buffer()->CellIsInStoreBuffer(reinterpret_cast<Address>( | |
1953 HeapObject::RawField(object, index.offset())))); | |
1954 } else { | |
1955 Page* p = Page::FromAddress(reinterpret_cast<Address>(ho)); | |
1956 if (p->IsEvacuationCandidate()) { | |
1957 Object** slot = HeapObject::RawField(object, index.offset()); | |
1958 SlotsBuffer::RemoveSlot(p->slots_buffer(), slot); | |
1959 } | |
1960 } | |
1961 } | |
1962 } | |
1963 | |
1964 | |
1965 // To migrate a fast instance to a fast map: | 1921 // To migrate a fast instance to a fast map: |
1966 // - First check whether the instance needs to be rewritten. If not, simply | 1922 // - First check whether the instance needs to be rewritten. If not, simply |
1967 // change the map. | 1923 // change the map. |
1968 // - Otherwise, allocate a fixed array large enough to hold all fields, in | 1924 // - Otherwise, allocate a fixed array large enough to hold all fields, in |
1969 // addition to unused space. | 1925 // addition to unused space. |
1970 // - Copy all existing properties in, in the following order: backing store | 1926 // - Copy all existing properties in, in the following order: backing store |
1971 // properties, unused fields, inobject properties. | 1927 // properties, unused fields, inobject properties. |
1972 // - If all allocation succeeded, commit the state atomically: | 1928 // - If all allocation succeeded, commit the state atomically: |
1973 // * Copy inobject properties from the backing store back into the object. | 1929 // * Copy inobject properties from the backing store back into the object. |
1974 // * Trim the difference in instance size of the object. This also cleanly | 1930 // * 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... |
2108 value = isolate->factory()->uninitialized_value(); | 2064 value = isolate->factory()->uninitialized_value(); |
2109 } | 2065 } |
2110 int target_index = new_descriptors->GetFieldIndex(i) - inobject; | 2066 int target_index = new_descriptors->GetFieldIndex(i) - inobject; |
2111 if (target_index < 0) target_index += total_size; | 2067 if (target_index < 0) target_index += total_size; |
2112 array->set(target_index, *value); | 2068 array->set(target_index, *value); |
2113 } | 2069 } |
2114 | 2070 |
2115 // From here on we cannot fail and we shouldn't GC anymore. | 2071 // From here on we cannot fail and we shouldn't GC anymore. |
2116 DisallowHeapAllocation no_allocation; | 2072 DisallowHeapAllocation no_allocation; |
2117 | 2073 |
2118 Heap* heap = isolate->heap(); | |
2119 | |
2120 // If we are going to put an unboxed double to the field that used to | |
2121 // contain HeapObject we should ensure that this slot is removed from | |
2122 // both StoreBuffer and respective SlotsBuffer. | |
2123 bool clear_slots_recorded = | |
2124 FLAG_unbox_double_fields && !heap->InNewSpace(object->address()) && | |
2125 ShouldClearSlotsRecorded(*old_map, *new_map, number_of_fields); | |
2126 if (clear_slots_recorded) { | |
2127 Address obj_address = object->address(); | |
2128 Address end_address = obj_address + old_map->instance_size(); | |
2129 heap->store_buffer()->RemoveSlots(obj_address, end_address); | |
2130 } | |
2131 | |
2132 // Copy (real) inobject properties. If necessary, stop at number_of_fields to | 2074 // Copy (real) inobject properties. If necessary, stop at number_of_fields to |
2133 // avoid overwriting |one_pointer_filler_map|. | 2075 // avoid overwriting |one_pointer_filler_map|. |
2134 int limit = Min(inobject, number_of_fields); | 2076 int limit = Min(inobject, number_of_fields); |
2135 for (int i = 0; i < limit; i++) { | 2077 for (int i = 0; i < limit; i++) { |
2136 FieldIndex index = FieldIndex::ForPropertyIndex(*new_map, i); | 2078 FieldIndex index = FieldIndex::ForPropertyIndex(*new_map, i); |
2137 Object* value = array->get(external + i); | 2079 Object* value = array->get(external + i); |
| 2080 // Can't use JSObject::FastPropertyAtPut() because proper map was not set |
| 2081 // yet. |
2138 if (new_map->IsUnboxedDoubleField(index)) { | 2082 if (new_map->IsUnboxedDoubleField(index)) { |
2139 DCHECK(value->IsMutableHeapNumber()); | 2083 DCHECK(value->IsMutableHeapNumber()); |
2140 if (clear_slots_recorded && !old_map->IsUnboxedDoubleField(index)) { | |
2141 RemoveOldToOldSlotsRecorded(heap, *object, index); | |
2142 } | |
2143 object->RawFastDoublePropertyAtPut(index, | 2084 object->RawFastDoublePropertyAtPut(index, |
2144 HeapNumber::cast(value)->value()); | 2085 HeapNumber::cast(value)->value()); |
2145 } else { | 2086 } else { |
2146 object->RawFastPropertyAtPut(index, value); | 2087 object->RawFastPropertyAtPut(index, value); |
2147 } | 2088 } |
2148 } | 2089 } |
2149 | 2090 |
| 2091 Heap* heap = isolate->heap(); |
| 2092 |
2150 // If there are properties in the new backing store, trim it to the correct | 2093 // If there are properties in the new backing store, trim it to the correct |
2151 // size and install the backing store into the object. | 2094 // size and install the backing store into the object. |
2152 if (external > 0) { | 2095 if (external > 0) { |
2153 heap->RightTrimFixedArray<Heap::FROM_MUTATOR>(*array, inobject); | 2096 heap->RightTrimFixedArray<Heap::FROM_MUTATOR>(*array, inobject); |
2154 object->set_properties(*array); | 2097 object->set_properties(*array); |
2155 } | 2098 } |
2156 | 2099 |
2157 // Create filler object past the new instance size. | 2100 // Create filler object past the new instance size. |
2158 int new_instance_size = new_map->instance_size(); | 2101 int new_instance_size = new_map->instance_size(); |
2159 int instance_size_delta = old_map->instance_size() - new_instance_size; | 2102 int instance_size_delta = old_map->instance_size() - new_instance_size; |
(...skipping 14967 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
17127 CompilationInfo* info) { | 17070 CompilationInfo* info) { |
17128 Handle<DependentCode> codes = DependentCode::InsertCompilationInfo( | 17071 Handle<DependentCode> codes = DependentCode::InsertCompilationInfo( |
17129 handle(cell->dependent_code(), info->isolate()), | 17072 handle(cell->dependent_code(), info->isolate()), |
17130 DependentCode::kPropertyCellChangedGroup, info->object_wrapper()); | 17073 DependentCode::kPropertyCellChangedGroup, info->object_wrapper()); |
17131 if (*codes != cell->dependent_code()) cell->set_dependent_code(*codes); | 17074 if (*codes != cell->dependent_code()) cell->set_dependent_code(*codes); |
17132 info->dependencies(DependentCode::kPropertyCellChangedGroup)->Add( | 17075 info->dependencies(DependentCode::kPropertyCellChangedGroup)->Add( |
17133 cell, info->zone()); | 17076 cell, info->zone()); |
17134 } | 17077 } |
17135 | 17078 |
17136 } } // namespace v8::internal | 17079 } } // namespace v8::internal |
OLD | NEW |