| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 51 #endif | 51 #endif |
| 52 | 52 |
| 53 namespace v8 { | 53 namespace v8 { |
| 54 namespace internal { | 54 namespace internal { |
| 55 | 55 |
| 56 // Getters and setters are stored in a fixed array property. These are | 56 // Getters and setters are stored in a fixed array property. These are |
| 57 // constants for their indices. | 57 // constants for their indices. |
| 58 const int kGetterIndex = 0; | 58 const int kGetterIndex = 0; |
| 59 const int kSetterIndex = 1; | 59 const int kSetterIndex = 1; |
| 60 | 60 |
| 61 uint64_t FixedDoubleArray::kHoleNanInt64 = -1; |
| 62 uint64_t FixedDoubleArray::kCanonicalNonHoleNanLower32 = 0x7FF00000; |
| 63 uint64_t FixedDoubleArray::kCanonicalNonHoleNanInt64 = |
| 64 kCanonicalNonHoleNanLower32 << 32; |
| 61 | 65 |
| 62 MUST_USE_RESULT static MaybeObject* CreateJSValue(JSFunction* constructor, | 66 MUST_USE_RESULT static MaybeObject* CreateJSValue(JSFunction* constructor, |
| 63 Object* value) { | 67 Object* value) { |
| 64 Object* result; | 68 Object* result; |
| 65 { MaybeObject* maybe_result = | 69 { MaybeObject* maybe_result = |
| 66 constructor->GetHeap()->AllocateJSObject(constructor); | 70 constructor->GetHeap()->AllocateJSObject(constructor); |
| 67 if (!maybe_result->ToObject(&result)) return maybe_result; | 71 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 68 } | 72 } |
| 69 JSValue::cast(result)->set_value(value); | 73 JSValue::cast(result)->set_value(value); |
| 70 return result; | 74 return result; |
| (...skipping 1100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1171 } | 1175 } |
| 1172 break; | 1176 break; |
| 1173 } | 1177 } |
| 1174 return; | 1178 return; |
| 1175 } | 1179 } |
| 1176 | 1180 |
| 1177 switch (type) { | 1181 switch (type) { |
| 1178 case FIXED_ARRAY_TYPE: | 1182 case FIXED_ARRAY_TYPE: |
| 1179 FixedArray::BodyDescriptor::IterateBody(this, object_size, v); | 1183 FixedArray::BodyDescriptor::IterateBody(this, object_size, v); |
| 1180 break; | 1184 break; |
| 1185 case FIXED_DOUBLE_ARRAY_TYPE: |
| 1186 break; |
| 1181 case JS_OBJECT_TYPE: | 1187 case JS_OBJECT_TYPE: |
| 1182 case JS_CONTEXT_EXTENSION_OBJECT_TYPE: | 1188 case JS_CONTEXT_EXTENSION_OBJECT_TYPE: |
| 1183 case JS_VALUE_TYPE: | 1189 case JS_VALUE_TYPE: |
| 1184 case JS_ARRAY_TYPE: | 1190 case JS_ARRAY_TYPE: |
| 1185 case JS_REGEXP_TYPE: | 1191 case JS_REGEXP_TYPE: |
| 1186 case JS_GLOBAL_PROXY_TYPE: | 1192 case JS_GLOBAL_PROXY_TYPE: |
| 1187 case JS_GLOBAL_OBJECT_TYPE: | 1193 case JS_GLOBAL_OBJECT_TYPE: |
| 1188 case JS_BUILTINS_OBJECT_TYPE: | 1194 case JS_BUILTINS_OBJECT_TYPE: |
| 1189 case JS_MESSAGE_OBJECT_TYPE: | 1195 case JS_MESSAGE_OBJECT_TYPE: |
| 1190 JSObject::BodyDescriptor::IterateBody(this, object_size, v); | 1196 JSObject::BodyDescriptor::IterateBody(this, object_size, v); |
| (...skipping 1602 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2793 ASSERT(!IsGlobalObject()); | 2799 ASSERT(!IsGlobalObject()); |
| 2794 return property_dictionary()-> | 2800 return property_dictionary()-> |
| 2795 TransformPropertiesToFastFor(this, unused_property_fields); | 2801 TransformPropertiesToFastFor(this, unused_property_fields); |
| 2796 } | 2802 } |
| 2797 | 2803 |
| 2798 | 2804 |
| 2799 MaybeObject* JSObject::NormalizeElements() { | 2805 MaybeObject* JSObject::NormalizeElements() { |
| 2800 ASSERT(!HasExternalArrayElements()); | 2806 ASSERT(!HasExternalArrayElements()); |
| 2801 if (HasDictionaryElements()) return this; | 2807 if (HasDictionaryElements()) return this; |
| 2802 Map* old_map = map(); | 2808 Map* old_map = map(); |
| 2803 ASSERT(old_map->has_fast_elements()); | 2809 ASSERT(old_map->has_fast_elements() || old_map->has_fast_double_elements()); |
| 2804 | 2810 |
| 2805 Object* obj; | 2811 Object* obj; |
| 2806 { MaybeObject* maybe_obj = old_map->GetSlowElementsMap(); | 2812 { MaybeObject* maybe_obj = old_map->GetSlowElementsMap(); |
| 2807 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 2813 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 2808 } | 2814 } |
| 2809 Map* new_map = Map::cast(obj); | 2815 Map* new_map = Map::cast(obj); |
| 2810 | 2816 |
| 2811 // Get number of entries. | 2817 // Get number of entries. |
| 2812 FixedArray* array = FixedArray::cast(elements()); | 2818 FixedArrayBase* array = FixedArrayBase::cast(elements()); |
| 2813 | 2819 |
| 2814 // Compute the effective length. | 2820 // Compute the effective length. |
| 2815 int length = IsJSArray() ? | 2821 int length = IsJSArray() ? |
| 2816 Smi::cast(JSArray::cast(this)->length())->value() : | 2822 Smi::cast(JSArray::cast(this)->length())->value() : |
| 2817 array->length(); | 2823 array->length(); |
| 2818 { MaybeObject* maybe_obj = NumberDictionary::Allocate(length); | 2824 { MaybeObject* maybe_obj = NumberDictionary::Allocate(length); |
| 2819 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 2825 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 2820 } | 2826 } |
| 2827 bool has_double_elements = old_map->has_fast_double_elements(); |
| 2821 NumberDictionary* dictionary = NumberDictionary::cast(obj); | 2828 NumberDictionary* dictionary = NumberDictionary::cast(obj); |
| 2822 // Copy entries. | 2829 // Copy entries. |
| 2823 for (int i = 0; i < length; i++) { | 2830 for (int i = 0; i < length; i++) { |
| 2824 Object* value = array->get(i); | 2831 Object* value = NULL; |
| 2832 if (has_double_elements) { |
| 2833 FixedDoubleArray* double_array = FixedDoubleArray::cast(array); |
| 2834 if (double_array->is_the_hole(i)) { |
| 2835 value = GetIsolate()->heap()->the_hole_value(); |
| 2836 } else { |
| 2837 // Objects must be allocated in the old object space, since the |
| 2838 // overall number of HeapNumbers needed for the conversion might |
| 2839 // exceed the capacity of new space, and we would fail repeatedly |
| 2840 // trying to convert the FixedDoubleArray. |
| 2841 MaybeObject* maybe_value_object = |
| 2842 GetHeap()->AllocateHeapNumber(double_array->get(i), TENURED); |
| 2843 if (!maybe_value_object->ToObject(&value)) return maybe_value_object; |
| 2844 } |
| 2845 } else { |
| 2846 ASSERT(old_map->has_fast_elements()); |
| 2847 FixedArray* fixed_array = FixedArray::cast(array); |
| 2848 value = fixed_array->get(i); |
| 2849 } |
| 2850 PropertyDetails details = PropertyDetails(NONE, NORMAL); |
| 2825 if (!value->IsTheHole()) { | 2851 if (!value->IsTheHole()) { |
| 2826 PropertyDetails details = PropertyDetails(NONE, NORMAL); | |
| 2827 Object* result; | 2852 Object* result; |
| 2828 { MaybeObject* maybe_result = | 2853 MaybeObject* maybe_result = |
| 2829 dictionary->AddNumberEntry(i, array->get(i), details); | 2854 dictionary->AddNumberEntry(i, value, details); |
| 2830 if (!maybe_result->ToObject(&result)) return maybe_result; | 2855 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 2831 } | |
| 2832 dictionary = NumberDictionary::cast(result); | 2856 dictionary = NumberDictionary::cast(result); |
| 2833 } | 2857 } |
| 2834 } | 2858 } |
| 2835 // Switch to using the dictionary as the backing storage for | 2859 // Switch to using the dictionary as the backing storage for |
| 2836 // elements. Set the new map first to satify the elements type | 2860 // elements. Set the new map first to satify the elements type |
| 2837 // assert in set_elements(). | 2861 // assert in set_elements(). |
| 2838 set_map(new_map); | 2862 set_map(new_map); |
| 2839 set_elements(dictionary); | 2863 set_elements(dictionary); |
| 2840 | 2864 |
| 2841 new_map->heap()->isolate()->counters()->elements_to_dictionary()-> | 2865 new_map->heap()->isolate()->counters()->elements_to_dictionary()-> |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2991 } | 3015 } |
| 2992 return DeleteElementWithInterceptor(index); | 3016 return DeleteElementWithInterceptor(index); |
| 2993 } | 3017 } |
| 2994 | 3018 |
| 2995 switch (GetElementsKind()) { | 3019 switch (GetElementsKind()) { |
| 2996 case FAST_ELEMENTS: { | 3020 case FAST_ELEMENTS: { |
| 2997 Object* obj; | 3021 Object* obj; |
| 2998 { MaybeObject* maybe_obj = EnsureWritableFastElements(); | 3022 { MaybeObject* maybe_obj = EnsureWritableFastElements(); |
| 2999 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 3023 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 3000 } | 3024 } |
| 3001 uint32_t length = IsJSArray() ? | 3025 int length = IsJSArray() |
| 3002 static_cast<uint32_t>(Smi::cast(JSArray::cast(this)->length())->value()) : | 3026 ? Smi::cast(JSArray::cast(this)->length())->value() |
| 3003 static_cast<uint32_t>(FixedArray::cast(elements())->length()); | 3027 : FixedArray::cast(elements())->length(); |
| 3004 if (index < length) { | 3028 if (index < static_cast<uint32_t>(length)) { |
| 3005 FixedArray::cast(elements())->set_the_hole(index); | 3029 FixedArray::cast(elements())->set_the_hole(index); |
| 3006 } | 3030 } |
| 3007 break; | 3031 break; |
| 3008 } | 3032 } |
| 3033 case FAST_DOUBLE_ELEMENTS: { |
| 3034 int length = IsJSArray() |
| 3035 ? Smi::cast(JSArray::cast(this)->length())->value() |
| 3036 : FixedArray::cast(elements())->length(); |
| 3037 if (index < static_cast<uint32_t>(length)) { |
| 3038 FixedDoubleArray::cast(elements())->set_the_hole(index); |
| 3039 } |
| 3040 break; |
| 3041 } |
| 3009 case EXTERNAL_PIXEL_ELEMENTS: | 3042 case EXTERNAL_PIXEL_ELEMENTS: |
| 3010 case EXTERNAL_BYTE_ELEMENTS: | 3043 case EXTERNAL_BYTE_ELEMENTS: |
| 3011 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 3044 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 3012 case EXTERNAL_SHORT_ELEMENTS: | 3045 case EXTERNAL_SHORT_ELEMENTS: |
| 3013 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 3046 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 3014 case EXTERNAL_INT_ELEMENTS: | 3047 case EXTERNAL_INT_ELEMENTS: |
| 3015 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 3048 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| 3016 case EXTERNAL_FLOAT_ELEMENTS: | 3049 case EXTERNAL_FLOAT_ELEMENTS: |
| 3017 case EXTERNAL_DOUBLE_ELEMENTS: | 3050 case EXTERNAL_DOUBLE_ELEMENTS: |
| 3018 // Pixel and external array elements cannot be deleted. Just | 3051 // Pixel and external array elements cannot be deleted. Just |
| (...skipping 4072 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7091 { MaybeObject* maybe_obj = heap->AllocateFixedArrayWithHoles(capacity); | 7124 { MaybeObject* maybe_obj = heap->AllocateFixedArrayWithHoles(capacity); |
| 7092 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 7125 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 7093 } | 7126 } |
| 7094 FixedArray* elems = FixedArray::cast(obj); | 7127 FixedArray* elems = FixedArray::cast(obj); |
| 7095 | 7128 |
| 7096 { MaybeObject* maybe_obj = map()->GetFastElementsMap(); | 7129 { MaybeObject* maybe_obj = map()->GetFastElementsMap(); |
| 7097 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 7130 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 7098 } | 7131 } |
| 7099 Map* new_map = Map::cast(obj); | 7132 Map* new_map = Map::cast(obj); |
| 7100 | 7133 |
| 7101 AssertNoAllocation no_gc; | |
| 7102 WriteBarrierMode mode = elems->GetWriteBarrierMode(no_gc); | |
| 7103 switch (GetElementsKind()) { | 7134 switch (GetElementsKind()) { |
| 7104 case FAST_ELEMENTS: { | 7135 case FAST_ELEMENTS: { |
| 7136 AssertNoAllocation no_gc; |
| 7137 WriteBarrierMode mode = elems->GetWriteBarrierMode(no_gc); |
| 7105 FixedArray* old_elements = FixedArray::cast(elements()); | 7138 FixedArray* old_elements = FixedArray::cast(elements()); |
| 7106 uint32_t old_length = static_cast<uint32_t>(old_elements->length()); | 7139 uint32_t old_length = static_cast<uint32_t>(old_elements->length()); |
| 7107 // Fill out the new array with this content and array holes. | 7140 // Fill out the new array with this content and array holes. |
| 7108 for (uint32_t i = 0; i < old_length; i++) { | 7141 for (uint32_t i = 0; i < old_length; i++) { |
| 7109 elems->set(i, old_elements->get(i), mode); | 7142 elems->set(i, old_elements->get(i), mode); |
| 7110 } | 7143 } |
| 7111 break; | 7144 break; |
| 7112 } | 7145 } |
| 7146 case FAST_DOUBLE_ELEMENTS: { |
| 7147 FixedDoubleArray* old_elements = FixedDoubleArray::cast(elements()); |
| 7148 uint32_t old_length = static_cast<uint32_t>(old_elements->length()); |
| 7149 // Fill out the new array with this content and array holes. |
| 7150 for (uint32_t i = 0; i < old_length; i++) { |
| 7151 if (!old_elements->is_the_hole(i)) { |
| 7152 Object* obj; |
| 7153 // Objects must be allocated in the old object space, since the |
| 7154 // overall number of HeapNumbers needed for the conversion might |
| 7155 // exceed the capacity of new space, and we would fail repeatedly |
| 7156 // trying to convert the FixedDoubleArray. |
| 7157 MaybeObject* maybe_value_object = |
| 7158 GetHeap()->AllocateHeapNumber(old_elements->get(i), TENURED); |
| 7159 if (!maybe_value_object->ToObject(&obj)) return maybe_value_object; |
| 7160 // Force write barrier. It's not worth trying to exploit |
| 7161 // elems->GetWriteBarrierMode(), since it requires an |
| 7162 // AssertNoAllocation stack object that would have to be positioned |
| 7163 // after the HeapNumber allocation anyway. |
| 7164 elems->set(i, obj, UPDATE_WRITE_BARRIER); |
| 7165 } |
| 7166 } |
| 7167 break; |
| 7168 } |
| 7113 case DICTIONARY_ELEMENTS: { | 7169 case DICTIONARY_ELEMENTS: { |
| 7170 AssertNoAllocation no_gc; |
| 7171 WriteBarrierMode mode = elems->GetWriteBarrierMode(no_gc); |
| 7114 NumberDictionary* dictionary = NumberDictionary::cast(elements()); | 7172 NumberDictionary* dictionary = NumberDictionary::cast(elements()); |
| 7115 for (int i = 0; i < dictionary->Capacity(); i++) { | 7173 for (int i = 0; i < dictionary->Capacity(); i++) { |
| 7116 Object* key = dictionary->KeyAt(i); | 7174 Object* key = dictionary->KeyAt(i); |
| 7117 if (key->IsNumber()) { | 7175 if (key->IsNumber()) { |
| 7118 uint32_t entry = static_cast<uint32_t>(key->Number()); | 7176 uint32_t entry = static_cast<uint32_t>(key->Number()); |
| 7119 elems->set(entry, dictionary->ValueAt(i), mode); | 7177 elems->set(entry, dictionary->ValueAt(i), mode); |
| 7120 } | 7178 } |
| 7121 } | 7179 } |
| 7122 break; | 7180 break; |
| 7123 } | 7181 } |
| 7124 default: | 7182 default: |
| 7125 UNREACHABLE(); | 7183 UNREACHABLE(); |
| 7126 break; | 7184 break; |
| 7127 } | 7185 } |
| 7128 | 7186 |
| 7129 set_map(new_map); | 7187 set_map(new_map); |
| 7130 set_elements(elems); | 7188 set_elements(elems); |
| 7131 | 7189 |
| 7132 if (IsJSArray()) { | 7190 if (IsJSArray()) { |
| 7133 JSArray::cast(this)->set_length(Smi::FromInt(length)); | 7191 JSArray::cast(this)->set_length(Smi::FromInt(length)); |
| 7134 } | 7192 } |
| 7135 | 7193 |
| 7136 return this; | 7194 return this; |
| 7137 } | 7195 } |
| 7138 | 7196 |
| 7139 | 7197 |
| 7198 MaybeObject* JSObject::SetFastDoubleElementsCapacityAndLength( |
| 7199 int capacity, |
| 7200 int length) { |
| 7201 Heap* heap = GetHeap(); |
| 7202 // We should never end in here with a pixel or external array. |
| 7203 ASSERT(!HasExternalArrayElements()); |
| 7204 |
| 7205 Object* obj; |
| 7206 { MaybeObject* maybe_obj = |
| 7207 heap->AllocateUninitializedFixedDoubleArray(capacity); |
| 7208 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 7209 } |
| 7210 FixedDoubleArray* elems = FixedDoubleArray::cast(obj); |
| 7211 |
| 7212 { MaybeObject* maybe_obj = map()->GetFastDoubleElementsMap(); |
| 7213 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 7214 } |
| 7215 Map* new_map = Map::cast(obj); |
| 7216 |
| 7217 AssertNoAllocation no_gc; |
| 7218 switch (GetElementsKind()) { |
| 7219 case FAST_ELEMENTS: { |
| 7220 elems->Initialize(FixedArray::cast(elements())); |
| 7221 break; |
| 7222 } |
| 7223 case FAST_DOUBLE_ELEMENTS: { |
| 7224 elems->Initialize(FixedDoubleArray::cast(elements())); |
| 7225 break; |
| 7226 } |
| 7227 case DICTIONARY_ELEMENTS: { |
| 7228 elems->Initialize(NumberDictionary::cast(elements())); |
| 7229 break; |
| 7230 } |
| 7231 default: |
| 7232 UNREACHABLE(); |
| 7233 break; |
| 7234 } |
| 7235 |
| 7236 set_map(new_map); |
| 7237 set_elements(elems); |
| 7238 |
| 7239 if (IsJSArray()) { |
| 7240 JSArray::cast(this)->set_length(Smi::FromInt(length)); |
| 7241 } |
| 7242 |
| 7243 return this; |
| 7244 } |
| 7245 |
| 7246 |
| 7140 MaybeObject* JSObject::SetSlowElements(Object* len) { | 7247 MaybeObject* JSObject::SetSlowElements(Object* len) { |
| 7141 // We should never end in here with a pixel or external array. | 7248 // We should never end in here with a pixel or external array. |
| 7142 ASSERT(!HasExternalArrayElements()); | 7249 ASSERT(!HasExternalArrayElements()); |
| 7143 | 7250 |
| 7144 uint32_t new_length = static_cast<uint32_t>(len->Number()); | 7251 uint32_t new_length = static_cast<uint32_t>(len->Number()); |
| 7145 | 7252 |
| 7146 switch (GetElementsKind()) { | 7253 switch (GetElementsKind()) { |
| 7147 case FAST_ELEMENTS: { | 7254 case FAST_ELEMENTS: { |
| 7148 // Make sure we never try to shrink dense arrays into sparse arrays. | 7255 // Make sure we never try to shrink dense arrays into sparse arrays. |
| 7149 ASSERT(static_cast<uint32_t>(FixedArray::cast(elements())->length()) <= | 7256 ASSERT(static_cast<uint32_t>(FixedArray::cast(elements())->length()) <= |
| (...skipping 701 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7851 if (check_prototype && | 7958 if (check_prototype && |
| 7852 (index >= elms_length || elms->get(index)->IsTheHole())) { | 7959 (index >= elms_length || elms->get(index)->IsTheHole())) { |
| 7853 bool found; | 7960 bool found; |
| 7854 MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index, | 7961 MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index, |
| 7855 value, | 7962 value, |
| 7856 &found, | 7963 &found, |
| 7857 strict_mode); | 7964 strict_mode); |
| 7858 if (found) return result; | 7965 if (found) return result; |
| 7859 } | 7966 } |
| 7860 | 7967 |
| 7861 | |
| 7862 // Check whether there is extra space in fixed array.. | 7968 // Check whether there is extra space in fixed array.. |
| 7863 if (index < elms_length) { | 7969 if (index < elms_length) { |
| 7864 elms->set(index, value); | 7970 elms->set(index, value); |
| 7865 if (IsJSArray()) { | 7971 if (IsJSArray()) { |
| 7866 // Update the length of the array if needed. | 7972 // Update the length of the array if needed. |
| 7867 uint32_t array_length = 0; | 7973 uint32_t array_length = 0; |
| 7868 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length)); | 7974 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length)); |
| 7869 if (index >= array_length) { | 7975 if (index >= array_length) { |
| 7870 JSArray::cast(this)->set_length(Smi::FromInt(index + 1)); | 7976 JSArray::cast(this)->set_length(Smi::FromInt(index + 1)); |
| 7871 } | 7977 } |
| (...skipping 21 matching lines...) Expand all Loading... |
| 7893 // Otherwise default to slow case. | 7999 // Otherwise default to slow case. |
| 7894 Object* obj; | 8000 Object* obj; |
| 7895 { MaybeObject* maybe_obj = NormalizeElements(); | 8001 { MaybeObject* maybe_obj = NormalizeElements(); |
| 7896 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 8002 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 7897 } | 8003 } |
| 7898 ASSERT(HasDictionaryElements()); | 8004 ASSERT(HasDictionaryElements()); |
| 7899 return SetElement(index, value, strict_mode, check_prototype); | 8005 return SetElement(index, value, strict_mode, check_prototype); |
| 7900 } | 8006 } |
| 7901 | 8007 |
| 7902 | 8008 |
| 8009 MUST_USE_RESULT MaybeObject* JSObject::SetFastDoubleElement( |
| 8010 uint32_t index, |
| 8011 Object* value, |
| 8012 StrictModeFlag strict_mode, |
| 8013 bool check_prototype) { |
| 8014 ASSERT(HasFastDoubleElements()); |
| 8015 |
| 8016 FixedDoubleArray* elms = FixedDoubleArray::cast(elements()); |
| 8017 uint32_t elms_length = static_cast<uint32_t>(elms->length()); |
| 8018 |
| 8019 // If storing to an element that isn't in the array, pass the store request |
| 8020 // up the prototype chain before storing in the receiver's elements. |
| 8021 if (check_prototype && |
| 8022 (index >= elms_length || elms->is_the_hole(index))) { |
| 8023 bool found; |
| 8024 MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index, |
| 8025 value, |
| 8026 &found, |
| 8027 strict_mode); |
| 8028 if (found) return result; |
| 8029 } |
| 8030 |
| 8031 // If the value object is not a heap number, switch to fast elements and try |
| 8032 // again. |
| 8033 bool value_is_smi = value->IsSmi(); |
| 8034 if (!value->IsNumber()) { |
| 8035 Object* obj; |
| 8036 uint32_t length = elms_length; |
| 8037 if (IsJSArray()) { |
| 8038 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length)); |
| 8039 } |
| 8040 MaybeObject* maybe_obj = |
| 8041 SetFastElementsCapacityAndLength(elms_length, length); |
| 8042 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 8043 return SetFastElement(index, value, strict_mode, check_prototype); |
| 8044 } |
| 8045 |
| 8046 double double_value = value_is_smi |
| 8047 ? static_cast<double>(Smi::cast(value)->value()) |
| 8048 : HeapNumber::cast(value)->value(); |
| 8049 |
| 8050 // Check whether there is extra space in the fixed array. |
| 8051 if (index < elms_length) { |
| 8052 elms->set(index, double_value); |
| 8053 if (IsJSArray()) { |
| 8054 // Update the length of the array if needed. |
| 8055 uint32_t array_length = 0; |
| 8056 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length)); |
| 8057 if (index >= array_length) { |
| 8058 JSArray::cast(this)->set_length(Smi::FromInt(index + 1)); |
| 8059 } |
| 8060 } |
| 8061 return value; |
| 8062 } |
| 8063 |
| 8064 // Allow gap in fast case. |
| 8065 if ((index - elms_length) < kMaxGap) { |
| 8066 // Try allocating extra space. |
| 8067 int new_capacity = NewElementsCapacity(index+1); |
| 8068 if (new_capacity <= kMaxFastElementsLength || |
| 8069 !ShouldConvertToSlowElements(new_capacity)) { |
| 8070 ASSERT(static_cast<uint32_t>(new_capacity) > index); |
| 8071 Object* obj; |
| 8072 { MaybeObject* maybe_obj = |
| 8073 SetFastDoubleElementsCapacityAndLength(new_capacity, |
| 8074 index + 1); |
| 8075 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 8076 } |
| 8077 FixedDoubleArray::cast(elements())->set(index, double_value); |
| 8078 return value; |
| 8079 } |
| 8080 } |
| 8081 |
| 8082 // Otherwise default to slow case. |
| 8083 Object* obj; |
| 8084 { MaybeObject* maybe_obj = NormalizeElements(); |
| 8085 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 8086 } |
| 8087 ASSERT(HasDictionaryElements()); |
| 8088 return SetElement(index, value, strict_mode, check_prototype); |
| 8089 } |
| 8090 |
| 8091 |
| 7903 MaybeObject* JSObject::SetElement(uint32_t index, | 8092 MaybeObject* JSObject::SetElement(uint32_t index, |
| 7904 Object* value, | 8093 Object* value, |
| 7905 StrictModeFlag strict_mode, | 8094 StrictModeFlag strict_mode, |
| 7906 bool check_prototype) { | 8095 bool check_prototype) { |
| 7907 // Check access rights if needed. | 8096 // Check access rights if needed. |
| 7908 if (IsAccessCheckNeeded()) { | 8097 if (IsAccessCheckNeeded()) { |
| 7909 Heap* heap = GetHeap(); | 8098 Heap* heap = GetHeap(); |
| 7910 if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_SET)) { | 8099 if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_SET)) { |
| 7911 HandleScope scope; | 8100 HandleScope scope; |
| 7912 Handle<Object> value_handle(value); | 8101 Handle<Object> value_handle(value); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 7942 | 8131 |
| 7943 MaybeObject* JSObject::SetElementWithoutInterceptor(uint32_t index, | 8132 MaybeObject* JSObject::SetElementWithoutInterceptor(uint32_t index, |
| 7944 Object* value, | 8133 Object* value, |
| 7945 StrictModeFlag strict_mode, | 8134 StrictModeFlag strict_mode, |
| 7946 bool check_prototype) { | 8135 bool check_prototype) { |
| 7947 Isolate* isolate = GetIsolate(); | 8136 Isolate* isolate = GetIsolate(); |
| 7948 switch (GetElementsKind()) { | 8137 switch (GetElementsKind()) { |
| 7949 case FAST_ELEMENTS: | 8138 case FAST_ELEMENTS: |
| 7950 // Fast case. | 8139 // Fast case. |
| 7951 return SetFastElement(index, value, strict_mode, check_prototype); | 8140 return SetFastElement(index, value, strict_mode, check_prototype); |
| 8141 case FAST_DOUBLE_ELEMENTS: |
| 8142 return SetFastDoubleElement(index, value, strict_mode, check_prototype); |
| 7952 case EXTERNAL_PIXEL_ELEMENTS: { | 8143 case EXTERNAL_PIXEL_ELEMENTS: { |
| 7953 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements()); | 8144 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements()); |
| 7954 return pixels->SetValue(index, value); | 8145 return pixels->SetValue(index, value); |
| 7955 } | 8146 } |
| 7956 case EXTERNAL_BYTE_ELEMENTS: { | 8147 case EXTERNAL_BYTE_ELEMENTS: { |
| 7957 ExternalByteArray* array = ExternalByteArray::cast(elements()); | 8148 ExternalByteArray* array = ExternalByteArray::cast(elements()); |
| 7958 return array->SetValue(index, value); | 8149 return array->SetValue(index, value); |
| 7959 } | 8150 } |
| 7960 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: { | 8151 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: { |
| 7961 ExternalUnsignedByteArray* array = | 8152 ExternalUnsignedByteArray* array = |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8065 } | 8256 } |
| 8066 | 8257 |
| 8067 // Attempt to put this object back in fast case. | 8258 // Attempt to put this object back in fast case. |
| 8068 if (ShouldConvertToFastElements()) { | 8259 if (ShouldConvertToFastElements()) { |
| 8069 uint32_t new_length = 0; | 8260 uint32_t new_length = 0; |
| 8070 if (IsJSArray()) { | 8261 if (IsJSArray()) { |
| 8071 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&new_length)); | 8262 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&new_length)); |
| 8072 } else { | 8263 } else { |
| 8073 new_length = NumberDictionary::cast(elements())->max_number_key() + 1; | 8264 new_length = NumberDictionary::cast(elements())->max_number_key() + 1; |
| 8074 } | 8265 } |
| 8075 Object* obj; | 8266 if (ShouldConvertToFastDoubleElements()) { |
| 8076 { MaybeObject* maybe_obj = | 8267 Object* obj; |
| 8077 SetFastElementsCapacityAndLength(new_length, new_length); | 8268 { MaybeObject* maybe_obj = |
| 8078 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 8269 SetFastDoubleElementsCapacityAndLength(new_length, new_length); |
| 8270 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 8271 } |
| 8272 #ifdef DEBUG |
| 8273 if (FLAG_trace_normalization) { |
| 8274 PrintF("Object elements are fast double case again:\n"); |
| 8275 Print(); |
| 8276 } |
| 8277 #endif |
| 8278 } else { |
| 8279 Object* obj; |
| 8280 { MaybeObject* maybe_obj = |
| 8281 SetFastElementsCapacityAndLength(new_length, new_length); |
| 8282 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 8283 } |
| 8284 #ifdef DEBUG |
| 8285 if (FLAG_trace_normalization) { |
| 8286 PrintF("Object elements are fast case again:\n"); |
| 8287 Print(); |
| 8288 } |
| 8289 #endif |
| 8079 } | 8290 } |
| 8080 #ifdef DEBUG | |
| 8081 if (FLAG_trace_normalization) { | |
| 8082 PrintF("Object elements are fast case again:\n"); | |
| 8083 Print(); | |
| 8084 } | |
| 8085 #endif | |
| 8086 } | 8291 } |
| 8087 | 8292 |
| 8088 return value; | 8293 return value; |
| 8089 } | 8294 } |
| 8090 default: | |
| 8091 UNREACHABLE(); | |
| 8092 break; | |
| 8093 } | 8295 } |
| 8094 // All possible cases have been handled above. Add a return to avoid the | 8296 // All possible cases have been handled above. Add a return to avoid the |
| 8095 // complaints from the compiler. | 8297 // complaints from the compiler. |
| 8096 UNREACHABLE(); | 8298 UNREACHABLE(); |
| 8097 return isolate->heap()->null_value(); | 8299 return isolate->heap()->null_value(); |
| 8098 } | 8300 } |
| 8099 | 8301 |
| 8100 | 8302 |
| 8101 MaybeObject* JSArray::JSArrayUpdateLengthFromIndex(uint32_t index, | 8303 MaybeObject* JSArray::JSArrayUpdateLengthFromIndex(uint32_t index, |
| 8102 Object* value) { | 8304 Object* value) { |
| (...skipping 19 matching lines...) Expand all Loading... |
| 8122 // JSArray::length cannot change. | 8324 // JSArray::length cannot change. |
| 8123 switch (GetElementsKind()) { | 8325 switch (GetElementsKind()) { |
| 8124 case FAST_ELEMENTS: { | 8326 case FAST_ELEMENTS: { |
| 8125 FixedArray* elms = FixedArray::cast(elements()); | 8327 FixedArray* elms = FixedArray::cast(elements()); |
| 8126 if (index < static_cast<uint32_t>(elms->length())) { | 8328 if (index < static_cast<uint32_t>(elms->length())) { |
| 8127 Object* value = elms->get(index); | 8329 Object* value = elms->get(index); |
| 8128 if (!value->IsTheHole()) return value; | 8330 if (!value->IsTheHole()) return value; |
| 8129 } | 8331 } |
| 8130 break; | 8332 break; |
| 8131 } | 8333 } |
| 8334 case FAST_DOUBLE_ELEMENTS: { |
| 8335 FixedDoubleArray* elms = FixedDoubleArray::cast(elements()); |
| 8336 if (index < static_cast<uint32_t>(elms->length())) { |
| 8337 if (!elms->is_the_hole(index)) { |
| 8338 return GetHeap()->NumberFromDouble(elms->get(index)); |
| 8339 } |
| 8340 } |
| 8341 break; |
| 8342 } |
| 8132 case EXTERNAL_PIXEL_ELEMENTS: | 8343 case EXTERNAL_PIXEL_ELEMENTS: |
| 8133 case EXTERNAL_BYTE_ELEMENTS: | 8344 case EXTERNAL_BYTE_ELEMENTS: |
| 8134 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 8345 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 8135 case EXTERNAL_SHORT_ELEMENTS: | 8346 case EXTERNAL_SHORT_ELEMENTS: |
| 8136 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 8347 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 8137 case EXTERNAL_INT_ELEMENTS: | 8348 case EXTERNAL_INT_ELEMENTS: |
| 8138 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 8349 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| 8139 case EXTERNAL_FLOAT_ELEMENTS: | 8350 case EXTERNAL_FLOAT_ELEMENTS: |
| 8140 case EXTERNAL_DOUBLE_ELEMENTS: { | 8351 case EXTERNAL_DOUBLE_ELEMENTS: { |
| 8141 MaybeObject* maybe_value = GetExternalElement(index); | 8352 MaybeObject* maybe_value = GetExternalElement(index); |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8225 // JSArray::length cannot change. | 8436 // JSArray::length cannot change. |
| 8226 switch (GetElementsKind()) { | 8437 switch (GetElementsKind()) { |
| 8227 case FAST_ELEMENTS: { | 8438 case FAST_ELEMENTS: { |
| 8228 FixedArray* elms = FixedArray::cast(elements()); | 8439 FixedArray* elms = FixedArray::cast(elements()); |
| 8229 if (index < static_cast<uint32_t>(elms->length())) { | 8440 if (index < static_cast<uint32_t>(elms->length())) { |
| 8230 Object* value = elms->get(index); | 8441 Object* value = elms->get(index); |
| 8231 if (!value->IsTheHole()) return value; | 8442 if (!value->IsTheHole()) return value; |
| 8232 } | 8443 } |
| 8233 break; | 8444 break; |
| 8234 } | 8445 } |
| 8446 case FAST_DOUBLE_ELEMENTS: { |
| 8447 FixedDoubleArray* elms = FixedDoubleArray::cast(elements()); |
| 8448 if (index < static_cast<uint32_t>(elms->length())) { |
| 8449 if (!elms->is_the_hole(index)) { |
| 8450 double double_value = elms->get(index); |
| 8451 return GetHeap()->NumberFromDouble(double_value); |
| 8452 } |
| 8453 } |
| 8454 break; |
| 8455 } |
| 8235 case EXTERNAL_PIXEL_ELEMENTS: | 8456 case EXTERNAL_PIXEL_ELEMENTS: |
| 8236 case EXTERNAL_BYTE_ELEMENTS: | 8457 case EXTERNAL_BYTE_ELEMENTS: |
| 8237 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 8458 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 8238 case EXTERNAL_SHORT_ELEMENTS: | 8459 case EXTERNAL_SHORT_ELEMENTS: |
| 8239 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 8460 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 8240 case EXTERNAL_INT_ELEMENTS: | 8461 case EXTERNAL_INT_ELEMENTS: |
| 8241 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 8462 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| 8242 case EXTERNAL_FLOAT_ELEMENTS: | 8463 case EXTERNAL_FLOAT_ELEMENTS: |
| 8243 case EXTERNAL_DOUBLE_ELEMENTS: { | 8464 case EXTERNAL_DOUBLE_ELEMENTS: { |
| 8244 MaybeObject* maybe_value = GetExternalElement(index); | 8465 MaybeObject* maybe_value = GetExternalElement(index); |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8344 break; | 8565 break; |
| 8345 } | 8566 } |
| 8346 case EXTERNAL_DOUBLE_ELEMENTS: { | 8567 case EXTERNAL_DOUBLE_ELEMENTS: { |
| 8347 ExternalDoubleArray* array = ExternalDoubleArray::cast(elements()); | 8568 ExternalDoubleArray* array = ExternalDoubleArray::cast(elements()); |
| 8348 if (index < static_cast<uint32_t>(array->length())) { | 8569 if (index < static_cast<uint32_t>(array->length())) { |
| 8349 double value = array->get(index); | 8570 double value = array->get(index); |
| 8350 return GetHeap()->AllocateHeapNumber(value); | 8571 return GetHeap()->AllocateHeapNumber(value); |
| 8351 } | 8572 } |
| 8352 break; | 8573 break; |
| 8353 } | 8574 } |
| 8575 case FAST_DOUBLE_ELEMENTS: |
| 8354 case FAST_ELEMENTS: | 8576 case FAST_ELEMENTS: |
| 8355 case DICTIONARY_ELEMENTS: | 8577 case DICTIONARY_ELEMENTS: |
| 8356 UNREACHABLE(); | 8578 UNREACHABLE(); |
| 8357 break; | 8579 break; |
| 8358 } | 8580 } |
| 8359 return GetHeap()->undefined_value(); | 8581 return GetHeap()->undefined_value(); |
| 8360 } | 8582 } |
| 8361 | 8583 |
| 8362 | 8584 |
| 8363 bool JSObject::HasDenseElements() { | 8585 bool JSObject::HasDenseElements() { |
| 8364 int capacity = 0; | 8586 int capacity = 0; |
| 8365 int number_of_elements = 0; | 8587 int number_of_elements = 0; |
| 8366 | 8588 |
| 8367 switch (GetElementsKind()) { | 8589 switch (GetElementsKind()) { |
| 8368 case FAST_ELEMENTS: { | 8590 case FAST_ELEMENTS: { |
| 8369 FixedArray* elms = FixedArray::cast(elements()); | 8591 FixedArray* elms = FixedArray::cast(elements()); |
| 8370 capacity = elms->length(); | 8592 capacity = elms->length(); |
| 8371 for (int i = 0; i < capacity; i++) { | 8593 for (int i = 0; i < capacity; i++) { |
| 8372 if (!elms->get(i)->IsTheHole()) number_of_elements++; | 8594 if (!elms->get(i)->IsTheHole()) number_of_elements++; |
| 8373 } | 8595 } |
| 8374 break; | 8596 break; |
| 8375 } | 8597 } |
| 8598 case FAST_DOUBLE_ELEMENTS: { |
| 8599 FixedDoubleArray* elms = FixedDoubleArray::cast(elements()); |
| 8600 capacity = elms->length(); |
| 8601 for (int i = 0; i < capacity; i++) { |
| 8602 if (!elms->is_the_hole(i)) number_of_elements++; |
| 8603 } |
| 8604 break; |
| 8605 } |
| 8376 case EXTERNAL_PIXEL_ELEMENTS: | 8606 case EXTERNAL_PIXEL_ELEMENTS: |
| 8377 case EXTERNAL_BYTE_ELEMENTS: | 8607 case EXTERNAL_BYTE_ELEMENTS: |
| 8378 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 8608 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 8379 case EXTERNAL_SHORT_ELEMENTS: | 8609 case EXTERNAL_SHORT_ELEMENTS: |
| 8380 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 8610 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 8381 case EXTERNAL_INT_ELEMENTS: | 8611 case EXTERNAL_INT_ELEMENTS: |
| 8382 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 8612 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| 8383 case EXTERNAL_FLOAT_ELEMENTS: | 8613 case EXTERNAL_FLOAT_ELEMENTS: |
| 8384 case EXTERNAL_DOUBLE_ELEMENTS: { | 8614 case EXTERNAL_DOUBLE_ELEMENTS: { |
| 8385 return true; | 8615 return true; |
| 8386 } | 8616 } |
| 8387 case DICTIONARY_ELEMENTS: { | 8617 case DICTIONARY_ELEMENTS: { |
| 8388 NumberDictionary* dictionary = NumberDictionary::cast(elements()); | 8618 NumberDictionary* dictionary = NumberDictionary::cast(elements()); |
| 8389 capacity = dictionary->Capacity(); | 8619 capacity = dictionary->Capacity(); |
| 8390 number_of_elements = dictionary->NumberOfElements(); | 8620 number_of_elements = dictionary->NumberOfElements(); |
| 8391 break; | 8621 break; |
| 8392 } | 8622 } |
| 8393 default: | 8623 default: |
| 8394 UNREACHABLE(); | 8624 UNREACHABLE(); |
| 8395 break; | 8625 break; |
| 8396 } | 8626 } |
| 8397 | 8627 |
| 8398 if (capacity == 0) return true; | 8628 if (capacity == 0) return true; |
| 8399 return (number_of_elements > (capacity / 2)); | 8629 return (number_of_elements > (capacity / 2)); |
| 8400 } | 8630 } |
| 8401 | 8631 |
| 8402 | 8632 |
| 8403 bool JSObject::ShouldConvertToSlowElements(int new_capacity) { | 8633 bool JSObject::ShouldConvertToSlowElements(int new_capacity) { |
| 8404 ASSERT(HasFastElements()); | |
| 8405 // Keep the array in fast case if the current backing storage is | 8634 // Keep the array in fast case if the current backing storage is |
| 8406 // almost filled and if the new capacity is no more than twice the | 8635 // almost filled and if the new capacity is no more than twice the |
| 8407 // old capacity. | 8636 // old capacity. |
| 8408 int elements_length = FixedArray::cast(elements())->length(); | 8637 int elements_length = 0; |
| 8638 if (HasFastElements()) { |
| 8639 elements_length = FixedArray::cast(elements())->length(); |
| 8640 } else if (HasFastDoubleElements()) { |
| 8641 elements_length = FixedDoubleArray::cast(elements())->length(); |
| 8642 } else { |
| 8643 UNREACHABLE(); |
| 8644 } |
| 8409 return !HasDenseElements() || ((new_capacity / 2) > elements_length); | 8645 return !HasDenseElements() || ((new_capacity / 2) > elements_length); |
| 8410 } | 8646 } |
| 8411 | 8647 |
| 8412 | 8648 |
| 8413 bool JSObject::ShouldConvertToFastElements() { | 8649 bool JSObject::ShouldConvertToFastElements() { |
| 8414 ASSERT(HasDictionaryElements()); | 8650 ASSERT(HasDictionaryElements()); |
| 8415 NumberDictionary* dictionary = NumberDictionary::cast(elements()); | 8651 NumberDictionary* dictionary = NumberDictionary::cast(elements()); |
| 8416 // If the elements are sparse, we should not go back to fast case. | 8652 // If the elements are sparse, we should not go back to fast case. |
| 8417 if (!HasDenseElements()) return false; | 8653 if (!HasDenseElements()) return false; |
| 8418 // If an element has been added at a very high index in the elements | 8654 // If an element has been added at a very high index in the elements |
| 8419 // dictionary, we cannot go back to fast case. | 8655 // dictionary, we cannot go back to fast case. |
| 8420 if (dictionary->requires_slow_elements()) return false; | 8656 if (dictionary->requires_slow_elements()) return false; |
| 8421 // An object requiring access checks is never allowed to have fast | 8657 // An object requiring access checks is never allowed to have fast |
| 8422 // elements. If it had fast elements we would skip security checks. | 8658 // elements. If it had fast elements we would skip security checks. |
| 8423 if (IsAccessCheckNeeded()) return false; | 8659 if (IsAccessCheckNeeded()) return false; |
| 8424 // If the dictionary backing storage takes up roughly half as much | 8660 // If the dictionary backing storage takes up roughly half as much |
| 8425 // space as a fast-case backing storage would the array should have | 8661 // space as a fast-case backing storage would the array should have |
| 8426 // fast elements. | 8662 // fast elements. |
| 8427 uint32_t length = 0; | 8663 uint32_t length = 0; |
| 8428 if (IsJSArray()) { | 8664 if (IsJSArray()) { |
| 8429 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length)); | 8665 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length)); |
| 8430 } else { | 8666 } else { |
| 8431 length = dictionary->max_number_key(); | 8667 length = dictionary->max_number_key(); |
| 8432 } | 8668 } |
| 8433 return static_cast<uint32_t>(dictionary->Capacity()) >= | 8669 return static_cast<uint32_t>(dictionary->Capacity()) >= |
| 8434 (length / (2 * NumberDictionary::kEntrySize)); | 8670 (length / (2 * NumberDictionary::kEntrySize)); |
| 8435 } | 8671 } |
| 8436 | 8672 |
| 8437 | 8673 |
| 8674 bool JSObject::ShouldConvertToFastDoubleElements() { |
| 8675 if (FLAG_unbox_double_arrays) { |
| 8676 ASSERT(HasDictionaryElements()); |
| 8677 NumberDictionary* dictionary = NumberDictionary::cast(elements()); |
| 8678 for (int i = 0; i < dictionary->Capacity(); i++) { |
| 8679 Object* key = dictionary->KeyAt(i); |
| 8680 if (key->IsNumber()) { |
| 8681 if (!dictionary->ValueAt(i)->IsNumber()) return false; |
| 8682 } |
| 8683 } |
| 8684 return true; |
| 8685 } else { |
| 8686 return false; |
| 8687 } |
| 8688 } |
| 8689 |
| 8690 |
| 8438 // Certain compilers request function template instantiation when they | 8691 // Certain compilers request function template instantiation when they |
| 8439 // see the definition of the other template functions in the | 8692 // see the definition of the other template functions in the |
| 8440 // class. This requires us to have the template functions put | 8693 // class. This requires us to have the template functions put |
| 8441 // together, so even though this function belongs in objects-debug.cc, | 8694 // together, so even though this function belongs in objects-debug.cc, |
| 8442 // we keep it here instead to satisfy certain compilers. | 8695 // we keep it here instead to satisfy certain compilers. |
| 8443 #ifdef OBJECT_PRINT | 8696 #ifdef OBJECT_PRINT |
| 8444 template<typename Shape, typename Key> | 8697 template<typename Shape, typename Key> |
| 8445 void Dictionary<Shape, Key>::Print(FILE* out) { | 8698 void Dictionary<Shape, Key>::Print(FILE* out) { |
| 8446 int capacity = HashTable<Shape, Key>::Capacity(); | 8699 int capacity = HashTable<Shape, Key>::Capacity(); |
| 8447 for (int i = 0; i < capacity; i++) { | 8700 for (int i = 0; i < capacity; i++) { |
| (...skipping 2507 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10955 if (break_point_objects()->IsUndefined()) return 0; | 11208 if (break_point_objects()->IsUndefined()) return 0; |
| 10956 // Single beak point. | 11209 // Single beak point. |
| 10957 if (!break_point_objects()->IsFixedArray()) return 1; | 11210 if (!break_point_objects()->IsFixedArray()) return 1; |
| 10958 // Multiple break points. | 11211 // Multiple break points. |
| 10959 return FixedArray::cast(break_point_objects())->length(); | 11212 return FixedArray::cast(break_point_objects())->length(); |
| 10960 } | 11213 } |
| 10961 #endif | 11214 #endif |
| 10962 | 11215 |
| 10963 | 11216 |
| 10964 } } // namespace v8::internal | 11217 } } // namespace v8::internal |
| OLD | NEW |