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 "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/accessors.h" | 7 #include "src/accessors.h" |
8 #include "src/allocation-site-scopes.h" | 8 #include "src/allocation-site-scopes.h" |
9 #include "src/api.h" | 9 #include "src/api.h" |
10 #include "src/arguments.h" | 10 #include "src/arguments.h" |
(...skipping 2150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2161 if (!old_map->InstancesNeedRewriting( | 2161 if (!old_map->InstancesNeedRewriting( |
2162 *new_map, number_of_fields, inobject, unused)) { | 2162 *new_map, number_of_fields, inobject, unused)) { |
2163 // Writing the new map here does not require synchronization since it does | 2163 // Writing the new map here does not require synchronization since it does |
2164 // not change the actual object size. | 2164 // not change the actual object size. |
2165 object->synchronized_set_map(*new_map); | 2165 object->synchronized_set_map(*new_map); |
2166 return; | 2166 return; |
2167 } | 2167 } |
2168 | 2168 |
2169 int total_size = number_of_fields + unused; | 2169 int total_size = number_of_fields + unused; |
2170 int external = total_size - inobject; | 2170 int external = total_size - inobject; |
| 2171 |
| 2172 if ((old_map->unused_property_fields() == 0) && |
| 2173 (new_map->GetBackPointer() == *old_map)) { |
| 2174 // This migration is a transition from a map that has run out out property |
| 2175 // space. Therefore it could be done by extending the backing store. |
| 2176 Handle<FixedArray> old_storage = handle(object->properties(), isolate); |
| 2177 Handle<FixedArray> new_storage = |
| 2178 FixedArray::CopySize(old_storage, external); |
| 2179 |
| 2180 // Properly initialize newly added property. |
| 2181 PropertyDetails details = new_map->GetLastDescriptorDetails(); |
| 2182 Handle<Object> value; |
| 2183 if (details.representation().IsDouble()) { |
| 2184 value = isolate->factory()->NewHeapNumber(0); |
| 2185 } else { |
| 2186 value = isolate->factory()->uninitialized_value(); |
| 2187 } |
| 2188 ASSERT(details.type() == FIELD); |
| 2189 int target_index = details.field_index() - inobject; |
| 2190 ASSERT(target_index >= 0); // Must be a backing store index. |
| 2191 new_storage->set(target_index, *value); |
| 2192 |
| 2193 // From here on we cannot fail and we shouldn't GC anymore. |
| 2194 DisallowHeapAllocation no_allocation; |
| 2195 |
| 2196 // Set the new property value and do the map transition. |
| 2197 object->set_properties(*new_storage); |
| 2198 // Writing the new map here does not require synchronization since it does |
| 2199 // not change the actual object size. |
| 2200 object->set_map(*new_map); |
| 2201 return; |
| 2202 } |
2171 Handle<FixedArray> array = isolate->factory()->NewFixedArray(total_size); | 2203 Handle<FixedArray> array = isolate->factory()->NewFixedArray(total_size); |
2172 | 2204 |
2173 Handle<DescriptorArray> old_descriptors(old_map->instance_descriptors()); | 2205 Handle<DescriptorArray> old_descriptors(old_map->instance_descriptors()); |
2174 Handle<DescriptorArray> new_descriptors(new_map->instance_descriptors()); | 2206 Handle<DescriptorArray> new_descriptors(new_map->instance_descriptors()); |
2175 int old_nof = old_map->NumberOfOwnDescriptors(); | 2207 int old_nof = old_map->NumberOfOwnDescriptors(); |
2176 int new_nof = new_map->NumberOfOwnDescriptors(); | 2208 int new_nof = new_map->NumberOfOwnDescriptors(); |
2177 | 2209 |
2178 // This method only supports generalizing instances to at least the same | 2210 // This method only supports generalizing instances to at least the same |
2179 // number of properties. | 2211 // number of properties. |
2180 ASSERT(old_nof <= new_nof); | 2212 ASSERT(old_nof <= new_nof); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2231 object->FastPropertyAtPut(index, array->get(external + i)); | 2263 object->FastPropertyAtPut(index, array->get(external + i)); |
2232 } | 2264 } |
2233 | 2265 |
2234 // Create filler object past the new instance size. | 2266 // Create filler object past the new instance size. |
2235 int new_instance_size = new_map->instance_size(); | 2267 int new_instance_size = new_map->instance_size(); |
2236 int instance_size_delta = old_map->instance_size() - new_instance_size; | 2268 int instance_size_delta = old_map->instance_size() - new_instance_size; |
2237 ASSERT(instance_size_delta >= 0); | 2269 ASSERT(instance_size_delta >= 0); |
2238 Address address = object->address() + new_instance_size; | 2270 Address address = object->address() + new_instance_size; |
2239 | 2271 |
2240 // The trimming is performed on a newly allocated object, which is on a | 2272 // The trimming is performed on a newly allocated object, which is on a |
2241 // fresly allocated page or on an already swept page. Hence, the sweeper | 2273 // freshly allocated page or on an already swept page. Hence, the sweeper |
2242 // thread can not get confused with the filler creation. No synchronization | 2274 // thread can not get confused with the filler creation. No synchronization |
2243 // needed. | 2275 // needed. |
2244 isolate->heap()->CreateFillerObjectAt(address, instance_size_delta); | 2276 isolate->heap()->CreateFillerObjectAt(address, instance_size_delta); |
2245 | 2277 |
2246 // If there are properties in the new backing store, trim it to the correct | 2278 // If there are properties in the new backing store, trim it to the correct |
2247 // size and install the backing store into the object. | 2279 // size and install the backing store into the object. |
2248 if (external > 0) { | 2280 if (external > 0) { |
2249 RightTrimFixedArray<Heap::FROM_MUTATOR>(isolate->heap(), *array, inobject); | 2281 RightTrimFixedArray<Heap::FROM_MUTATOR>(isolate->heap(), *array, inobject); |
2250 object->set_properties(*array); | 2282 object->set_properties(*array); |
2251 } | 2283 } |
2252 | 2284 |
2253 // The trimming is performed on a newly allocated object, which is on a | 2285 // The trimming is performed on a newly allocated object, which is on a |
2254 // fresly allocated page or on an already swept page. Hence, the sweeper | 2286 // freshly allocated page or on an already swept page. Hence, the sweeper |
2255 // thread can not get confused with the filler creation. No synchronization | 2287 // thread can not get confused with the filler creation. No synchronization |
2256 // needed. | 2288 // needed. |
2257 object->set_map(*new_map); | 2289 object->set_map(*new_map); |
2258 } | 2290 } |
2259 | 2291 |
2260 | 2292 |
2261 void JSObject::GeneralizeFieldRepresentation(Handle<JSObject> object, | 2293 void JSObject::GeneralizeFieldRepresentation(Handle<JSObject> object, |
2262 int modify_index, | 2294 int modify_index, |
2263 Representation new_representation, | 2295 Representation new_representation, |
2264 Handle<HeapType> new_field_type, | 2296 Handle<HeapType> new_field_type, |
(...skipping 14735 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
17000 #define ERROR_MESSAGES_TEXTS(C, T) T, | 17032 #define ERROR_MESSAGES_TEXTS(C, T) T, |
17001 static const char* error_messages_[] = { | 17033 static const char* error_messages_[] = { |
17002 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) | 17034 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) |
17003 }; | 17035 }; |
17004 #undef ERROR_MESSAGES_TEXTS | 17036 #undef ERROR_MESSAGES_TEXTS |
17005 return error_messages_[reason]; | 17037 return error_messages_[reason]; |
17006 } | 17038 } |
17007 | 17039 |
17008 | 17040 |
17009 } } // namespace v8::internal | 17041 } } // namespace v8::internal |
OLD | NEW |