OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 1528 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1539 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 1539 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
1540 } | 1540 } |
1541 return AddSlowProperty(name, value, attributes); | 1541 return AddSlowProperty(name, value, attributes); |
1542 } | 1542 } |
1543 | 1543 |
1544 DescriptorArray* old_descriptors = map()->instance_descriptors(); | 1544 DescriptorArray* old_descriptors = map()->instance_descriptors(); |
1545 // Compute the new index for new field. | 1545 // Compute the new index for new field. |
1546 int index = map()->NextFreePropertyIndex(); | 1546 int index = map()->NextFreePropertyIndex(); |
1547 | 1547 |
1548 // Allocate new instance descriptors with (name, index) added | 1548 // Allocate new instance descriptors with (name, index) added |
1549 FieldDescriptor new_field(name, index, attributes); | 1549 FieldDescriptor new_field(name, index, attributes, 0); |
1550 DescriptorArray* new_descriptors; | 1550 DescriptorArray* new_descriptors; |
1551 { MaybeObject* maybe_new_descriptors = | 1551 { MaybeObject* maybe_new_descriptors = |
1552 old_descriptors->CopyInsert(&new_field); | 1552 old_descriptors->CopyInsert(&new_field); |
1553 if (!maybe_new_descriptors->To(&new_descriptors)) { | 1553 if (!maybe_new_descriptors->To(&new_descriptors)) { |
1554 return maybe_new_descriptors; | 1554 return maybe_new_descriptors; |
1555 } | 1555 } |
1556 } | 1556 } |
1557 | 1557 |
1558 // Only allow map transition if the object isn't the global object and there | 1558 // Only allow map transition if the object isn't the global object. |
1559 // is not a transition for the name, or there's a transition for the name but | |
1560 // it's unrelated to properties. | |
1561 int descriptor_index = old_descriptors->SearchWithCache(name); | |
1562 | |
1563 // Element transitions are stored in the descriptor for property "", which is | |
1564 // not a identifier and should have forced a switch to slow properties above. | |
1565 bool can_insert_transition = descriptor_index == DescriptorArray::kNotFound; | |
1566 bool allow_map_transition = | 1559 bool allow_map_transition = |
1567 can_insert_transition && | |
1568 (isolate->context()->global_context()->object_function()->map() != map()); | 1560 (isolate->context()->global_context()->object_function()->map() != map()); |
1569 | 1561 |
| 1562 ASSERT(old_descriptors->Search(name) == DescriptorArray::kNotFound); |
1570 ASSERT(index < map()->inobject_properties() || | 1563 ASSERT(index < map()->inobject_properties() || |
1571 (index - map()->inobject_properties()) < properties()->length() || | 1564 (index - map()->inobject_properties()) < properties()->length() || |
1572 map()->unused_property_fields() == 0); | 1565 map()->unused_property_fields() == 0); |
1573 // Allocate a new map for the object. | 1566 // Allocate a new map for the object. |
1574 Object* r; | 1567 Object* r; |
1575 { MaybeObject* maybe_r = map()->CopyDropDescriptors(); | 1568 { MaybeObject* maybe_r = map()->CopyDropDescriptors(); |
1576 if (!maybe_r->ToObject(&r)) return maybe_r; | 1569 if (!maybe_r->ToObject(&r)) return maybe_r; |
1577 } | 1570 } |
1578 Map* new_map = Map::cast(r); | 1571 Map* new_map = Map::cast(r); |
1579 | 1572 |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1615 set_map(new_map); | 1608 set_map(new_map); |
1616 return FastPropertyAtPut(index, value); | 1609 return FastPropertyAtPut(index, value); |
1617 } | 1610 } |
1618 | 1611 |
1619 | 1612 |
1620 MaybeObject* JSObject::AddConstantFunctionProperty( | 1613 MaybeObject* JSObject::AddConstantFunctionProperty( |
1621 String* name, | 1614 String* name, |
1622 JSFunction* function, | 1615 JSFunction* function, |
1623 PropertyAttributes attributes) { | 1616 PropertyAttributes attributes) { |
1624 // Allocate new instance descriptors with (name, function) added | 1617 // Allocate new instance descriptors with (name, function) added |
1625 ConstantFunctionDescriptor d(name, function, attributes); | 1618 ConstantFunctionDescriptor d(name, function, attributes, 0); |
1626 DescriptorArray* new_descriptors; | 1619 DescriptorArray* new_descriptors; |
1627 { MaybeObject* maybe_new_descriptors = | 1620 { MaybeObject* maybe_new_descriptors = |
1628 map()->instance_descriptors()->CopyInsert(&d); | 1621 map()->instance_descriptors()->CopyInsert(&d); |
1629 if (!maybe_new_descriptors->To(&new_descriptors)) { | 1622 if (!maybe_new_descriptors->To(&new_descriptors)) { |
1630 return maybe_new_descriptors; | 1623 return maybe_new_descriptors; |
1631 } | 1624 } |
1632 } | 1625 } |
1633 | 1626 |
1634 // Allocate a new map for the object. | 1627 // Allocate a new map for the object. |
1635 Map* new_map; | 1628 Map* new_map; |
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1858 TooManyFastProperties(properties()->length(), MAY_BE_STORE_FROM_KEYED)) { | 1851 TooManyFastProperties(properties()->length(), MAY_BE_STORE_FROM_KEYED)) { |
1859 Object* obj; | 1852 Object* obj; |
1860 { MaybeObject* maybe_obj = | 1853 { MaybeObject* maybe_obj = |
1861 NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); | 1854 NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); |
1862 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 1855 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
1863 } | 1856 } |
1864 return ReplaceSlowProperty(name, new_value, attributes); | 1857 return ReplaceSlowProperty(name, new_value, attributes); |
1865 } | 1858 } |
1866 | 1859 |
1867 int index = map()->NextFreePropertyIndex(); | 1860 int index = map()->NextFreePropertyIndex(); |
1868 FieldDescriptor new_field(name, index, attributes); | 1861 FieldDescriptor new_field(name, index, attributes, 0); |
1869 // Make a new DescriptorArray replacing an entry with FieldDescriptor. | 1862 // Make a new DescriptorArray replacing an entry with FieldDescriptor. |
1870 Object* descriptors_unchecked; | 1863 Object* descriptors_unchecked; |
1871 { MaybeObject* maybe_descriptors_unchecked = | 1864 { MaybeObject* maybe_descriptors_unchecked = |
1872 map()->instance_descriptors()->CopyInsert(&new_field); | 1865 map()->instance_descriptors()->CopyInsert(&new_field); |
1873 if (!maybe_descriptors_unchecked->ToObject(&descriptors_unchecked)) { | 1866 if (!maybe_descriptors_unchecked->ToObject(&descriptors_unchecked)) { |
1874 return maybe_descriptors_unchecked; | 1867 return maybe_descriptors_unchecked; |
1875 } | 1868 } |
1876 } | 1869 } |
1877 DescriptorArray* new_descriptors = | 1870 DescriptorArray* new_descriptors = |
1878 DescriptorArray::cast(descriptors_unchecked); | 1871 DescriptorArray::cast(descriptors_unchecked); |
(...skipping 1052 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2931 } | 2924 } |
2932 return self->SetPropertyWithCallback(transition, | 2925 return self->SetPropertyWithCallback(transition, |
2933 *name, | 2926 *name, |
2934 *value, | 2927 *value, |
2935 result->holder(), | 2928 result->holder(), |
2936 strict_mode); | 2929 strict_mode); |
2937 } | 2930 } |
2938 | 2931 |
2939 Map* transition_map = Map::cast(transition); | 2932 Map* transition_map = Map::cast(transition); |
2940 DescriptorArray* descriptors = transition_map->instance_descriptors(); | 2933 DescriptorArray* descriptors = transition_map->instance_descriptors(); |
2941 int descriptor = descriptors->SearchWithCache(*name); | 2934 int descriptor = descriptors->LastAdded(); |
2942 PropertyDetails details = descriptors->GetDetails(descriptor); | 2935 PropertyDetails details = descriptors->GetDetails(descriptor); |
2943 ASSERT(details.type() == FIELD || details.type() == CONSTANT_FUNCTION); | 2936 ASSERT(details.type() == FIELD || details.type() == CONSTANT_FUNCTION); |
2944 | 2937 |
2945 if (details.type() == FIELD) { | 2938 if (details.type() == FIELD) { |
2946 if (attributes == details.attributes()) { | 2939 if (attributes == details.attributes()) { |
2947 int field_index = descriptors->GetFieldIndex(descriptor); | 2940 int field_index = descriptors->GetFieldIndex(descriptor); |
2948 return self->AddFastPropertyUsingMap(transition_map, | 2941 return self->AddFastPropertyUsingMap(transition_map, |
2949 *name, | 2942 *name, |
2950 *value, | 2943 *value, |
2951 field_index); | 2944 field_index); |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3055 return ConvertDescriptorToField(name, value, attributes); | 3048 return ConvertDescriptorToField(name, value, attributes); |
3056 case TRANSITION: { | 3049 case TRANSITION: { |
3057 Object* transition = result.GetTransitionValue(); | 3050 Object* transition = result.GetTransitionValue(); |
3058 | 3051 |
3059 if (transition->IsAccessorPair()) { | 3052 if (transition->IsAccessorPair()) { |
3060 return ConvertDescriptorToField(name, value, attributes); | 3053 return ConvertDescriptorToField(name, value, attributes); |
3061 } | 3054 } |
3062 | 3055 |
3063 Map* transition_map = Map::cast(transition); | 3056 Map* transition_map = Map::cast(transition); |
3064 DescriptorArray* descriptors = transition_map->instance_descriptors(); | 3057 DescriptorArray* descriptors = transition_map->instance_descriptors(); |
3065 int descriptor = descriptors->Search(name); | 3058 int descriptor = descriptors->LastAdded(); |
3066 PropertyDetails details = descriptors->GetDetails(descriptor); | 3059 PropertyDetails details = descriptors->GetDetails(descriptor); |
3067 ASSERT(details.type() == FIELD || details.type() == CONSTANT_FUNCTION); | 3060 ASSERT(details.type() == FIELD || details.type() == CONSTANT_FUNCTION); |
3068 | 3061 |
3069 if (details.type() == FIELD) { | 3062 if (details.type() == FIELD) { |
3070 if (attributes == details.attributes()) { | 3063 if (attributes == details.attributes()) { |
3071 int field_index = descriptors->GetFieldIndex(descriptor); | 3064 int field_index = descriptors->GetFieldIndex(descriptor); |
3072 return AddFastPropertyUsingMap(transition_map, | 3065 return AddFastPropertyUsingMap(transition_map, |
3073 name, | 3066 name, |
3074 value, | 3067 value, |
3075 field_index); | 3068 field_index); |
(...skipping 1527 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4603 // step 1: create a new getter/setter pair with only the accessor in it | 4596 // step 1: create a new getter/setter pair with only the accessor in it |
4604 Heap* heap = obj->GetHeap(); | 4597 Heap* heap = obj->GetHeap(); |
4605 AccessorPair* accessors2; | 4598 AccessorPair* accessors2; |
4606 { MaybeObject* maybe_accessors2 = heap->AllocateAccessorPair(); | 4599 { MaybeObject* maybe_accessors2 = heap->AllocateAccessorPair(); |
4607 if (!maybe_accessors2->To(&accessors2)) return maybe_accessors2; | 4600 if (!maybe_accessors2->To(&accessors2)) return maybe_accessors2; |
4608 } | 4601 } |
4609 accessors2->set(component, accessor); | 4602 accessors2->set(component, accessor); |
4610 | 4603 |
4611 // step 2: create a copy of the descriptors, incl. the new getter/setter pair | 4604 // step 2: create a copy of the descriptors, incl. the new getter/setter pair |
4612 Map* map1 = obj->map(); | 4605 Map* map1 = obj->map(); |
4613 CallbacksDescriptor callbacks_descr2(name, accessors2, attributes); | 4606 CallbacksDescriptor callbacks_descr2(name, accessors2, attributes, 0); |
4614 DescriptorArray* descriptors2; | 4607 DescriptorArray* descriptors2; |
4615 { MaybeObject* maybe_descriptors2 = | 4608 { MaybeObject* maybe_descriptors2 = |
4616 map1->instance_descriptors()->CopyInsert(&callbacks_descr2); | 4609 map1->instance_descriptors()->CopyInsert(&callbacks_descr2); |
4617 if (!maybe_descriptors2->To(&descriptors2)) return maybe_descriptors2; | 4610 if (!maybe_descriptors2->To(&descriptors2)) return maybe_descriptors2; |
4618 } | 4611 } |
4619 | 4612 |
4620 // step 3: create a new map with the new descriptors | 4613 // step 3: create a new map with the new descriptors |
4621 Map* map2; | 4614 Map* map2; |
4622 { MaybeObject* maybe_map2 = map1->CopyDropDescriptors(); | 4615 { MaybeObject* maybe_map2 = map1->CopyDropDescriptors(); |
4623 if (!maybe_map2->To(&map2)) return maybe_map2; | 4616 if (!maybe_map2->To(&map2)) return maybe_map2; |
(...skipping 26 matching lines...) Expand all Loading... |
4650 return obj; | 4643 return obj; |
4651 } | 4644 } |
4652 | 4645 |
4653 | 4646 |
4654 static bool TransitionToSameAccessor(Object* map, | 4647 static bool TransitionToSameAccessor(Object* map, |
4655 String* name, | 4648 String* name, |
4656 AccessorComponent component, | 4649 AccessorComponent component, |
4657 Object* accessor, | 4650 Object* accessor, |
4658 PropertyAttributes attributes ) { | 4651 PropertyAttributes attributes ) { |
4659 DescriptorArray* descs = Map::cast(map)->instance_descriptors(); | 4652 DescriptorArray* descs = Map::cast(map)->instance_descriptors(); |
4660 int number = descs->SearchWithCache(name); | 4653 int number = descs->LastAdded(); |
4661 ASSERT(number != DescriptorArray::kNotFound); | 4654 ASSERT(number != DescriptorArray::kNotFound); |
4662 Object* target_accessor = | 4655 Object* target_accessor = |
4663 AccessorPair::cast(descs->GetCallbacksObject(number))->get(component); | 4656 AccessorPair::cast(descs->GetCallbacksObject(number))->get(component); |
4664 PropertyAttributes target_attributes = descs->GetDetails(number).attributes(); | 4657 PropertyAttributes target_attributes = descs->GetDetails(number).attributes(); |
4665 return target_accessor == accessor && target_attributes == attributes; | 4658 return target_accessor == accessor && target_attributes == attributes; |
4666 } | 4659 } |
4667 | 4660 |
4668 | 4661 |
4669 static MaybeObject* NewCallbackTransition(JSObject* obj, | 4662 static MaybeObject* NewCallbackTransition(JSObject* obj, |
4670 String* name, | 4663 String* name, |
4671 AccessorComponent component, | 4664 AccessorComponent component, |
4672 Object* accessor, | 4665 Object* accessor, |
4673 PropertyAttributes attributes, | 4666 PropertyAttributes attributes, |
4674 AccessorPair* accessors2) { | 4667 AccessorPair* accessors2) { |
4675 // step 1: copy the old getter/setter pair and set the new accessor | 4668 // step 1: copy the old getter/setter pair and set the new accessor |
4676 AccessorPair* accessors3; | 4669 AccessorPair* accessors3; |
4677 { MaybeObject* maybe_accessors3 = accessors2->CopyWithoutTransitions(); | 4670 { MaybeObject* maybe_accessors3 = accessors2->CopyWithoutTransitions(); |
4678 if (!maybe_accessors3->To(&accessors3)) return maybe_accessors3; | 4671 if (!maybe_accessors3->To(&accessors3)) return maybe_accessors3; |
4679 } | 4672 } |
4680 accessors3->set(component, accessor); | 4673 accessors3->set(component, accessor); |
4681 | 4674 |
4682 // step 2: create a copy of the descriptors, incl. the new getter/setter pair | 4675 // step 2: create a copy of the descriptors, incl. the new getter/setter pair |
4683 Map* map2 = obj->map(); | 4676 Map* map2 = obj->map(); |
4684 CallbacksDescriptor callbacks_descr3(name, accessors3, attributes); | 4677 CallbacksDescriptor callbacks_descr3(name, accessors3, attributes, 0); |
4685 DescriptorArray* descriptors3; | 4678 DescriptorArray* descriptors3; |
4686 { MaybeObject* maybe_descriptors3 = | 4679 { MaybeObject* maybe_descriptors3 = |
4687 map2->instance_descriptors()->CopyInsert(&callbacks_descr3); | 4680 map2->instance_descriptors()->CopyInsert(&callbacks_descr3); |
4688 if (!maybe_descriptors3->To(&descriptors3)) return maybe_descriptors3; | 4681 if (!maybe_descriptors3->To(&descriptors3)) return maybe_descriptors3; |
4689 } | 4682 } |
4690 | 4683 |
4691 // step 3: create a new map with the new descriptors | 4684 // step 3: create a new map with the new descriptors |
4692 Map* map3; | 4685 Map* map3; |
4693 { MaybeObject* maybe_map3 = map2->CopyDropDescriptors(); | 4686 { MaybeObject* maybe_map3 = map2->CopyDropDescriptors(); |
4694 if (!maybe_map3->To(&map3)) return maybe_map3; | 4687 if (!maybe_map3->To(&map3)) return maybe_map3; |
(...skipping 1115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5810 FixedArray* result; | 5803 FixedArray* result; |
5811 if (number_of_descriptors == 0 && shared_mode == MAY_BE_SHARED) { | 5804 if (number_of_descriptors == 0 && shared_mode == MAY_BE_SHARED) { |
5812 return heap->empty_descriptor_array(); | 5805 return heap->empty_descriptor_array(); |
5813 } | 5806 } |
5814 // Allocate the array of keys. | 5807 // Allocate the array of keys. |
5815 { MaybeObject* maybe_array = | 5808 { MaybeObject* maybe_array = |
5816 heap->AllocateFixedArray(ToKeyIndex(number_of_descriptors)); | 5809 heap->AllocateFixedArray(ToKeyIndex(number_of_descriptors)); |
5817 if (!maybe_array->To(&result)) return maybe_array; | 5810 if (!maybe_array->To(&result)) return maybe_array; |
5818 } | 5811 } |
5819 | 5812 |
5820 result->set(kEnumerationIndexIndex, | 5813 result->set(kLastAddedIndex, Smi::FromInt(-1)); |
5821 Smi::FromInt(PropertyDetails::kInitialIndex)); | |
5822 result->set(kTransitionsIndex, Smi::FromInt(0)); | 5814 result->set(kTransitionsIndex, Smi::FromInt(0)); |
5823 return result; | 5815 return result; |
5824 } | 5816 } |
5825 | 5817 |
5826 | 5818 |
5827 void DescriptorArray::SetEnumCache(FixedArray* bridge_storage, | 5819 void DescriptorArray::SetEnumCache(FixedArray* bridge_storage, |
5828 FixedArray* new_cache, | 5820 FixedArray* new_cache, |
5829 Object* new_index_cache) { | 5821 Object* new_index_cache) { |
5830 ASSERT(bridge_storage->length() >= kEnumCacheBridgeLength); | 5822 ASSERT(bridge_storage->length() >= kEnumCacheBridgeLength); |
5831 ASSERT(new_index_cache->IsSmi() || new_index_cache->IsFixedArray()); | 5823 ASSERT(new_index_cache->IsSmi() || new_index_cache->IsFixedArray()); |
5832 if (HasEnumCache()) { | 5824 if (HasEnumCache()) { |
5833 FixedArray::cast(get(kEnumerationIndexIndex))-> | 5825 FixedArray::cast(get(kLastAddedIndex))-> |
5834 set(kEnumCacheBridgeCacheIndex, new_cache); | 5826 set(kEnumCacheBridgeCacheIndex, new_cache); |
5835 FixedArray::cast(get(kEnumerationIndexIndex))-> | 5827 FixedArray::cast(get(kLastAddedIndex))-> |
5836 set(kEnumCacheBridgeIndicesCacheIndex, new_index_cache); | 5828 set(kEnumCacheBridgeIndicesCacheIndex, new_index_cache); |
5837 } else { | 5829 } else { |
5838 if (IsEmpty()) return; // Do nothing for empty descriptor array. | 5830 if (IsEmpty()) return; // Do nothing for empty descriptor array. |
5839 FixedArray::cast(bridge_storage)-> | 5831 FixedArray::cast(bridge_storage)-> |
5840 set(kEnumCacheBridgeCacheIndex, new_cache); | 5832 set(kEnumCacheBridgeCacheIndex, new_cache); |
5841 FixedArray::cast(bridge_storage)-> | 5833 FixedArray::cast(bridge_storage)-> |
5842 set(kEnumCacheBridgeIndicesCacheIndex, new_index_cache); | 5834 set(kEnumCacheBridgeIndicesCacheIndex, new_index_cache); |
5843 NoWriteBarrierSet(FixedArray::cast(bridge_storage), | 5835 NoWriteBarrierSet(FixedArray::cast(bridge_storage), |
5844 kEnumCacheBridgeEnumIndex, | 5836 kEnumCacheBridgeLastAdded, |
5845 get(kEnumerationIndexIndex)); | 5837 get(kLastAddedIndex)); |
5846 set(kEnumerationIndexIndex, bridge_storage); | 5838 set(kLastAddedIndex, bridge_storage); |
5847 } | 5839 } |
5848 } | 5840 } |
5849 | 5841 |
5850 | 5842 |
5851 static bool InsertionPointFound(String* key1, String* key2) { | 5843 static bool InsertionPointFound(String* key1, String* key2) { |
5852 return key1->Hash() > key2->Hash() || key1 == key2; | 5844 return key1->Hash() > key2->Hash() || key1 == key2; |
5853 } | 5845 } |
5854 | 5846 |
5855 | 5847 |
5856 void DescriptorArray::CopyFrom(Handle<DescriptorArray> dst, | 5848 void DescriptorArray::CopyFrom(Handle<DescriptorArray> dst, |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5903 | 5895 |
5904 DescriptorArray* new_descriptors; | 5896 DescriptorArray* new_descriptors; |
5905 { MaybeObject* maybe_result = Allocate(new_size, MAY_BE_SHARED); | 5897 { MaybeObject* maybe_result = Allocate(new_size, MAY_BE_SHARED); |
5906 if (!maybe_result->To(&new_descriptors)) return maybe_result; | 5898 if (!maybe_result->To(&new_descriptors)) return maybe_result; |
5907 } | 5899 } |
5908 | 5900 |
5909 FixedArray::WhitenessWitness witness(new_descriptors); | 5901 FixedArray::WhitenessWitness witness(new_descriptors); |
5910 | 5902 |
5911 // Set the enumeration index in the descriptors and set the enumeration index | 5903 // Set the enumeration index in the descriptors and set the enumeration index |
5912 // in the result. | 5904 // in the result. |
5913 int enumeration_index = NextEnumerationIndex(); | |
5914 if (keep_enumeration_index) { | 5905 if (keep_enumeration_index) { |
5915 descriptor->SetEnumerationIndex(GetDetails(index).index()); | 5906 descriptor->SetEnumerationIndex(GetDetails(index).index()); |
5916 } else { | 5907 } else { |
5917 descriptor->SetEnumerationIndex(enumeration_index); | 5908 descriptor->SetEnumerationIndex(NextEnumerationIndex()); |
5918 ++enumeration_index; | |
5919 } | 5909 } |
5920 new_descriptors->SetNextEnumerationIndex(enumeration_index); | |
5921 | 5910 |
5922 // Copy the descriptors, inserting or replacing a descriptor. | 5911 // Copy the descriptors, inserting or replacing a descriptor. |
5923 int to_index = 0; | 5912 int to_index = 0; |
5924 int insertion_index = -1; | 5913 int insertion_index = -1; |
5925 int from_index = 0; | 5914 int from_index = 0; |
5926 while (from_index < number_of_descriptors()) { | 5915 while (from_index < number_of_descriptors()) { |
5927 if (insertion_index < 0 && | 5916 if (insertion_index < 0 && |
5928 InsertionPointFound(GetKey(from_index), descriptor->GetKey())) { | 5917 InsertionPointFound(GetKey(from_index), descriptor->GetKey())) { |
5929 insertion_index = to_index++; | 5918 insertion_index = to_index++; |
5930 if (replacing) from_index++; | 5919 if (replacing) from_index++; |
5931 } else { | 5920 } else { |
5932 MaybeObject* copy_result = | 5921 MaybeObject* copy_result = |
5933 new_descriptors->CopyFrom(to_index++, this, from_index, witness); | 5922 new_descriptors->CopyFrom(to_index++, this, from_index, witness); |
5934 if (copy_result->IsFailure()) return copy_result; | 5923 if (copy_result->IsFailure()) return copy_result; |
5935 from_index++; | 5924 from_index++; |
5936 } | 5925 } |
5937 } | 5926 } |
5938 if (insertion_index < 0) insertion_index = to_index++; | 5927 if (insertion_index < 0) insertion_index = to_index++; |
5939 | 5928 |
5940 ASSERT(insertion_index < new_descriptors->number_of_descriptors()); | 5929 ASSERT(insertion_index < new_descriptors->number_of_descriptors()); |
5941 new_descriptors->Set(insertion_index, descriptor, witness); | 5930 new_descriptors->Set(insertion_index, descriptor, witness); |
| 5931 if (!replacing) { |
| 5932 new_descriptors->SetLastAdded(insertion_index); |
| 5933 } else { |
| 5934 new_descriptors->SetLastAdded(LastAdded()); |
| 5935 } |
5942 | 5936 |
5943 ASSERT(to_index == new_descriptors->number_of_descriptors()); | 5937 ASSERT(to_index == new_descriptors->number_of_descriptors()); |
5944 SLOW_ASSERT(new_descriptors->IsSortedNoDuplicates()); | 5938 SLOW_ASSERT(new_descriptors->IsSortedNoDuplicates()); |
5945 | 5939 |
5946 return new_descriptors; | 5940 return new_descriptors; |
5947 } | 5941 } |
5948 | 5942 |
5949 | 5943 |
5950 MaybeObject* DescriptorArray::Copy(SharedMode shared_mode) { | 5944 MaybeObject* DescriptorArray::Copy(SharedMode shared_mode) { |
5951 // Allocate the new descriptor array. | 5945 // Allocate the new descriptor array. |
5952 int number_of_descriptors = this->number_of_descriptors(); | 5946 int number_of_descriptors = this->number_of_descriptors(); |
5953 DescriptorArray* new_descriptors; | 5947 DescriptorArray* new_descriptors; |
5954 { MaybeObject* maybe_result = Allocate(number_of_descriptors, | 5948 { MaybeObject* maybe_result = Allocate(number_of_descriptors, |
5955 shared_mode); | 5949 shared_mode); |
5956 if (!maybe_result->To(&new_descriptors)) return maybe_result; | 5950 if (!maybe_result->To(&new_descriptors)) return maybe_result; |
5957 } | 5951 } |
5958 | 5952 |
5959 // Copy the content. | 5953 // Copy the content. |
5960 if (number_of_descriptors > 0) { | 5954 if (number_of_descriptors > 0) { |
5961 FixedArray::WhitenessWitness witness(new_descriptors); | 5955 FixedArray::WhitenessWitness witness(new_descriptors); |
5962 for (int i = 0; i < number_of_descriptors; i++) { | 5956 for (int i = 0; i < number_of_descriptors; i++) { |
5963 MaybeObject* copy_result = | 5957 MaybeObject* copy_result = |
5964 new_descriptors->CopyFrom(i, this, i, witness); | 5958 new_descriptors->CopyFrom(i, this, i, witness); |
5965 if (copy_result->IsFailure()) return copy_result; | 5959 if (copy_result->IsFailure()) return copy_result; |
5966 } | 5960 } |
| 5961 new_descriptors->SetLastAdded(LastAdded()); |
5967 } | 5962 } |
5968 new_descriptors->SetNextEnumerationIndex(NextEnumerationIndex()); | 5963 |
5969 return new_descriptors; | 5964 return new_descriptors; |
5970 } | 5965 } |
5971 | 5966 |
5972 // We need the whiteness witness since sort will reshuffle the entries in the | 5967 // We need the whiteness witness since sort will reshuffle the entries in the |
5973 // descriptor array. If the descriptor array were to be black, the shuffling | 5968 // descriptor array. If the descriptor array were to be black, the shuffling |
5974 // would move a slot that was already recorded as pointing into an evacuation | 5969 // would move a slot that was already recorded as pointing into an evacuation |
5975 // candidate. This would result in missing updates upon evacuation. | 5970 // candidate. This would result in missing updates upon evacuation. |
5976 void DescriptorArray::SortUnchecked(const WhitenessWitness& witness) { | 5971 void DescriptorArray::SortUnchecked(const WhitenessWitness& witness) { |
5977 // In-place heap sort. | 5972 // In-place heap sort. |
5978 int len = number_of_descriptors(); | 5973 int len = number_of_descriptors(); |
| 5974 // Nothing to sort. |
| 5975 if (len == 0) return; |
5979 | 5976 |
5980 // Bottom-up max-heap construction. | 5977 // Bottom-up max-heap construction. |
5981 // Index of the last node with children | 5978 // Index of the last node with children |
5982 const int max_parent_index = (len / 2) - 1; | 5979 const int max_parent_index = (len / 2) - 1; |
5983 for (int i = max_parent_index; i >= 0; --i) { | 5980 for (int i = max_parent_index; i >= 0; --i) { |
5984 int parent_index = i; | 5981 int parent_index = i; |
5985 const uint32_t parent_hash = GetKey(i)->Hash(); | 5982 const uint32_t parent_hash = GetKey(i)->Hash(); |
5986 while (parent_index <= max_parent_index) { | 5983 while (parent_index <= max_parent_index) { |
5987 int child_index = 2 * parent_index + 1; | 5984 int child_index = 2 * parent_index + 1; |
5988 uint32_t child_hash = GetKey(child_index)->Hash(); | 5985 uint32_t child_hash = GetKey(child_index)->Hash(); |
(...skipping 27 matching lines...) Expand all Loading... |
6016 if (right_child_hash > child_hash) { | 6013 if (right_child_hash > child_hash) { |
6017 child_index++; | 6014 child_index++; |
6018 child_hash = right_child_hash; | 6015 child_hash = right_child_hash; |
6019 } | 6016 } |
6020 } | 6017 } |
6021 if (child_hash <= parent_hash) break; | 6018 if (child_hash <= parent_hash) break; |
6022 NoIncrementalWriteBarrierSwapDescriptors(parent_index, child_index); | 6019 NoIncrementalWriteBarrierSwapDescriptors(parent_index, child_index); |
6023 parent_index = child_index; | 6020 parent_index = child_index; |
6024 } | 6021 } |
6025 } | 6022 } |
| 6023 |
| 6024 int last_enum_index = -1; |
| 6025 int last_added = -1; |
| 6026 for (int i = 0; i < len; ++i) { |
| 6027 int current_enum = GetDetails(i).index(); |
| 6028 if (current_enum > last_enum_index) { |
| 6029 last_added = i; |
| 6030 last_enum_index = current_enum; |
| 6031 } |
| 6032 } |
| 6033 SetLastAdded(last_added); |
| 6034 |
| 6035 ASSERT(LastAdded() != -1); |
6026 } | 6036 } |
6027 | 6037 |
6028 | 6038 |
6029 void DescriptorArray::Sort(const WhitenessWitness& witness) { | 6039 void DescriptorArray::Sort(const WhitenessWitness& witness) { |
6030 SortUnchecked(witness); | 6040 SortUnchecked(witness); |
6031 SLOW_ASSERT(IsSortedNoDuplicates()); | 6041 SLOW_ASSERT(IsSortedNoDuplicates()); |
6032 } | 6042 } |
6033 | 6043 |
6034 | 6044 |
6035 MaybeObject* AccessorPair::CopyWithoutTransitions() { | 6045 MaybeObject* AccessorPair::CopyWithoutTransitions() { |
(...skipping 6677 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12713 if (!maybe_key->ToObject(&key)) return maybe_key; | 12723 if (!maybe_key->ToObject(&key)) return maybe_key; |
12714 } | 12724 } |
12715 PropertyDetails details = DetailsAt(i); | 12725 PropertyDetails details = DetailsAt(i); |
12716 PropertyType type = details.type(); | 12726 PropertyType type = details.type(); |
12717 | 12727 |
12718 if (value->IsJSFunction() && !heap->InNewSpace(value)) { | 12728 if (value->IsJSFunction() && !heap->InNewSpace(value)) { |
12719 ConstantFunctionDescriptor d(String::cast(key), | 12729 ConstantFunctionDescriptor d(String::cast(key), |
12720 JSFunction::cast(value), | 12730 JSFunction::cast(value), |
12721 details.attributes(), | 12731 details.attributes(), |
12722 details.index()); | 12732 details.index()); |
12723 descriptors->Set(next_descriptor++, &d, witness); | 12733 descriptors->Set(next_descriptor, &d, witness); |
12724 } else if (type == NORMAL) { | 12734 } else if (type == NORMAL) { |
12725 if (current_offset < inobject_props) { | 12735 if (current_offset < inobject_props) { |
12726 obj->InObjectPropertyAtPut(current_offset, | 12736 obj->InObjectPropertyAtPut(current_offset, |
12727 value, | 12737 value, |
12728 UPDATE_WRITE_BARRIER); | 12738 UPDATE_WRITE_BARRIER); |
12729 } else { | 12739 } else { |
12730 int offset = current_offset - inobject_props; | 12740 int offset = current_offset - inobject_props; |
12731 FixedArray::cast(fields)->set(offset, value); | 12741 FixedArray::cast(fields)->set(offset, value); |
12732 } | 12742 } |
12733 FieldDescriptor d(String::cast(key), | 12743 FieldDescriptor d(String::cast(key), |
12734 current_offset++, | 12744 current_offset++, |
12735 details.attributes(), | 12745 details.attributes(), |
12736 details.index()); | 12746 details.index()); |
12737 descriptors->Set(next_descriptor++, &d, witness); | 12747 descriptors->Set(next_descriptor, &d, witness); |
12738 } else if (type == CALLBACKS) { | 12748 } else if (type == CALLBACKS) { |
12739 if (value->IsAccessorPair()) { | 12749 if (value->IsAccessorPair()) { |
12740 MaybeObject* maybe_copy = | 12750 MaybeObject* maybe_copy = |
12741 AccessorPair::cast(value)->CopyWithoutTransitions(); | 12751 AccessorPair::cast(value)->CopyWithoutTransitions(); |
12742 if (!maybe_copy->To(&value)) return maybe_copy; | 12752 if (!maybe_copy->To(&value)) return maybe_copy; |
12743 } | 12753 } |
12744 CallbacksDescriptor d(String::cast(key), | 12754 CallbacksDescriptor d(String::cast(key), |
12745 value, | 12755 value, |
12746 details.attributes(), | 12756 details.attributes(), |
12747 details.index()); | 12757 details.index()); |
12748 descriptors->Set(next_descriptor++, &d, witness); | 12758 descriptors->Set(next_descriptor, &d, witness); |
12749 } else { | 12759 } else { |
12750 UNREACHABLE(); | 12760 UNREACHABLE(); |
12751 } | 12761 } |
| 12762 ++next_descriptor; |
12752 } | 12763 } |
12753 } | 12764 } |
12754 ASSERT(current_offset == number_of_fields); | 12765 ASSERT(current_offset == number_of_fields); |
12755 | 12766 |
12756 descriptors->Sort(witness); | 12767 descriptors->Sort(witness); |
12757 // Allocate new map. | 12768 // Allocate new map. |
12758 Object* new_map; | 12769 Object* new_map; |
12759 { MaybeObject* maybe_new_map = obj->map()->CopyDropDescriptors(); | 12770 { MaybeObject* maybe_new_map = obj->map()->CopyDropDescriptors(); |
12760 if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map; | 12771 if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map; |
12761 } | 12772 } |
12762 | 12773 |
12763 // Transform the object. | 12774 // Transform the object. |
12764 obj->set_map(Map::cast(new_map)); | 12775 obj->set_map(Map::cast(new_map)); |
12765 obj->map()->set_instance_descriptors(descriptors); | 12776 obj->map()->set_instance_descriptors(descriptors); |
12766 obj->map()->set_unused_property_fields(unused_property_fields); | 12777 obj->map()->set_unused_property_fields(unused_property_fields); |
12767 | 12778 |
12768 obj->set_properties(FixedArray::cast(fields)); | 12779 obj->set_properties(FixedArray::cast(fields)); |
12769 ASSERT(obj->IsJSObject()); | 12780 ASSERT(obj->IsJSObject()); |
12770 | 12781 |
12771 descriptors->SetNextEnumerationIndex(NextEnumerationIndex()); | |
12772 // Check that it really works. | 12782 // Check that it really works. |
12773 ASSERT(obj->HasFastProperties()); | 12783 ASSERT(obj->HasFastProperties()); |
12774 | 12784 |
12775 return obj; | 12785 return obj; |
12776 } | 12786 } |
12777 | 12787 |
12778 | 12788 |
12779 bool ObjectHashSet::Contains(Object* key) { | 12789 bool ObjectHashSet::Contains(Object* key) { |
12780 ASSERT(IsKey(key)); | 12790 ASSERT(IsKey(key)); |
12781 | 12791 |
(...skipping 491 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13273 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); | 13283 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); |
13274 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); | 13284 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); |
13275 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); | 13285 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); |
13276 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); | 13286 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); |
13277 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); | 13287 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); |
13278 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); | 13288 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); |
13279 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); | 13289 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); |
13280 } | 13290 } |
13281 | 13291 |
13282 } } // namespace v8::internal | 13292 } } // namespace v8::internal |
OLD | NEW |