| OLD | NEW |
| 1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 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 3182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3193 Object* value = other->get(y); | 3193 Object* value = other->get(y); |
| 3194 if (!value->IsTheHole() && !HasKey(this, value)) extra++; | 3194 if (!value->IsTheHole() && !HasKey(this, value)) extra++; |
| 3195 } | 3195 } |
| 3196 | 3196 |
| 3197 if (extra == 0) return this; | 3197 if (extra == 0) return this; |
| 3198 | 3198 |
| 3199 // Allocate the result | 3199 // Allocate the result |
| 3200 Object* obj = Heap::AllocateFixedArray(len0 + extra); | 3200 Object* obj = Heap::AllocateFixedArray(len0 + extra); |
| 3201 if (obj->IsFailure()) return obj; | 3201 if (obj->IsFailure()) return obj; |
| 3202 // Fill in the content | 3202 // Fill in the content |
| 3203 AssertNoAllocation no_gc; |
| 3203 FixedArray* result = FixedArray::cast(obj); | 3204 FixedArray* result = FixedArray::cast(obj); |
| 3204 WriteBarrierMode mode = result->GetWriteBarrierMode(); | 3205 WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc); |
| 3205 for (int i = 0; i < len0; i++) { | 3206 for (int i = 0; i < len0; i++) { |
| 3206 result->set(i, get(i), mode); | 3207 result->set(i, get(i), mode); |
| 3207 } | 3208 } |
| 3208 // Fill in the extra keys. | 3209 // Fill in the extra keys. |
| 3209 int index = 0; | 3210 int index = 0; |
| 3210 for (int y = 0; y < len1; y++) { | 3211 for (int y = 0; y < len1; y++) { |
| 3211 Object* value = other->get(y); | 3212 Object* value = other->get(y); |
| 3212 if (!value->IsTheHole() && !HasKey(this, value)) { | 3213 if (!value->IsTheHole() && !HasKey(this, value)) { |
| 3213 result->set(len0 + index, other->get(y), mode); | 3214 result->set(len0 + index, other->get(y), mode); |
| 3214 index++; | 3215 index++; |
| 3215 } | 3216 } |
| 3216 } | 3217 } |
| 3217 ASSERT(extra == index); | 3218 ASSERT(extra == index); |
| 3218 return result; | 3219 return result; |
| 3219 } | 3220 } |
| 3220 | 3221 |
| 3221 | 3222 |
| 3222 Object* FixedArray::CopySize(int new_length) { | 3223 Object* FixedArray::CopySize(int new_length) { |
| 3223 if (new_length == 0) return Heap::empty_fixed_array(); | 3224 if (new_length == 0) return Heap::empty_fixed_array(); |
| 3224 Object* obj = Heap::AllocateFixedArray(new_length); | 3225 Object* obj = Heap::AllocateFixedArray(new_length); |
| 3225 if (obj->IsFailure()) return obj; | 3226 if (obj->IsFailure()) return obj; |
| 3226 FixedArray* result = FixedArray::cast(obj); | 3227 FixedArray* result = FixedArray::cast(obj); |
| 3227 // Copy the content | 3228 // Copy the content |
| 3229 AssertNoAllocation no_gc; |
| 3228 int len = length(); | 3230 int len = length(); |
| 3229 if (new_length < len) len = new_length; | 3231 if (new_length < len) len = new_length; |
| 3230 result->set_map(map()); | 3232 result->set_map(map()); |
| 3231 WriteBarrierMode mode = result->GetWriteBarrierMode(); | 3233 WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc); |
| 3232 for (int i = 0; i < len; i++) { | 3234 for (int i = 0; i < len; i++) { |
| 3233 result->set(i, get(i), mode); | 3235 result->set(i, get(i), mode); |
| 3234 } | 3236 } |
| 3235 return result; | 3237 return result; |
| 3236 } | 3238 } |
| 3237 | 3239 |
| 3238 | 3240 |
| 3239 void FixedArray::CopyTo(int pos, FixedArray* dest, int dest_pos, int len) { | 3241 void FixedArray::CopyTo(int pos, FixedArray* dest, int dest_pos, int len) { |
| 3240 WriteBarrierMode mode = dest->GetWriteBarrierMode(); | 3242 AssertNoAllocation no_gc; |
| 3243 WriteBarrierMode mode = dest->GetWriteBarrierMode(no_gc); |
| 3241 for (int index = 0; index < len; index++) { | 3244 for (int index = 0; index < len; index++) { |
| 3242 dest->set(dest_pos+index, get(pos+index), mode); | 3245 dest->set(dest_pos+index, get(pos+index), mode); |
| 3243 } | 3246 } |
| 3244 } | 3247 } |
| 3245 | 3248 |
| 3246 | 3249 |
| 3247 #ifdef DEBUG | 3250 #ifdef DEBUG |
| 3248 bool FixedArray::IsEqualTo(FixedArray* other) { | 3251 bool FixedArray::IsEqualTo(FixedArray* other) { |
| 3249 if (length() != other->length()) return false; | 3252 if (length() != other->length()) return false; |
| 3250 for (int i = 0 ; i < length(); ++i) { | 3253 for (int i = 0 ; i < length(); ++i) { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 3264 Heap::AllocateFixedArray(ToKeyIndex(number_of_descriptors)); | 3267 Heap::AllocateFixedArray(ToKeyIndex(number_of_descriptors)); |
| 3265 if (array->IsFailure()) return array; | 3268 if (array->IsFailure()) return array; |
| 3266 // Do not use DescriptorArray::cast on incomplete object. | 3269 // Do not use DescriptorArray::cast on incomplete object. |
| 3267 FixedArray* result = FixedArray::cast(array); | 3270 FixedArray* result = FixedArray::cast(array); |
| 3268 | 3271 |
| 3269 // Allocate the content array and set it in the descriptor array. | 3272 // Allocate the content array and set it in the descriptor array. |
| 3270 array = Heap::AllocateFixedArray(number_of_descriptors << 1); | 3273 array = Heap::AllocateFixedArray(number_of_descriptors << 1); |
| 3271 if (array->IsFailure()) return array; | 3274 if (array->IsFailure()) return array; |
| 3272 result->set(kContentArrayIndex, array); | 3275 result->set(kContentArrayIndex, array); |
| 3273 result->set(kEnumerationIndexIndex, | 3276 result->set(kEnumerationIndexIndex, |
| 3274 Smi::FromInt(PropertyDetails::kInitialIndex), | 3277 Smi::FromInt(PropertyDetails::kInitialIndex)); |
| 3275 SKIP_WRITE_BARRIER); | |
| 3276 return result; | 3278 return result; |
| 3277 } | 3279 } |
| 3278 | 3280 |
| 3279 | 3281 |
| 3280 void DescriptorArray::SetEnumCache(FixedArray* bridge_storage, | 3282 void DescriptorArray::SetEnumCache(FixedArray* bridge_storage, |
| 3281 FixedArray* new_cache) { | 3283 FixedArray* new_cache) { |
| 3282 ASSERT(bridge_storage->length() >= kEnumCacheBridgeLength); | 3284 ASSERT(bridge_storage->length() >= kEnumCacheBridgeLength); |
| 3283 if (HasEnumCache()) { | 3285 if (HasEnumCache()) { |
| 3284 FixedArray::cast(get(kEnumerationIndexIndex))-> | 3286 FixedArray::cast(get(kEnumerationIndexIndex))-> |
| 3285 set(kEnumCacheBridgeCacheIndex, new_cache); | 3287 set(kEnumCacheBridgeCacheIndex, new_cache); |
| (...skipping 1407 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4693 // check if the target is live. If not, null the descriptor. | 4695 // check if the target is live. If not, null the descriptor. |
| 4694 // Also drop the back pointer for that map transition, so that this | 4696 // Also drop the back pointer for that map transition, so that this |
| 4695 // map is not reached again by following a back pointer from a | 4697 // map is not reached again by following a back pointer from a |
| 4696 // non-live object. | 4698 // non-live object. |
| 4697 PropertyDetails details(Smi::cast(contents->get(i + 1))); | 4699 PropertyDetails details(Smi::cast(contents->get(i + 1))); |
| 4698 if (details.type() == MAP_TRANSITION) { | 4700 if (details.type() == MAP_TRANSITION) { |
| 4699 Map* target = reinterpret_cast<Map*>(contents->get(i)); | 4701 Map* target = reinterpret_cast<Map*>(contents->get(i)); |
| 4700 ASSERT(target->IsHeapObject()); | 4702 ASSERT(target->IsHeapObject()); |
| 4701 if (!target->IsMarked()) { | 4703 if (!target->IsMarked()) { |
| 4702 ASSERT(target->IsMap()); | 4704 ASSERT(target->IsMap()); |
| 4703 contents->set(i + 1, NullDescriptorDetails, SKIP_WRITE_BARRIER); | 4705 contents->set(i + 1, NullDescriptorDetails); |
| 4704 contents->set(i, Heap::null_value(), SKIP_WRITE_BARRIER); | 4706 contents->set_null(i); |
| 4705 ASSERT(target->prototype() == this || | 4707 ASSERT(target->prototype() == this || |
| 4706 target->prototype() == real_prototype); | 4708 target->prototype() == real_prototype); |
| 4707 // Getter prototype() is read-only, set_prototype() has side effects. | 4709 // Getter prototype() is read-only, set_prototype() has side effects. |
| 4708 *RawField(target, Map::kPrototypeOffset) = real_prototype; | 4710 *RawField(target, Map::kPrototypeOffset) = real_prototype; |
| 4709 } | 4711 } |
| 4710 } | 4712 } |
| 4711 } | 4713 } |
| 4712 } | 4714 } |
| 4713 | 4715 |
| 4714 | 4716 |
| (...skipping 439 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5154 | 5156 |
| 5155 | 5157 |
| 5156 void JSObject::SetFastElements(FixedArray* elems) { | 5158 void JSObject::SetFastElements(FixedArray* elems) { |
| 5157 // We should never end in here with a pixel or external array. | 5159 // We should never end in here with a pixel or external array. |
| 5158 ASSERT(!HasPixelElements() && !HasExternalArrayElements()); | 5160 ASSERT(!HasPixelElements() && !HasExternalArrayElements()); |
| 5159 #ifdef DEBUG | 5161 #ifdef DEBUG |
| 5160 // Check the provided array is filled with the_hole. | 5162 // Check the provided array is filled with the_hole. |
| 5161 uint32_t len = static_cast<uint32_t>(elems->length()); | 5163 uint32_t len = static_cast<uint32_t>(elems->length()); |
| 5162 for (uint32_t i = 0; i < len; i++) ASSERT(elems->get(i)->IsTheHole()); | 5164 for (uint32_t i = 0; i < len; i++) ASSERT(elems->get(i)->IsTheHole()); |
| 5163 #endif | 5165 #endif |
| 5164 WriteBarrierMode mode = elems->GetWriteBarrierMode(); | 5166 AssertNoAllocation no_gc; |
| 5167 WriteBarrierMode mode = elems->GetWriteBarrierMode(no_gc); |
| 5165 switch (GetElementsKind()) { | 5168 switch (GetElementsKind()) { |
| 5166 case FAST_ELEMENTS: { | 5169 case FAST_ELEMENTS: { |
| 5167 FixedArray* old_elements = FixedArray::cast(elements()); | 5170 FixedArray* old_elements = FixedArray::cast(elements()); |
| 5168 uint32_t old_length = static_cast<uint32_t>(old_elements->length()); | 5171 uint32_t old_length = static_cast<uint32_t>(old_elements->length()); |
| 5169 // Fill out the new array with this content and array holes. | 5172 // Fill out the new array with this content and array holes. |
| 5170 for (uint32_t i = 0; i < old_length; i++) { | 5173 for (uint32_t i = 0; i < old_length; i++) { |
| 5171 elems->set(i, old_elements->get(i), mode); | 5174 elems->set(i, old_elements->get(i), mode); |
| 5172 } | 5175 } |
| 5173 break; | 5176 break; |
| 5174 } | 5177 } |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5221 default: | 5224 default: |
| 5222 UNREACHABLE(); | 5225 UNREACHABLE(); |
| 5223 break; | 5226 break; |
| 5224 } | 5227 } |
| 5225 return this; | 5228 return this; |
| 5226 } | 5229 } |
| 5227 | 5230 |
| 5228 | 5231 |
| 5229 Object* JSArray::Initialize(int capacity) { | 5232 Object* JSArray::Initialize(int capacity) { |
| 5230 ASSERT(capacity >= 0); | 5233 ASSERT(capacity >= 0); |
| 5231 set_length(Smi::FromInt(0), SKIP_WRITE_BARRIER); | 5234 set_length(Smi::FromInt(0)); |
| 5232 FixedArray* new_elements; | 5235 FixedArray* new_elements; |
| 5233 if (capacity == 0) { | 5236 if (capacity == 0) { |
| 5234 new_elements = Heap::empty_fixed_array(); | 5237 new_elements = Heap::empty_fixed_array(); |
| 5235 } else { | 5238 } else { |
| 5236 Object* obj = Heap::AllocateFixedArrayWithHoles(capacity); | 5239 Object* obj = Heap::AllocateFixedArrayWithHoles(capacity); |
| 5237 if (obj->IsFailure()) return obj; | 5240 if (obj->IsFailure()) return obj; |
| 5238 new_elements = FixedArray::cast(obj); | 5241 new_elements = FixedArray::cast(obj); |
| 5239 } | 5242 } |
| 5240 set_elements(new_elements); | 5243 set_elements(new_elements); |
| 5241 return this; | 5244 return this; |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5281 int old_capacity = FixedArray::cast(elements())->length(); | 5284 int old_capacity = FixedArray::cast(elements())->length(); |
| 5282 if (value <= old_capacity) { | 5285 if (value <= old_capacity) { |
| 5283 if (IsJSArray()) { | 5286 if (IsJSArray()) { |
| 5284 int old_length = FastD2I(JSArray::cast(this)->length()->Number()); | 5287 int old_length = FastD2I(JSArray::cast(this)->length()->Number()); |
| 5285 // NOTE: We may be able to optimize this by removing the | 5288 // NOTE: We may be able to optimize this by removing the |
| 5286 // last part of the elements backing storage array and | 5289 // last part of the elements backing storage array and |
| 5287 // setting the capacity to the new size. | 5290 // setting the capacity to the new size. |
| 5288 for (int i = value; i < old_length; i++) { | 5291 for (int i = value; i < old_length; i++) { |
| 5289 FixedArray::cast(elements())->set_the_hole(i); | 5292 FixedArray::cast(elements())->set_the_hole(i); |
| 5290 } | 5293 } |
| 5291 JSArray::cast(this)->set_length(smi_length, SKIP_WRITE_BARRIER); | 5294 JSArray::cast(this)->set_length(Smi::cast(smi_length)); |
| 5292 } | 5295 } |
| 5293 return this; | 5296 return this; |
| 5294 } | 5297 } |
| 5295 int min = NewElementsCapacity(old_capacity); | 5298 int min = NewElementsCapacity(old_capacity); |
| 5296 int new_capacity = value > min ? value : min; | 5299 int new_capacity = value > min ? value : min; |
| 5297 if (new_capacity <= kMaxFastElementsLength || | 5300 if (new_capacity <= kMaxFastElementsLength || |
| 5298 !ShouldConvertToSlowElements(new_capacity)) { | 5301 !ShouldConvertToSlowElements(new_capacity)) { |
| 5299 Object* obj = Heap::AllocateFixedArrayWithHoles(new_capacity); | 5302 Object* obj = Heap::AllocateFixedArrayWithHoles(new_capacity); |
| 5300 if (obj->IsFailure()) return obj; | 5303 if (obj->IsFailure()) return obj; |
| 5301 if (IsJSArray()) JSArray::cast(this)->set_length(smi_length, | 5304 if (IsJSArray()) { |
| 5302 SKIP_WRITE_BARRIER); | 5305 JSArray::cast(this)->set_length(Smi::cast(smi_length)); |
| 5306 } |
| 5303 SetFastElements(FixedArray::cast(obj)); | 5307 SetFastElements(FixedArray::cast(obj)); |
| 5304 return this; | 5308 return this; |
| 5305 } | 5309 } |
| 5306 break; | 5310 break; |
| 5307 } | 5311 } |
| 5308 case DICTIONARY_ELEMENTS: { | 5312 case DICTIONARY_ELEMENTS: { |
| 5309 if (IsJSArray()) { | 5313 if (IsJSArray()) { |
| 5310 if (value == 0) { | 5314 if (value == 0) { |
| 5311 // If the length of a slow array is reset to zero, we clear | 5315 // If the length of a slow array is reset to zero, we clear |
| 5312 // the array and flush backing storage. This has the added | 5316 // the array and flush backing storage. This has the added |
| 5313 // benefit that the array returns to fast mode. | 5317 // benefit that the array returns to fast mode. |
| 5314 initialize_elements(); | 5318 initialize_elements(); |
| 5315 } else { | 5319 } else { |
| 5316 // Remove deleted elements. | 5320 // Remove deleted elements. |
| 5317 uint32_t old_length = | 5321 uint32_t old_length = |
| 5318 static_cast<uint32_t>(JSArray::cast(this)->length()->Number()); | 5322 static_cast<uint32_t>(JSArray::cast(this)->length()->Number()); |
| 5319 element_dictionary()->RemoveNumberEntries(value, old_length); | 5323 element_dictionary()->RemoveNumberEntries(value, old_length); |
| 5320 } | 5324 } |
| 5321 JSArray::cast(this)->set_length(smi_length, SKIP_WRITE_BARRIER); | 5325 JSArray::cast(this)->set_length(Smi::cast(smi_length)); |
| 5322 } | 5326 } |
| 5323 return this; | 5327 return this; |
| 5324 } | 5328 } |
| 5325 default: | 5329 default: |
| 5326 UNREACHABLE(); | 5330 UNREACHABLE(); |
| 5327 break; | 5331 break; |
| 5328 } | 5332 } |
| 5329 } | 5333 } |
| 5330 | 5334 |
| 5331 // General slow case. | 5335 // General slow case. |
| 5332 if (len->IsNumber()) { | 5336 if (len->IsNumber()) { |
| 5333 uint32_t length; | 5337 uint32_t length; |
| 5334 if (Array::IndexFromObject(len, &length)) { | 5338 if (Array::IndexFromObject(len, &length)) { |
| 5335 return SetSlowElements(len); | 5339 return SetSlowElements(len); |
| 5336 } else { | 5340 } else { |
| 5337 return ArrayLengthRangeError(); | 5341 return ArrayLengthRangeError(); |
| 5338 } | 5342 } |
| 5339 } | 5343 } |
| 5340 | 5344 |
| 5341 // len is not a number so make the array size one and | 5345 // len is not a number so make the array size one and |
| 5342 // set only element to len. | 5346 // set only element to len. |
| 5343 Object* obj = Heap::AllocateFixedArray(1); | 5347 Object* obj = Heap::AllocateFixedArray(1); |
| 5344 if (obj->IsFailure()) return obj; | 5348 if (obj->IsFailure()) return obj; |
| 5345 FixedArray::cast(obj)->set(0, len); | 5349 FixedArray::cast(obj)->set(0, len); |
| 5346 if (IsJSArray()) JSArray::cast(this)->set_length(Smi::FromInt(1), | 5350 if (IsJSArray()) JSArray::cast(this)->set_length(Smi::FromInt(1)); |
| 5347 SKIP_WRITE_BARRIER); | |
| 5348 set_elements(FixedArray::cast(obj)); | 5351 set_elements(FixedArray::cast(obj)); |
| 5349 return this; | 5352 return this; |
| 5350 } | 5353 } |
| 5351 | 5354 |
| 5352 | 5355 |
| 5353 bool JSObject::HasElementPostInterceptor(JSObject* receiver, uint32_t index) { | 5356 bool JSObject::HasElementPostInterceptor(JSObject* receiver, uint32_t index) { |
| 5354 switch (GetElementsKind()) { | 5357 switch (GetElementsKind()) { |
| 5355 case FAST_ELEMENTS: { | 5358 case FAST_ELEMENTS: { |
| 5356 uint32_t length = IsJSArray() ? | 5359 uint32_t length = IsJSArray() ? |
| 5357 static_cast<uint32_t> | 5360 static_cast<uint32_t> |
| (...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5607 | 5610 |
| 5608 // Check whether there is extra space in fixed array.. | 5611 // Check whether there is extra space in fixed array.. |
| 5609 if (index < elms_length) { | 5612 if (index < elms_length) { |
| 5610 elms->set(index, value); | 5613 elms->set(index, value); |
| 5611 if (IsJSArray()) { | 5614 if (IsJSArray()) { |
| 5612 // Update the length of the array if needed. | 5615 // Update the length of the array if needed. |
| 5613 uint32_t array_length = 0; | 5616 uint32_t array_length = 0; |
| 5614 CHECK(Array::IndexFromObject(JSArray::cast(this)->length(), | 5617 CHECK(Array::IndexFromObject(JSArray::cast(this)->length(), |
| 5615 &array_length)); | 5618 &array_length)); |
| 5616 if (index >= array_length) { | 5619 if (index >= array_length) { |
| 5617 JSArray::cast(this)->set_length(Smi::FromInt(index + 1), | 5620 JSArray::cast(this)->set_length(Smi::FromInt(index + 1)); |
| 5618 SKIP_WRITE_BARRIER); | |
| 5619 } | 5621 } |
| 5620 } | 5622 } |
| 5621 return value; | 5623 return value; |
| 5622 } | 5624 } |
| 5623 | 5625 |
| 5624 // Allow gap in fast case. | 5626 // Allow gap in fast case. |
| 5625 if ((index - elms_length) < kMaxGap) { | 5627 if ((index - elms_length) < kMaxGap) { |
| 5626 // Try allocating extra space. | 5628 // Try allocating extra space. |
| 5627 int new_capacity = NewElementsCapacity(index+1); | 5629 int new_capacity = NewElementsCapacity(index+1); |
| 5628 if (new_capacity <= kMaxFastElementsLength || | 5630 if (new_capacity <= kMaxFastElementsLength || |
| 5629 !ShouldConvertToSlowElements(new_capacity)) { | 5631 !ShouldConvertToSlowElements(new_capacity)) { |
| 5630 ASSERT(static_cast<uint32_t>(new_capacity) > index); | 5632 ASSERT(static_cast<uint32_t>(new_capacity) > index); |
| 5631 Object* obj = Heap::AllocateFixedArrayWithHoles(new_capacity); | 5633 Object* obj = Heap::AllocateFixedArrayWithHoles(new_capacity); |
| 5632 if (obj->IsFailure()) return obj; | 5634 if (obj->IsFailure()) return obj; |
| 5633 SetFastElements(FixedArray::cast(obj)); | 5635 SetFastElements(FixedArray::cast(obj)); |
| 5634 if (IsJSArray()) JSArray::cast(this)->set_length(Smi::FromInt(index + 1), | 5636 if (IsJSArray()) { |
| 5635 SKIP_WRITE_BARRIER); | 5637 JSArray::cast(this)->set_length(Smi::FromInt(index + 1)); |
| 5638 } |
| 5636 FixedArray::cast(elements())->set(index, value); | 5639 FixedArray::cast(elements())->set(index, value); |
| 5637 return value; | 5640 return value; |
| 5638 } | 5641 } |
| 5639 } | 5642 } |
| 5640 | 5643 |
| 5641 // Otherwise default to slow case. | 5644 // Otherwise default to slow case. |
| 5642 Object* obj = NormalizeElements(); | 5645 Object* obj = NormalizeElements(); |
| 5643 if (obj->IsFailure()) return obj; | 5646 if (obj->IsFailure()) return obj; |
| 5644 ASSERT(HasDictionaryElements()); | 5647 ASSERT(HasDictionaryElements()); |
| 5645 return SetElement(index, value); | 5648 return SetElement(index, value); |
| (...skipping 476 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6122 } | 6125 } |
| 6123 } | 6126 } |
| 6124 } | 6127 } |
| 6125 #endif | 6128 #endif |
| 6126 | 6129 |
| 6127 | 6130 |
| 6128 template<typename Shape, typename Key> | 6131 template<typename Shape, typename Key> |
| 6129 void Dictionary<Shape, Key>::CopyValuesTo(FixedArray* elements) { | 6132 void Dictionary<Shape, Key>::CopyValuesTo(FixedArray* elements) { |
| 6130 int pos = 0; | 6133 int pos = 0; |
| 6131 int capacity = HashTable<Shape, Key>::Capacity(); | 6134 int capacity = HashTable<Shape, Key>::Capacity(); |
| 6132 WriteBarrierMode mode = elements->GetWriteBarrierMode(); | 6135 AssertNoAllocation no_gc; |
| 6136 WriteBarrierMode mode = elements->GetWriteBarrierMode(no_gc); |
| 6133 for (int i = 0; i < capacity; i++) { | 6137 for (int i = 0; i < capacity; i++) { |
| 6134 Object* k = Dictionary<Shape, Key>::KeyAt(i); | 6138 Object* k = Dictionary<Shape, Key>::KeyAt(i); |
| 6135 if (Dictionary<Shape, Key>::IsKey(k)) { | 6139 if (Dictionary<Shape, Key>::IsKey(k)) { |
| 6136 elements->set(pos++, ValueAt(i), mode); | 6140 elements->set(pos++, ValueAt(i), mode); |
| 6137 } | 6141 } |
| 6138 } | 6142 } |
| 6139 ASSERT(pos == elements->length()); | 6143 ASSERT(pos == elements->length()); |
| 6140 } | 6144 } |
| 6141 | 6145 |
| 6142 | 6146 |
| (...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6493 PropertyAttributes filter) { | 6497 PropertyAttributes filter) { |
| 6494 int counter = 0; | 6498 int counter = 0; |
| 6495 switch (GetElementsKind()) { | 6499 switch (GetElementsKind()) { |
| 6496 case FAST_ELEMENTS: { | 6500 case FAST_ELEMENTS: { |
| 6497 int length = IsJSArray() ? | 6501 int length = IsJSArray() ? |
| 6498 Smi::cast(JSArray::cast(this)->length())->value() : | 6502 Smi::cast(JSArray::cast(this)->length())->value() : |
| 6499 FixedArray::cast(elements())->length(); | 6503 FixedArray::cast(elements())->length(); |
| 6500 for (int i = 0; i < length; i++) { | 6504 for (int i = 0; i < length; i++) { |
| 6501 if (!FixedArray::cast(elements())->get(i)->IsTheHole()) { | 6505 if (!FixedArray::cast(elements())->get(i)->IsTheHole()) { |
| 6502 if (storage != NULL) { | 6506 if (storage != NULL) { |
| 6503 storage->set(counter, Smi::FromInt(i), SKIP_WRITE_BARRIER); | 6507 storage->set(counter, Smi::FromInt(i)); |
| 6504 } | 6508 } |
| 6505 counter++; | 6509 counter++; |
| 6506 } | 6510 } |
| 6507 } | 6511 } |
| 6508 ASSERT(!storage || storage->length() >= counter); | 6512 ASSERT(!storage || storage->length() >= counter); |
| 6509 break; | 6513 break; |
| 6510 } | 6514 } |
| 6511 case PIXEL_ELEMENTS: { | 6515 case PIXEL_ELEMENTS: { |
| 6512 int length = PixelArray::cast(elements())->length(); | 6516 int length = PixelArray::cast(elements())->length(); |
| 6513 while (counter < length) { | 6517 while (counter < length) { |
| 6514 if (storage != NULL) { | 6518 if (storage != NULL) { |
| 6515 storage->set(counter, Smi::FromInt(counter), SKIP_WRITE_BARRIER); | 6519 storage->set(counter, Smi::FromInt(counter)); |
| 6516 } | 6520 } |
| 6517 counter++; | 6521 counter++; |
| 6518 } | 6522 } |
| 6519 ASSERT(!storage || storage->length() >= counter); | 6523 ASSERT(!storage || storage->length() >= counter); |
| 6520 break; | 6524 break; |
| 6521 } | 6525 } |
| 6522 case EXTERNAL_BYTE_ELEMENTS: | 6526 case EXTERNAL_BYTE_ELEMENTS: |
| 6523 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 6527 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 6524 case EXTERNAL_SHORT_ELEMENTS: | 6528 case EXTERNAL_SHORT_ELEMENTS: |
| 6525 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 6529 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 6526 case EXTERNAL_INT_ELEMENTS: | 6530 case EXTERNAL_INT_ELEMENTS: |
| 6527 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 6531 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| 6528 case EXTERNAL_FLOAT_ELEMENTS: { | 6532 case EXTERNAL_FLOAT_ELEMENTS: { |
| 6529 int length = ExternalArray::cast(elements())->length(); | 6533 int length = ExternalArray::cast(elements())->length(); |
| 6530 while (counter < length) { | 6534 while (counter < length) { |
| 6531 if (storage != NULL) { | 6535 if (storage != NULL) { |
| 6532 storage->set(counter, Smi::FromInt(counter), SKIP_WRITE_BARRIER); | 6536 storage->set(counter, Smi::FromInt(counter)); |
| 6533 } | 6537 } |
| 6534 counter++; | 6538 counter++; |
| 6535 } | 6539 } |
| 6536 ASSERT(!storage || storage->length() >= counter); | 6540 ASSERT(!storage || storage->length() >= counter); |
| 6537 break; | 6541 break; |
| 6538 } | 6542 } |
| 6539 case DICTIONARY_ELEMENTS: { | 6543 case DICTIONARY_ELEMENTS: { |
| 6540 if (storage != NULL) { | 6544 if (storage != NULL) { |
| 6541 element_dictionary()->CopyKeysTo(storage, filter); | 6545 element_dictionary()->CopyKeysTo(storage, filter); |
| 6542 } | 6546 } |
| 6543 counter = element_dictionary()->NumberOfElementsFilterAttributes(filter); | 6547 counter = element_dictionary()->NumberOfElementsFilterAttributes(filter); |
| 6544 break; | 6548 break; |
| 6545 } | 6549 } |
| 6546 default: | 6550 default: |
| 6547 UNREACHABLE(); | 6551 UNREACHABLE(); |
| 6548 break; | 6552 break; |
| 6549 } | 6553 } |
| 6550 | 6554 |
| 6551 if (this->IsJSValue()) { | 6555 if (this->IsJSValue()) { |
| 6552 Object* val = JSValue::cast(this)->value(); | 6556 Object* val = JSValue::cast(this)->value(); |
| 6553 if (val->IsString()) { | 6557 if (val->IsString()) { |
| 6554 String* str = String::cast(val); | 6558 String* str = String::cast(val); |
| 6555 if (storage) { | 6559 if (storage) { |
| 6556 for (int i = 0; i < str->length(); i++) { | 6560 for (int i = 0; i < str->length(); i++) { |
| 6557 storage->set(counter + i, Smi::FromInt(i), SKIP_WRITE_BARRIER); | 6561 storage->set(counter + i, Smi::FromInt(i)); |
| 6558 } | 6562 } |
| 6559 } | 6563 } |
| 6560 counter += str->length(); | 6564 counter += str->length(); |
| 6561 } | 6565 } |
| 6562 } | 6566 } |
| 6563 ASSERT(!storage || storage->length() == counter); | 6567 ASSERT(!storage || storage->length() == counter); |
| 6564 return counter; | 6568 return counter; |
| 6565 } | 6569 } |
| 6566 | 6570 |
| 6567 | 6571 |
| (...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6879 int nof = NumberOfElements() + n; | 6883 int nof = NumberOfElements() + n; |
| 6880 int nod = NumberOfDeletedElements(); | 6884 int nod = NumberOfDeletedElements(); |
| 6881 // Return if: | 6885 // Return if: |
| 6882 // 50% is still free after adding n elements and | 6886 // 50% is still free after adding n elements and |
| 6883 // at most 50% of the free elements are deleted elements. | 6887 // at most 50% of the free elements are deleted elements. |
| 6884 if ((nof + (nof >> 1) <= capacity) && | 6888 if ((nof + (nof >> 1) <= capacity) && |
| 6885 (nod <= (capacity - nof) >> 1)) return this; | 6889 (nod <= (capacity - nof) >> 1)) return this; |
| 6886 | 6890 |
| 6887 Object* obj = Allocate(nof * 2); | 6891 Object* obj = Allocate(nof * 2); |
| 6888 if (obj->IsFailure()) return obj; | 6892 if (obj->IsFailure()) return obj; |
| 6893 |
| 6894 AssertNoAllocation no_gc; |
| 6889 HashTable* table = HashTable::cast(obj); | 6895 HashTable* table = HashTable::cast(obj); |
| 6890 WriteBarrierMode mode = table->GetWriteBarrierMode(); | 6896 WriteBarrierMode mode = table->GetWriteBarrierMode(no_gc); |
| 6891 | 6897 |
| 6892 // Copy prefix to new array. | 6898 // Copy prefix to new array. |
| 6893 for (int i = kPrefixStartIndex; | 6899 for (int i = kPrefixStartIndex; |
| 6894 i < kPrefixStartIndex + Shape::kPrefixSize; | 6900 i < kPrefixStartIndex + Shape::kPrefixSize; |
| 6895 i++) { | 6901 i++) { |
| 6896 table->set(i, get(i), mode); | 6902 table->set(i, get(i), mode); |
| 6897 } | 6903 } |
| 6898 // Rehash the elements. | 6904 // Rehash the elements. |
| 6899 for (int i = 0; i < capacity; i++) { | 6905 for (int i = 0; i < capacity; i++) { |
| 6900 uint32_t from_index = EntryToIndex(i); | 6906 uint32_t from_index = EntryToIndex(i); |
| (...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7127 // we start mutating the array. | 7133 // we start mutating the array. |
| 7128 Object* new_double = Heap::AllocateHeapNumber(0.0); | 7134 Object* new_double = Heap::AllocateHeapNumber(0.0); |
| 7129 if (new_double->IsFailure()) return new_double; | 7135 if (new_double->IsFailure()) return new_double; |
| 7130 result_double = HeapNumber::cast(new_double); | 7136 result_double = HeapNumber::cast(new_double); |
| 7131 } | 7137 } |
| 7132 | 7138 |
| 7133 AssertNoAllocation no_alloc; | 7139 AssertNoAllocation no_alloc; |
| 7134 | 7140 |
| 7135 // Split elements into defined, undefined and the_hole, in that order. | 7141 // Split elements into defined, undefined and the_hole, in that order. |
| 7136 // Only count locations for undefined and the hole, and fill them afterwards. | 7142 // Only count locations for undefined and the hole, and fill them afterwards. |
| 7137 WriteBarrierMode write_barrier = elements->GetWriteBarrierMode(); | 7143 WriteBarrierMode write_barrier = elements->GetWriteBarrierMode(no_alloc); |
| 7138 unsigned int undefs = limit; | 7144 unsigned int undefs = limit; |
| 7139 unsigned int holes = limit; | 7145 unsigned int holes = limit; |
| 7140 // Assume most arrays contain no holes and undefined values, so minimize the | 7146 // Assume most arrays contain no holes and undefined values, so minimize the |
| 7141 // number of stores of non-undefined, non-the-hole values. | 7147 // number of stores of non-undefined, non-the-hole values. |
| 7142 for (unsigned int i = 0; i < undefs; i++) { | 7148 for (unsigned int i = 0; i < undefs; i++) { |
| 7143 Object* current = elements->get(i); | 7149 Object* current = elements->get(i); |
| 7144 if (current->IsTheHole()) { | 7150 if (current->IsTheHole()) { |
| 7145 holes--; | 7151 holes--; |
| 7146 undefs--; | 7152 undefs--; |
| 7147 } else if (current->IsUndefined()) { | 7153 } else if (current->IsUndefined()) { |
| (...skipping 474 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7622 | 7628 |
| 7623 template<typename Shape, typename Key> | 7629 template<typename Shape, typename Key> |
| 7624 Object* Dictionary<Shape, Key>::GenerateNewEnumerationIndices() { | 7630 Object* Dictionary<Shape, Key>::GenerateNewEnumerationIndices() { |
| 7625 int length = HashTable<Shape, Key>::NumberOfElements(); | 7631 int length = HashTable<Shape, Key>::NumberOfElements(); |
| 7626 | 7632 |
| 7627 // Allocate and initialize iteration order array. | 7633 // Allocate and initialize iteration order array. |
| 7628 Object* obj = Heap::AllocateFixedArray(length); | 7634 Object* obj = Heap::AllocateFixedArray(length); |
| 7629 if (obj->IsFailure()) return obj; | 7635 if (obj->IsFailure()) return obj; |
| 7630 FixedArray* iteration_order = FixedArray::cast(obj); | 7636 FixedArray* iteration_order = FixedArray::cast(obj); |
| 7631 for (int i = 0; i < length; i++) { | 7637 for (int i = 0; i < length; i++) { |
| 7632 iteration_order->set(i, Smi::FromInt(i), SKIP_WRITE_BARRIER); | 7638 iteration_order->set(i, Smi::FromInt(i)); |
| 7633 } | 7639 } |
| 7634 | 7640 |
| 7635 // Allocate array with enumeration order. | 7641 // Allocate array with enumeration order. |
| 7636 obj = Heap::AllocateFixedArray(length); | 7642 obj = Heap::AllocateFixedArray(length); |
| 7637 if (obj->IsFailure()) return obj; | 7643 if (obj->IsFailure()) return obj; |
| 7638 FixedArray* enumeration_order = FixedArray::cast(obj); | 7644 FixedArray* enumeration_order = FixedArray::cast(obj); |
| 7639 | 7645 |
| 7640 // Fill the enumeration order array with property details. | 7646 // Fill the enumeration order array with property details. |
| 7641 int capacity = HashTable<Shape, Key>::Capacity(); | 7647 int capacity = HashTable<Shape, Key>::Capacity(); |
| 7642 int pos = 0; | 7648 int pos = 0; |
| 7643 for (int i = 0; i < capacity; i++) { | 7649 for (int i = 0; i < capacity; i++) { |
| 7644 if (Dictionary<Shape, Key>::IsKey(Dictionary<Shape, Key>::KeyAt(i))) { | 7650 if (Dictionary<Shape, Key>::IsKey(Dictionary<Shape, Key>::KeyAt(i))) { |
| 7645 enumeration_order->set(pos++, | 7651 enumeration_order->set(pos++, Smi::FromInt(DetailsAt(i).index())); |
| 7646 Smi::FromInt(DetailsAt(i).index()), | |
| 7647 SKIP_WRITE_BARRIER); | |
| 7648 } | 7652 } |
| 7649 } | 7653 } |
| 7650 | 7654 |
| 7651 // Sort the arrays wrt. enumeration order. | 7655 // Sort the arrays wrt. enumeration order. |
| 7652 iteration_order->SortPairs(enumeration_order, enumeration_order->length()); | 7656 iteration_order->SortPairs(enumeration_order, enumeration_order->length()); |
| 7653 | 7657 |
| 7654 // Overwrite the enumeration_order with the enumeration indices. | 7658 // Overwrite the enumeration_order with the enumeration indices. |
| 7655 for (int i = 0; i < length; i++) { | 7659 for (int i = 0; i < length; i++) { |
| 7656 int index = Smi::cast(iteration_order->get(i))->value(); | 7660 int index = Smi::cast(iteration_order->get(i))->value(); |
| 7657 int enum_index = PropertyDetails::kInitialIndex + i; | 7661 int enum_index = PropertyDetails::kInitialIndex + i; |
| 7658 enumeration_order->set(index, | 7662 enumeration_order->set(index, Smi::FromInt(enum_index)); |
| 7659 Smi::FromInt(enum_index), | |
| 7660 SKIP_WRITE_BARRIER); | |
| 7661 } | 7663 } |
| 7662 | 7664 |
| 7663 // Update the dictionary with new indices. | 7665 // Update the dictionary with new indices. |
| 7664 capacity = HashTable<Shape, Key>::Capacity(); | 7666 capacity = HashTable<Shape, Key>::Capacity(); |
| 7665 pos = 0; | 7667 pos = 0; |
| 7666 for (int i = 0; i < capacity; i++) { | 7668 for (int i = 0; i < capacity; i++) { |
| 7667 if (Dictionary<Shape, Key>::IsKey(Dictionary<Shape, Key>::KeyAt(i))) { | 7669 if (Dictionary<Shape, Key>::IsKey(Dictionary<Shape, Key>::KeyAt(i))) { |
| 7668 int enum_index = Smi::cast(enumeration_order->get(pos++))->value(); | 7670 int enum_index = Smi::cast(enumeration_order->get(pos++))->value(); |
| 7669 PropertyDetails details = DetailsAt(i); | 7671 PropertyDetails details = DetailsAt(i); |
| 7670 PropertyDetails new_details = | 7672 PropertyDetails new_details = |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7798 // Check if this index is high enough that we should require slow | 7800 // Check if this index is high enough that we should require slow |
| 7799 // elements. | 7801 // elements. |
| 7800 if (key > kRequiresSlowElementsLimit) { | 7802 if (key > kRequiresSlowElementsLimit) { |
| 7801 set_requires_slow_elements(); | 7803 set_requires_slow_elements(); |
| 7802 return; | 7804 return; |
| 7803 } | 7805 } |
| 7804 // Update max key value. | 7806 // Update max key value. |
| 7805 Object* max_index_object = get(kMaxNumberKeyIndex); | 7807 Object* max_index_object = get(kMaxNumberKeyIndex); |
| 7806 if (!max_index_object->IsSmi() || max_number_key() < key) { | 7808 if (!max_index_object->IsSmi() || max_number_key() < key) { |
| 7807 FixedArray::set(kMaxNumberKeyIndex, | 7809 FixedArray::set(kMaxNumberKeyIndex, |
| 7808 Smi::FromInt(key << kRequiresSlowElementsTagSize), | 7810 Smi::FromInt(key << kRequiresSlowElementsTagSize)); |
| 7809 SKIP_WRITE_BARRIER); | |
| 7810 } | 7811 } |
| 7811 } | 7812 } |
| 7812 | 7813 |
| 7813 | 7814 |
| 7814 Object* NumberDictionary::AddNumberEntry(uint32_t key, | 7815 Object* NumberDictionary::AddNumberEntry(uint32_t key, |
| 7815 Object* value, | 7816 Object* value, |
| 7816 PropertyDetails details) { | 7817 PropertyDetails details) { |
| 7817 UpdateMaxNumberKey(key); | 7818 UpdateMaxNumberKey(key); |
| 7818 SLOW_ASSERT(FindEntry(key) == kNotFound); | 7819 SLOW_ASSERT(FindEntry(key) == kNotFound); |
| 7819 return Add(key, value, details); | 7820 return Add(key, value, details); |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7890 FixedArray* sort_array) { | 7891 FixedArray* sort_array) { |
| 7891 ASSERT(storage->length() >= NumberOfEnumElements()); | 7892 ASSERT(storage->length() >= NumberOfEnumElements()); |
| 7892 int capacity = Capacity(); | 7893 int capacity = Capacity(); |
| 7893 int index = 0; | 7894 int index = 0; |
| 7894 for (int i = 0; i < capacity; i++) { | 7895 for (int i = 0; i < capacity; i++) { |
| 7895 Object* k = KeyAt(i); | 7896 Object* k = KeyAt(i); |
| 7896 if (IsKey(k)) { | 7897 if (IsKey(k)) { |
| 7897 PropertyDetails details = DetailsAt(i); | 7898 PropertyDetails details = DetailsAt(i); |
| 7898 if (details.IsDeleted() || details.IsDontEnum()) continue; | 7899 if (details.IsDeleted() || details.IsDontEnum()) continue; |
| 7899 storage->set(index, k); | 7900 storage->set(index, k); |
| 7900 sort_array->set(index, | 7901 sort_array->set(index, Smi::FromInt(details.index())); |
| 7901 Smi::FromInt(details.index()), | |
| 7902 SKIP_WRITE_BARRIER); | |
| 7903 index++; | 7902 index++; |
| 7904 } | 7903 } |
| 7905 } | 7904 } |
| 7906 storage->SortPairs(sort_array, sort_array->length()); | 7905 storage->SortPairs(sort_array, sort_array->length()); |
| 7907 ASSERT(storage->length() >= index); | 7906 ASSERT(storage->length() >= index); |
| 7908 } | 7907 } |
| 7909 | 7908 |
| 7910 | 7909 |
| 7911 template<typename Shape, typename Key> | 7910 template<typename Shape, typename Key> |
| 7912 void Dictionary<Shape, Key>::CopyKeysTo(FixedArray* storage) { | 7911 void Dictionary<Shape, Key>::CopyKeysTo(FixedArray* storage) { |
| (...skipping 388 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8301 if (break_point_objects()->IsUndefined()) return 0; | 8300 if (break_point_objects()->IsUndefined()) return 0; |
| 8302 // Single beak point. | 8301 // Single beak point. |
| 8303 if (!break_point_objects()->IsFixedArray()) return 1; | 8302 if (!break_point_objects()->IsFixedArray()) return 1; |
| 8304 // Multiple break points. | 8303 // Multiple break points. |
| 8305 return FixedArray::cast(break_point_objects())->length(); | 8304 return FixedArray::cast(break_point_objects())->length(); |
| 8306 } | 8305 } |
| 8307 #endif | 8306 #endif |
| 8308 | 8307 |
| 8309 | 8308 |
| 8310 } } // namespace v8::internal | 8309 } } // namespace v8::internal |
| OLD | NEW |