OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 2252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2263 ASSERT(target_inobject < inobject_properties()); | 2263 ASSERT(target_inobject < inobject_properties()); |
2264 if (target_number_of_fields <= target_inobject) { | 2264 if (target_number_of_fields <= target_inobject) { |
2265 ASSERT(target_number_of_fields + target_unused == target_inobject); | 2265 ASSERT(target_number_of_fields + target_unused == target_inobject); |
2266 return false; | 2266 return false; |
2267 } | 2267 } |
2268 // Otherwise, properties will need to be moved to the backing store. | 2268 // Otherwise, properties will need to be moved to the backing store. |
2269 return true; | 2269 return true; |
2270 } | 2270 } |
2271 | 2271 |
2272 | 2272 |
| 2273 void JSObject::MigrateToMap(Handle<JSObject> object, Handle<Map> new_map) { |
| 2274 CALL_HEAP_FUNCTION_VOID(object->GetIsolate(), object->MigrateToMap(*new_map)); |
| 2275 } |
| 2276 |
| 2277 |
2273 // To migrate an instance to a map: | 2278 // To migrate an instance to a map: |
2274 // - First check whether the instance needs to be rewritten. If not, simply | 2279 // - First check whether the instance needs to be rewritten. If not, simply |
2275 // change the map. | 2280 // change the map. |
2276 // - Otherwise, allocate a fixed array large enough to hold all fields, in | 2281 // - Otherwise, allocate a fixed array large enough to hold all fields, in |
2277 // addition to unused space. | 2282 // addition to unused space. |
2278 // - Copy all existing properties in, in the following order: backing store | 2283 // - Copy all existing properties in, in the following order: backing store |
2279 // properties, unused fields, inobject properties. | 2284 // properties, unused fields, inobject properties. |
2280 // - If all allocation succeeded, commit the state atomically: | 2285 // - If all allocation succeeded, commit the state atomically: |
2281 // * Copy inobject properties from the backing store back into the object. | 2286 // * Copy inobject properties from the backing store back into the object. |
2282 // * Trim the difference in instance size of the object. This also cleanly | 2287 // * Trim the difference in instance size of the object. This also cleanly |
2283 // frees inobject properties that moved to the backing store. | 2288 // frees inobject properties that moved to the backing store. |
2284 // * If there are properties left in the backing store, trim of the space used | 2289 // * If there are properties left in the backing store, trim of the space used |
2285 // to temporarily store the inobject properties. | 2290 // to temporarily store the inobject properties. |
2286 // * If there are properties left in the backing store, install the backing | 2291 // * If there are properties left in the backing store, install the backing |
2287 // store. | 2292 // store. |
2288 void JSObject::MigrateToMap(Handle<JSObject> object, Handle<Map> new_map) { | 2293 MaybeObject* JSObject::MigrateToMap(Map* new_map) { |
2289 Isolate* isolate = object->GetIsolate(); | 2294 Heap* heap = GetHeap(); |
2290 Handle<Map> old_map(object->map()); | 2295 Map* old_map = map(); |
2291 int number_of_fields = new_map->NumberOfFields(); | 2296 int number_of_fields = new_map->NumberOfFields(); |
2292 int inobject = new_map->inobject_properties(); | 2297 int inobject = new_map->inobject_properties(); |
2293 int unused = new_map->unused_property_fields(); | 2298 int unused = new_map->unused_property_fields(); |
2294 | 2299 |
2295 // Nothing to do if no functions were converted to fields and no smis were | 2300 // Nothing to do if no functions were converted to fields. |
2296 // converted to doubles. | |
2297 if (!old_map->InstancesNeedRewriting( | 2301 if (!old_map->InstancesNeedRewriting( |
2298 *new_map, number_of_fields, inobject, unused)) { | 2302 new_map, number_of_fields, inobject, unused)) { |
2299 object->set_map(*new_map); | 2303 set_map(new_map); |
2300 return; | 2304 return this; |
2301 } | 2305 } |
2302 | 2306 |
2303 int total_size = number_of_fields + unused; | 2307 int total_size = number_of_fields + unused; |
2304 int external = total_size - inobject; | 2308 int external = total_size - inobject; |
2305 Handle<FixedArray> array = isolate->factory()->NewFixedArray(total_size); | 2309 FixedArray* array; |
| 2310 MaybeObject* maybe_array = heap->AllocateFixedArray(total_size); |
| 2311 if (!maybe_array->To(&array)) return maybe_array; |
2306 | 2312 |
2307 DescriptorArray* old_descriptors = old_map->instance_descriptors(); | 2313 DescriptorArray* old_descriptors = old_map->instance_descriptors(); |
2308 DescriptorArray* new_descriptors = new_map->instance_descriptors(); | 2314 DescriptorArray* new_descriptors = new_map->instance_descriptors(); |
2309 int descriptors = new_map->NumberOfOwnDescriptors(); | 2315 int descriptors = new_map->NumberOfOwnDescriptors(); |
2310 | 2316 |
2311 for (int i = 0; i < descriptors; i++) { | 2317 for (int i = 0; i < descriptors; i++) { |
2312 PropertyDetails details = new_descriptors->GetDetails(i); | 2318 PropertyDetails details = new_descriptors->GetDetails(i); |
2313 if (details.type() != FIELD) continue; | 2319 if (details.type() != FIELD) continue; |
2314 PropertyDetails old_details = old_descriptors->GetDetails(i); | 2320 PropertyDetails old_details = old_descriptors->GetDetails(i); |
2315 if (old_details.type() == CALLBACKS) { | 2321 if (old_details.type() == CALLBACKS) { |
2316 ASSERT(details.representation().IsTagged()); | 2322 ASSERT(details.representation().IsTagged()); |
2317 continue; | 2323 continue; |
2318 } | 2324 } |
2319 ASSERT(old_details.type() == CONSTANT || | 2325 ASSERT(old_details.type() == CONSTANT || |
2320 old_details.type() == FIELD); | 2326 old_details.type() == FIELD); |
2321 Object* raw_value = old_details.type() == CONSTANT | 2327 Object* value = old_details.type() == CONSTANT |
2322 ? old_descriptors->GetValue(i) | 2328 ? old_descriptors->GetValue(i) |
2323 : object->RawFastPropertyAt(old_descriptors->GetFieldIndex(i)); | 2329 : RawFastPropertyAt(old_descriptors->GetFieldIndex(i)); |
2324 Handle<Object> value(raw_value, isolate); | |
2325 if (FLAG_track_double_fields && | 2330 if (FLAG_track_double_fields && |
2326 !old_details.representation().IsDouble() && | 2331 !old_details.representation().IsDouble() && |
2327 details.representation().IsDouble()) { | 2332 details.representation().IsDouble()) { |
2328 if (old_details.representation().IsNone()) { | 2333 if (old_details.representation().IsNone()) value = Smi::FromInt(0); |
2329 value = handle(Smi::FromInt(0), isolate); | 2334 // Objects must be allocated in the old object space, since the |
2330 } | 2335 // overall number of HeapNumbers needed for the conversion might |
2331 value = NewStorageFor(isolate, value, details.representation()); | 2336 // exceed the capacity of new space, and we would fail repeatedly |
| 2337 // trying to migrate the instance. |
| 2338 MaybeObject* maybe_storage = |
| 2339 value->AllocateNewStorageFor(heap, details.representation(), TENURED); |
| 2340 if (!maybe_storage->To(&value)) return maybe_storage; |
2332 } | 2341 } |
2333 ASSERT(!(FLAG_track_double_fields && | 2342 ASSERT(!(FLAG_track_double_fields && |
2334 details.representation().IsDouble() && | 2343 details.representation().IsDouble() && |
2335 value->IsSmi())); | 2344 value->IsSmi())); |
2336 int target_index = new_descriptors->GetFieldIndex(i) - inobject; | 2345 int target_index = new_descriptors->GetFieldIndex(i) - inobject; |
2337 if (target_index < 0) target_index += total_size; | 2346 if (target_index < 0) target_index += total_size; |
2338 array->set(target_index, *value); | 2347 array->set(target_index, value); |
2339 } | 2348 } |
2340 | 2349 |
2341 // From here on we cannot fail and we shouldn't GC anymore. | 2350 // From here on we cannot fail anymore. |
2342 DisallowHeapAllocation no_allocation; | |
2343 | 2351 |
2344 // Copy (real) inobject properties. If necessary, stop at number_of_fields to | 2352 // Copy (real) inobject properties. If necessary, stop at number_of_fields to |
2345 // avoid overwriting |one_pointer_filler_map|. | 2353 // avoid overwriting |one_pointer_filler_map|. |
2346 int limit = Min(inobject, number_of_fields); | 2354 int limit = Min(inobject, number_of_fields); |
2347 for (int i = 0; i < limit; i++) { | 2355 for (int i = 0; i < limit; i++) { |
2348 object->FastPropertyAtPut(i, array->get(external + i)); | 2356 FastPropertyAtPut(i, array->get(external + i)); |
2349 } | 2357 } |
2350 | 2358 |
2351 // Create filler object past the new instance size. | 2359 // Create filler object past the new instance size. |
2352 int new_instance_size = new_map->instance_size(); | 2360 int new_instance_size = new_map->instance_size(); |
2353 int instance_size_delta = old_map->instance_size() - new_instance_size; | 2361 int instance_size_delta = old_map->instance_size() - new_instance_size; |
2354 ASSERT(instance_size_delta >= 0); | 2362 ASSERT(instance_size_delta >= 0); |
2355 Address address = object->address() + new_instance_size; | 2363 Address address = this->address() + new_instance_size; |
2356 isolate->heap()->CreateFillerObjectAt(address, instance_size_delta); | 2364 heap->CreateFillerObjectAt(address, instance_size_delta); |
2357 | 2365 |
2358 // If there are properties in the new backing store, trim it to the correct | 2366 // If there are properties in the new backing store, trim it to the correct |
2359 // size and install the backing store into the object. | 2367 // size and install the backing store into the object. |
2360 if (external > 0) { | 2368 if (external > 0) { |
2361 RightTrimFixedArray<FROM_MUTATOR>(isolate->heap(), *array, inobject); | 2369 RightTrimFixedArray<FROM_MUTATOR>(heap, array, inobject); |
2362 object->set_properties(*array); | 2370 set_properties(array); |
2363 } | 2371 } |
2364 | 2372 |
2365 object->set_map(*new_map); | 2373 set_map(new_map); |
| 2374 |
| 2375 return this; |
2366 } | 2376 } |
2367 | 2377 |
2368 | 2378 |
2369 void JSObject::GeneralizeFieldRepresentation(Handle<JSObject> object, | 2379 void JSObject::GeneralizeFieldRepresentation(Handle<JSObject> object, |
2370 int modify_index, | 2380 int modify_index, |
2371 Representation new_representation, | 2381 Representation new_representation, |
2372 StoreMode store_mode) { | 2382 StoreMode store_mode) { |
2373 Handle<Map> new_map = Map::GeneralizeRepresentation( | 2383 Handle<Map> new_map = Map::GeneralizeRepresentation( |
2374 handle(object->map()), modify_index, new_representation, store_mode); | 2384 handle(object->map()), modify_index, new_representation, store_mode); |
2375 if (object->map() == *new_map) return; | 2385 if (object->map() == *new_map) return; |
(...skipping 1365 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3741 Handle<Map> original_map(object->map()); | 3751 Handle<Map> original_map(object->map()); |
3742 GeneralizeFieldRepresentation( | 3752 GeneralizeFieldRepresentation( |
3743 object, 0, Representation::None(), ALLOW_AS_CONSTANT); | 3753 object, 0, Representation::None(), ALLOW_AS_CONSTANT); |
3744 if (FLAG_trace_migration) { | 3754 if (FLAG_trace_migration) { |
3745 object->PrintInstanceMigration(stdout, *original_map, object->map()); | 3755 object->PrintInstanceMigration(stdout, *original_map, object->map()); |
3746 } | 3756 } |
3747 } | 3757 } |
3748 | 3758 |
3749 | 3759 |
3750 Handle<Object> JSObject::TryMigrateInstance(Handle<JSObject> object) { | 3760 Handle<Object> JSObject::TryMigrateInstance(Handle<JSObject> object) { |
3751 Map* new_map = object->map()->CurrentMapForDeprecated(); | 3761 MigrateInstance(object); |
3752 if (new_map == NULL) return Handle<Object>(); | |
3753 Handle<Map> original_map(object->map()); | |
3754 JSObject::MigrateToMap(object, handle(new_map)); | |
3755 if (FLAG_trace_migration) { | |
3756 object->PrintInstanceMigration(stdout, *original_map, object->map()); | |
3757 } | |
3758 return object; | 3762 return object; |
3759 } | 3763 } |
3760 | 3764 |
3761 | 3765 |
3762 Handle<Object> JSObject::SetPropertyUsingTransition( | 3766 Handle<Object> JSObject::SetPropertyUsingTransition( |
3763 Handle<JSObject> object, | 3767 Handle<JSObject> object, |
3764 LookupResult* lookup, | 3768 LookupResult* lookup, |
3765 Handle<Name> name, | 3769 Handle<Name> name, |
3766 Handle<Object> value, | 3770 Handle<Object> value, |
3767 PropertyAttributes attributes) { | 3771 PropertyAttributes attributes) { |
(...skipping 12334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
16102 #define ERROR_MESSAGES_TEXTS(C, T) T, | 16106 #define ERROR_MESSAGES_TEXTS(C, T) T, |
16103 static const char* error_messages_[] = { | 16107 static const char* error_messages_[] = { |
16104 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) | 16108 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) |
16105 }; | 16109 }; |
16106 #undef ERROR_MESSAGES_TEXTS | 16110 #undef ERROR_MESSAGES_TEXTS |
16107 return error_messages_[reason]; | 16111 return error_messages_[reason]; |
16108 } | 16112 } |
16109 | 16113 |
16110 | 16114 |
16111 } } // namespace v8::internal | 16115 } } // namespace v8::internal |
OLD | NEW |