| 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 |