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

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: final version before commit 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
« no previous file with comments | « src/objects.h ('k') | src/objects-debug.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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);
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/objects.h ('k') | src/objects-debug.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698