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 1432 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1443 PrintF(file, " from "); | 1443 PrintF(file, " from "); |
1444 from_elements->ShortPrint(file); | 1444 from_elements->ShortPrint(file); |
1445 PrintF(file, " to "); | 1445 PrintF(file, " to "); |
1446 to_elements->ShortPrint(file); | 1446 to_elements->ShortPrint(file); |
1447 PrintF(file, "\n"); | 1447 PrintF(file, "\n"); |
1448 } | 1448 } |
1449 } | 1449 } |
1450 | 1450 |
1451 | 1451 |
1452 void Map::PrintGeneralization(FILE* file, | 1452 void Map::PrintGeneralization(FILE* file, |
| 1453 const char* reason, |
1453 int modify_index, | 1454 int modify_index, |
1454 int split, | 1455 int split, |
1455 int descriptors, | 1456 int descriptors, |
| 1457 bool constant_to_field, |
1456 Representation old_representation, | 1458 Representation old_representation, |
1457 Representation new_representation) { | 1459 Representation new_representation) { |
1458 PrintF(file, "[generalizing "); | 1460 PrintF(file, "[generalizing "); |
1459 constructor_name()->PrintOn(file); | 1461 constructor_name()->PrintOn(file); |
1460 PrintF(file, "] "); | 1462 PrintF(file, "] "); |
1461 String::cast(instance_descriptors()->GetKey(modify_index))->PrintOn(file); | 1463 String::cast(instance_descriptors()->GetKey(modify_index))->PrintOn(file); |
1462 PrintF(file, ":%s->%s (+%i maps) [", | 1464 if (constant_to_field) { |
1463 old_representation.Mnemonic(), | 1465 PrintF(file, ":c->f"); |
1464 new_representation.Mnemonic(), | 1466 } else { |
1465 descriptors - split); | 1467 PrintF(file, ":%s->%s", |
| 1468 old_representation.Mnemonic(), |
| 1469 new_representation.Mnemonic()); |
| 1470 } |
| 1471 PrintF(file, " ("); |
| 1472 if (strlen(reason) > 0) { |
| 1473 PrintF(file, "%s", reason); |
| 1474 } else { |
| 1475 PrintF(file, "+%i maps", descriptors - split); |
| 1476 } |
| 1477 PrintF(file, ") ["); |
1466 JavaScriptFrame::PrintTop(GetIsolate(), file, false, true); | 1478 JavaScriptFrame::PrintTop(GetIsolate(), file, false, true); |
1467 PrintF(file, "]\n"); | 1479 PrintF(file, "]\n"); |
1468 } | 1480 } |
1469 | 1481 |
1470 | 1482 |
1471 void JSObject::PrintInstanceMigration(FILE* file, | 1483 void JSObject::PrintInstanceMigration(FILE* file, |
1472 Map* original_map, | 1484 Map* original_map, |
1473 Map* new_map) { | 1485 Map* new_map) { |
1474 PrintF(file, "[migrating "); | 1486 PrintF(file, "[migrating "); |
1475 map()->constructor_name()->PrintOn(file); | 1487 map()->constructor_name()->PrintOn(file); |
(...skipping 505 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1981 | 1993 |
1982 | 1994 |
1983 MaybeObject* JSObject::AddConstantProperty( | 1995 MaybeObject* JSObject::AddConstantProperty( |
1984 Name* name, | 1996 Name* name, |
1985 Object* constant, | 1997 Object* constant, |
1986 PropertyAttributes attributes) { | 1998 PropertyAttributes attributes) { |
1987 // Allocate new instance descriptors with (name, constant) added | 1999 // Allocate new instance descriptors with (name, constant) added |
1988 ConstantDescriptor d(name, constant, attributes); | 2000 ConstantDescriptor d(name, constant, attributes); |
1989 | 2001 |
1990 TransitionFlag flag = | 2002 TransitionFlag flag = |
1991 // Do not add transitions to global objects. | 2003 // Do not add transitions to global objects. |
1992 (IsGlobalObject() || | 2004 (IsGlobalObject() || |
1993 // Don't add transitions to special properties with non-trivial | 2005 // Don't add transitions to special properties with non-trivial |
1994 // attributes. | 2006 // attributes. |
1995 attributes != NONE) | 2007 attributes != NONE) |
1996 ? OMIT_TRANSITION | 2008 ? OMIT_TRANSITION |
1997 : INSERT_TRANSITION; | 2009 : INSERT_TRANSITION; |
1998 | 2010 |
1999 Map* new_map; | 2011 Map* new_map; |
2000 MaybeObject* maybe_new_map = map()->CopyAddDescriptor(&d, flag); | 2012 MaybeObject* maybe_new_map = map()->CopyAddDescriptor(&d, flag); |
2001 if (!maybe_new_map->To(&new_map)) return maybe_new_map; | 2013 if (!maybe_new_map->To(&new_map)) return maybe_new_map; |
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2183 if (old_index != -1) { | 2195 if (old_index != -1) { |
2184 // All calls to ReplaceSlowProperty have had all transitions removed. | 2196 // All calls to ReplaceSlowProperty have had all transitions removed. |
2185 new_enumeration_index = dictionary->DetailsAt(old_index).dictionary_index(); | 2197 new_enumeration_index = dictionary->DetailsAt(old_index).dictionary_index(); |
2186 } | 2198 } |
2187 | 2199 |
2188 PropertyDetails new_details(attributes, NORMAL, new_enumeration_index); | 2200 PropertyDetails new_details(attributes, NORMAL, new_enumeration_index); |
2189 return SetNormalizedProperty(name, value, new_details); | 2201 return SetNormalizedProperty(name, value, new_details); |
2190 } | 2202 } |
2191 | 2203 |
2192 | 2204 |
2193 MaybeObject* JSObject::ConvertTransitionToMapTransition( | |
2194 int transition_index, | |
2195 Name* name, | |
2196 Object* new_value, | |
2197 PropertyAttributes attributes) { | |
2198 Map* old_map = map(); | |
2199 Map* old_target = old_map->GetTransition(transition_index); | |
2200 Object* result; | |
2201 | |
2202 MaybeObject* maybe_result = ConvertDescriptorToField( | |
2203 name, new_value, attributes, OMIT_TRANSITION_KEEP_REPRESENTATIONS); | |
2204 if (!maybe_result->To(&result)) return maybe_result; | |
2205 | |
2206 if (!HasFastProperties()) return result; | |
2207 | |
2208 // This method should only be used to convert existing transitions. | |
2209 Map* new_map = map(); | |
2210 | |
2211 // TODO(verwaest): From here on we lose existing map transitions, causing | |
2212 // invalid back pointers. This will change once we can store multiple | |
2213 // transitions with the same key. | |
2214 bool owned_descriptors = old_map->owns_descriptors(); | |
2215 if (owned_descriptors || | |
2216 old_target->instance_descriptors() == old_map->instance_descriptors()) { | |
2217 // Since the conversion above generated a new fast map with an additional | |
2218 // property which can be shared as well, install this descriptor pointer | |
2219 // along the entire chain of smaller maps. | |
2220 Map* map; | |
2221 DescriptorArray* new_descriptors = new_map->instance_descriptors(); | |
2222 DescriptorArray* old_descriptors = old_map->instance_descriptors(); | |
2223 for (Object* current = old_map; | |
2224 !current->IsUndefined(); | |
2225 current = map->GetBackPointer()) { | |
2226 map = Map::cast(current); | |
2227 if (map->instance_descriptors() != old_descriptors) break; | |
2228 map->SetEnumLength(Map::kInvalidEnumCache); | |
2229 map->set_instance_descriptors(new_descriptors); | |
2230 } | |
2231 old_map->set_owns_descriptors(false); | |
2232 } | |
2233 | |
2234 old_target->DeprecateTransitionTree(); | |
2235 | |
2236 old_map->SetTransition(transition_index, new_map); | |
2237 new_map->SetBackPointer(old_map); | |
2238 return result; | |
2239 } | |
2240 | |
2241 | |
2242 MaybeObject* JSObject::ConvertDescriptorToField(Name* name, | 2205 MaybeObject* JSObject::ConvertDescriptorToField(Name* name, |
2243 Object* new_value, | 2206 Object* new_value, |
2244 PropertyAttributes attributes, | 2207 PropertyAttributes attributes, |
2245 TransitionFlag flag) { | 2208 TransitionFlag flag) { |
2246 if (map()->unused_property_fields() == 0 && | 2209 if (map()->unused_property_fields() == 0 && |
2247 TooManyFastProperties(properties()->length(), MAY_BE_STORE_FROM_KEYED)) { | 2210 TooManyFastProperties(properties()->length(), MAY_BE_STORE_FROM_KEYED)) { |
2248 Object* obj; | 2211 Object* obj; |
2249 MaybeObject* maybe_obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); | 2212 MaybeObject* maybe_obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); |
2250 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 2213 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
2251 return ReplaceSlowProperty(name, new_value, attributes); | 2214 return ReplaceSlowProperty(name, new_value, attributes); |
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2484 } | 2447 } |
2485 | 2448 |
2486 set_map(new_map); | 2449 set_map(new_map); |
2487 | 2450 |
2488 return this; | 2451 return this; |
2489 } | 2452 } |
2490 | 2453 |
2491 | 2454 |
2492 MaybeObject* JSObject::GeneralizeFieldRepresentation( | 2455 MaybeObject* JSObject::GeneralizeFieldRepresentation( |
2493 int modify_index, | 2456 int modify_index, |
2494 Representation new_representation) { | 2457 Representation new_representation, |
| 2458 StoreMode store_mode) { |
2495 Map* new_map; | 2459 Map* new_map; |
2496 MaybeObject* maybe_new_map = | 2460 MaybeObject* maybe_new_map = map()->GeneralizeRepresentation( |
2497 map()->GeneralizeRepresentation(modify_index, new_representation); | 2461 modify_index, new_representation, store_mode); |
2498 if (!maybe_new_map->To(&new_map)) return maybe_new_map; | 2462 if (!maybe_new_map->To(&new_map)) return maybe_new_map; |
2499 if (map() == new_map) return this; | 2463 if (map() == new_map) return this; |
2500 | 2464 |
2501 return MigrateToMap(new_map); | 2465 return MigrateToMap(new_map); |
2502 } | 2466 } |
2503 | 2467 |
2504 | 2468 |
2505 int Map::NumberOfFields() { | 2469 int Map::NumberOfFields() { |
2506 DescriptorArray* descriptors = instance_descriptors(); | 2470 DescriptorArray* descriptors = instance_descriptors(); |
2507 int result = 0; | 2471 int result = 0; |
2508 for (int i = 0; i < NumberOfOwnDescriptors(); i++) { | 2472 for (int i = 0; i < NumberOfOwnDescriptors(); i++) { |
2509 if (descriptors->GetDetails(i).type() == FIELD) result++; | 2473 if (descriptors->GetDetails(i).type() == FIELD) result++; |
2510 } | 2474 } |
2511 return result; | 2475 return result; |
2512 } | 2476 } |
2513 | 2477 |
2514 | 2478 |
2515 MaybeObject* Map::CopyGeneralizeAllRepresentations() { | 2479 MaybeObject* Map::CopyGeneralizeAllRepresentations( |
| 2480 int modify_index, |
| 2481 StoreMode store_mode, |
| 2482 const char* reason) { |
2516 Map* new_map; | 2483 Map* new_map; |
2517 MaybeObject* maybe_map = this->Copy(); | 2484 MaybeObject* maybe_map = this->Copy(); |
2518 if (!maybe_map->To(&new_map)) return maybe_map; | 2485 if (!maybe_map->To(&new_map)) return maybe_map; |
2519 | 2486 |
2520 new_map->instance_descriptors()->InitializeRepresentations( | 2487 DescriptorArray* descriptors = new_map->instance_descriptors(); |
2521 Representation::Tagged()); | 2488 descriptors->InitializeRepresentations(Representation::Tagged()); |
| 2489 |
| 2490 // Unless the instance is being migrated, ensure that modify_index is a field. |
| 2491 PropertyDetails details = descriptors->GetDetails(modify_index); |
| 2492 if (store_mode == FORCE_FIELD && details.type() != FIELD) { |
| 2493 FieldDescriptor d(descriptors->GetKey(modify_index), |
| 2494 new_map->NumberOfFields(), |
| 2495 details.attributes(), |
| 2496 Representation::Tagged()); |
| 2497 d.SetSortedKeyIndex(details.pointer()); |
| 2498 descriptors->Set(modify_index, &d); |
| 2499 int unused_property_fields = new_map->unused_property_fields() - 1; |
| 2500 if (unused_property_fields < 0) { |
| 2501 unused_property_fields += JSObject::kFieldsAdded; |
| 2502 } |
| 2503 new_map->set_unused_property_fields(unused_property_fields); |
| 2504 } |
| 2505 |
2522 if (FLAG_trace_generalization) { | 2506 if (FLAG_trace_generalization) { |
2523 PrintF("failed generalization %p -> %p\n", | 2507 PrintGeneralization(stdout, reason, modify_index, |
2524 static_cast<void*>(this), static_cast<void*>(new_map)); | 2508 new_map->NumberOfOwnDescriptors(), |
| 2509 new_map->NumberOfOwnDescriptors(), |
| 2510 details.type() == CONSTANT && store_mode == FORCE_FIELD, |
| 2511 Representation::Tagged(), Representation::Tagged()); |
2525 } | 2512 } |
2526 return new_map; | 2513 return new_map; |
2527 } | 2514 } |
2528 | 2515 |
2529 | 2516 |
2530 void Map::DeprecateTransitionTree() { | 2517 void Map::DeprecateTransitionTree() { |
2531 if (!FLAG_track_fields) return; | 2518 if (!FLAG_track_fields) return; |
2532 if (is_deprecated()) return; | 2519 if (is_deprecated()) return; |
2533 if (HasTransitionArray()) { | 2520 if (HasTransitionArray()) { |
2534 TransitionArray* transitions = this->transitions(); | 2521 TransitionArray* transitions = this->transitions(); |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2659 // walk the transition tree. | 2646 // walk the transition tree. |
2660 // - Merge/generalize the descriptor array of the current map and |updated|. | 2647 // - Merge/generalize the descriptor array of the current map and |updated|. |
2661 // - Generalize the |modify_index| descriptor using |new_representation|. | 2648 // - Generalize the |modify_index| descriptor using |new_representation|. |
2662 // - Walk the tree again starting from the root towards |updated|. Stop at | 2649 // - Walk the tree again starting from the root towards |updated|. Stop at |
2663 // |split_map|, the first map who's descriptor array does not match the merged | 2650 // |split_map|, the first map who's descriptor array does not match the merged |
2664 // descriptor array. | 2651 // descriptor array. |
2665 // - If |updated| == |split_map|, |updated| is in the expected state. Return it. | 2652 // - If |updated| == |split_map|, |updated| is in the expected state. Return it. |
2666 // - Otherwise, invalidate the outdated transition target from |updated|, and | 2653 // - Otherwise, invalidate the outdated transition target from |updated|, and |
2667 // replace its transition tree with a new branch for the updated descriptors. | 2654 // replace its transition tree with a new branch for the updated descriptors. |
2668 MaybeObject* Map::GeneralizeRepresentation(int modify_index, | 2655 MaybeObject* Map::GeneralizeRepresentation(int modify_index, |
2669 Representation new_representation) { | 2656 Representation new_representation, |
| 2657 StoreMode store_mode) { |
2670 Map* old_map = this; | 2658 Map* old_map = this; |
2671 DescriptorArray* old_descriptors = old_map->instance_descriptors(); | 2659 DescriptorArray* old_descriptors = old_map->instance_descriptors(); |
2672 Representation old_representation = | 2660 Representation old_representation = |
2673 old_descriptors->GetDetails(modify_index).representation(); | 2661 old_descriptors->GetDetails(modify_index).representation(); |
2674 | 2662 |
2675 // It's fine to transition from None to anything but double without any | 2663 // It's fine to transition from None to anything but double without any |
2676 // modification to the object, because the default uninitialized value for | 2664 // modification to the object, because the default uninitialized value for |
2677 // representation None can be overwritten by both smi and tagged values. | 2665 // representation None can be overwritten by both smi and tagged values. |
2678 // Doubles, however, would require a box allocation. | 2666 // Doubles, however, would require a box allocation. |
2679 if (old_representation.IsNone() && | 2667 if (old_representation.IsNone() && |
2680 !new_representation.IsNone() && | 2668 !new_representation.IsNone() && |
2681 !new_representation.IsDouble()) { | 2669 !new_representation.IsDouble()) { |
2682 old_descriptors->SetRepresentation(modify_index, new_representation); | 2670 old_descriptors->SetRepresentation(modify_index, new_representation); |
2683 return old_map; | 2671 return old_map; |
2684 } | 2672 } |
2685 | 2673 |
2686 int descriptors = old_map->NumberOfOwnDescriptors(); | 2674 int descriptors = old_map->NumberOfOwnDescriptors(); |
2687 Map* root_map = old_map->FindRootMap(); | 2675 Map* root_map = old_map->FindRootMap(); |
2688 | 2676 |
2689 // Check the state of the root map. | 2677 // Check the state of the root map. |
2690 if (!old_map->EquivalentToForTransition(root_map)) { | 2678 if (!old_map->EquivalentToForTransition(root_map)) { |
2691 return CopyGeneralizeAllRepresentations(); | 2679 return CopyGeneralizeAllRepresentations( |
| 2680 modify_index, store_mode, "not equivalent"); |
2692 } | 2681 } |
2693 | 2682 |
2694 int verbatim = root_map->NumberOfOwnDescriptors(); | 2683 int verbatim = root_map->NumberOfOwnDescriptors(); |
2695 | 2684 |
| 2685 if (store_mode != ALLOW_AS_CONSTANT && modify_index < verbatim) { |
| 2686 return CopyGeneralizeAllRepresentations( |
| 2687 modify_index, store_mode, "root modification"); |
| 2688 } |
| 2689 |
2696 Map* updated = root_map->FindUpdatedMap( | 2690 Map* updated = root_map->FindUpdatedMap( |
2697 verbatim, descriptors, old_descriptors); | 2691 verbatim, descriptors, old_descriptors); |
2698 if (updated == NULL) return CopyGeneralizeAllRepresentations(); | 2692 if (updated == NULL) { |
| 2693 return CopyGeneralizeAllRepresentations( |
| 2694 modify_index, store_mode, "incompatible"); |
| 2695 } |
2699 | 2696 |
2700 DescriptorArray* updated_descriptors = updated->instance_descriptors(); | 2697 DescriptorArray* updated_descriptors = updated->instance_descriptors(); |
2701 | 2698 |
2702 int valid = updated->NumberOfOwnDescriptors(); | 2699 int valid = updated->NumberOfOwnDescriptors(); |
| 2700 |
| 2701 // Directly change the map if the target map is more general. Ensure that the |
| 2702 // target type of the modify_index is a FIELD, unless we are migrating. |
2703 if (updated_descriptors->IsMoreGeneralThan( | 2703 if (updated_descriptors->IsMoreGeneralThan( |
2704 verbatim, valid, descriptors, old_descriptors)) { | 2704 verbatim, valid, descriptors, old_descriptors) && |
| 2705 (store_mode == ALLOW_AS_CONSTANT || |
| 2706 updated_descriptors->GetDetails(modify_index).type() == FIELD)) { |
2705 Representation updated_representation = | 2707 Representation updated_representation = |
2706 updated_descriptors->GetDetails(modify_index).representation(); | 2708 updated_descriptors->GetDetails(modify_index).representation(); |
2707 if (new_representation.fits_into(updated_representation)) { | 2709 if (new_representation.fits_into(updated_representation)) return updated; |
2708 if (FLAG_trace_generalization && | |
2709 !(modify_index == 0 && new_representation.IsNone())) { | |
2710 PropertyDetails old_details = old_descriptors->GetDetails(modify_index); | |
2711 PrintGeneralization(stdout, modify_index, descriptors, descriptors, | |
2712 old_details.representation(), | |
2713 updated_representation); | |
2714 } | |
2715 return updated; | |
2716 } | |
2717 } | 2710 } |
2718 | 2711 |
2719 DescriptorArray* new_descriptors; | 2712 DescriptorArray* new_descriptors; |
2720 MaybeObject* maybe_descriptors = updated_descriptors->Merge( | 2713 MaybeObject* maybe_descriptors = updated_descriptors->Merge( |
2721 verbatim, valid, descriptors, old_descriptors); | 2714 verbatim, valid, descriptors, modify_index, store_mode, old_descriptors); |
2722 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; | 2715 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; |
| 2716 ASSERT(store_mode == ALLOW_AS_CONSTANT || |
| 2717 new_descriptors->GetDetails(modify_index).type() == FIELD); |
2723 | 2718 |
2724 old_representation = | 2719 old_representation = |
2725 new_descriptors->GetDetails(modify_index).representation(); | 2720 new_descriptors->GetDetails(modify_index).representation(); |
2726 Representation updated_representation = | 2721 Representation updated_representation = |
2727 new_representation.generalize(old_representation); | 2722 new_representation.generalize(old_representation); |
2728 if (!updated_representation.Equals(old_representation)) { | 2723 if (!updated_representation.Equals(old_representation)) { |
2729 new_descriptors->SetRepresentation(modify_index, updated_representation); | 2724 new_descriptors->SetRepresentation(modify_index, updated_representation); |
2730 } | 2725 } |
2731 | 2726 |
2732 Map* split_map = root_map->FindLastMatchMap( | 2727 Map* split_map = root_map->FindLastMatchMap( |
2733 verbatim, descriptors, new_descriptors); | 2728 verbatim, descriptors, new_descriptors); |
2734 | 2729 |
2735 int split_descriptors = split_map->NumberOfOwnDescriptors(); | 2730 int split_descriptors = split_map->NumberOfOwnDescriptors(); |
2736 // This is shadowed by |updated_descriptors| being more general than | 2731 // This is shadowed by |updated_descriptors| being more general than |
2737 // |old_descriptors|. | 2732 // |old_descriptors|. |
2738 ASSERT(descriptors != split_descriptors); | 2733 ASSERT(descriptors != split_descriptors); |
2739 | 2734 |
2740 int descriptor = split_descriptors; | 2735 int descriptor = split_descriptors; |
2741 split_map->DeprecateTarget( | 2736 split_map->DeprecateTarget( |
2742 old_descriptors->GetKey(descriptor), new_descriptors); | 2737 old_descriptors->GetKey(descriptor), new_descriptors); |
2743 | 2738 |
2744 if (FLAG_trace_generalization && | 2739 if (FLAG_trace_generalization && store_mode != ALLOW_AS_CONSTANT) { |
2745 !(modify_index == 0 && new_representation.IsNone())) { | 2740 PrintGeneralization( |
2746 PrintGeneralization(stdout, modify_index, descriptor, descriptors, | 2741 stdout, "", modify_index, descriptor, descriptors, |
2747 old_representation, updated_representation); | 2742 old_descriptors->GetDetails(modify_index).type() == CONSTANT, |
| 2743 old_representation, updated_representation); |
2748 } | 2744 } |
2749 | 2745 |
2750 Map* new_map = split_map; | 2746 Map* new_map = split_map; |
2751 // Add missing transitions. | 2747 // Add missing transitions. |
2752 for (; descriptor < descriptors; descriptor++) { | 2748 for (; descriptor < descriptors; descriptor++) { |
2753 MaybeObject* maybe_map = new_map->CopyInstallDescriptors( | 2749 MaybeObject* maybe_map = new_map->CopyInstallDescriptors( |
2754 descriptor, new_descriptors); | 2750 descriptor, new_descriptors); |
2755 if (!maybe_map->To(&new_map)) { | 2751 if (!maybe_map->To(&new_map)) { |
2756 // Create a handle for the last created map to ensure it stays alive | 2752 // Create a handle for the last created map to ensure it stays alive |
2757 // during GC. Its descriptor array is too large, but it will be | 2753 // during GC. Its descriptor array is too large, but it will be |
(...skipping 1017 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3775 Handle<Object> JSObject::TryMigrateInstance(Handle<JSObject> object) { | 3771 Handle<Object> JSObject::TryMigrateInstance(Handle<JSObject> object) { |
3776 CALL_HEAP_FUNCTION( | 3772 CALL_HEAP_FUNCTION( |
3777 object->GetIsolate(), | 3773 object->GetIsolate(), |
3778 object->MigrateInstance(), | 3774 object->MigrateInstance(), |
3779 Object); | 3775 Object); |
3780 } | 3776 } |
3781 | 3777 |
3782 | 3778 |
3783 Handle<Map> Map::GeneralizeRepresentation(Handle<Map> map, | 3779 Handle<Map> Map::GeneralizeRepresentation(Handle<Map> map, |
3784 int modify_index, | 3780 int modify_index, |
3785 Representation representation) { | 3781 Representation representation, |
| 3782 StoreMode store_mode) { |
3786 CALL_HEAP_FUNCTION( | 3783 CALL_HEAP_FUNCTION( |
3787 map->GetIsolate(), | 3784 map->GetIsolate(), |
3788 map->GeneralizeRepresentation(modify_index, representation), | 3785 map->GeneralizeRepresentation(modify_index, representation, store_mode), |
3789 Map); | 3786 Map); |
3790 } | 3787 } |
3791 | 3788 |
3792 | 3789 |
| 3790 static MaybeObject* SetPropertyUsingTransition(LookupResult* lookup, |
| 3791 Handle<Name> name, |
| 3792 Handle<Object> value, |
| 3793 PropertyAttributes attributes) { |
| 3794 Map* transition_map = lookup->GetTransitionTarget(); |
| 3795 int descriptor = transition_map->LastAdded(); |
| 3796 |
| 3797 DescriptorArray* descriptors = transition_map->instance_descriptors(); |
| 3798 PropertyDetails details = descriptors->GetDetails(descriptor); |
| 3799 |
| 3800 if (details.type() == CALLBACKS || attributes != details.attributes()) { |
| 3801 return lookup->holder()->ConvertDescriptorToField( |
| 3802 *name, *value, attributes); |
| 3803 } |
| 3804 |
| 3805 // Keep the target CONSTANT if the same value is stored. |
| 3806 // TODO(verwaest): Also support keeping the placeholder |
| 3807 // (value->IsUninitialized) as constant. |
| 3808 if (details.type() == CONSTANT && |
| 3809 descriptors->GetValue(descriptor) == *value) { |
| 3810 lookup->holder()->set_map(transition_map); |
| 3811 return *value; |
| 3812 } |
| 3813 |
| 3814 Representation representation = details.representation(); |
| 3815 |
| 3816 if (!value->FitsRepresentation(representation) || |
| 3817 details.type() == CONSTANT) { |
| 3818 MaybeObject* maybe_map = transition_map->GeneralizeRepresentation( |
| 3819 descriptor, value->OptimalRepresentation(), FORCE_FIELD); |
| 3820 if (!maybe_map->To(&transition_map)) return maybe_map; |
| 3821 Object* back = transition_map->GetBackPointer(); |
| 3822 if (back->IsMap()) { |
| 3823 MaybeObject* maybe_failure = |
| 3824 lookup->holder()->MigrateToMap(Map::cast(back)); |
| 3825 if (maybe_failure->IsFailure()) return maybe_failure; |
| 3826 } |
| 3827 descriptors = transition_map->instance_descriptors(); |
| 3828 representation = descriptors->GetDetails(descriptor).representation(); |
| 3829 } |
| 3830 |
| 3831 int field_index = descriptors->GetFieldIndex(descriptor); |
| 3832 return lookup->holder()->AddFastPropertyUsingMap( |
| 3833 transition_map, *name, *value, field_index, representation); |
| 3834 } |
| 3835 |
| 3836 |
| 3837 static MaybeObject* SetPropertyToField(LookupResult* lookup, |
| 3838 Handle<Name> name, |
| 3839 Handle<Object> value) { |
| 3840 Representation representation = lookup->representation(); |
| 3841 if (!value->FitsRepresentation(representation) || |
| 3842 lookup->type() == CONSTANT) { |
| 3843 MaybeObject* maybe_failure = |
| 3844 lookup->holder()->GeneralizeFieldRepresentation( |
| 3845 lookup->GetDescriptorIndex(), |
| 3846 value->OptimalRepresentation(), |
| 3847 FORCE_FIELD); |
| 3848 if (maybe_failure->IsFailure()) return maybe_failure; |
| 3849 DescriptorArray* desc = lookup->holder()->map()->instance_descriptors(); |
| 3850 int descriptor = lookup->GetDescriptorIndex(); |
| 3851 representation = desc->GetDetails(descriptor).representation(); |
| 3852 } |
| 3853 |
| 3854 if (FLAG_track_double_fields && representation.IsDouble()) { |
| 3855 HeapNumber* storage = HeapNumber::cast(lookup->holder()->RawFastPropertyAt( |
| 3856 lookup->GetFieldIndex().field_index())); |
| 3857 storage->set_value(value->Number()); |
| 3858 return *value; |
| 3859 } |
| 3860 |
| 3861 lookup->holder()->FastPropertyAtPut( |
| 3862 lookup->GetFieldIndex().field_index(), *value); |
| 3863 return *value; |
| 3864 } |
| 3865 |
| 3866 |
3793 MaybeObject* JSObject::SetPropertyForResult(LookupResult* lookup, | 3867 MaybeObject* JSObject::SetPropertyForResult(LookupResult* lookup, |
3794 Name* name_raw, | 3868 Name* name_raw, |
3795 Object* value_raw, | 3869 Object* value_raw, |
3796 PropertyAttributes attributes, | 3870 PropertyAttributes attributes, |
3797 StrictModeFlag strict_mode, | 3871 StrictModeFlag strict_mode, |
3798 StoreFromKeyed store_mode) { | 3872 StoreFromKeyed store_mode) { |
3799 Heap* heap = GetHeap(); | 3873 Heap* heap = GetHeap(); |
3800 Isolate* isolate = heap->isolate(); | 3874 Isolate* isolate = heap->isolate(); |
3801 // Make sure that the top context does not change when doing callbacks or | 3875 // Make sure that the top context does not change when doing callbacks or |
3802 // interceptor calls. | 3876 // interceptor calls. |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3871 old_value = Object::GetProperty(self, name); | 3945 old_value = Object::GetProperty(self, name); |
3872 } | 3946 } |
3873 | 3947 |
3874 // This is a real property that is not read-only, or it is a | 3948 // This is a real property that is not read-only, or it is a |
3875 // transition or null descriptor and there are no setters in the prototypes. | 3949 // transition or null descriptor and there are no setters in the prototypes. |
3876 MaybeObject* result = *value; | 3950 MaybeObject* result = *value; |
3877 switch (lookup->type()) { | 3951 switch (lookup->type()) { |
3878 case NORMAL: | 3952 case NORMAL: |
3879 result = lookup->holder()->SetNormalizedProperty(lookup, *value); | 3953 result = lookup->holder()->SetNormalizedProperty(lookup, *value); |
3880 break; | 3954 break; |
3881 case FIELD: { | 3955 case FIELD: |
3882 Representation representation = lookup->representation(); | 3956 result = SetPropertyToField(lookup, name, value); |
3883 if (!value->FitsRepresentation(representation)) { | |
3884 MaybeObject* maybe_failure = | |
3885 lookup->holder()->GeneralizeFieldRepresentation( | |
3886 lookup->GetDescriptorIndex(), value->OptimalRepresentation()); | |
3887 if (maybe_failure->IsFailure()) return maybe_failure; | |
3888 DescriptorArray* desc = lookup->holder()->map()->instance_descriptors(); | |
3889 int descriptor = lookup->GetDescriptorIndex(); | |
3890 representation = desc->GetDetails(descriptor).representation(); | |
3891 } | |
3892 if (FLAG_track_double_fields && representation.IsDouble()) { | |
3893 HeapNumber* storage = | |
3894 HeapNumber::cast(lookup->holder()->RawFastPropertyAt( | |
3895 lookup->GetFieldIndex().field_index())); | |
3896 storage->set_value(value->Number()); | |
3897 result = *value; | |
3898 break; | |
3899 } | |
3900 lookup->holder()->FastPropertyAtPut( | |
3901 lookup->GetFieldIndex().field_index(), *value); | |
3902 result = *value; | |
3903 break; | 3957 break; |
3904 } | |
3905 case CONSTANT: | 3958 case CONSTANT: |
3906 // Only replace the constant if necessary. | 3959 // Only replace the constant if necessary. |
3907 if (*value == lookup->GetConstant()) return *value; | 3960 if (*value == lookup->GetConstant()) return *value; |
3908 // Preserve the attributes of this existing property. | 3961 result = SetPropertyToField(lookup, name, value); |
3909 attributes = lookup->GetAttributes(); | |
3910 result = lookup->holder()->ConvertDescriptorToField( | |
3911 *name, *value, attributes); | |
3912 break; | 3962 break; |
3913 case CALLBACKS: { | 3963 case CALLBACKS: { |
3914 Object* callback_object = lookup->GetCallbackObject(); | 3964 Object* callback_object = lookup->GetCallbackObject(); |
3915 return self->SetPropertyWithCallback( | 3965 return self->SetPropertyWithCallback( |
3916 callback_object, *name, *value, lookup->holder(), strict_mode); | 3966 callback_object, *name, *value, lookup->holder(), strict_mode); |
3917 } | 3967 } |
3918 case INTERCEPTOR: | 3968 case INTERCEPTOR: |
3919 result = lookup->holder()->SetPropertyWithInterceptor( | 3969 result = lookup->holder()->SetPropertyWithInterceptor( |
3920 *name, *value, attributes, strict_mode); | 3970 *name, *value, attributes, strict_mode); |
3921 break; | 3971 break; |
3922 case TRANSITION: { | 3972 case TRANSITION: { |
3923 Map* transition_map = lookup->GetTransitionTarget(); | 3973 result = SetPropertyUsingTransition(lookup, name, value, attributes); |
3924 int descriptor = transition_map->LastAdded(); | |
3925 | |
3926 DescriptorArray* descriptors = transition_map->instance_descriptors(); | |
3927 PropertyDetails details = descriptors->GetDetails(descriptor); | |
3928 | |
3929 if (details.type() == FIELD) { | |
3930 if (attributes == details.attributes()) { | |
3931 Representation representation = details.representation(); | |
3932 if (!value->FitsRepresentation(representation)) { | |
3933 MaybeObject* maybe_map = transition_map->GeneralizeRepresentation( | |
3934 descriptor, value->OptimalRepresentation()); | |
3935 if (!maybe_map->To(&transition_map)) return maybe_map; | |
3936 Object* back = transition_map->GetBackPointer(); | |
3937 if (back->IsMap()) { | |
3938 MaybeObject* maybe_failure = | |
3939 lookup->holder()->MigrateToMap(Map::cast(back)); | |
3940 if (maybe_failure->IsFailure()) return maybe_failure; | |
3941 } | |
3942 DescriptorArray* desc = transition_map->instance_descriptors(); | |
3943 int descriptor = transition_map->LastAdded(); | |
3944 representation = desc->GetDetails(descriptor).representation(); | |
3945 } | |
3946 int field_index = descriptors->GetFieldIndex(descriptor); | |
3947 result = lookup->holder()->AddFastPropertyUsingMap( | |
3948 transition_map, *name, *value, field_index, representation); | |
3949 } else { | |
3950 result = lookup->holder()->ConvertDescriptorToField( | |
3951 *name, *value, attributes); | |
3952 } | |
3953 } else if (details.type() == CALLBACKS) { | |
3954 result = lookup->holder()->ConvertDescriptorToField( | |
3955 *name, *value, attributes); | |
3956 } else { | |
3957 ASSERT(details.type() == CONSTANT); | |
3958 | |
3959 Object* constant = descriptors->GetValue(descriptor); | |
3960 if (constant == *value) { | |
3961 // If the same constant function is being added we can simply | |
3962 // transition to the target map. | |
3963 lookup->holder()->set_map(transition_map); | |
3964 result = constant; | |
3965 } else { | |
3966 // Otherwise, replace with a map transition to a new map with a FIELD, | |
3967 // even if the value is a constant function. | |
3968 result = lookup->holder()->ConvertTransitionToMapTransition( | |
3969 lookup->GetTransitionIndex(), *name, *value, attributes); | |
3970 } | |
3971 } | |
3972 break; | 3974 break; |
3973 } | 3975 } |
3974 case HANDLER: | 3976 case HANDLER: |
3975 case NONEXISTENT: | 3977 case NONEXISTENT: |
3976 UNREACHABLE(); | 3978 UNREACHABLE(); |
3977 } | 3979 } |
3978 | 3980 |
3979 Handle<Object> hresult; | 3981 Handle<Object> hresult; |
3980 if (!result->ToHandle(&hresult, isolate)) return result; | 3982 if (!result->ToHandle(&hresult, isolate)) return result; |
3981 | 3983 |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4081 } | 4083 } |
4082 | 4084 |
4083 // Check of IsReadOnly removed from here in clone. | 4085 // Check of IsReadOnly removed from here in clone. |
4084 MaybeObject* result = *value; | 4086 MaybeObject* result = *value; |
4085 switch (lookup.type()) { | 4087 switch (lookup.type()) { |
4086 case NORMAL: { | 4088 case NORMAL: { |
4087 PropertyDetails details = PropertyDetails(attributes, NORMAL, 0); | 4089 PropertyDetails details = PropertyDetails(attributes, NORMAL, 0); |
4088 result = self->SetNormalizedProperty(*name, *value, details); | 4090 result = self->SetNormalizedProperty(*name, *value, details); |
4089 break; | 4091 break; |
4090 } | 4092 } |
4091 case FIELD: { | 4093 case FIELD: |
4092 Representation representation = lookup.representation(); | 4094 if (value->IsUninitialized()) break; |
4093 Representation value_representation = | 4095 result = SetPropertyToField(&lookup, name, value); |
4094 value->OptimalRepresentation(value_type); | |
4095 if (value_representation.IsNone()) break; | |
4096 if (!value_representation.fits_into(representation)) { | |
4097 MaybeObject* maybe_failure = self->GeneralizeFieldRepresentation( | |
4098 lookup.GetDescriptorIndex(), value_representation); | |
4099 if (maybe_failure->IsFailure()) return maybe_failure; | |
4100 DescriptorArray* desc = self->map()->instance_descriptors(); | |
4101 int descriptor = lookup.GetDescriptorIndex(); | |
4102 representation = desc->GetDetails(descriptor).representation(); | |
4103 } | |
4104 if (FLAG_track_double_fields && representation.IsDouble()) { | |
4105 HeapNumber* storage = | |
4106 HeapNumber::cast(self->RawFastPropertyAt( | |
4107 lookup.GetFieldIndex().field_index())); | |
4108 storage->set_value(value->Number()); | |
4109 result = *value; | |
4110 break; | |
4111 } | |
4112 self->FastPropertyAtPut(lookup.GetFieldIndex().field_index(), *value); | |
4113 result = *value; | |
4114 break; | 4096 break; |
4115 } | |
4116 case CONSTANT: | 4097 case CONSTANT: |
4117 // Only replace the function if necessary. | 4098 // Only replace the constant if necessary. |
4118 if (*value != lookup.GetConstant()) { | 4099 if (*value == lookup.GetConstant()) return *value; |
4119 // Preserve the attributes of this existing property. | 4100 if (value->IsUninitialized()) break; |
4120 attributes = lookup.GetAttributes(); | 4101 result = SetPropertyToField(&lookup, name, value); |
4121 result = self->ConvertDescriptorToField(*name, *value, attributes); | |
4122 } | |
4123 break; | 4102 break; |
4124 case CALLBACKS: | 4103 case CALLBACKS: |
4125 case INTERCEPTOR: | 4104 case INTERCEPTOR: |
4126 // Override callback in clone | 4105 // Override callback in clone |
4127 result = self->ConvertDescriptorToField(*name, *value, attributes); | 4106 result = self->ConvertDescriptorToField(*name, *value, attributes); |
4128 break; | 4107 break; |
4129 case TRANSITION: { | 4108 case TRANSITION: |
4130 Map* transition_map = lookup.GetTransitionTarget(); | 4109 result = SetPropertyUsingTransition(&lookup, name, value, attributes); |
4131 int descriptor = transition_map->LastAdded(); | |
4132 | |
4133 DescriptorArray* descriptors = transition_map->instance_descriptors(); | |
4134 PropertyDetails details = descriptors->GetDetails(descriptor); | |
4135 | |
4136 if (details.type() == FIELD) { | |
4137 if (attributes == details.attributes()) { | |
4138 Representation representation = details.representation(); | |
4139 Representation value_representation = | |
4140 value->OptimalRepresentation(value_type); | |
4141 if (!value_representation.fits_into(representation)) { | |
4142 MaybeObject* maybe_map = transition_map->GeneralizeRepresentation( | |
4143 descriptor, value_representation); | |
4144 if (!maybe_map->To(&transition_map)) return maybe_map; | |
4145 Object* back = transition_map->GetBackPointer(); | |
4146 if (back->IsMap()) { | |
4147 MaybeObject* maybe_failure = self->MigrateToMap(Map::cast(back)); | |
4148 if (maybe_failure->IsFailure()) return maybe_failure; | |
4149 } | |
4150 DescriptorArray* desc = transition_map->instance_descriptors(); | |
4151 int descriptor = transition_map->LastAdded(); | |
4152 representation = desc->GetDetails(descriptor).representation(); | |
4153 } | |
4154 int field_index = descriptors->GetFieldIndex(descriptor); | |
4155 result = self->AddFastPropertyUsingMap( | |
4156 transition_map, *name, *value, field_index, representation); | |
4157 } else { | |
4158 result = self->ConvertDescriptorToField(*name, *value, attributes); | |
4159 } | |
4160 } else if (details.type() == CALLBACKS) { | |
4161 result = self->ConvertDescriptorToField(*name, *value, attributes); | |
4162 } else { | |
4163 ASSERT(details.type() == CONSTANT); | |
4164 | |
4165 // Replace transition to CONSTANT FUNCTION with a map transition to a | |
4166 // new map with a FIELD, even if the value is a function. | |
4167 result = self->ConvertTransitionToMapTransition( | |
4168 lookup.GetTransitionIndex(), *name, *value, attributes); | |
4169 } | |
4170 break; | 4110 break; |
4171 } | |
4172 case HANDLER: | 4111 case HANDLER: |
4173 case NONEXISTENT: | 4112 case NONEXISTENT: |
4174 UNREACHABLE(); | 4113 UNREACHABLE(); |
4175 } | 4114 } |
4176 | 4115 |
4177 Handle<Object> hresult; | 4116 Handle<Object> hresult; |
4178 if (!result->ToHandle(&hresult, isolate)) return result; | 4117 if (!result->ToHandle(&hresult, isolate)) return result; |
4179 | 4118 |
4180 if (is_observed) { | 4119 if (is_observed) { |
4181 if (lookup.IsTransition()) { | 4120 if (lookup.IsTransition()) { |
(...skipping 2486 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6668 if (!maybe_result->To(&result)) return maybe_result; | 6607 if (!maybe_result->To(&result)) return maybe_result; |
6669 | 6608 |
6670 result->InitializeDescriptors(descriptors); | 6609 result->InitializeDescriptors(descriptors); |
6671 | 6610 |
6672 if (flag == INSERT_TRANSITION && CanHaveMoreTransitions()) { | 6611 if (flag == INSERT_TRANSITION && CanHaveMoreTransitions()) { |
6673 TransitionArray* transitions; | 6612 TransitionArray* transitions; |
6674 MaybeObject* maybe_transitions = AddTransition(name, result, simple_flag); | 6613 MaybeObject* maybe_transitions = AddTransition(name, result, simple_flag); |
6675 if (!maybe_transitions->To(&transitions)) return maybe_transitions; | 6614 if (!maybe_transitions->To(&transitions)) return maybe_transitions; |
6676 set_transitions(transitions); | 6615 set_transitions(transitions); |
6677 result->SetBackPointer(this); | 6616 result->SetBackPointer(this); |
6678 } else if (flag != OMIT_TRANSITION_KEEP_REPRESENTATIONS) { | 6617 } else { |
6679 descriptors->InitializeRepresentations(Representation::Tagged()); | 6618 descriptors->InitializeRepresentations(Representation::Tagged()); |
6680 } | 6619 } |
6681 | 6620 |
6682 return result; | 6621 return result; |
6683 } | 6622 } |
6684 | 6623 |
6685 | 6624 |
6686 // Since this method is used to rewrite an existing transition tree, it can | 6625 // Since this method is used to rewrite an existing transition tree, it can |
6687 // always insert transitions without checking. | 6626 // always insert transitions without checking. |
6688 MaybeObject* Map::CopyInstallDescriptors(int new_descriptor, | 6627 MaybeObject* Map::CopyInstallDescriptors(int new_descriptor, |
(...skipping 1107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7796 // The method merges two descriptor array in three parts. Both descriptor arrays | 7735 // The method merges two descriptor array in three parts. Both descriptor arrays |
7797 // are identical up to |verbatim|. They also overlap in keys up to |valid|. | 7736 // are identical up to |verbatim|. They also overlap in keys up to |valid|. |
7798 // Between |verbatim| and |valid|, the resulting descriptor type as well as the | 7737 // Between |verbatim| and |valid|, the resulting descriptor type as well as the |
7799 // representation are generalized from both |this| and |other|. Beyond |valid|, | 7738 // representation are generalized from both |this| and |other|. Beyond |valid|, |
7800 // the descriptors are copied verbatim from |other| up to |new_size|. | 7739 // the descriptors are copied verbatim from |other| up to |new_size|. |
7801 // In case of incompatible types, the type and representation of |other| is | 7740 // In case of incompatible types, the type and representation of |other| is |
7802 // used. | 7741 // used. |
7803 MaybeObject* DescriptorArray::Merge(int verbatim, | 7742 MaybeObject* DescriptorArray::Merge(int verbatim, |
7804 int valid, | 7743 int valid, |
7805 int new_size, | 7744 int new_size, |
| 7745 int modify_index, |
| 7746 StoreMode store_mode, |
7806 DescriptorArray* other) { | 7747 DescriptorArray* other) { |
7807 ASSERT(verbatim <= valid); | 7748 ASSERT(verbatim <= valid); |
7808 ASSERT(valid <= new_size); | 7749 ASSERT(valid <= new_size); |
7809 | 7750 |
7810 DescriptorArray* result; | 7751 DescriptorArray* result; |
7811 // Allocate a new descriptor array large enough to hold the required | 7752 // Allocate a new descriptor array large enough to hold the required |
7812 // descriptors, with minimally the exact same size as this descriptor array. | 7753 // descriptors, with minimally the exact same size as this descriptor array. |
7813 MaybeObject* maybe_descriptors = DescriptorArray::Allocate( | 7754 MaybeObject* maybe_descriptors = DescriptorArray::Allocate( |
7814 new_size, Max(new_size, other->number_of_descriptors()) - new_size); | 7755 new_size, Max(new_size, other->number_of_descriptors()) - new_size); |
7815 if (!maybe_descriptors->To(&result)) return maybe_descriptors; | 7756 if (!maybe_descriptors->To(&result)) return maybe_descriptors; |
(...skipping 13 matching lines...) Expand all Loading... |
7829 result->CopyFrom(descriptor, this, descriptor, witness); | 7770 result->CopyFrom(descriptor, this, descriptor, witness); |
7830 } | 7771 } |
7831 | 7772 |
7832 // |verbatim| -> |valid| | 7773 // |verbatim| -> |valid| |
7833 for (; descriptor < valid; descriptor++) { | 7774 for (; descriptor < valid; descriptor++) { |
7834 Name* key = GetKey(descriptor); | 7775 Name* key = GetKey(descriptor); |
7835 PropertyDetails details = GetDetails(descriptor); | 7776 PropertyDetails details = GetDetails(descriptor); |
7836 PropertyDetails other_details = other->GetDetails(descriptor); | 7777 PropertyDetails other_details = other->GetDetails(descriptor); |
7837 | 7778 |
7838 if (details.type() == FIELD || other_details.type() == FIELD || | 7779 if (details.type() == FIELD || other_details.type() == FIELD || |
| 7780 (store_mode == FORCE_FIELD && descriptor == modify_index) || |
7839 (details.type() == CONSTANT && | 7781 (details.type() == CONSTANT && |
7840 other_details.type() == CONSTANT && | 7782 other_details.type() == CONSTANT && |
7841 GetValue(descriptor) != other->GetValue(descriptor))) { | 7783 GetValue(descriptor) != other->GetValue(descriptor))) { |
7842 Representation representation = | 7784 Representation representation = |
7843 details.representation().generalize(other_details.representation()); | 7785 details.representation().generalize(other_details.representation()); |
7844 FieldDescriptor d(key, | 7786 FieldDescriptor d(key, |
7845 current_offset++, | 7787 current_offset++, |
7846 other_details.attributes(), | 7788 other_details.attributes(), |
7847 representation); | 7789 representation); |
7848 result->Set(descriptor, &d, witness); | 7790 result->Set(descriptor, &d, witness); |
7849 } else { | 7791 } else { |
7850 result->CopyFrom(descriptor, other, descriptor, witness); | 7792 result->CopyFrom(descriptor, other, descriptor, witness); |
7851 } | 7793 } |
7852 } | 7794 } |
7853 | 7795 |
7854 // |valid| -> |new_size| | 7796 // |valid| -> |new_size| |
7855 for (; descriptor < new_size; descriptor++) { | 7797 for (; descriptor < new_size; descriptor++) { |
7856 PropertyDetails details = other->GetDetails(descriptor); | 7798 PropertyDetails details = other->GetDetails(descriptor); |
7857 if (details.type() == FIELD) { | 7799 if (details.type() == FIELD || |
| 7800 (store_mode == FORCE_FIELD && descriptor == modify_index)) { |
7858 Name* key = other->GetKey(descriptor); | 7801 Name* key = other->GetKey(descriptor); |
7859 FieldDescriptor d(key, | 7802 FieldDescriptor d(key, |
7860 current_offset++, | 7803 current_offset++, |
7861 details.attributes(), | 7804 details.attributes(), |
7862 details.representation()); | 7805 details.representation()); |
7863 result->Set(descriptor, &d, witness); | 7806 result->Set(descriptor, &d, witness); |
7864 } else { | 7807 } else { |
7865 result->CopyFrom(descriptor, other, descriptor, witness); | 7808 result->CopyFrom(descriptor, other, descriptor, witness); |
7866 } | 7809 } |
7867 } | 7810 } |
(...skipping 8139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
16007 #define ERROR_MESSAGES_TEXTS(C, T) T, | 15950 #define ERROR_MESSAGES_TEXTS(C, T) T, |
16008 static const char* error_messages_[] = { | 15951 static const char* error_messages_[] = { |
16009 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) | 15952 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) |
16010 }; | 15953 }; |
16011 #undef ERROR_MESSAGES_TEXTS | 15954 #undef ERROR_MESSAGES_TEXTS |
16012 return error_messages_[reason]; | 15955 return error_messages_[reason]; |
16013 } | 15956 } |
16014 | 15957 |
16015 | 15958 |
16016 } } // namespace v8::internal | 15959 } } // namespace v8::internal |
OLD | NEW |