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