| 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 <sstream> | 5 #include <sstream> |
| 6 | 6 |
| 7 #include "src/v8.h" | 7 #include "src/v8.h" |
| 8 | 8 |
| 9 #include "src/accessors.h" | 9 #include "src/accessors.h" |
| 10 #include "src/allocation-site-scopes.h" | 10 #include "src/allocation-site-scopes.h" |
| (...skipping 1251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1262 object->ShortPrint(file); | 1262 object->ShortPrint(file); |
| 1263 PrintF(file, " from "); | 1263 PrintF(file, " from "); |
| 1264 from_elements->ShortPrint(file); | 1264 from_elements->ShortPrint(file); |
| 1265 PrintF(file, " to "); | 1265 PrintF(file, " to "); |
| 1266 to_elements->ShortPrint(file); | 1266 to_elements->ShortPrint(file); |
| 1267 PrintF(file, "\n"); | 1267 PrintF(file, "\n"); |
| 1268 } | 1268 } |
| 1269 } | 1269 } |
| 1270 | 1270 |
| 1271 | 1271 |
| 1272 void Map::PrintReconfiguration(FILE* file, int modify_index, PropertyKind kind, |
| 1273 PropertyAttributes attributes) { |
| 1274 OFStream os(file); |
| 1275 os << "[reconfiguring "; |
| 1276 constructor_name()->PrintOn(file); |
| 1277 os << "] "; |
| 1278 Name* name = instance_descriptors()->GetKey(modify_index); |
| 1279 if (name->IsString()) { |
| 1280 String::cast(name)->PrintOn(file); |
| 1281 } else { |
| 1282 os << "{symbol " << static_cast<void*>(name) << "}"; |
| 1283 } |
| 1284 os << ": " << (kind == kData ? "kData" : "ACCESSORS") << ", attrs: "; |
| 1285 os << attributes << " ["; |
| 1286 JavaScriptFrame::PrintTop(GetIsolate(), file, false, true); |
| 1287 os << "]\n"; |
| 1288 } |
| 1289 |
| 1290 |
| 1272 void Map::PrintGeneralization(FILE* file, | 1291 void Map::PrintGeneralization(FILE* file, |
| 1273 const char* reason, | 1292 const char* reason, |
| 1274 int modify_index, | 1293 int modify_index, |
| 1275 int split, | 1294 int split, |
| 1276 int descriptors, | 1295 int descriptors, |
| 1277 bool constant_to_field, | 1296 bool constant_to_field, |
| 1278 Representation old_representation, | 1297 Representation old_representation, |
| 1279 Representation new_representation, | 1298 Representation new_representation, |
| 1280 HeapType* old_field_type, | 1299 HeapType* old_field_type, |
| 1281 HeapType* new_field_type) { | 1300 HeapType* new_field_type) { |
| (...skipping 688 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1970 int new_nof = new_map->NumberOfOwnDescriptors(); | 1989 int new_nof = new_map->NumberOfOwnDescriptors(); |
| 1971 | 1990 |
| 1972 // This method only supports generalizing instances to at least the same | 1991 // This method only supports generalizing instances to at least the same |
| 1973 // number of properties. | 1992 // number of properties. |
| 1974 DCHECK(old_nof <= new_nof); | 1993 DCHECK(old_nof <= new_nof); |
| 1975 | 1994 |
| 1976 for (int i = 0; i < old_nof; i++) { | 1995 for (int i = 0; i < old_nof; i++) { |
| 1977 PropertyDetails details = new_descriptors->GetDetails(i); | 1996 PropertyDetails details = new_descriptors->GetDetails(i); |
| 1978 if (details.type() != DATA) continue; | 1997 if (details.type() != DATA) continue; |
| 1979 PropertyDetails old_details = old_descriptors->GetDetails(i); | 1998 PropertyDetails old_details = old_descriptors->GetDetails(i); |
| 1980 if (old_details.type() == ACCESSOR_CONSTANT) { | |
| 1981 DCHECK(details.representation().IsTagged()); | |
| 1982 continue; | |
| 1983 } | |
| 1984 Representation old_representation = old_details.representation(); | 1999 Representation old_representation = old_details.representation(); |
| 1985 Representation representation = details.representation(); | 2000 Representation representation = details.representation(); |
| 1986 DCHECK(old_details.type() == DATA_CONSTANT || old_details.type() == DATA); | |
| 1987 Handle<Object> value; | 2001 Handle<Object> value; |
| 1988 if (old_details.type() == DATA_CONSTANT) { | 2002 if (old_details.type() == ACCESSOR_CONSTANT) { |
| 2003 // In case of kAccessor -> kData property reconfiguration, the property |
| 2004 // must already be prepared for data or certain type. |
| 2005 DCHECK(!details.representation().IsNone()); |
| 2006 if (details.representation().IsDouble()) { |
| 2007 value = isolate->factory()->NewHeapNumber(0, MUTABLE); |
| 2008 } else { |
| 2009 value = isolate->factory()->uninitialized_value(); |
| 2010 } |
| 2011 } else if (old_details.type() == DATA_CONSTANT) { |
| 1989 value = handle(old_descriptors->GetValue(i), isolate); | 2012 value = handle(old_descriptors->GetValue(i), isolate); |
| 1990 DCHECK(!old_representation.IsDouble() && !representation.IsDouble()); | 2013 DCHECK(!old_representation.IsDouble() && !representation.IsDouble()); |
| 1991 } else { | 2014 } else { |
| 1992 FieldIndex index = FieldIndex::ForDescriptor(*old_map, i); | 2015 FieldIndex index = FieldIndex::ForDescriptor(*old_map, i); |
| 1993 if (object->IsUnboxedDoubleField(index)) { | 2016 if (object->IsUnboxedDoubleField(index)) { |
| 1994 double old = object->RawFastDoublePropertyAt(index); | 2017 double old = object->RawFastDoublePropertyAt(index); |
| 1995 value = isolate->factory()->NewHeapNumber( | 2018 value = isolate->factory()->NewHeapNumber( |
| 1996 old, representation.IsDouble() ? MUTABLE : IMMUTABLE); | 2019 old, representation.IsDouble() ? MUTABLE : IMMUTABLE); |
| 1997 | 2020 |
| 1998 } else { | 2021 } else { |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2072 // We are storing the new map using release store after creating a filler for | 2095 // We are storing the new map using release store after creating a filler for |
| 2073 // the left-over space to avoid races with the sweeper thread. | 2096 // the left-over space to avoid races with the sweeper thread. |
| 2074 object->synchronized_set_map(*new_map); | 2097 object->synchronized_set_map(*new_map); |
| 2075 } | 2098 } |
| 2076 | 2099 |
| 2077 | 2100 |
| 2078 int Map::NumberOfFields() { | 2101 int Map::NumberOfFields() { |
| 2079 DescriptorArray* descriptors = instance_descriptors(); | 2102 DescriptorArray* descriptors = instance_descriptors(); |
| 2080 int result = 0; | 2103 int result = 0; |
| 2081 for (int i = 0; i < NumberOfOwnDescriptors(); i++) { | 2104 for (int i = 0; i < NumberOfOwnDescriptors(); i++) { |
| 2082 if (descriptors->GetDetails(i).type() == DATA) result++; | 2105 if (descriptors->GetDetails(i).location() == kField) result++; |
| 2083 } | 2106 } |
| 2084 return result; | 2107 return result; |
| 2085 } | 2108 } |
| 2086 | 2109 |
| 2087 | 2110 |
| 2088 Handle<Map> Map::CopyGeneralizeAllRepresentations(Handle<Map> map, | 2111 Handle<Map> Map::CopyGeneralizeAllRepresentations( |
| 2089 int modify_index, | 2112 Handle<Map> map, int modify_index, StoreMode store_mode, PropertyKind kind, |
| 2090 StoreMode store_mode, | 2113 PropertyAttributes attributes, const char* reason) { |
| 2091 PropertyAttributes attributes, | |
| 2092 const char* reason) { | |
| 2093 Isolate* isolate = map->GetIsolate(); | 2114 Isolate* isolate = map->GetIsolate(); |
| 2094 Handle<DescriptorArray> old_descriptors(map->instance_descriptors(), isolate); | 2115 Handle<DescriptorArray> old_descriptors(map->instance_descriptors(), isolate); |
| 2095 int number_of_own_descriptors = map->NumberOfOwnDescriptors(); | 2116 int number_of_own_descriptors = map->NumberOfOwnDescriptors(); |
| 2096 Handle<DescriptorArray> descriptors = | 2117 Handle<DescriptorArray> descriptors = |
| 2097 DescriptorArray::CopyUpTo(old_descriptors, number_of_own_descriptors); | 2118 DescriptorArray::CopyUpTo(old_descriptors, number_of_own_descriptors); |
| 2098 | 2119 |
| 2099 for (int i = 0; i < number_of_own_descriptors; i++) { | 2120 for (int i = 0; i < number_of_own_descriptors; i++) { |
| 2100 descriptors->SetRepresentation(i, Representation::Tagged()); | 2121 descriptors->SetRepresentation(i, Representation::Tagged()); |
| 2101 if (descriptors->GetDetails(i).type() == DATA) { | 2122 if (descriptors->GetDetails(i).type() == DATA) { |
| 2102 descriptors->SetValue(i, HeapType::Any()); | 2123 descriptors->SetValue(i, HeapType::Any()); |
| 2103 } | 2124 } |
| 2104 } | 2125 } |
| 2105 | 2126 |
| 2106 Handle<LayoutDescriptor> new_layout_descriptor( | 2127 Handle<LayoutDescriptor> new_layout_descriptor( |
| 2107 LayoutDescriptor::FastPointerLayout(), isolate); | 2128 LayoutDescriptor::FastPointerLayout(), isolate); |
| 2108 Handle<Map> new_map = CopyReplaceDescriptors( | 2129 Handle<Map> new_map = CopyReplaceDescriptors( |
| 2109 map, descriptors, new_layout_descriptor, OMIT_TRANSITION, | 2130 map, descriptors, new_layout_descriptor, OMIT_TRANSITION, |
| 2110 MaybeHandle<Name>(), reason, SPECIAL_TRANSITION); | 2131 MaybeHandle<Name>(), reason, SPECIAL_TRANSITION); |
| 2111 | 2132 |
| 2112 // Unless the instance is being migrated, ensure that modify_index is a field. | 2133 // Unless the instance is being migrated, ensure that modify_index is a field. |
| 2113 PropertyDetails details = descriptors->GetDetails(modify_index); | 2134 if (modify_index >= 0) { |
| 2114 if (store_mode == FORCE_FIELD && | 2135 PropertyDetails details = descriptors->GetDetails(modify_index); |
| 2115 (details.type() != DATA || details.attributes() != attributes)) { | 2136 if (store_mode == FORCE_FIELD && |
| 2116 int field_index = details.type() == DATA ? details.field_index() | 2137 (details.type() != DATA || details.attributes() != attributes)) { |
| 2117 : new_map->NumberOfFields(); | 2138 int field_index = details.type() == DATA ? details.field_index() |
| 2118 DataDescriptor d(handle(descriptors->GetKey(modify_index), isolate), | 2139 : new_map->NumberOfFields(); |
| 2119 field_index, attributes, Representation::Tagged()); | 2140 DataDescriptor d(handle(descriptors->GetKey(modify_index), isolate), |
| 2120 descriptors->Replace(modify_index, &d); | 2141 field_index, attributes, Representation::Tagged()); |
| 2121 if (details.type() != DATA) { | 2142 descriptors->Replace(modify_index, &d); |
| 2122 int unused_property_fields = new_map->unused_property_fields() - 1; | 2143 if (details.type() != DATA) { |
| 2123 if (unused_property_fields < 0) { | 2144 int unused_property_fields = new_map->unused_property_fields() - 1; |
| 2124 unused_property_fields += JSObject::kFieldsAdded; | 2145 if (unused_property_fields < 0) { |
| 2146 unused_property_fields += JSObject::kFieldsAdded; |
| 2147 } |
| 2148 new_map->set_unused_property_fields(unused_property_fields); |
| 2125 } | 2149 } |
| 2126 new_map->set_unused_property_fields(unused_property_fields); | 2150 } else { |
| 2151 DCHECK(details.attributes() == attributes); |
| 2127 } | 2152 } |
| 2128 } else { | |
| 2129 DCHECK(details.attributes() == attributes); | |
| 2130 } | |
| 2131 | 2153 |
| 2132 if (FLAG_trace_generalization) { | 2154 if (FLAG_trace_generalization) { |
| 2133 HeapType* field_type = | 2155 HeapType* field_type = |
| 2134 (details.type() == DATA) | 2156 (details.type() == DATA) |
| 2135 ? map->instance_descriptors()->GetFieldType(modify_index) | 2157 ? map->instance_descriptors()->GetFieldType(modify_index) |
| 2136 : NULL; | 2158 : NULL; |
| 2137 map->PrintGeneralization( | 2159 map->PrintGeneralization( |
| 2138 stdout, reason, modify_index, new_map->NumberOfOwnDescriptors(), | 2160 stdout, reason, modify_index, new_map->NumberOfOwnDescriptors(), |
| 2139 new_map->NumberOfOwnDescriptors(), | 2161 new_map->NumberOfOwnDescriptors(), |
| 2140 details.type() == DATA_CONSTANT && store_mode == FORCE_FIELD, | 2162 details.type() == DATA_CONSTANT && store_mode == FORCE_FIELD, |
| 2141 details.representation(), Representation::Tagged(), field_type, | 2163 details.representation(), Representation::Tagged(), field_type, |
| 2142 HeapType::Any()); | 2164 HeapType::Any()); |
| 2165 } |
| 2143 } | 2166 } |
| 2144 return new_map; | 2167 return new_map; |
| 2145 } | 2168 } |
| 2146 | 2169 |
| 2147 | 2170 |
| 2148 // static | |
| 2149 Handle<Map> Map::CopyGeneralizeAllRepresentations(Handle<Map> map, | |
| 2150 int modify_index, | |
| 2151 StoreMode store_mode, | |
| 2152 const char* reason) { | |
| 2153 PropertyDetails details = | |
| 2154 map->instance_descriptors()->GetDetails(modify_index); | |
| 2155 return CopyGeneralizeAllRepresentations(map, modify_index, store_mode, | |
| 2156 details.attributes(), reason); | |
| 2157 } | |
| 2158 | |
| 2159 | |
| 2160 void Map::DeprecateTransitionTree() { | 2171 void Map::DeprecateTransitionTree() { |
| 2161 if (is_deprecated()) return; | 2172 if (is_deprecated()) return; |
| 2162 if (HasTransitionArray()) { | 2173 if (HasTransitionArray()) { |
| 2163 TransitionArray* transitions = this->transitions(); | 2174 TransitionArray* transitions = this->transitions(); |
| 2164 for (int i = 0; i < transitions->number_of_transitions(); i++) { | 2175 for (int i = 0; i < transitions->number_of_transitions(); i++) { |
| 2165 transitions->GetTarget(i)->DeprecateTransitionTree(); | 2176 transitions->GetTarget(i)->DeprecateTransitionTree(); |
| 2166 } | 2177 } |
| 2167 } | 2178 } |
| 2168 deprecate(); | 2179 deprecate(); |
| 2169 dependent_code()->DeoptimizeDependentCodeGroup( | 2180 dependent_code()->DeoptimizeDependentCodeGroup( |
| 2170 GetIsolate(), DependentCode::kTransitionGroup); | 2181 GetIsolate(), DependentCode::kTransitionGroup); |
| 2171 NotifyLeafMapLayoutChange(); | 2182 NotifyLeafMapLayoutChange(); |
| 2172 } | 2183 } |
| 2173 | 2184 |
| 2174 | 2185 |
| 2186 static inline bool EqualImmutableValues(Object* obj1, Object* obj2) { |
| 2187 if (obj1 == obj2) return true; // Valid for both kData and kAccessor kinds. |
| 2188 // TODO(ishell): compare AccessorPairs. |
| 2189 return false; |
| 2190 } |
| 2191 |
| 2192 |
| 2175 // Invalidates a transition target at |key|, and installs |new_descriptors| over | 2193 // Invalidates a transition target at |key|, and installs |new_descriptors| over |
| 2176 // the current instance_descriptors to ensure proper sharing of descriptor | 2194 // the current instance_descriptors to ensure proper sharing of descriptor |
| 2177 // arrays. | 2195 // arrays. |
| 2178 // Returns true if the transition target at given key was deprecated. | 2196 // Returns true if the transition target at given key was deprecated. |
| 2179 bool Map::DeprecateTarget(PropertyKind kind, Name* key, | 2197 bool Map::DeprecateTarget(PropertyKind kind, Name* key, |
| 2180 PropertyAttributes attributes, | 2198 PropertyAttributes attributes, |
| 2181 DescriptorArray* new_descriptors, | 2199 DescriptorArray* new_descriptors, |
| 2182 LayoutDescriptor* new_layout_descriptor) { | 2200 LayoutDescriptor* new_layout_descriptor) { |
| 2183 bool transition_target_deprecated = false; | 2201 bool transition_target_deprecated = false; |
| 2184 if (HasTransitionArray()) { | 2202 if (HasTransitionArray()) { |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2235 PropertyDetails details = descriptors->GetDetails(i); | 2253 PropertyDetails details = descriptors->GetDetails(i); |
| 2236 TransitionArray* transitions = current->transitions(); | 2254 TransitionArray* transitions = current->transitions(); |
| 2237 int transition = | 2255 int transition = |
| 2238 transitions->Search(details.kind(), name, details.attributes()); | 2256 transitions->Search(details.kind(), name, details.attributes()); |
| 2239 if (transition == TransitionArray::kNotFound) break; | 2257 if (transition == TransitionArray::kNotFound) break; |
| 2240 | 2258 |
| 2241 Map* next = transitions->GetTarget(transition); | 2259 Map* next = transitions->GetTarget(transition); |
| 2242 DescriptorArray* next_descriptors = next->instance_descriptors(); | 2260 DescriptorArray* next_descriptors = next->instance_descriptors(); |
| 2243 | 2261 |
| 2244 PropertyDetails next_details = next_descriptors->GetDetails(i); | 2262 PropertyDetails next_details = next_descriptors->GetDetails(i); |
| 2245 if (details.type() != next_details.type()) break; | 2263 DCHECK_EQ(details.kind(), next_details.kind()); |
| 2246 if (details.attributes() != next_details.attributes()) break; | 2264 DCHECK_EQ(details.attributes(), next_details.attributes()); |
| 2265 if (details.location() != next_details.location()) break; |
| 2247 if (!details.representation().Equals(next_details.representation())) break; | 2266 if (!details.representation().Equals(next_details.representation())) break; |
| 2248 if (next_details.type() == DATA) { | 2267 |
| 2249 if (!descriptors->GetFieldType(i)->NowIs( | 2268 if (next_details.location() == kField) { |
| 2250 next_descriptors->GetFieldType(i))) break; | 2269 HeapType* next_field_type = next_descriptors->GetFieldType(i); |
| 2270 if (!descriptors->GetFieldType(i)->NowIs(next_field_type)) { |
| 2271 break; |
| 2272 } |
| 2251 } else { | 2273 } else { |
| 2252 if (descriptors->GetValue(i) != next_descriptors->GetValue(i)) break; | 2274 if (!EqualImmutableValues(descriptors->GetValue(i), |
| 2275 next_descriptors->GetValue(i))) { |
| 2276 break; |
| 2277 } |
| 2253 } | 2278 } |
| 2254 | |
| 2255 current = next; | 2279 current = next; |
| 2256 } | 2280 } |
| 2257 return current; | 2281 return current; |
| 2258 } | 2282 } |
| 2259 | 2283 |
| 2260 | 2284 |
| 2261 Map* Map::FindFieldOwner(int descriptor) { | 2285 Map* Map::FindFieldOwner(int descriptor) { |
| 2262 DisallowHeapAllocation no_allocation; | 2286 DisallowHeapAllocation no_allocation; |
| 2263 DCHECK_EQ(DATA, instance_descriptors()->GetDetails(descriptor).type()); | 2287 DCHECK_EQ(DATA, instance_descriptors()->GetDetails(descriptor).type()); |
| 2264 Map* result = this; | 2288 Map* result = this; |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2360 map->PrintGeneralization( | 2384 map->PrintGeneralization( |
| 2361 stdout, "field type generalization", | 2385 stdout, "field type generalization", |
| 2362 modify_index, map->NumberOfOwnDescriptors(), | 2386 modify_index, map->NumberOfOwnDescriptors(), |
| 2363 map->NumberOfOwnDescriptors(), false, | 2387 map->NumberOfOwnDescriptors(), false, |
| 2364 details.representation(), details.representation(), | 2388 details.representation(), details.representation(), |
| 2365 *old_field_type, *new_field_type); | 2389 *old_field_type, *new_field_type); |
| 2366 } | 2390 } |
| 2367 } | 2391 } |
| 2368 | 2392 |
| 2369 | 2393 |
| 2370 // Generalize the representation of the descriptor at |modify_index|. | 2394 static inline Handle<HeapType> GetFieldType(Isolate* isolate, |
| 2371 // This method rewrites the transition tree to reflect the new change. To avoid | 2395 Handle<DescriptorArray> descriptors, |
| 2372 // high degrees over polymorphism, and to stabilize quickly, on every rewrite | 2396 int descriptor, |
| 2373 // the new type is deduced by merging the current type with any potential new | 2397 PropertyLocation location, |
| 2374 // (partial) version of the type in the transition tree. | 2398 Representation representation) { |
| 2399 #ifdef DEBUG |
| 2400 PropertyDetails details = descriptors->GetDetails(descriptor); |
| 2401 DCHECK_EQ(kData, details.kind()); |
| 2402 DCHECK_EQ(details.location(), location); |
| 2403 #endif |
| 2404 if (location == kField) { |
| 2405 return handle(descriptors->GetFieldType(descriptor), isolate); |
| 2406 } else { |
| 2407 return descriptors->GetValue(descriptor) |
| 2408 ->OptimalType(isolate, representation); |
| 2409 } |
| 2410 } |
| 2411 |
| 2412 |
| 2413 // Reconfigures property at |modify_index| with |new_kind|, |new_attributes|, |
| 2414 // |store_mode| and/or |new_representation|/|new_field_type|. |
| 2415 // If |modify_index| is negative then no properties are reconfigured but the |
| 2416 // map is migrated to the up-to-date non-deprecated state. |
| 2417 // |
| 2418 // This method rewrites or completes the transition tree to reflect the new |
| 2419 // change. To avoid high degrees over polymorphism, and to stabilize quickly, |
| 2420 // on every rewrite the new type is deduced by merging the current type with |
| 2421 // any potential new (partial) version of the type in the transition tree. |
| 2375 // To do this, on each rewrite: | 2422 // To do this, on each rewrite: |
| 2376 // - Search the root of the transition tree using FindRootMap. | 2423 // - Search the root of the transition tree using FindRootMap. |
| 2377 // - Find |target_map|, the newest matching version of this map using the keys | 2424 // - Find |target_map|, the newest matching version of this map using the |
| 2378 // in the |old_map|'s descriptor array to walk the transition tree. | 2425 // virtually "enhanced" |old_map|'s descriptor array (i.e. whose entry at |
| 2379 // - Merge/generalize the descriptor array of the |old_map| and |target_map|. | 2426 // |modify_index| is considered to be of |new_kind| and having |
| 2427 // |new_attributes|) to walk the transition tree. |
| 2428 // - Merge/generalize the "enhanced" descriptor array of the |old_map| and |
| 2429 // descriptor array of the |target_map|. |
| 2380 // - Generalize the |modify_index| descriptor using |new_representation| and | 2430 // - Generalize the |modify_index| descriptor using |new_representation| and |
| 2381 // |new_field_type|. | 2431 // |new_field_type|. |
| 2382 // - Walk the tree again starting from the root towards |target_map|. Stop at | 2432 // - Walk the tree again starting from the root towards |target_map|. Stop at |
| 2383 // |split_map|, the first map who's descriptor array does not match the merged | 2433 // |split_map|, the first map who's descriptor array does not match the merged |
| 2384 // descriptor array. | 2434 // descriptor array. |
| 2385 // - If |target_map| == |split_map|, |target_map| is in the expected state. | 2435 // - If |target_map| == |split_map|, |target_map| is in the expected state. |
| 2386 // Return it. | 2436 // Return it. |
| 2387 // - Otherwise, invalidate the outdated transition target from |target_map|, and | 2437 // - Otherwise, invalidate the outdated transition target from |target_map|, and |
| 2388 // replace its transition tree with a new branch for the updated descriptors. | 2438 // replace its transition tree with a new branch for the updated descriptors. |
| 2389 Handle<Map> Map::GeneralizeRepresentation(Handle<Map> old_map, | 2439 Handle<Map> Map::ReconfigureProperty(Handle<Map> old_map, int modify_index, |
| 2390 int modify_index, | 2440 PropertyKind new_kind, |
| 2391 Representation new_representation, | 2441 PropertyAttributes new_attributes, |
| 2392 Handle<HeapType> new_field_type, | 2442 Representation new_representation, |
| 2393 StoreMode store_mode) { | 2443 Handle<HeapType> new_field_type, |
| 2444 StoreMode store_mode) { |
| 2445 DCHECK_NE(kAccessor, new_kind); // TODO(ishell): not supported yet. |
| 2446 DCHECK(store_mode != FORCE_FIELD || modify_index >= 0); |
| 2394 Isolate* isolate = old_map->GetIsolate(); | 2447 Isolate* isolate = old_map->GetIsolate(); |
| 2395 | 2448 |
| 2396 Handle<DescriptorArray> old_descriptors( | 2449 Handle<DescriptorArray> old_descriptors( |
| 2397 old_map->instance_descriptors(), isolate); | 2450 old_map->instance_descriptors(), isolate); |
| 2398 int old_nof = old_map->NumberOfOwnDescriptors(); | 2451 int old_nof = old_map->NumberOfOwnDescriptors(); |
| 2399 PropertyDetails old_details = old_descriptors->GetDetails(modify_index); | |
| 2400 Representation old_representation = old_details.representation(); | |
| 2401 | 2452 |
| 2402 // It's fine to transition from None to anything but double without any | 2453 // If it's just a representation generalization case (i.e. property kind and |
| 2403 // modification to the object, because the default uninitialized value for | 2454 // attributes stays unchanged) it's fine to transition from None to anything |
| 2404 // representation None can be overwritten by both smi and tagged values. | 2455 // but double without any modification to the object, because the default |
| 2405 // Doubles, however, would require a box allocation. | 2456 // uninitialized value for representation None can be overwritten by both |
| 2406 if (old_representation.IsNone() && !new_representation.IsNone() && | 2457 // smi and tagged values. Doubles, however, would require a box allocation. |
| 2458 if (modify_index >= 0 && !new_representation.IsNone() && |
| 2407 !new_representation.IsDouble()) { | 2459 !new_representation.IsDouble()) { |
| 2408 DCHECK(old_details.type() == DATA); | 2460 PropertyDetails old_details = old_descriptors->GetDetails(modify_index); |
| 2409 if (FLAG_trace_generalization) { | 2461 Representation old_representation = old_details.representation(); |
| 2410 old_map->PrintGeneralization( | 2462 |
| 2411 stdout, "uninitialized field", | 2463 if (old_representation.IsNone()) { |
| 2412 modify_index, old_map->NumberOfOwnDescriptors(), | 2464 DCHECK_EQ(new_kind, old_details.kind()); |
| 2413 old_map->NumberOfOwnDescriptors(), false, | 2465 DCHECK_EQ(new_attributes, old_details.attributes()); |
| 2414 old_representation, new_representation, | 2466 DCHECK_EQ(DATA, old_details.type()); |
| 2415 old_descriptors->GetFieldType(modify_index), *new_field_type); | 2467 if (FLAG_trace_generalization) { |
| 2468 old_map->PrintGeneralization( |
| 2469 stdout, "uninitialized field", modify_index, |
| 2470 old_map->NumberOfOwnDescriptors(), |
| 2471 old_map->NumberOfOwnDescriptors(), false, old_representation, |
| 2472 new_representation, old_descriptors->GetFieldType(modify_index), |
| 2473 *new_field_type); |
| 2474 } |
| 2475 Handle<Map> field_owner(old_map->FindFieldOwner(modify_index), isolate); |
| 2476 |
| 2477 GeneralizeFieldType(field_owner, modify_index, new_representation, |
| 2478 new_field_type); |
| 2479 DCHECK(old_descriptors->GetDetails(modify_index) |
| 2480 .representation() |
| 2481 .Equals(new_representation)); |
| 2482 DCHECK( |
| 2483 old_descriptors->GetFieldType(modify_index)->NowIs(new_field_type)); |
| 2484 return old_map; |
| 2416 } | 2485 } |
| 2417 Handle<Map> field_owner(old_map->FindFieldOwner(modify_index), isolate); | |
| 2418 | |
| 2419 GeneralizeFieldType(field_owner, modify_index, new_representation, | |
| 2420 new_field_type); | |
| 2421 DCHECK(old_descriptors->GetDetails(modify_index).representation().Equals( | |
| 2422 new_representation)); | |
| 2423 DCHECK(old_descriptors->GetFieldType(modify_index)->NowIs(new_field_type)); | |
| 2424 return old_map; | |
| 2425 } | 2486 } |
| 2426 | 2487 |
| 2427 // Check the state of the root map. | 2488 // Check the state of the root map. |
| 2428 Handle<Map> root_map(old_map->FindRootMap(), isolate); | 2489 Handle<Map> root_map(old_map->FindRootMap(), isolate); |
| 2429 if (!old_map->EquivalentToForTransition(*root_map)) { | 2490 if (!old_map->EquivalentToForTransition(*root_map)) { |
| 2430 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, | 2491 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, |
| 2492 new_kind, new_attributes, |
| 2431 "GenAll_NotEquivalent"); | 2493 "GenAll_NotEquivalent"); |
| 2432 } | 2494 } |
| 2433 int root_nof = root_map->NumberOfOwnDescriptors(); | 2495 int root_nof = root_map->NumberOfOwnDescriptors(); |
| 2434 if (modify_index < root_nof) { | 2496 if (modify_index >= 0 && modify_index < root_nof) { |
| 2435 PropertyDetails old_details = old_descriptors->GetDetails(modify_index); | 2497 PropertyDetails old_details = old_descriptors->GetDetails(modify_index); |
| 2498 if (old_details.kind() != new_kind || |
| 2499 old_details.attributes() != new_attributes) { |
| 2500 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, |
| 2501 new_kind, new_attributes, |
| 2502 "GenAll_RootModification1"); |
| 2503 } |
| 2436 if ((old_details.type() != DATA && store_mode == FORCE_FIELD) || | 2504 if ((old_details.type() != DATA && store_mode == FORCE_FIELD) || |
| 2437 (old_details.type() == DATA && | 2505 (old_details.type() == DATA && |
| 2438 (!new_field_type->NowIs(old_descriptors->GetFieldType(modify_index)) || | 2506 (!new_field_type->NowIs(old_descriptors->GetFieldType(modify_index)) || |
| 2439 !new_representation.fits_into(old_details.representation())))) { | 2507 !new_representation.fits_into(old_details.representation())))) { |
| 2440 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, | 2508 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, |
| 2441 "GenAll_RootModification"); | 2509 new_kind, new_attributes, |
| 2510 "GenAll_RootModification2"); |
| 2442 } | 2511 } |
| 2443 } | 2512 } |
| 2444 | 2513 |
| 2445 Handle<Map> target_map = root_map; | 2514 Handle<Map> target_map = root_map; |
| 2446 for (int i = root_nof; i < old_nof; ++i) { | 2515 for (int i = root_nof; i < old_nof; ++i) { |
| 2447 PropertyDetails old_details = old_descriptors->GetDetails(i); | 2516 PropertyDetails old_details = old_descriptors->GetDetails(i); |
| 2448 int j = target_map->SearchTransition(old_details.kind(), | 2517 PropertyKind next_kind; |
| 2449 old_descriptors->GetKey(i), | 2518 PropertyLocation next_location; |
| 2450 old_details.attributes()); | 2519 PropertyAttributes next_attributes; |
| 2520 Representation next_representation; |
| 2521 bool property_kind_reconfiguration = false; |
| 2522 |
| 2523 if (modify_index == i) { |
| 2524 DCHECK_EQ(FORCE_FIELD, store_mode); |
| 2525 property_kind_reconfiguration = old_details.kind() != new_kind; |
| 2526 |
| 2527 next_kind = new_kind; |
| 2528 next_location = kField; |
| 2529 next_attributes = new_attributes; |
| 2530 // If property kind is not reconfigured merge the result with |
| 2531 // representation/field type from the old descriptor. |
| 2532 next_representation = new_representation; |
| 2533 if (!property_kind_reconfiguration) { |
| 2534 next_representation = |
| 2535 next_representation.generalize(old_details.representation()); |
| 2536 } |
| 2537 |
| 2538 } else { |
| 2539 next_kind = old_details.kind(); |
| 2540 next_location = old_details.location(); |
| 2541 next_attributes = old_details.attributes(); |
| 2542 next_representation = old_details.representation(); |
| 2543 } |
| 2544 int j = target_map->SearchTransition(next_kind, old_descriptors->GetKey(i), |
| 2545 next_attributes); |
| 2451 if (j == TransitionArray::kNotFound) break; | 2546 if (j == TransitionArray::kNotFound) break; |
| 2452 Handle<Map> tmp_map(target_map->GetTransition(j), isolate); | 2547 Handle<Map> tmp_map(target_map->GetTransition(j), isolate); |
| 2453 Handle<DescriptorArray> tmp_descriptors = handle( | 2548 Handle<DescriptorArray> tmp_descriptors = handle( |
| 2454 tmp_map->instance_descriptors(), isolate); | 2549 tmp_map->instance_descriptors(), isolate); |
| 2455 | 2550 |
| 2456 // Check if target map is incompatible. | 2551 // Check if target map is incompatible. |
| 2457 PropertyDetails tmp_details = tmp_descriptors->GetDetails(i); | 2552 PropertyDetails tmp_details = tmp_descriptors->GetDetails(i); |
| 2458 PropertyType old_type = old_details.type(); | 2553 DCHECK_EQ(next_kind, tmp_details.kind()); |
| 2459 PropertyType tmp_type = tmp_details.type(); | 2554 DCHECK_EQ(next_attributes, tmp_details.attributes()); |
| 2460 DCHECK_EQ(old_details.attributes(), tmp_details.attributes()); | 2555 if (next_kind == kAccessor && |
| 2461 if ((tmp_type == ACCESSOR_CONSTANT || old_type == ACCESSOR_CONSTANT) && | 2556 !EqualImmutableValues(old_descriptors->GetValue(i), |
| 2462 (tmp_type != old_type || | 2557 tmp_descriptors->GetValue(i))) { |
| 2463 tmp_descriptors->GetValue(i) != old_descriptors->GetValue(i))) { | |
| 2464 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, | 2558 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, |
| 2559 new_kind, new_attributes, |
| 2465 "GenAll_Incompatible"); | 2560 "GenAll_Incompatible"); |
| 2466 } | 2561 } |
| 2467 Representation old_representation = old_details.representation(); | 2562 if (next_location == kField && tmp_details.location() == kDescriptor) break; |
| 2563 |
| 2468 Representation tmp_representation = tmp_details.representation(); | 2564 Representation tmp_representation = tmp_details.representation(); |
| 2469 if (!old_representation.fits_into(tmp_representation) || | 2565 if (!next_representation.fits_into(tmp_representation)) break; |
| 2470 (!new_representation.fits_into(tmp_representation) && | 2566 |
| 2471 modify_index == i)) { | 2567 PropertyLocation old_location = old_details.location(); |
| 2568 PropertyLocation tmp_location = tmp_details.location(); |
| 2569 if (tmp_location == kField) { |
| 2570 if (next_kind == kData) { |
| 2571 Handle<HeapType> next_field_type; |
| 2572 if (modify_index == i) { |
| 2573 next_field_type = new_field_type; |
| 2574 if (!property_kind_reconfiguration) { |
| 2575 Handle<HeapType> old_field_type = |
| 2576 GetFieldType(isolate, old_descriptors, i, |
| 2577 old_details.location(), tmp_representation); |
| 2578 next_field_type = |
| 2579 GeneralizeFieldType(next_field_type, old_field_type, isolate); |
| 2580 } |
| 2581 } else { |
| 2582 Handle<HeapType> old_field_type = |
| 2583 GetFieldType(isolate, old_descriptors, i, old_details.location(), |
| 2584 tmp_representation); |
| 2585 next_field_type = old_field_type; |
| 2586 } |
| 2587 GeneralizeFieldType(tmp_map, i, tmp_representation, next_field_type); |
| 2588 } |
| 2589 } else if (old_location == kField || |
| 2590 !EqualImmutableValues(old_descriptors->GetValue(i), |
| 2591 tmp_descriptors->GetValue(i))) { |
| 2472 break; | 2592 break; |
| 2473 } | 2593 } |
| 2474 if (tmp_type == DATA) { | 2594 DCHECK(!tmp_map->is_deprecated()); |
| 2475 // Generalize the field type as necessary. | |
| 2476 Handle<HeapType> old_field_type = | |
| 2477 (old_type == DATA) ? handle(old_descriptors->GetFieldType(i), isolate) | |
| 2478 : old_descriptors->GetValue(i) | |
| 2479 ->OptimalType(isolate, tmp_representation); | |
| 2480 if (modify_index == i) { | |
| 2481 old_field_type = GeneralizeFieldType( | |
| 2482 new_field_type, old_field_type, isolate); | |
| 2483 } | |
| 2484 GeneralizeFieldType(tmp_map, i, tmp_representation, old_field_type); | |
| 2485 } else if (tmp_type == DATA_CONSTANT) { | |
| 2486 if (old_type != DATA_CONSTANT || | |
| 2487 old_descriptors->GetConstant(i) != tmp_descriptors->GetConstant(i)) { | |
| 2488 break; | |
| 2489 } | |
| 2490 } else { | |
| 2491 DCHECK_EQ(tmp_type, old_type); | |
| 2492 DCHECK_EQ(tmp_descriptors->GetValue(i), old_descriptors->GetValue(i)); | |
| 2493 } | |
| 2494 target_map = tmp_map; | 2595 target_map = tmp_map; |
| 2495 } | 2596 } |
| 2496 | 2597 |
| 2497 // Directly change the map if the target map is more general. | 2598 // Directly change the map if the target map is more general. |
| 2498 Handle<DescriptorArray> target_descriptors( | 2599 Handle<DescriptorArray> target_descriptors( |
| 2499 target_map->instance_descriptors(), isolate); | 2600 target_map->instance_descriptors(), isolate); |
| 2500 int target_nof = target_map->NumberOfOwnDescriptors(); | 2601 int target_nof = target_map->NumberOfOwnDescriptors(); |
| 2501 if (target_nof == old_nof && | 2602 if (target_nof == old_nof && |
| 2502 (store_mode != FORCE_FIELD || | 2603 (store_mode != FORCE_FIELD || |
| 2503 target_descriptors->GetDetails(modify_index).type() == DATA)) { | 2604 (modify_index >= 0 && |
| 2504 DCHECK(modify_index < target_nof); | 2605 target_descriptors->GetDetails(modify_index).location() == kField))) { |
| 2505 DCHECK(new_representation.fits_into( | 2606 #ifdef DEBUG |
| 2506 target_descriptors->GetDetails(modify_index).representation())); | 2607 if (modify_index >= 0) { |
| 2507 DCHECK( | 2608 PropertyDetails details = target_descriptors->GetDetails(modify_index); |
| 2508 target_descriptors->GetDetails(modify_index).type() != DATA || | 2609 DCHECK_EQ(new_kind, details.kind()); |
| 2509 new_field_type->NowIs(target_descriptors->GetFieldType(modify_index))); | 2610 DCHECK_EQ(new_attributes, details.attributes()); |
| 2611 DCHECK(new_representation.fits_into(details.representation())); |
| 2612 DCHECK(details.location() != kField || |
| 2613 new_field_type->NowIs( |
| 2614 target_descriptors->GetFieldType(modify_index))); |
| 2615 } |
| 2616 #endif |
| 2510 return target_map; | 2617 return target_map; |
| 2511 } | 2618 } |
| 2512 | 2619 |
| 2513 // Find the last compatible target map in the transition tree. | 2620 // Find the last compatible target map in the transition tree. |
| 2514 for (int i = target_nof; i < old_nof; ++i) { | 2621 for (int i = target_nof; i < old_nof; ++i) { |
| 2515 PropertyDetails old_details = old_descriptors->GetDetails(i); | 2622 PropertyDetails old_details = old_descriptors->GetDetails(i); |
| 2516 int j = target_map->SearchTransition(old_details.kind(), | 2623 PropertyKind next_kind; |
| 2517 old_descriptors->GetKey(i), | 2624 PropertyAttributes next_attributes; |
| 2518 old_details.attributes()); | 2625 if (modify_index == i) { |
| 2626 next_kind = new_kind; |
| 2627 next_attributes = new_attributes; |
| 2628 } else { |
| 2629 next_kind = old_details.kind(); |
| 2630 next_attributes = old_details.attributes(); |
| 2631 } |
| 2632 int j = target_map->SearchTransition(next_kind, old_descriptors->GetKey(i), |
| 2633 next_attributes); |
| 2519 if (j == TransitionArray::kNotFound) break; | 2634 if (j == TransitionArray::kNotFound) break; |
| 2520 Handle<Map> tmp_map(target_map->GetTransition(j), isolate); | 2635 Handle<Map> tmp_map(target_map->GetTransition(j), isolate); |
| 2521 Handle<DescriptorArray> tmp_descriptors( | 2636 Handle<DescriptorArray> tmp_descriptors( |
| 2522 tmp_map->instance_descriptors(), isolate); | 2637 tmp_map->instance_descriptors(), isolate); |
| 2523 | 2638 |
| 2524 // Check if target map is compatible. | 2639 // Check if target map is compatible. |
| 2640 #ifdef DEBUG |
| 2525 PropertyDetails tmp_details = tmp_descriptors->GetDetails(i); | 2641 PropertyDetails tmp_details = tmp_descriptors->GetDetails(i); |
| 2526 DCHECK_EQ(old_details.attributes(), tmp_details.attributes()); | 2642 DCHECK_EQ(next_kind, tmp_details.kind()); |
| 2527 if ((tmp_details.type() == ACCESSOR_CONSTANT || | 2643 DCHECK_EQ(next_attributes, tmp_details.attributes()); |
| 2528 old_details.type() == ACCESSOR_CONSTANT) && | 2644 #endif |
| 2529 (tmp_details.type() != old_details.type() || | 2645 if (next_kind == kAccessor && |
| 2530 tmp_descriptors->GetValue(i) != old_descriptors->GetValue(i))) { | 2646 !EqualImmutableValues(old_descriptors->GetValue(i), |
| 2647 tmp_descriptors->GetValue(i))) { |
| 2531 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, | 2648 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, |
| 2649 new_kind, new_attributes, |
| 2532 "GenAll_Incompatible"); | 2650 "GenAll_Incompatible"); |
| 2533 } | 2651 } |
| 2652 DCHECK(!tmp_map->is_deprecated()); |
| 2534 target_map = tmp_map; | 2653 target_map = tmp_map; |
| 2535 } | 2654 } |
| 2536 target_nof = target_map->NumberOfOwnDescriptors(); | 2655 target_nof = target_map->NumberOfOwnDescriptors(); |
| 2537 target_descriptors = handle(target_map->instance_descriptors(), isolate); | 2656 target_descriptors = handle(target_map->instance_descriptors(), isolate); |
| 2538 | 2657 |
| 2539 // Allocate a new descriptor array large enough to hold the required | 2658 // Allocate a new descriptor array large enough to hold the required |
| 2540 // descriptors, with minimally the exact same size as the old descriptor | 2659 // descriptors, with minimally the exact same size as the old descriptor |
| 2541 // array. | 2660 // array. |
| 2542 int new_slack = Max( | 2661 int new_slack = Max( |
| 2543 old_nof, old_descriptors->number_of_descriptors()) - old_nof; | 2662 old_nof, old_descriptors->number_of_descriptors()) - old_nof; |
| 2544 Handle<DescriptorArray> new_descriptors = DescriptorArray::Allocate( | 2663 Handle<DescriptorArray> new_descriptors = DescriptorArray::Allocate( |
| 2545 isolate, old_nof, new_slack); | 2664 isolate, old_nof, new_slack); |
| 2546 DCHECK(new_descriptors->length() > target_descriptors->length() || | 2665 DCHECK(new_descriptors->length() > target_descriptors->length() || |
| 2547 new_descriptors->NumberOfSlackDescriptors() > 0 || | 2666 new_descriptors->NumberOfSlackDescriptors() > 0 || |
| 2548 new_descriptors->number_of_descriptors() == | 2667 new_descriptors->number_of_descriptors() == |
| 2549 old_descriptors->number_of_descriptors()); | 2668 old_descriptors->number_of_descriptors()); |
| 2550 DCHECK(new_descriptors->number_of_descriptors() == old_nof); | 2669 DCHECK(new_descriptors->number_of_descriptors() == old_nof); |
| 2551 | 2670 |
| 2552 // 0 -> |root_nof| | 2671 // 0 -> |root_nof| |
| 2553 int current_offset = 0; | 2672 int current_offset = 0; |
| 2554 for (int i = 0; i < root_nof; ++i) { | 2673 for (int i = 0; i < root_nof; ++i) { |
| 2555 PropertyDetails old_details = old_descriptors->GetDetails(i); | 2674 PropertyDetails old_details = old_descriptors->GetDetails(i); |
| 2556 if (old_details.type() == DATA) { | 2675 if (old_details.location() == kField) { |
| 2557 current_offset += old_details.field_width_in_words(); | 2676 current_offset += old_details.field_width_in_words(); |
| 2558 } | 2677 } |
| 2559 Descriptor d(handle(old_descriptors->GetKey(i), isolate), | 2678 Descriptor d(handle(old_descriptors->GetKey(i), isolate), |
| 2560 handle(old_descriptors->GetValue(i), isolate), | 2679 handle(old_descriptors->GetValue(i), isolate), |
| 2561 old_details); | 2680 old_details); |
| 2562 new_descriptors->Set(i, &d); | 2681 new_descriptors->Set(i, &d); |
| 2563 } | 2682 } |
| 2564 | 2683 |
| 2565 // |root_nof| -> |target_nof| | 2684 // |root_nof| -> |target_nof| |
| 2566 for (int i = root_nof; i < target_nof; ++i) { | 2685 for (int i = root_nof; i < target_nof; ++i) { |
| 2567 Handle<Name> target_key(target_descriptors->GetKey(i), isolate); | 2686 Handle<Name> target_key(target_descriptors->GetKey(i), isolate); |
| 2568 PropertyDetails old_details = old_descriptors->GetDetails(i); | 2687 PropertyDetails old_details = old_descriptors->GetDetails(i); |
| 2569 PropertyDetails target_details = target_descriptors->GetDetails(i); | 2688 PropertyDetails target_details = target_descriptors->GetDetails(i); |
| 2570 target_details = target_details.CopyWithRepresentation( | 2689 |
| 2571 old_details.representation().generalize( | 2690 PropertyKind next_kind; |
| 2572 target_details.representation())); | 2691 PropertyAttributes next_attributes; |
| 2692 PropertyLocation next_location; |
| 2693 Representation next_representation; |
| 2694 bool property_kind_reconfiguration = false; |
| 2695 |
| 2573 if (modify_index == i) { | 2696 if (modify_index == i) { |
| 2574 target_details = target_details.CopyWithRepresentation( | 2697 DCHECK_EQ(FORCE_FIELD, store_mode); |
| 2575 new_representation.generalize(target_details.representation())); | 2698 property_kind_reconfiguration = old_details.kind() != new_kind; |
| 2699 |
| 2700 next_kind = new_kind; |
| 2701 next_attributes = new_attributes; |
| 2702 next_location = kField; |
| 2703 |
| 2704 // Merge new representation/field type with ones from the target |
| 2705 // descriptor. If property kind is not reconfigured merge the result with |
| 2706 // representation/field type from the old descriptor. |
| 2707 next_representation = |
| 2708 new_representation.generalize(target_details.representation()); |
| 2709 if (!property_kind_reconfiguration) { |
| 2710 next_representation = |
| 2711 next_representation.generalize(old_details.representation()); |
| 2712 } |
| 2713 } else { |
| 2714 // Merge old_descriptor and target_descriptor entries. |
| 2715 DCHECK_EQ(target_details.kind(), old_details.kind()); |
| 2716 next_kind = target_details.kind(); |
| 2717 next_attributes = target_details.attributes(); |
| 2718 next_location = |
| 2719 old_details.location() == kField || |
| 2720 target_details.location() == kField || |
| 2721 !EqualImmutableValues(target_descriptors->GetValue(i), |
| 2722 old_descriptors->GetValue(i)) |
| 2723 ? kField |
| 2724 : kDescriptor; |
| 2725 |
| 2726 next_representation = old_details.representation().generalize( |
| 2727 target_details.representation()); |
| 2576 } | 2728 } |
| 2577 DCHECK_EQ(old_details.attributes(), target_details.attributes()); | 2729 DCHECK_EQ(next_kind, target_details.kind()); |
| 2578 if (old_details.type() == DATA || target_details.type() == DATA || | 2730 DCHECK_EQ(next_attributes, target_details.attributes()); |
| 2579 (modify_index == i && store_mode == FORCE_FIELD) || | 2731 |
| 2580 (target_descriptors->GetValue(i) != old_descriptors->GetValue(i))) { | 2732 if (next_location == kField) { |
| 2581 Handle<HeapType> old_field_type = | 2733 if (next_kind == kData) { |
| 2582 (old_details.type() == DATA) | 2734 Handle<HeapType> target_field_type = |
| 2583 ? handle(old_descriptors->GetFieldType(i), isolate) | 2735 GetFieldType(isolate, target_descriptors, i, |
| 2584 : old_descriptors->GetValue(i) | 2736 target_details.location(), next_representation); |
| 2585 ->OptimalType(isolate, target_details.representation()); | 2737 |
| 2586 Handle<HeapType> target_field_type = | 2738 Handle<HeapType> next_field_type; |
| 2587 (target_details.type() == DATA) | 2739 if (modify_index == i) { |
| 2588 ? handle(target_descriptors->GetFieldType(i), isolate) | 2740 next_field_type = |
| 2589 : target_descriptors->GetValue(i) | 2741 GeneralizeFieldType(target_field_type, new_field_type, isolate); |
| 2590 ->OptimalType(isolate, target_details.representation()); | 2742 if (!property_kind_reconfiguration) { |
| 2591 target_field_type = GeneralizeFieldType( | 2743 Handle<HeapType> old_field_type = |
| 2592 target_field_type, old_field_type, isolate); | 2744 GetFieldType(isolate, old_descriptors, i, |
| 2593 if (modify_index == i) { | 2745 old_details.location(), next_representation); |
| 2594 target_field_type = GeneralizeFieldType( | 2746 next_field_type = |
| 2595 target_field_type, new_field_type, isolate); | 2747 GeneralizeFieldType(next_field_type, old_field_type, isolate); |
| 2748 } |
| 2749 } else { |
| 2750 Handle<HeapType> old_field_type = |
| 2751 GetFieldType(isolate, old_descriptors, i, old_details.location(), |
| 2752 next_representation); |
| 2753 next_field_type = |
| 2754 GeneralizeFieldType(target_field_type, old_field_type, isolate); |
| 2755 } |
| 2756 DataDescriptor d(target_key, current_offset, next_field_type, |
| 2757 next_attributes, next_representation); |
| 2758 current_offset += d.GetDetails().field_width_in_words(); |
| 2759 new_descriptors->Set(i, &d); |
| 2760 } else { |
| 2761 UNIMPLEMENTED(); // TODO(ishell): implement. |
| 2596 } | 2762 } |
| 2597 DataDescriptor d(target_key, current_offset, target_field_type, | |
| 2598 target_details.attributes(), | |
| 2599 target_details.representation()); | |
| 2600 current_offset += d.GetDetails().field_width_in_words(); | |
| 2601 new_descriptors->Set(i, &d); | |
| 2602 } else { | 2763 } else { |
| 2603 DCHECK_NE(DATA, target_details.type()); | 2764 PropertyDetails details(next_attributes, next_kind, next_location, |
| 2604 Descriptor d(target_key, | 2765 next_representation); |
| 2605 handle(target_descriptors->GetValue(i), isolate), | 2766 Descriptor d(target_key, handle(target_descriptors->GetValue(i), isolate), |
| 2606 target_details); | 2767 details); |
| 2607 new_descriptors->Set(i, &d); | 2768 new_descriptors->Set(i, &d); |
| 2608 } | 2769 } |
| 2609 } | 2770 } |
| 2610 | 2771 |
| 2611 // |target_nof| -> |old_nof| | 2772 // |target_nof| -> |old_nof| |
| 2612 for (int i = target_nof; i < old_nof; ++i) { | 2773 for (int i = target_nof; i < old_nof; ++i) { |
| 2613 PropertyDetails old_details = old_descriptors->GetDetails(i); | 2774 PropertyDetails old_details = old_descriptors->GetDetails(i); |
| 2614 Handle<Name> old_key(old_descriptors->GetKey(i), isolate); | 2775 Handle<Name> old_key(old_descriptors->GetKey(i), isolate); |
| 2776 |
| 2777 // Merge old_descriptor entry and modified details together. |
| 2778 PropertyKind next_kind; |
| 2779 PropertyAttributes next_attributes; |
| 2780 PropertyLocation next_location; |
| 2781 Representation next_representation; |
| 2782 bool property_kind_reconfiguration = false; |
| 2783 |
| 2615 if (modify_index == i) { | 2784 if (modify_index == i) { |
| 2616 old_details = old_details.CopyWithRepresentation( | 2785 DCHECK_EQ(FORCE_FIELD, store_mode); |
| 2617 new_representation.generalize(old_details.representation())); | 2786 // In case of property kind reconfiguration it is not necessary to |
| 2787 // take into account representation/field type of the old descriptor. |
| 2788 property_kind_reconfiguration = old_details.kind() != new_kind; |
| 2789 |
| 2790 next_kind = new_kind; |
| 2791 next_attributes = new_attributes; |
| 2792 next_location = kField; |
| 2793 next_representation = new_representation; |
| 2794 if (!property_kind_reconfiguration) { |
| 2795 next_representation = |
| 2796 next_representation.generalize(old_details.representation()); |
| 2797 } |
| 2798 } else { |
| 2799 next_kind = old_details.kind(); |
| 2800 next_attributes = old_details.attributes(); |
| 2801 next_location = old_details.location(); |
| 2802 next_representation = old_details.representation(); |
| 2618 } | 2803 } |
| 2619 if (old_details.type() == DATA) { | 2804 |
| 2620 Handle<HeapType> old_field_type( | 2805 if (next_location == kField) { |
| 2621 old_descriptors->GetFieldType(i), isolate); | 2806 if (next_kind == kData) { |
| 2622 if (modify_index == i) { | 2807 Handle<HeapType> next_field_type; |
| 2623 old_field_type = GeneralizeFieldType( | 2808 if (modify_index == i) { |
| 2624 old_field_type, new_field_type, isolate); | 2809 next_field_type = new_field_type; |
| 2625 } | 2810 if (!property_kind_reconfiguration) { |
| 2626 DataDescriptor d(old_key, current_offset, old_field_type, | 2811 Handle<HeapType> old_field_type = |
| 2627 old_details.attributes(), old_details.representation()); | 2812 GetFieldType(isolate, old_descriptors, i, |
| 2628 current_offset += d.GetDetails().field_width_in_words(); | 2813 old_details.location(), next_representation); |
| 2629 new_descriptors->Set(i, &d); | 2814 old_field_type = |
| 2630 } else { | 2815 GeneralizeFieldType(old_field_type, next_field_type, isolate); |
| 2631 DCHECK(old_details.type() == DATA_CONSTANT || | 2816 } |
| 2632 old_details.type() == ACCESSOR_CONSTANT); | 2817 } else { |
| 2633 if (modify_index == i && store_mode == FORCE_FIELD) { | 2818 Handle<HeapType> old_field_type = |
| 2634 DataDescriptor d( | 2819 GetFieldType(isolate, old_descriptors, i, old_details.location(), |
| 2635 old_key, current_offset, | 2820 next_representation); |
| 2636 GeneralizeFieldType(old_descriptors->GetValue(i)->OptimalType( | 2821 next_field_type = old_field_type; |
| 2637 isolate, old_details.representation()), | 2822 } |
| 2638 new_field_type, isolate), | 2823 |
| 2639 old_details.attributes(), old_details.representation()); | 2824 DataDescriptor d(old_key, current_offset, next_field_type, |
| 2825 next_attributes, next_representation); |
| 2640 current_offset += d.GetDetails().field_width_in_words(); | 2826 current_offset += d.GetDetails().field_width_in_words(); |
| 2641 new_descriptors->Set(i, &d); | 2827 new_descriptors->Set(i, &d); |
| 2642 } else { | 2828 } else { |
| 2643 DCHECK_NE(DATA, old_details.type()); | 2829 UNIMPLEMENTED(); // TODO(ishell): implement. |
| 2644 Descriptor d(old_key, | |
| 2645 handle(old_descriptors->GetValue(i), isolate), | |
| 2646 old_details); | |
| 2647 new_descriptors->Set(i, &d); | |
| 2648 } | 2830 } |
| 2831 } else { |
| 2832 PropertyDetails details(next_attributes, next_kind, next_location, |
| 2833 next_representation); |
| 2834 Descriptor d(old_key, handle(old_descriptors->GetValue(i), isolate), |
| 2835 details); |
| 2836 new_descriptors->Set(i, &d); |
| 2649 } | 2837 } |
| 2650 } | 2838 } |
| 2651 | 2839 |
| 2652 new_descriptors->Sort(); | 2840 new_descriptors->Sort(); |
| 2653 | 2841 |
| 2654 DCHECK(store_mode != FORCE_FIELD || | 2842 DCHECK(store_mode != FORCE_FIELD || |
| 2655 new_descriptors->GetDetails(modify_index).type() == DATA); | 2843 new_descriptors->GetDetails(modify_index).location() == kField); |
| 2656 | 2844 |
| 2657 Handle<Map> split_map(root_map->FindLastMatchMap( | 2845 Handle<Map> split_map(root_map->FindLastMatchMap( |
| 2658 root_nof, old_nof, *new_descriptors), isolate); | 2846 root_nof, old_nof, *new_descriptors), isolate); |
| 2659 int split_nof = split_map->NumberOfOwnDescriptors(); | 2847 int split_nof = split_map->NumberOfOwnDescriptors(); |
| 2660 DCHECK_NE(old_nof, split_nof); | 2848 DCHECK_NE(old_nof, split_nof); |
| 2661 | 2849 |
| 2662 Handle<LayoutDescriptor> new_layout_descriptor = | 2850 Handle<LayoutDescriptor> new_layout_descriptor = |
| 2663 LayoutDescriptor::New(split_map, new_descriptors, old_nof); | 2851 LayoutDescriptor::New(split_map, new_descriptors, old_nof); |
| 2664 PropertyDetails split_prop_details = old_descriptors->GetDetails(split_nof); | 2852 |
| 2853 PropertyKind split_kind; |
| 2854 PropertyAttributes split_attributes; |
| 2855 if (modify_index == split_nof) { |
| 2856 split_kind = new_kind; |
| 2857 split_attributes = new_attributes; |
| 2858 } else { |
| 2859 PropertyDetails split_prop_details = old_descriptors->GetDetails(split_nof); |
| 2860 split_kind = split_prop_details.kind(); |
| 2861 split_attributes = split_prop_details.attributes(); |
| 2862 } |
| 2665 bool transition_target_deprecated = split_map->DeprecateTarget( | 2863 bool transition_target_deprecated = split_map->DeprecateTarget( |
| 2666 split_prop_details.kind(), old_descriptors->GetKey(split_nof), | 2864 split_kind, old_descriptors->GetKey(split_nof), split_attributes, |
| 2667 split_prop_details.attributes(), *new_descriptors, | 2865 *new_descriptors, *new_layout_descriptor); |
| 2668 *new_layout_descriptor); | |
| 2669 | 2866 |
| 2670 // If |transition_target_deprecated| is true then the transition array | 2867 // If |transition_target_deprecated| is true then the transition array |
| 2671 // already contains entry for given descriptor. This means that the transition | 2868 // already contains entry for given descriptor. This means that the transition |
| 2672 // could be inserted regardless of whether transitions array is full or not. | 2869 // could be inserted regardless of whether transitions array is full or not. |
| 2673 if (!transition_target_deprecated && !split_map->CanHaveMoreTransitions()) { | 2870 if (!transition_target_deprecated && !split_map->CanHaveMoreTransitions()) { |
| 2674 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, | 2871 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, |
| 2872 new_kind, new_attributes, |
| 2675 "GenAll_CantHaveMoreTransitions"); | 2873 "GenAll_CantHaveMoreTransitions"); |
| 2676 } | 2874 } |
| 2677 | 2875 |
| 2678 if (FLAG_trace_generalization) { | 2876 if (FLAG_trace_generalization && modify_index >= 0) { |
| 2679 PropertyDetails old_details = old_descriptors->GetDetails(modify_index); | 2877 PropertyDetails old_details = old_descriptors->GetDetails(modify_index); |
| 2680 PropertyDetails new_details = new_descriptors->GetDetails(modify_index); | 2878 PropertyDetails new_details = new_descriptors->GetDetails(modify_index); |
| 2681 Handle<HeapType> old_field_type = | 2879 Handle<HeapType> old_field_type = |
| 2682 (old_details.type() == DATA) | 2880 (old_details.type() == DATA) |
| 2683 ? handle(old_descriptors->GetFieldType(modify_index), isolate) | 2881 ? handle(old_descriptors->GetFieldType(modify_index), isolate) |
| 2684 : HeapType::Constant( | 2882 : HeapType::Constant( |
| 2685 handle(old_descriptors->GetValue(modify_index), isolate), | 2883 handle(old_descriptors->GetValue(modify_index), isolate), |
| 2686 isolate); | 2884 isolate); |
| 2687 Handle<HeapType> new_field_type = | 2885 Handle<HeapType> new_field_type = |
| 2688 (new_details.type() == DATA) | 2886 (new_details.type() == DATA) |
| 2689 ? handle(new_descriptors->GetFieldType(modify_index), isolate) | 2887 ? handle(new_descriptors->GetFieldType(modify_index), isolate) |
| 2690 : HeapType::Constant( | 2888 : HeapType::Constant( |
| 2691 handle(new_descriptors->GetValue(modify_index), isolate), | 2889 handle(new_descriptors->GetValue(modify_index), isolate), |
| 2692 isolate); | 2890 isolate); |
| 2693 old_map->PrintGeneralization( | 2891 old_map->PrintGeneralization( |
| 2694 stdout, "", modify_index, split_nof, old_nof, | 2892 stdout, "", modify_index, split_nof, old_nof, |
| 2695 old_details.type() == DATA_CONSTANT && store_mode == FORCE_FIELD, | 2893 old_details.location() == kDescriptor && store_mode == FORCE_FIELD, |
| 2696 old_details.representation(), new_details.representation(), | 2894 old_details.representation(), new_details.representation(), |
| 2697 *old_field_type, *new_field_type); | 2895 *old_field_type, *new_field_type); |
| 2698 } | 2896 } |
| 2699 | 2897 |
| 2700 // Add missing transitions. | 2898 // Add missing transitions. |
| 2701 Handle<Map> new_map = split_map; | 2899 Handle<Map> new_map = split_map; |
| 2702 for (int i = split_nof; i < old_nof; ++i) { | 2900 for (int i = split_nof; i < old_nof; ++i) { |
| 2703 new_map = CopyInstallDescriptors(new_map, i, new_descriptors, | 2901 new_map = CopyInstallDescriptors(new_map, i, new_descriptors, |
| 2704 new_layout_descriptor); | 2902 new_layout_descriptor); |
| 2705 } | 2903 } |
| 2706 new_map->set_owns_descriptors(true); | 2904 new_map->set_owns_descriptors(true); |
| 2707 return new_map; | 2905 return new_map; |
| 2708 } | 2906 } |
| 2709 | 2907 |
| 2710 | 2908 |
| 2711 // Generalize the representation of all DATA descriptors. | 2909 // Generalize the representation of all DATA descriptors. |
| 2712 Handle<Map> Map::GeneralizeAllFieldRepresentations( | 2910 Handle<Map> Map::GeneralizeAllFieldRepresentations( |
| 2713 Handle<Map> map) { | 2911 Handle<Map> map) { |
| 2714 Handle<DescriptorArray> descriptors(map->instance_descriptors()); | 2912 Handle<DescriptorArray> descriptors(map->instance_descriptors()); |
| 2715 for (int i = 0; i < map->NumberOfOwnDescriptors(); ++i) { | 2913 for (int i = 0; i < map->NumberOfOwnDescriptors(); ++i) { |
| 2716 if (descriptors->GetDetails(i).type() == DATA) { | 2914 PropertyDetails details = descriptors->GetDetails(i); |
| 2717 map = GeneralizeRepresentation(map, i, Representation::Tagged(), | 2915 if (details.type() == DATA) { |
| 2718 HeapType::Any(map->GetIsolate()), | 2916 map = ReconfigureProperty(map, i, kData, details.attributes(), |
| 2719 FORCE_FIELD); | 2917 Representation::Tagged(), |
| 2918 HeapType::Any(map->GetIsolate()), FORCE_FIELD); |
| 2720 } | 2919 } |
| 2721 } | 2920 } |
| 2722 return map; | 2921 return map; |
| 2723 } | 2922 } |
| 2724 | 2923 |
| 2725 | 2924 |
| 2726 // static | 2925 // static |
| 2727 MaybeHandle<Map> Map::TryUpdate(Handle<Map> map) { | 2926 MaybeHandle<Map> Map::TryUpdate(Handle<Map> map) { |
| 2728 Handle<Map> proto_map(map); | 2927 Handle<Map> proto_map(map); |
| 2729 while (proto_map->prototype()->IsJSObject()) { | 2928 while (proto_map->prototype()->IsJSObject()) { |
| 2730 Handle<JSObject> holder(JSObject::cast(proto_map->prototype())); | 2929 Handle<JSObject> holder(JSObject::cast(proto_map->prototype())); |
| 2731 proto_map = Handle<Map>(holder->map()); | 2930 proto_map = Handle<Map>(holder->map()); |
| 2732 if (proto_map->is_deprecated() && JSObject::TryMigrateInstance(holder)) { | 2931 if (proto_map->is_deprecated() && JSObject::TryMigrateInstance(holder)) { |
| 2733 proto_map = Handle<Map>(holder->map()); | 2932 proto_map = Handle<Map>(holder->map()); |
| 2734 } | 2933 } |
| 2735 } | 2934 } |
| 2736 return TryUpdateInternal(map); | 2935 return TryUpdateInternal(map); |
| 2737 } | 2936 } |
| 2738 | 2937 |
| 2739 | 2938 |
| 2740 // static | 2939 // static |
| 2741 Handle<Map> Map::Update(Handle<Map> map) { | 2940 Handle<Map> Map::Update(Handle<Map> map) { |
| 2742 if (!map->is_deprecated()) return map; | 2941 if (!map->is_deprecated()) return map; |
| 2743 return GeneralizeRepresentation(map, 0, Representation::None(), | 2942 return ReconfigureProperty(map, -1, kData, NONE, Representation::None(), |
| 2744 HeapType::None(map->GetIsolate()), | 2943 HeapType::None(map->GetIsolate()), |
| 2745 ALLOW_IN_DESCRIPTOR); | 2944 ALLOW_IN_DESCRIPTOR); |
| 2746 } | 2945 } |
| 2747 | 2946 |
| 2748 | 2947 |
| 2749 // static | 2948 // static |
| 2750 MaybeHandle<Map> Map::TryUpdateInternal(Handle<Map> old_map) { | 2949 MaybeHandle<Map> Map::TryUpdateInternal(Handle<Map> old_map) { |
| 2751 DisallowHeapAllocation no_allocation; | 2950 DisallowHeapAllocation no_allocation; |
| 2752 DisallowDeoptimization no_deoptimization(old_map->GetIsolate()); | 2951 DisallowDeoptimization no_deoptimization(old_map->GetIsolate()); |
| 2753 | 2952 |
| 2754 if (!old_map->is_deprecated()) return old_map; | 2953 if (!old_map->is_deprecated()) return old_map; |
| 2755 | 2954 |
| (...skipping 1189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3945 RETURN_ON_EXCEPTION( | 4144 RETURN_ON_EXCEPTION( |
| 3946 it.isolate(), | 4145 it.isolate(), |
| 3947 EnqueueChangeRecord(object, "reconfigure", name, | 4146 EnqueueChangeRecord(object, "reconfigure", name, |
| 3948 it.isolate()->factory()->the_hole_value()), | 4147 it.isolate()->factory()->the_hole_value()), |
| 3949 Object); | 4148 Object); |
| 3950 } | 4149 } |
| 3951 return value; | 4150 return value; |
| 3952 } | 4151 } |
| 3953 | 4152 |
| 3954 it.ReconfigureDataProperty(value, attributes); | 4153 it.ReconfigureDataProperty(value, attributes); |
| 3955 it.PrepareForDataProperty(value); | |
| 3956 value = it.WriteDataValue(value); | 4154 value = it.WriteDataValue(value); |
| 3957 | 4155 |
| 3958 if (is_observed) { | 4156 if (is_observed) { |
| 3959 RETURN_ON_EXCEPTION( | 4157 RETURN_ON_EXCEPTION( |
| 3960 it.isolate(), | 4158 it.isolate(), |
| 3961 EnqueueChangeRecord(object, "reconfigure", name, | 4159 EnqueueChangeRecord(object, "reconfigure", name, |
| 3962 it.isolate()->factory()->the_hole_value()), | 4160 it.isolate()->factory()->the_hole_value()), |
| 3963 Object); | 4161 Object); |
| 3964 } | 4162 } |
| 3965 | 4163 |
| 3966 return value; | 4164 return value; |
| 3967 } | 4165 } |
| 3968 | 4166 |
| 3969 case LookupIterator::DATA: { | 4167 case LookupIterator::DATA: { |
| 3970 PropertyDetails details = it.property_details(); | 4168 PropertyDetails details = it.property_details(); |
| 3971 Handle<Object> old_value = it.isolate()->factory()->the_hole_value(); | 4169 Handle<Object> old_value = it.isolate()->factory()->the_hole_value(); |
| 3972 // Regular property update if the attributes match. | 4170 // Regular property update if the attributes match. |
| 3973 if (details.attributes() == attributes) { | 4171 if (details.attributes() == attributes) { |
| 3974 return SetDataProperty(&it, value); | 4172 return SetDataProperty(&it, value); |
| 3975 } | 4173 } |
| 3976 // Reconfigure the data property if the attributes mismatch. | 4174 // Reconfigure the data property if the attributes mismatch. |
| 3977 if (is_observed) old_value = it.GetDataValue(); | 4175 if (is_observed) old_value = it.GetDataValue(); |
| 3978 | 4176 |
| 3979 it.ReconfigureDataProperty(value, attributes); | 4177 it.ReconfigureDataProperty(value, attributes); |
| 3980 it.PrepareForDataProperty(value); | |
| 3981 value = it.WriteDataValue(value); | 4178 value = it.WriteDataValue(value); |
| 3982 | 4179 |
| 3983 if (is_observed) { | 4180 if (is_observed) { |
| 3984 if (old_value->SameValue(*value)) { | 4181 if (old_value->SameValue(*value)) { |
| 3985 old_value = it.isolate()->factory()->the_hole_value(); | 4182 old_value = it.isolate()->factory()->the_hole_value(); |
| 3986 } | 4183 } |
| 3987 RETURN_ON_EXCEPTION( | 4184 RETURN_ON_EXCEPTION( |
| 3988 it.isolate(), | 4185 it.isolate(), |
| 3989 EnqueueChangeRecord(object, "reconfigure", name, old_value), | 4186 EnqueueChangeRecord(object, "reconfigure", name, old_value), |
| 3990 Object); | 4187 Object); |
| (...skipping 1848 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5839 return result; | 6036 return result; |
| 5840 } | 6037 } |
| 5841 | 6038 |
| 5842 | 6039 |
| 5843 int Map::NextFreePropertyIndex() { | 6040 int Map::NextFreePropertyIndex() { |
| 5844 int free_index = 0; | 6041 int free_index = 0; |
| 5845 int number_of_own_descriptors = NumberOfOwnDescriptors(); | 6042 int number_of_own_descriptors = NumberOfOwnDescriptors(); |
| 5846 DescriptorArray* descs = instance_descriptors(); | 6043 DescriptorArray* descs = instance_descriptors(); |
| 5847 for (int i = 0; i < number_of_own_descriptors; i++) { | 6044 for (int i = 0; i < number_of_own_descriptors; i++) { |
| 5848 PropertyDetails details = descs->GetDetails(i); | 6045 PropertyDetails details = descs->GetDetails(i); |
| 5849 if (details.type() == DATA) { | 6046 if (details.location() == kField) { |
| 5850 int candidate = details.field_index() + details.field_width_in_words(); | 6047 int candidate = details.field_index() + details.field_width_in_words(); |
| 5851 if (candidate > free_index) free_index = candidate; | 6048 if (candidate > free_index) free_index = candidate; |
| 5852 } | 6049 } |
| 5853 } | 6050 } |
| 5854 return free_index; | 6051 return free_index; |
| 5855 } | 6052 } |
| 5856 | 6053 |
| 5857 | 6054 |
| 5858 static bool ContainsOnlyValidKeys(Handle<FixedArray> array) { | 6055 static bool ContainsOnlyValidKeys(Handle<FixedArray> array) { |
| 5859 int len = array->length(); | 6056 int len = array->length(); |
| (...skipping 974 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6834 Handle<LayoutDescriptor> full_layout_descriptor) { | 7031 Handle<LayoutDescriptor> full_layout_descriptor) { |
| 6835 DCHECK(descriptors->IsSortedNoDuplicates()); | 7032 DCHECK(descriptors->IsSortedNoDuplicates()); |
| 6836 | 7033 |
| 6837 Handle<Map> result = CopyDropDescriptors(map); | 7034 Handle<Map> result = CopyDropDescriptors(map); |
| 6838 | 7035 |
| 6839 result->set_instance_descriptors(*descriptors); | 7036 result->set_instance_descriptors(*descriptors); |
| 6840 result->SetNumberOfOwnDescriptors(new_descriptor + 1); | 7037 result->SetNumberOfOwnDescriptors(new_descriptor + 1); |
| 6841 | 7038 |
| 6842 int unused_property_fields = map->unused_property_fields(); | 7039 int unused_property_fields = map->unused_property_fields(); |
| 6843 PropertyDetails details = descriptors->GetDetails(new_descriptor); | 7040 PropertyDetails details = descriptors->GetDetails(new_descriptor); |
| 6844 if (details.type() == DATA) { | 7041 if (details.location() == kField) { |
| 6845 unused_property_fields = map->unused_property_fields() - 1; | 7042 unused_property_fields = map->unused_property_fields() - 1; |
| 6846 if (unused_property_fields < 0) { | 7043 if (unused_property_fields < 0) { |
| 6847 unused_property_fields += JSObject::kFieldsAdded; | 7044 unused_property_fields += JSObject::kFieldsAdded; |
| 6848 } | 7045 } |
| 6849 } | 7046 } |
| 6850 result->set_unused_property_fields(unused_property_fields); | 7047 result->set_unused_property_fields(unused_property_fields); |
| 6851 | 7048 |
| 6852 if (FLAG_unbox_double_fields) { | 7049 if (FLAG_unbox_double_fields) { |
| 6853 Handle<LayoutDescriptor> layout_descriptor = | 7050 Handle<LayoutDescriptor> layout_descriptor = |
| 6854 LayoutDescriptor::AppendIfFastOrUseFull(map, details, | 7051 LayoutDescriptor::AppendIfFastOrUseFull(map, details, |
| (...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7052 if (map->is_dictionary_map()) return map; | 7249 if (map->is_dictionary_map()) return map; |
| 7053 | 7250 |
| 7054 // Migrate to the newest map before storing the property. | 7251 // Migrate to the newest map before storing the property. |
| 7055 map = Update(map); | 7252 map = Update(map); |
| 7056 | 7253 |
| 7057 Handle<DescriptorArray> descriptors(map->instance_descriptors()); | 7254 Handle<DescriptorArray> descriptors(map->instance_descriptors()); |
| 7058 | 7255 |
| 7059 if (descriptors->CanHoldValue(descriptor, *value)) return map; | 7256 if (descriptors->CanHoldValue(descriptor, *value)) return map; |
| 7060 | 7257 |
| 7061 Isolate* isolate = map->GetIsolate(); | 7258 Isolate* isolate = map->GetIsolate(); |
| 7259 PropertyAttributes attributes = |
| 7260 descriptors->GetDetails(descriptor).attributes(); |
| 7062 Representation representation = value->OptimalRepresentation(); | 7261 Representation representation = value->OptimalRepresentation(); |
| 7063 Handle<HeapType> type = value->OptimalType(isolate, representation); | 7262 Handle<HeapType> type = value->OptimalType(isolate, representation); |
| 7064 | 7263 |
| 7065 return GeneralizeRepresentation(map, descriptor, representation, type, | 7264 return ReconfigureProperty(map, descriptor, kData, attributes, representation, |
| 7066 FORCE_FIELD); | 7265 type, FORCE_FIELD); |
| 7067 } | 7266 } |
| 7068 | 7267 |
| 7069 | 7268 |
| 7070 Handle<Map> Map::TransitionToDataProperty(Handle<Map> map, Handle<Name> name, | 7269 Handle<Map> Map::TransitionToDataProperty(Handle<Map> map, Handle<Name> name, |
| 7071 Handle<Object> value, | 7270 Handle<Object> value, |
| 7072 PropertyAttributes attributes, | 7271 PropertyAttributes attributes, |
| 7073 StoreFromKeyed store_mode) { | 7272 StoreFromKeyed store_mode) { |
| 7074 // Dictionary maps can always have additional data properties. | 7273 // Dictionary maps can always have additional data properties. |
| 7075 if (map->is_dictionary_map()) return map; | 7274 if (map->is_dictionary_map()) return map; |
| 7076 | 7275 |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7113 } | 7312 } |
| 7114 #endif | 7313 #endif |
| 7115 return Map::Normalize(map, CLEAR_INOBJECT_PROPERTIES, | 7314 return Map::Normalize(map, CLEAR_INOBJECT_PROPERTIES, |
| 7116 "TooManyFastProperties"); | 7315 "TooManyFastProperties"); |
| 7117 } | 7316 } |
| 7118 | 7317 |
| 7119 return result; | 7318 return result; |
| 7120 } | 7319 } |
| 7121 | 7320 |
| 7122 | 7321 |
| 7123 Handle<Map> Map::ReconfigureDataProperty(Handle<Map> map, int descriptor, | 7322 Handle<Map> Map::ReconfigureExistingProperty(Handle<Map> map, int descriptor, |
| 7124 PropertyAttributes attributes) { | 7323 PropertyKind kind, |
| 7324 PropertyAttributes attributes) { |
| 7125 // Dictionaries have to be reconfigured in-place. | 7325 // Dictionaries have to be reconfigured in-place. |
| 7126 DCHECK(!map->is_dictionary_map()); | 7326 DCHECK(!map->is_dictionary_map()); |
| 7127 | 7327 |
| 7128 // For now, give up on transitioning and just create a unique map. | 7328 if (!map->GetBackPointer()->IsMap()) { |
| 7129 // TODO(verwaest/ishell): Cache transitions with different attributes. | 7329 // There is no benefit from reconstructing transition tree for maps without |
| 7130 return CopyGeneralizeAllRepresentations( | 7330 // back pointers. |
| 7131 map, descriptor, FORCE_FIELD, attributes, "GenAll_AttributesMismatch"); | 7331 return CopyGeneralizeAllRepresentations( |
| 7332 map, descriptor, FORCE_FIELD, kind, attributes, |
| 7333 "GenAll_AttributesMismatchProtoMap"); |
| 7334 } |
| 7335 |
| 7336 if (FLAG_trace_generalization) { |
| 7337 map->PrintReconfiguration(stdout, descriptor, kind, attributes); |
| 7338 } |
| 7339 |
| 7340 Isolate* isolate = map->GetIsolate(); |
| 7341 Handle<Map> new_map = ReconfigureProperty( |
| 7342 map, descriptor, kind, attributes, Representation::None(), |
| 7343 HeapType::None(isolate), FORCE_FIELD); |
| 7344 return new_map; |
| 7132 } | 7345 } |
| 7133 | 7346 |
| 7134 | 7347 |
| 7135 Handle<Map> Map::TransitionToAccessorProperty(Handle<Map> map, | 7348 Handle<Map> Map::TransitionToAccessorProperty(Handle<Map> map, |
| 7136 Handle<Name> name, | 7349 Handle<Name> name, |
| 7137 AccessorComponent component, | 7350 AccessorComponent component, |
| 7138 Handle<Object> accessor, | 7351 Handle<Object> accessor, |
| 7139 PropertyAttributes attributes) { | 7352 PropertyAttributes attributes) { |
| 7140 Isolate* isolate = name->GetIsolate(); | 7353 Isolate* isolate = name->GetIsolate(); |
| 7141 | 7354 |
| (...skipping 9852 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 16994 CompilationInfo* info) { | 17207 CompilationInfo* info) { |
| 16995 Handle<DependentCode> codes = DependentCode::InsertCompilationInfo( | 17208 Handle<DependentCode> codes = DependentCode::InsertCompilationInfo( |
| 16996 handle(cell->dependent_code(), info->isolate()), | 17209 handle(cell->dependent_code(), info->isolate()), |
| 16997 DependentCode::kPropertyCellChangedGroup, info->object_wrapper()); | 17210 DependentCode::kPropertyCellChangedGroup, info->object_wrapper()); |
| 16998 if (*codes != cell->dependent_code()) cell->set_dependent_code(*codes); | 17211 if (*codes != cell->dependent_code()) cell->set_dependent_code(*codes); |
| 16999 info->dependencies(DependentCode::kPropertyCellChangedGroup)->Add( | 17212 info->dependencies(DependentCode::kPropertyCellChangedGroup)->Add( |
| 17000 cell, info->zone()); | 17213 cell, info->zone()); |
| 17001 } | 17214 } |
| 17002 | 17215 |
| 17003 } } // namespace v8::internal | 17216 } } // namespace v8::internal |
| OLD | NEW |