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