| 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 687 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 698 | 698 |
| 699 Handle<JSArray> GetKeysFor(Handle<JSReceiver> object, bool* threw) { | 699 Handle<JSArray> GetKeysFor(Handle<JSReceiver> object, bool* threw) { |
| 700 Isolate* isolate = object->GetIsolate(); | 700 Isolate* isolate = object->GetIsolate(); |
| 701 isolate->counters()->for_in()->Increment(); | 701 isolate->counters()->for_in()->Increment(); |
| 702 Handle<FixedArray> elements = | 702 Handle<FixedArray> elements = |
| 703 GetKeysInFixedArrayFor(object, INCLUDE_PROTOS, threw); | 703 GetKeysInFixedArrayFor(object, INCLUDE_PROTOS, threw); |
| 704 return isolate->factory()->NewJSArrayWithElements(elements); | 704 return isolate->factory()->NewJSArrayWithElements(elements); |
| 705 } | 705 } |
| 706 | 706 |
| 707 | 707 |
| 708 Handle<FixedArray> ReduceFixedArrayTo(Handle<FixedArray> array, int length) { | |
| 709 ASSERT(array->length() >= length); | |
| 710 if (array->length() == length) return array; | |
| 711 | |
| 712 Handle<FixedArray> new_array = | |
| 713 array->GetIsolate()->factory()->NewFixedArray(length); | |
| 714 for (int i = 0; i < length; ++i) new_array->set(i, array->get(i)); | |
| 715 return new_array; | |
| 716 } | |
| 717 | |
| 718 | |
| 719 Handle<FixedArray> GetEnumPropertyKeys(Handle<JSObject> object, | 708 Handle<FixedArray> GetEnumPropertyKeys(Handle<JSObject> object, |
| 720 bool cache_result) { | 709 bool cache_result) { |
| 721 Isolate* isolate = object->GetIsolate(); | 710 Isolate* isolate = object->GetIsolate(); |
| 722 if (object->HasFastProperties()) { | 711 if (object->HasFastProperties()) { |
| 723 if (object->map()->instance_descriptors()->HasEnumCache()) { | 712 if (object->map()->instance_descriptors()->HasEnumCache()) { |
| 724 int own_property_count = object->map()->EnumLength(); | 713 int own_property_count = object->map()->EnumLength(); |
| 725 // If we have an enum cache, but the enum length of the given map is set | |
| 726 // to kInvalidEnumCache, this means that the map itself has never used the | |
| 727 // present enum cache. The first step to using the cache is to set the | |
| 728 // enum length of the map by counting the number of own descriptors that | |
| 729 // are not DONT_ENUM. | |
| 730 if (own_property_count == Map::kInvalidEnumCache) { | |
| 731 own_property_count = object->map()->NumberOfDescribedProperties( | |
| 732 OWN_DESCRIPTORS, DONT_ENUM); | |
| 733 | 714 |
| 734 if (cache_result) object->map()->SetEnumLength(own_property_count); | 715 // Mark that we have an enum cache if we are allowed to cache it. |
| 716 if (cache_result && own_property_count == Map::kInvalidEnumCache) { |
| 717 int num_enum = object->map()->NumberOfDescribedProperties(DONT_ENUM); |
| 718 object->map()->SetEnumLength(num_enum); |
| 735 } | 719 } |
| 736 | 720 |
| 737 DescriptorArray* desc = object->map()->instance_descriptors(); | 721 DescriptorArray* desc = object->map()->instance_descriptors(); |
| 738 Handle<FixedArray> keys(FixedArray::cast(desc->GetEnumCache()), isolate); | 722 Handle<FixedArray> keys(FixedArray::cast(desc->GetEnumCache()), isolate); |
| 739 | 723 |
| 740 // In case the number of properties required in the enum are actually | 724 isolate->counters()->enum_cache_hits()->Increment(); |
| 741 // present, we can reuse the enum cache. Otherwise, this means that the | 725 return keys; |
| 742 // enum cache was generated for a previous (smaller) version of the | |
| 743 // Descriptor Array. In that case we regenerate the enum cache. | |
| 744 if (own_property_count <= keys->length()) { | |
| 745 isolate->counters()->enum_cache_hits()->Increment(); | |
| 746 return ReduceFixedArrayTo(keys, own_property_count); | |
| 747 } | |
| 748 } | 726 } |
| 749 | 727 |
| 750 Handle<Map> map(object->map()); | 728 Handle<Map> map(object->map()); |
| 751 | 729 |
| 752 if (map->instance_descriptors()->IsEmpty()) { | 730 if (map->instance_descriptors()->IsEmpty()) { |
| 753 isolate->counters()->enum_cache_hits()->Increment(); | 731 isolate->counters()->enum_cache_hits()->Increment(); |
| 754 if (cache_result) map->SetEnumLength(0); | 732 if (cache_result) map->SetEnumLength(0); |
| 755 return isolate->factory()->empty_fixed_array(); | 733 return isolate->factory()->empty_fixed_array(); |
| 756 } | 734 } |
| 757 | 735 |
| 758 isolate->counters()->enum_cache_misses()->Increment(); | 736 isolate->counters()->enum_cache_misses()->Increment(); |
| 759 int num_enum = map->NumberOfDescribedProperties(ALL_DESCRIPTORS, DONT_ENUM); | 737 |
| 738 int num_enum = map->NumberOfDescribedProperties(DONT_ENUM); |
| 760 | 739 |
| 761 Handle<FixedArray> storage = isolate->factory()->NewFixedArray(num_enum); | 740 Handle<FixedArray> storage = isolate->factory()->NewFixedArray(num_enum); |
| 762 Handle<FixedArray> indices = isolate->factory()->NewFixedArray(num_enum); | 741 Handle<FixedArray> indices = isolate->factory()->NewFixedArray(num_enum); |
| 763 | 742 |
| 764 Handle<DescriptorArray> descs = | 743 Handle<DescriptorArray> descs = |
| 765 Handle<DescriptorArray>(object->map()->instance_descriptors(), isolate); | 744 Handle<DescriptorArray>(object->map()->instance_descriptors(), isolate); |
| 766 | 745 |
| 767 int real_size = map->NumberOfOwnDescriptors(); | |
| 768 int enum_size = 0; | |
| 769 int index = 0; | 746 int index = 0; |
| 770 | |
| 771 for (int i = 0; i < descs->number_of_descriptors(); i++) { | 747 for (int i = 0; i < descs->number_of_descriptors(); i++) { |
| 772 PropertyDetails details = descs->GetDetails(i); | 748 PropertyDetails details = descs->GetDetails(i); |
| 773 if (!details.IsDontEnum()) { | 749 if (!details.IsDontEnum()) { |
| 774 if (i < real_size) ++enum_size; | |
| 775 storage->set(index, descs->GetKey(i)); | 750 storage->set(index, descs->GetKey(i)); |
| 776 if (!indices.is_null()) { | 751 if (!indices.is_null()) { |
| 777 if (details.type() != FIELD) { | 752 if (details.type() != FIELD) { |
| 778 indices = Handle<FixedArray>(); | 753 indices = Handle<FixedArray>(); |
| 779 } else { | 754 } else { |
| 780 int field_index = Descriptor::IndexFromValue(descs->GetValue(i)); | 755 int field_index = Descriptor::IndexFromValue(descs->GetValue(i)); |
| 781 if (field_index >= map->inobject_properties()) { | 756 if (field_index >= map->inobject_properties()) { |
| 782 field_index = -(field_index - map->inobject_properties() + 1); | 757 field_index = -(field_index - map->inobject_properties() + 1); |
| 783 } | 758 } |
| 784 indices->set(index, Smi::FromInt(field_index)); | 759 indices->set(index, Smi::FromInt(field_index)); |
| 785 } | 760 } |
| 786 } | 761 } |
| 787 index++; | 762 index++; |
| 788 } | 763 } |
| 789 } | 764 } |
| 790 ASSERT(index == storage->length()); | 765 ASSERT(index == storage->length()); |
| 791 | 766 |
| 792 Handle<FixedArray> bridge_storage = | 767 Handle<FixedArray> bridge_storage = |
| 793 isolate->factory()->NewFixedArray( | 768 isolate->factory()->NewFixedArray( |
| 794 DescriptorArray::kEnumCacheBridgeLength); | 769 DescriptorArray::kEnumCacheBridgeLength); |
| 795 DescriptorArray* desc = object->map()->instance_descriptors(); | 770 DescriptorArray* desc = object->map()->instance_descriptors(); |
| 796 desc->SetEnumCache(*bridge_storage, | 771 desc->SetEnumCache(*bridge_storage, |
| 797 *storage, | 772 *storage, |
| 798 indices.is_null() ? Object::cast(Smi::FromInt(0)) | 773 indices.is_null() ? Object::cast(Smi::FromInt(0)) |
| 799 : Object::cast(*indices)); | 774 : Object::cast(*indices)); |
| 800 if (cache_result) { | 775 if (cache_result) { |
| 801 object->map()->SetEnumLength(enum_size); | 776 object->map()->SetEnumLength(index); |
| 802 } | 777 } |
| 803 | 778 return storage; |
| 804 return ReduceFixedArrayTo(storage, enum_size); | |
| 805 } else { | 779 } else { |
| 806 Handle<StringDictionary> dictionary(object->property_dictionary()); | 780 Handle<StringDictionary> dictionary(object->property_dictionary()); |
| 807 | 781 |
| 808 int length = dictionary->NumberOfElements(); | 782 int length = dictionary->NumberOfElements(); |
| 809 if (length == 0) { | 783 if (length == 0) { |
| 810 return Handle<FixedArray>(isolate->heap()->empty_fixed_array()); | 784 return Handle<FixedArray>(isolate->heap()->empty_fixed_array()); |
| 811 } | 785 } |
| 812 | 786 |
| 813 // The enumeration array is generated by allocating an array big enough to | 787 // The enumeration array is generated by allocating an array big enough to |
| 814 // hold all properties that have been seen, whether they are are deleted or | 788 // hold all properties that have been seen, whether they are are deleted or |
| (...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1058 data->next = prev_next_; | 1032 data->next = prev_next_; |
| 1059 data->limit = prev_limit_; | 1033 data->limit = prev_limit_; |
| 1060 #ifdef DEBUG | 1034 #ifdef DEBUG |
| 1061 handles_detached_ = true; | 1035 handles_detached_ = true; |
| 1062 #endif | 1036 #endif |
| 1063 return deferred; | 1037 return deferred; |
| 1064 } | 1038 } |
| 1065 | 1039 |
| 1066 | 1040 |
| 1067 } } // namespace v8::internal | 1041 } } // namespace v8::internal |
| OLD | NEW |