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 1835 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1846 | 1846 |
1847 | 1847 |
1848 String* JSReceiver::constructor_name() { | 1848 String* JSReceiver::constructor_name() { |
1849 return map()->constructor_name(); | 1849 return map()->constructor_name(); |
1850 } | 1850 } |
1851 | 1851 |
1852 | 1852 |
1853 // TODO(mstarzinger): Temporary wrapper until handlified. | 1853 // TODO(mstarzinger): Temporary wrapper until handlified. |
1854 static Handle<Object> NewStorageFor(Isolate* isolate, | 1854 static Handle<Object> NewStorageFor(Isolate* isolate, |
1855 Handle<Object> object, | 1855 Handle<Object> object, |
1856 Representation representation) { | 1856 Representation representation, |
1857 PretenureFlag tenure = NOT_TENURED) { | |
1857 Heap* heap = isolate->heap(); | 1858 Heap* heap = isolate->heap(); |
1858 CALL_HEAP_FUNCTION(isolate, | 1859 CALL_HEAP_FUNCTION(isolate, |
1859 object->AllocateNewStorageFor(heap, representation), | 1860 object->AllocateNewStorageFor( |
1861 heap, representation, tenure), | |
1860 Object); | 1862 Object); |
1861 } | 1863 } |
1862 | 1864 |
1863 | 1865 |
1864 void JSObject::AddFastPropertyUsingMap(Handle<JSObject> object, | 1866 void JSObject::AddFastPropertyUsingMap(Handle<JSObject> object, |
1865 Handle<Map> new_map, | 1867 Handle<Map> new_map, |
1866 Handle<Name> name, | 1868 Handle<Name> name, |
1867 Handle<Object> value, | 1869 Handle<Object> value, |
1868 int field_index, | 1870 int field_index, |
1869 Representation representation) { | 1871 Representation representation) { |
(...skipping 393 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2263 ASSERT(target_inobject < inobject_properties()); | 2265 ASSERT(target_inobject < inobject_properties()); |
2264 if (target_number_of_fields <= target_inobject) { | 2266 if (target_number_of_fields <= target_inobject) { |
2265 ASSERT(target_number_of_fields + target_unused == target_inobject); | 2267 ASSERT(target_number_of_fields + target_unused == target_inobject); |
2266 return false; | 2268 return false; |
2267 } | 2269 } |
2268 // Otherwise, properties will need to be moved to the backing store. | 2270 // Otherwise, properties will need to be moved to the backing store. |
2269 return true; | 2271 return true; |
2270 } | 2272 } |
2271 | 2273 |
2272 | 2274 |
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: | 2275 // To migrate an instance to a map: |
2279 // - First check whether the instance needs to be rewritten. If not, simply | 2276 // - First check whether the instance needs to be rewritten. If not, simply |
2280 // change the map. | 2277 // change the map. |
2281 // - Otherwise, allocate a fixed array large enough to hold all fields, in | 2278 // - Otherwise, allocate a fixed array large enough to hold all fields, in |
2282 // addition to unused space. | 2279 // addition to unused space. |
2283 // - Copy all existing properties in, in the following order: backing store | 2280 // - Copy all existing properties in, in the following order: backing store |
2284 // properties, unused fields, inobject properties. | 2281 // properties, unused fields, inobject properties. |
2285 // - If all allocation succeeded, commit the state atomically: | 2282 // - If all allocation succeeded, commit the state atomically: |
2286 // * Copy inobject properties from the backing store back into the object. | 2283 // * Copy inobject properties from the backing store back into the object. |
2287 // * Trim the difference in instance size of the object. This also cleanly | 2284 // * Trim the difference in instance size of the object. This also cleanly |
2288 // frees inobject properties that moved to the backing store. | 2285 // frees inobject properties that moved to the backing store. |
2289 // * If there are properties left in the backing store, trim of the space used | 2286 // * If there are properties left in the backing store, trim of the space used |
2290 // to temporarily store the inobject properties. | 2287 // to temporarily store the inobject properties. |
2291 // * If there are properties left in the backing store, install the backing | 2288 // * If there are properties left in the backing store, install the backing |
2292 // store. | 2289 // store. |
2293 MaybeObject* JSObject::MigrateToMap(Map* new_map) { | 2290 void JSObject::MigrateToMap(Handle<JSObject> object, Handle<Map> new_map) { |
2294 Heap* heap = GetHeap(); | 2291 Isolate* isolate = object->GetIsolate(); |
2295 Map* old_map = map(); | 2292 Handle<Map> old_map(object->map()); |
2296 int number_of_fields = new_map->NumberOfFields(); | 2293 int number_of_fields = new_map->NumberOfFields(); |
2297 int inobject = new_map->inobject_properties(); | 2294 int inobject = new_map->inobject_properties(); |
2298 int unused = new_map->unused_property_fields(); | 2295 int unused = new_map->unused_property_fields(); |
2299 | 2296 |
2300 // Nothing to do if no functions were converted to fields. | 2297 // Nothing to do if no functions were converted to fields. |
Toon Verwaest
2013/09/19 11:41:42
and no smis were converted to doubles.
Michael Starzinger
2013/09/19 15:47:56
Done.
| |
2301 if (!old_map->InstancesNeedRewriting( | 2298 if (!old_map->InstancesNeedRewriting( |
2302 new_map, number_of_fields, inobject, unused)) { | 2299 *new_map, number_of_fields, inobject, unused)) { |
2303 set_map(new_map); | 2300 object->set_map(*new_map); |
2304 return this; | 2301 return; |
2305 } | 2302 } |
2306 | 2303 |
2307 int total_size = number_of_fields + unused; | 2304 int total_size = number_of_fields + unused; |
2308 int external = total_size - inobject; | 2305 int external = total_size - inobject; |
2309 FixedArray* array; | 2306 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 | 2307 |
2313 DescriptorArray* old_descriptors = old_map->instance_descriptors(); | 2308 DescriptorArray* old_descriptors = old_map->instance_descriptors(); |
2314 DescriptorArray* new_descriptors = new_map->instance_descriptors(); | 2309 DescriptorArray* new_descriptors = new_map->instance_descriptors(); |
2315 int descriptors = new_map->NumberOfOwnDescriptors(); | 2310 int descriptors = new_map->NumberOfOwnDescriptors(); |
2316 | 2311 |
2317 for (int i = 0; i < descriptors; i++) { | 2312 for (int i = 0; i < descriptors; i++) { |
2318 PropertyDetails details = new_descriptors->GetDetails(i); | 2313 PropertyDetails details = new_descriptors->GetDetails(i); |
2319 if (details.type() != FIELD) continue; | 2314 if (details.type() != FIELD) continue; |
2320 PropertyDetails old_details = old_descriptors->GetDetails(i); | 2315 PropertyDetails old_details = old_descriptors->GetDetails(i); |
2321 if (old_details.type() == CALLBACKS) { | 2316 if (old_details.type() == CALLBACKS) { |
2322 ASSERT(details.representation().IsTagged()); | 2317 ASSERT(details.representation().IsTagged()); |
2323 continue; | 2318 continue; |
2324 } | 2319 } |
2325 ASSERT(old_details.type() == CONSTANT || | 2320 ASSERT(old_details.type() == CONSTANT || |
2326 old_details.type() == FIELD); | 2321 old_details.type() == FIELD); |
2327 Object* value = old_details.type() == CONSTANT | 2322 Object* raw_value = old_details.type() == CONSTANT |
2328 ? old_descriptors->GetValue(i) | 2323 ? old_descriptors->GetValue(i) |
2329 : RawFastPropertyAt(old_descriptors->GetFieldIndex(i)); | 2324 : object->RawFastPropertyAt(old_descriptors->GetFieldIndex(i)); |
2325 Handle<Object> value(raw_value, isolate); | |
2330 if (FLAG_track_double_fields && | 2326 if (FLAG_track_double_fields && |
2331 !old_details.representation().IsDouble() && | 2327 !old_details.representation().IsDouble() && |
2332 details.representation().IsDouble()) { | 2328 details.representation().IsDouble()) { |
2333 if (old_details.representation().IsNone()) value = Smi::FromInt(0); | 2329 if (old_details.representation().IsNone()) { |
2330 value = handle(Smi::FromInt(0), isolate); | |
2331 } | |
2334 // Objects must be allocated in the old object space, since the | 2332 // Objects must be allocated in the old object space, since the |
2335 // overall number of HeapNumbers needed for the conversion might | 2333 // overall number of HeapNumbers needed for the conversion might |
2336 // exceed the capacity of new space, and we would fail repeatedly | 2334 // exceed the capacity of new space, and we would fail repeatedly |
2337 // trying to migrate the instance. | 2335 // trying to migrate the instance. |
Toon Verwaest
2013/09/19 11:41:42
Now that this is handlified, we don't need to pre-
Michael Starzinger
2013/09/19 15:47:56
Done.
| |
2338 MaybeObject* maybe_storage = | 2336 value = NewStorageFor(isolate, value, details.representation(), TENURED); |
2339 value->AllocateNewStorageFor(heap, details.representation(), TENURED); | |
2340 if (!maybe_storage->To(&value)) return maybe_storage; | |
2341 } | 2337 } |
2342 ASSERT(!(FLAG_track_double_fields && | 2338 ASSERT(!(FLAG_track_double_fields && |
2343 details.representation().IsDouble() && | 2339 details.representation().IsDouble() && |
2344 value->IsSmi())); | 2340 value->IsSmi())); |
2345 int target_index = new_descriptors->GetFieldIndex(i) - inobject; | 2341 int target_index = new_descriptors->GetFieldIndex(i) - inobject; |
2346 if (target_index < 0) target_index += total_size; | 2342 if (target_index < 0) target_index += total_size; |
2347 array->set(target_index, value); | 2343 array->set(target_index, *value); |
2348 } | 2344 } |
2349 | 2345 |
2350 // From here on we cannot fail anymore. | 2346 // From here on we cannot fail and we shouldn't GC anymore. |
2351 | 2347 |
2352 // Copy (real) inobject properties. If necessary, stop at number_of_fields to | 2348 // Copy (real) inobject properties. If necessary, stop at number_of_fields to |
2353 // avoid overwriting |one_pointer_filler_map|. | 2349 // avoid overwriting |one_pointer_filler_map|. |
2354 int limit = Min(inobject, number_of_fields); | 2350 int limit = Min(inobject, number_of_fields); |
2355 for (int i = 0; i < limit; i++) { | 2351 for (int i = 0; i < limit; i++) { |
2356 FastPropertyAtPut(i, array->get(external + i)); | 2352 object->FastPropertyAtPut(i, array->get(external + i)); |
2357 } | 2353 } |
2358 | 2354 |
2359 // Create filler object past the new instance size. | 2355 // Create filler object past the new instance size. |
2360 int new_instance_size = new_map->instance_size(); | 2356 int new_instance_size = new_map->instance_size(); |
2361 int instance_size_delta = old_map->instance_size() - new_instance_size; | 2357 int instance_size_delta = old_map->instance_size() - new_instance_size; |
2362 ASSERT(instance_size_delta >= 0); | 2358 ASSERT(instance_size_delta >= 0); |
2363 Address address = this->address() + new_instance_size; | 2359 Address address = object->address() + new_instance_size; |
2364 heap->CreateFillerObjectAt(address, instance_size_delta); | 2360 isolate->heap()->CreateFillerObjectAt(address, instance_size_delta); |
2365 | 2361 |
2366 // If there are properties in the new backing store, trim it to the correct | 2362 // If there are properties in the new backing store, trim it to the correct |
2367 // size and install the backing store into the object. | 2363 // size and install the backing store into the object. |
2368 if (external > 0) { | 2364 if (external > 0) { |
2369 RightTrimFixedArray<FROM_MUTATOR>(heap, array, inobject); | 2365 RightTrimFixedArray<FROM_MUTATOR>(isolate->heap(), *array, inobject); |
2370 set_properties(array); | 2366 object->set_properties(*array); |
2371 } | 2367 } |
2372 | 2368 |
2373 set_map(new_map); | 2369 object->set_map(*new_map); |
2374 | |
2375 return this; | |
2376 } | 2370 } |
2377 | 2371 |
2378 | 2372 |
2379 void JSObject::GeneralizeFieldRepresentation(Handle<JSObject> object, | 2373 void JSObject::GeneralizeFieldRepresentation(Handle<JSObject> object, |
2380 int modify_index, | 2374 int modify_index, |
2381 Representation new_representation, | 2375 Representation new_representation, |
2382 StoreMode store_mode) { | 2376 StoreMode store_mode) { |
2383 Handle<Map> new_map = Map::GeneralizeRepresentation( | 2377 Handle<Map> new_map = Map::GeneralizeRepresentation( |
2384 handle(object->map()), modify_index, new_representation, store_mode); | 2378 handle(object->map()), modify_index, new_representation, store_mode); |
2385 if (object->map() == *new_map) return; | 2379 if (object->map() == *new_map) return; |
(...skipping 1368 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3754 Handle<Map> original_map(object->map()); | 3748 Handle<Map> original_map(object->map()); |
3755 GeneralizeFieldRepresentation( | 3749 GeneralizeFieldRepresentation( |
3756 object, 0, Representation::None(), ALLOW_AS_CONSTANT); | 3750 object, 0, Representation::None(), ALLOW_AS_CONSTANT); |
3757 if (FLAG_trace_migration) { | 3751 if (FLAG_trace_migration) { |
3758 object->PrintInstanceMigration(stdout, *original_map, object->map()); | 3752 object->PrintInstanceMigration(stdout, *original_map, object->map()); |
3759 } | 3753 } |
3760 } | 3754 } |
3761 | 3755 |
3762 | 3756 |
3763 Handle<Object> JSObject::TryMigrateInstance(Handle<JSObject> object) { | 3757 Handle<Object> JSObject::TryMigrateInstance(Handle<JSObject> object) { |
3764 MigrateInstance(object); | 3758 Map* new_map = object->map()->CurrentMapForDeprecated(); |
3759 if (new_map == NULL) return Handle<Object>(); | |
3760 Handle<Map> original_map(object->map()); | |
3761 JSObject::MigrateToMap(object, handle(new_map)); | |
3762 if (FLAG_trace_migration) { | |
3763 object->PrintInstanceMigration(stdout, *original_map, object->map()); | |
3764 } | |
3765 return object; | 3765 return object; |
3766 } | 3766 } |
3767 | 3767 |
3768 | 3768 |
3769 Handle<Object> JSObject::SetPropertyUsingTransition( | 3769 Handle<Object> JSObject::SetPropertyUsingTransition( |
3770 Handle<JSObject> object, | 3770 Handle<JSObject> object, |
3771 LookupResult* lookup, | 3771 LookupResult* lookup, |
3772 Handle<Name> name, | 3772 Handle<Name> name, |
3773 Handle<Object> value, | 3773 Handle<Object> value, |
3774 PropertyAttributes attributes) { | 3774 PropertyAttributes attributes) { |
(...skipping 12350 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
16125 #define ERROR_MESSAGES_TEXTS(C, T) T, | 16125 #define ERROR_MESSAGES_TEXTS(C, T) T, |
16126 static const char* error_messages_[] = { | 16126 static const char* error_messages_[] = { |
16127 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) | 16127 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) |
16128 }; | 16128 }; |
16129 #undef ERROR_MESSAGES_TEXTS | 16129 #undef ERROR_MESSAGES_TEXTS |
16130 return error_messages_[reason]; | 16130 return error_messages_[reason]; |
16131 } | 16131 } |
16132 | 16132 |
16133 | 16133 |
16134 } } // namespace v8::internal | 16134 } } // namespace v8::internal |
OLD | NEW |