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 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
66 Object* result; | 66 Object* result; |
67 { MaybeObject* maybe_result = | 67 { MaybeObject* maybe_result = |
68 constructor->GetHeap()->AllocateJSObject(constructor); | 68 constructor->GetHeap()->AllocateJSObject(constructor); |
69 if (!maybe_result->ToObject(&result)) return maybe_result; | 69 if (!maybe_result->ToObject(&result)) return maybe_result; |
70 } | 70 } |
71 JSValue::cast(result)->set_value(value); | 71 JSValue::cast(result)->set_value(value); |
72 return result; | 72 return result; |
73 } | 73 } |
74 | 74 |
75 | 75 |
76 Handle<HeapType> Object::OptimalType(Isolate* isolate, | |
77 Representation representation) { | |
78 if (!FLAG_track_field_types) return HeapType::Any(isolate); | |
79 if (representation.IsNone()) return HeapType::None(isolate); | |
80 if (representation.IsHeapObject() && IsHeapObject()) { | |
81 // We can track only JavaScript objects with stable maps. | |
82 Handle<Map> map(HeapObject::cast(this)->map(), isolate); | |
83 if (map->is_stable() && | |
84 map->instance_type() >= FIRST_NONCALLABLE_SPEC_OBJECT_TYPE && | |
85 map->instance_type() <= LAST_NONCALLABLE_SPEC_OBJECT_TYPE) { | |
86 return HeapType::Class(map, isolate); | |
87 } | |
88 } | |
89 return HeapType::Any(isolate); | |
90 } | |
91 | |
92 | |
93 MaybeObject* Object::ToObject(Context* native_context) { | 76 MaybeObject* Object::ToObject(Context* native_context) { |
94 if (IsNumber()) { | 77 if (IsNumber()) { |
95 return CreateJSValue(native_context->number_function(), this); | 78 return CreateJSValue(native_context->number_function(), this); |
96 } else if (IsBoolean()) { | 79 } else if (IsBoolean()) { |
97 return CreateJSValue(native_context->boolean_function(), this); | 80 return CreateJSValue(native_context->boolean_function(), this); |
98 } else if (IsString()) { | 81 } else if (IsString()) { |
99 return CreateJSValue(native_context->string_function(), this); | 82 return CreateJSValue(native_context->string_function(), this); |
100 } else if (IsSymbol()) { | 83 } else if (IsSymbol()) { |
101 return CreateJSValue(native_context->symbol_function(), this); | 84 return CreateJSValue(native_context->symbol_function(), this); |
102 } | 85 } |
(...skipping 1354 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1457 } | 1440 } |
1458 | 1441 |
1459 | 1442 |
1460 void Map::PrintGeneralization(FILE* file, | 1443 void Map::PrintGeneralization(FILE* file, |
1461 const char* reason, | 1444 const char* reason, |
1462 int modify_index, | 1445 int modify_index, |
1463 int split, | 1446 int split, |
1464 int descriptors, | 1447 int descriptors, |
1465 bool constant_to_field, | 1448 bool constant_to_field, |
1466 Representation old_representation, | 1449 Representation old_representation, |
1467 Representation new_representation, | 1450 Representation new_representation) { |
1468 HeapType* old_field_type, | |
1469 HeapType* new_field_type) { | |
1470 PrintF(file, "[generalizing "); | 1451 PrintF(file, "[generalizing "); |
1471 constructor_name()->PrintOn(file); | 1452 constructor_name()->PrintOn(file); |
1472 PrintF(file, "] "); | 1453 PrintF(file, "] "); |
1473 Name* name = instance_descriptors()->GetKey(modify_index); | 1454 Name* name = instance_descriptors()->GetKey(modify_index); |
1474 if (name->IsString()) { | 1455 if (name->IsString()) { |
1475 String::cast(name)->PrintOn(file); | 1456 String::cast(name)->PrintOn(file); |
1476 } else { | 1457 } else { |
1477 PrintF(file, "{symbol %p}", static_cast<void*>(name)); | 1458 PrintF(file, "{symbol %p}", static_cast<void*>(name)); |
1478 } | 1459 } |
1479 PrintF(file, ":"); | |
1480 if (constant_to_field) { | 1460 if (constant_to_field) { |
1481 PrintF(file, "c"); | 1461 PrintF(file, ":c->f"); |
1482 } else { | 1462 } else { |
1483 PrintF(file, "%s", old_representation.Mnemonic()); | 1463 PrintF(file, ":%s->%s", |
1484 PrintF(file, "{"); | 1464 old_representation.Mnemonic(), |
1485 old_field_type->TypePrint(file, HeapType::SEMANTIC_DIM); | 1465 new_representation.Mnemonic()); |
1486 PrintF(file, "}"); | |
1487 } | 1466 } |
1488 PrintF(file, "->%s", new_representation.Mnemonic()); | |
1489 PrintF(file, "{"); | |
1490 new_field_type->TypePrint(file, HeapType::SEMANTIC_DIM); | |
1491 PrintF(file, "}"); | |
1492 PrintF(file, " ("); | 1467 PrintF(file, " ("); |
1493 if (strlen(reason) > 0) { | 1468 if (strlen(reason) > 0) { |
1494 PrintF(file, "%s", reason); | 1469 PrintF(file, "%s", reason); |
1495 } else { | 1470 } else { |
1496 PrintF(file, "+%i maps", descriptors - split); | 1471 PrintF(file, "+%i maps", descriptors - split); |
1497 } | 1472 } |
1498 PrintF(file, ") ["); | 1473 PrintF(file, ") ["); |
1499 JavaScriptFrame::PrintTop(GetIsolate(), file, false, true); | 1474 JavaScriptFrame::PrintTop(GetIsolate(), file, false, true); |
1500 PrintF(file, "]\n"); | 1475 PrintF(file, "]\n"); |
1501 } | 1476 } |
(...skipping 371 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1873 Heap* heap = isolate->heap(); | 1848 Heap* heap = isolate->heap(); |
1874 CALL_HEAP_FUNCTION(isolate, | 1849 CALL_HEAP_FUNCTION(isolate, |
1875 object->AllocateNewStorageFor(heap, representation), | 1850 object->AllocateNewStorageFor(heap, representation), |
1876 Object); | 1851 Object); |
1877 } | 1852 } |
1878 | 1853 |
1879 | 1854 |
1880 static Handle<Map> CopyAddFieldDescriptor(Handle<Map> map, | 1855 static Handle<Map> CopyAddFieldDescriptor(Handle<Map> map, |
1881 Handle<Name> name, | 1856 Handle<Name> name, |
1882 int index, | 1857 int index, |
1883 Handle<HeapType> field_type, | |
1884 PropertyAttributes attributes, | 1858 PropertyAttributes attributes, |
1885 Representation representation, | 1859 Representation representation, |
1886 TransitionFlag flag) { | 1860 TransitionFlag flag) { |
1887 FieldDescriptor new_field_desc(name, index, field_type, | 1861 FieldDescriptor new_field_desc(name, index, attributes, representation); |
1888 attributes, representation); | |
1889 Handle<Map> new_map = Map::CopyAddDescriptor(map, &new_field_desc, flag); | 1862 Handle<Map> new_map = Map::CopyAddDescriptor(map, &new_field_desc, flag); |
1890 int unused_property_fields = map->unused_property_fields() - 1; | 1863 int unused_property_fields = map->unused_property_fields() - 1; |
1891 if (unused_property_fields < 0) { | 1864 if (unused_property_fields < 0) { |
1892 unused_property_fields += JSObject::kFieldsAdded; | 1865 unused_property_fields += JSObject::kFieldsAdded; |
1893 } | 1866 } |
1894 new_map->set_unused_property_fields(unused_property_fields); | 1867 new_map->set_unused_property_fields(unused_property_fields); |
1895 return new_map; | 1868 return new_map; |
1896 } | 1869 } |
1897 | 1870 |
1898 | 1871 |
(...skipping 16 matching lines...) Expand all Loading... |
1915 if (!name->IsCacheable(isolate) || | 1888 if (!name->IsCacheable(isolate) || |
1916 object->TooManyFastProperties(store_mode)) { | 1889 object->TooManyFastProperties(store_mode)) { |
1917 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0); | 1890 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0); |
1918 AddSlowProperty(object, name, value, attributes); | 1891 AddSlowProperty(object, name, value, attributes); |
1919 return; | 1892 return; |
1920 } | 1893 } |
1921 | 1894 |
1922 // Compute the new index for new field. | 1895 // Compute the new index for new field. |
1923 int index = object->map()->NextFreePropertyIndex(); | 1896 int index = object->map()->NextFreePropertyIndex(); |
1924 | 1897 |
1925 // Compute the optimal representation for the new field. | 1898 // Allocate new instance descriptors with (name, index) added |
1926 if (object->IsJSContextExtensionObject()) value_type = FORCE_TAGGED; | 1899 if (object->IsJSContextExtensionObject()) value_type = FORCE_TAGGED; |
1927 Representation representation = value->OptimalRepresentation(value_type); | 1900 Representation representation = value->OptimalRepresentation(value_type); |
1928 | |
1929 Handle<Map> new_map = CopyAddFieldDescriptor( | 1901 Handle<Map> new_map = CopyAddFieldDescriptor( |
1930 handle(object->map()), name, index, | 1902 handle(object->map()), name, index, attributes, representation, flag); |
1931 value->OptimalType(isolate, representation), | |
1932 attributes, representation, flag); | |
1933 | 1903 |
1934 JSObject::MigrateToMap(object, new_map); | 1904 JSObject::MigrateToMap(object, new_map); |
1935 | 1905 |
1936 if (representation.IsDouble()) { | 1906 if (representation.IsDouble()) { |
1937 // Nothing more to be done. | 1907 // Nothing more to be done. |
1938 if (value->IsUninitialized()) return; | 1908 if (value->IsUninitialized()) return; |
1939 HeapNumber* box = HeapNumber::cast(object->RawFastPropertyAt(index)); | 1909 HeapNumber* box = HeapNumber::cast(object->RawFastPropertyAt(index)); |
1940 box->set_value(value->Number()); | 1910 box->set_value(value->Number()); |
1941 } else { | 1911 } else { |
1942 object->FastPropertyAtPut(index, *value); | 1912 object->FastPropertyAtPut(index, *value); |
(...skipping 425 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2368 // fresly allocated page or on an already swept page. Hence, the sweeper | 2338 // fresly allocated page or on an already swept page. Hence, the sweeper |
2369 // thread can not get confused with the filler creation. No synchronization | 2339 // thread can not get confused with the filler creation. No synchronization |
2370 // needed. | 2340 // needed. |
2371 object->set_map(*new_map); | 2341 object->set_map(*new_map); |
2372 } | 2342 } |
2373 | 2343 |
2374 | 2344 |
2375 void JSObject::GeneralizeFieldRepresentation(Handle<JSObject> object, | 2345 void JSObject::GeneralizeFieldRepresentation(Handle<JSObject> object, |
2376 int modify_index, | 2346 int modify_index, |
2377 Representation new_representation, | 2347 Representation new_representation, |
2378 Handle<HeapType> new_field_type, | |
2379 StoreMode store_mode) { | 2348 StoreMode store_mode) { |
2380 Handle<Map> new_map = Map::GeneralizeRepresentation( | 2349 Handle<Map> new_map = Map::GeneralizeRepresentation( |
2381 handle(object->map()), modify_index, new_representation, | 2350 handle(object->map()), modify_index, new_representation, store_mode); |
2382 new_field_type, store_mode); | |
2383 if (object->map() == *new_map) return; | 2351 if (object->map() == *new_map) return; |
2384 return MigrateToMap(object, new_map); | 2352 return MigrateToMap(object, new_map); |
2385 } | 2353 } |
2386 | 2354 |
2387 | 2355 |
2388 int Map::NumberOfFields() { | 2356 int Map::NumberOfFields() { |
2389 DescriptorArray* descriptors = instance_descriptors(); | 2357 DescriptorArray* descriptors = instance_descriptors(); |
2390 int result = 0; | 2358 int result = 0; |
2391 for (int i = 0; i < NumberOfOwnDescriptors(); i++) { | 2359 for (int i = 0; i < NumberOfOwnDescriptors(); i++) { |
2392 if (descriptors->GetDetails(i).type() == FIELD) result++; | 2360 if (descriptors->GetDetails(i).type() == FIELD) result++; |
2393 } | 2361 } |
2394 return result; | 2362 return result; |
2395 } | 2363 } |
2396 | 2364 |
2397 | 2365 |
2398 Handle<Map> Map::CopyGeneralizeAllRepresentations(Handle<Map> map, | 2366 Handle<Map> Map::CopyGeneralizeAllRepresentations(Handle<Map> map, |
2399 int modify_index, | 2367 int modify_index, |
2400 StoreMode store_mode, | 2368 StoreMode store_mode, |
2401 PropertyAttributes attributes, | 2369 PropertyAttributes attributes, |
2402 const char* reason) { | 2370 const char* reason) { |
2403 Isolate* isolate = map->GetIsolate(); | |
2404 Handle<Map> new_map = Copy(map); | 2371 Handle<Map> new_map = Copy(map); |
2405 | 2372 |
2406 DescriptorArray* descriptors = new_map->instance_descriptors(); | 2373 DescriptorArray* descriptors = new_map->instance_descriptors(); |
2407 int length = descriptors->number_of_descriptors(); | 2374 descriptors->InitializeRepresentations(Representation::Tagged()); |
2408 for (int i = 0; i < length; i++) { | |
2409 descriptors->SetRepresentation(i, Representation::Tagged()); | |
2410 if (descriptors->GetDetails(i).type() == FIELD) { | |
2411 descriptors->SetValue(i, HeapType::Any()); | |
2412 } | |
2413 } | |
2414 | 2375 |
2415 // Unless the instance is being migrated, ensure that modify_index is a field. | 2376 // Unless the instance is being migrated, ensure that modify_index is a field. |
2416 PropertyDetails details = descriptors->GetDetails(modify_index); | 2377 PropertyDetails details = descriptors->GetDetails(modify_index); |
2417 if (store_mode == FORCE_FIELD && details.type() != FIELD) { | 2378 if (store_mode == FORCE_FIELD && details.type() != FIELD) { |
2418 FieldDescriptor d(handle(descriptors->GetKey(modify_index), isolate), | 2379 FieldDescriptor d(handle(descriptors->GetKey(modify_index), |
| 2380 map->GetIsolate()), |
2419 new_map->NumberOfFields(), | 2381 new_map->NumberOfFields(), |
2420 attributes, | 2382 attributes, |
2421 Representation::Tagged()); | 2383 Representation::Tagged()); |
2422 descriptors->Replace(modify_index, &d); | 2384 descriptors->Replace(modify_index, &d); |
2423 int unused_property_fields = new_map->unused_property_fields() - 1; | 2385 int unused_property_fields = new_map->unused_property_fields() - 1; |
2424 if (unused_property_fields < 0) { | 2386 if (unused_property_fields < 0) { |
2425 unused_property_fields += JSObject::kFieldsAdded; | 2387 unused_property_fields += JSObject::kFieldsAdded; |
2426 } | 2388 } |
2427 new_map->set_unused_property_fields(unused_property_fields); | 2389 new_map->set_unused_property_fields(unused_property_fields); |
2428 } | 2390 } |
2429 | 2391 |
2430 if (FLAG_trace_generalization) { | 2392 if (FLAG_trace_generalization) { |
2431 HeapType* field_type = (details.type() == FIELD) | |
2432 ? map->instance_descriptors()->GetFieldType(modify_index) | |
2433 : NULL; | |
2434 map->PrintGeneralization(stdout, reason, modify_index, | 2393 map->PrintGeneralization(stdout, reason, modify_index, |
2435 new_map->NumberOfOwnDescriptors(), | 2394 new_map->NumberOfOwnDescriptors(), |
2436 new_map->NumberOfOwnDescriptors(), | 2395 new_map->NumberOfOwnDescriptors(), |
2437 details.type() == CONSTANT && store_mode == FORCE_FIELD, | 2396 details.type() == CONSTANT && store_mode == FORCE_FIELD, |
2438 details.representation(), Representation::Tagged(), | 2397 Representation::Tagged(), Representation::Tagged()); |
2439 field_type, HeapType::Any()); | |
2440 } | 2398 } |
2441 return new_map; | 2399 return new_map; |
2442 } | 2400 } |
2443 | 2401 |
2444 | 2402 |
2445 void Map::DeprecateTransitionTree() { | 2403 void Map::DeprecateTransitionTree() { |
2446 if (is_deprecated()) return; | 2404 if (is_deprecated()) return; |
2447 if (HasTransitionArray()) { | 2405 if (HasTransitionArray()) { |
2448 TransitionArray* transitions = this->transitions(); | 2406 TransitionArray* transitions = this->transitions(); |
2449 for (int i = 0; i < transitions->number_of_transitions(); i++) { | 2407 for (int i = 0; i < transitions->number_of_transitions(); i++) { |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2494 if (back->IsUndefined()) return result; | 2452 if (back->IsUndefined()) return result; |
2495 result = Map::cast(back); | 2453 result = Map::cast(back); |
2496 } | 2454 } |
2497 } | 2455 } |
2498 | 2456 |
2499 | 2457 |
2500 // Returns NULL if the updated map is incompatible. | 2458 // Returns NULL if the updated map is incompatible. |
2501 Map* Map::FindUpdatedMap(int verbatim, | 2459 Map* Map::FindUpdatedMap(int verbatim, |
2502 int length, | 2460 int length, |
2503 DescriptorArray* descriptors) { | 2461 DescriptorArray* descriptors) { |
2504 DisallowHeapAllocation no_allocation; | |
2505 | |
2506 // This can only be called on roots of transition trees. | 2462 // This can only be called on roots of transition trees. |
2507 ASSERT(GetBackPointer()->IsUndefined()); | 2463 ASSERT(GetBackPointer()->IsUndefined()); |
2508 | 2464 |
2509 Map* current = this; | 2465 Map* current = this; |
2510 | 2466 |
2511 for (int i = verbatim; i < length; i++) { | 2467 for (int i = verbatim; i < length; i++) { |
2512 if (!current->HasTransitionArray()) break; | 2468 if (!current->HasTransitionArray()) break; |
2513 Name* name = descriptors->GetKey(i); | 2469 Name* name = descriptors->GetKey(i); |
2514 TransitionArray* transitions = current->transitions(); | 2470 TransitionArray* transitions = current->transitions(); |
2515 int transition = transitions->Search(name); | 2471 int transition = transitions->Search(name); |
(...skipping 14 matching lines...) Expand all Loading... |
2530 } | 2486 } |
2531 } | 2487 } |
2532 | 2488 |
2533 return current; | 2489 return current; |
2534 } | 2490 } |
2535 | 2491 |
2536 | 2492 |
2537 Map* Map::FindLastMatchMap(int verbatim, | 2493 Map* Map::FindLastMatchMap(int verbatim, |
2538 int length, | 2494 int length, |
2539 DescriptorArray* descriptors) { | 2495 DescriptorArray* descriptors) { |
2540 DisallowHeapAllocation no_allocation; | |
2541 | |
2542 // This can only be called on roots of transition trees. | 2496 // This can only be called on roots of transition trees. |
2543 ASSERT(GetBackPointer()->IsUndefined()); | 2497 ASSERT(GetBackPointer()->IsUndefined()); |
2544 | 2498 |
2545 Map* current = this; | 2499 Map* current = this; |
2546 | 2500 |
2547 for (int i = verbatim; i < length; i++) { | 2501 for (int i = verbatim; i < length; i++) { |
2548 if (!current->HasTransitionArray()) break; | 2502 if (!current->HasTransitionArray()) break; |
2549 Name* name = descriptors->GetKey(i); | 2503 Name* name = descriptors->GetKey(i); |
2550 TransitionArray* transitions = current->transitions(); | 2504 TransitionArray* transitions = current->transitions(); |
2551 int transition = transitions->Search(name); | 2505 int transition = transitions->Search(name); |
2552 if (transition == TransitionArray::kNotFound) break; | 2506 if (transition == TransitionArray::kNotFound) break; |
2553 | 2507 |
2554 Map* next = transitions->GetTarget(transition); | 2508 Map* next = transitions->GetTarget(transition); |
2555 DescriptorArray* next_descriptors = next->instance_descriptors(); | 2509 DescriptorArray* next_descriptors = next->instance_descriptors(); |
2556 | 2510 |
| 2511 if (next_descriptors->GetValue(i) != descriptors->GetValue(i)) break; |
| 2512 |
2557 PropertyDetails details = descriptors->GetDetails(i); | 2513 PropertyDetails details = descriptors->GetDetails(i); |
2558 PropertyDetails next_details = next_descriptors->GetDetails(i); | 2514 PropertyDetails next_details = next_descriptors->GetDetails(i); |
2559 if (details.type() != next_details.type()) break; | 2515 if (details.type() != next_details.type()) break; |
2560 if (details.attributes() != next_details.attributes()) break; | 2516 if (details.attributes() != next_details.attributes()) break; |
2561 if (!details.representation().Equals(next_details.representation())) break; | 2517 if (!details.representation().Equals(next_details.representation())) break; |
2562 if (next_details.type() == FIELD) { | |
2563 if (!descriptors->GetFieldType(i)->NowIs( | |
2564 next_descriptors->GetFieldType(i))) break; | |
2565 } else { | |
2566 if (descriptors->GetValue(i) != next_descriptors->GetValue(i)) break; | |
2567 } | |
2568 | 2518 |
2569 current = next; | 2519 current = next; |
2570 } | 2520 } |
2571 return current; | 2521 return current; |
2572 } | 2522 } |
2573 | 2523 |
2574 | 2524 |
2575 Map* Map::FindFieldOwner(int descriptor) { | |
2576 DisallowHeapAllocation no_allocation; | |
2577 ASSERT_EQ(FIELD, instance_descriptors()->GetDetails(descriptor).type()); | |
2578 Map* result = this; | |
2579 while (true) { | |
2580 Object* back = result->GetBackPointer(); | |
2581 if (back->IsUndefined()) break; | |
2582 Map* parent = Map::cast(back); | |
2583 if (parent->NumberOfOwnDescriptors() <= descriptor) break; | |
2584 result = parent; | |
2585 } | |
2586 return result; | |
2587 } | |
2588 | |
2589 | |
2590 void Map::UpdateDescriptor(int descriptor_number, Descriptor* desc) { | |
2591 DisallowHeapAllocation no_allocation; | |
2592 if (HasTransitionArray()) { | |
2593 TransitionArray* transitions = this->transitions(); | |
2594 for (int i = 0; i < transitions->number_of_transitions(); ++i) { | |
2595 transitions->GetTarget(i)->UpdateDescriptor(descriptor_number, desc); | |
2596 } | |
2597 } | |
2598 instance_descriptors()->Replace(descriptor_number, desc);; | |
2599 } | |
2600 | |
2601 | |
2602 // static | |
2603 Handle<HeapType> Map::GeneralizeFieldType(Handle<HeapType> old_field_type, | |
2604 Handle<HeapType> new_field_type, | |
2605 Isolate* isolate) { | |
2606 if (new_field_type->NowIs(old_field_type)) return old_field_type; | |
2607 if (old_field_type->NowIs(new_field_type)) return new_field_type; | |
2608 return HeapType::Any(isolate); | |
2609 } | |
2610 | |
2611 | |
2612 // static | |
2613 void Map::GeneralizeFieldType(Handle<Map> map, | |
2614 int modify_index, | |
2615 Handle<HeapType> new_field_type) { | |
2616 Isolate* isolate = map->GetIsolate(); | |
2617 Handle<Map> field_owner(map->FindFieldOwner(modify_index), isolate); | |
2618 Handle<DescriptorArray> descriptors( | |
2619 field_owner->instance_descriptors(), isolate); | |
2620 | |
2621 // Check if we actually need to generalize the field type at all. | |
2622 Handle<HeapType> old_field_type( | |
2623 descriptors->GetFieldType(modify_index), isolate); | |
2624 if (new_field_type->NowIs(old_field_type)) { | |
2625 ASSERT(Map::GeneralizeFieldType(old_field_type, | |
2626 new_field_type, | |
2627 isolate)->NowIs(old_field_type)); | |
2628 return; | |
2629 } | |
2630 | |
2631 // Determine the generalized new field type. | |
2632 new_field_type = Map::GeneralizeFieldType( | |
2633 old_field_type, new_field_type, isolate); | |
2634 | |
2635 PropertyDetails details = descriptors->GetDetails(modify_index); | |
2636 FieldDescriptor d(handle(descriptors->GetKey(modify_index), isolate), | |
2637 descriptors->GetFieldIndex(modify_index), | |
2638 new_field_type, | |
2639 details.attributes(), | |
2640 details.representation()); | |
2641 field_owner->UpdateDescriptor(modify_index, &d); | |
2642 field_owner->dependent_code()->DeoptimizeDependentCodeGroup( | |
2643 isolate, DependentCode::kFieldTypeGroup); | |
2644 | |
2645 if (FLAG_trace_generalization) { | |
2646 map->PrintGeneralization( | |
2647 stdout, "field type generalization", | |
2648 modify_index, map->NumberOfOwnDescriptors(), | |
2649 map->NumberOfOwnDescriptors(), false, | |
2650 details.representation(), details.representation(), | |
2651 *old_field_type, *new_field_type); | |
2652 } | |
2653 } | |
2654 | |
2655 | |
2656 // Generalize the representation of the descriptor at |modify_index|. | 2525 // Generalize the representation of the descriptor at |modify_index|. |
2657 // This method rewrites the transition tree to reflect the new change. To avoid | 2526 // This method rewrites the transition tree to reflect the new change. To avoid |
2658 // high degrees over polymorphism, and to stabilize quickly, on every rewrite | 2527 // high degrees over polymorphism, and to stabilize quickly, on every rewrite |
2659 // the new type is deduced by merging the current type with any potential new | 2528 // the new type is deduced by merging the current type with any potential new |
2660 // (partial) version of the type in the transition tree. | 2529 // (partial) version of the type in the transition tree. |
2661 // To do this, on each rewrite: | 2530 // To do this, on each rewrite: |
2662 // - Search the root of the transition tree using FindRootMap. | 2531 // - Search the root of the transition tree using FindRootMap. |
2663 // - Find |updated|, the newest matching version of this map using | 2532 // - Find |updated|, the newest matching version of this map using |
2664 // FindUpdatedMap. This uses the keys in the own map's descriptor array to | 2533 // FindUpdatedMap. This uses the keys in the own map's descriptor array to |
2665 // walk the transition tree. | 2534 // walk the transition tree. |
2666 // - Merge/generalize the descriptor array of the current map and |updated|. | 2535 // - Merge/generalize the descriptor array of the current map and |updated|. |
2667 // - Generalize the |modify_index| descriptor using |new_representation|. | 2536 // - Generalize the |modify_index| descriptor using |new_representation|. |
2668 // - Walk the tree again starting from the root towards |updated|. Stop at | 2537 // - Walk the tree again starting from the root towards |updated|. Stop at |
2669 // |split_map|, the first map who's descriptor array does not match the merged | 2538 // |split_map|, the first map who's descriptor array does not match the merged |
2670 // descriptor array. | 2539 // descriptor array. |
2671 // - If |updated| == |split_map|, |updated| is in the expected state. Return it. | 2540 // - If |updated| == |split_map|, |updated| is in the expected state. Return it. |
2672 // - Otherwise, invalidate the outdated transition target from |updated|, and | 2541 // - Otherwise, invalidate the outdated transition target from |updated|, and |
2673 // replace its transition tree with a new branch for the updated descriptors. | 2542 // replace its transition tree with a new branch for the updated descriptors. |
2674 Handle<Map> Map::GeneralizeRepresentation(Handle<Map> old_map, | 2543 Handle<Map> Map::GeneralizeRepresentation(Handle<Map> old_map, |
2675 int modify_index, | 2544 int modify_index, |
2676 Representation new_representation, | 2545 Representation new_representation, |
2677 Handle<HeapType> new_field_type, | |
2678 StoreMode store_mode) { | 2546 StoreMode store_mode) { |
2679 Handle<DescriptorArray> old_descriptors(old_map->instance_descriptors()); | 2547 Handle<DescriptorArray> old_descriptors(old_map->instance_descriptors()); |
2680 PropertyDetails old_details = old_descriptors->GetDetails(modify_index); | 2548 PropertyDetails old_details = old_descriptors->GetDetails(modify_index); |
2681 Representation old_representation = old_details.representation(); | 2549 Representation old_representation = old_details.representation(); |
2682 | 2550 |
2683 // It's fine to transition from None to anything but double without any | 2551 // It's fine to transition from None to anything but double without any |
2684 // modification to the object, because the default uninitialized value for | 2552 // modification to the object, because the default uninitialized value for |
2685 // representation None can be overwritten by both smi and tagged values. | 2553 // representation None can be overwritten by both smi and tagged values. |
2686 // Doubles, however, would require a box allocation. | 2554 // Doubles, however, would require a box allocation. |
2687 if (old_representation.IsNone() && | 2555 if (old_representation.IsNone() && |
2688 !new_representation.IsNone() && | 2556 !new_representation.IsNone() && |
2689 !new_representation.IsDouble()) { | 2557 !new_representation.IsDouble()) { |
2690 ASSERT(old_details.type() == FIELD); | |
2691 ASSERT(old_descriptors->GetFieldType(modify_index)->NowIs( | |
2692 HeapType::None())); | |
2693 if (FLAG_trace_generalization) { | |
2694 old_map->PrintGeneralization( | |
2695 stdout, "uninitialized field", | |
2696 modify_index, old_map->NumberOfOwnDescriptors(), | |
2697 old_map->NumberOfOwnDescriptors(), false, | |
2698 old_representation, new_representation, | |
2699 old_descriptors->GetFieldType(modify_index), *new_field_type); | |
2700 } | |
2701 old_descriptors->SetRepresentation(modify_index, new_representation); | 2558 old_descriptors->SetRepresentation(modify_index, new_representation); |
2702 old_descriptors->SetValue(modify_index, *new_field_type); | |
2703 return old_map; | 2559 return old_map; |
2704 } | 2560 } |
2705 | 2561 |
2706 if (new_representation.Equals(old_representation) && | 2562 int descriptors = old_map->NumberOfOwnDescriptors(); |
2707 old_details.type() == FIELD) { | |
2708 Map::GeneralizeFieldType(old_map, modify_index, new_field_type); | |
2709 return old_map; | |
2710 } | |
2711 | |
2712 Handle<Map> root_map(old_map->FindRootMap()); | 2563 Handle<Map> root_map(old_map->FindRootMap()); |
2713 | 2564 |
2714 // Check the state of the root map. | 2565 // Check the state of the root map. |
2715 if (!old_map->EquivalentToForTransition(*root_map)) { | 2566 if (!old_map->EquivalentToForTransition(*root_map)) { |
2716 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, | 2567 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, |
2717 old_details.attributes(), "not equivalent"); | 2568 old_details.attributes(), "not equivalent"); |
2718 } | 2569 } |
2719 | 2570 |
2720 int verbatim = root_map->NumberOfOwnDescriptors(); | 2571 int verbatim = root_map->NumberOfOwnDescriptors(); |
2721 | 2572 |
2722 if (store_mode != ALLOW_AS_CONSTANT && modify_index < verbatim) { | 2573 if (store_mode != ALLOW_AS_CONSTANT && modify_index < verbatim) { |
2723 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, | 2574 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, |
2724 old_details.attributes(), "root modification"); | 2575 old_details.attributes(), "root modification"); |
2725 } | 2576 } |
2726 | 2577 |
2727 int descriptors = old_map->NumberOfOwnDescriptors(); | |
2728 Map* raw_updated = root_map->FindUpdatedMap( | 2578 Map* raw_updated = root_map->FindUpdatedMap( |
2729 verbatim, descriptors, *old_descriptors); | 2579 verbatim, descriptors, *old_descriptors); |
2730 if (raw_updated == NULL) { | 2580 if (raw_updated == NULL) { |
2731 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, | 2581 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, |
2732 old_details.attributes(), "incompatible"); | 2582 old_details.attributes(), "incompatible"); |
2733 } | 2583 } |
2734 | 2584 |
2735 Handle<Map> updated(raw_updated); | 2585 Handle<Map> updated(raw_updated); |
2736 Handle<DescriptorArray> updated_descriptors(updated->instance_descriptors()); | 2586 Handle<DescriptorArray> updated_descriptors(updated->instance_descriptors()); |
2737 | 2587 |
2738 int valid = updated->NumberOfOwnDescriptors(); | 2588 int valid = updated->NumberOfOwnDescriptors(); |
2739 | 2589 |
2740 // Directly change the map if the target map is more general. Ensure that the | 2590 // Directly change the map if the target map is more general. Ensure that the |
2741 // target type of the modify_index is a FIELD, unless we are migrating. | 2591 // target type of the modify_index is a FIELD, unless we are migrating. |
2742 if (updated_descriptors->IsMoreGeneralThan( | 2592 if (updated_descriptors->IsMoreGeneralThan( |
2743 verbatim, valid, descriptors, *old_descriptors) && | 2593 verbatim, valid, descriptors, *old_descriptors) && |
2744 (store_mode == ALLOW_AS_CONSTANT || | 2594 (store_mode == ALLOW_AS_CONSTANT || |
2745 updated_descriptors->GetDetails(modify_index).type() == FIELD)) { | 2595 updated_descriptors->GetDetails(modify_index).type() == FIELD)) { |
2746 Representation updated_representation = | 2596 Representation updated_representation = |
2747 updated_descriptors->GetDetails(modify_index).representation(); | 2597 updated_descriptors->GetDetails(modify_index).representation(); |
2748 if (new_representation.fits_into(updated_representation)) return updated; | 2598 if (new_representation.fits_into(updated_representation)) return updated; |
2749 } | 2599 } |
2750 | 2600 |
2751 Handle<DescriptorArray> new_descriptors = DescriptorArray::Merge( | 2601 Handle<DescriptorArray> new_descriptors = DescriptorArray::Merge( |
2752 updated, verbatim, valid, descriptors, modify_index, | 2602 updated, verbatim, valid, descriptors, modify_index, |
2753 store_mode, old_map); | 2603 store_mode, old_map); |
2754 ASSERT(store_mode == ALLOW_AS_CONSTANT || | 2604 ASSERT(store_mode == ALLOW_AS_CONSTANT || |
2755 new_descriptors->GetDetails(modify_index).type() == FIELD); | 2605 new_descriptors->GetDetails(modify_index).type() == FIELD); |
2756 | 2606 |
2757 Isolate* isolate = new_descriptors->GetIsolate(); | |
2758 old_representation = | 2607 old_representation = |
2759 new_descriptors->GetDetails(modify_index).representation(); | 2608 new_descriptors->GetDetails(modify_index).representation(); |
2760 Representation updated_representation = | 2609 Representation updated_representation = |
2761 new_representation.generalize(old_representation); | 2610 new_representation.generalize(old_representation); |
2762 if (!updated_representation.Equals(old_representation)) { | 2611 if (!updated_representation.Equals(old_representation)) { |
2763 new_descriptors->SetRepresentation(modify_index, updated_representation); | 2612 new_descriptors->SetRepresentation(modify_index, updated_representation); |
2764 } | 2613 } |
2765 if (new_descriptors->GetDetails(modify_index).type() == FIELD) { | |
2766 Handle<HeapType> field_type( | |
2767 new_descriptors->GetFieldType(modify_index), isolate); | |
2768 new_field_type = Map::GeneralizeFieldType( | |
2769 field_type, new_field_type, isolate); | |
2770 new_descriptors->SetValue(modify_index, *new_field_type); | |
2771 } | |
2772 | 2614 |
2773 Handle<Map> split_map(root_map->FindLastMatchMap( | 2615 Handle<Map> split_map(root_map->FindLastMatchMap( |
2774 verbatim, descriptors, *new_descriptors)); | 2616 verbatim, descriptors, *new_descriptors)); |
2775 | 2617 |
2776 int split_descriptors = split_map->NumberOfOwnDescriptors(); | 2618 int split_descriptors = split_map->NumberOfOwnDescriptors(); |
2777 // This is shadowed by |updated_descriptors| being more general than | 2619 // This is shadowed by |updated_descriptors| being more general than |
2778 // |old_descriptors|. | 2620 // |old_descriptors|. |
2779 ASSERT(descriptors != split_descriptors); | 2621 ASSERT(descriptors != split_descriptors); |
2780 | 2622 |
2781 int descriptor = split_descriptors; | 2623 int descriptor = split_descriptors; |
2782 split_map->DeprecateTarget( | 2624 split_map->DeprecateTarget( |
2783 old_descriptors->GetKey(descriptor), *new_descriptors); | 2625 old_descriptors->GetKey(descriptor), *new_descriptors); |
2784 | 2626 |
2785 if (FLAG_trace_generalization) { | 2627 if (FLAG_trace_generalization) { |
2786 PropertyDetails old_details = old_descriptors->GetDetails(modify_index); | |
2787 PropertyDetails new_details = new_descriptors->GetDetails(modify_index); | |
2788 Handle<HeapType> old_field_type = (old_details.type() == FIELD) | |
2789 ? handle(old_descriptors->GetFieldType(modify_index), isolate) | |
2790 : HeapType::Constant(handle(old_descriptors->GetValue(modify_index), | |
2791 isolate), isolate); | |
2792 Handle<HeapType> new_field_type = (new_details.type() == FIELD) | |
2793 ? handle(new_descriptors->GetFieldType(modify_index), isolate) | |
2794 : HeapType::Constant(handle(new_descriptors->GetValue(modify_index), | |
2795 isolate), isolate); | |
2796 old_map->PrintGeneralization( | 2628 old_map->PrintGeneralization( |
2797 stdout, "", modify_index, descriptor, descriptors, | 2629 stdout, "", modify_index, descriptor, descriptors, |
2798 old_details.type() == CONSTANT && store_mode == FORCE_FIELD, | 2630 old_descriptors->GetDetails(modify_index).type() == CONSTANT && |
2799 old_details.representation(), new_details.representation(), | 2631 store_mode == FORCE_FIELD, |
2800 *old_field_type, *new_field_type); | 2632 old_representation, updated_representation); |
2801 } | 2633 } |
2802 | 2634 |
2803 // Add missing transitions. | 2635 // Add missing transitions. |
2804 Handle<Map> new_map = split_map; | 2636 Handle<Map> new_map = split_map; |
2805 for (; descriptor < descriptors; descriptor++) { | 2637 for (; descriptor < descriptors; descriptor++) { |
2806 new_map = Map::CopyInstallDescriptors(new_map, descriptor, new_descriptors); | 2638 new_map = Map::CopyInstallDescriptors(new_map, descriptor, new_descriptors); |
2807 } | 2639 } |
2808 | 2640 |
2809 new_map->set_owns_descriptors(true); | 2641 new_map->set_owns_descriptors(true); |
2810 return new_map; | 2642 return new_map; |
2811 } | 2643 } |
2812 | 2644 |
2813 | 2645 |
2814 // Generalize the representation of all FIELD descriptors. | 2646 // Generalize the representation of all FIELD descriptors. |
2815 Handle<Map> Map::GeneralizeAllFieldRepresentations( | 2647 Handle<Map> Map::GeneralizeAllFieldRepresentations( |
2816 Handle<Map> map) { | 2648 Handle<Map> map, |
| 2649 Representation new_representation) { |
2817 Handle<DescriptorArray> descriptors(map->instance_descriptors()); | 2650 Handle<DescriptorArray> descriptors(map->instance_descriptors()); |
2818 for (int i = 0; i < map->NumberOfOwnDescriptors(); ++i) { | 2651 for (int i = 0; i < map->NumberOfOwnDescriptors(); i++) { |
2819 if (descriptors->GetDetails(i).type() == FIELD) { | 2652 PropertyDetails details = descriptors->GetDetails(i); |
2820 map = GeneralizeRepresentation(map, i, Representation::Tagged(), | 2653 if (details.type() == FIELD) { |
2821 HeapType::Any(map->GetIsolate()), | 2654 map = GeneralizeRepresentation(map, i, new_representation, FORCE_FIELD); |
2822 FORCE_FIELD); | |
2823 } | 2655 } |
2824 } | 2656 } |
2825 return map; | 2657 return map; |
2826 } | 2658 } |
2827 | 2659 |
2828 | 2660 |
2829 Handle<Map> Map::CurrentMapForDeprecated(Handle<Map> map) { | 2661 Handle<Map> Map::CurrentMapForDeprecated(Handle<Map> map) { |
2830 Handle<Map> proto_map(map); | 2662 Handle<Map> proto_map(map); |
2831 while (proto_map->prototype()->IsJSObject()) { | 2663 while (proto_map->prototype()->IsJSObject()) { |
2832 Handle<JSObject> holder(JSObject::cast(proto_map->prototype())); | 2664 Handle<JSObject> holder(JSObject::cast(proto_map->prototype())); |
(...skipping 1118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3951 JSObject::MigrateToMap(object, map); | 3783 JSObject::MigrateToMap(object, map); |
3952 } | 3784 } |
3953 | 3785 |
3954 | 3786 |
3955 void JSObject::MigrateInstance(Handle<JSObject> object) { | 3787 void JSObject::MigrateInstance(Handle<JSObject> object) { |
3956 // Converting any field to the most specific type will cause the | 3788 // Converting any field to the most specific type will cause the |
3957 // GeneralizeFieldRepresentation algorithm to create the most general existing | 3789 // GeneralizeFieldRepresentation algorithm to create the most general existing |
3958 // transition that matches the object. This achieves what is needed. | 3790 // transition that matches the object. This achieves what is needed. |
3959 Handle<Map> original_map(object->map()); | 3791 Handle<Map> original_map(object->map()); |
3960 GeneralizeFieldRepresentation( | 3792 GeneralizeFieldRepresentation( |
3961 object, 0, Representation::None(), | 3793 object, 0, Representation::None(), ALLOW_AS_CONSTANT); |
3962 HeapType::None(object->GetIsolate()), | |
3963 ALLOW_AS_CONSTANT); | |
3964 object->map()->set_migration_target(true); | 3794 object->map()->set_migration_target(true); |
3965 if (FLAG_trace_migration) { | 3795 if (FLAG_trace_migration) { |
3966 object->PrintInstanceMigration(stdout, *original_map, object->map()); | 3796 object->PrintInstanceMigration(stdout, *original_map, object->map()); |
3967 } | 3797 } |
3968 } | 3798 } |
3969 | 3799 |
3970 | 3800 |
3971 Handle<Object> JSObject::TryMigrateInstance(Handle<JSObject> object) { | 3801 Handle<Object> JSObject::TryMigrateInstance(Handle<JSObject> object) { |
3972 Handle<Map> original_map(object->map()); | 3802 Handle<Map> original_map(object->map()); |
3973 Handle<Map> new_map = Map::CurrentMapForDeprecatedInternal(original_map); | 3803 Handle<Map> new_map = Map::CurrentMapForDeprecatedInternal(original_map); |
3974 if (new_map.is_null()) return Handle<Object>(); | 3804 if (new_map.is_null()) return Handle<Object>(); |
3975 JSObject::MigrateToMap(object, new_map); | 3805 JSObject::MigrateToMap(object, new_map); |
3976 if (FLAG_trace_migration) { | 3806 if (FLAG_trace_migration) { |
3977 object->PrintInstanceMigration(stdout, *original_map, object->map()); | 3807 object->PrintInstanceMigration(stdout, *original_map, object->map()); |
3978 } | 3808 } |
3979 return object; | 3809 return object; |
3980 } | 3810 } |
3981 | 3811 |
3982 | 3812 |
3983 MaybeHandle<Object> JSObject::SetPropertyUsingTransition( | 3813 MaybeHandle<Object> JSObject::SetPropertyUsingTransition( |
3984 Handle<JSObject> object, | 3814 Handle<JSObject> object, |
3985 LookupResult* lookup, | 3815 LookupResult* lookup, |
3986 Handle<Name> name, | 3816 Handle<Name> name, |
3987 Handle<Object> value, | 3817 Handle<Object> value, |
3988 PropertyAttributes attributes) { | 3818 PropertyAttributes attributes) { |
3989 Handle<Map> transition_map(lookup->GetTransitionTarget()); | 3819 Handle<Map> transition_map(lookup->GetTransitionTarget()); |
3990 int descriptor = transition_map->LastAdded(); | 3820 int descriptor = transition_map->LastAdded(); |
3991 | 3821 |
3992 Handle<DescriptorArray> descriptors(transition_map->instance_descriptors()); | 3822 DescriptorArray* descriptors = transition_map->instance_descriptors(); |
3993 PropertyDetails details = descriptors->GetDetails(descriptor); | 3823 PropertyDetails details = descriptors->GetDetails(descriptor); |
3994 | 3824 |
3995 if (details.type() == CALLBACKS || attributes != details.attributes()) { | 3825 if (details.type() == CALLBACKS || attributes != details.attributes()) { |
3996 // AddProperty will either normalize the object, or create a new fast copy | 3826 // AddProperty will either normalize the object, or create a new fast copy |
3997 // of the map. If we get a fast copy of the map, all field representations | 3827 // of the map. If we get a fast copy of the map, all field representations |
3998 // will be tagged since the transition is omitted. | 3828 // will be tagged since the transition is omitted. |
3999 return JSObject::AddProperty( | 3829 return JSObject::AddProperty( |
4000 object, name, value, attributes, SLOPPY, | 3830 object, name, value, attributes, SLOPPY, |
4001 JSReceiver::CERTAINLY_NOT_STORE_FROM_KEYED, | 3831 JSReceiver::CERTAINLY_NOT_STORE_FROM_KEYED, |
4002 JSReceiver::OMIT_EXTENSIBILITY_CHECK, | 3832 JSReceiver::OMIT_EXTENSIBILITY_CHECK, |
4003 JSObject::FORCE_TAGGED, FORCE_FIELD, OMIT_TRANSITION); | 3833 JSObject::FORCE_TAGGED, FORCE_FIELD, OMIT_TRANSITION); |
4004 } | 3834 } |
4005 | 3835 |
4006 // Keep the target CONSTANT if the same value is stored. | 3836 // Keep the target CONSTANT if the same value is stored. |
4007 // TODO(verwaest): Also support keeping the placeholder | 3837 // TODO(verwaest): Also support keeping the placeholder |
4008 // (value->IsUninitialized) as constant. | 3838 // (value->IsUninitialized) as constant. |
4009 if (!lookup->CanHoldValue(value)) { | 3839 if (!lookup->CanHoldValue(value) || |
4010 Representation field_representation = value->OptimalRepresentation(); | 3840 (details.type() == CONSTANT && |
4011 Handle<HeapType> field_type = value->OptimalType( | 3841 descriptors->GetValue(descriptor) != *value)) { |
4012 lookup->isolate(), field_representation); | 3842 transition_map = Map::GeneralizeRepresentation(transition_map, |
4013 transition_map = Map::GeneralizeRepresentation( | 3843 descriptor, value->OptimalRepresentation(), FORCE_FIELD); |
4014 transition_map, descriptor, | |
4015 field_representation, field_type, FORCE_FIELD); | |
4016 } | 3844 } |
4017 | 3845 |
4018 JSObject::MigrateToMap(object, transition_map); | 3846 JSObject::MigrateToMap(object, transition_map); |
4019 | 3847 |
4020 // Reload. | 3848 // Reload. |
4021 descriptors = handle(transition_map->instance_descriptors()); | 3849 descriptors = transition_map->instance_descriptors(); |
4022 details = descriptors->GetDetails(descriptor); | 3850 details = descriptors->GetDetails(descriptor); |
4023 | 3851 |
4024 if (details.type() != FIELD) return value; | 3852 if (details.type() != FIELD) return value; |
4025 | 3853 |
4026 int field_index = descriptors->GetFieldIndex(descriptor); | 3854 int field_index = descriptors->GetFieldIndex(descriptor); |
4027 if (details.representation().IsDouble()) { | 3855 if (details.representation().IsDouble()) { |
4028 // Nothing more to be done. | 3856 // Nothing more to be done. |
4029 if (value->IsUninitialized()) return value; | 3857 if (value->IsUninitialized()) return value; |
4030 HeapNumber* box = HeapNumber::cast(object->RawFastPropertyAt(field_index)); | 3858 HeapNumber* box = HeapNumber::cast(object->RawFastPropertyAt(field_index)); |
4031 box->set_value(value->Number()); | 3859 box->set_value(value->Number()); |
4032 } else { | 3860 } else { |
4033 object->FastPropertyAtPut(field_index, *value); | 3861 object->FastPropertyAtPut(field_index, *value); |
4034 } | 3862 } |
4035 | 3863 |
4036 return value; | 3864 return value; |
4037 } | 3865 } |
4038 | 3866 |
4039 | 3867 |
4040 static void SetPropertyToField(LookupResult* lookup, | 3868 static void SetPropertyToField(LookupResult* lookup, |
4041 Handle<Object> value) { | 3869 Handle<Object> value) { |
4042 Representation representation = lookup->representation(); | 3870 Representation representation = lookup->representation(); |
4043 if (lookup->type() == CONSTANT || !lookup->CanHoldValue(value)) { | 3871 if (!lookup->CanHoldValue(value) || |
4044 Representation field_representation = value->OptimalRepresentation(); | 3872 lookup->type() == CONSTANT) { |
4045 Handle<HeapType> field_type = value->OptimalType( | |
4046 lookup->isolate(), field_representation); | |
4047 JSObject::GeneralizeFieldRepresentation(handle(lookup->holder()), | 3873 JSObject::GeneralizeFieldRepresentation(handle(lookup->holder()), |
4048 lookup->GetDescriptorIndex(), | 3874 lookup->GetDescriptorIndex(), |
4049 field_representation, field_type, | 3875 value->OptimalRepresentation(), |
4050 FORCE_FIELD); | 3876 FORCE_FIELD); |
4051 DescriptorArray* desc = lookup->holder()->map()->instance_descriptors(); | 3877 DescriptorArray* desc = lookup->holder()->map()->instance_descriptors(); |
4052 int descriptor = lookup->GetDescriptorIndex(); | 3878 int descriptor = lookup->GetDescriptorIndex(); |
4053 representation = desc->GetDetails(descriptor).representation(); | 3879 representation = desc->GetDetails(descriptor).representation(); |
4054 } | 3880 } |
4055 | 3881 |
4056 if (representation.IsDouble()) { | 3882 if (representation.IsDouble()) { |
4057 HeapNumber* storage = HeapNumber::cast(lookup->holder()->RawFastPropertyAt( | 3883 HeapNumber* storage = HeapNumber::cast(lookup->holder()->RawFastPropertyAt( |
4058 lookup->GetFieldIndex().field_index())); | 3884 lookup->GetFieldIndex().field_index())); |
4059 storage->set_value(value->Number()); | 3885 storage->set_value(value->Number()); |
(...skipping 15 matching lines...) Expand all Loading... |
4075 } | 3901 } |
4076 | 3902 |
4077 if (!object->HasFastProperties()) { | 3903 if (!object->HasFastProperties()) { |
4078 ReplaceSlowProperty(object, name, value, attributes); | 3904 ReplaceSlowProperty(object, name, value, attributes); |
4079 return; | 3905 return; |
4080 } | 3906 } |
4081 | 3907 |
4082 int descriptor_index = lookup->GetDescriptorIndex(); | 3908 int descriptor_index = lookup->GetDescriptorIndex(); |
4083 if (lookup->GetAttributes() == attributes) { | 3909 if (lookup->GetAttributes() == attributes) { |
4084 JSObject::GeneralizeFieldRepresentation( | 3910 JSObject::GeneralizeFieldRepresentation( |
4085 object, descriptor_index, Representation::Tagged(), | 3911 object, descriptor_index, Representation::Tagged(), FORCE_FIELD); |
4086 HeapType::Any(lookup->isolate()), FORCE_FIELD); | |
4087 } else { | 3912 } else { |
4088 Handle<Map> old_map(object->map()); | 3913 Handle<Map> old_map(object->map()); |
4089 Handle<Map> new_map = Map::CopyGeneralizeAllRepresentations(old_map, | 3914 Handle<Map> new_map = Map::CopyGeneralizeAllRepresentations(old_map, |
4090 descriptor_index, FORCE_FIELD, attributes, "attributes mismatch"); | 3915 descriptor_index, FORCE_FIELD, attributes, "attributes mismatch"); |
4091 JSObject::MigrateToMap(object, new_map); | 3916 JSObject::MigrateToMap(object, new_map); |
4092 } | 3917 } |
4093 | 3918 |
4094 DescriptorArray* descriptors = object->map()->instance_descriptors(); | 3919 DescriptorArray* descriptors = object->map()->instance_descriptors(); |
4095 int index = descriptors->GetDetails(descriptor_index).field_index(); | 3920 int index = descriptors->GetDetails(descriptor_index).field_index(); |
4096 object->FastPropertyAtPut(index, *value); | 3921 object->FastPropertyAtPut(index, *value); |
(...skipping 2967 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7064 | 6889 |
7065 Handle<Map> result = CopyDropDescriptors(map); | 6890 Handle<Map> result = CopyDropDescriptors(map); |
7066 result->InitializeDescriptors(*descriptors); | 6891 result->InitializeDescriptors(*descriptors); |
7067 | 6892 |
7068 if (flag == INSERT_TRANSITION && map->CanHaveMoreTransitions()) { | 6893 if (flag == INSERT_TRANSITION && map->CanHaveMoreTransitions()) { |
7069 Handle<TransitionArray> transitions = TransitionArray::CopyInsert( | 6894 Handle<TransitionArray> transitions = TransitionArray::CopyInsert( |
7070 map, name, result, simple_flag); | 6895 map, name, result, simple_flag); |
7071 map->set_transitions(*transitions); | 6896 map->set_transitions(*transitions); |
7072 result->SetBackPointer(*map); | 6897 result->SetBackPointer(*map); |
7073 } else { | 6898 } else { |
7074 int length = descriptors->number_of_descriptors(); | 6899 descriptors->InitializeRepresentations(Representation::Tagged()); |
7075 for (int i = 0; i < length; i++) { | |
7076 descriptors->SetRepresentation(i, Representation::Tagged()); | |
7077 if (descriptors->GetDetails(i).type() == FIELD) { | |
7078 descriptors->SetValue(i, HeapType::Any()); | |
7079 } | |
7080 } | |
7081 } | 6900 } |
7082 | 6901 |
7083 return result; | 6902 return result; |
7084 } | 6903 } |
7085 | 6904 |
7086 | 6905 |
7087 // Since this method is used to rewrite an existing transition tree, it can | 6906 // Since this method is used to rewrite an existing transition tree, it can |
7088 // always insert transitions without checking. | 6907 // always insert transitions without checking. |
7089 Handle<Map> Map::CopyInstallDescriptors(Handle<Map> map, | 6908 Handle<Map> Map::CopyInstallDescriptors(Handle<Map> map, |
7090 int new_descriptor, | 6909 int new_descriptor, |
(...skipping 1168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8259 | 8078 |
8260 // |verbatim| -> |valid| | 8079 // |verbatim| -> |valid| |
8261 for (; descriptor < valid; descriptor++) { | 8080 for (; descriptor < valid; descriptor++) { |
8262 PropertyDetails left_details = left->GetDetails(descriptor); | 8081 PropertyDetails left_details = left->GetDetails(descriptor); |
8263 PropertyDetails right_details = right->GetDetails(descriptor); | 8082 PropertyDetails right_details = right->GetDetails(descriptor); |
8264 if (left_details.type() == FIELD || right_details.type() == FIELD || | 8083 if (left_details.type() == FIELD || right_details.type() == FIELD || |
8265 (store_mode == FORCE_FIELD && descriptor == modify_index) || | 8084 (store_mode == FORCE_FIELD && descriptor == modify_index) || |
8266 (left_details.type() == CONSTANT && | 8085 (left_details.type() == CONSTANT && |
8267 right_details.type() == CONSTANT && | 8086 right_details.type() == CONSTANT && |
8268 left->GetValue(descriptor) != right->GetValue(descriptor))) { | 8087 left->GetValue(descriptor) != right->GetValue(descriptor))) { |
8269 ASSERT(left_details.type() == CONSTANT || left_details.type() == FIELD); | |
8270 ASSERT(right_details.type() == CONSTANT || right_details.type() == FIELD); | |
8271 Representation representation = left_details.representation().generalize( | 8088 Representation representation = left_details.representation().generalize( |
8272 right_details.representation()); | 8089 right_details.representation()); |
8273 Handle<HeapType> left_type = (left_details.type() == FIELD) | 8090 FieldDescriptor d(handle(left->GetKey(descriptor)), |
8274 ? handle(left->GetFieldType(descriptor), isolate) | |
8275 : left->GetValue(descriptor)->OptimalType(isolate, representation); | |
8276 Handle<HeapType> right_type = (right_details.type() == FIELD) | |
8277 ? handle(right->GetFieldType(descriptor), isolate) | |
8278 : right->GetValue(descriptor)->OptimalType(isolate, representation); | |
8279 Handle<HeapType> field_type = Map::GeneralizeFieldType( | |
8280 left_type, right_type, isolate); | |
8281 FieldDescriptor d(handle(left->GetKey(descriptor), isolate), | |
8282 current_offset++, | 8091 current_offset++, |
8283 field_type, | |
8284 right_details.attributes(), | 8092 right_details.attributes(), |
8285 representation); | 8093 representation); |
8286 result->Set(descriptor, &d); | 8094 result->Set(descriptor, &d); |
8287 } else { | 8095 } else { |
8288 Descriptor d(handle(right->GetKey(descriptor), isolate), | 8096 Descriptor d(handle(right->GetKey(descriptor)), |
8289 handle(right->GetValue(descriptor), isolate), | 8097 handle(right->GetValue(descriptor), right->GetIsolate()), |
8290 right_details); | 8098 right_details); |
8291 result->Set(descriptor, &d); | 8099 result->Set(descriptor, &d); |
8292 } | 8100 } |
8293 } | 8101 } |
8294 | 8102 |
8295 // |valid| -> |new_size| | 8103 // |valid| -> |new_size| |
8296 for (; descriptor < new_size; descriptor++) { | 8104 for (; descriptor < new_size; descriptor++) { |
8297 PropertyDetails right_details = right->GetDetails(descriptor); | 8105 PropertyDetails right_details = right->GetDetails(descriptor); |
8298 if (right_details.type() == FIELD) { | 8106 if (right_details.type() == FIELD || |
8299 FieldDescriptor d(handle(right->GetKey(descriptor), isolate), | 8107 (store_mode == FORCE_FIELD && descriptor == modify_index)) { |
| 8108 FieldDescriptor d(handle(right->GetKey(descriptor)), |
8300 current_offset++, | 8109 current_offset++, |
8301 handle(right->GetFieldType(descriptor), isolate), | |
8302 right_details.attributes(), | 8110 right_details.attributes(), |
8303 right_details.representation()); | 8111 right_details.representation()); |
8304 result->Set(descriptor, &d); | 8112 result->Set(descriptor, &d); |
8305 } else if (store_mode == FORCE_FIELD && descriptor == modify_index) { | |
8306 ASSERT_EQ(CONSTANT, right_details.type()); | |
8307 Representation field_representation = right_details.representation(); | |
8308 Handle<HeapType> field_type = right->GetValue(descriptor)->OptimalType( | |
8309 isolate, field_representation); | |
8310 FieldDescriptor d(handle(right->GetKey(descriptor), isolate), | |
8311 current_offset++, | |
8312 field_type, | |
8313 right_details.attributes(), | |
8314 field_representation); | |
8315 result->Set(descriptor, &d); | |
8316 } else { | 8113 } else { |
8317 Descriptor d(handle(right->GetKey(descriptor), isolate), | 8114 Descriptor d(handle(right->GetKey(descriptor)), |
8318 handle(right->GetValue(descriptor), isolate), | 8115 handle(right->GetValue(descriptor), right->GetIsolate()), |
8319 right_details); | 8116 right_details); |
8320 result->Set(descriptor, &d); | 8117 result->Set(descriptor, &d); |
8321 } | 8118 } |
8322 } | 8119 } |
8323 | 8120 |
8324 result->Sort(); | 8121 result->Sort(); |
8325 return result; | 8122 return result; |
8326 } | 8123 } |
8327 | 8124 |
8328 | 8125 |
(...skipping 8391 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
16720 #define ERROR_MESSAGES_TEXTS(C, T) T, | 16517 #define ERROR_MESSAGES_TEXTS(C, T) T, |
16721 static const char* error_messages_[] = { | 16518 static const char* error_messages_[] = { |
16722 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) | 16519 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) |
16723 }; | 16520 }; |
16724 #undef ERROR_MESSAGES_TEXTS | 16521 #undef ERROR_MESSAGES_TEXTS |
16725 return error_messages_[reason]; | 16522 return error_messages_[reason]; |
16726 } | 16523 } |
16727 | 16524 |
16728 | 16525 |
16729 } } // namespace v8::internal | 16526 } } // namespace v8::internal |
OLD | NEW |