Chromium Code Reviews| 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 | |
| 76 MaybeObject* Object::ToObject(Context* native_context) { | 93 MaybeObject* Object::ToObject(Context* native_context) { |
| 77 if (IsNumber()) { | 94 if (IsNumber()) { |
| 78 return CreateJSValue(native_context->number_function(), this); | 95 return CreateJSValue(native_context->number_function(), this); |
| 79 } else if (IsBoolean()) { | 96 } else if (IsBoolean()) { |
| 80 return CreateJSValue(native_context->boolean_function(), this); | 97 return CreateJSValue(native_context->boolean_function(), this); |
| 81 } else if (IsString()) { | 98 } else if (IsString()) { |
| 82 return CreateJSValue(native_context->string_function(), this); | 99 return CreateJSValue(native_context->string_function(), this); |
| 83 } else if (IsSymbol()) { | 100 } else if (IsSymbol()) { |
| 84 return CreateJSValue(native_context->symbol_function(), this); | 101 return CreateJSValue(native_context->symbol_function(), this); |
| 85 } | 102 } |
| (...skipping 1447 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1533 } | 1550 } |
| 1534 | 1551 |
| 1535 | 1552 |
| 1536 void Map::PrintGeneralization(FILE* file, | 1553 void Map::PrintGeneralization(FILE* file, |
| 1537 const char* reason, | 1554 const char* reason, |
| 1538 int modify_index, | 1555 int modify_index, |
| 1539 int split, | 1556 int split, |
| 1540 int descriptors, | 1557 int descriptors, |
| 1541 bool constant_to_field, | 1558 bool constant_to_field, |
| 1542 Representation old_representation, | 1559 Representation old_representation, |
| 1543 Representation new_representation) { | 1560 Representation new_representation, |
| 1561 HeapType* old_field_type, | |
| 1562 HeapType* new_field_type) { | |
| 1544 PrintF(file, "[generalizing "); | 1563 PrintF(file, "[generalizing "); |
| 1545 constructor_name()->PrintOn(file); | 1564 constructor_name()->PrintOn(file); |
| 1546 PrintF(file, "] "); | 1565 PrintF(file, "] "); |
| 1547 Name* name = instance_descriptors()->GetKey(modify_index); | 1566 Name* name = instance_descriptors()->GetKey(modify_index); |
| 1548 if (name->IsString()) { | 1567 if (name->IsString()) { |
| 1549 String::cast(name)->PrintOn(file); | 1568 String::cast(name)->PrintOn(file); |
| 1550 } else { | 1569 } else { |
| 1551 PrintF(file, "{symbol %p}", static_cast<void*>(name)); | 1570 PrintF(file, "{symbol %p}", static_cast<void*>(name)); |
| 1552 } | 1571 } |
| 1572 PrintF(file, ":"); | |
| 1553 if (constant_to_field) { | 1573 if (constant_to_field) { |
| 1554 PrintF(file, ":c->f"); | 1574 PrintF(file, "c"); |
| 1555 } else { | 1575 } else { |
| 1556 PrintF(file, ":%s->%s", | 1576 PrintF(file, "%s", old_representation.Mnemonic()); |
| 1557 old_representation.Mnemonic(), | 1577 PrintF(file, "{"); |
| 1558 new_representation.Mnemonic()); | 1578 old_field_type->TypePrint(file, HeapType::SEMANTIC_DIM); |
| 1579 PrintF(file, "}"); | |
| 1559 } | 1580 } |
| 1581 PrintF(file, "->%s", new_representation.Mnemonic()); | |
| 1582 PrintF(file, "{"); | |
| 1583 new_field_type->TypePrint(file, HeapType::SEMANTIC_DIM); | |
| 1584 PrintF(file, "}"); | |
| 1560 PrintF(file, " ("); | 1585 PrintF(file, " ("); |
| 1561 if (strlen(reason) > 0) { | 1586 if (strlen(reason) > 0) { |
| 1562 PrintF(file, "%s", reason); | 1587 PrintF(file, "%s", reason); |
| 1563 } else { | 1588 } else { |
| 1564 PrintF(file, "+%i maps", descriptors - split); | 1589 PrintF(file, "+%i maps", descriptors - split); |
| 1565 } | 1590 } |
| 1566 PrintF(file, ") ["); | 1591 PrintF(file, ") ["); |
| 1567 JavaScriptFrame::PrintTop(GetIsolate(), file, false, true); | 1592 JavaScriptFrame::PrintTop(GetIsolate(), file, false, true); |
| 1568 PrintF(file, "]\n"); | 1593 PrintF(file, "]\n"); |
| 1569 } | 1594 } |
| (...skipping 371 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1941 Heap* heap = isolate->heap(); | 1966 Heap* heap = isolate->heap(); |
| 1942 CALL_HEAP_FUNCTION(isolate, | 1967 CALL_HEAP_FUNCTION(isolate, |
| 1943 object->AllocateNewStorageFor(heap, representation), | 1968 object->AllocateNewStorageFor(heap, representation), |
| 1944 Object); | 1969 Object); |
| 1945 } | 1970 } |
| 1946 | 1971 |
| 1947 | 1972 |
| 1948 static Handle<Map> CopyAddFieldDescriptor(Handle<Map> map, | 1973 static Handle<Map> CopyAddFieldDescriptor(Handle<Map> map, |
| 1949 Handle<Name> name, | 1974 Handle<Name> name, |
| 1950 int index, | 1975 int index, |
| 1976 Handle<HeapType> field_type, | |
| 1951 PropertyAttributes attributes, | 1977 PropertyAttributes attributes, |
| 1952 Representation representation, | 1978 Representation representation, |
| 1953 TransitionFlag flag) { | 1979 TransitionFlag flag) { |
| 1954 FieldDescriptor new_field_desc(name, index, attributes, representation); | 1980 FieldDescriptor new_field_desc(name, index, field_type, |
| 1981 attributes, representation); | |
| 1955 Handle<Map> new_map = Map::CopyAddDescriptor(map, &new_field_desc, flag); | 1982 Handle<Map> new_map = Map::CopyAddDescriptor(map, &new_field_desc, flag); |
| 1956 int unused_property_fields = map->unused_property_fields() - 1; | 1983 int unused_property_fields = map->unused_property_fields() - 1; |
| 1957 if (unused_property_fields < 0) { | 1984 if (unused_property_fields < 0) { |
| 1958 unused_property_fields += JSObject::kFieldsAdded; | 1985 unused_property_fields += JSObject::kFieldsAdded; |
| 1959 } | 1986 } |
| 1960 new_map->set_unused_property_fields(unused_property_fields); | 1987 new_map->set_unused_property_fields(unused_property_fields); |
| 1961 return new_map; | 1988 return new_map; |
| 1962 } | 1989 } |
| 1963 | 1990 |
| 1964 | 1991 |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 1981 if (!name->IsCacheable(isolate) || | 2008 if (!name->IsCacheable(isolate) || |
| 1982 object->TooManyFastProperties(store_mode)) { | 2009 object->TooManyFastProperties(store_mode)) { |
| 1983 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0); | 2010 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0); |
| 1984 AddSlowProperty(object, name, value, attributes); | 2011 AddSlowProperty(object, name, value, attributes); |
| 1985 return; | 2012 return; |
| 1986 } | 2013 } |
| 1987 | 2014 |
| 1988 // Compute the new index for new field. | 2015 // Compute the new index for new field. |
| 1989 int index = object->map()->NextFreePropertyIndex(); | 2016 int index = object->map()->NextFreePropertyIndex(); |
| 1990 | 2017 |
| 1991 // Allocate new instance descriptors with (name, index) added | 2018 // Compute the optimal representation for the new field. |
| 1992 if (object->IsJSContextExtensionObject()) value_type = FORCE_TAGGED; | 2019 if (object->IsJSContextExtensionObject()) value_type = FORCE_TAGGED; |
| 1993 Representation representation = value->OptimalRepresentation(value_type); | 2020 Representation representation = value->OptimalRepresentation(value_type); |
| 2021 | |
| 2022 // Allocate new instance descriptors with (name, index) added | |
|
Toon Verwaest
2014/04/11 12:49:43
This comment is a bit weird. I'd just drop it enti
Benedikt Meurer
2014/04/14 06:29:04
Done.
| |
| 1994 Handle<Map> new_map = CopyAddFieldDescriptor( | 2023 Handle<Map> new_map = CopyAddFieldDescriptor( |
| 1995 handle(object->map()), name, index, attributes, representation, flag); | 2024 handle(object->map()), name, index, |
| 2025 value->OptimalType(isolate, representation), | |
| 2026 attributes, representation, flag); | |
| 1996 | 2027 |
| 1997 JSObject::MigrateToMap(object, new_map); | 2028 JSObject::MigrateToMap(object, new_map); |
| 1998 | 2029 |
| 1999 if (representation.IsDouble()) { | 2030 if (representation.IsDouble()) { |
| 2000 // Nothing more to be done. | 2031 // Nothing more to be done. |
| 2001 if (value->IsUninitialized()) return; | 2032 if (value->IsUninitialized()) return; |
| 2002 HeapNumber* box = HeapNumber::cast(object->RawFastPropertyAt(index)); | 2033 HeapNumber* box = HeapNumber::cast(object->RawFastPropertyAt(index)); |
| 2003 box->set_value(value->Number()); | 2034 box->set_value(value->Number()); |
| 2004 } else { | 2035 } else { |
| 2005 object->FastPropertyAtPut(index, *value); | 2036 object->FastPropertyAtPut(index, *value); |
| (...skipping 425 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2431 // fresly allocated page or on an already swept page. Hence, the sweeper | 2462 // fresly allocated page or on an already swept page. Hence, the sweeper |
| 2432 // thread can not get confused with the filler creation. No synchronization | 2463 // thread can not get confused with the filler creation. No synchronization |
| 2433 // needed. | 2464 // needed. |
| 2434 object->set_map(*new_map); | 2465 object->set_map(*new_map); |
| 2435 } | 2466 } |
| 2436 | 2467 |
| 2437 | 2468 |
| 2438 void JSObject::GeneralizeFieldRepresentation(Handle<JSObject> object, | 2469 void JSObject::GeneralizeFieldRepresentation(Handle<JSObject> object, |
| 2439 int modify_index, | 2470 int modify_index, |
| 2440 Representation new_representation, | 2471 Representation new_representation, |
| 2472 Handle<HeapType> new_field_type, | |
| 2441 StoreMode store_mode) { | 2473 StoreMode store_mode) { |
| 2442 Handle<Map> new_map = Map::GeneralizeRepresentation( | 2474 Handle<Map> new_map = Map::GeneralizeRepresentation( |
| 2443 handle(object->map()), modify_index, new_representation, store_mode); | 2475 handle(object->map()), modify_index, new_representation, |
| 2476 new_field_type, store_mode); | |
| 2444 if (object->map() == *new_map) return; | 2477 if (object->map() == *new_map) return; |
| 2445 return MigrateToMap(object, new_map); | 2478 return MigrateToMap(object, new_map); |
| 2446 } | 2479 } |
| 2447 | 2480 |
| 2448 | 2481 |
| 2449 int Map::NumberOfFields() { | 2482 int Map::NumberOfFields() { |
| 2450 DescriptorArray* descriptors = instance_descriptors(); | 2483 DescriptorArray* descriptors = instance_descriptors(); |
| 2451 int result = 0; | 2484 int result = 0; |
| 2452 for (int i = 0; i < NumberOfOwnDescriptors(); i++) { | 2485 for (int i = 0; i < NumberOfOwnDescriptors(); i++) { |
| 2453 if (descriptors->GetDetails(i).type() == FIELD) result++; | 2486 if (descriptors->GetDetails(i).type() == FIELD) result++; |
| 2454 } | 2487 } |
| 2455 return result; | 2488 return result; |
| 2456 } | 2489 } |
| 2457 | 2490 |
| 2458 | 2491 |
| 2459 Handle<Map> Map::CopyGeneralizeAllRepresentations(Handle<Map> map, | 2492 Handle<Map> Map::CopyGeneralizeAllRepresentations(Handle<Map> map, |
| 2460 int modify_index, | 2493 int modify_index, |
| 2461 StoreMode store_mode, | 2494 StoreMode store_mode, |
| 2462 PropertyAttributes attributes, | 2495 PropertyAttributes attributes, |
| 2463 const char* reason) { | 2496 const char* reason) { |
| 2497 Isolate* isolate = map->GetIsolate(); | |
| 2464 Handle<Map> new_map = Copy(map); | 2498 Handle<Map> new_map = Copy(map); |
| 2465 | 2499 |
| 2466 DescriptorArray* descriptors = new_map->instance_descriptors(); | 2500 DescriptorArray* descriptors = new_map->instance_descriptors(); |
| 2467 descriptors->InitializeRepresentations(Representation::Tagged()); | 2501 int length = descriptors->number_of_descriptors(); |
| 2502 for (int i = 0; i < length; i++) { | |
| 2503 descriptors->SetRepresentation(i, Representation::Tagged()); | |
| 2504 if (descriptors->GetDetails(i).type() == FIELD) { | |
| 2505 descriptors->SetValue(i, HeapType::Any()); | |
| 2506 } | |
| 2507 } | |
| 2468 | 2508 |
| 2469 // Unless the instance is being migrated, ensure that modify_index is a field. | 2509 // Unless the instance is being migrated, ensure that modify_index is a field. |
| 2470 PropertyDetails details = descriptors->GetDetails(modify_index); | 2510 PropertyDetails details = descriptors->GetDetails(modify_index); |
| 2471 if (store_mode == FORCE_FIELD && details.type() != FIELD) { | 2511 if (store_mode == FORCE_FIELD && details.type() != FIELD) { |
| 2472 FieldDescriptor d(handle(descriptors->GetKey(modify_index), | 2512 FieldDescriptor d(handle(descriptors->GetKey(modify_index), isolate), |
| 2473 map->GetIsolate()), | |
| 2474 new_map->NumberOfFields(), | 2513 new_map->NumberOfFields(), |
| 2475 attributes, | 2514 attributes, |
| 2476 Representation::Tagged()); | 2515 Representation::Tagged()); |
| 2477 descriptors->Replace(modify_index, &d); | 2516 descriptors->Replace(modify_index, &d); |
| 2478 int unused_property_fields = new_map->unused_property_fields() - 1; | 2517 int unused_property_fields = new_map->unused_property_fields() - 1; |
| 2479 if (unused_property_fields < 0) { | 2518 if (unused_property_fields < 0) { |
| 2480 unused_property_fields += JSObject::kFieldsAdded; | 2519 unused_property_fields += JSObject::kFieldsAdded; |
| 2481 } | 2520 } |
| 2482 new_map->set_unused_property_fields(unused_property_fields); | 2521 new_map->set_unused_property_fields(unused_property_fields); |
| 2483 } | 2522 } |
| 2484 | 2523 |
| 2485 if (FLAG_trace_generalization) { | 2524 if (FLAG_trace_generalization) { |
| 2525 HeapType* field_type = (details.type() == FIELD) | |
| 2526 ? map->instance_descriptors()->GetFieldType(modify_index) | |
| 2527 : NULL; | |
| 2486 map->PrintGeneralization(stdout, reason, modify_index, | 2528 map->PrintGeneralization(stdout, reason, modify_index, |
| 2487 new_map->NumberOfOwnDescriptors(), | 2529 new_map->NumberOfOwnDescriptors(), |
| 2488 new_map->NumberOfOwnDescriptors(), | 2530 new_map->NumberOfOwnDescriptors(), |
| 2489 details.type() == CONSTANT && store_mode == FORCE_FIELD, | 2531 details.type() == CONSTANT && store_mode == FORCE_FIELD, |
| 2490 Representation::Tagged(), Representation::Tagged()); | 2532 details.representation(), Representation::Tagged(), |
| 2533 field_type, HeapType::Any()); | |
| 2491 } | 2534 } |
| 2492 return new_map; | 2535 return new_map; |
| 2493 } | 2536 } |
| 2494 | 2537 |
| 2495 | 2538 |
| 2496 void Map::DeprecateTransitionTree() { | 2539 void Map::DeprecateTransitionTree() { |
| 2497 if (is_deprecated()) return; | 2540 if (is_deprecated()) return; |
| 2498 if (HasTransitionArray()) { | 2541 if (HasTransitionArray()) { |
| 2499 TransitionArray* transitions = this->transitions(); | 2542 TransitionArray* transitions = this->transitions(); |
| 2500 for (int i = 0; i < transitions->number_of_transitions(); i++) { | 2543 for (int i = 0; i < transitions->number_of_transitions(); i++) { |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2545 if (back->IsUndefined()) return result; | 2588 if (back->IsUndefined()) return result; |
| 2546 result = Map::cast(back); | 2589 result = Map::cast(back); |
| 2547 } | 2590 } |
| 2548 } | 2591 } |
| 2549 | 2592 |
| 2550 | 2593 |
| 2551 // Returns NULL if the updated map is incompatible. | 2594 // Returns NULL if the updated map is incompatible. |
| 2552 Map* Map::FindUpdatedMap(int verbatim, | 2595 Map* Map::FindUpdatedMap(int verbatim, |
| 2553 int length, | 2596 int length, |
| 2554 DescriptorArray* descriptors) { | 2597 DescriptorArray* descriptors) { |
| 2598 DisallowHeapAllocation no_allocation; | |
| 2599 | |
| 2555 // This can only be called on roots of transition trees. | 2600 // This can only be called on roots of transition trees. |
| 2556 ASSERT(GetBackPointer()->IsUndefined()); | 2601 ASSERT(GetBackPointer()->IsUndefined()); |
| 2557 | 2602 |
| 2558 Map* current = this; | 2603 Map* current = this; |
| 2559 | 2604 |
| 2560 for (int i = verbatim; i < length; i++) { | 2605 for (int i = verbatim; i < length; i++) { |
| 2561 if (!current->HasTransitionArray()) break; | 2606 if (!current->HasTransitionArray()) break; |
| 2562 Name* name = descriptors->GetKey(i); | 2607 Name* name = descriptors->GetKey(i); |
| 2563 TransitionArray* transitions = current->transitions(); | 2608 TransitionArray* transitions = current->transitions(); |
| 2564 int transition = transitions->Search(name); | 2609 int transition = transitions->Search(name); |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 2579 } | 2624 } |
| 2580 } | 2625 } |
| 2581 | 2626 |
| 2582 return current; | 2627 return current; |
| 2583 } | 2628 } |
| 2584 | 2629 |
| 2585 | 2630 |
| 2586 Map* Map::FindLastMatchMap(int verbatim, | 2631 Map* Map::FindLastMatchMap(int verbatim, |
| 2587 int length, | 2632 int length, |
| 2588 DescriptorArray* descriptors) { | 2633 DescriptorArray* descriptors) { |
| 2634 DisallowHeapAllocation no_allocation; | |
| 2635 | |
| 2589 // This can only be called on roots of transition trees. | 2636 // This can only be called on roots of transition trees. |
| 2590 ASSERT(GetBackPointer()->IsUndefined()); | 2637 ASSERT(GetBackPointer()->IsUndefined()); |
| 2591 | 2638 |
| 2592 Map* current = this; | 2639 Map* current = this; |
| 2593 | 2640 |
| 2594 for (int i = verbatim; i < length; i++) { | 2641 for (int i = verbatim; i < length; i++) { |
| 2595 if (!current->HasTransitionArray()) break; | 2642 if (!current->HasTransitionArray()) break; |
| 2596 Name* name = descriptors->GetKey(i); | 2643 Name* name = descriptors->GetKey(i); |
| 2597 TransitionArray* transitions = current->transitions(); | 2644 TransitionArray* transitions = current->transitions(); |
| 2598 int transition = transitions->Search(name); | 2645 int transition = transitions->Search(name); |
| 2599 if (transition == TransitionArray::kNotFound) break; | 2646 if (transition == TransitionArray::kNotFound) break; |
| 2600 | 2647 |
| 2601 Map* next = transitions->GetTarget(transition); | 2648 Map* next = transitions->GetTarget(transition); |
| 2602 DescriptorArray* next_descriptors = next->instance_descriptors(); | 2649 DescriptorArray* next_descriptors = next->instance_descriptors(); |
| 2603 | 2650 |
| 2604 if (next_descriptors->GetValue(i) != descriptors->GetValue(i)) break; | |
| 2605 | |
| 2606 PropertyDetails details = descriptors->GetDetails(i); | 2651 PropertyDetails details = descriptors->GetDetails(i); |
| 2607 PropertyDetails next_details = next_descriptors->GetDetails(i); | 2652 PropertyDetails next_details = next_descriptors->GetDetails(i); |
| 2608 if (details.type() != next_details.type()) break; | 2653 if (details.type() != next_details.type()) break; |
| 2609 if (details.attributes() != next_details.attributes()) break; | 2654 if (details.attributes() != next_details.attributes()) break; |
| 2610 if (!details.representation().Equals(next_details.representation())) break; | 2655 if (!details.representation().Equals(next_details.representation())) break; |
| 2656 if (next_details.type() == FIELD) { | |
| 2657 if (!descriptors->GetFieldType(i)->NowIs( | |
| 2658 next_descriptors->GetFieldType(i))) break; | |
| 2659 } else { | |
| 2660 if (descriptors->GetValue(i) != next_descriptors->GetValue(i)) break; | |
| 2661 } | |
| 2611 | 2662 |
| 2612 current = next; | 2663 current = next; |
| 2613 } | 2664 } |
| 2614 return current; | 2665 return current; |
| 2615 } | 2666 } |
| 2616 | 2667 |
| 2617 | 2668 |
| 2669 Map* Map::FindFieldOwner(int descriptor) { | |
| 2670 DisallowHeapAllocation no_allocation; | |
| 2671 ASSERT_EQ(FIELD, instance_descriptors()->GetDetails(descriptor).type()); | |
| 2672 Map* result = this; | |
| 2673 while (true) { | |
| 2674 Object* back = result->GetBackPointer(); | |
| 2675 if (back->IsUndefined()) break; | |
| 2676 Map* parent = Map::cast(back); | |
| 2677 if (parent->NumberOfOwnDescriptors() <= descriptor) break; | |
| 2678 result = parent; | |
| 2679 } | |
| 2680 return result; | |
| 2681 } | |
| 2682 | |
| 2683 | |
| 2684 void Map::UpdateDescriptor(int descriptor_number, Descriptor* desc) { | |
| 2685 DisallowHeapAllocation no_allocation; | |
| 2686 if (HasTransitionArray()) { | |
| 2687 TransitionArray* transitions = this->transitions(); | |
| 2688 for (int i = 0; i < transitions->number_of_transitions(); ++i) { | |
| 2689 transitions->GetTarget(i)->UpdateDescriptor(descriptor_number, desc); | |
| 2690 } | |
| 2691 } | |
| 2692 instance_descriptors()->Replace(descriptor_number, desc);; | |
| 2693 } | |
| 2694 | |
| 2695 | |
| 2696 // static | |
| 2697 void Map::GeneralizeFieldType(Handle<Map> map, | |
| 2698 int modify_index, | |
| 2699 Handle<HeapType> new_field_type) { | |
| 2700 Isolate* isolate = map->GetIsolate(); | |
| 2701 Handle<Map> field_owner(map->FindFieldOwner(modify_index), isolate); | |
| 2702 Handle<DescriptorArray> descriptors( | |
| 2703 field_owner->instance_descriptors(), isolate); | |
| 2704 PropertyDetails details = descriptors->GetDetails(modify_index); | |
| 2705 | |
| 2706 // Check if we actually need to generalize the field type at all. | |
| 2707 Handle<HeapType> old_field_type( | |
| 2708 descriptors->GetFieldType(modify_index), isolate); | |
| 2709 if (new_field_type->NowIs(old_field_type)) return; | |
| 2710 | |
| 2711 // Determine the generalized new field type. | |
| 2712 if (!old_field_type->NowIs(new_field_type)) { | |
| 2713 new_field_type = HeapType::Any(isolate); | |
| 2714 } | |
| 2715 | |
| 2716 FieldDescriptor d(handle(descriptors->GetKey(modify_index), isolate), | |
| 2717 descriptors->GetFieldIndex(modify_index), | |
| 2718 new_field_type, | |
| 2719 details.attributes(), | |
| 2720 details.representation()); | |
| 2721 field_owner->UpdateDescriptor(modify_index, &d); | |
| 2722 field_owner->dependent_code()->DeoptimizeDependentCodeGroup( | |
| 2723 isolate, DependentCode::kFieldTypeGroup); | |
| 2724 | |
| 2725 if (FLAG_trace_generalization) { | |
| 2726 map->PrintGeneralization( | |
| 2727 stdout, "field type update", | |
| 2728 modify_index, map->NumberOfOwnDescriptors(), | |
| 2729 map->NumberOfOwnDescriptors(), false, | |
| 2730 details.representation(), details.representation(), | |
| 2731 *old_field_type, *new_field_type); | |
| 2732 } | |
| 2733 } | |
| 2734 | |
| 2735 | |
| 2618 // Generalize the representation of the descriptor at |modify_index|. | 2736 // Generalize the representation of the descriptor at |modify_index|. |
| 2619 // This method rewrites the transition tree to reflect the new change. To avoid | 2737 // This method rewrites the transition tree to reflect the new change. To avoid |
| 2620 // high degrees over polymorphism, and to stabilize quickly, on every rewrite | 2738 // high degrees over polymorphism, and to stabilize quickly, on every rewrite |
| 2621 // the new type is deduced by merging the current type with any potential new | 2739 // the new type is deduced by merging the current type with any potential new |
| 2622 // (partial) version of the type in the transition tree. | 2740 // (partial) version of the type in the transition tree. |
| 2623 // To do this, on each rewrite: | 2741 // To do this, on each rewrite: |
| 2624 // - Search the root of the transition tree using FindRootMap. | 2742 // - Search the root of the transition tree using FindRootMap. |
| 2625 // - Find |updated|, the newest matching version of this map using | 2743 // - Find |updated|, the newest matching version of this map using |
| 2626 // FindUpdatedMap. This uses the keys in the own map's descriptor array to | 2744 // FindUpdatedMap. This uses the keys in the own map's descriptor array to |
| 2627 // walk the transition tree. | 2745 // walk the transition tree. |
| 2628 // - Merge/generalize the descriptor array of the current map and |updated|. | 2746 // - Merge/generalize the descriptor array of the current map and |updated|. |
| 2629 // - Generalize the |modify_index| descriptor using |new_representation|. | 2747 // - Generalize the |modify_index| descriptor using |new_representation|. |
| 2630 // - Walk the tree again starting from the root towards |updated|. Stop at | 2748 // - Walk the tree again starting from the root towards |updated|. Stop at |
| 2631 // |split_map|, the first map who's descriptor array does not match the merged | 2749 // |split_map|, the first map who's descriptor array does not match the merged |
| 2632 // descriptor array. | 2750 // descriptor array. |
| 2633 // - If |updated| == |split_map|, |updated| is in the expected state. Return it. | 2751 // - If |updated| == |split_map|, |updated| is in the expected state. Return it. |
| 2634 // - Otherwise, invalidate the outdated transition target from |updated|, and | 2752 // - Otherwise, invalidate the outdated transition target from |updated|, and |
| 2635 // replace its transition tree with a new branch for the updated descriptors. | 2753 // replace its transition tree with a new branch for the updated descriptors. |
| 2636 Handle<Map> Map::GeneralizeRepresentation(Handle<Map> old_map, | 2754 Handle<Map> Map::GeneralizeRepresentation(Handle<Map> old_map, |
| 2637 int modify_index, | 2755 int modify_index, |
| 2638 Representation new_representation, | 2756 Representation new_representation, |
| 2757 Handle<HeapType> new_field_type, | |
| 2639 StoreMode store_mode) { | 2758 StoreMode store_mode) { |
| 2640 Handle<DescriptorArray> old_descriptors(old_map->instance_descriptors()); | 2759 Handle<DescriptorArray> old_descriptors(old_map->instance_descriptors()); |
| 2641 PropertyDetails old_details = old_descriptors->GetDetails(modify_index); | 2760 PropertyDetails old_details = old_descriptors->GetDetails(modify_index); |
| 2642 Representation old_representation = old_details.representation(); | 2761 Representation old_representation = old_details.representation(); |
| 2643 | 2762 |
| 2644 // It's fine to transition from None to anything but double without any | 2763 // It's fine to transition from None to anything but double without any |
| 2645 // modification to the object, because the default uninitialized value for | 2764 // modification to the object, because the default uninitialized value for |
| 2646 // representation None can be overwritten by both smi and tagged values. | 2765 // representation None can be overwritten by both smi and tagged values. |
| 2647 // Doubles, however, would require a box allocation. | 2766 // Doubles, however, would require a box allocation. |
| 2648 if (old_representation.IsNone() && | 2767 if (old_representation.IsNone() && |
| 2649 !new_representation.IsNone() && | 2768 !new_representation.IsNone() && |
| 2650 !new_representation.IsDouble()) { | 2769 !new_representation.IsDouble()) { |
| 2770 ASSERT(old_details.type() == FIELD); | |
| 2771 ASSERT(old_descriptors->GetFieldType(modify_index)->NowIs( | |
| 2772 HeapType::None())); | |
| 2773 if (FLAG_trace_generalization) { | |
| 2774 old_map->PrintGeneralization( | |
| 2775 stdout, "uninitialized field", | |
| 2776 modify_index, old_map->NumberOfOwnDescriptors(), | |
| 2777 old_map->NumberOfOwnDescriptors(), false, | |
| 2778 old_representation, new_representation, | |
| 2779 old_descriptors->GetFieldType(modify_index), *new_field_type); | |
| 2780 } | |
| 2651 old_descriptors->SetRepresentation(modify_index, new_representation); | 2781 old_descriptors->SetRepresentation(modify_index, new_representation); |
| 2782 old_descriptors->SetValue(modify_index, *new_field_type); | |
| 2652 return old_map; | 2783 return old_map; |
| 2653 } | 2784 } |
| 2654 | 2785 |
| 2655 int descriptors = old_map->NumberOfOwnDescriptors(); | 2786 if (new_representation.Equals(old_representation) && |
| 2787 old_details.type() == FIELD) { | |
| 2788 Map::GeneralizeFieldType(old_map, modify_index, new_field_type); | |
| 2789 return old_map; | |
| 2790 } | |
| 2791 | |
| 2656 Handle<Map> root_map(old_map->FindRootMap()); | 2792 Handle<Map> root_map(old_map->FindRootMap()); |
| 2657 | 2793 |
| 2658 // Check the state of the root map. | 2794 // Check the state of the root map. |
| 2659 if (!old_map->EquivalentToForTransition(*root_map)) { | 2795 if (!old_map->EquivalentToForTransition(*root_map)) { |
| 2660 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, | 2796 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, |
| 2661 old_details.attributes(), "not equivalent"); | 2797 old_details.attributes(), "not equivalent"); |
| 2662 } | 2798 } |
| 2663 | 2799 |
| 2664 int verbatim = root_map->NumberOfOwnDescriptors(); | 2800 int verbatim = root_map->NumberOfOwnDescriptors(); |
| 2665 | 2801 |
| 2666 if (store_mode != ALLOW_AS_CONSTANT && modify_index < verbatim) { | 2802 if (store_mode != ALLOW_AS_CONSTANT && modify_index < verbatim) { |
| 2667 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, | 2803 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, |
| 2668 old_details.attributes(), "root modification"); | 2804 old_details.attributes(), "root modification"); |
| 2669 } | 2805 } |
| 2670 | 2806 |
| 2807 int descriptors = old_map->NumberOfOwnDescriptors(); | |
| 2671 Map* raw_updated = root_map->FindUpdatedMap( | 2808 Map* raw_updated = root_map->FindUpdatedMap( |
| 2672 verbatim, descriptors, *old_descriptors); | 2809 verbatim, descriptors, *old_descriptors); |
| 2673 if (raw_updated == NULL) { | 2810 if (raw_updated == NULL) { |
| 2674 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, | 2811 return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, |
| 2675 old_details.attributes(), "incompatible"); | 2812 old_details.attributes(), "incompatible"); |
| 2676 } | 2813 } |
| 2677 | 2814 |
| 2678 Handle<Map> updated(raw_updated); | 2815 Handle<Map> updated(raw_updated); |
| 2679 Handle<DescriptorArray> updated_descriptors(updated->instance_descriptors()); | 2816 Handle<DescriptorArray> updated_descriptors(updated->instance_descriptors()); |
| 2680 | 2817 |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 2697 ASSERT(store_mode == ALLOW_AS_CONSTANT || | 2834 ASSERT(store_mode == ALLOW_AS_CONSTANT || |
| 2698 new_descriptors->GetDetails(modify_index).type() == FIELD); | 2835 new_descriptors->GetDetails(modify_index).type() == FIELD); |
| 2699 | 2836 |
| 2700 old_representation = | 2837 old_representation = |
| 2701 new_descriptors->GetDetails(modify_index).representation(); | 2838 new_descriptors->GetDetails(modify_index).representation(); |
| 2702 Representation updated_representation = | 2839 Representation updated_representation = |
| 2703 new_representation.generalize(old_representation); | 2840 new_representation.generalize(old_representation); |
| 2704 if (!updated_representation.Equals(old_representation)) { | 2841 if (!updated_representation.Equals(old_representation)) { |
| 2705 new_descriptors->SetRepresentation(modify_index, updated_representation); | 2842 new_descriptors->SetRepresentation(modify_index, updated_representation); |
| 2706 } | 2843 } |
| 2844 if (new_descriptors->GetDetails(modify_index).type() == FIELD) { | |
| 2845 Handle<HeapType> field_type(new_descriptors->GetFieldType(modify_index), | |
| 2846 new_descriptors->GetIsolate()); | |
| 2847 if (!new_field_type->NowIs(field_type)) { | |
| 2848 if (!field_type->NowIs(new_field_type)) { | |
| 2849 new_field_type = HeapType::Any(updated->GetIsolate()); | |
|
Toon Verwaest
2014/04/11 12:49:43
Could you introduce a method similar to new_repres
Benedikt Meurer
2014/04/14 06:29:04
Done.
| |
| 2850 } | |
| 2851 new_descriptors->SetValue(modify_index, *new_field_type); | |
| 2852 } | |
| 2853 } | |
| 2707 | 2854 |
| 2708 Handle<Map> split_map(root_map->FindLastMatchMap( | 2855 Handle<Map> split_map(root_map->FindLastMatchMap( |
| 2709 verbatim, descriptors, *new_descriptors)); | 2856 verbatim, descriptors, *new_descriptors)); |
| 2710 | 2857 |
| 2711 int split_descriptors = split_map->NumberOfOwnDescriptors(); | 2858 int split_descriptors = split_map->NumberOfOwnDescriptors(); |
| 2712 // This is shadowed by |updated_descriptors| being more general than | 2859 // This is shadowed by |updated_descriptors| being more general than |
| 2713 // |old_descriptors|. | 2860 // |old_descriptors|. |
| 2714 ASSERT(descriptors != split_descriptors); | 2861 ASSERT(descriptors != split_descriptors); |
| 2715 | 2862 |
| 2716 int descriptor = split_descriptors; | 2863 int descriptor = split_descriptors; |
| 2717 split_map->DeprecateTarget( | 2864 split_map->DeprecateTarget( |
| 2718 old_descriptors->GetKey(descriptor), *new_descriptors); | 2865 old_descriptors->GetKey(descriptor), *new_descriptors); |
| 2719 | 2866 |
| 2720 if (FLAG_trace_generalization) { | 2867 if (FLAG_trace_generalization) { |
| 2868 Isolate* isolate = old_map->GetIsolate(); | |
| 2869 PropertyDetails old_details = old_descriptors->GetDetails(modify_index); | |
| 2870 PropertyDetails new_details = new_descriptors->GetDetails(modify_index); | |
| 2871 Handle<HeapType> old_field_type = (old_details.type() == FIELD) | |
| 2872 ? handle(old_descriptors->GetFieldType(modify_index), isolate) | |
| 2873 : HeapType::Constant(handle(old_descriptors->GetValue(modify_index), | |
| 2874 isolate), isolate); | |
| 2875 Handle<HeapType> new_field_type = (new_details.type() == FIELD) | |
| 2876 ? handle(new_descriptors->GetFieldType(modify_index), isolate) | |
| 2877 : HeapType::Constant(handle(new_descriptors->GetValue(modify_index), | |
| 2878 isolate), isolate); | |
| 2721 old_map->PrintGeneralization( | 2879 old_map->PrintGeneralization( |
| 2722 stdout, "", modify_index, descriptor, descriptors, | 2880 stdout, "", modify_index, descriptor, descriptors, |
| 2723 old_descriptors->GetDetails(modify_index).type() == CONSTANT && | 2881 old_details.type() == CONSTANT && store_mode == FORCE_FIELD, |
| 2724 store_mode == FORCE_FIELD, | 2882 old_details.representation(), new_details.representation(), |
| 2725 old_representation, updated_representation); | 2883 *old_field_type, *new_field_type); |
| 2726 } | 2884 } |
| 2727 | 2885 |
| 2728 // Add missing transitions. | 2886 // Add missing transitions. |
| 2729 Handle<Map> new_map = split_map; | 2887 Handle<Map> new_map = split_map; |
| 2730 for (; descriptor < descriptors; descriptor++) { | 2888 for (; descriptor < descriptors; descriptor++) { |
| 2731 new_map = Map::CopyInstallDescriptors(new_map, descriptor, new_descriptors); | 2889 new_map = Map::CopyInstallDescriptors(new_map, descriptor, new_descriptors); |
| 2732 } | 2890 } |
| 2733 | 2891 |
| 2734 new_map->set_owns_descriptors(true); | 2892 new_map->set_owns_descriptors(true); |
| 2735 return new_map; | 2893 return new_map; |
| 2736 } | 2894 } |
| 2737 | 2895 |
| 2738 | 2896 |
| 2739 // Generalize the representation of all FIELD descriptors. | 2897 // Generalize the representation of all FIELD descriptors. |
| 2740 Handle<Map> Map::GeneralizeAllFieldRepresentations( | 2898 Handle<Map> Map::GeneralizeAllFieldRepresentations( |
| 2741 Handle<Map> map, | 2899 Handle<Map> map) { |
| 2742 Representation new_representation) { | |
| 2743 Handle<DescriptorArray> descriptors(map->instance_descriptors()); | 2900 Handle<DescriptorArray> descriptors(map->instance_descriptors()); |
| 2744 for (int i = 0; i < map->NumberOfOwnDescriptors(); i++) { | 2901 for (int i = 0; i < map->NumberOfOwnDescriptors(); ++i) { |
| 2745 PropertyDetails details = descriptors->GetDetails(i); | 2902 if (descriptors->GetDetails(i).type() == FIELD) { |
| 2746 if (details.type() == FIELD) { | 2903 map = GeneralizeRepresentation(map, i, Representation::Tagged(), |
| 2747 map = GeneralizeRepresentation(map, i, new_representation, FORCE_FIELD); | 2904 HeapType::Any(map->GetIsolate()), |
| 2905 FORCE_FIELD); | |
| 2748 } | 2906 } |
| 2749 } | 2907 } |
| 2750 return map; | 2908 return map; |
| 2751 } | 2909 } |
| 2752 | 2910 |
| 2753 | 2911 |
| 2754 Handle<Map> Map::CurrentMapForDeprecated(Handle<Map> map) { | 2912 Handle<Map> Map::CurrentMapForDeprecated(Handle<Map> map) { |
| 2755 Handle<Map> proto_map(map); | 2913 Handle<Map> proto_map(map); |
| 2756 while (proto_map->prototype()->IsJSObject()) { | 2914 while (proto_map->prototype()->IsJSObject()) { |
| 2757 Handle<JSObject> holder(JSObject::cast(proto_map->prototype())); | 2915 Handle<JSObject> holder(JSObject::cast(proto_map->prototype())); |
| (...skipping 1115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3873 JSObject::MigrateToMap(object, map); | 4031 JSObject::MigrateToMap(object, map); |
| 3874 } | 4032 } |
| 3875 | 4033 |
| 3876 | 4034 |
| 3877 void JSObject::MigrateInstance(Handle<JSObject> object) { | 4035 void JSObject::MigrateInstance(Handle<JSObject> object) { |
| 3878 // Converting any field to the most specific type will cause the | 4036 // Converting any field to the most specific type will cause the |
| 3879 // GeneralizeFieldRepresentation algorithm to create the most general existing | 4037 // GeneralizeFieldRepresentation algorithm to create the most general existing |
| 3880 // transition that matches the object. This achieves what is needed. | 4038 // transition that matches the object. This achieves what is needed. |
| 3881 Handle<Map> original_map(object->map()); | 4039 Handle<Map> original_map(object->map()); |
| 3882 GeneralizeFieldRepresentation( | 4040 GeneralizeFieldRepresentation( |
| 3883 object, 0, Representation::None(), ALLOW_AS_CONSTANT); | 4041 object, 0, Representation::None(), |
| 4042 HeapType::None(object->GetIsolate()), | |
| 4043 ALLOW_AS_CONSTANT); | |
| 3884 object->map()->set_migration_target(true); | 4044 object->map()->set_migration_target(true); |
| 3885 if (FLAG_trace_migration) { | 4045 if (FLAG_trace_migration) { |
| 3886 object->PrintInstanceMigration(stdout, *original_map, object->map()); | 4046 object->PrintInstanceMigration(stdout, *original_map, object->map()); |
| 3887 } | 4047 } |
| 3888 } | 4048 } |
| 3889 | 4049 |
| 3890 | 4050 |
| 3891 Handle<Object> JSObject::TryMigrateInstance(Handle<JSObject> object) { | 4051 Handle<Object> JSObject::TryMigrateInstance(Handle<JSObject> object) { |
| 3892 Handle<Map> original_map(object->map()); | 4052 Handle<Map> original_map(object->map()); |
| 3893 Handle<Map> new_map = Map::CurrentMapForDeprecatedInternal(original_map); | 4053 Handle<Map> new_map = Map::CurrentMapForDeprecatedInternal(original_map); |
| 3894 if (new_map.is_null()) return Handle<Object>(); | 4054 if (new_map.is_null()) return Handle<Object>(); |
| 3895 JSObject::MigrateToMap(object, new_map); | 4055 JSObject::MigrateToMap(object, new_map); |
| 3896 if (FLAG_trace_migration) { | 4056 if (FLAG_trace_migration) { |
| 3897 object->PrintInstanceMigration(stdout, *original_map, object->map()); | 4057 object->PrintInstanceMigration(stdout, *original_map, object->map()); |
| 3898 } | 4058 } |
| 3899 return object; | 4059 return object; |
| 3900 } | 4060 } |
| 3901 | 4061 |
| 3902 | 4062 |
| 3903 MaybeHandle<Object> JSObject::SetPropertyUsingTransition( | 4063 MaybeHandle<Object> JSObject::SetPropertyUsingTransition( |
| 3904 Handle<JSObject> object, | 4064 Handle<JSObject> object, |
| 3905 LookupResult* lookup, | 4065 LookupResult* lookup, |
| 3906 Handle<Name> name, | 4066 Handle<Name> name, |
| 3907 Handle<Object> value, | 4067 Handle<Object> value, |
| 3908 PropertyAttributes attributes) { | 4068 PropertyAttributes attributes) { |
| 3909 Handle<Map> transition_map(lookup->GetTransitionTarget()); | 4069 Handle<Map> transition_map(lookup->GetTransitionTarget()); |
| 3910 int descriptor = transition_map->LastAdded(); | 4070 int descriptor = transition_map->LastAdded(); |
| 3911 | 4071 |
| 3912 DescriptorArray* descriptors = transition_map->instance_descriptors(); | 4072 Handle<DescriptorArray> descriptors(transition_map->instance_descriptors()); |
| 3913 PropertyDetails details = descriptors->GetDetails(descriptor); | 4073 PropertyDetails details = descriptors->GetDetails(descriptor); |
| 3914 | 4074 |
| 3915 if (details.type() == CALLBACKS || attributes != details.attributes()) { | 4075 if (details.type() == CALLBACKS || attributes != details.attributes()) { |
| 3916 // AddProperty will either normalize the object, or create a new fast copy | 4076 // AddProperty will either normalize the object, or create a new fast copy |
| 3917 // of the map. If we get a fast copy of the map, all field representations | 4077 // of the map. If we get a fast copy of the map, all field representations |
| 3918 // will be tagged since the transition is omitted. | 4078 // will be tagged since the transition is omitted. |
| 3919 return JSObject::AddProperty( | 4079 return JSObject::AddProperty( |
| 3920 object, name, value, attributes, SLOPPY, | 4080 object, name, value, attributes, SLOPPY, |
| 3921 JSReceiver::CERTAINLY_NOT_STORE_FROM_KEYED, | 4081 JSReceiver::CERTAINLY_NOT_STORE_FROM_KEYED, |
| 3922 JSReceiver::OMIT_EXTENSIBILITY_CHECK, | 4082 JSReceiver::OMIT_EXTENSIBILITY_CHECK, |
| 3923 JSObject::FORCE_TAGGED, FORCE_FIELD, OMIT_TRANSITION); | 4083 JSObject::FORCE_TAGGED, FORCE_FIELD, OMIT_TRANSITION); |
| 3924 } | 4084 } |
| 3925 | 4085 |
| 3926 // Keep the target CONSTANT if the same value is stored. | 4086 // Keep the target CONSTANT if the same value is stored. |
| 3927 // TODO(verwaest): Also support keeping the placeholder | 4087 // TODO(verwaest): Also support keeping the placeholder |
| 3928 // (value->IsUninitialized) as constant. | 4088 // (value->IsUninitialized) as constant. |
| 3929 if (!lookup->CanHoldValue(value) || | 4089 if (!lookup->CanHoldValue(value)) { |
| 3930 (details.type() == CONSTANT && | 4090 Representation field_representation = value->OptimalRepresentation(); |
| 3931 descriptors->GetValue(descriptor) != *value)) { | 4091 Handle<HeapType> field_type = value->OptimalType( |
| 3932 transition_map = Map::GeneralizeRepresentation(transition_map, | 4092 lookup->isolate(), field_representation); |
| 3933 descriptor, value->OptimalRepresentation(), FORCE_FIELD); | 4093 transition_map = Map::GeneralizeRepresentation( |
| 4094 transition_map, descriptor, | |
| 4095 field_representation, field_type, FORCE_FIELD); | |
| 3934 } | 4096 } |
| 3935 | 4097 |
| 3936 JSObject::MigrateToMap(object, transition_map); | 4098 JSObject::MigrateToMap(object, transition_map); |
| 3937 | 4099 |
| 3938 // Reload. | 4100 // Reload. |
| 3939 descriptors = transition_map->instance_descriptors(); | 4101 descriptors = handle(transition_map->instance_descriptors()); |
| 3940 details = descriptors->GetDetails(descriptor); | 4102 details = descriptors->GetDetails(descriptor); |
| 3941 | 4103 |
| 3942 if (details.type() != FIELD) return value; | 4104 if (details.type() != FIELD) return value; |
| 3943 | 4105 |
| 3944 int field_index = descriptors->GetFieldIndex(descriptor); | 4106 int field_index = descriptors->GetFieldIndex(descriptor); |
| 3945 if (details.representation().IsDouble()) { | 4107 if (details.representation().IsDouble()) { |
| 3946 // Nothing more to be done. | 4108 // Nothing more to be done. |
| 3947 if (value->IsUninitialized()) return value; | 4109 if (value->IsUninitialized()) return value; |
| 3948 HeapNumber* box = HeapNumber::cast(object->RawFastPropertyAt(field_index)); | 4110 HeapNumber* box = HeapNumber::cast(object->RawFastPropertyAt(field_index)); |
| 3949 box->set_value(value->Number()); | 4111 box->set_value(value->Number()); |
| 3950 } else { | 4112 } else { |
| 3951 object->FastPropertyAtPut(field_index, *value); | 4113 object->FastPropertyAtPut(field_index, *value); |
| 3952 } | 4114 } |
| 3953 | 4115 |
| 3954 return value; | 4116 return value; |
| 3955 } | 4117 } |
| 3956 | 4118 |
| 3957 | 4119 |
| 3958 static void SetPropertyToField(LookupResult* lookup, | 4120 static void SetPropertyToField(LookupResult* lookup, |
| 3959 Handle<Object> value) { | 4121 Handle<Object> value) { |
| 3960 Representation representation = lookup->representation(); | 4122 Representation representation = lookup->representation(); |
| 3961 if (!lookup->CanHoldValue(value) || | 4123 if (lookup->type() == CONSTANT || !lookup->CanHoldValue(value)) { |
| 3962 lookup->type() == CONSTANT) { | 4124 Representation field_representation = value->OptimalRepresentation(); |
| 4125 Handle<HeapType> field_type = value->OptimalType( | |
| 4126 lookup->isolate(), field_representation); | |
| 3963 JSObject::GeneralizeFieldRepresentation(handle(lookup->holder()), | 4127 JSObject::GeneralizeFieldRepresentation(handle(lookup->holder()), |
| 3964 lookup->GetDescriptorIndex(), | 4128 lookup->GetDescriptorIndex(), |
| 3965 value->OptimalRepresentation(), | 4129 field_representation, field_type, |
| 3966 FORCE_FIELD); | 4130 FORCE_FIELD); |
| 3967 DescriptorArray* desc = lookup->holder()->map()->instance_descriptors(); | 4131 DescriptorArray* desc = lookup->holder()->map()->instance_descriptors(); |
| 3968 int descriptor = lookup->GetDescriptorIndex(); | 4132 int descriptor = lookup->GetDescriptorIndex(); |
| 3969 representation = desc->GetDetails(descriptor).representation(); | 4133 representation = desc->GetDetails(descriptor).representation(); |
| 3970 } | 4134 } |
| 3971 | 4135 |
| 3972 if (representation.IsDouble()) { | 4136 if (representation.IsDouble()) { |
| 3973 HeapNumber* storage = HeapNumber::cast(lookup->holder()->RawFastPropertyAt( | 4137 HeapNumber* storage = HeapNumber::cast(lookup->holder()->RawFastPropertyAt( |
| 3974 lookup->GetFieldIndex().field_index())); | 4138 lookup->GetFieldIndex().field_index())); |
| 3975 storage->set_value(value->Number()); | 4139 storage->set_value(value->Number()); |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 3991 } | 4155 } |
| 3992 | 4156 |
| 3993 if (!object->HasFastProperties()) { | 4157 if (!object->HasFastProperties()) { |
| 3994 ReplaceSlowProperty(object, name, value, attributes); | 4158 ReplaceSlowProperty(object, name, value, attributes); |
| 3995 return; | 4159 return; |
| 3996 } | 4160 } |
| 3997 | 4161 |
| 3998 int descriptor_index = lookup->GetDescriptorIndex(); | 4162 int descriptor_index = lookup->GetDescriptorIndex(); |
| 3999 if (lookup->GetAttributes() == attributes) { | 4163 if (lookup->GetAttributes() == attributes) { |
| 4000 JSObject::GeneralizeFieldRepresentation( | 4164 JSObject::GeneralizeFieldRepresentation( |
| 4001 object, descriptor_index, Representation::Tagged(), FORCE_FIELD); | 4165 object, descriptor_index, Representation::Tagged(), |
| 4166 HeapType::Any(lookup->isolate()), FORCE_FIELD); | |
| 4002 } else { | 4167 } else { |
| 4003 Handle<Map> old_map(object->map()); | 4168 Handle<Map> old_map(object->map()); |
| 4004 Handle<Map> new_map = Map::CopyGeneralizeAllRepresentations(old_map, | 4169 Handle<Map> new_map = Map::CopyGeneralizeAllRepresentations(old_map, |
| 4005 descriptor_index, FORCE_FIELD, attributes, "attributes mismatch"); | 4170 descriptor_index, FORCE_FIELD, attributes, "attributes mismatch"); |
| 4006 JSObject::MigrateToMap(object, new_map); | 4171 JSObject::MigrateToMap(object, new_map); |
| 4007 } | 4172 } |
| 4008 | 4173 |
| 4009 DescriptorArray* descriptors = object->map()->instance_descriptors(); | 4174 DescriptorArray* descriptors = object->map()->instance_descriptors(); |
| 4010 int index = descriptors->GetDetails(descriptor_index).field_index(); | 4175 int index = descriptors->GetDetails(descriptor_index).field_index(); |
| 4011 object->FastPropertyAtPut(index, *value); | 4176 object->FastPropertyAtPut(index, *value); |
| (...skipping 2821 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6833 | 6998 |
| 6834 Handle<Map> result = CopyDropDescriptors(map); | 6999 Handle<Map> result = CopyDropDescriptors(map); |
| 6835 result->InitializeDescriptors(*descriptors); | 7000 result->InitializeDescriptors(*descriptors); |
| 6836 | 7001 |
| 6837 if (flag == INSERT_TRANSITION && map->CanHaveMoreTransitions()) { | 7002 if (flag == INSERT_TRANSITION && map->CanHaveMoreTransitions()) { |
| 6838 Handle<TransitionArray> transitions = TransitionArray::CopyInsert( | 7003 Handle<TransitionArray> transitions = TransitionArray::CopyInsert( |
| 6839 map, name, result, simple_flag); | 7004 map, name, result, simple_flag); |
| 6840 map->set_transitions(*transitions); | 7005 map->set_transitions(*transitions); |
| 6841 result->SetBackPointer(*map); | 7006 result->SetBackPointer(*map); |
| 6842 } else { | 7007 } else { |
| 6843 descriptors->InitializeRepresentations(Representation::Tagged()); | 7008 int length = descriptors->number_of_descriptors(); |
| 7009 for (int i = 0; i < length; i++) { | |
| 7010 descriptors->SetRepresentation(i, Representation::Tagged()); | |
| 7011 if (descriptors->GetDetails(i).type() == FIELD) { | |
| 7012 descriptors->SetValue(i, HeapType::Any()); | |
| 7013 } | |
| 7014 } | |
| 6844 } | 7015 } |
| 6845 | 7016 |
| 6846 return result; | 7017 return result; |
| 6847 } | 7018 } |
| 6848 | 7019 |
| 6849 | 7020 |
| 6850 // Since this method is used to rewrite an existing transition tree, it can | 7021 // Since this method is used to rewrite an existing transition tree, it can |
| 6851 // always insert transitions without checking. | 7022 // always insert transitions without checking. |
| 6852 Handle<Map> Map::CopyInstallDescriptors(Handle<Map> map, | 7023 Handle<Map> Map::CopyInstallDescriptors(Handle<Map> map, |
| 6853 int new_descriptor, | 7024 int new_descriptor, |
| (...skipping 1136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7990 int valid, | 8161 int valid, |
| 7991 int new_size, | 8162 int new_size, |
| 7992 int modify_index, | 8163 int modify_index, |
| 7993 StoreMode store_mode, | 8164 StoreMode store_mode, |
| 7994 Handle<Map> right_map) { | 8165 Handle<Map> right_map) { |
| 7995 ASSERT(verbatim <= valid); | 8166 ASSERT(verbatim <= valid); |
| 7996 ASSERT(valid <= new_size); | 8167 ASSERT(valid <= new_size); |
| 7997 | 8168 |
| 7998 // Allocate a new descriptor array large enough to hold the required | 8169 // Allocate a new descriptor array large enough to hold the required |
| 7999 // descriptors, with minimally the exact same size as this descriptor array. | 8170 // descriptors, with minimally the exact same size as this descriptor array. |
| 8000 Factory* factory = left_map->GetIsolate()->factory(); | 8171 Isolate* isolate = left_map->GetIsolate(); |
| 8001 Handle<DescriptorArray> left(left_map->instance_descriptors()); | 8172 Handle<DescriptorArray> left(left_map->instance_descriptors()); |
| 8002 Handle<DescriptorArray> right(right_map->instance_descriptors()); | 8173 Handle<DescriptorArray> right(right_map->instance_descriptors()); |
| 8003 Handle<DescriptorArray> result = factory->NewDescriptorArray( | 8174 Handle<DescriptorArray> result = isolate->factory()->NewDescriptorArray( |
| 8004 new_size, Max(new_size, right->number_of_descriptors()) - new_size); | 8175 new_size, Max(new_size, right->number_of_descriptors()) - new_size); |
| 8005 ASSERT(result->length() > left->length() || | 8176 ASSERT(result->length() > left->length() || |
| 8006 result->NumberOfSlackDescriptors() > 0 || | 8177 result->NumberOfSlackDescriptors() > 0 || |
| 8007 result->number_of_descriptors() == right->number_of_descriptors()); | 8178 result->number_of_descriptors() == right->number_of_descriptors()); |
| 8008 ASSERT(result->number_of_descriptors() == new_size); | 8179 ASSERT(result->number_of_descriptors() == new_size); |
| 8009 | 8180 |
| 8010 int descriptor; | 8181 int descriptor; |
| 8011 | 8182 |
| 8012 // 0 -> |verbatim| | 8183 // 0 -> |verbatim| |
| 8013 int current_offset = 0; | 8184 int current_offset = 0; |
| 8014 for (descriptor = 0; descriptor < verbatim; descriptor++) { | 8185 for (descriptor = 0; descriptor < verbatim; descriptor++) { |
| 8015 if (left->GetDetails(descriptor).type() == FIELD) current_offset++; | 8186 if (left->GetDetails(descriptor).type() == FIELD) current_offset++; |
| 8016 Descriptor d(handle(right->GetKey(descriptor)), | 8187 Descriptor d(handle(right->GetKey(descriptor)), |
| 8017 handle(right->GetValue(descriptor), right->GetIsolate()), | 8188 handle(right->GetValue(descriptor), right->GetIsolate()), |
| 8018 right->GetDetails(descriptor)); | 8189 right->GetDetails(descriptor)); |
| 8019 result->Set(descriptor, &d); | 8190 result->Set(descriptor, &d); |
| 8020 } | 8191 } |
| 8021 | 8192 |
| 8022 // |verbatim| -> |valid| | 8193 // |verbatim| -> |valid| |
| 8023 for (; descriptor < valid; descriptor++) { | 8194 for (; descriptor < valid; descriptor++) { |
| 8024 PropertyDetails left_details = left->GetDetails(descriptor); | 8195 PropertyDetails left_details = left->GetDetails(descriptor); |
| 8025 PropertyDetails right_details = right->GetDetails(descriptor); | 8196 PropertyDetails right_details = right->GetDetails(descriptor); |
| 8026 if (left_details.type() == FIELD || right_details.type() == FIELD || | 8197 if (left_details.type() == FIELD || right_details.type() == FIELD || |
| 8027 (store_mode == FORCE_FIELD && descriptor == modify_index) || | 8198 (store_mode == FORCE_FIELD && descriptor == modify_index) || |
| 8028 (left_details.type() == CONSTANT && | 8199 (left_details.type() == CONSTANT && |
| 8029 right_details.type() == CONSTANT && | 8200 right_details.type() == CONSTANT && |
| 8030 left->GetValue(descriptor) != right->GetValue(descriptor))) { | 8201 left->GetValue(descriptor) != right->GetValue(descriptor))) { |
| 8202 ASSERT(left_details.type() == CONSTANT || left_details.type() == FIELD); | |
| 8203 ASSERT(right_details.type() == CONSTANT || right_details.type() == FIELD); | |
| 8031 Representation representation = left_details.representation().generalize( | 8204 Representation representation = left_details.representation().generalize( |
| 8032 right_details.representation()); | 8205 right_details.representation()); |
| 8033 FieldDescriptor d(handle(left->GetKey(descriptor)), | 8206 Handle<HeapType> left_type = (left_details.type() == FIELD) |
| 8207 ? handle(left->GetFieldType(descriptor), isolate) | |
| 8208 : left->GetValue(descriptor)->OptimalType(isolate, representation); | |
| 8209 Handle<HeapType> right_type = (right_details.type() == FIELD) | |
| 8210 ? handle(right->GetFieldType(descriptor), isolate) | |
| 8211 : right->GetValue(descriptor)->OptimalType(isolate, representation); | |
| 8212 Handle<HeapType> field_type; | |
| 8213 if (right_type->NowIs(left_type)) { | |
|
Toon Verwaest
2014/04/11 12:49:43
Same generalize logic would apply here
Benedikt Meurer
2014/04/14 06:29:04
Done.
| |
| 8214 field_type = left_type; | |
| 8215 } else if (left_type->NowIs(right_type)) { | |
| 8216 field_type = right_type; | |
| 8217 } else { | |
| 8218 field_type = HeapType::Any(isolate); | |
| 8219 } | |
| 8220 FieldDescriptor d(handle(left->GetKey(descriptor), isolate), | |
| 8034 current_offset++, | 8221 current_offset++, |
| 8222 field_type, | |
| 8035 right_details.attributes(), | 8223 right_details.attributes(), |
| 8036 representation); | 8224 representation); |
| 8037 result->Set(descriptor, &d); | 8225 result->Set(descriptor, &d); |
| 8038 } else { | 8226 } else { |
| 8039 Descriptor d(handle(right->GetKey(descriptor)), | 8227 Descriptor d(handle(right->GetKey(descriptor), isolate), |
| 8040 handle(right->GetValue(descriptor), right->GetIsolate()), | 8228 handle(right->GetValue(descriptor), isolate), |
| 8041 right_details); | 8229 right_details); |
| 8042 result->Set(descriptor, &d); | 8230 result->Set(descriptor, &d); |
| 8043 } | 8231 } |
| 8044 } | 8232 } |
| 8045 | 8233 |
| 8046 // |valid| -> |new_size| | 8234 // |valid| -> |new_size| |
| 8047 for (; descriptor < new_size; descriptor++) { | 8235 for (; descriptor < new_size; descriptor++) { |
| 8048 PropertyDetails right_details = right->GetDetails(descriptor); | 8236 PropertyDetails right_details = right->GetDetails(descriptor); |
| 8049 if (right_details.type() == FIELD || | 8237 if (right_details.type() == FIELD) { |
| 8050 (store_mode == FORCE_FIELD && descriptor == modify_index)) { | 8238 FieldDescriptor d(handle(right->GetKey(descriptor), isolate), |
| 8051 FieldDescriptor d(handle(right->GetKey(descriptor)), | |
| 8052 current_offset++, | 8239 current_offset++, |
| 8240 handle(right->GetFieldType(descriptor), isolate), | |
| 8053 right_details.attributes(), | 8241 right_details.attributes(), |
| 8054 right_details.representation()); | 8242 right_details.representation()); |
| 8055 result->Set(descriptor, &d); | 8243 result->Set(descriptor, &d); |
| 8244 } else if (store_mode == FORCE_FIELD && descriptor == modify_index) { | |
| 8245 ASSERT_EQ(CONSTANT, right_details.type()); | |
| 8246 Representation field_representation = right_details.representation(); | |
| 8247 Handle<HeapType> field_type = right->GetValue(descriptor)->OptimalType( | |
| 8248 isolate, field_representation); | |
| 8249 FieldDescriptor d(handle(right->GetKey(descriptor), isolate), | |
| 8250 current_offset++, | |
| 8251 field_type, | |
| 8252 right_details.attributes(), | |
| 8253 field_representation); | |
| 8254 result->Set(descriptor, &d); | |
| 8056 } else { | 8255 } else { |
| 8057 Descriptor d(handle(right->GetKey(descriptor)), | 8256 Descriptor d(handle(right->GetKey(descriptor), isolate), |
| 8058 handle(right->GetValue(descriptor), right->GetIsolate()), | 8257 handle(right->GetValue(descriptor), isolate), |
| 8059 right_details); | 8258 right_details); |
| 8060 result->Set(descriptor, &d); | 8259 result->Set(descriptor, &d); |
| 8061 } | 8260 } |
| 8062 } | 8261 } |
| 8063 | 8262 |
| 8064 result->Sort(); | 8263 result->Sort(); |
| 8065 return result; | 8264 return result; |
| 8066 } | 8265 } |
| 8067 | 8266 |
| 8068 | 8267 |
| (...skipping 8539 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 16608 #define ERROR_MESSAGES_TEXTS(C, T) T, | 16807 #define ERROR_MESSAGES_TEXTS(C, T) T, |
| 16609 static const char* error_messages_[] = { | 16808 static const char* error_messages_[] = { |
| 16610 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) | 16809 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) |
| 16611 }; | 16810 }; |
| 16612 #undef ERROR_MESSAGES_TEXTS | 16811 #undef ERROR_MESSAGES_TEXTS |
| 16613 return error_messages_[reason]; | 16812 return error_messages_[reason]; |
| 16614 } | 16813 } |
| 16615 | 16814 |
| 16616 | 16815 |
| 16617 } } // namespace v8::internal | 16816 } } // namespace v8::internal |
| OLD | NEW |