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