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