Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(52)

Side by Side Diff: src/objects.cc

Issue 7089002: Implement core support for FixedDoubleArrays. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: review feedback Created 9 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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);
2851 ASSERT(value != NULL);
2825 if (!value->IsTheHole()) { 2852 if (!value->IsTheHole()) {
2826 PropertyDetails details = PropertyDetails(NONE, NORMAL);
2827 Object* result; 2853 Object* result;
2828 { MaybeObject* maybe_result = 2854 MaybeObject* maybe_result =
2829 dictionary->AddNumberEntry(i, array->get(i), details); 2855 dictionary->AddNumberEntry(i, value, details);
2830 if (!maybe_result->ToObject(&result)) return maybe_result; 2856 if (!maybe_result->ToObject(&result)) return maybe_result;
2831 }
2832 dictionary = NumberDictionary::cast(result); 2857 dictionary = NumberDictionary::cast(result);
2833 } 2858 }
2834 } 2859 }
2835 // Switch to using the dictionary as the backing storage for 2860 // Switch to using the dictionary as the backing storage for
2836 // elements. Set the new map first to satify the elements type 2861 // elements. Set the new map first to satify the elements type
2837 // assert in set_elements(). 2862 // assert in set_elements().
2838 set_map(new_map); 2863 set_map(new_map);
2839 set_elements(dictionary); 2864 set_elements(dictionary);
2840 2865
2841 new_map->heap()->isolate()->counters()->elements_to_dictionary()-> 2866 new_map->heap()->isolate()->counters()->elements_to_dictionary()->
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
2991 } 3016 }
2992 return DeleteElementWithInterceptor(index); 3017 return DeleteElementWithInterceptor(index);
2993 } 3018 }
2994 3019
2995 switch (GetElementsKind()) { 3020 switch (GetElementsKind()) {
2996 case FAST_ELEMENTS: { 3021 case FAST_ELEMENTS: {
2997 Object* obj; 3022 Object* obj;
2998 { MaybeObject* maybe_obj = EnsureWritableFastElements(); 3023 { MaybeObject* maybe_obj = EnsureWritableFastElements();
2999 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 3024 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
3000 } 3025 }
3001 uint32_t length = IsJSArray() ? 3026 int length = IsJSArray()
3002 static_cast<uint32_t>(Smi::cast(JSArray::cast(this)->length())->value()) : 3027 ? Smi::cast(JSArray::cast(this)->length())->value()
3003 static_cast<uint32_t>(FixedArray::cast(elements())->length()); 3028 : FixedArray::cast(elements())->length();
3004 if (index < length) { 3029 if (index < static_cast<uint32_t>(length)) {
3005 FixedArray::cast(elements())->set_the_hole(index); 3030 FixedArray::cast(elements())->set_the_hole(index);
3006 } 3031 }
3007 break; 3032 break;
3008 } 3033 }
3034 case FAST_DOUBLE_ELEMENTS: {
3035 int length = IsJSArray()
3036 ? Smi::cast(JSArray::cast(this)->length())->value()
3037 : FixedArray::cast(elements())->length();
3038 if (index < static_cast<uint32_t>(length)) {
3039 FixedDoubleArray::cast(elements())->set_the_hole(index);
3040 }
3041 break;
3042 }
3009 case EXTERNAL_PIXEL_ELEMENTS: 3043 case EXTERNAL_PIXEL_ELEMENTS:
3010 case EXTERNAL_BYTE_ELEMENTS: 3044 case EXTERNAL_BYTE_ELEMENTS:
3011 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 3045 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
3012 case EXTERNAL_SHORT_ELEMENTS: 3046 case EXTERNAL_SHORT_ELEMENTS:
3013 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 3047 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
3014 case EXTERNAL_INT_ELEMENTS: 3048 case EXTERNAL_INT_ELEMENTS:
3015 case EXTERNAL_UNSIGNED_INT_ELEMENTS: 3049 case EXTERNAL_UNSIGNED_INT_ELEMENTS:
3016 case EXTERNAL_FLOAT_ELEMENTS: 3050 case EXTERNAL_FLOAT_ELEMENTS:
3017 case EXTERNAL_DOUBLE_ELEMENTS: 3051 case EXTERNAL_DOUBLE_ELEMENTS:
3018 // Pixel and external array elements cannot be deleted. Just 3052 // Pixel and external array elements cannot be deleted. Just
(...skipping 4072 matching lines...) Expand 10 before | Expand all | Expand 10 after
7091 { MaybeObject* maybe_obj = heap->AllocateFixedArrayWithHoles(capacity); 7125 { MaybeObject* maybe_obj = heap->AllocateFixedArrayWithHoles(capacity);
7092 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 7126 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
7093 } 7127 }
7094 FixedArray* elems = FixedArray::cast(obj); 7128 FixedArray* elems = FixedArray::cast(obj);
7095 7129
7096 { MaybeObject* maybe_obj = map()->GetFastElementsMap(); 7130 { MaybeObject* maybe_obj = map()->GetFastElementsMap();
7097 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 7131 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
7098 } 7132 }
7099 Map* new_map = Map::cast(obj); 7133 Map* new_map = Map::cast(obj);
7100 7134
7101 AssertNoAllocation no_gc;
7102 WriteBarrierMode mode = elems->GetWriteBarrierMode(no_gc);
7103 switch (GetElementsKind()) { 7135 switch (GetElementsKind()) {
7104 case FAST_ELEMENTS: { 7136 case FAST_ELEMENTS: {
7137 AssertNoAllocation no_gc;
7138 WriteBarrierMode mode = elems->GetWriteBarrierMode(no_gc);
7105 FixedArray* old_elements = FixedArray::cast(elements()); 7139 FixedArray* old_elements = FixedArray::cast(elements());
7106 uint32_t old_length = static_cast<uint32_t>(old_elements->length()); 7140 uint32_t old_length = static_cast<uint32_t>(old_elements->length());
7107 // Fill out the new array with this content and array holes. 7141 // Fill out the new array with this content and array holes.
7108 for (uint32_t i = 0; i < old_length; i++) { 7142 for (uint32_t i = 0; i < old_length; i++) {
7109 elems->set(i, old_elements->get(i), mode); 7143 elems->set(i, old_elements->get(i), mode);
7110 } 7144 }
7111 break; 7145 break;
7112 } 7146 }
7147 case FAST_DOUBLE_ELEMENTS: {
7148 FixedDoubleArray* old_elements = FixedDoubleArray::cast(elements());
7149 uint32_t old_length = static_cast<uint32_t>(old_elements->length());
7150 // Fill out the new array with this content and array holes.
7151 for (uint32_t i = 0; i < old_length; i++) {
7152 if (!old_elements->is_the_hole(i)) {
7153 Object* obj;
7154 // Objects must be allocated in the old object space, since the
7155 // overall number of HeapNumbers needed for the conversion might
7156 // exceed the capacity of new space, and we would fail repeatedly
7157 // trying to convert the FixedDoubleArray.
7158 MaybeObject* maybe_value_object =
7159 GetHeap()->AllocateHeapNumber(old_elements->get(i), TENURED);
7160 if (!maybe_value_object->ToObject(&obj)) return maybe_value_object;
7161 // Force write barrier. It's not worth trying to exploit
7162 // elems->GetWriteBarrierMode(), since it requires an
7163 // AssertNoAllocation stack object that would have to be positioned
7164 // after the HeapNumber allocation anyway.
7165 elems->set(i, obj, UPDATE_WRITE_BARRIER);
7166 }
7167 }
7168 break;
7169 }
7113 case DICTIONARY_ELEMENTS: { 7170 case DICTIONARY_ELEMENTS: {
7171 AssertNoAllocation no_gc;
7172 WriteBarrierMode mode = elems->GetWriteBarrierMode(no_gc);
7114 NumberDictionary* dictionary = NumberDictionary::cast(elements()); 7173 NumberDictionary* dictionary = NumberDictionary::cast(elements());
7115 for (int i = 0; i < dictionary->Capacity(); i++) { 7174 for (int i = 0; i < dictionary->Capacity(); i++) {
7116 Object* key = dictionary->KeyAt(i); 7175 Object* key = dictionary->KeyAt(i);
7117 if (key->IsNumber()) { 7176 if (key->IsNumber()) {
7118 uint32_t entry = static_cast<uint32_t>(key->Number()); 7177 uint32_t entry = static_cast<uint32_t>(key->Number());
7119 elems->set(entry, dictionary->ValueAt(i), mode); 7178 elems->set(entry, dictionary->ValueAt(i), mode);
7120 } 7179 }
7121 } 7180 }
7122 break; 7181 break;
7123 } 7182 }
7124 default: 7183 default:
7125 UNREACHABLE(); 7184 UNREACHABLE();
7126 break; 7185 break;
7127 } 7186 }
7128 7187
7129 set_map(new_map); 7188 set_map(new_map);
7130 set_elements(elems); 7189 set_elements(elems);
7131 7190
7132 if (IsJSArray()) { 7191 if (IsJSArray()) {
7133 JSArray::cast(this)->set_length(Smi::FromInt(length)); 7192 JSArray::cast(this)->set_length(Smi::FromInt(length));
7134 } 7193 }
7135 7194
7136 return this; 7195 return this;
7137 } 7196 }
7138 7197
7139 7198
7199 MaybeObject* JSObject::SetFastDoubleElementsCapacityAndLength(
7200 int capacity,
7201 int length) {
7202 Heap* heap = GetHeap();
7203 // We should never end in here with a pixel or external array.
7204 ASSERT(!HasExternalArrayElements());
7205
7206 Object* obj;
7207 { MaybeObject* maybe_obj =
7208 heap->AllocateUninitializedFixedDoubleArray(capacity);
7209 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
7210 }
7211 FixedDoubleArray* elems = FixedDoubleArray::cast(obj);
7212
7213 { MaybeObject* maybe_obj = map()->GetFastDoubleElementsMap();
7214 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
7215 }
7216 Map* new_map = Map::cast(obj);
7217
7218 AssertNoAllocation no_gc;
7219 switch (GetElementsKind()) {
7220 case FAST_ELEMENTS: {
7221 elems->Initialize(FixedArray::cast(elements()));
7222 break;
7223 }
7224 case FAST_DOUBLE_ELEMENTS: {
7225 elems->Initialize(FixedDoubleArray::cast(elements()));
7226 break;
7227 }
7228 case DICTIONARY_ELEMENTS: {
7229 elems->Initialize(NumberDictionary::cast(elements()));
7230 break;
7231 }
7232 default:
7233 UNREACHABLE();
7234 break;
7235 }
7236
7237 set_map(new_map);
7238 set_elements(elems);
7239
7240 if (IsJSArray()) {
7241 JSArray::cast(this)->set_length(Smi::FromInt(length));
7242 }
7243
7244 return this;
7245 }
7246
7247
7140 MaybeObject* JSObject::SetSlowElements(Object* len) { 7248 MaybeObject* JSObject::SetSlowElements(Object* len) {
7141 // We should never end in here with a pixel or external array. 7249 // We should never end in here with a pixel or external array.
7142 ASSERT(!HasExternalArrayElements()); 7250 ASSERT(!HasExternalArrayElements());
7143 7251
7144 uint32_t new_length = static_cast<uint32_t>(len->Number()); 7252 uint32_t new_length = static_cast<uint32_t>(len->Number());
7145 7253
7146 switch (GetElementsKind()) { 7254 switch (GetElementsKind()) {
7147 case FAST_ELEMENTS: { 7255 case FAST_ELEMENTS: {
7148 // Make sure we never try to shrink dense arrays into sparse arrays. 7256 // Make sure we never try to shrink dense arrays into sparse arrays.
7149 ASSERT(static_cast<uint32_t>(FixedArray::cast(elements())->length()) <= 7257 ASSERT(static_cast<uint32_t>(FixedArray::cast(elements())->length()) <=
(...skipping 701 matching lines...) Expand 10 before | Expand all | Expand 10 after
7851 if (check_prototype && 7959 if (check_prototype &&
7852 (index >= elms_length || elms->get(index)->IsTheHole())) { 7960 (index >= elms_length || elms->get(index)->IsTheHole())) {
7853 bool found; 7961 bool found;
7854 MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index, 7962 MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index,
7855 value, 7963 value,
7856 &found, 7964 &found,
7857 strict_mode); 7965 strict_mode);
7858 if (found) return result; 7966 if (found) return result;
7859 } 7967 }
7860 7968
7861
7862 // Check whether there is extra space in fixed array.. 7969 // Check whether there is extra space in fixed array..
7863 if (index < elms_length) { 7970 if (index < elms_length) {
7864 elms->set(index, value); 7971 elms->set(index, value);
7865 if (IsJSArray()) { 7972 if (IsJSArray()) {
7866 // Update the length of the array if needed. 7973 // Update the length of the array if needed.
7867 uint32_t array_length = 0; 7974 uint32_t array_length = 0;
7868 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length)); 7975 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length));
7869 if (index >= array_length) { 7976 if (index >= array_length) {
7870 JSArray::cast(this)->set_length(Smi::FromInt(index + 1)); 7977 JSArray::cast(this)->set_length(Smi::FromInt(index + 1));
7871 } 7978 }
(...skipping 21 matching lines...) Expand all
7893 // Otherwise default to slow case. 8000 // Otherwise default to slow case.
7894 Object* obj; 8001 Object* obj;
7895 { MaybeObject* maybe_obj = NormalizeElements(); 8002 { MaybeObject* maybe_obj = NormalizeElements();
7896 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 8003 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
7897 } 8004 }
7898 ASSERT(HasDictionaryElements()); 8005 ASSERT(HasDictionaryElements());
7899 return SetElement(index, value, strict_mode, check_prototype); 8006 return SetElement(index, value, strict_mode, check_prototype);
7900 } 8007 }
7901 8008
7902 8009
8010 MUST_USE_RESULT MaybeObject* JSObject::SetFastDoubleElement(
8011 uint32_t index,
8012 Object* value,
8013 StrictModeFlag strict_mode,
8014 bool check_prototype) {
8015 ASSERT(HasFastDoubleElements());
8016
8017 FixedDoubleArray* elms = FixedDoubleArray::cast(elements());
8018 uint32_t elms_length = static_cast<uint32_t>(elms->length());
8019
8020 // If storing to an element that isn't in the array, pass the store request
8021 // up the prototype chain before storing in the receiver's elements.
8022 if (check_prototype &&
8023 (index >= elms_length || elms->is_the_hole(index))) {
8024 bool found;
8025 MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index,
8026 value,
8027 &found,
8028 strict_mode);
8029 if (found) return result;
8030 }
8031
8032 // If the value object is not a heap number, switch to fast elements and try
8033 // again.
8034 bool value_is_smi = value->IsSmi();
8035 if (!value->IsNumber()) {
8036 Object* obj;
8037 uint32_t length = elms_length;
8038 if (IsJSArray()) {
8039 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length));
8040 }
8041 MaybeObject* maybe_obj =
8042 SetFastElementsCapacityAndLength(elms_length, length);
8043 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
8044 return SetFastElement(index, value, strict_mode, check_prototype);
8045 }
8046
8047 double double_value = value_is_smi
8048 ? static_cast<double>(Smi::cast(value)->value())
8049 : HeapNumber::cast(value)->value();
8050
8051 // Check whether there is extra space in the fixed array..
Mads Ager (chromium) 2011/06/08 13:13:13 .. -> .
danno 2011/06/09 09:45:40 Done.
8052 if (index < elms_length) {
8053 elms->set(index, double_value);
8054 if (IsJSArray()) {
8055 // Update the length of the array if needed.
8056 uint32_t array_length = 0;
8057 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length));
8058 if (index >= array_length) {
8059 JSArray::cast(this)->set_length(Smi::FromInt(index + 1));
8060 }
8061 }
8062 return value;
8063 }
8064
8065 // Allow gap in fast case.
8066 if ((index - elms_length) < kMaxGap) {
8067 // Try allocating extra space.
8068 int new_capacity = NewElementsCapacity(index+1);
8069 if (new_capacity <= kMaxFastElementsLength ||
8070 !ShouldConvertToSlowElements(new_capacity)) {
8071 ASSERT(static_cast<uint32_t>(new_capacity) > index);
8072 Object* obj;
8073 { MaybeObject* maybe_obj =
8074 SetFastDoubleElementsCapacityAndLength(new_capacity,
8075 index + 1);
8076 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
8077 }
8078 FixedDoubleArray::cast(elements())->set(index, double_value);
8079 return value;
8080 }
8081 }
8082
8083 // Otherwise default to slow case.
8084 Object* obj;
8085 { MaybeObject* maybe_obj = NormalizeElements();
8086 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
8087 }
8088 ASSERT(HasDictionaryElements());
8089 return SetElement(index, value, strict_mode, check_prototype);
8090 }
8091
8092
7903 MaybeObject* JSObject::SetElement(uint32_t index, 8093 MaybeObject* JSObject::SetElement(uint32_t index,
7904 Object* value, 8094 Object* value,
7905 StrictModeFlag strict_mode, 8095 StrictModeFlag strict_mode,
7906 bool check_prototype) { 8096 bool check_prototype) {
7907 // Check access rights if needed. 8097 // Check access rights if needed.
7908 if (IsAccessCheckNeeded()) { 8098 if (IsAccessCheckNeeded()) {
7909 Heap* heap = GetHeap(); 8099 Heap* heap = GetHeap();
7910 if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_SET)) { 8100 if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_SET)) {
7911 HandleScope scope; 8101 HandleScope scope;
7912 Handle<Object> value_handle(value); 8102 Handle<Object> value_handle(value);
(...skipping 29 matching lines...) Expand all
7942 8132
7943 MaybeObject* JSObject::SetElementWithoutInterceptor(uint32_t index, 8133 MaybeObject* JSObject::SetElementWithoutInterceptor(uint32_t index,
7944 Object* value, 8134 Object* value,
7945 StrictModeFlag strict_mode, 8135 StrictModeFlag strict_mode,
7946 bool check_prototype) { 8136 bool check_prototype) {
7947 Isolate* isolate = GetIsolate(); 8137 Isolate* isolate = GetIsolate();
7948 switch (GetElementsKind()) { 8138 switch (GetElementsKind()) {
7949 case FAST_ELEMENTS: 8139 case FAST_ELEMENTS:
7950 // Fast case. 8140 // Fast case.
7951 return SetFastElement(index, value, strict_mode, check_prototype); 8141 return SetFastElement(index, value, strict_mode, check_prototype);
8142 case FAST_DOUBLE_ELEMENTS:
8143 return SetFastDoubleElement(index, value, strict_mode, check_prototype);
7952 case EXTERNAL_PIXEL_ELEMENTS: { 8144 case EXTERNAL_PIXEL_ELEMENTS: {
7953 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements()); 8145 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements());
7954 return pixels->SetValue(index, value); 8146 return pixels->SetValue(index, value);
7955 } 8147 }
7956 case EXTERNAL_BYTE_ELEMENTS: { 8148 case EXTERNAL_BYTE_ELEMENTS: {
7957 ExternalByteArray* array = ExternalByteArray::cast(elements()); 8149 ExternalByteArray* array = ExternalByteArray::cast(elements());
7958 return array->SetValue(index, value); 8150 return array->SetValue(index, value);
7959 } 8151 }
7960 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: { 8152 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: {
7961 ExternalUnsignedByteArray* array = 8153 ExternalUnsignedByteArray* array =
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
8065 } 8257 }
8066 8258
8067 // Attempt to put this object back in fast case. 8259 // Attempt to put this object back in fast case.
8068 if (ShouldConvertToFastElements()) { 8260 if (ShouldConvertToFastElements()) {
8069 uint32_t new_length = 0; 8261 uint32_t new_length = 0;
8070 if (IsJSArray()) { 8262 if (IsJSArray()) {
8071 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&new_length)); 8263 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&new_length));
8072 } else { 8264 } else {
8073 new_length = NumberDictionary::cast(elements())->max_number_key() + 1; 8265 new_length = NumberDictionary::cast(elements())->max_number_key() + 1;
8074 } 8266 }
8075 Object* obj; 8267 if (ShouldConvertToFastDoubleElements()) {
8076 { MaybeObject* maybe_obj = 8268 Object* obj;
8077 SetFastElementsCapacityAndLength(new_length, new_length); 8269 { MaybeObject* maybe_obj =
8078 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 8270 SetFastDoubleElementsCapacityAndLength(new_length, new_length);
8271 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
8272 }
8273 #ifdef DEBUG
8274 if (FLAG_trace_normalization) {
8275 PrintF("Object elements are fast double case again:\n");
8276 Print();
8277 }
8278 #endif
8279 } else {
8280 Object* obj;
8281 { MaybeObject* maybe_obj =
8282 SetFastElementsCapacityAndLength(new_length, new_length);
8283 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
8284 }
8285 #ifdef DEBUG
8286 if (FLAG_trace_normalization) {
8287 PrintF("Object elements are fast case again:\n");
8288 Print();
8289 }
8290 #endif
8079 } 8291 }
8080 #ifdef DEBUG
8081 if (FLAG_trace_normalization) {
8082 PrintF("Object elements are fast case again:\n");
8083 Print();
8084 }
8085 #endif
8086 } 8292 }
8087 8293
8088 return value; 8294 return value;
8089 } 8295 }
8090 default:
8091 UNREACHABLE();
8092 break;
8093 } 8296 }
8094 // All possible cases have been handled above. Add a return to avoid the 8297 // All possible cases have been handled above. Add a return to avoid the
8095 // complaints from the compiler. 8298 // complaints from the compiler.
8096 UNREACHABLE(); 8299 UNREACHABLE();
8097 return isolate->heap()->null_value(); 8300 return isolate->heap()->null_value();
8098 } 8301 }
8099 8302
8100 8303
8101 MaybeObject* JSArray::JSArrayUpdateLengthFromIndex(uint32_t index, 8304 MaybeObject* JSArray::JSArrayUpdateLengthFromIndex(uint32_t index,
8102 Object* value) { 8305 Object* value) {
(...skipping 19 matching lines...) Expand all
8122 // JSArray::length cannot change. 8325 // JSArray::length cannot change.
8123 switch (GetElementsKind()) { 8326 switch (GetElementsKind()) {
8124 case FAST_ELEMENTS: { 8327 case FAST_ELEMENTS: {
8125 FixedArray* elms = FixedArray::cast(elements()); 8328 FixedArray* elms = FixedArray::cast(elements());
8126 if (index < static_cast<uint32_t>(elms->length())) { 8329 if (index < static_cast<uint32_t>(elms->length())) {
8127 Object* value = elms->get(index); 8330 Object* value = elms->get(index);
8128 if (!value->IsTheHole()) return value; 8331 if (!value->IsTheHole()) return value;
8129 } 8332 }
8130 break; 8333 break;
8131 } 8334 }
8335 case FAST_DOUBLE_ELEMENTS: {
8336 FixedDoubleArray* elms = FixedDoubleArray::cast(elements());
8337 if (index < static_cast<uint32_t>(elms->length())) {
8338 if (!elms->is_the_hole(index)) {
8339 return GetHeap()->NumberFromDouble(elms->get(index));
8340 }
8341 }
8342 break;
8343 }
8132 case EXTERNAL_PIXEL_ELEMENTS: 8344 case EXTERNAL_PIXEL_ELEMENTS:
8133 case EXTERNAL_BYTE_ELEMENTS: 8345 case EXTERNAL_BYTE_ELEMENTS:
8134 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 8346 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
8135 case EXTERNAL_SHORT_ELEMENTS: 8347 case EXTERNAL_SHORT_ELEMENTS:
8136 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 8348 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
8137 case EXTERNAL_INT_ELEMENTS: 8349 case EXTERNAL_INT_ELEMENTS:
8138 case EXTERNAL_UNSIGNED_INT_ELEMENTS: 8350 case EXTERNAL_UNSIGNED_INT_ELEMENTS:
8139 case EXTERNAL_FLOAT_ELEMENTS: 8351 case EXTERNAL_FLOAT_ELEMENTS:
8140 case EXTERNAL_DOUBLE_ELEMENTS: { 8352 case EXTERNAL_DOUBLE_ELEMENTS: {
8141 MaybeObject* maybe_value = GetExternalElement(index); 8353 MaybeObject* maybe_value = GetExternalElement(index);
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
8225 // JSArray::length cannot change. 8437 // JSArray::length cannot change.
8226 switch (GetElementsKind()) { 8438 switch (GetElementsKind()) {
8227 case FAST_ELEMENTS: { 8439 case FAST_ELEMENTS: {
8228 FixedArray* elms = FixedArray::cast(elements()); 8440 FixedArray* elms = FixedArray::cast(elements());
8229 if (index < static_cast<uint32_t>(elms->length())) { 8441 if (index < static_cast<uint32_t>(elms->length())) {
8230 Object* value = elms->get(index); 8442 Object* value = elms->get(index);
8231 if (!value->IsTheHole()) return value; 8443 if (!value->IsTheHole()) return value;
8232 } 8444 }
8233 break; 8445 break;
8234 } 8446 }
8447 case FAST_DOUBLE_ELEMENTS: {
8448 FixedDoubleArray* elms = FixedDoubleArray::cast(elements());
8449 if (index < static_cast<uint32_t>(elms->length())) {
8450 if (!elms->is_the_hole(index)) {
8451 double double_value = elms->get(index);
8452 return GetHeap()->AllocateHeapNumber(double_value);
Mads Ager (chromium) 2011/06/08 13:13:13 Use NumberFromDouble?
danno 2011/06/09 09:45:40 Done.
8453 }
8454 }
8455 break;
8456 }
8235 case EXTERNAL_PIXEL_ELEMENTS: 8457 case EXTERNAL_PIXEL_ELEMENTS:
8236 case EXTERNAL_BYTE_ELEMENTS: 8458 case EXTERNAL_BYTE_ELEMENTS:
8237 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 8459 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
8238 case EXTERNAL_SHORT_ELEMENTS: 8460 case EXTERNAL_SHORT_ELEMENTS:
8239 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 8461 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
8240 case EXTERNAL_INT_ELEMENTS: 8462 case EXTERNAL_INT_ELEMENTS:
8241 case EXTERNAL_UNSIGNED_INT_ELEMENTS: 8463 case EXTERNAL_UNSIGNED_INT_ELEMENTS:
8242 case EXTERNAL_FLOAT_ELEMENTS: 8464 case EXTERNAL_FLOAT_ELEMENTS:
8243 case EXTERNAL_DOUBLE_ELEMENTS: { 8465 case EXTERNAL_DOUBLE_ELEMENTS: {
8244 MaybeObject* maybe_value = GetExternalElement(index); 8466 MaybeObject* maybe_value = GetExternalElement(index);
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
8344 break; 8566 break;
8345 } 8567 }
8346 case EXTERNAL_DOUBLE_ELEMENTS: { 8568 case EXTERNAL_DOUBLE_ELEMENTS: {
8347 ExternalDoubleArray* array = ExternalDoubleArray::cast(elements()); 8569 ExternalDoubleArray* array = ExternalDoubleArray::cast(elements());
8348 if (index < static_cast<uint32_t>(array->length())) { 8570 if (index < static_cast<uint32_t>(array->length())) {
8349 double value = array->get(index); 8571 double value = array->get(index);
8350 return GetHeap()->AllocateHeapNumber(value); 8572 return GetHeap()->AllocateHeapNumber(value);
8351 } 8573 }
8352 break; 8574 break;
8353 } 8575 }
8576 case FAST_DOUBLE_ELEMENTS:
8354 case FAST_ELEMENTS: 8577 case FAST_ELEMENTS:
8355 case DICTIONARY_ELEMENTS: 8578 case DICTIONARY_ELEMENTS:
8356 UNREACHABLE(); 8579 UNREACHABLE();
8357 break; 8580 break;
8358 } 8581 }
8359 return GetHeap()->undefined_value(); 8582 return GetHeap()->undefined_value();
8360 } 8583 }
8361 8584
8362 8585
8363 bool JSObject::HasDenseElements() { 8586 bool JSObject::HasDenseElements() {
(...skipping 30 matching lines...) Expand all
8394 UNREACHABLE(); 8617 UNREACHABLE();
8395 break; 8618 break;
8396 } 8619 }
8397 8620
8398 if (capacity == 0) return true; 8621 if (capacity == 0) return true;
8399 return (number_of_elements > (capacity / 2)); 8622 return (number_of_elements > (capacity / 2));
8400 } 8623 }
8401 8624
8402 8625
8403 bool JSObject::ShouldConvertToSlowElements(int new_capacity) { 8626 bool JSObject::ShouldConvertToSlowElements(int new_capacity) {
8404 ASSERT(HasFastElements());
8405 // Keep the array in fast case if the current backing storage is 8627 // 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 8628 // almost filled and if the new capacity is no more than twice the
8407 // old capacity. 8629 // old capacity.
8408 int elements_length = FixedArray::cast(elements())->length(); 8630 int elements_length = 0;
8631 if (HasFastElements()) {
8632 elements_length = FixedArray::cast(elements())->length();
8633 } else if (HasFastDoubleElements()) {
8634 elements_length = FixedDoubleArray::cast(elements())->length();
8635 } else {
8636 UNREACHABLE();
8637 }
8409 return !HasDenseElements() || ((new_capacity / 2) > elements_length); 8638 return !HasDenseElements() || ((new_capacity / 2) > elements_length);
8410 } 8639 }
8411 8640
8412 8641
8413 bool JSObject::ShouldConvertToFastElements() { 8642 bool JSObject::ShouldConvertToFastElements() {
8414 ASSERT(HasDictionaryElements()); 8643 ASSERT(HasDictionaryElements());
8415 NumberDictionary* dictionary = NumberDictionary::cast(elements()); 8644 NumberDictionary* dictionary = NumberDictionary::cast(elements());
8416 // If the elements are sparse, we should not go back to fast case. 8645 // If the elements are sparse, we should not go back to fast case.
8417 if (!HasDenseElements()) return false; 8646 if (!HasDenseElements()) return false;
8418 // If an element has been added at a very high index in the elements 8647 // If an element has been added at a very high index in the elements
8419 // dictionary, we cannot go back to fast case. 8648 // dictionary, we cannot go back to fast case.
8420 if (dictionary->requires_slow_elements()) return false; 8649 if (dictionary->requires_slow_elements()) return false;
8421 // An object requiring access checks is never allowed to have fast 8650 // An object requiring access checks is never allowed to have fast
8422 // elements. If it had fast elements we would skip security checks. 8651 // elements. If it had fast elements we would skip security checks.
8423 if (IsAccessCheckNeeded()) return false; 8652 if (IsAccessCheckNeeded()) return false;
8424 // If the dictionary backing storage takes up roughly half as much 8653 // If the dictionary backing storage takes up roughly half as much
8425 // space as a fast-case backing storage would the array should have 8654 // space as a fast-case backing storage would the array should have
8426 // fast elements. 8655 // fast elements.
8427 uint32_t length = 0; 8656 uint32_t length = 0;
8428 if (IsJSArray()) { 8657 if (IsJSArray()) {
8429 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length)); 8658 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length));
8430 } else { 8659 } else {
8431 length = dictionary->max_number_key(); 8660 length = dictionary->max_number_key();
8432 } 8661 }
8433 return static_cast<uint32_t>(dictionary->Capacity()) >= 8662 return static_cast<uint32_t>(dictionary->Capacity()) >=
8434 (length / (2 * NumberDictionary::kEntrySize)); 8663 (length / (2 * NumberDictionary::kEntrySize));
8435 } 8664 }
8436 8665
8437 8666
8667 bool JSObject::ShouldConvertToFastDoubleElements() {
8668 if (FLAG_unbox_double_arrays) {
8669 ASSERT(HasDictionaryElements());
8670 NumberDictionary* dictionary = NumberDictionary::cast(elements());
8671 for (int i = 0; i < dictionary->Capacity(); i++) {
8672 Object* key = dictionary->KeyAt(i);
8673 if (key->IsNumber()) {
8674 if (!dictionary->ValueAt(i)->IsNumber()) return false;
8675 }
8676 }
8677 return true;
8678 } else {
8679 return false;
8680 }
8681 }
8682
8683
8438 // Certain compilers request function template instantiation when they 8684 // Certain compilers request function template instantiation when they
8439 // see the definition of the other template functions in the 8685 // see the definition of the other template functions in the
8440 // class. This requires us to have the template functions put 8686 // class. This requires us to have the template functions put
8441 // together, so even though this function belongs in objects-debug.cc, 8687 // together, so even though this function belongs in objects-debug.cc,
8442 // we keep it here instead to satisfy certain compilers. 8688 // we keep it here instead to satisfy certain compilers.
8443 #ifdef OBJECT_PRINT 8689 #ifdef OBJECT_PRINT
8444 template<typename Shape, typename Key> 8690 template<typename Shape, typename Key>
8445 void Dictionary<Shape, Key>::Print(FILE* out) { 8691 void Dictionary<Shape, Key>::Print(FILE* out) {
8446 int capacity = HashTable<Shape, Key>::Capacity(); 8692 int capacity = HashTable<Shape, Key>::Capacity();
8447 for (int i = 0; i < capacity; i++) { 8693 for (int i = 0; i < capacity; i++) {
(...skipping 2507 matching lines...) Expand 10 before | Expand all | Expand 10 after
10955 if (break_point_objects()->IsUndefined()) return 0; 11201 if (break_point_objects()->IsUndefined()) return 0;
10956 // Single beak point. 11202 // Single beak point.
10957 if (!break_point_objects()->IsFixedArray()) return 1; 11203 if (!break_point_objects()->IsFixedArray()) return 1;
10958 // Multiple break points. 11204 // Multiple break points.
10959 return FixedArray::cast(break_point_objects())->length(); 11205 return FixedArray::cast(break_point_objects())->length();
10960 } 11206 }
10961 #endif 11207 #endif
10962 11208
10963 11209
10964 } } // namespace v8::internal 11210 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698