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 4743 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4754 object->Print(); | 4754 object->Print(); |
4755 } | 4755 } |
4756 #endif | 4756 #endif |
4757 } | 4757 } |
4758 | 4758 |
4759 | 4759 |
4760 void JSObject::TransformToFastProperties(Handle<JSObject> object, | 4760 void JSObject::TransformToFastProperties(Handle<JSObject> object, |
4761 int unused_property_fields) { | 4761 int unused_property_fields) { |
4762 if (object->HasFastProperties()) return; | 4762 if (object->HasFastProperties()) return; |
4763 ASSERT(!object->IsGlobalObject()); | 4763 ASSERT(!object->IsGlobalObject()); |
4764 CALL_HEAP_FUNCTION_VOID( | 4764 Isolate* isolate = object->GetIsolate(); |
4765 object->GetIsolate(), | 4765 Factory* factory = isolate->factory(); |
4766 object->property_dictionary()->TransformPropertiesToFastFor( | 4766 Handle<NameDictionary> dictionary(object->property_dictionary()); |
4767 *object, unused_property_fields)); | 4767 |
| 4768 // Make sure we preserve dictionary representation if there are too many |
| 4769 // descriptors. |
| 4770 int number_of_elements = dictionary->NumberOfElements(); |
| 4771 if (number_of_elements > kMaxNumberOfDescriptors) return; |
| 4772 |
| 4773 if (number_of_elements != dictionary->NextEnumerationIndex()) { |
| 4774 NameDictionary::DoGenerateNewEnumerationIndices(dictionary); |
| 4775 } |
| 4776 |
| 4777 int instance_descriptor_length = 0; |
| 4778 int number_of_fields = 0; |
| 4779 |
| 4780 // Compute the length of the instance descriptor. |
| 4781 int capacity = dictionary->Capacity(); |
| 4782 for (int i = 0; i < capacity; i++) { |
| 4783 Object* k = dictionary->KeyAt(i); |
| 4784 if (dictionary->IsKey(k)) { |
| 4785 Object* value = dictionary->ValueAt(i); |
| 4786 PropertyType type = dictionary->DetailsAt(i).type(); |
| 4787 ASSERT(type != FIELD); |
| 4788 instance_descriptor_length++; |
| 4789 if (type == NORMAL && !value->IsJSFunction()) { |
| 4790 number_of_fields += 1; |
| 4791 } |
| 4792 } |
| 4793 } |
| 4794 |
| 4795 int inobject_props = object->map()->inobject_properties(); |
| 4796 |
| 4797 // Allocate new map. |
| 4798 Handle<Map> new_map = Map::CopyDropDescriptors(handle(object->map())); |
| 4799 new_map->set_dictionary_map(false); |
| 4800 |
| 4801 if (instance_descriptor_length == 0) { |
| 4802 DisallowHeapAllocation no_gc; |
| 4803 ASSERT_LE(unused_property_fields, inobject_props); |
| 4804 // Transform the object. |
| 4805 new_map->set_unused_property_fields(inobject_props); |
| 4806 object->set_map(*new_map); |
| 4807 object->set_properties(isolate->heap()->empty_fixed_array()); |
| 4808 // Check that it really works. |
| 4809 ASSERT(object->HasFastProperties()); |
| 4810 return; |
| 4811 } |
| 4812 |
| 4813 // Allocate the instance descriptor. |
| 4814 Handle<DescriptorArray> descriptors = DescriptorArray::Allocate( |
| 4815 isolate, instance_descriptor_length); |
| 4816 |
| 4817 int number_of_allocated_fields = |
| 4818 number_of_fields + unused_property_fields - inobject_props; |
| 4819 if (number_of_allocated_fields < 0) { |
| 4820 // There is enough inobject space for all fields (including unused). |
| 4821 number_of_allocated_fields = 0; |
| 4822 unused_property_fields = inobject_props - number_of_fields; |
| 4823 } |
| 4824 |
| 4825 // Allocate the fixed array for the fields. |
| 4826 Handle<FixedArray> fields = factory->NewFixedArray( |
| 4827 number_of_allocated_fields); |
| 4828 |
| 4829 // Fill in the instance descriptor and the fields. |
| 4830 int current_offset = 0; |
| 4831 for (int i = 0; i < capacity; i++) { |
| 4832 Object* k = dictionary->KeyAt(i); |
| 4833 if (dictionary->IsKey(k)) { |
| 4834 Object* value = dictionary->ValueAt(i); |
| 4835 Handle<Name> key; |
| 4836 if (k->IsSymbol()) { |
| 4837 key = handle(Symbol::cast(k)); |
| 4838 } else { |
| 4839 // Ensure the key is a unique name before writing into the |
| 4840 // instance descriptor. |
| 4841 key = factory->InternalizeString(handle(String::cast(k))); |
| 4842 } |
| 4843 |
| 4844 PropertyDetails details = dictionary->DetailsAt(i); |
| 4845 int enumeration_index = details.dictionary_index(); |
| 4846 PropertyType type = details.type(); |
| 4847 |
| 4848 if (value->IsJSFunction()) { |
| 4849 ConstantDescriptor d(key, |
| 4850 handle(value, isolate), |
| 4851 details.attributes()); |
| 4852 descriptors->Set(enumeration_index - 1, &d); |
| 4853 } else if (type == NORMAL) { |
| 4854 if (current_offset < inobject_props) { |
| 4855 object->InObjectPropertyAtPut(current_offset, |
| 4856 value, |
| 4857 UPDATE_WRITE_BARRIER); |
| 4858 } else { |
| 4859 int offset = current_offset - inobject_props; |
| 4860 fields->set(offset, value); |
| 4861 } |
| 4862 FieldDescriptor d(key, |
| 4863 current_offset++, |
| 4864 details.attributes(), |
| 4865 // TODO(verwaest): value->OptimalRepresentation(); |
| 4866 Representation::Tagged()); |
| 4867 descriptors->Set(enumeration_index - 1, &d); |
| 4868 } else if (type == CALLBACKS) { |
| 4869 CallbacksDescriptor d(key, |
| 4870 handle(value, isolate), |
| 4871 details.attributes()); |
| 4872 descriptors->Set(enumeration_index - 1, &d); |
| 4873 } else { |
| 4874 UNREACHABLE(); |
| 4875 } |
| 4876 } |
| 4877 } |
| 4878 ASSERT(current_offset == number_of_fields); |
| 4879 |
| 4880 descriptors->Sort(); |
| 4881 |
| 4882 DisallowHeapAllocation no_gc; |
| 4883 new_map->InitializeDescriptors(*descriptors); |
| 4884 new_map->set_unused_property_fields(unused_property_fields); |
| 4885 |
| 4886 // Transform the object. |
| 4887 object->set_map(*new_map); |
| 4888 |
| 4889 object->set_properties(*fields); |
| 4890 ASSERT(object->IsJSObject()); |
| 4891 |
| 4892 // Check that it really works. |
| 4893 ASSERT(object->HasFastProperties()); |
4768 } | 4894 } |
4769 | 4895 |
4770 | 4896 |
4771 void JSObject::ResetElements(Handle<JSObject> object) { | 4897 void JSObject::ResetElements(Handle<JSObject> object) { |
4772 if (object->map()->is_observed()) { | 4898 if (object->map()->is_observed()) { |
4773 // Maintain invariant that observed elements are always in dictionary mode. | 4899 // Maintain invariant that observed elements are always in dictionary mode. |
4774 Factory* factory = object->GetIsolate()->factory(); | 4900 Factory* factory = object->GetIsolate()->factory(); |
4775 Handle<SeededNumberDictionary> dictionary = | 4901 Handle<SeededNumberDictionary> dictionary = |
4776 factory->NewSeededNumberDictionary(0); | 4902 factory->NewSeededNumberDictionary(0); |
4777 if (object->map() == *factory->sloppy_arguments_elements_map()) { | 4903 if (object->map() == *factory->sloppy_arguments_elements_map()) { |
(...skipping 2045 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6823 if (FLAG_verify_heap && result->is_shared()) { | 6949 if (FLAG_verify_heap && result->is_shared()) { |
6824 result->SharedMapVerify(); | 6950 result->SharedMapVerify(); |
6825 } | 6951 } |
6826 #endif | 6952 #endif |
6827 | 6953 |
6828 return result; | 6954 return result; |
6829 } | 6955 } |
6830 | 6956 |
6831 | 6957 |
6832 Handle<Map> Map::CopyDropDescriptors(Handle<Map> map) { | 6958 Handle<Map> Map::CopyDropDescriptors(Handle<Map> map) { |
6833 CALL_HEAP_FUNCTION(map->GetIsolate(), map->CopyDropDescriptors(), Map); | 6959 Handle<Map> result = RawCopy(map, map->instance_size()); |
6834 } | |
6835 | |
6836 | |
6837 MaybeObject* Map::CopyDropDescriptors() { | |
6838 Map* result; | |
6839 MaybeObject* maybe_result = RawCopy(instance_size()); | |
6840 if (!maybe_result->To(&result)) return maybe_result; | |
6841 | 6960 |
6842 // Please note instance_type and instance_size are set when allocated. | 6961 // Please note instance_type and instance_size are set when allocated. |
6843 result->set_inobject_properties(inobject_properties()); | 6962 result->set_inobject_properties(map->inobject_properties()); |
6844 result->set_unused_property_fields(unused_property_fields()); | 6963 result->set_unused_property_fields(map->unused_property_fields()); |
6845 | 6964 |
6846 result->set_pre_allocated_property_fields(pre_allocated_property_fields()); | 6965 result->set_pre_allocated_property_fields( |
| 6966 map->pre_allocated_property_fields()); |
6847 result->set_is_shared(false); | 6967 result->set_is_shared(false); |
6848 result->ClearCodeCache(GetHeap()); | 6968 result->ClearCodeCache(map->GetHeap()); |
6849 NotifyLeafMapLayoutChange(); | 6969 map->NotifyLeafMapLayoutChange(); |
6850 return result; | 6970 return result; |
6851 } | 6971 } |
6852 | 6972 |
6853 | 6973 |
6854 Handle<Map> Map::ShareDescriptor(Handle<Map> map, | 6974 Handle<Map> Map::ShareDescriptor(Handle<Map> map, |
6855 Handle<DescriptorArray> descriptors, | 6975 Handle<DescriptorArray> descriptors, |
6856 Descriptor* descriptor) { | 6976 Descriptor* descriptor) { |
6857 // Sanity check. This path is only to be taken if the map owns its descriptor | 6977 // Sanity check. This path is only to be taken if the map owns its descriptor |
6858 // array, implying that its NumberOfOwnDescriptors equals the number of | 6978 // array, implying that its NumberOfOwnDescriptors equals the number of |
6859 // descriptors in the descriptor array. | 6979 // descriptors in the descriptor array. |
6860 ASSERT(map->NumberOfOwnDescriptors() == | 6980 ASSERT(map->NumberOfOwnDescriptors() == |
6861 map->instance_descriptors()->number_of_descriptors()); | 6981 map->instance_descriptors()->number_of_descriptors()); |
6862 | 6982 |
6863 Handle<Map> result = Map::CopyDropDescriptors(map); | 6983 Handle<Map> result = Map::CopyDropDescriptors(map); |
6864 Handle<Name> name = descriptor->GetKey(); | 6984 Handle<Name> name = descriptor->GetKey(); |
6865 Handle<TransitionArray> transitions = | 6985 Handle<TransitionArray> transitions = |
6866 TransitionArray::CopyInsert(map, name, result, SIMPLE_TRANSITION); | 6986 TransitionArray::CopyInsert(map, name, result, SIMPLE_TRANSITION); |
6867 | 6987 |
6868 // Ensure there's space for the new descriptor in the shared descriptor array. | 6988 // Ensure there's space for the new descriptor in the shared descriptor array. |
6869 if (descriptors->NumberOfSlackDescriptors() == 0) { | 6989 if (descriptors->NumberOfSlackDescriptors() == 0) { |
6870 int old_size = descriptors->number_of_descriptors(); | 6990 int old_size = descriptors->number_of_descriptors(); |
6871 if (old_size == 0) { | 6991 if (old_size == 0) { |
6872 descriptors = map->GetIsolate()->factory()->NewDescriptorArray(0, 1); | 6992 descriptors = DescriptorArray::Allocate(map->GetIsolate(), 0, 1); |
6873 } else { | 6993 } else { |
6874 Map::EnsureDescriptorSlack(map, old_size < 4 ? 1 : old_size / 2); | 6994 Map::EnsureDescriptorSlack(map, old_size < 4 ? 1 : old_size / 2); |
6875 descriptors = handle(map->instance_descriptors()); | 6995 descriptors = handle(map->instance_descriptors()); |
6876 } | 6996 } |
6877 } | 6997 } |
6878 | 6998 |
6879 // Commit the state atomically. | 6999 // Commit the state atomically. |
6880 DisallowHeapAllocation no_gc; | 7000 DisallowHeapAllocation no_gc; |
6881 | 7001 |
6882 descriptors->Append(descriptor); | 7002 descriptors->Append(descriptor); |
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7130 int enumeration_index, | 7250 int enumeration_index, |
7131 PropertyAttributes attributes, | 7251 PropertyAttributes attributes, |
7132 int slack) { | 7252 int slack) { |
7133 if (enumeration_index + slack == 0) { | 7253 if (enumeration_index + slack == 0) { |
7134 return desc->GetIsolate()->factory()->empty_descriptor_array(); | 7254 return desc->GetIsolate()->factory()->empty_descriptor_array(); |
7135 } | 7255 } |
7136 | 7256 |
7137 int size = enumeration_index; | 7257 int size = enumeration_index; |
7138 | 7258 |
7139 Handle<DescriptorArray> descriptors = | 7259 Handle<DescriptorArray> descriptors = |
7140 desc->GetIsolate()->factory()->NewDescriptorArray(size, slack); | 7260 DescriptorArray::Allocate(desc->GetIsolate(), size, slack); |
7141 DescriptorArray::WhitenessWitness witness(*descriptors); | 7261 DescriptorArray::WhitenessWitness witness(*descriptors); |
7142 | 7262 |
7143 if (attributes != NONE) { | 7263 if (attributes != NONE) { |
7144 for (int i = 0; i < size; ++i) { | 7264 for (int i = 0; i < size; ++i) { |
7145 Object* value = desc->GetValue(i); | 7265 Object* value = desc->GetValue(i); |
7146 PropertyDetails details = desc->GetDetails(i); | 7266 PropertyDetails details = desc->GetDetails(i); |
7147 int mask = DONT_DELETE | DONT_ENUM; | 7267 int mask = DONT_DELETE | DONT_ENUM; |
7148 // READ_ONLY is an invalid attribute for JS setters/getters. | 7268 // READ_ONLY is an invalid attribute for JS setters/getters. |
7149 if (details.type() != CALLBACKS || !value->IsAccessorPair()) { | 7269 if (details.type() != CALLBACKS || !value->IsAccessorPair()) { |
7150 mask |= READ_ONLY; | 7270 mask |= READ_ONLY; |
(...skipping 838 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7989 bool FixedArray::IsEqualTo(FixedArray* other) { | 8109 bool FixedArray::IsEqualTo(FixedArray* other) { |
7990 if (length() != other->length()) return false; | 8110 if (length() != other->length()) return false; |
7991 for (int i = 0 ; i < length(); ++i) { | 8111 for (int i = 0 ; i < length(); ++i) { |
7992 if (get(i) != other->get(i)) return false; | 8112 if (get(i) != other->get(i)) return false; |
7993 } | 8113 } |
7994 return true; | 8114 return true; |
7995 } | 8115 } |
7996 #endif | 8116 #endif |
7997 | 8117 |
7998 | 8118 |
7999 MaybeObject* DescriptorArray::Allocate(Isolate* isolate, | 8119 Handle<DescriptorArray> DescriptorArray::Allocate(Isolate* isolate, |
8000 int number_of_descriptors, | 8120 int number_of_descriptors, |
8001 int slack) { | 8121 int slack) { |
8002 Heap* heap = isolate->heap(); | 8122 ASSERT(0 <= number_of_descriptors); |
| 8123 Factory* factory = isolate->factory(); |
8003 // Do not use DescriptorArray::cast on incomplete object. | 8124 // Do not use DescriptorArray::cast on incomplete object. |
8004 int size = number_of_descriptors + slack; | 8125 int size = number_of_descriptors + slack; |
8005 if (size == 0) return heap->empty_descriptor_array(); | 8126 if (size == 0) return factory->empty_descriptor_array(); |
8006 FixedArray* result; | |
8007 // Allocate the array of keys. | 8127 // Allocate the array of keys. |
8008 MaybeObject* maybe_array = heap->AllocateFixedArray(LengthFor(size)); | 8128 Handle<FixedArray> result = factory->NewFixedArray(LengthFor(size)); |
8009 if (!maybe_array->To(&result)) return maybe_array; | |
8010 | 8129 |
8011 result->set(kDescriptorLengthIndex, Smi::FromInt(number_of_descriptors)); | 8130 result->set(kDescriptorLengthIndex, Smi::FromInt(number_of_descriptors)); |
8012 result->set(kEnumCacheIndex, Smi::FromInt(0)); | 8131 result->set(kEnumCacheIndex, Smi::FromInt(0)); |
8013 return result; | 8132 return Handle<DescriptorArray>::cast(result); |
8014 } | 8133 } |
8015 | 8134 |
8016 | 8135 |
8017 void DescriptorArray::ClearEnumCache() { | 8136 void DescriptorArray::ClearEnumCache() { |
8018 set(kEnumCacheIndex, Smi::FromInt(0)); | 8137 set(kEnumCacheIndex, Smi::FromInt(0)); |
8019 } | 8138 } |
8020 | 8139 |
8021 | 8140 |
8022 void DescriptorArray::Replace(int index, Descriptor* descriptor) { | 8141 void DescriptorArray::Replace(int index, Descriptor* descriptor) { |
8023 descriptor->SetSortedKeyIndex(GetSortedKeyIndex(index)); | 8142 descriptor->SetSortedKeyIndex(GetSortedKeyIndex(index)); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8067 int valid, | 8186 int valid, |
8068 int new_size, | 8187 int new_size, |
8069 int modify_index, | 8188 int modify_index, |
8070 StoreMode store_mode, | 8189 StoreMode store_mode, |
8071 Handle<Map> right_map) { | 8190 Handle<Map> right_map) { |
8072 ASSERT(verbatim <= valid); | 8191 ASSERT(verbatim <= valid); |
8073 ASSERT(valid <= new_size); | 8192 ASSERT(valid <= new_size); |
8074 | 8193 |
8075 // Allocate a new descriptor array large enough to hold the required | 8194 // Allocate a new descriptor array large enough to hold the required |
8076 // descriptors, with minimally the exact same size as this descriptor array. | 8195 // descriptors, with minimally the exact same size as this descriptor array. |
8077 Factory* factory = left_map->GetIsolate()->factory(); | 8196 Isolate* isolate = left_map->GetIsolate(); |
8078 Handle<DescriptorArray> left(left_map->instance_descriptors()); | 8197 Handle<DescriptorArray> left(left_map->instance_descriptors()); |
8079 Handle<DescriptorArray> right(right_map->instance_descriptors()); | 8198 Handle<DescriptorArray> right(right_map->instance_descriptors()); |
8080 Handle<DescriptorArray> result = factory->NewDescriptorArray( | 8199 Handle<DescriptorArray> result = DescriptorArray::Allocate( |
8081 new_size, Max(new_size, right->number_of_descriptors()) - new_size); | 8200 isolate, |
| 8201 new_size, |
| 8202 Max(new_size, right->number_of_descriptors()) - new_size); |
8082 ASSERT(result->length() > left->length() || | 8203 ASSERT(result->length() > left->length() || |
8083 result->NumberOfSlackDescriptors() > 0 || | 8204 result->NumberOfSlackDescriptors() > 0 || |
8084 result->number_of_descriptors() == right->number_of_descriptors()); | 8205 result->number_of_descriptors() == right->number_of_descriptors()); |
8085 ASSERT(result->number_of_descriptors() == new_size); | 8206 ASSERT(result->number_of_descriptors() == new_size); |
8086 | 8207 |
8087 int descriptor; | 8208 int descriptor; |
8088 | 8209 |
8089 // 0 -> |verbatim| | 8210 // 0 -> |verbatim| |
8090 int current_offset = 0; | 8211 int current_offset = 0; |
8091 for (descriptor = 0; descriptor < verbatim; descriptor++) { | 8212 for (descriptor = 0; descriptor < verbatim; descriptor++) { |
(...skipping 3410 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11502 int capacity = (cache->length() - header) / step; | 11623 int capacity = (cache->length() - header) / step; |
11503 int transitions = map->NumberOfProtoTransitions() + 1; | 11624 int transitions = map->NumberOfProtoTransitions() + 1; |
11504 | 11625 |
11505 if (transitions > capacity) { | 11626 if (transitions > capacity) { |
11506 if (capacity > kMaxCachedPrototypeTransitions) return map; | 11627 if (capacity > kMaxCachedPrototypeTransitions) return map; |
11507 | 11628 |
11508 // Grow array by factor 2 over and above what we need. | 11629 // Grow array by factor 2 over and above what we need. |
11509 Factory* factory = map->GetIsolate()->factory(); | 11630 Factory* factory = map->GetIsolate()->factory(); |
11510 cache = factory->CopySizeFixedArray(cache, transitions * 2 * step + header); | 11631 cache = factory->CopySizeFixedArray(cache, transitions * 2 * step + header); |
11511 | 11632 |
11512 CALL_AND_RETRY_OR_DIE(map->GetIsolate(), | 11633 Map::SetPrototypeTransitions(map, cache); |
11513 map->SetPrototypeTransitions(*cache), | |
11514 break, | |
11515 return Handle<Map>()); | |
11516 } | 11634 } |
11517 | 11635 |
11518 // Reload number of transitions as GC might shrink them. | 11636 // Reload number of transitions as GC might shrink them. |
11519 int last = map->NumberOfProtoTransitions(); | 11637 int last = map->NumberOfProtoTransitions(); |
11520 int entry = header + last * step; | 11638 int entry = header + last * step; |
11521 | 11639 |
11522 cache->set(entry + kProtoTransitionPrototypeOffset, *prototype); | 11640 cache->set(entry + kProtoTransitionPrototypeOffset, *prototype); |
11523 cache->set(entry + kProtoTransitionMapOffset, *target_map); | 11641 cache->set(entry + kProtoTransitionMapOffset, *target_map); |
11524 map->SetNumberOfProtoTransitions(last + 1); | 11642 map->SetNumberOfProtoTransitions(last + 1); |
11525 | 11643 |
(...skipping 4058 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
15584 e = PropertyCell::cast(e)->value(); | 15702 e = PropertyCell::cast(e)->value(); |
15585 } | 15703 } |
15586 if (e == value) return k; | 15704 if (e == value) return k; |
15587 } | 15705 } |
15588 } | 15706 } |
15589 Heap* heap = Dictionary<Shape, Key>::GetHeap(); | 15707 Heap* heap = Dictionary<Shape, Key>::GetHeap(); |
15590 return heap->undefined_value(); | 15708 return heap->undefined_value(); |
15591 } | 15709 } |
15592 | 15710 |
15593 | 15711 |
15594 MaybeObject* NameDictionary::TransformPropertiesToFastFor( | |
15595 JSObject* obj, int unused_property_fields) { | |
15596 // Make sure we preserve dictionary representation if there are too many | |
15597 // descriptors. | |
15598 int number_of_elements = NumberOfElements(); | |
15599 if (number_of_elements > kMaxNumberOfDescriptors) return obj; | |
15600 | |
15601 if (number_of_elements != NextEnumerationIndex()) { | |
15602 MaybeObject* maybe_result = GenerateNewEnumerationIndices(); | |
15603 if (maybe_result->IsFailure()) return maybe_result; | |
15604 } | |
15605 | |
15606 int instance_descriptor_length = 0; | |
15607 int number_of_fields = 0; | |
15608 | |
15609 Heap* heap = GetHeap(); | |
15610 | |
15611 // Compute the length of the instance descriptor. | |
15612 int capacity = Capacity(); | |
15613 for (int i = 0; i < capacity; i++) { | |
15614 Object* k = KeyAt(i); | |
15615 if (IsKey(k)) { | |
15616 Object* value = ValueAt(i); | |
15617 PropertyType type = DetailsAt(i).type(); | |
15618 ASSERT(type != FIELD); | |
15619 instance_descriptor_length++; | |
15620 if (type == NORMAL && !value->IsJSFunction()) { | |
15621 number_of_fields += 1; | |
15622 } | |
15623 } | |
15624 } | |
15625 | |
15626 int inobject_props = obj->map()->inobject_properties(); | |
15627 | |
15628 // Allocate new map. | |
15629 Map* new_map; | |
15630 MaybeObject* maybe_new_map = obj->map()->CopyDropDescriptors(); | |
15631 if (!maybe_new_map->To(&new_map)) return maybe_new_map; | |
15632 new_map->set_dictionary_map(false); | |
15633 | |
15634 if (instance_descriptor_length == 0) { | |
15635 ASSERT_LE(unused_property_fields, inobject_props); | |
15636 // Transform the object. | |
15637 new_map->set_unused_property_fields(inobject_props); | |
15638 obj->set_map(new_map); | |
15639 obj->set_properties(heap->empty_fixed_array()); | |
15640 // Check that it really works. | |
15641 ASSERT(obj->HasFastProperties()); | |
15642 return obj; | |
15643 } | |
15644 | |
15645 // Allocate the instance descriptor. | |
15646 DescriptorArray* descriptors; | |
15647 MaybeObject* maybe_descriptors = | |
15648 DescriptorArray::Allocate(GetIsolate(), instance_descriptor_length); | |
15649 if (!maybe_descriptors->To(&descriptors)) { | |
15650 return maybe_descriptors; | |
15651 } | |
15652 | |
15653 DescriptorArray::WhitenessWitness witness(descriptors); | |
15654 | |
15655 int number_of_allocated_fields = | |
15656 number_of_fields + unused_property_fields - inobject_props; | |
15657 if (number_of_allocated_fields < 0) { | |
15658 // There is enough inobject space for all fields (including unused). | |
15659 number_of_allocated_fields = 0; | |
15660 unused_property_fields = inobject_props - number_of_fields; | |
15661 } | |
15662 | |
15663 // Allocate the fixed array for the fields. | |
15664 FixedArray* fields; | |
15665 MaybeObject* maybe_fields = | |
15666 heap->AllocateFixedArray(number_of_allocated_fields); | |
15667 if (!maybe_fields->To(&fields)) return maybe_fields; | |
15668 | |
15669 // Fill in the instance descriptor and the fields. | |
15670 int current_offset = 0; | |
15671 for (int i = 0; i < capacity; i++) { | |
15672 Object* k = KeyAt(i); | |
15673 if (IsKey(k)) { | |
15674 Object* value = ValueAt(i); | |
15675 Name* key; | |
15676 if (k->IsSymbol()) { | |
15677 key = Symbol::cast(k); | |
15678 } else { | |
15679 // Ensure the key is a unique name before writing into the | |
15680 // instance descriptor. | |
15681 MaybeObject* maybe_key = heap->InternalizeString(String::cast(k)); | |
15682 if (!maybe_key->To(&key)) return maybe_key; | |
15683 } | |
15684 | |
15685 PropertyDetails details = DetailsAt(i); | |
15686 int enumeration_index = details.dictionary_index(); | |
15687 PropertyType type = details.type(); | |
15688 | |
15689 if (value->IsJSFunction()) { | |
15690 ConstantDescriptor d(handle(key), | |
15691 handle(value, GetIsolate()), | |
15692 details.attributes()); | |
15693 descriptors->Set(enumeration_index - 1, &d, witness); | |
15694 } else if (type == NORMAL) { | |
15695 if (current_offset < inobject_props) { | |
15696 obj->InObjectPropertyAtPut(current_offset, | |
15697 value, | |
15698 UPDATE_WRITE_BARRIER); | |
15699 } else { | |
15700 int offset = current_offset - inobject_props; | |
15701 fields->set(offset, value); | |
15702 } | |
15703 FieldDescriptor d(handle(key), | |
15704 current_offset++, | |
15705 details.attributes(), | |
15706 // TODO(verwaest): value->OptimalRepresentation(); | |
15707 Representation::Tagged()); | |
15708 descriptors->Set(enumeration_index - 1, &d, witness); | |
15709 } else if (type == CALLBACKS) { | |
15710 CallbacksDescriptor d(handle(key), | |
15711 handle(value, GetIsolate()), | |
15712 details.attributes()); | |
15713 descriptors->Set(enumeration_index - 1, &d, witness); | |
15714 } else { | |
15715 UNREACHABLE(); | |
15716 } | |
15717 } | |
15718 } | |
15719 ASSERT(current_offset == number_of_fields); | |
15720 | |
15721 descriptors->Sort(); | |
15722 | |
15723 new_map->InitializeDescriptors(descriptors); | |
15724 new_map->set_unused_property_fields(unused_property_fields); | |
15725 | |
15726 // Transform the object. | |
15727 obj->set_map(new_map); | |
15728 | |
15729 obj->set_properties(fields); | |
15730 ASSERT(obj->IsJSObject()); | |
15731 | |
15732 // Check that it really works. | |
15733 ASSERT(obj->HasFastProperties()); | |
15734 | |
15735 return obj; | |
15736 } | |
15737 | |
15738 | |
15739 Handle<ObjectHashTable> ObjectHashTable::EnsureCapacity( | 15712 Handle<ObjectHashTable> ObjectHashTable::EnsureCapacity( |
15740 Handle<ObjectHashTable> table, | 15713 Handle<ObjectHashTable> table, |
15741 int n, | 15714 int n, |
15742 Handle<Object> key, | 15715 Handle<Object> key, |
15743 PretenureFlag pretenure) { | 15716 PretenureFlag pretenure) { |
15744 Handle<HashTable<ObjectHashTableShape, Object*> > table_base = table; | 15717 Handle<HashTable<ObjectHashTableShape, Object*> > table_base = table; |
15745 CALL_HEAP_FUNCTION(table_base->GetIsolate(), | 15718 CALL_HEAP_FUNCTION(table_base->GetIsolate(), |
15746 table_base->EnsureCapacity(n, *key, pretenure), | 15719 table_base->EnsureCapacity(n, *key, pretenure), |
15747 ObjectHashTable); | 15720 ObjectHashTable); |
15748 } | 15721 } |
(...skipping 880 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
16629 #define ERROR_MESSAGES_TEXTS(C, T) T, | 16602 #define ERROR_MESSAGES_TEXTS(C, T) T, |
16630 static const char* error_messages_[] = { | 16603 static const char* error_messages_[] = { |
16631 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) | 16604 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) |
16632 }; | 16605 }; |
16633 #undef ERROR_MESSAGES_TEXTS | 16606 #undef ERROR_MESSAGES_TEXTS |
16634 return error_messages_[reason]; | 16607 return error_messages_[reason]; |
16635 } | 16608 } |
16636 | 16609 |
16637 | 16610 |
16638 } } // namespace v8::internal | 16611 } } // namespace v8::internal |
OLD | NEW |